verilog实现毫秒计时器

verilog实现毫秒计时器


整体电路图

整体电路图

实验状态图

实验状态图
Stop代表没有计时,Start代表开始计时,Inc代表计时器加1,Trap代表inc按钮按下去时候的消抖状态。

状态编码表

状态编码表

实验设计思路

  • 时钟分频:用一个diver=49999来让count从0根据100MHz的内部时钟变化到diver让myclk取反一次,以达到myclk的频率为1KHz的时钟。
  • 计时器:以myclk来触发,从小数点后第三位开始计数,每次+1,用往前面进位的方法,从而不需要分成四个自定义时钟。
  • 显示器:定义好七段译码器的数字显示,然后每次挑选一位数字,分频每次显示一位,小数点同最高位同时显示消失。分频足够低的时候,肉眼的视觉暂留效果,看起来就是同时显示。
  • 亮点:代码全程用模块实现,简单易读易维护。

完整代码

//counter.v
`timescale 1ns / 1ps

module counter(
	input myclk,
	input reset,
	input cen,
	output [15:0] number
    );
	 
	wire up0, up1, up2;
	
	counter4bit c1(
		.myclk(myclk),
		.reset(reset),
		.cen(cen),
		.four(number[3:0]),
		.up(up0)
	);
	
	counter4bit c2(
		.myclk(myclk),
		.reset(reset),
		.cen(cen & up0),
		.four(number[7:4]),
		.up(up1)
	);
	
	counter4bit c3(
		.myclk(myclk),
		.reset(reset),
		.cen(cen & up0 & up1),
		.four(number[11:8]),
		.up(up2)
	);
	
	counter4bit c4(
		.myclk(myclk),
		.reset(reset),
		.cen(cen & up0 & up1 & up2),
		.four(number[15:12]),
		.up()
	);

endmodule

//clk_div.v
`timescale 1ns / 1ps

module clk_div(
	input clk_in,
	input reset,
	output reg clk_out
    );
	parameter diver = 49999;//for FPGA
	//parameter diver = 4;//for test
	reg [15:0] count;//just for 49999 or warning
	
	always@(posedge clk_in or posedge reset)
	begin
		if(reset)
		begin
			count <= 0;
			clk_out <= 1'b0;
		end
		else if(count == diver)
		begin
			clk_out <= ~clk_out;
			count <= 0;
		end
		else
		begin
			count <= count + 1'b1;
		end
	end

endmodule

//MillisecondCounter.v
`timescale 1ns / 1ps

module MillisecondCounter(
	input start,
	input stop,
	input inc,
	input clk,
	input reset,
	output [3:0] en,
	output [6:0] light,
	output dot
    );
	
	wire myclk;
	wire cen;
	wire [15:0] number;
	
	clk_div d(
		.clk_in(clk),
		.reset(reset),
		.clk_out(myclk)
	);
	
	state_transform st(
		.start(start),
		.stop(stop),
		.inc(inc),
		.myclk(myclk),
		.reset(reset),
		.cen(cen)
	);
	
	counter ct(
	.myclk(myclk),
	.reset(reset),
	.cen(cen),
	.number(number[15:0])
    );
	 
	show_number sn(
	.myclk(myclk),
	.reset(reset),
	.number(number[15:0]),
	.en(en[3:0]),
	.light(light[6:0]),
	.dot(dot)
    );

endmodule

//counter4bit.v
`timescale 1ns / 1ps

module counter4bit(
	input myclk,
	input reset,
	input cen,
	output reg [3:0] four,
	output up
    );

	assign up = (four == 4'b1001) ? 1'b1 : 1'b0;
	
	always@(posedge myclk or posedge reset)
	begin
		if(reset)
			four <= 0;
		else if(cen)
		begin
			if(four == 4'b1001)
				four <= 0;
			else
				four <= four + 1'b1;
		end
	end

endmodule

//state_transform.v
`timescale 1ns / 1ps

module state_transform(
	input start,
	input stop,
	input inc,
	input myclk,
	input reset,
	output reg cen
    );
	parameter STOP = 2'b00, START = 2'B01, INC = 2'b10, TRAP = 2'b11;
	
	reg [1:0] state, nextstate;
	
	always@(posedge myclk or posedge reset)
	begin
		if(reset)
			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;
			default:
									nextstate <= STOP;
		endcase
	end
	
	always@(*)
	begin
		case(state)
			STOP:		cen <= 1'b0;
			START:	cen <= 1'b1;
			INC:		cen <= 1'b1;
			TRAP:		cen <= 1'b0;
			default:	cen <= 1'b0;
		endcase
	end

endmodule

//show_number.v
`timescale 1ns / 1ps

module show_number(
	input myclk,
	input reset,
	input [15:0] number,
	output reg [3:0] en,
	output reg [6:0] light,
	output dot
    );
	 
	reg [1:0] index;
	reg [3:0] num_index;
	
	assign dot = (index == 2'b11) ? 1'b0 : 1'b1;
	
	always@(posedge myclk or posedge reset)
	begin
		if(reset)
			index <= 0;
		else
			index <= index + 1'b1;
	end
	
	always@(*)
	begin
		case(index)
			2'b00:	en <= 4'b1110;
			2'b01:	en <= 4'b1101;
			2'b10:	en <= 4'b1011;
			2'b11:	en <= 4'b0111;
			default:	en <= 4'b1111;
		endcase
	end

	always@(*)
	begin
		case(index)
			2'b00:	num_index <= number[3:0];
			2'b01:	num_index <= number[7:4];
			2'b10:	num_index <= number[11:8];
			2'b11:	num_index <= number[15:12];
			default:	num_index <= 4'b0000;
		endcase
	end

	always@(*)
	begin
		case(num_index)
			4'b0000: light <= 7'b0000001;  
			4'b0001: light <= 7'b1001111;  
			4'b0010: light <= 7'b0010010;  
			4'b0011: light <= 7'b0000110;  
			4'b0100: light <= 7'b1001100;  
			4'b0101: light <= 7'b0100100;  
			4'b0110: light <= 7'b0100000;  
			4'b0111: light <= 7'b0001111;  
			4'b1000: light <= 7'b0000000;  
			4'b1001: light <= 7'b0000100;  
			default: light <= 7'b1111111; 
		endcase
	end


endmodule

仿真测试文件

//VTF_Millisecond.v
`timescale 1ns / 1ps

module VTF_Millisecond;

	// Inputs
	reg start;
	reg stop;
	reg inc;
	reg clk;
	reg reset;

	// Outputs
	wire [3:0] en;
	wire [6:0] light;
	wire dot;

	// Instantiate the Unit Under Test (UUT)
	MillisecondCounter uut (
		.start(start), 
		.stop(stop), 
		.inc(inc), 
		.clk(clk), 
		.reset(reset), 
		.en(en), 
		.light(light), 
		.dot(dot)
	);

	initial begin
		// Initialize Inputs
		start = 0;
		stop = 0;
		inc = 0;
		clk = 0;
		reset = 1;

		// Wait 100 ns for global reset to finish
		#100;
      reset = 0;
		// Add stimulus here
		start = 1;
		#1200;
		start = 0;
		stop = 1;
		#200;
		inc = 1;
		#200;
		stop = 1;
		#200;
		start = 1;
		#200;
		inc = 0;
		#200;
		reset = 1;
		#200;
		reset = 0;
	end
   
	always #2 clk = ~clk;
	
endmodule

原文地址:https://www.cnblogs.com/wsine/p/4292810.html