fengboy 发表于 2008-6-29 21:23:08

用verilog语言编写的电子琴跟电子钟

如题,,,再附加上程序的控制说明.......是用GW48教学实验箱仿真的

如果对你有帮助,请大家顶上...
程序直接贴上了
控制说明:
1、电子琴:程序设计采用八个输入端口,分别与实验箱上的按键8~1引脚相连接,采用一个输出端口,与扬声器的引脚连接,时钟频率采用6MHz和4Hz。按键7~1分别用于中音的七个音符的发音(DO,RE,MI,FA,SO,LA,SI),按键8用于控制乐曲的播放。程序的编写采用状态机的编写方法,对按键的状态进行判断,对应相应的音符或乐曲。
2、电子钟:程序的设计模块有:时钟初始化模块、时钟工作模块、时钟设置模块、闹钟设置模块、闰年的月份天数判断模块、数码管显示模块、闹钟铃声模块及其它的设置模块。程序使用8个输入分别与8个按键连接,用按键8对应时钟工作状态(work_state),当work_state为0时,时钟正常工作,当work_state为1时,进入时钟设置状态。按键7对应输入端口display_set控制时钟显示状态(display_state),每按2次(用于产生上升沿触发)则数码管的输出不同。Display_state与work_state相结合使用,以区分设置的参数。按键6~4对应输入个脚in_set,该参数共有三位,用以表示三个状态:state_yorh (设置年或小时)、state_morm(设置月份或分钟)、 state_dors(设置日期或秒钟)。按键3~2对应数值设置端口up各down。Up用于产生上升沿触发,当down为0时,则每一个上升沿产生时,相应的参数加1,当down为1时,则每一个上升沿产生时,相应的参数减1。按键1与输入端口clock_on相连,用于闹钟的开与关,当 clock_on为1时开闹钟,否则关闹钟。扬声器与输出端口speaker相连,用于输出闹钟铃声。



