您当前的位置: 首页 > 

耐心的小黑

暂无认证

  • 1浏览

    0关注

    323博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

FPGA 频率计实验

耐心的小黑 发布时间:2020-11-01 11:27:44 ,浏览量:1

参考:正点原子开拓者 FPGA 开发指南

数字频率计是一种基本的测量仪器,被广泛应用于航天、电子、测控等领域。基于传统测频原理的频率计的测量精度将随被测信号频率的下降而降低,在使用中有较大的局限性,而等精度频率计不但具有较高的测量精度,而且在整个频率区域能保持恒定的测试精度。

一、等精度频率计简介

频率测量在电子设计和测量领域中经常用到,因此对频率测量方法的研究在实际工程应用中具有重要意义。常用的频率测量方法有两种:周期测量法和频率测量法。

  • 周期测量法是先测量出被测信号的周期T,然后根据频率f = 1/T求出被测信号的频率。
  • 频率测量法是在时间t内对被测信号的脉冲数N进行计数,然后求出单位时间内的脉冲数,即为被测信号的频率。

但是上述两种方法都会产生±1个被测脉冲的误差,在实际应用中有一定的局限性。根据测量原理,很容易发现周期测量法适合于低频信号测量,频率测量法适合于高频信号测量(因为周期越大或者频率越高那么所测得的周期或者脉冲数N的相对误差就会越小),但二者都不能兼顾高低频率同样精度的测量要求。

等精度测量的一个最大特点是测量的实际门控时间不是一个固定值,而是一个与被测信号有关的值,刚好是被测信号的整数倍。在计数允许时间内,同时对基准时钟和被测信号进行计数,再通过数学公式推导得到被测信号的频率。由于门控信号是被测信号的整数倍,就消除了对被测信号产生的±l周期误差,但是会产生对基准时钟±1周期的误差。 等精度测量原理如下图所示:

在这里插入图片描述 从以上叙述的等精度的测量原理可以很容易得出如下结论:首先,被测信号频率clk_fx的相对误差与被测信号的频率无关;其次,增大测量时间段“软件闸门”或提高“标频”clk_fs,可以减小相对误差,提高测量精度;最后,由于一般提供基准时钟clk_fs的石英晶振稳定性很高,所以基准时钟的相对误差很小,可忽略。假设基准时钟的频率为100MHz,只要实际闸门时间大于或等于1s,就可使测量的最大相对误差小于或等于10^(-8),即精度达到1/100MHz。等精度测量的核心思想在于如何保证在实际测量门闸内被测信号为整数个周期,这就需要在设计中让实际测量门闸信号与被测信号建立一定的关系。基于这种思想,设计中以被测信号的上升沿作为开启门闸和关闭门闸的驱动信号,只有在被测信号的上升沿才将上图中预置的“软件闸门”的状态锁存,因此在“实际闸门”Tx内被测信号的个数就能保证整数个周期,这样就避免普通测量方法中被测信号的±1的误差,但会产生高频的基准时钟信号的±l周期误差,由于基准时钟频率远高于被测信号,因此它产生的±1周期误差对测量精度的影响十分有限,特别是在中低频测量的时候,相较于传统的频率测量和周期测量方法,可以大大提高测量精度。

等精度测频的原理图如下图所示。图中,预置软件闸门信号GATE是由FPGA的定时模块产生,GATE的时间宽度对测频精度的影响较小,故可以在较大的范围内选择,GATE信号经被测时钟clk_fx同步化(图中的D触发器)到被测时钟域下。另外,为了方便处理,这里选择预置闸门信号的长度由参数GATE_TIME设置。图中的fs_cnt和fx_cnt是2个可控的32位高速计数器,fs_cnt_en和fx_cnt_en分别是其计数使能端,由同步化后的GATE信号控制,基准时钟信号clk_fs从时钟输入端clk_fs输入,待测信号clk_fx从时钟输入端clk_fx输入。测量时,生成的GATE信号,在被测时钟同步化后用来控制启动和关闭2个计数器,2个计数器分别对被测信号和基准时钟计数。若在一次实际闸门时间GATE_TIME中,计数器对被测信号的计数值为fx_cnt,对基准时钟的计数值为fs_cnt,而基准时钟的频率为CLK_FS,则被测信号的频率为clk_fx,则由公式:

在这里插入图片描述 在这里插入图片描述

二、实验任务

板载50MHz的时钟通过分频产生某一频率的时钟信号,作为被测时钟,然后用Verilog HDL编写的等精度测量模块测量被测时钟,并通过数码管显示。

三、程序设计

根据实验任务,我们可以大致规划出系统的控制流程:首先我们设计一个测试时钟模块用于生成被测的时钟,然后用等精度频率计模块测量被测时钟的频率,并将测得的时钟频率值送入数码管显示模块进行显示。由此画出系统的功能框图如下所示:

在这里插入图片描述 由系统框图可知,FPGA部分包括四个模块:顶层模块(top_cymometer)、等精度频率计模块(cymometer)、时钟产生模块(clk_test)、以及数码管显示模块(seg_led)。各模块功能如下:

顶层模块(top_cymometer):顶层模块完成了对其它三个模块的例化,实现各模块之间的数据交互。时钟产生模块产生被测时钟输出,并从外部接入至等精度频率计模块,以进行频率测量,将测量的结果传输给数码管驱动模块进行显示。顶层模块的原理图如下图所示:

在这里插入图片描述

等精度频率计模块(cymometer):等精度频率计模块测量输入的被测时钟的频率。并将测得的频率结果输出。

时钟产生模块(clk_test):时钟产生模块产生被测的时钟。

数码管显示模块(seg_led):将等精度频率计测得的时钟频率值在数码管上显示出来。

1、顶层模块的代码如下:
module top_cymometer(
    //system clock
    input                  sys_clk  ,    // 时钟信号
    input                  sys_rst_n,    // 复位信号

    //cymometer interface
    input                  clk_fx   ,    // 被测时钟
    output                 clk_out  ,    // 输出时钟
    //user interface
    output          [5:0]  sel      ,    // 数码管位选
    output          [7:0]  seg_led       // 数码管段选
);

//parameter define
parameter    CLK_FS = 26'd50000000;      // 基准时钟频率值

//wire define
wire    [19:0]       data_fx;            // 被测信号测量值

//*****************************************************
//**                    main code
//*****************************************************

//例化等精度频率计模块
cymometer #(.CLK_FS(CLK_FS)              // 基准时钟频率值
) u_cymometer(
    //system clock
    .clk_fs      (sys_clk  ),            // 基准时钟信号
    .rst_n       (sys_rst_n),            // 复位信号
    //cymometer interface
    .clk_fx      (clk_fx   ),            // 被测时钟信号
    .data_fx     (data_fx  )             // 被测时钟频率输出
);
    
//例化测试时钟模块,产生测试时钟
clk_test #(.DIV_N(7'd100)                // 分频系数
) u_clk_test(
    //源时钟
    .clk_in      (sys_clk  ),            // 输入时钟
    .rst_n       (sys_rst_n),            // 复位信号
    //分频后的时钟
    .clk_out     (clk_out  )             // 测试时钟
);

//例化数码管显示模块
seg_led u_seg_led(
    //module clock
    .clk         (sys_clk  ),            // 数码管驱动模块的驱动时钟
    .rst_n       (sys_rst_n),            // 复位信号
    //seg_led interface
    .sel         (sel      ),            // 数码管位选
    .seg_led     (seg_led  ),            // 数码管段选
    //user interface
    .data        (data_fx  ),            // 被测频率值
    .point       (6'd0     ),            // 数码管显示的点控制
    .en          (1'b1     ),            // 数码管驱动使能信号
    .sign        (1'b0     )             // 控制符号位显示
);

endmodule
2、时钟产生模块的代码如下:
module clk_test #(parameter DIV_N = 7'd100)    //分频系数
    (
     //源时钟
     input        clk_in     ,                 // 输入时钟
     input        rst_n      ,                 // 复位信号
     //分频后的时钟
     output  reg  clk_out                      // 输出时钟
);

//reg define
reg [9:0] cnt;                                 // 时钟分频计数

//*****************************************************
//**                    main code
//*****************************************************

//时钟分频
always @(posedge clk_in or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        cnt                 
关注
打赏
1640088279
查看更多评论
0.0400s