赞
踩
学校黄老师的FPGA的设计课设,最后的课设为数字时钟,实现分时的计数功能,带有整点报时,按键调节的功能,供电子类学生学习和参考。
1、能进行正常的时、分、秒计时功能,分别由6个数码管显示24小时、60分钟、60秒钟的计数器显示。
2、能利用实验系统上的按键实现“校时”“校分”功能:
⑴按下“SA”键时,计时器迅速递增,并按24小时循环,计满23小时后回“00”;
⑵按下“SB”键时,计分器迅速递增,并按59分钟循环,计满59分钟后回“00”,但不向“时”进位;
⑷要求按下“SA”、“SB”或“SC”时均不产生数字跳变(SA”、“SB”、“SC”按键是有抖动的,必须对其消除抖动处理)。
3、能利用扬声器做整点报时:
⑴当计时到达59分50秒时开始报时,在59分50秒、52秒、54秒、56秒、58秒鸣叫,鸣叫声频率可定为512Hz;
⑵到达59分60秒时为最后一声整点报时,整点报时频率可定为1024Hz。
4、用层次化设计方法设计该电路,用Verilog语言编写各个功能模块。
5、完成电路设计后,用实验系统下载验证。
要求实现闹铃功能,准确到分钟。用功能仿真的方法验证,可通过观察有关波形确认电路设计是否正确。
秒计数器
- reg [25:0] cnt2;
- wire add_cnt2;
- wire end_cnt2;
- always@(posedge clk or negedge rst_n)begin //1s计数,可以通过按键更改
-
- if(rst_n == 0)
- cnt2 <= 0;
- else if (add_cnt2)begin
- if(end_cnt2)
- cnt2 <= 0;
- else
- cnt2 <= cnt2 +1;
- end
- end
-
- assign add_cnt2 = 1;
- assign end_cnt2 = add_cnt2 && cnt2 == y-1;//y可以通过按键更改,实现按键调节时钟频率

us计数器
- reg [8:0] cnt0;
-
- always@(posedge clk or negedge rst_n) //数码管显示
-
- if(rst_n == 0)
- cnt0 <= 0;
- else if (add_cnt0)
- begin
- if(end_cnt0 )
- cnt0 <= 0;
- else
- cnt0 <= cnt0 +1;
- end
-
- assign add_cnt0 = 1;
- assign end_cnt0 = add_cnt0 && cnt0== TIME_1US-1;//通过短时间的数码管显示,实现动态扫描

数码管显示 对4个数码管进行us级的循环点亮,达到视觉上的暂留
- reg [2:0] cnt1;
- wire add_cnt1;
- wire end_cnt1;
-
- always@(posedge clk or negedge rst_n)begin //4个数码管
-
- if(rst_n == 0)
- cnt1 <= 0;
- else if (add_cnt1)begin
- if(end_cnt1)
- cnt1 <= 0;
- else
- cnt1 <= cnt1 +1;
- end
-
-
- end
-
- assign add_cnt1 = end_cnt0;
- assign end_cnt1 = add_cnt1 && cnt1 == 4-1;