附录:源程序
一、        电子琴:
module piano(in,clk_6MHz,clk_4Hz,song,speaker);
        input in,clk_6MHz,clk_4Hz,song;
        output speaker;
        reg speaker;
        reg state;
        reg song_on;
        wire in;
       
        reg high,med,low;
        reg divider,origin;
        reg counter;
        reg out;
        wire carry;
                       
        reg i;
        parameter zero=8'b0000_0000,
                          one=8'b0000_0001,
                        two=8'b0000_0010,
                        three=8'b0000_0100,
                        four=8'b0000_1000,
                        five=8'b0001_0000,
                        six=8'b0010_0000,
                        seven=8'b0100_0000;
        initial
                begin
                song_on<=0;
                end


        always @(posedge song)
                begin
                song_on<=~song_on;
                end

        always @(posedge clk_6MHz)
                  
                begin
                if(song_on)
                        speaker<=out;
                else
                begin               
                        case(in)
                zero:begin
                        speaker<=0;
                        i<=0;
                        end
                one:begin                //do
                        if(i>=11451)
                                begin
                                speaker=!speaker;
                                i<=0;
                                end
                        else
                                i<=i+1;
                        end
                two:begin                                //re
                        if(i>=10204)
                                begin
                                speaker=!speaker;
                                i<=0;
                                end
                        else
                                i<=i+1;
                        end
                three:begin                                //mi
                        if(i>=9091)
                                begin
                                speaker=!speaker;
                                i<=0;
                                end
                        else
                                i<=i+1;
                        end
                four:begin                                //        fa
                        if(i>=8596)
                                begin
                                speaker=!speaker;
                                i<=0;
                                end
                        else
                                i<=i+1;
                        end
                five:begin                        //so
                        if(i>=7653)
                                begin
                                speaker=!speaker;
                                i<=0;
                                end
                        else
                                i<=i+1;
                        end
                six:begin                        //lo
                        if(i>=6818)
                                begin
                                speaker=!speaker;
                                i<=0;
                                end
                        else
                                i<=i+1;
                        end
                seven:begin                        //si
                        if(i>=6073)
                                begin
                                speaker=!speaker;
                                i<=0;
                                end
                        else
                                i<=i+1;
                        end
                default:begin
                        speaker<=0;
                        i<=0;
                        end
                endcase
                end
        end


               
                assign carry=(divider==16383);
                always @(posedge clk_6MHz)
                        begin
                        if(carry)
                                divider<=origin;
                        else
                                divider<=divider+1;
                        end
                always @(posedge carry)
                        begin
                        out<=~out; //2 分频产生方波信号
                        end
                always @(posedge clk_4Hz)
                        begin
                        case({high,med,low}) //分频比预置
                'b000000000011: origin<=7281;
                'b000000000101: origin<=8730;
                'b000000000110: origin<=9565;
                'b000000000111: origin<=10310;
                'b000000010000: origin<=10647;
                'b000000100000: origin<=11272;
                'b000000110000: origin<=11831;
                'b000001010000: origin<=12556;
                'b000001100000: origin<=12974;
                'b000100000000: origin<=13516;
                'b000000000000: origin<=16383;
                        endcase
                        end
                always @(posedge clk_4Hz)
                        begin
                        if(counter==63)
                                counter<=0; //计时,以实现循环演奏
                        else
                                counter<=counter+1;
                        case(counter) //记谱
                0: {high,med,low}<='b000000000011; //低音“3”
                1: {high,med,low}<='b000000000011; //持续4 个时钟节拍
                2: {high,med,low}<='b000000000011;
                3: {high,med,low}<='b000000000011;
                4: {high,med,low}<='b000000000101; //低音“5”
                5: {high,med,low}<='b000000000101; //发3 个时钟节拍
                6: {high,med,low}<='b000000000101;
                7: {high,med,low}<='b000000000110; //低音“6”
                8: {high,med,low}<='b000000010000; //中音“1”
                9: {high,med,low}<='b000000010000; //发3 个时钟节拍
                10: {high,med,low}<='b000000010000;
                11: {high,med,low}<='b000000100000; //中音“2”
                12: {high,med,low}<='b000000000110; //低音“6”
                13: {high,med,low}<='b000000010000;
                14: {high,med,low}<='b000000000101;
                15: {high,med,low}<='b000000000101;
                16: {high,med,low}<='b000001010000; //中音“5”
                17: {high,med,low}<='b000001010000; //发3 个时钟节拍
                18: {high,med,low}<='b000001010000;
                19: {high,med,low}<='b000100000000; //高音“1”
                20: {high,med,low}<='b000001100000;
                21: {high,med,low}<='b000001010000;
                22: {high,med,low}<='b000000110000;
                23: {high,med,low}<='b000001010000;
                24: {high,med,low}<='b000000100000; //中音“2”
                25: {high,med,low}<='b000000100000; //持续11 个时钟节拍
                26: {high,med,low}<='b000000100000;
                27: {high,med,low}<='b000000100000;
                28: {high,med,low}<='b000000100000;
                29: {high,med,low}<='b000000100000;
                30: {high,med,low}<='b000000100000;
                31: {high,med,low}<='b000000100000;
                32: {high,med,low}<='b000000100000;
                33: {high,med,low}<='b000000100000;
                34: {high,med,low}<='b000000100000;
                35: {high,med,low}<='b000000110000; //中音“3”
                36: {high,med,low}<='b000000000111; //低音“7”
                37: {high,med,low}<='b000000000111;
                38: {high,med,low}<='b000000000110; //低音“6”
                39: {high,med,low}<='b000000000110;
                40: {high,med,low}<='b000000000101; //低音“5”
                41: {high,med,low}<='b000000000101;
                42: {high,med,low}<='b000000000101;
                43: {high,med,low}<='b000000000110; //低音“6”
                44: {high,med,low}<='b000000010000; //中音“1”
                45: {high,med,low}<='b000000010000;
                46: {high,med,low}<='b000000100000; //中音“2”
                47: {high,med,low}<='b000000100000;
                48: {high,med,low}<='b000000000011; //低音“3”
                49: {high,med,low}<='b000000000011;
                50: {high,med,low}<='b000000010000; //中音“1”
                51: {high,med,low}<='b000000010000;
                52: {high,med,low}<='b000000000110;
                53: {high,med,low}<='b000000000101; //低音“5”
                54: {high,med,low}<='b000000000110;
                55: {high,med,low}<='b000000010000; //中音“1”
                56: {high,med,low}<='b000000000101; //低音“5”
                57: {high,med,low}<='b000000000101; //持续8 个时钟节拍
                58: {high,med,low}<='b000000000101;
                59: {high,med,low}<='b000000000101;
                60: {high,med,low}<='b000000000101;
                61: {high,med,low}<='b000000000101;
                62: {high,med,low}<='b000000000101;
                63: {high,med,low}<='b000000000101;
                        endcase
                        end
