signed

QiShunwang

“诚信为本、客户至上”

FPGA 正向计时器(Verilog)

2021/6/24 13:27:33   来源:

  • 硬件部分
  • 设计思路
  • 代码(verilog)
    • 顶层模块(连接计时器与数码管)
    • 计时器模块
    • 数码管显示模块
    • testbench*(单独对计时器模块进行测试)
  • 波形图

硬件部分

使用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 

波形图

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