用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[7:0] state;
reg song_on;
wire[6:0] in;

reg[3:0] high,med,low;
reg[13:0] divider,origin;
reg[7:0] counter;
reg out;
wire carry;

reg[20:0] 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[2:0] in_set;
reg[3:0] out1,out2,out3,out4,out5,out6,out7,out8;
reg[2:0] display_state;
reg[7:0] hour,minute,second,year,month,day,day_max;
reg[7:0] hour_set,minute_set,second_set,day_set,month_set,year_set,day_set_max;
integer century=20;
integer i=0;
reg speaker;

reg[7:0] clock_hour,clock_minute,clock_second;

reg[3:0] high,med,low;
reg[13:0] divider,origin;
reg[7:0] 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

永不止步步 发表于04-06 10:11 浏览65232次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67410个|学分:305067个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号