endmodule

二、电子钟
module clock(work_state,clock_on,clk_6MHz,clk_4Hz,in_set,display_set,clk_1024Hz,up,down,out1,out2,out3,out4,out5,out6,out7,out8,speaker);

input work_state,clk_1024Hz,up,down,display_set,clk_6MHz,in_set,clock_on,clk_4Hz;
output out1,out2,out3,out4,out5,out6,out7,out8,speaker;
wire in_set;
reg out1,out2,out3,out4,out5,out6,out7,out8;
reg display_state;
reg hour,minute,second,year,month,day,day_max;
reg hour_set,minute_set,second_set,day_set,month_set,year_set,day_set_max;
integer century=20;
integer i=0;
reg speaker;

reg clock_hour,clock_minute,clock_second;

reg high,med,low;
        reg divider,origin;
        reg counter;
        reg out;
        wire carry;

//*****各初始值设置时对应的状态********//
parameter state_yorh=3'b100,    //设置年或小时对应的按键状态
                  state_morm=3'b010,        //设置月或分对应的按键状态
                  state_dors=3'b001;        //设置日或秒对应的按键状态


//***初始化时钟:08年08月08日00:00:00*****//
initial
        begin
        year<=8;
        year_set<=8;
        month<=8;
        month_set<=8;
        day<=8;
        day_set<=8;
        hour<=0;
        minute<=0;
        second<=0;
        clock_hour<=0;
        clock_minute<=0;
        clock_second<=0;
        display_state<=0;
        end
       
       
//******电子钟正常工作状态下/work_state等于0时,时钟处于工作状态*******//
always @(posedge clk_1024Hz)         //频率选择1024HZ
        begin
        if(i>=1023)
                begin
                i<=0;
                if(work_state)
                        begin
                        second<=second_set;
                        minute<=minute_set;
                        hour<=hour_set;
                        day<=day_set;
                        month<=month_set;
                        year<=year_set;
                end
                else       
                begin
                        if(second>=59)
                        begin
                                second<=0;
                                if(minute>=59)
                                begin
                                        minute<=0;
                                        if(hour>=23)
                                        begin
                                                hour<=0;
                                                if(day>=day_max)
                                                begin
                                                        day<=1;
                                                        if(month>=12)
                                                        begin
                                                                month<=1;
                                                                if(year>=99)
                                                                        year<=0;
                                                                else
                                                                        year<=year+1;
                                                        end
                                                        else
                                                                month<=month+1;
                                                end
                                                else
                                                        day<=day+1;
                                        end
                                        else
                                                hour<=hour+1;
                                end
                               else
                                        minute<=minute+1;
                        end
                        else
                                second<=second+1;
                end
                end
        else
                i<=i+1;
        end

//******数码管显示状态设置*******//
always @(posedge display_set)
        begin
        if(display_state>=2)
                display_state<=0;
        else
                display_state<=display_state+1;
        end
       
//*闹钟模块设置,用clock_on控制闹钟,闹钟铃声播放时间为一分钟,可手动关闭闹钟**//
always @(posedge clk_6MHz)
        begin
        if(clock_on)
                begin
                        if(clock_hour==hour&&clock_minute==minute)
                                speaker<=out;
                        else        speaker<=0;
                end
        else        speaker<=0;
        end
       
//*************设置时钟的初值*************************//
/*用up来触发,当down=0时,一个上升沿触发来时加1,否则减1.***/
always        @( posedge up)
        begin
        if(!work_state)       //时间处于正常工作状态时,使要设置的初始值保持同步
                begin
                  second_set<=second;
                        minute_set<=minute;
                        hour_set<=hour;
                        day_set<=day;
                        month_set<=month;
                        year_set<=year;
                end
        else
        begin
                if(display_state==1)//当display_state==1时,则是设置年月日的初始值,否则是设置时间.
                begin
                        if(down==0)
                        begin
                                case(in_set)
                                state_yorh:begin
                                                if(year_set>=99)
                                                        year_set<=0;
                                                else
                                                        year_set<=year_set+1;
                                                end                               
                          state_morm:begin
                                                if(month_set>=12)
                                                        month_set<=1;
                                                else
                                                        month_set<=month_set+1;
                                                end
                          state_dors:begin
                                                if(day_set>=day_set_max)
                                                        day_set<=1;
                                                else
                                                        day_set<=day_set+1;
                                                end
                                endcase
                        end
                        else
                        begin
                                case(in_set)

                                state_yorh:begin
                                                if(year_set<=0)
                                                        year_set<=99;
                                                else
                                                        year_set<=year_set-1;
                                                end                               
                          state_morm:begin
                                                if(month_set<=1)
                                                        month_set<=12;
                                                else
                                                        month_set<=month_set-1;
                                                end
                          state_dors:begin
                                                if(day_set<=1)
                                                        day_set<=day_set_max;
                                                else
                                                        day_set<=day_set-1;
                                                end

                                endcase
                        end
                end
                else if(display_state==0)
                begin
                        if(down==0)
                        begin
                                case(in_set)

                                state_yorh:begin
                                                if(hour_set>=23)
                                                        hour_set<=0;
                                                else
                                                        hour_set<=hour_set+1;
                                                end                               
                          state_morm:begin
                                                if(minute_set>=59)
                                                        minute_set<=0;
                                                else
                                                        minute_set<=minute_set+1;
                                                end
                          state_dors:begin
                                                if(second_set>=59)
                                                        second_set<=0;
                                                else
                                                        second_set<=second_set+1;
                                                end

                                endcase
                        end
                        else
                        begin
                                case(in_set)

                                state_yorh:begin
                                                if(hour_set<=0)
                                                        hour_set<=23;
                                                else
                                                        hour_set<=hour_set-1;
                                                end                               
                          state_morm:begin
                                                if(minute_set<=0)
                                                        minute_set<=59;
                                                else
                                                        minute_set<=minute_set-1;
                                                end
                          state_dors:begin
                                                if(second_set<=0)
                                                        second_set<=59;
                                                else
                                                        second_set<=second_set-1;
                                                end

                                endcase
                        end
                end
                else if(display_state==2)
                begin
                        if(down==0)
                        begin
                                case(in_set)

                                state_yorh:begin
                                                if(clock_hour>=23)
                                                        clock_hour<=0;
                                                else
                                                        clock_hour<=clock_hour+1;
                                                end                               
                          state_morm:begin
                                                if(clock_minute>=59)
                                                        clock_minute<=0;
                                                else
                                                        clock_minute=clock_minute+1;
                                                end
                          state_dors:begin
                                                if(clock_second>=59)
                                                        clock_second<=0;
                                                else
                                                        clock_second<=clock_second+1;
                                                end

                                endcase
                        end
                        else
                        begin
                                case(in_set)

                                state_yorh:begin
                                                if(clock_hour<=0)
                                                        clock_hour<=23;
                                                else
                                                        clock_hour<=clock_hour-1;
                                                end                               
                          state_morm:begin
                                                if(clock_minute<=0)
                                                        clock_minute<=59;
                                                else
                                                        clock_minute<=clock_minute-1;
                                                end
                          state_dors:begin
                                                if(clock_second<=0)
                                                        clock_second<=59;
                                                else
                                                        clock_second<=clock_second-1;
                                                end

                                endcase
                        end
               
                end
        end
        end


