Verilog实现毫秒级计时器(秒表)

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个模块便能构造出一个毫秒级的计时器。


Verilog实现毫秒级计时器(秒表)_第1张图片计时器顶级逻辑图
 


Verilog实现毫秒级计时器(秒表)_第2张图片
时钟分频器电路图

 


Verilog实现毫秒级计时器(秒表)_第3张图片
 计时器状态机图示

 


Verilog实现毫秒级计时器(秒表)_第4张图片
 4 位十进制计数器电路图

 


Verilog实现毫秒级计时器(秒表)_第5张图片
 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

 

    注意:附件有更加详细的文档描述和测试代码!

 

 

你可能感兴趣的:(计时器,Verilog,Nexys3,秒表)