zoukankan      html  css  js  c++  java
  • 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
    
    
  • 相关阅读:
    11.菜单(一)
    线性表之顺序存储详解
    SVN 撤回已提交的代码
    线性表1
    顶层父类
    异常类之派生类
    new和delete重载
    异常类之基类
    Qt中多线程问题
    智能指针实例
  • 原文地址:https://www.cnblogs.com/wsine/p/4292810.html
Copyright © 2011-2022 走看看