系统时钟计时器产生模块与Verilog代码

在FPGA设计中经常需要使用到计时器,包括使用系统时钟产生1ms,10ms,100ms,1s计时等信号。使用一个通用的计时器产生模块,可以方便其它模块调用,参考代码如下:

// *****************************************************************************
// Project Name     : *
// Target Device    : *
// Tool version     : *
// Module Name      : timer_gen
// Description      : timer generation
// Function         : to generate all kinds of timer signals
// Attention        : *
// Version History  : *
// *****************************************************************************
// Engineer         : zyhe
// Date             : 2016-01-01
// Modification     : 1) initial version
// *****************************************************************************
// Engineer         : zyhe
// Date             : 2016-05-01
// Modification     : 1) standard coding style
//                    i_ for input, o_ for output, w_ for wire, r_ for register
// *****************************************************************************
// All rights reserved.
// *****************************************************************************
 
`timescale 1ns / 1ps

module timer_gen # (
    parameter   CLK_FREQ = 125000000          // max to 65536*2000 = 131.072MHz
    ) (
    input               i_sys_rst           , // system reset
    input               i_sys_clk           , // system clock
    output  reg         o_pulse_1khz        , // 50% duty, cycle is 1ms
    output  reg         o_pulse_100hz       , // 50% duty, cycle is 10ms
    output  reg         o_pulse_10hz        , // 50% duty, cycle is 100ms
    output  reg         o_pulse_1hz         , // 50% duty, cycle is 1s
    output  reg         o_tick_1khz         , // 1 high duty, cycle is 1ms
    output  reg         o_tick_100hz        , // 1 high duty, cycle is 10ms
    output  reg         o_tick_10hz         , // 1 high duty, cycle is 100ms
    output  reg         o_tick_1hz            // 1 high duty, cycle is 1s
    );

    reg [15:0]  r_cnt_1khz      ; // 62500
    reg [2:0]   r_cnt_100hz     ;
    reg [2:0]   r_cnt_10hz      ;
    reg [2:0]   r_cnt_1hz       ;
    reg         r_clk_1khz      ;
    reg         r_clk_1khz_d0   ; // delay one cycle
    reg         r_clk_100hz     ;
    reg         r_clk_100hz_d0  ; // delay one cycle
    reg         r_clk_10hz      ;
    reg         r_clk_10hz_d0   ; // delay one cycle
    reg         r_clk_1hz       ;
    reg         r_clk_1hz_d0    ; // delay one cycle

    always @ (posedge i_sys_clk)
    begin
        if (i_sys_rst)
        begin
            r_cnt_1khz  <= 16'd0;
            r_clk_1khz  <= 1'b0;
        end
        else if (r_cnt_1khz == (CLK_FREQ / 2000) - 1)
        begin
            r_cnt_1khz  <= 16'd0;
            r_clk_1khz  <= ~r_clk_1khz;
        end
        else
        begin
            r_cnt_1khz  <= r_cnt_1khz + 1'b1;
            r_clk_1khz  <= r_clk_1khz;
        end
    end

    always @ (posedge i_sys_clk)
    begin
        r_clk_1khz_d0   <= r_clk_1khz;
        if (i_sys_rst)
        begin
            r_cnt_100hz <= 4'd0;
            r_clk_100hz <= 1'b0;
        end
        else if (~r_clk_1khz_d0 & r_clk_1khz)
        begin
            if (r_cnt_100hz == 4'd4)
            begin
                r_cnt_100hz <= 4'd0;
                r_clk_100hz <= ~r_clk_100hz;
            end
            else
            begin
                r_cnt_100hz <= r_cnt_100hz + 1'b1;
                r_clk_100hz <= r_clk_100hz;
            end
        end
    end

    always @ (posedge i_sys_clk)
    begin
        r_clk_100hz_d0  <= r_clk_100hz;
        if (i_sys_rst)
        begin
            r_cnt_10hz  <= 4'd0;
            r_clk_10hz  <= 1'b0;
        end
        else if (~r_clk_100hz_d0 & r_clk_100hz)
        begin
            if (r_cnt_10hz == 4'd4)
            begin
                r_cnt_10hz  <= 0;
                r_clk_10hz  <= ~r_clk_10hz;
            end
            else
            begin
                r_cnt_10hz  <= r_cnt_10hz + 1'b1;
                r_clk_10hz  <= r_clk_10hz;
            end
        end
    end

    always @ (posedge i_sys_clk)
    begin
        r_clk_10hz_d0   <= r_clk_10hz;
        if (i_sys_rst)
        begin
            r_cnt_1hz   <= 4'd0;
            r_clk_1hz   <= 1'b0;
        end
        else if (~r_clk_10hz_d0 & r_clk_10hz)
        begin
            if (r_cnt_1hz == 4'd4)
            begin
                r_cnt_1hz   <= 4'd0;
                r_clk_1hz   <= ~r_clk_1hz;
            end
            else
            begin
                r_cnt_1hz   <= r_cnt_1hz + 1'b1;
                r_clk_1hz   <= r_clk_1hz;
            end
        end
    end

    always @ (posedge i_sys_clk)
    begin
        o_pulse_1khz    <= r_clk_1khz;
        o_pulse_100hz   <= r_clk_100hz;
        o_pulse_10hz    <= r_clk_10hz;
        o_pulse_1hz     <= r_clk_1hz;
        o_tick_1khz     <= r_clk_1khz & (~r_clk_1khz_d0);
        o_tick_100hz    <= r_clk_100hz & (~r_clk_100hz_d0);
        o_tick_10hz     <= r_clk_10hz & (~r_clk_10hz_d0);
        o_tick_1hz      <= r_clk_1hz & (~r_clk_1hz_d0);
    end

endmodule

 

你可能感兴趣的:(系统时钟计时器产生模块与Verilog代码)