当前位置:   article > 正文

基于FPGA的数字等精度频率计_fpga等精度数字频率计

fpga等精度数字频率计


传统的测频法原理

直接计数单位时间内被测信号的脉冲数。

  • 在理想条件下:

门控时间=基准时钟的整数倍,门控时间=待测信号的整数倍,计数器检测上升沿

对照示意图,可得如下公式(1)(2):

(1)

(2)

得到待测时钟

(3)

其中CLK_FS为基准时钟,clk_fx待测信号,GATE_TIME门控时间,

       fs_cnt为单位时间内的基准时钟的个数,

       fx_cnt单位时间内的待测时钟的个数。

  • 实际条件下:

门控信号不等于待测信号的整数倍

在对待测信号的计数时会产生误差∆fx_cnt=±1

由公式(3)计算得到待测信号的误差,通过计算可以得到相对误差,因此测量低频信号会产生较大误差.


等精度频率计原理

测量相对误差与被测信号的大小无关,实现整个频段的等精度测量

由图可以看出门控信号是待测信号的整数倍,这样对于基准信号计数时产生误差,从而使门控时间产生误差:

最后被测时钟的误差:,

相对误差: ,相对误差与被测信号,只与被测信号的大小无关。


实验程序设计

  • RTL视图

由以下四个模块:gate,  pexg , CNT, seg_led。

模块gate的作用:通过待测信号生成周期是待测信号周期整数倍(5000)的闸门信号gate,以及一个与基准时钟同步的gate_fs信号。

模块pexg:捕获gate信号和gate_fs的下降沿。

模块CNT:用gate和gate_fs分别待测信号和基准时钟计数,得到fs_cntfx_cnt,并将计算待测信号的频率date_fx。

模块seg_led:用七段数码管显示测量值。

  • 代码实现

顶层模块top_cymometer:

  1. module top_cymometer(
  2. //system clock
  3. input sys_clk , // 时钟信号
  4. input sys_rst_n, // 复位信号
  5. //spi没有使用
  6. // input CS_N,
  7. // input SCLK,
  8. // output MISO,
  9. //cymometer interface
  10. input clk_fx , // 被测时钟
  11. // output clk_out , // 输出时钟
  12. output [7:0] led0,
  13. output [7:0] led1,
  14. output [7:0] led2,
  15. output [7:0] led3,
  16. output [63:0]data_fx
  17. );
  18. //parameter define
  19. parameter CLK_FS = 26'd50000000; // 基准时钟频率值
  20. gate//生成门控信号
  21. (
  22. .clk_fs (sys_clk ), // 基准时钟信号
  23. .rst_n (sys_rst_n), // 复位信号
  24. //cymometer interface
  25. .clk_fx (clk_fx ), //待测信号
  26. .gate(gate ) , //门控信号
  27. .gate_fs(gate_fs) // 同步到基准时钟的门控信号
  28. );
  29. pexg//边沿捕获
  30. (
  31. .clk_fs (sys_clk ), // 基准时钟信号
  32. .rst_n (sys_rst_n), // 复位信号
  33. .gate(gate ) , //门控信号
  34. .gate_fs(gate_fs), // 同步到基准时钟的门控信号
  35. .clk_fx (clk_fx), //待测信号
  36. .neg_gate_fs(neg_gate_fs),
  37. .neg_gate_fx(neg_gate_fx)
  38. );
  39. CNT
  40. (
  41. //system clock
  42. .clk_fs (sys_clk ), // 基准时钟信号
  43. .rst_n (sys_rst_n), // 复位信号
  44. //cymometer interface
  45. .clk_fx (clk_fx ), //待测信号
  46. .gate(gate ) ,//门控信号
  47. .gate_fs(gate_fs) ,// 同步到基准时钟的门控信号
  48. .neg_gate_fs(neg_gate_fs),
  49. .neg_gate_fx(neg_gate_fx),
  50. .fs_cnt(fs_cnt) , // 门控时间内基准时钟的计数值
  51. .fx_cnt(fx_cnt) , // 门控时间内被测时钟的计数值
  52. .data_fx_temp(data_fx)
  53. );
  54. //通过SPI模块实现与单片机通信
  55. //spi(.clk(sys_clk),
  56. // .rst_n(sys_rst_n),
  57. // .CS_N(CS_N),
  58. // .SCLK(SCLK),
  59. // .MOSI(MOSI),
  60. // .txd_data(data_fx),
  61. // .MISO (MISO)
  62. // );
  63. //实现比较,最后调试是通过signaltap分析
  64. //seg_led u_seg_led(
  65. // //module clock
  66. // .clk (sys_clk ), // 数码管驱动模块的驱动时钟
  67. // .rst_n (sys_rst_n), // 复位信号
  68. //user interface
  69. // .data (data_fx ), // 被测频率值
  70. // .seg_led0 (led0),
  71. // .seg_led1 (led1),
  72. // .seg_led2 (led2),
  73. // .seg_led3 (led3)
  74. //);
  75. endmodule