数码管动态扫描
- always@(posedge clk or negedge rst_n) //动态扫描
- begin
- if(rst_n == 1'b0)
- seg_sel <= 4'b111_1;
- else if (cnt1 == 0)
- seg_sel <= 4'b111_0;
- else if (cnt1 == 1)
- seg_sel <= 4'b110_1;
- else if (cnt1 == 2)
- seg_sel <= 4'b101_1;
- else if (cnt1 == 3)
- seg_sel <= 4'b011_1;
- else
- seg_sel <= 4'b111_1;
-
- end

数码管选择显示
- reg [3:0] sel_data;
-
- always@(posedge clk or negedge rst_n) // 选择显示
- begin
-
- if(rst_n == 0)
- seg_ment <=8'hc0;
- else if (sel_data==0)
- seg_ment <= 8'hc0;
- else if (sel_data==1)
- seg_ment <= 8'hf9;
- else if (sel_data==2)
- seg_ment <= 8'ha4;
- else if (sel_data==3)
- seg_ment <= 8'hb0;
- else if (sel_data==4)
- seg_ment <= 8'h99;
- else if (sel_data==5)
- seg_ment <= 8'h92;
- else if (sel_data==6)
- seg_ment <= 8'h82;
- else if (sel_data==7)
- seg_ment <= 8'hf8;
- else if (sel_data==8)
- seg_ment <= 8'h80;
- else if (sel_data==9)
- seg_ment <= 8'h90;
- else
- seg_ment <= 8'hc0;
- end
-
- always@(*)
- begin
-
- if (cnt1==0)
- sel_data <= m_g;
- else if (cnt1==1)
- sel_data <= m_s;
- else if (cnt1==2)
- sel_data <= s_g;
- else
- sel_data <= s_s;
-
- end

分个位 分十位 时个位 时十位
- reg [3:0] m_g;
- wire add_m_g;
- wire end_m_g;
- always@(posedge clk or negedge rst_n)begin
-
- if(rst_n == 0)
- m_g <= 0;
-
-
- else if (add_m_g)
- begin
- if(end_m_g)
- m_g <= 0;
-
- else
- m_g <= m_g +1;
- end
- else
- m_g <= m_g;
-
- end
-
- assign add_m_g = end_cnt2;
- assign end_m_g = add_m_g && m_g == 10-1;
-
-
- reg [2:0] m_s;
- wire add_m_s;
- wire end_m_s;
- always@(posedge clk or negedge rst_n)begin
-
- if(rst_n == 0)
- m_s <= 0;
- else if (add_m_s)begin
- if(end_m_s)
- m_s <= 0;
-
- else
- m_s <= m_s +1;
- end
- end
-
- assign add_m_s = end_m_g;
- assign end_m_s = add_m_s && m_s == 6-1;
-
-
- reg [3:0] s_g;
- wire add_s_g;
- wire end_s_g;
- always@(posedge clk or negedge rst_n)begin
-
- if(rst_n == 0)
- s_g <= 0;
- else if (add_s_g)
- begin
- if(end_s_g)
- s_g <= 0;
- else if (key_in1 == 1'b0)//保证按键按下时位不产生变化
- s_g <= s_g ;
- else
- s_g <= s_g +1;
- end
- else
- s_g <= s_g;
- end
- assign add_s_g = end_m_s;
- assign end_s_g = add_s_g && s_g == x-1;
- reg [1:0] s_s;
- wire add_s_s;
- wire end_s_s;
- always@(posedge clk or negedge rst_n)begin
- if(rst_n == 0)
- s_s <= 0;
- else if (add_s_s)begin
- if(end_s_s)
- s_s <= 0;
- else
- s_s <= s_s +1;
- end
- end
- assign add_s_s = end_s_g;
- assign end_s_s = add_s_s && s_s == 3-1;
- always@(*)
- begin
- if(s_s==2)
- x=4;
- else
- x=10;
- end

上述基本可以达到数码管显示计数的效果
//按键更改频率
- parameter TIME_1S = 5000_000_0;
- parameter TIME_1MS = 5000_000;
- parameter TIME_1NS = 5000_00;
-
-
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- y <= TIME_1S;
- else if ( key_in1 == 1'b0) //按键1改时钟频率,同时s_g数码管不变
- begin
-
- y=TIME_1MS;
-
- end
- else if (key_in2 == 1'b0)//按键2 改时钟频率,改的更快
- y=TIME_1NS;
- else
- begin
- y <= TIME_1S;
-
-
- end

beep报时
- //beep 计数
- reg [24:0] cnt;
- reg [2:0] cnt_500ms;
- reg [17:0] freq_cnt;
- reg [17:0] freq_data;
- reg [17:0] freq_data2;
- wire [16:0] duty_data1;
- wire [16:0] duty_data2;
-
- // beep 0.5s的计数
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- cnt <= 25'd0;
- else if (cnt == CNT_MAX)
- cnt <= 25'd0;
- else
- cnt <= cnt + 25'b1;
-
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- cnt_500ms <= 3'd0;
- else if ((cnt_500ms == 3'd6)&&(cnt == CNT_MAX))
- cnt_500ms <= 3'd0;
- else if (cnt == CNT_MAX)
- cnt_500ms <= cnt_500ms + 3'd1;
- else
- cnt_500ms <= cnt_500ms;
- //频率计数
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- freq_cnt <= 18'd0;
- else if ((freq_cnt == freq_data)||(cnt == CNT_MAX))
- freq_cnt <= 18'd0;
- else
- freq_cnt <= freq_cnt + 18'd1;
-
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- freq_data <= DO;
- else case(cnt_500ms)
- 3'd0:
- begin
- freq_data <= DO;
- freq_data2<= XI;
- end
-
-
- default :
- begin
- freq_data <= DO;
- freq_data2<= XI;
- end
-
- endcase
-
- assign duty_data1 = freq_data >> 1;
- assign duty_data2 = freq_data2 >> 1;
- //报时
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- beep <= 1'b0;
- else if ((freq_cnt >= duty_data1)&&(((m_s == 5)&&(m_g== 2))||((m_s == 5)&&
- (m_g ==0))||((m_s == 5)&&(m_g ==4))||((m_s == 5)&&(m_g ==6))||((m_s == 5)&&(m_g ==8))))// 50 52 54 56 58 报时
- beep <= 1'b1;
- else if ((freq_cnt >= duty_data2)&&(((m_s == 0)&&(m_g== 0))))// 正点报时
- beep <= 1'b1;
- else
- beep <= 1'b0;

- module clock_k_b
- (
-
- input clk,
- input rst_n,
- input wire key_in1,
- input wire key_in2,
-
- output reg [3:0] seg_sel,
- output reg [7:0] seg_ment,
- output reg beep
-
- );
-
- parameter TIME_1US = 500;
- parameter TIME_1S = 5000_000_0;
- parameter TIME_1MS = 5000_000;
- parameter TIME_1NS = 5000_00;
- parameter CNT_MAX =25'd24_999_999;
- parameter DO = 18'd190839;
- parameter XI = 18'd101213;
- //
- reg [25:0] y;
- reg [8:0] cnt0;
- reg [3:0] x;
- wire add_cnt0;
- wire end_cnt0;
- //beep 计数
- reg [24:0] cnt;
- reg [2:0] cnt_500ms;
- reg [17:0] freq_cnt;
- reg [17:0] freq_data;
- reg [17:0] freq_data2;
- wire [16:0] duty_data1;
- wire [16:0] duty_data2;
- // beep 0.5s的计数
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- cnt <= 25'd0;
- else if (cnt == CNT_MAX)
- cnt <= 25'd0;
- else
- cnt <= cnt + 25'b1;
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- cnt_500ms <= 3'd0;
- else if ((cnt_500ms == 3'd6)&&(cnt == CNT_MAX))
- cnt_500ms <= 3'd0;
- else if (cnt == CNT_MAX)
- cnt_500ms <= cnt_500ms + 3'd1;
- else
- cnt_500ms <= cnt_500ms;
- //频率计数
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- freq_cnt <= 18'd0;
- else if ((freq_cnt == freq_data)||(cnt == CNT_MAX))
- freq_cnt <= 18'd0;
- else
- freq_cnt <= freq_cnt + 18'd1;
-
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- freq_data <= DO;
- else case(cnt_500ms)
- 3'd0:
- begin
- freq_data <= DO;
- freq_data2<= XI;
- end
-
-
-
- default :
- begin
- freq_data <= DO;
- freq_data2<= XI;
- end
-
- endcase
-
- assign duty_data1 = freq_data >> 1;
- assign duty_data2 = freq_data2 >> 1;
- //报时
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- beep <= 1'b0;
- else if ((freq_cnt >= duty_data1)&&(((m_s == 5)&&(m_g== 2))||((m_s == 5)&&
- (m_g ==0))||((m_s == 5)&&(m_g ==4))||((m_s == 5)&&(m_g ==6))||((m_s == 5)&&(m_g ==8))))// 50 52 54 56 58 报时
- beep <= 1'b1;
- else if ((freq_cnt >= duty_data2)&&(((m_s == 0)&&(m_g== 0))))// 正点报时
- beep <= 1'b1;
- else
- beep <= 1'b0;
- always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- y <= TIME_1S;
- else if ( key_in1 == 1'b0) //按键1改时钟频率,同时s_g数码管不变
- begin
-
- y=TIME_1MS;
-
- end
- else if (key_in2 == 1'b0)//按键2 改时钟频率,改的更快
- y=TIME_1NS;
- else
- begin
- y <= TIME_1S;
-
-
- end
-
- /* always@(posedge clk or negedge rst_n)
- if(rst_n == 1'b0)
- begin
- //beep <= 1'b0;
- led <= 1'b1;
- end
- else if (m_s>= 5)
- begin
- //beep <= 1'b1;
- led <= ~led;
- end
- else
- begin
- //beep <= 1'b0;
- led <= led;
- end */
-
- always@(posedge clk or negedge rst_n) //数码管显示
- if(rst_n == 0)
- cnt0 <= 0;
- else if (add_cnt0)
- begin
- if(end_cnt0 )
- cnt0 <= 0;
- else
- cnt0 <= cnt0 +1;
- end
-
- assign add_cnt0 = 1;
- assign end_cnt0 = add_cnt0 && cnt0== TIME_1US-1;
- reg [2:0] cnt1;
- wire add_cnt1;
- wire end_cnt1;
- always@(posedge clk or negedge rst_n)begin //4个数码管
- if(rst_n == 0)
- cnt1 <= 0;
- else if (add_cnt1)begin
- if(end_cnt1)
- cnt1 <= 0;
- else
- cnt1 <= cnt1 +1;
- end
-
-
- end
- assign add_cnt1 = end_cnt0;
- assign end_cnt1 = add_cnt1 && cnt1 == 4-1;
- reg [25:0] cnt2;
- wire add_cnt2;
- wire end_cnt2;
- always@(posedge clk or negedge rst_n)begin //1s计数,可以通过按键更改
- if(rst_n == 0)
- cnt2 <= 0;
- else if (add_cnt2)begin
- if(end_cnt2)
- cnt2 <= 0;
- else
- cnt2 <= cnt2 +1;
- end
- end
- assign add_cnt2 = 1;
- assign end_cnt2 = add_cnt2 && cnt2 == y-1;
- reg [3:0] sel_data;
- always@(posedge clk or negedge rst_n) // 选择显示
- begin
- if(rst_n == 0)
- seg_ment <=8'hc0;
- else if (sel_data==0)
- seg_ment <= 8'hc0;
- else if (sel_data==1)
- seg_ment <= 8'hf9;
- else if (sel_data==2)
- seg_ment <= 8'ha4;
- else if (sel_data==3)
- seg_ment <= 8'hb0;
- else if (sel_data==4)
- seg_ment <= 8'h99;
- else if (sel_data==5)
- seg_ment <= 8'h92;
- else if (sel_data==6)
- seg_ment <= 8'h82;
- else if (sel_data==7)
- seg_ment <= 8'hf8;
- else if (sel_data==8)
- seg_ment <= 8'h80;
- else if (sel_data==9)
- seg_ment <= 8'h90;
- else
- seg_ment <= 8'hc0;
- end
-
-
-
- always@(posedge clk or negedge rst_n) //动态扫描
- begin
- if(rst_n == 1'b0)
- seg_sel <= 4'b111_1;
- else if (cnt1 == 0)
- seg_sel <= 4'b111_0;
- else if (cnt1 == 1)
- seg_sel <= 4'b110_1;
- else if (cnt1 == 2)
- seg_sel <= 4'b101_1;
- else if (cnt1 == 3)
- seg_sel <= 4'b011_1;
- else
- seg_sel <= 4'b111_1;
-
- end
-
- reg [3:0] m_g;
- wire add_m_g;
- wire end_m_g;
- always@(posedge clk or negedge rst_n)begin
-
- if(rst_n == 0)
- m_g <= 0;
-
-
- else if (add_m_g)
- begin
- if(end_m_g)
- m_g <= 0;
-
- else
- m_g <= m_g +1;
- end
- else
- m_g <= m_g;
-
- end
-
- assign add_m_g = end_cnt2;
- assign end_m_g = add_m_g && m_g == 10-1;
-
-
- reg [2:0] m_s;
- wire add_m_s;
- wire end_m_s;
- always@(posedge clk or negedge rst_n)begin
-
- if(rst_n == 0)
- m_s <= 0;
- else if (add_m_s)begin
- if(end_m_s)
- m_s <= 0;
-
- else
- m_s <= m_s +1;
- end
- end
-
- assign add_m_s = end_m_g;
- assign end_m_s = add_m_s && m_s == 6-1;
-
-
- reg [3:0] s_g;
- wire add_s_g;
- wire end_s_g;
- always@(posedge clk or negedge rst_n)begin
-
- if(rst_n == 0)
- s_g <= 0;
- else if (add_s_g)
- begin
- if(end_s_g)
- s_g <= 0;
- else if (key_in1 == 1'b0)
- s_g <= s_g ;
- else
- s_g <= s_g +1;
- end
- else
- s_g <= s_g;
- end
- assign add_s_g = end_m_s;
- assign end_s_g = add_s_g && s_g == x-1;
- reg [1:0] s_s;
- wire add_s_s;
- wire end_s_s;
- always@(posedge clk or negedge rst_n)begin
- if(rst_n == 0)
- s_s <= 0;
- else if (add_s_s)begin
- if(end_s_s)
- s_s <= 0;
- else
- s_s <= s_s +1;
- end
- end
- assign add_s_s = end_s_g;
- assign end_s_s = add_s_s && s_s == 3-1;
- always@(*)
- begin
- if(s_s==2)
- x=4;
- else
- x=10;
- end
- /* always@(posedge clk or negedge rst_n)
- begin
- if(rst_n == 1'b0)
- sel_data <= 0;
- else if (cnt1==0)
- sel_data <= m_g;
- else if (cnt1==1)
- sel_data <= m_s;
- else if (cnt1==2)
- sel_data <= s_g;
- else if (cnt1==3)
- sel_data <= s_s;
-
- end */
-
- always@(*)
- begin
-
- if (cnt1==0)
- sel_data <= m_g;
- else if (cnt1==1)
- sel_data <= m_s;
- else if (cnt1==2)
- sel_data <= s_g;
- else
- sel_data <= s_s;
-
- end
-
-
-
- endmodule

- `timescale 1ns/1ns
-
- module tb_clock();
-
- parameter CYCLE = 20;
-
- reg clk;
- reg rst_n;
-
- wire [3:0] seg_sel;
- wire [6:0] seg_ment;
-
- clock
- #(
- .TIME_1US (100),
- .TIME_1S (10)
- )
- clock_inst
- (
- .clk (clk),
- .rst_n (rst_n),
- .seg_sel (seg_sel),
- .seg_ment (seg_ment)
- );
-
- initial
- begin
- clk = 0;
- forever#(CYCLE/2)begin
- clk=~clk;
- end
- end
-
- initial
- begin
- #1
- rst_n = 0;
- #(10*CYCLE);
- rst_n = 1;
- end
-
-
-
- endmodule

这是暑假自学搞得数字时钟的设计,虽然功能齐全,但是难免有点不完美的地方,也可以通过层次化的设计让代码变得没有这么长,可以通过这一份代码,要是期末课设弄不出来,参考一下也是可以的,免得挂了,功能反正都可以实现。若有更好的点子也可以一起交流学习一下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。