状态机实现数字时钟 fpga
目录
- 原理
- 实现
原理
数字时钟:我这里实现的是数码管显示,外加设置时间功能和闹钟功能,闹钟就是蜂鸣器,没有其他的功能。
状态机:这里就不具体介绍了,上一篇已经介绍过了。
实现
设计:
1)按键消抖模块
2)控制模块(实现状态机,产生数码管显示数据,输出蜂鸣器信号,主要模块)
3)数码管驱动模块
4)蜂鸣器驱动模块
按键消抖就不粘贴复制了,上一篇博客很清楚了,
驱动
控制模块
别看代码多,大部分粘贴复制再改下信号名
我认为逻辑还是比较清晰了
分三个功能,正常显示时间(时间计数器),设置时间(再定义一组寄存器,结构和时间计数器一样,就是加1条件不太一样,基本是用按键控制的),设置闹钟(同设置时间一样)
module control(input clk ,input rst_n ,input [2:0] key ,output [23:0] time_data ,output alarm_clk_flag ,output [5:0] shan_shuo
);
localparam TIME_1S = 50_000_000;
localparam IDLE = 3'b001;
localparam SET_TIME = 3'b010;
localparam SET_ALARM = 3'b100;wire idle2set_time;
wire idle2set_alarm;
wire set_time2idle;
wire set_alarm2idle;
reg [2:0] state_c;
reg [2:0] state_n;reg [5:0] shanshuo_r;//闪烁标志,选中位0/1不停变换reg set_time_flag;//设置时间标志
reg set_alarm_flag;//设置闹钟标志reg [23:0] time_data_r;reg [25:0] cnt_1s;//1s计数器
wire add_cnt_1s;
wire end_cnt_1s;reg [3:0] cnt0;//s个位计数器
wire add_cnt0;
wire end_cnt0;reg [3:0] cnt1;//s十位计数器
wire add_cnt1;
wire end_cnt1;reg [3:0] cnt2;//m个位计数器
wire add_cnt2;
wire end_cnt2;reg [3:0] cnt3;//m十位计数器
wire add_cnt3;
wire end_cnt3;reg [3:0] cnt4;//h个位计数器
wire add_cnt4;
wire end_cnt4;reg [3:0] cnt5;//h十位计数器
wire add_cnt5;
wire end_cnt5;//设置时间寄存器
reg [3:0] set_time_cnt0;//s个位计数器reg [3:0] set_time_cnt1;//s十位计数器reg [3:0] set_time_cnt2;//m个位计数器reg [3:0] set_time_cnt3;//m十位计数器reg [3:0] set_time_cnt4;//h个位计数器reg [3:0] set_time_cnt5;//h十位计数器reg [2:0] key_sel_time;//设置时间片选记录
wire add_key_sel_time;
wire end_key_sel_time;reg [2:0] key_sel_alarm;//设置闹钟片选记录
wire add_key_sel_alarm;
wire end_key_sel_alarm;//设置闹钟寄存器
reg [23:0] alarm;//保存闹钟数据
reg [3:0] set_alarm_cnt0;//s个位计数器reg [3:0] set_alarm_cnt1;//s十位计数器reg [3:0] set_alarm_cnt2;//m个位计数器reg [3:0] set_alarm_cnt3;//m十位计数器reg [3:0] set_alarm_cnt4;//h个位计数器reg [3:0] set_alarm_cnt5;//h十位计数器always@(posedge clk or negedge rst_n)beginif(!rst_n)beginstate_c <= IDLE;endelse beginstate_c <= state_n;end
endalways @(*) begincase(state_c)IDLE:beginif(idle2set_time)beginstate_n <= SET_TIME;endelse if(idle2set_alarm)beginstate_n <= SET_ALARM;endelse beginstate_n <= state_c;endendSET_TIME:beginif(set_time2idle)beginstate_n <= IDLE;endelse beginstate_n <= state_c;endendSET_ALARM:beginif(set_alarm2idle)beginstate_n <= IDLE;endelse beginstate_n <= state_c;endenddefault:state_n = state_c;endcase
endassign idle2set_time = (state_c == IDLE) && (set_time_flag);
assign idle2set_alarm = (state_c == IDLE) && (set_alarm_flag);
assign set_time2idle = (state_c == SET_TIME) && (!set_time_flag);
assign set_alarm2idle = (state_c == SET_ALARM)&& (!set_alarm_flag);//1s计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_1s <= 26'b0;endelse if(add_cnt_1s)beginif(end_cnt_1s)begincnt_1s <= 26'b0;endelse begincnt_1s <= cnt_1s + 1'b1;endend
end
assign add_cnt_1s = 1'b1;
assign end_cnt_1s = add_cnt_1s && (cnt_1s == TIME_1S - 1);
//s个位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt0 <= 4'b0;endelse if(add_cnt0)beginif(end_cnt0)begincnt0 <= 4'b0;endelse begincnt0 <= cnt0 + 1'b1;endendelse if(set_time2idle)begincnt0 <= set_time_cnt0;end
end
assign add_cnt0 = end_cnt_1s;
assign end_cnt0 = add_cnt0 && (cnt0 == 10 - 1);
//s十位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt1 <= 4'b0;endelse if(add_cnt1)beginif(end_cnt1)begincnt1 <= 4'b0;endelse begincnt1 <= cnt1 + 1'b1;endendelse if(set_time2idle)begincnt1 <= set_time_cnt1;end
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && (cnt1 == 6 - 1);
//m个位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt2 <= 4'b0;endelse if(add_cnt2)beginif(end_cnt2)begincnt2 <= 4'b0;endelse begincnt2 <= cnt2 + 1'b1;endendelse if(set_time2idle)begincnt2 <= set_time_cnt2;end
end
assign add_cnt2 = end_cnt1;
assign end_cnt2 = add_cnt2 && (cnt2 == 10 - 1);
//m十位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt3 <= 4'b0;endelse if(add_cnt3)beginif(end_cnt3)begincnt3 <= 4'b0;endelse begincnt3 <= cnt3 + 1'b1;endendelse if(set_time2idle)begincnt3 <= set_time_cnt3;end
end
assign add_cnt3 = end_cnt2;
assign end_cnt3 = add_cnt3 && (cnt3 == 6 - 1);
//h个位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt4 <= 4'b0;endelse if(add_cnt4)beginif(end_cnt4)begincnt4 <= 4'b0;endelse begincnt4 <= cnt4 + 1'b1;endendelse if(set_time2idle)begincnt4 <= set_time_cnt4;end
end
assign add_cnt4 = end_cnt3;
assign end_cnt4 = add_cnt4 && (cnt4 == ((cnt5 == 2)?(4 - 1):(10 - 1)));
//h十位计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt5 <= 4'b0;endelse if(add_cnt5)beginif(end_cnt5)begincnt5 <= 4'b0;endelse begincnt5 <= cnt5 + 1'b1;endendelse if(set_time2idle)begincnt5 <= set_time_cnt5;end
end
assign add_cnt5 = end_cnt4;
assign end_cnt5 = add_cnt5 && (cnt5 == 2);//选中位反转
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginshanshuo_r <= 0;endelse if(state_c == IDLE)beginshanshuo_r <= 6'b000_000;endelse if(state_c == SET_TIME)begincase(key_sel_time)3'd0:beginif(end_cnt0)beginshanshuo_r[5]<=1;shanshuo_r[0] <= ~shanshuo_r[0];endend3'd1:beginif(end_cnt0)beginshanshuo_r[0]<=1;shanshuo_r[1] <= ~shanshuo_r[1];endend3'd2:beginif(end_cnt0)beginshanshuo_r[1]<=1;shanshuo_r[2] <= ~shanshuo_r[2];endend3'd3:beginif(end_cnt0)beginshanshuo_r[2]<=1;shanshuo_r[3] <= ~shanshuo_r[3];endend3'd4:beginif(end_cnt0)beginshanshuo_r[3]<=1;shanshuo_r[4] <= ~shanshuo_r[4];endend3'd5:beginif(end_cnt0)beginshanshuo_r[4]<=1;shanshuo_r[5] <= ~shanshuo_r[5];endenddefault:shanshuo_r <= shanshuo_r;endcaseendelse if(state_c == SET_ALARM)begincase(key_sel_alarm)3'd0:beginif(cbt_1s)beginshanshuo_r[5]<=1;shanshuo_r[0] <= ~shanshuo_r[0];endend3'd1:beginif(cbt_1s)beginshanshuo_r[0]<=1;shanshuo_r[1] <= ~shanshuo_r[1];endend3'd2:beginif(cbt_1s)beginshanshuo_r[1]<=1;shanshuo_r[2] <= ~shanshuo_r[2];endend3'd3:beginif(cbt_1s)beginshanshuo_r[2]<=1;shanshuo_r[3] <= ~shanshuo_r[3];endend3'd4:beginif(cbt_1s)beginshanshuo_r[3]<=1;shanshuo_r[4] <= ~shanshuo_r[4];endend3'd5:beginif(cbt_1s)beginshanshuo_r[4]<=1;shanshuo_r[5] <= ~shanshuo_r[5];endenddefault:shanshuo_r <= shanshuo_r;endcaseend
end
assign shan_shuo = shanshuo_r;//-----------------------------设置时间------------------------------------------------------------------------//时间设置标志
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_time_flag <= 1'b0;endelse if((state_c == IDLE) && key[0])beginset_time_flag <= 1'b1;endelse if((state_c == SET_TIME) && key[0])beginset_time_flag <= 1'b0;end
end
//时间设置寄存器赋值
//s个位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_time_cnt0 <= 0;endelse if(idle2set_time)beginset_time_cnt0 <= cnt0;endelse if((state_c == SET_TIME) && key[1] && key_sel_time == 3'd0)beginif(set_time_cnt0 == 10 -1)beginset_time_cnt0 <= 0;endelse beginset_time_cnt0 <= set_time_cnt0 + 1;end end
end
//s十位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_time_cnt1 <= 0;endelse if(idle2set_time)beginset_time_cnt1 <= cnt1;endelse if((state_c == SET_TIME) && key[1] && key_sel_time == 3'd1)beginif(set_time_cnt1 == 6 - 1)beginset_time_cnt1 <= 0;endelse beginset_time_cnt1 <= set_time_cnt1 + 1;endend
end
//m个位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_time_cnt2 <= 0;endelse if(idle2set_time)beginset_time_cnt2 <= cnt2;endelse if((state_c == SET_TIME) && key[1] && key_sel_time == 3'd2)beginif(set_time_cnt2 == 10 - 1)beginset_time_cnt2 <= 0;endelse beginset_time_cnt2 <= set_time_cnt2 + 1;end end
end
//m十位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_time_cnt3 <= 0;endelse if(idle2set_time)beginset_time_cnt3 <= cnt3;endelse if((state_c == SET_TIME) && key[1] && key_sel_time == 3'd3)beginif(set_time_cnt3 == 6 - 1)beginset_time_cnt3 <= 0;endelse beginset_time_cnt3 <= set_time_cnt3 + 1;end end
end
//h个位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_time_cnt4 <= 0;endelse if(idle2set_time)beginset_time_cnt4 <= cnt4;endelse if((state_c == SET_TIME) && key[1] && key_sel_time == 3'd4)beginif(set_time_cnt4 == ((set_time_cnt5 == 2)?(4 - 1):(10 - 1)))beginset_time_cnt4 <= 0;endelse beginset_time_cnt4 <= set_time_cnt4 + 1;end end
end
//h十位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_time_cnt5 <= 0;endelse if(idle2set_time)beginset_time_cnt5 <= cnt5;endelse if((state_c == SET_TIME) && key[1] && key_sel_time == 3'd5)beginif(set_time_cnt5 == ((set_time_cnt4<3)?1:2))beginset_time_cnt5 <= 0;endelse beginset_time_cnt5 <= set_time_cnt5 + 1;end end
end
//设置时间片选计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginkey_sel_time <= 0;endelse if(add_key_sel_time)beginif(end_key_sel_time)beginkey_sel_time <= 0;endelse beginkey_sel_time <= key_sel_time + 1;endend
end
assign add_key_sel_time = key[2] && (state_c == SET_TIME);
assign end_key_sel_time = add_key_sel_time && (key_sel_time == 6 - 1);//---------------------------设置闹钟------------------------------------------------------------------//闹钟设置标志
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_alarm_flag <= 1'b0;endelse if((state_c == IDLE) && key[1])beginset_alarm_flag <= 1'b1;endelse if((state_c == SET_ALARM) && key[1])beginset_alarm_flag <= 1'b0;end
end//设置闹钟片选计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginkey_sel_alarm <= 0;endelse if(add_key_sel_alarm)beginif(end_key_sel_alarm)beginkey_sel_alarm <= 0;endelse beginkey_sel_alarm <= key_sel_alarm + 1;endend
end
assign add_key_sel_alarm = key[2] && (state_c == SET_ALARM);
assign end_key_sel_alarm = add_key_sel_alarm && (key_sel_alarm == 6 - 1);
//s个位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_alarm_cnt0 <= 0;endelse if(idle2set_alarm)beginset_alarm_cnt0 <= cnt0;endelse if((state_c == SET_ALARM) && key[0] && key_sel_alarm == 3'd0)beginif(set_alarm_cnt0 == 10 -1)beginset_alarm_cnt0 <= 0;endelse beginset_alarm_cnt0 <= set_alarm_cnt0 + 1;end end
end
//s十位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_alarm_cnt1 <= 0;endelse if(idle2set_alarm)beginset_alarm_cnt1 <= cnt1;endelse if((state_c == SET_ALARM) && key[0] && key_sel_alarm == 3'd1)beginif(set_alarm_cnt1 == 6 -1)beginset_alarm_cnt1 <= 0;endelse beginset_alarm_cnt1 <= set_alarm_cnt1 + 1;end end
end
//m个位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_alarm_cnt2 <= 0;endelse if(idle2set_alarm)beginset_alarm_cnt2 <= cnt2;endelse if((state_c == SET_ALARM) && key[0] && key_sel_alarm == 3'd2)beginif(set_alarm_cnt2 == 10 -1)beginset_alarm_cnt2 <= 0;endelse beginset_alarm_cnt2 <= set_alarm_cnt2 + 1;endend
end
//m十位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_alarm_cnt3 <= 0;endelse if(idle2set_alarm)beginset_alarm_cnt3 <= cnt3;endelse if((state_c == SET_ALARM) && key[0] && key_sel_alarm == 3'd3)beginif(set_alarm_cnt3 == 6 -1)beginset_alarm_cnt3 <= 0;endelse beginset_alarm_cnt3 <= set_alarm_cnt3 + 1;endend
end
//h个位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_alarm_cnt4 <= 0;endelse if(idle2set_alarm)beginset_alarm_cnt4 <= cnt4;endelse if((state_c == SET_ALARM) && key[0] && key_sel_alarm == 3'd4)beginif(set_alarm_cnt4 == ((set_alarm_cnt5 == 2)?(4 - 1):(10 - 1)))beginset_alarm_cnt4 <= 0;endelse beginset_alarm_cnt4 <= set_alarm_cnt4 + 1;endend
end
//h十位
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginset_alarm_cnt5 <= 0;endelse if(idle2set_alarm)beginset_alarm_cnt5 <= cnt5;endelse if((state_c == SET_ALARM) && key[0] && key_sel_alarm == 3'd5)beginif(set_alarm_cnt5 == ((set_alarm_cnt5 > 3)?1:2)beginset_alarm_cnt5 <= 0;endelse beginset_alarm_cnt5 <= set_alarm_cnt5 + 1;endend
end//保存闹钟
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginalarm <= 0;endelse if(set_alarm2idle)beginalarm <= {set_alarm_cnt5,set_alarm_cnt4,set_alarm_cnt3,set_alarm_cnt2,set_alarm_cnt1,set_alarm_cnt0};end
end//数码管显示
always@(posedge clk or negedge rst_n)beginif(!rst_n)begintime_data_r <= 0;endelse begincase(state_c)IDLE: time_data_r <= {cnt5,cnt4,cnt3,cnt2,cnt1,cnt0}; SET_TIME: time_data_r <= {set_time_cnt5,set_time_cnt4,set_time_cnt3,set_time_cnt2,set_time_cnt1,set_time_cnt0};SET_ALARM:time_data_r <= {set_alarm_cnt5,set_alarm_cnt4,set_alarm_cnt3,set_alarm_cnt2,set_alarm_cnt1,set_alarm_cnt0};default: time_data_r <= {cnt5,cnt4,cnt3,cnt2,cnt1,cnt0};endcaseend
end
assign time_data = time_data_r;//闹钟标志信号
assign alarm_clk_flag = ((state_c == IDLE) && (alarm == {cnt5,cnt4,cnt3,cnt2,cnt1,cnt0}));endmodule
数码管驱动
和正常的驱动就多了个闪烁信号,可以使选中位闪烁
module seg_driver(input clk ,input rst_n ,input [23:0] din ,output reg [5:0] sel ,output reg [7:0] dig , input [5:0] shan_shuo
);parameter TIME_10MS = 25_000;
parameter TIME_500MS = 25_000_000;
//共阳极数码管 低电平点亮localparam ZERO = 7'b100_0000,ONE = 7'b111_1001,TWO = 7'b010_0100, THREE = 7'b011_0000, FOUR = 7'b001_1001,FIVE = 7'b001_0010, SIX = 7'b000_0010, SEVEN = 7'b111_1000, EIGHT = 7'b000_0000,NINE = 7'b001_0000,OFF = 7'b111_1111;//信号定义reg dot;reg [19:0] cnt;//扫描计数器
wire add_cnt;
wire end_cnt;reg [3:0] data;//根据片选信号选择高四位还是第四位//刷新频率计数器
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt <= 0;endelse if(add_cnt)beginif(end_cnt)begincnt <= 0;endelse begincnt <= cnt + 1'b1;endend
end
assign add_cnt = 1'b1;
assign end_cnt = add_cnt && (cnt == TIME_10MS - 1);
//片选信号选择
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginsel <= 6'b111_110;;endelse if(end_cnt)beginsel <= {sel[0],sel[5:1]};end
endalways @(posedge clk or negedge rst_n) beginif(!rst_n)begindata <= 4'b0;endelse begincase(sel)6'b111_110: begin data <= shan_shuo[0]? din [3:0] :7'd10 ;dot <= 1'b1;end6'b111_101: begin data <= shan_shuo[1]? din [7:4] :7'd10 ;dot <= 1'b1;end6'b111_011: begin data <= shan_shuo[2]? din [11:8] :7'd10 ;dot <= 1'b0;end6'b110_111: begin data <= shan_shuo[3]? din [15:12]:7'd10 ;dot <= 1'b1;end6'b101_111: begin data <= shan_shuo[4]? din [19:16]:7'd10 ;dot <= 1'b0;end6'b011_111: begin data <= shan_shuo[5]? din [23:20]:7'd10 ;dot <= 1'b1;enddefault: data <= din[3:0];endcase end
endalways @(*) begincase(data)4'd0:dig = {dot,ZERO } ;4'd1:dig = {dot,ONE } ;4'd2:dig = {dot,TWO } ;4'd3:dig = {dot,THREE} ;4'd4:dig = {dot,FOUR } ;4'd5:dig = {dot,FIVE } ;4'd6:dig = {dot,SIX } ;4'd7:dig = {dot,SEVEN} ;4'd8:dig = {dot,EIGHT} ;4'd9:dig = {dot,NINE } ;4'd10:dig = {dot,OFF};default: dig = {dot,ZERO};endcase
end
endmodule
beep模块
这其实就是播放音乐的蜂鸣器程序加了个标志信号,当标志信号有效才令蜂鸣器响,另外控制蜂鸣器响的时间。
module beep(input clk ,input rst_n ,input alarm_clk_flag ,output beep
);parameter M1 = 17'd95600;
parameter M2 = 17'd85150;
parameter M3 = 17'd75850;
parameter M4 = 17'd71600;
parameter M5 = 17'd63750;
parameter M6 = 17'd56800;
parameter M7 = 17'd50600;reg beep_r;
reg alarm_clk_flag_r;reg [16:0] cnt0;//音符周期计数器
wire add_cnt0;
wire end_cnt0;reg [8:0] cnt1;//音符重复次数计数器
wire add_cnt1;
wire end_cnt1;reg [4:0] cnt2;//音符总次数
wire add_cnt2;
wire end_cnt2;reg [1:0] cnt3;//音乐时间计数器 7次完结
wire add_cnt3;
wire end_cnt3;reg [16:0] preset_note;//预设音符周期数
wire [16:0] preset_duty;//占空比always@(posedge clk or negedge rst_n)beginif(!rst_n)beginalarm_clk_flag_r <= 1'b0;endelse if(alarm_clk_flag)beginalarm_clk_flag_r <= 1'b1;endelse if(cnt3 == 1)beginalarm_clk_flag_r <= 1'b0;end
end//音符周期计数
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt0 <= 17'b0;endelse if(add_cnt0)beginif(end_cnt0)begincnt0 <= 17'b0;endelse begincnt0 <= cnt0 +1'b1;endend
end
assign add_cnt0 = 1'b1;
assign end_cnt0 = add_cnt0 && (cnt0 == preset_note - 1);//音符重复次数
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt1 <= 9'b0;endelse if(add_cnt1)beginif(end_cnt1)begincnt1 <= 9'b0;endelse begincnt1 <= cnt1 +1'b1;endend
end
assign add_cnt1 = end_cnt0;
assign end_cnt1 = add_cnt1 && (cnt1 == 299);//音符总次数
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt2 <= 5'b0;endelse if(add_cnt2)beginif(end_cnt2)begincnt2 <= 5'b0;endelse begincnt2 <= cnt2 +1'b1;endend
end
assign add_cnt2 = end_cnt1;
assign end_cnt2 = add_cnt2 && (cnt2 == 31);//音乐时间计数器 响3次
always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt3 <= 0;endelse if(add_cnt3)beginif(end_cnt3)begincnt3 <= 0;endelse begincnt3 <= cnt3 + 1;endend
end
assign add_cnt3 = end_cnt2;
assign end_cnt3 = add_cnt3 && (cnt3 == 4 - 1);//给音符周期赋值
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginpreset_note <= 17'b0;endelse begincase(cnt2)6'd0 : preset_note <= M1;6'd1 : preset_note <= M2;6'd2 : preset_note <= M3;6'd3 : preset_note <= M1;6'd4 : preset_note <= M1;6'd5 : preset_note <= M2;6'd6 : preset_note <= M3;6'd7 : preset_note <= M1;6'd8 : preset_note <= M3;6'd9 : preset_note <= M4;6'd10 : preset_note <= M5;6'd11 : preset_note <= M3;6'd12 : preset_note <= M4;6'd13 : preset_note <= M5;6'd14 : preset_note <= M5;6'd15 : preset_note <= M6;6'd16 : preset_note <= M5;6'd17 : preset_note <= M4;6'd18 : preset_note <= M3;6'd19 : preset_note <= M1;6'd20 : preset_note <= M5;6'd21 : preset_note <= M6;6'd22 : preset_note <= M5;6'd23 : preset_note <= M4;6'd24 : preset_note <= M3;6'd25 : preset_note <= M1;6'd26 : preset_note <= M2;6'd27 : preset_note <= M5;6'd28 : preset_note <= M1;6'd29 : preset_note <= M2;6'd30 : preset_note <= M5;6'd31 : preset_note <= M1;default : preset_note <= M1;endcaseend
end//给蜂鸣器赋值,并设定占空比
always@(posedge clk or negedge rst_n)beginif(!rst_n)beginbeep_r <= 1'b1;endelse if(cnt3 == 2'd1)beginbeep_r <= 1'b1;endelse if(alarm_clk_flag_r)beginif(cnt0 <= preset_duty)beginbeep_r <= 1'b0;endelse beginbeep_r <= 1'b1;endendelse begin beep_r <= 1'b1;end
end
assign preset_duty = preset_note >> 1;
assign beep = beep_r;endmodule
顶层
module top(input clk ,input rst_n ,input [2:0] key_in ,output [5:0] sel ,output [7:0] dig ,output beep
);
wire [23:0] time_data;//显示数据
wire [2:0] key_out;//按键消抖输出
wire alarm_clk_flag;//闹钟响标志
wire [5:0] shan_shuo;
seg_driver u_seg_driver(.clk (clk ),.rst_n (rst_n ),.din (time_data ),.sel (sel ),.dig (dig ),.shan_shuo(shan_shuo)
);fsm_key_debounce # (.KEY_W(3)) u_fsm_key_debounce(.clk (clk ),.rst_n (rst_n ),.key_in (key_in ),.key_out (key_out )
);control u_control(.clk (clk ),.rst_n (rst_n ),.key (key_out ),.time_data (time_data ),.alarm_clk_flag (alarm_clk_flag ),.shan_shuo (shan_shuo )
);beep u_beep(.clk (clk ),.rst_n (rst_n ),.alarm_clk_flag (alarm_clk_flag ),.beep (beep )
);endmodule
总结:实际上就是把前面学的按键消抖、蜂鸣器、时钟、状态机,组合起来用,真正需要写的就只有控制模块,其他模块基本改改原来的代码就能用了。
只要把状态机的情况考虑完了,先把状态机前两段写完,后面就是慢慢添小逻辑就可以了,唯一烦恼的就是有时候第三段需要写的东西太多,一时间有点晕,没有一条完整的思路链直接写完,我就是想到哪写哪,最后磕磕绊绊把这个程序调试出来了,不过是直接上板,哪个功能不对改哪里的代码,因为我感觉,像这种信号多的一批的程序,要是去写仿真文件都得想晕(实际上就是自己的调试能力不够,哈哈)。
状态机实现数字时钟 fpga相关推荐
- OLED数字时钟---FPGA实现
一. 硬件 FPGA开发版 4个按键 0.96寸 IIC接口的oled显示模块 二. 功能介绍 oled初始化 oled清屏 oled数字时钟显示 oled字符显示 三. 效果演示 关注 微信公众号 ...
- FPGA学习之 状态机实现数码管的数字时钟
FPGA学习之 状态机实现数字时钟 开发板型号:EP4CE6F17C8 六位数码管原理图: 由图可知,数码管段选和片选均为低电平有效. 由于人眼的视觉残留,我们控制一定频率对每一位数码管进行刷新,就能 ...
- 基于FPGA的遥控数字时钟设计
基于FPGA的遥控数字时钟设计报告 Author:张宏宇 摘要 数字时钟是一种通过数字显示时间的计时装置,本次项目采用Cyclone Ⅳ系列芯片,使用QuartusII开发环境,使用Ver ...
- FPGA期末项目 | 数字时钟
戳这里下载整个项目包(已上传到CSDN资源库) 一.实验设备 FPGA开发平台.计算机.其它外接器件 二.需求分析(选题的意义.功能要求等...这里有点水,小伙伴们可以选择性跳过) 选题的意义:个人认 ...
- 基于FPGA的数字时钟的设计课设(HUAT)
目录 前言 一.数字时钟课设目标 二.部分代码 1.clock.v代码的编写 2.完整代码 3.仿真代码 总结 前言 学校黄老师的FPGA的设计课设,最后的课设为数字时钟,实现分时的计数功能,带有整点 ...
- 基于FPGA的数字时钟设计
基于FPGA的数字时钟设计 芯片与开发板 技术指标 1.具有正常的日时分秒技术显示功能,用七个数码管分别显示日,时,分,秒. 2.有按键校日,校时,校分,校秒. 3.利用led模拟整点报时功能. 4. ...
- 基于FPGA数字时钟的设计(附源码)
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分.大侠可以关注"FPGA技术江湖"微信公众号,在"闯荡江湖"."行侠仗义"栏里获取其 ...
- FPGA芯片结构(可编程输入输出单元IOB/可配置逻辑块CLB/数字时钟管理模块DCM/ 嵌入式块RAM(BRAM)/丰富的布线资源/ 底层内嵌功能单元/内嵌专用硬核)
目前主流的FPGA仍是基于查找表技术的,已经远远超出了先前版本的基本性能,并且整合了常用功能(如RAM.时钟管理 和DSP)的硬核(ASIC型)模块.如图1-1所示(注:图1-1只是一个示意图,实际上 ...
- FPGA数字时钟(可暂停调数,含代码)
前言 前段时间刚刚开始初步学习FPGA相关知识,在学习了一段时间后,利用前面所学知识,写了一个数字时钟,顺便在这里写下总结,方便理解. (本人小白一名,有错欢迎指出,欢迎探讨) (我使用的开发板是Cy ...
最新文章
- 设计模式——装饰者模式
- mysql无级分销_3级分销(mysql存储过程写法)
- ArcGIS API for JavaScript 4.4学习笔记[新] AJS4.4和AJS3.21新特性
- 如何基于多线程队列简单实现mq
- Netty实现自定义协议
- linux下安装php的swoole扩展模块(安装后php加载不出来?)
- python安装opencv出现错误,通过pip安装opencv时出错
- 七牛云存储:通过SDK上传图片
- MySQL数据库权限管理
- Dubbo 需求、架构、使用Demo
- ruby array_Ruby中带有示例的Array.fill()方法(1)
- 115_Power Pivot之HR薪酬计算:公积金、社保、个税、实发工资相关
- Windows进程通信之共享内存通信(C++)
- python 字符串_Python中常用的8种字符串操作方法
- ORACLE 锁解释
- 徐姗姗 20190912-2 命令行
- 阿里云游戏服务器攻击怎么防御?
- mysql 相同分数排名
- 中国象棋对局软件设计(四)[完]
- heavy r.com index.php,AngularJS - Computation-Heavy Tasks