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需要跑很久,這里就不貼圖了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM