FPGA测量频率的方法

  测量频率在自动化测试应用广泛,常用的测频率的工具也有挺多,比如示波器,频率计等。外部信号给到FPGA无非是0和1,因此测量频率主要是对周期信号进行统计,原理也挺简单。测量频率的方法也很多,这里就简单的列举下笔者知道的两种方式,其实下面的这两种方式原理差不多。

  原理基本都是通过等时间计算频率,公式为:N0/f0 = N1/f1。f0为已知时钟频率,N0为在某一时间段T内周期个数,f1为待测信号频率,N1为待测信号在时间段T内的周期数。根据公式转换则 f1 = N1*f0/N0。由于要保证时间T尽可能相等,这就需要用到积分,也就是时间越长结果越准确,而实际应用只要达到目标精度即可。这里为仿真方便只设置200ms测量时间。系统时钟为100MHz,待测信号设为6.25MHz。

  方法一:

  直接根据上述公式进行代码编写,使能信号在200ms时间段内保持高电平。该方式下输入信号作为时钟边沿敏感信号进行计数,会存在跨时钟域的问题,因此需要做复位同步,使能信号同步等操作。这会导致时间有些偏差,但影响不大。

  1 //**************************************************************************
  2 // *** file name      : Fre_Measure1.v
  3 // *** version        : 1.0
  4 // *** Description    : Frequency measurement method 1 
  5 // *** Blogs          : https://www.cnblogs.com/WenGalois123/
  6 // *** Author         : Galois_V
  7 // *** Date           : 2022.05.06        
  8 // *** Changes        : Initial 
  9 //**************************************************************************
 10 `timescale 1ns/1ps
 11 module Fre_Measure1
 12 (
 13     input                            i_sys_clk          ,
 14     input                            i_sys_rstn         ,
 15     input                            i_signal_clk       ,
 16     input                            i_measure_en       ,
 17     output    reg    [31:0]          o_signal_cnt       ,
 18     output    reg    [31:0]          o_refer_cnt        ,
 19     output                           o_measure_busy
 20 );
 21 
 22     wire                        w_measure_busy ;
 23     reg            [2:0]        r_syn_rstn     ;
 24     reg            [2:0]        r_signal_en    ;
 25     reg            [1:0]        r_measure_busy ;
 26     
 27 /******************************************************************************\
 28 Reference clock count
 29 \******************************************************************************/    
 30     always@(posedge i_sys_clk)
 31     begin
 32         if(~i_sys_rstn)
 33         begin
 34             o_refer_cnt <= 'd0;
 35         end
 36         else if(i_measure_en)
 37         begin
 38             o_refer_cnt <= o_refer_cnt + 1'b1;
 39         end
 40         else
 41         begin
 42             o_refer_cnt <= o_refer_cnt;
 43         end
 44     end
 45 /******************************************************************************\
 46 Asynchronous reset and synchronous release
 47 \******************************************************************************/    
 48     always@(posedge i_signal_clk or negedge i_sys_rstn)
 49     begin
 50         if(~i_sys_rstn)
 51         begin
 52             r_syn_rstn <= 'd0;
 53         end
 54         else
 55         begin
 56             r_syn_rstn <= {r_syn_rstn[1:0],1'b1};
 57         end
 58     end
 59 /******************************************************************************\
 60 Synchronous enable
 61 \******************************************************************************/    
 62     always@(posedge i_signal_clk)
 63     begin
 64         if(~r_syn_rstn[2])
 65         begin
 66             r_signal_en <= 'd0;
 67         end
 68         else
 69         begin
 70             r_signal_en <= {r_signal_en[1:0],i_measure_en};
 71         end
 72     end
 73 /******************************************************************************\
 74 Signal count to be measured
 75 \******************************************************************************/    
 76     always@(posedge i_signal_clk)
 77     begin
 78         if(~r_syn_rstn[2])
 79         begin
 80             o_signal_cnt <= 'd0;
 81         end
 82         else if(r_signal_en[2])
 83         begin
 84             o_signal_cnt <= o_signal_cnt + 1'b1;
 85         end
 86         else
 87         begin
 88             o_signal_cnt <= o_signal_cnt;
 89         end
 90     end
 91 /******************************************************************************\
 92 Detection and measurement status
 93 \******************************************************************************/    
 94     assign w_measure_busy = i_measure_en | r_signal_en[2];
 95     
 96     always@(posedge i_sys_clk)
 97     begin
 98         if(~i_sys_rstn)
 99         begin
100             r_measure_busy <= 'd0;
101         end
102         else 
103         begin
104             r_measure_busy <= {r_measure_busy[0],w_measure_busy};
105         end
106     end
107     
108     assign o_measure_busy = r_measure_busy[1];
109     
110 endmodule

  方法二:

  这种方法适合测量比参考信号频率小得多的信号,方法一各种频率都能测。不过方法二能够测量信号的占空比,原理也挺简单。即通过时间段内计算出上升沿个数,算出该待测信号频率;累计高电平所耗时间,算出占空比。

 1 //**************************************************************************
 2 // *** file name      : Fre_Measure2.v
 3 // *** version        : 1.0
 4 // *** Description    : Frequency measurement method 2 
 5 // *** Blogs          : https://www.cnblogs.com/WenGalois123/
 6 // *** Author         : Galois_V
 7 // *** Date           : 2022.05.06        
 8 // *** Changes        : Initial 
 9 //**************************************************************************
10 `timescale 1ns/1ps
11 module Fre_Measure2
12 (
13     input                            i_sys_clk        ,
14     input                            i_sys_rstn       ,
15     input                            i_signal         ,
16     input                            i_measure_en     ,
17     output    reg    [31:0]          o_pos_cnt        ,
18     output    reg    [31:0]          o_high_cnt        
19 );
20     wire                        w_signal_pos;
21     wire                        w_signal_neg;
22     
23     reg            [2:0]        r_signal;
24 /******************************************************************************\
25 Synchronous i_signal
26 \******************************************************************************/    
27     always@(posedge i_sys_clk)
28     begin
29         if(~i_sys_rstn)
30         begin
31             r_signal <= 'd0;
32         end
33         else
34         begin
35             r_signal <= {r_signal[1:0],i_signal};
36         end
37     end
38 
39     assign w_signal_pos = ~r_signal[2] & r_signal[1];
40     assign w_signal_neg = ~r_signal[1] & r_signal[2];
41 /******************************************************************************\
42 Cumulative number of rising edges
43 \******************************************************************************/    
44     always@(posedge i_sys_clk)
45     begin
46         if(~i_sys_rstn)
47         begin
48             o_pos_cnt <= 'd0;
49         end
50         else if(i_measure_en & w_signal_pos)
51         begin
52             o_pos_cnt <= o_pos_cnt + 1'b1;
53         end
54         else
55         begin
56             o_pos_cnt <= o_pos_cnt;
57         end
58     end
59 /******************************************************************************\
60 Cumulative number of high-level edges
61 \******************************************************************************/    
62     always@(posedge i_sys_clk)
63     begin
64         if(~i_sys_rstn)
65         begin
66             o_high_cnt <= 'd0;
67         end
68         else if(i_measure_en & r_signal[2])
69         begin
70             o_high_cnt <= o_high_cnt + 1'b1;
71         end
72         else
73         begin
74             o_high_cnt <= o_high_cnt;
75         end
76     end
77     
78 endmodule

  顶层文件AXI4_Fre_measure.v

  1 //**************************************************************************
  2 // *** file name      : AXI4_Fre_measure.v
  3 // *** version        : 1.0
  4 // *** Description    : Frequency measurement module top 
  5 // *** Blogs          : https://www.cnblogs.com/WenGalois123/
  6 // *** Author         : Galois_V
  7 // *** Date           : 2022.05.06        
  8 // *** Changes        : Initial 
  9 //**************************************************************************
 10 `timescale 1ns/1ps
 11 module AXI4_Fre_measure
 12 #(
 13     parameter                    SYS_FRE        = 100_000_000
 14 )
 15 (
 16     input        wire                i_s_axi_aclk              ,
 17     input        wire                i_s_axi_aresetn           ,
 18     input        wire    [31:0]      i_s_axi_awaddr            ,
 19     input        wire    [2:0]       i_s_axi_awprot            ,
 20     input        wire                i_s_axi_awvalid           ,
 21     output       wire                o_s_axi_awready           ,
 22     input        wire    [31:0]      i_s_axi_wdata             ,
 23     input        wire    [3:0]       i_s_axi_wstrb             ,
 24     input        wire                i_s_axi_wvalid            ,
 25     output       wire                o_s_axi_wready            ,
 26     output       wire     [1:0]      o_s_axi_bresp             ,
 27     output       wire                o_s_axi_bvalid            ,
 28     input        wire                i_s_axi_bready            ,
 29     input        wire    [31:0]      i_s_axi_araddr            ,
 30     input        wire    [2:0]       i_s_axi_arprot            ,
 31     input        wire                i_s_axi_arvalid           ,
 32     output       wire                o_s_axi_arready           ,
 33     output       wire    [31:0]      o_s_axi_rdata             ,
 34     output       wire    [1:0]       o_s_axi_rresp             ,
 35     output       wire                o_s_axi_rvalid            ,
 36     input        wire                i_s_axi_rready            ,
 37     input        wire                i_signal                                
 38 );
 39     wire                          w_module_en           ;
 40     wire        [31:0]            w_ms_number           ;
 41     wire                          w_measure_en          ;
 42     wire        [31:0]            w_signal_cnt          ;
 43     wire        [31:0]            w_refer_cnt           ;
 44     wire                          w_measure_busy        ;
 45     wire        [31:0]            w_signal_pos_cnt      ;
 46     wire        [31:0]            w_signal_high_cnt     ;
 47 
 48 /******************************************************************************\
 49 Fre measure control 
 50 \******************************************************************************/
 51     Fre_Measure_ctrl
 52     #(
 53         .SYS_FRE                  (SYS_FRE                   )
 54     )
 55     u_Fre_Measure_ctrl
 56     (
 57         .i_s_axi_aclk             (i_s_axi_aclk              ),
 58         .i_s_axi_aresetn          (i_s_axi_aresetn           ),
 59         .i_s_axi_awaddr           (i_s_axi_awaddr            ),
 60         .i_s_axi_awprot           (i_s_axi_awprot            ),
 61         .i_s_axi_awvalid          (i_s_axi_awvalid           ),
 62         .o_s_axi_awready          (o_s_axi_awready           ),
 63         .i_s_axi_wdata            (i_s_axi_wdata             ),
 64         .i_s_axi_wstrb            (i_s_axi_wstrb             ),
 65         .i_s_axi_wvalid           (i_s_axi_wvalid            ),
 66         .o_s_axi_wready           (o_s_axi_wready            ),
 67         .o_s_axi_bresp            (o_s_axi_bresp             ),
 68         .o_s_axi_bvalid           (o_s_axi_bvalid            ),
 69         .i_s_axi_bready           (i_s_axi_bready            ),
 70         .i_s_axi_araddr           (i_s_axi_araddr            ),
 71         .i_s_axi_arprot           (i_s_axi_arprot            ),
 72         .i_s_axi_arvalid          (i_s_axi_arvalid           ),
 73         .o_s_axi_arready          (o_s_axi_arready           ),
 74         .o_s_axi_rdata            (o_s_axi_rdata             ),
 75         .o_s_axi_rresp            (o_s_axi_rresp             ),
 76         .o_s_axi_rvalid           (o_s_axi_rvalid            ),
 77         .i_s_axi_rready           (i_s_axi_rready            ),
 78         .o_module_en              (w_module_en               ),
 79         .i_measure_busy           (w_measure_busy            ),
 80         .o_ms_number              (w_ms_number               ),
 81         .i_signal_cnt             (w_signal_cnt              ),
 82         .i_refer_cnt              (w_refer_cnt               ),
 83         .i_signal_pos_cnt         (w_signal_pos_cnt          ),
 84         .i_signal_high_cnt        (w_signal_high_cnt         )
 85     );
 86 /******************************************************************************\
 87 Gener enable signal 
 88 \******************************************************************************/    
 89     time_cnt
 90     #(
 91         .SYS_FRE                  (SYS_FRE                  )
 92     )
 93     u_time_cnt
 94     (
 95         .i_sys_clk                (i_s_axi_aclk             ),
 96         .i_sys_rstn               (i_s_axi_aresetn & w_module_en),
 97         .i_time_number            (w_ms_number              ),
 98         .o_measure_en             (w_measure_en             )
 99     );
100 /******************************************************************************\
101 Fre measure method 1 
102 \******************************************************************************/    
103     Fre_Measure1 u_Fre_Measure1
104     (
105         .i_sys_clk                (i_s_axi_aclk             ),
106         .i_sys_rstn               (i_s_axi_aresetn & w_module_en),
107         .i_signal_clk             (i_signal                 ),
108         .i_measure_en             (w_measure_en             ),
109         .o_signal_cnt             (w_signal_cnt             ),
110         .o_refer_cnt              (w_refer_cnt              ),
111         .o_measure_busy           (w_measure_busy           )
112     );
113     
114 /******************************************************************************\
115 Fre measure method 2 
116 \******************************************************************************/    
117     Fre_Measure2 u_Fre_Measure2
118     (
119         .i_sys_clk                (i_s_axi_aclk             ),
120         .i_sys_rstn               (i_s_axi_aresetn & w_module_en),
121         .i_signal                 (i_signal                 ),
122         .i_measure_en             (w_measure_en             ),
123         .o_pos_cnt                (w_signal_pos_cnt         ),
124         .o_high_cnt               (w_signal_high_cnt        )
125     );
126 endmodule

  其他模块的代码前面提到过或者比较简单,这里就不一一贴出。仿真结果如下:

顶层文件信号波形:

  Fre_Measure1:

   Fre_Measure2:

  根据上面的原理分别计算

  方法一:f1 = N1*f0/N0 = 1249997*100/20000000 = 6.249985MHz

  方法二:f1 = N1*f0/N0 = 1250000*100/20000000 = 6.25MHz                       占空比:z = 9999999/20000000 = 49.999995%  注意:对于PWM信号占空比是直接这样算,对于ADC采样信号最高位为符号位0表示正,1表示负的时候应该在信号进入模块之前取反。

根据结果貌似方法二计算的频率更加精确但精度也相差不多,仿真没问题后,可以对代码进行IP核封装使用。

 

posted on 2022-05-06 11:02  Galois_V  阅读(1520)  评论(0编辑  收藏  举报