gate模块:产生门控信号gate和同步到基准时钟下的门控信号gate_fs

  1. module gate
  2. (
  3. input clk_fs , // 基准时钟信号
  4. input rst_n , // 复位信号
  5. //cymometer interface
  6. input clk_fx ,//待测信号
  7. output reg gate , //门控信号
  8. output reg gate_fs // 同步到基准时钟的门控信号
  9. );
  10. localparam GATE_TIME = 16'd5_000; // 门控时间设置
  11. reg [15:0] gate_cnt ; // 门控计数
  12. reg gate_fs_r ; // 用于同步gate信号的寄存器
  13. //门控信号计数器,使用被测时钟计数
  14. always @(posedge clk_fx or negedge rst_n) begin
  15. if(!rst_n)
  16. gate_cnt <= 16'd0;
  17. else if(gate_cnt == GATE_TIME + 5'd20)
  18. gate_cnt <= 16'd0;
  19. else
  20. gate_cnt <= gate_cnt + 1'b1;
  21. end
  22. //门控信号,拉高时间为GATE_TIME个实测时钟周期
  23. always @(posedge clk_fx or negedge rst_n) begin
  24. if(!rst_n)
  25. gate <= 1'b0;
  26. else if(gate_cnt < 4'd10)
  27. gate <= 1'b0;
  28. else if(gate_cnt < GATE_TIME + 4'd10)
  29. gate <= 1'b1;
  30. else if(gate_cnt <= GATE_TIME + 5'd20)
  31. gate <= 1'b0;
  32. else
  33. gate <= 1'b0;
  34. end
  35. //将门控信号同步到基准时钟下
  36. always @(posedge clk_fs or negedge rst_n) begin
  37. if(!rst_n) begin
  38. gate_fs_r <= 1'b0;
  39. gate_fs <= 1'b0;
  40. end
  41. else begin
  42. gate_fs_r <= gate;
  43. gate_fs <= gate_fs_r;
  44. end
  45. end

pexg模块:边沿检测,得到的基准时钟下的gate的下降和待测时钟信号下gate的下降沿

  1. module pexg
  2. (
  3. input clk_fs , // 基准时钟信号
  4. input rst_n , // 复位信号
  5. input clk_fx ,
  6. input gate,
  7. input gate_fs ,
  8. output neg_gate_fs,
  9. output neg_gate_fx
  10. );
  11. reg gate_fs_d0 ; // 用于采集基准时钟下gate下降沿
  12. reg gate_fs_d1 ; //
  13. reg gate_fx_d0 ; // 用于采集被测时钟下gate下降沿
  14. reg gate_fx_d1 ; //
  15. //wire define
  16. //边沿检测,捕获信号下降沿
  17. assign neg_gate_fs = gate_fs_d1 & (~gate_fs_d0);
  18. assign neg_gate_fx = gate_fx_d1 & (~gate_fx_d0);
  19. //打拍采门控信号的下降沿(被测时钟)
  20. always @(posedge clk_fx or negedge rst_n) begin
  21. if(!rst_n) begin
  22. gate_fx_d0 <= 1'b0;
  23. gate_fx_d1 <= 1'b0;
  24. end
  25. else begin
  26. gate_fx_d0 <= gate;
  27. gate_fx_d1 <= gate_fx_d0;
  28. end
  29. end
  30. //打拍采门控信号的下降沿(基准时钟)
  31. always @(posedge clk_fs or negedge rst_n) begin
  32. if(!rst_n) begin
  33. gate_fs_d0 <= 1'b0;
  34. gate_fs_d1 <= 1'b0;
  35. end
  36. else begin
  37. gate_fs_d0 <= gate_fs;
  38. gate_fs_d1 <= gate_fs_d0;
  39. end
  40. end
  41. endmodule

计数&计算模块

  1. module CNT
  2. #(parameter CLK_FS = 26'd50_000_000,// 基准时钟频率
  3. parameter MAX = 10'd64) // 定义数据位宽
  4. ( //system clock
  5. input clk_fs , // 时钟信号
  6. input rst_n , // 复位信号
  7. //cymometer interface
  8. input clk_fx , // 待测信号
  9. input gate, // 门控信号(与待测时钟同步)
  10. input gate_fs, // 与基准时钟同步的门控信号
  11. input neg_gate_fx,//
  12. input neg_gate_fs,//
  13. output reg [MAX-1:0] fs_cnt , //门控时间内基准时钟信号的个数
  14. output reg [MAX-1:0] fx_cnt , // 门控时间内待测信号的个数
  15. output reg [MAX-1:0] data_fx_temp // 待测信号的频率值
  16. );
  17. reg [MAX-1:0] fs_cnt_temp ; // fs_cnt 计数
  18. reg [MAX-1:0] fx_cnt_temp ; // fx_cnt 计数
  19. //门控时间内待测信号的计数,设置的为5000个,这里重新计数,只是用于检验信号是否正确
  20. always @(posedge clk_fx or negedge rst_n) begin
  21. if(!rst_n) begin
  22. fx_cnt_temp <= 32'd0;
  23. fx_cnt <= 32'd0;
  24. end
  25. else if(gate)begin
  26. fx_cnt_temp <= fx_cnt_temp + 1'b1;
  27. end
  28. else if(neg_gate_fx) begin
  29. fx_cnt_temp <= 32'd0;
  30. fx_cnt <= fx_cnt_temp;
  31. end
  32. end
  33. //门控时间内基准时钟的计数
  34. always @(posedge clk_fs or negedge rst_n) begin
  35. if(!rst_n) begin
  36. fs_cnt_temp <= 32'd0;
  37. fs_cnt <= 32'd0;
  38. end
  39. else if(gate_fs)
  40. begin
  41. fs_cnt_temp <= fs_cnt_temp + 1'b1;
  42. end
  43. else if(neg_gate_fs) begin
  44. fs_cnt_temp <= 32'd0;
  45. fs_cnt <= fs_cnt_temp;
  46. end
  47. end
  48. //计算待测信号的频率值
  49. always @(posedge clk_fs or negedge rst_n) begin
  50. if(!rst_n) begin
  51. data_fx_temp <= 64'd0;
  52. end
  53. else if(gate_fs == 1'b0)
  54. data_fx_temp <=CLK_FS*fx_cnt/fs_cnt;
  55. end
  56. endmodule

seg_led模块。

原本打算用FPGA上的7段数码管显示,所用的DE0实验板数码管个数不够,不便显示,没有使用,于是使用signaltap分析验证


调试验证

-待测频率 5MHz  5.0Vpp

测量结果:5,000,000Hz


-待测时钟 100KHz

Signaltap测量值:100001Hz

-待测时钟 100Hz

Signaltap测量值:100Hz

-待测时钟输入:123456Hz

Signaltap测量值:123457Hz


结论

当输入待测方波信号赋值(实验测量使用的是5.0Vpp),测量结果准确稳定,能够在全频段实现比较精确的测量。


补充

上述实验测试的信号源输入方式很不安全,当信号幅度5Vpp,偏移0mV,意味着信号是\pm2.5V的输出,而FPGA通常输入范围是0~3.3V,极限是-0.7V~4.0V

信号源输出的下限超出了FPGA允许的下限,是比较危险的,推荐的设置是输出3.3Vpp,偏移1.65V。

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/383578
推荐阅读
相关标签
  

闽ICP备14008679号