Verilog 语言实现时间计数

  FPGA实现时间计数其实算是很基础的功能,首先我们先通过公式了解时间与频率的关系:

        ƒ = 1 / T

  这里的f表示频率,T表示周期,1的话就是时间国际单位下的1秒。对于FPGA来说f表示的是时钟的频率,T就是该频率下的周期。对于100MHz的时钟信号来说,T = 1 / f = (1*1_000_000_000) / 100_000_000 = 10ns。对于50MHz信号, T = 1 / f = (1*1_000_000_000) / 50_000_000 = 20ns。

  知道了以上的基本概念就可以知道具体时间其实就是时钟周期的累加。比如在100MHz 的信号下,需要得到1us的时间,就需要cnt =  time / T = 1 * 1_000/10 = 100,就需要累计100个时钟周期。以下的代码块是在100MHz下进行时间计数的,分别产生1us,1ms,1s及设置大于1s的整数计时结束脉冲。

 

  1 `timescale 1ns/1ps
  2 module time_cnt
  3 #(
  4     parameter                SYS_FRE = 100_000_000
  5 )
  6 (
  7     input                    i_sys_clk,
  8     input                    i_sys_rstn,
  9     input        [31:0]        i_time_number,
 10     output                    o_1us_pulse,
 11     output                    o_1ms_pulse,
 12     output                    o_1s_pulse,
 13     output                    o_time_end
 14 );
 15 
 16     parameter            CLK_PERIOD = 1_000_000_000/SYS_FRE;
 17     parameter            TIME_1US = 1000/CLK_PERIOD;
 18     parameter            TIME_STEP = 1000;
 19     
 20     reg            [6:0]        r_time_us_cnt;
 21     reg            [9:0]        r_time_ms_cnt;
 22     reg            [9:0]        r_time_s_cnt;
 23     reg            [31:0]        r_time_cnt;
 24     reg                        r_time_over;
 25     
 26     wire                    w_time_1us_end;
 27     wire                    w_time_1ms_end;
 28     wire                    w_time_1s_end;
 29     wire                    w_time_end;
 30     
 31 /******************************************************************************\
 32 1us count 
 33 \******************************************************************************/    
 34     always@(posedge i_sys_clk)
 35     begin
 36         if(~i_sys_rstn | w_time_1us_end)
 37         begin
 38             r_time_us_cnt <= 'd1;
 39         end
 40         else
 41         begin
 42             r_time_us_cnt <= r_time_us_cnt + 1'b1;
 43         end
 44     end
 45 
 46     assign w_time_1us_end = (r_time_us_cnt == TIME_1US) ? 1'b1 : 'd0;
 47 /******************************************************************************\
 48 1ms count 
 49 \******************************************************************************/    
 50     always@(posedge i_sys_clk)
 51     begin
 52         if(~i_sys_rstn)
 53         begin
 54             r_time_ms_cnt <= 'd1;
 55         end
 56         else if(w_time_1ms_end)
 57         begin
 58             r_time_ms_cnt <= 'd1;
 59         end
 60         else if(w_time_1us_end)
 61         begin
 62             r_time_ms_cnt <= r_time_ms_cnt + 1'b1;
 63         end
 64     end
 65     
 66     assign w_time_1ms_end = (r_time_ms_cnt == TIME_STEP) & w_time_1us_end ? 1'b1 : 1'b0;    
 67 /******************************************************************************\
 68 1s count 
 69 \******************************************************************************/    
 70     always@(posedge i_sys_clk)
 71     begin
 72         if(~i_sys_rstn | w_time_1s_end)
 73         begin
 74             r_time_s_cnt <= 'd1;
 75         end
 76         else if(w_time_1ms_end)
 77         begin
 78             r_time_s_cnt <= r_time_s_cnt + 1'b1;
 79         end
 80     end
 81     
 82     assign w_time_1s_end = (r_time_s_cnt == TIME_STEP) & w_time_1ms_end ? 1'b1 : 1'b0;
 83 /******************************************************************************\
 84 time count ,step unit is s
 85 \******************************************************************************/
 86     always@(posedge i_sys_clk)
 87     begin
 88         if(~i_sys_rstn | w_time_end)
 89         begin
 90             r_time_cnt <= 'd1;
 91             r_time_over <= 'd0;
 92         end
 93         else if(&r_time_cnt)
 94         begin
 95             r_time_cnt <= r_time_cnt;
 96             r_time_over<= 1'b1;
 97         end
 98         else if(w_time_1s_end)
 99         begin
100             r_time_cnt <= r_time_cnt + 1'b1;
101         end
102     end
103 
104     assign w_time_end = (r_time_cnt == i_time_number) & w_time_1s_end ? 1'b1 : 1'b0;
105     
106     assign o_1us_pulse = w_time_1us_end;
107     assign o_1ms_pulse = w_time_1ms_end;
108     assign o_1s_pulse = w_time_1s_end;
109     assign o_time_end = w_time_end;
110     
111 endmodule
View Code

 

  然后是对上述模块的仿真

 1 `timescale 1ns/1ps
 2 module time_cnt_tb;
 3     
 4     reg        clk;
 5     reg        rst_n;
 6     
 7     
 8     wire    w_1us_pulse;
 9     wire    w_1ms_pulse;
10     wire    w_1s_pulse;
11     wire    w_time_end;
12     
13     initial
14     begin
15         rst_n = 1'b0;
16         #2000;
17         rst_n = 1'b1;
18     end
19     
20     initial
21     begin
22         clk = 1'b0;
23     end
24     
25     always #5 clk = ~clk;
26     
27     time_cnt 
28     #(
29         .SYS_FRE        (100_000_000    )
30     )
31     u_time_cnt
32     (
33         .i_sys_clk        (clk            ),
34         .i_sys_rstn        (rst_n            ),
35         .i_time_number    (2                ),
36         .o_1us_pulse    (w_1us_pulse    ),
37         .o_1ms_pulse    (w_1ms_pulse    ),
38         .o_1s_pulse        (w_1s_pulse        ),
39         .o_time_end        (w_time_end        )
40     );
41     
42     
43 endmodule
View Code

以下就是modelsim仿真后的图像可以看到1us计数产生的脉冲间隔是1000ns即1us。相应的1ms跟1s,及我这里设置的总时间2s都可以通过仿真波形看到,只是仿真2s多的时间modelsim需要跑很久,这里就不贴图了。

 

posted on 2022-03-28 10:04  Galois_V  阅读(844)  评论(0编辑  收藏  举报