//**********本年度当前月的天数的计算**********//
always @(day or day_set)//当日期变化时,则其所处月份的天数;
        begin
                if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
                        day_max<=31;
                else if(month==4||month==6||month==9||month==11)
                        day_max<=30;
                else
                begin
                        if(({century,year}%400==0)||(({century,year}%4==0)&&({century,year}%10!=0)))
                                day_max<=29;
                        else day_max<=28;
                end
                       
                if(month_set==1||month_set==3||month_set==5||month_set==7||month_set==8||month_set==10||month_set==12)
                        day_set_max<=31;
                else if(month_set==4||month_set==6||month_set==9||month_set==11)
                        day_set_max<=30;
                else
                begin
                        if(({century,year_set}%400==0)||(({century,year_set}%4==0)&&({century,year_set}%10!=0)))
                                day_set_max<=29;
                        else day_set_max<=28;
                end
        end
       
//**********数码管显示模块,display_state=1时,显示年月日,否则显示时间////

always @(posedge clk_6MHz)
        begin
        if(!work_state)
                begin
                if(display_state==1)
                        begin
                        out8<=year%10;
                        out7<=year/10;
                        out6<=13;
                        out5<=month%10;
                        out4<=month/10;
                        out3<=13;
                        out2<=day%10;
                        out1<=day/10;
                        end
                else if(display_state==0)
                        begin
                        out8<=hour%10;
                        out7<=hour/10;
                        out6<=15;
                        out5<=minute%10;
                        out4<=minute/10;
                        out3<=15;
                        out2<=second%10;
                        out1<=second/10;
                        end
                else if(display_state==2)
                        begin
                        out8<=clock_hour%10;
                        out7<=clock_hour/10;
                        out6<=12;
                        out5<=clock_minute%10;
                        out4<=clock_minute/10;
                        out3<=12;
                        out2<=clock_second%10;
                        out1<=clock_second/10;
                        end
                end
        else
                begin
                if(display_state==1)
                        begin
                        out8<=year_set%10;
                        out7<=year_set/10;
                        out6<=13;
                        out5<=month_set%10;
                        out4<=month_set/10;
                        out3<=13;
                        out2<=day_set%10;
                        out1<=day_set/10;
                        end
                else if(display_state==0)
                        begin
                        out8<=hour_set%10;
                        out7<=hour_set/10;
                        out6<=15;
                        out5<=minute_set%10;
                        out4<=minute_set/10;
                        out3<=15;
                        out2<=second_set%10;
                        out1<=second_set/10;
                        end
                else if(display_state==2)
                        begin
                        out8<=clock_hour%10;
                        out7<=clock_hour/10;
                        out6<=12;
                        out5<=clock_minute%10;
                        out4<=clock_minute/10;
                        out3<=12;
                        out2<=clock_second%10;
                        out1<=clock_second/10;
                        end
                end
        end

//*******用乐曲《梁祝》作为闹钟铃声*************//
       
