Verilog实现毫秒级计时器(秒表)
功能描述
使用Verilog语言在Nexys3开发板上实现一个毫秒精度的计时器。
计时器从0.000s开始计时到9.999s,然后重头开始计时,如此往复。Nexys3开发板上7段译码管要实时显示当前计数时间值和小数点。另外,跟一般的秒表类似,本文实现的计时器有4个控制按钮,分别为reset,start,stop以及increment,唯一不太一样的是increment按钮,在计时器停止的状态下按一下increment按钮,计时器的时间值会增加0.001s。
功能实现
计时器由4个不同的功能模块组成:
clk_divider: 时钟分频器,将Nexys3开发板的100MHz系统时钟转换为秒表的1KHz时钟;
timer_fsm: 计时器状态机,响应控制按钮的输入,跳转到不同状态(start, stop, inc, trap);
counter: 计时器,由4个0-9的计数器组成;
seg7_controller: 7段译码管控制器,以扫描显示的方式显示4位不同数字。
因此,只需要在顶级逻辑调用这4个模块便能构造出一个毫秒级的计时器。
计时器顶级逻辑图
时钟分频器电路图
计时器状态机图示
4 位十进制计数器电路图
7 段数码管控制器电路图
代码实现
// millitimer.v `timescale 1ns / 1ps module millitimer( input start_btn, input stop_btn, input inc_btn, input clk, input rst, output [3:0] an, output [6:0] seg, output dp ); parameter DP_SELECT = 3'b111; wire mclk; wire cen; wire [15:0] data; timer_fsm u_tfs ( .start(start_btn), .stop(stop_btn), .inc(inc_btn), .clk(mclk), .rst(rst), .cen(cen) ); clk_divider u_clk_d ( .clk(clk), .rst(rst), .mclk(mclk) ); counter u_count ( .cen(cen), .clk(mclk), .rst(rst), .out(data) ); seg7_controller u_seg7_ctrl ( .en(1'b1), .data(data), .dp_select(DP_SELECT), .clk(mclk), .rst(rst), .an(an), .seg(seg), .dp(dp) ); endmodule
// clk_divider.v `timescale 1ns / 1ps module clk_divider( input clk, input rst, output reg mclk ); parameter CLK_COUNT = 4; // 板级验证的时候该值改为49999 reg [31:0] count; always @ (posedge clk or posedge rst) begin if (rst) begin count <= 0; mclk <= 0; end else if (count == CLK_COUNT) begin count <= 0; mclk <= ~mclk; end else begin count <= count+1; mclk <= mclk; end end endmodule
// timer_fsm.v `timescale 1ns / 1ps module timer_fsm( input start, input stop, input inc, input clk, input rst, output reg cen ); parameter STOP = 2'b00; parameter START = 2'b01; parameter INC = 2'b10; parameter TRAP = 2'b11; reg [1:0] state, nextstate; always @(posedge clk or posedge rst) begin if (rst) state <= STOP; else state <= nextstate; end always @(*) begin case (state) STOP: if (stop) nextstate = STOP; else if (start) nextstate = START; else if (inc) nextstate = INC; else nextstate = STOP; START: if (start) nextstate = START; else if (stop) nextstate = STOP; else nextstate = START; INC: nextstate = TRAP; TRAP: if (inc) nextstate = TRAP; else nextstate = STOP; endcase end always @(*) begin case (state) STOP: cen = 1'b0; START: cen = 1'b1; INC: cen = 1'b1; TRAP: cen = 1'b0; endcase end endmodule
// counter.v `timescale 1ns / 1ps module counter( input cen, input clk, input rst, output [15:0] out ); wire tc0, tc1, tc2; counter4b u_c41 ( .cen(cen), .clk(clk), .rst(rst), .out(out[3:0]), .tc(tc0) ); counter4b u_c42 ( .cen(cen & tc0), .clk(clk), .rst(rst), .out(out[7:4]), .tc(tc1) ); counter4b u_c43 ( .cen(cen & tc0 & tc1), .clk(clk), .rst(rst), .out(out[11:8]), .tc(tc2) ); counter4b u_c44 ( .cen(cen & tc0 & tc1 & tc2), .clk(clk), .rst(rst), .out(out[15:12]), .tc() ); endmodule module counter4b ( input cen, input clk, input rst, output reg [3:0] out, output tc ); assign tc = (out == 4'b1001) ? 1'b1 : 1'b0; always @ (posedge clk or posedge rst) begin if (rst) begin out <= 0; end else if (cen) begin if (out == 4'b1001) out <= 0; else out <= out+1; end else begin out <= out; end end endmodule
// seg7_controller.v `timescale 1ns / 1ps module seg7_controller( input en, input [15:0] data, input [2:0] dp_select, input clk, input rst, output reg [3:0] an, output reg[6:0] seg, output dp ); reg [1:0] count; reg [3:0] selected_data; assign dp = (dp_select[2] && (dp_select[1:0]==count)) ? 1'b0 : 1'b1; always @ (posedge clk or posedge rst) begin if (rst) count <= 0; else if (!en) count <= 0; else if (count == 2'b11) count <= 0; else count <= count+1; end always @ (*) begin if (en) begin case (count) 2'b00: an = 4'b1110; 2'b01: an = 4'b1101; 2'b10: an = 4'b1011; 2'b11: an = 4'b0111; default: an = 4'b1111; endcase end else begin an = 4'b1111; end end always @ (*) begin case (count) 2'b00: selected_data = data[3:0]; 2'b01: selected_data = data[7:4]; 2'b10: selected_data = data[11:8]; 2'b11: selected_data = data[15:12]; default: selected_data = 4'b0000; endcase end always @ (*) begin case (selected_data) 4'b0000: seg = 7'b0000001; 4'b0001: seg = 7'b1001111; 4'b0010: seg = 7'b0010010; 4'b0011: seg = 7'b0000110; 4'b0100: seg = 7'b1001100; 4'b0101: seg = 7'b0100100; 4'b0110: seg = 7'b0100000; 4'b0111: seg = 7'b0001111; 4'b1000: seg = 7'b0000000; 4'b1001: seg = 7'b0000100; default: seg = 7'b1111111; endcase end endmodule
// 仿真测试文件:millitimer_test.v `timescale 1ns / 1ps module millitimer_test; // Inputs reg start_btn; reg stop_btn; reg inc_btn; reg clk; reg rst; // Outputs wire [3:0] an; wire [6:0] seg; wire dp; // Instantiate the Unit Under Test (UUT) millitimer uut ( .start_btn(start_btn), .stop_btn(stop_btn), .inc_btn(inc_btn), .clk(clk), .rst(rst), .an(an), .seg(seg), .dp(dp) ); initial begin // Initialize Inputs start_btn = 0; stop_btn = 0; inc_btn = 0; clk = 0; rst = 0; // Wait 100 ns for global reset to finish #100; // Add stimulus here rst = 1; #100; rst = 0; #100; start_btn = 1; #1200; start_btn = 0; stop_btn = 1; #200; inc_btn = 1; #200; stop_btn = 0; #200; start_btn = 1; #200; inc_btn = 0; #200; rst = 1; #200; rst = 0; end always #5 clk = ~clk; endmodule
注意:附件有更加详细的文档描述和测试代码!
相关推荐
从左到右数码管的前两个显示小时(范围0-24),第3-4个数码管显示分(范围0-59,计数到60,向小时位进1),第5-6个数码管显示秒(范围0-59,计数到60向分位进1),第7-8个数码管显示毫秒(范围0-99,计数到100向秒位...
4. **Verilog HDL编程**:在Verilog中,计时器、控制单元和显示单元可以分别定义为独立的模块。模块化设计的好处在于可重用性和可维护性,每个模块都有清晰的功能定义,便于理解和调试。在编写Verilog代码时,需要...
实验任务要求设计一个能显示“分:秒:毫秒”的秒表,具备“计时复位”、“计数/暂停”和“显示暂停/显示继续”等功能,以满足马拉松或长跑运动员的计时需求。 设计过程包括以下几个关键环节: 1. **上电初始化**...
- 计时器模块:实现毫秒级别的计数,通过输入时钟和控制信号进行计数或暂停。 - 取数模块:根据计时器的值获取当前秒、分钟等时间信息。 - 编码模块:将时间信息转换为七段码,以驱动数码管。 - 数码管显示控制模块...
综上所述,"miaobiao.rar_miaobiao_数字秒表"项目提供了一个使用Verilog实现的数字秒表实例,涉及了计时器设计、状态机、分频器等多个硬件设计领域,是学习和实践Verilog语言的好素材。通过深入研究这个项目,开发者...
在硬件描述语言(HDL)如Verilog或VHDL中编写秒表程序,可以实现精确的计时功能,这对于数字系统的设计和仿真至关重要。下面将详细介绍这个名为“miaobiao.zip”的压缩包中可能包含的秒表程序及其相关知识点。 1. *...
【标题】"miaobiao.rar_fpga数字秒表_数字秒表" 提供了一个使用FPGA(Field-Programmable Gate Array)技术实现的数字秒表项目,它能够精确到0.01秒进行计时。 【描述】中的关键信息是“基于FPGA EP3C5E的数字秒表...
sevenseg模块负责将内部计时器的数值转换为适合LED显示器的格式,stopwatch执行计时操作,而eliminate_jitter处理按键的消抖问题。 6. 计时逻辑:秒表计时通过计数器实现。例如,参数COUNT_40HZ和COUNT_100HZ分别...
在实现过程中,学生可能需要使用硬件描述语言(HDL),如Verilog或VHDL,来编写秒表的逻辑代码。这些代码会描述秒表的各个部分如何交互,然后通过EDA工具进行仿真和综合,最终生成可以在FPGA或ASIC上实现的网表。 ...
在数字秒表的例子中,设计可能从整体秒表功能开始,然后分解为计时器、显示控制器、控制逻辑等子模块。这种方法有助于管理复杂性,提高设计的可重用性和可测试性。 **三、Quartus II软件** Quartus II是Altera公司...
FPGA课程设计——数字电子时钟VERILOG(基于正点原子新起点开发板,支持8位或6位共阳极数码管显示时分秒毫秒,可校时,可设闹钟,闹钟开关,led指示) 本文是用verilog语言来描述一个基于FPGA的多功能数字电子时钟的...
3. **秒表计时功能**:秒表计时器是基于定时器/计数器功能,可以由FPGA内部逻辑实现。它记录脉冲的数量,这些脉冲通常来自系统时钟,然后将这些数值转换为秒、毫秒等单位。 4. **定时功能**:定时功能可以用于设定...