【veriog】正向计时器设计(FPGA,秒表,时钟,正向计时)

本文介绍了一个用Verilog实现的硬件计时器设计,包括顶层模块、计时器模块和数码管显示模块。计时器模块通过异步复位初始化并以50MHz系统时钟进行计数,每过1s更新数码管显示的时间。设计考虑了小时、分钟和秒的进位逻辑,确保时间正确滚动。同时提供了testbench用于单独测试计时器模块的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

硬件部分

使用6位8段数码管将时间值显示出来

设计思路

将时间拆分为6个参数:

        s1  -> 秒个位
        s10 -> 秒十位
        m1  -> 分个位
        m10 -> 分十位
        h1;   -> 时个位
        h10;  -> 时十位

在异步复位的时候为上述六个参数赋初始值。
然后对50Mhz系统时钟进行计数,计数50M次(即为1s)。然后对六个参数的当前值做出判断,并在下一个clk做出改变。

当计满1s,判断当前各h、m、s,的数值
-控制s个位:
若(s个位>=0 <9) s个位+1 
-控制s十位:
若(s个位=9 s十位>=0 <5)s个位清0 s十位+1 
-控制m个位:
若(s个位=9 s十位=5,(m个位>=0 <9)s个位清0 s十位清0 若m个位+1
-控制m十位:
若(s个位=9 s十位=5 )(m个位=9,m十位>=0 <5 )s个位清0 s十位清0 m个位归0 m十位+1
-控制h个位:
分为两种情况:
1、若(s个位=9 s十位=5 )(m个位=9,m十位=5 )(h个位>=0 <9 且 h十位 >=0 < 2 )m十位清0 			
   s个位清0 s十位清0 m个位清0  h个位+1  
2、若(s个位=9 s十位=5 )(m个位=9,m十位=5 )(h个位>=0 <3 且 h十位 = 2)
   s个位清0 s十位清0 m个位清0 m十位清0 h个位+1 
-控制h十位:
(s个位=9 s十位=5 )(m个位=9,m十位=5 )(h个位=9 且 十位>=0 <2)
 s个位清0 s十位清0 m个位清0 m十位清0 h个位清0 h十位+1
-若当前时间为: 23:59:59 
 置为00:00:00

代码(verilog)

顶层模块(连接计时器与数码管)

module top(
				clk,
				rst,
				dig,
                dict
				);
    input clk;
    input rst;
    output  [5:0] dig;  //六个数码管片选
    output  [7:0] dict; //动态数码管段选
    
    wire [23:0] set_data;//数码管显示的内容:4bit*6 

        clock f1(
					.clk(clk),
					.rst(rst),
					.s1(set_data[3:0]),
					.s10(set_data[7:4]),
					.m1(set_data[11:8]),
					.m10(set_data[15:12]),
					.h1(set_data[19:16]),
					.h10(set_data[23:20])
					);
                
        dig8_6 f2(
                 .clk(clk),
                 .rst(rst),
                 .set_data(set_data),
                 .dig(dig), 
                 .dict(dict)
               );
               
            
endmodule


计时器模块

module clock(
					clk,
					rst,
					s1,
					s10,
					m1,
					m10,
					h1,
					h10
					);

	input clk;
	input rst;
	output reg[3:0] s1;
	output reg[3:0] s10;
	output reg[3:0] m1;
	output reg[3:0] m10;
	output reg[3:0] h1;
	output reg[3:0] h10;
	
	reg [31:0] cnt; 
	
	always@(posedge clk or negedge rst)
	begin
		if(!rst)
			begin
			
				cnt <= 32'd0;
				
				s1 <= 4'd0;
				s10 <= 4'd5;
                m1 <= 4'd9;
				m10 <= 4'd5;
                h1 <= 4'd3;
                h10 <= 4'd2; //初始时间我设置为了23:59:50
			end
//s1++ : 当计满1s 且(s个位>=0 <9) s个位+1 计数器归0
		else if(cnt == 32'd50000000 && s1 >= 4'd0 && s1 < 4'd9 ) 
			begin 	
				s1 <= s1 + 1'd1;
				cnt <= 32'd0;
			end
//s10++ : 当计满1s 且(s个位=9 s十位>=0 <5)s个位清0 s十位+1 计数器归0
		else if(cnt == 32'd50000000 && s1 == 4'd9 && s10 >= 4'd0 && s10 < 4'd5) 
				begin	
					s1 <= 1'd0;
					s10 <= s10 + 1'd1;
					cnt <= 32'd0;
				end
//m1++ :当计满1s 且(s个位=9 s十位=5 )s个位清0 s十位清0 
//      若(m个位>=0 <9)m个位+1 计数器归0
		else if(cnt == 32'd50000000 && s1 == 4'd9 && s10 == 4'd5 && m1 >= 4'd0 && m1 < 4'd9) 
				begin	
					s1 <= 1'd0;
					s10 <= 1'd0;
					m1 <= m1 + 1'd1;
					cnt <= 32'd0;
				end
//m10++ : 计满1s 且(s个位=9 s十位=5 )s个位清0 s十位清0
//        若(m个位=9,m十位>=0 <5 )m个位归0 m十位+1 计数器归0
		else if(cnt == 32'd50000000 && s1 == 4'd9 && s10 == 4'd5 && m1 == 4'd9 && m10 >= 4'd0 && m10 < 4'd5) 
				begin	
					s1 <= 1'd0;
					s10 <= 1'd0;
					m1 <= 1'd0;
					m10 <= m10 + 1'd1;
					cnt <= 32'd0;
				end
//h1 ++ 分为两种情况:
//1、计满1s 且(s个位=9 s十位=5 )(m个位=9,m十位=5 )s个位清0 s十位清0 m个位清0 m十位清0 			
//   若(h个位>=0 <9 且 h十位 >=0 < 2 )h个位+1 计数器归0  
//2、计满1s 且(s个位=9 s十位=5 )(m个位=9,m十位=5 )s个位清0 s十位清0 m个位清0 m十位清0 
//   若(h个位>=0 <3 且 h十位 = 2) h个位+1 计数器归0
		else if(cnt == 32'd50000000 && s1 == 4'd9 && s10 == 4'd5 && m1 == 4'd9 && m10 == 4'd5 && h1 >= 4'd0 && h1 < 4'd9 && h10 >= 4'd0 && h10 < 4'd2) 
		begin	
			s1 <= 1'd0;
			s10 <= 1'd0;
			m1 <= 1'd0;
			m10 <= 1'd0;
			h1 <= h1 + 1'd1;
			cnt <= 32'd0;
		end
		else if(cnt == 32'd50000000 && s1 == 4'd9 && s10 == 4'd5 && m1 == 4'd9 && m10 == 4'd5 && h1 >= 4'd0 && h1 < 4'd3 && h10 == 4'd2) 
		begin	
			s1 <= 1'd0;
			s10 <= 1'd0;
			m1 <= 1'd0;
			m10 <= 1'd0;
			h1 <= h1 + 1'd1;
			cnt <= 32'd0;
		end
//h10 ++ : 计满1s 且(s个位=9 s十位=5 )(m个位=9,m十位=5 )s个位清0 s十位清0 m个位清0 m十位清0 
//         若(h个位=9 且 十位>=0 <2)h个位清0 h十位+1 计数器归0
		else if(cnt == 32'd50000000 && s1 == 4'd9 && s10 == 4'd5 && m1 == 4'd9 && m10 == 4'd5 && h1 == 4'd9 && h10 >= 4'd0 && h10 < 4'd2) 

		begin	
			s1 <= 1'd0;
			s10 <= 1'd0;
			m1 <= 1'd0;
			m10 <= 1'd0;
			h1 <= 1'd0;
			h10 <= h10 + 1'd1;
			cnt <= 32'd0;
		end
//23:59:59
//计满1s 且(s个位=9 s十位=5)(m个位=9,m十位=5)(h个位=3,十位=2)
//s个位置0 s十位清0 m个位清0 m十位清0 若h个位清0 h十位清
//计数器归0
		else if(cnt == 32'd50000000 && s1 == 4'd9 && s10 == 4'd5 && m1 == 4'd9 && m10 == 4'd5 && h1 == 4'd3 && h10 == 4'd2) 
		begin	
			s1 <= 1'd0;
			s10 <= 1'd0;
			m1 <= 1'd0;
			m10 <= 1'd0;
			h1 <= 1'd0;
			h10 <= 0;
			cnt <= 32'd0;
		end
//cnt ++ 
		else 
			cnt <= cnt + 1'b1;
	end  
	endmodule
	

数码管显示模块

(数码管的驱动见:链接

testbench*(单独对计时器模块进行测试)

需要将计时器模块设为顶层,在测试时,需要将cnt计数值调低 以便观察!!!

`timescale 1ns/1ns
`define clk_period 20

module tb;

	reg clk;
	reg rst;
	
	wire [3:0] s1;
	wire [3:0] s10;
	wire [3:0] m1;
	wire [3:0] m10;
	wire [3:0] h1;
	wire [3:0] h10;
	
	clock clock1(
					.clk(clk),
					.rst(rst),
					.s1(s1),
					.s10(s10),
					.m1(m1),
					.m10(m10),
					.h1(h1),
					.h10(h10)
					);
					
	initial clk = 1'd0;
	always #10 clk = ~ clk;
	
	initial begin
		rst = 1'b0;
		#(`clk_period*20)
		rst = 1'b1;
		#(`clk_period)
		
		#20000000;
		
		$stop;
	end 
	
	endmodule 

波形图

在这里插入图片描述
在这里插入图片描述

### 使用Verilog设计数字秒表并在FPGA上进行仿真的教程 #### 1. 秒表计数器的设计原理 为了实现一个简单的秒表计数器,需要定义几个主要模块来处理不同的功能。这些模块包括时钟分频器、计数器以及七段显示器驱动程序。 - **时钟分频器**:由于大多数FPGA开发板上的晶振频率较高(例如50MHz),因此有必要创建一个较低频率的脉冲作为秒表的时间单位。这可以通过除法运算完成。 - **计数器**:该部分负责记录经过的时间长度。通常会有一个或多个寄存器用来保存当前时间值,并且每当接收到新的时钟周期时更新它们的内容[^1]。 - **七段显示器驱动程序**:为了让用户能够直观地看到所测得的时间数据,还需要编写一段代码去控制外部连接着系统的共阴极型或者共阳极类型的7-segment LED显示屏。此过程涉及到将BCD编码转换成适合显示的形式并发送给相应的端口引脚[^2]。 以下是简化版的Verilog源代码片段: ```verilog module stopwatch( input wire clk, input wire reset_n, output reg [6:0] seg_display, output reg dp, output reg [3:0] anodes ); // Internal signals declaration reg [23:0] counter; wire tick_1hz; // Clock divider to generate a 1Hz signal from the main clock (assuming it's higher than 1Hz) always @(posedge clk or negedge reset_n) begin if (!reset_n) counter <= 24'b0; else counter <= counter + 1; end assign tick_1hz = &counter[23:1]; // Simplified way of generating a pulse every second when using a high-frequency clock. // Counter logic for seconds and minutes reg [5:0] sec_count; // Counts up to 59 reg [4:0] min_count; // Counts up to 59 always @(posedge tick_1hz or negedge reset_n) begin if (!reset_n) begin sec_count <= 6'd0; min_count <= 5'd0; end else begin if(sec_count == 6'd59) begin sec_count <= 6'd0; if(min_count == 5'd59) min_count <= 5'd0; else min_count <= min_count + 1; end else sec_count <= sec_count + 1; end end // BCD-to-seven segment decoder function here... // ... endmodule ``` 这段代码实现了基本的秒表功能,其中包含了对输入时钟信号`clk`的分频以获得一秒一次触发的事件;同时维护了一个六位宽(`sec_count`)表示秒钟数量加上五位宽(`min_count`)表示分钟数量的状态机结构来进行累加计算。最后还预留了接口供后续加入具体的七段译码逻辑[^3]。 #### 2. 进一步扩展特性 对于更复杂的应用场景来说,还可以考虑增加如下额外特性的支持: - 添加暂停/继续按钮的支持; - 实现计时模式而非仅仅是正向计时; - 提供报警提醒机制,在特定条件下激活蜂鸣器或其他形式的通知装置; - 支持多组独立运行的小工具以便于同时监控多项活动进展状况等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搞IC的那些年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值