assign carry=(divider==16383);
                always @(posedge clk_6MHz)
                        begin
                        if(carry)
                                divider<=origin;
                        else
                                divider<=divider+1;
                        end
                always @(posedge carry)
                        begin
                        out<=~out; //2 分频产生方波信号
                        end
                always @(posedge clk_4Hz)
                        begin
                        case({high,med,low}) //分频比预置
                'b000000000011: origin<=7281;
                'b000000000101: origin<=8730;
                'b000000000110: origin<=9565;
                'b000000000111: origin<=10310;
                'b000000010000: origin<=10647;
                'b000000100000: origin<=11272;
                'b000000110000: origin<=11831;
                'b000001010000: origin<=12556;
                'b000001100000: origin<=12974;
                'b000100000000: origin<=13516;
                'b000000000000: origin<=16383;
                        endcase
                        end
                always @(posedge clk_4Hz)
                        begin
                        if(counter==63)
                                counter<=0; //计时,以实现循环演奏
                        else
                                counter<=counter+1;
                        case(counter) //记谱
                0: {high,med,low}<='b000000000011; //低音“3”
                1: {high,med,low}<='b000000000011; //持续4 个时钟节拍
                2: {high,med,low}<='b000000000011;
                3: {high,med,low}<='b000000000011;
                4: {high,med,low}<='b000000000101; //低音“5”
                5: {high,med,low}<='b000000000101; //发3 个时钟节拍
                6: {high,med,low}<='b000000000101;
                7: {high,med,low}<='b000000000110; //低音“6”
                8: {high,med,low}<='b000000010000; //中音“1”
                9: {high,med,low}<='b000000010000; //发3 个时钟节拍
                10: {high,med,low}<='b000000010000;
                11: {high,med,low}<='b000000100000; //中音“2”
                12: {high,med,low}<='b000000000110; //低音“6”
                13: {high,med,low}<='b000000010000;
                14: {high,med,low}<='b000000000101;
                15: {high,med,low}<='b000000000101;
                16: {high,med,low}<='b000001010000; //中音“5”
                17: {high,med,low}<='b000001010000; //发3 个时钟节拍
                18: {high,med,low}<='b000001010000;
                19: {high,med,low}<='b000100000000; //高音“1”
                20: {high,med,low}<='b000001100000;
                21: {high,med,low}<='b000001010000;
                22: {high,med,low}<='b000000110000;
                23: {high,med,low}<='b000001010000;
                24: {high,med,low}<='b000000100000; //中音“2”
                25: {high,med,low}<='b000000100000; //持续11 个时钟节拍
                26: {high,med,low}<='b000000100000;
                27: {high,med,low}<='b000000100000;
                28: {high,med,low}<='b000000100000;
                29: {high,med,low}<='b000000100000;
                30: {high,med,low}<='b000000100000;
                31: {high,med,low}<='b000000100000;
                32: {high,med,low}<='b000000100000;
                33: {high,med,low}<='b000000100000;
                34: {high,med,low}<='b000000100000;
                35: {high,med,low}<='b000000110000; //中音“3”
                36: {high,med,low}<='b000000000111; //低音“7”
                37: {high,med,low}<='b000000000111;
                38: {high,med,low}<='b000000000110; //低音“6”
                39: {high,med,low}<='b000000000110;
                40: {high,med,low}<='b000000000101; //低音“5”
                41: {high,med,low}<='b000000000101;
                42: {high,med,low}<='b000000000101;
                43: {high,med,low}<='b000000000110; //低音“6”
                44: {high,med,low}<='b000000010000; //中音“1”
                45: {high,med,low}<='b000000010000;
                46: {high,med,low}<='b000000100000; //中音“2”
                47: {high,med,low}<='b000000100000;
                48: {high,med,low}<='b000000000011; //低音“3”
                49: {high,med,low}<='b000000000011;
                50: {high,med,low}<='b000000010000; //中音“1”
                51: {high,med,low}<='b000000010000;
                52: {high,med,low}<='b000000000110;
                53: {high,med,low}<='b000000000101; //低音“5”
                54: {high,med,low}<='b000000000110;
                55: {high,med,low}<='b000000010000; //中音“1”
                56: {high,med,low}<='b000000000101; //低音“5”
                57: {high,med,low}<='b000000000101; //持续8 个时钟节拍
                58: {high,med,low}<='b000000000101;
                59: {high,med,low}<='b000000000101;
                60: {high,med,low}<='b000000000101;
                61: {high,med,low}<='b000000000101;
                62: {high,med,low}<='b000000000101;
                63: {high,med,low}<='b000000000101;
                        endcase
                        end       
       
endmodule

szkalwa 发表于 2008-7-3 10:39:34

我顶!!!

scrap_iron 发表于 2008-7-4 17:24:16

我也顶

highwest 发表于 2008-7-4 19:23:45

不错!!我顶!./emotion/em035.gif

lyhlt520 发表于 2010-5-24 01:09:14

注释偏少了。。。顶顶~

wuyongqing1960 发表于 2010-5-24 17:16:05

顶    mark

wuyongqing1960 发表于 2010-7-21 10:08:10

mark

wanwzy 发表于 2010-7-21 12:39:53

mark,多点注释呀!

justsun 发表于 2010-7-25 10:11:57

wxx116zh 发表于 2010-7-25 12:00:10

mark

flyhixd 发表于 2011-5-31 13:25:08

mark

feighh 发表于 2011-6-2 12:57:03

mark 有空看看!

arcui 发表于 2011-6-17 23:49:07

mark,等着,我会回来的!
页: [1]
查看完整版本: 用verilog语言编写的电子琴跟电子钟