一天一个设计实例-任意分频器设计

(一)分频器相关原理1.DDS原理任意分频原理起源于DDS(Direct Digital Synthesizer,直接频率合成法)的原理,DDS是重要的频率合成方法,在波形发生器中占有举足轻重的地位。DDS是一种从相位概念出发,直接合成所需要的波形的频率合成技术,其实质是以基准频率源(系统时钟)对相位进行等间隔采样。对于正余弦类型的频率合成,DDS基本上等效于NCO加上DA实现。DDS由相位累加器和波形存储器、数模转换器(DAC)以及模拟低通滤波器(LPF)三部分组成,实现原理与NCO完全一致,只是存储的ROM由NCO替代为需要发生的波形文件,并通过数模转换器转换为模拟信号,最后由具有内插作用的LPF将其平滑转化为连续的正弦波形以输出。一个典型的DDS硬件结构如图1‑75所示

图1‑75 典型的DDS硬件结构2.任意分频发生器的实现直接频率合成法通过相位累加原理,实现了通过步长可配置的任意波形输出。根据这个原理,通过对相位累加的地址进行处理,可以直接计算得到相应的频率。这一原理应用于Verilog HDL中,理论上也能实现任意频率的分频电路。设计实现的框图如图1‑76所示。

图1‑76 相位累加原理的实现框图假定FPGA基准时钟为100MHz,即基准时钟为:fc=100x106Hz同时规定计数器的位数N2=32,K为频率控制字,则相位累加后输出的最大频率与最小频率分别为:

21(.)变换公式,可以计算得到固定基准频率下每增/减1 Hz的频率控制字K的大小,如下所示:

22(.)由此公式可知,每增、减1 Hz,K的步进为42.949 672 96。另外,与前面的分析一致,最大的频率、最小频率(频率分辨率)分别为:

23(.)根据以上公式可以得到固定基准时钟下的任意频率发生器,其精度为0.0232831Hz。不过相位累加器得到的只是cnt累加的结果,为了得到频率,还需要对相位累加值cnt进行一定的处理,即采用类似于AD9850内DDS核的比较器,来实现方波à频率的转换。3.实验验证假定FPGA基准时钟为100MHz,即基准时钟为:fc=100x106Hz当使用UART时,波特率BPS=115200 bps。(一)直接分频法一个位的周期 = 1 / bps= 1/ 115200= 0.000086805555555555555555555555555556传输一位数据占用 0.000086805555555555555555555555555556s 时间。如果是一帧 11 位的数据,就需要0.000086805555555555556 x 11 = 0.00095486111111111111111111那么一秒钟内可以传输1 / 0.00095486111111111111111111 = 1047.27272727272727272727394591741047.2727272727272727272 个帧数据。如果用 100Mhz 的时钟频率去量化的话:( 1/115200 ) / (1/100E+6) = 8.68E-6 / 20E-9= 868.05555555555555555555555555556≈868计数上限为整数,将此值反馈代入输出频率计算式,如下:

24(.)现在要将基准时钟进行751分频(特殊才具有说明意义),产生的频率为:

25(.)由该公式可知,结果与预期的数据相差了近 10 Hz。不管这是否在波特率的允许误差范围内,用FPGA分频得到误差如此之大的频率误差简直让人无法接受。(二)任意分频发生器实现“任意频率发生器”方法:首先计算频率控制字,如下所示:

26(.)由于在FPGA中不能进行浮点运算,所以K取整数6597070。将此值反馈代入输出频率计算式,如下图所示:

27(.)最终输出的频率所产生的误差为:

28(.)由公式课件,尽管取K为整数,但最终产生的频率误差也在小数点后10位,这已经是一个非常理想的结果了。而UART转串口芯片一般允许一定的误差,如CH340 TXD的允许波特率误差小于0.3%,RXD的允许波特率误差不小于2%。因此,在可允许的范围内还有很大的余量。按照上述分析进行分频器的设计:(1)新建precise_divider的模块,其模块框图如图1‑77所示,端口定义如表1‑32所示。

图1‑77 任意分频模块框图表1‑32 任意分频模块端口列表端口名位宽输入/输出说明clk1Input全局时钟信号rst_n1Input全局复位信号divide_clk1Output分频时钟信号divide_clken1Output使能时钟信号(2)相位计数器-32位K步计数器,如下所示:代码1‑6 32位K步计数器1.//------------------------------------------------------  2.//RTL1: Precise fractional frequency for uart bps clock   3.reg [31:0]  cnt;  4.always@(posedge clk or negedge rst_n)  5.begin  6.    if(!rst_n)  7.        cnt <= 0;  8.    else  9.        cnt <= cnt + DEVIDE_CNT;       10.end如上所示,在全局时钟驱使下,进行K步计数,cnt可以理解为0~232-1的地址。类似于AD9850,可以通过计数器来实现跳跃寻址。其中DEVICE_CNT是一个在接口中经过宏定义的16倍波特率(9600x16)的分频参数,方便文件在例化时可以直接修改分频参数。(3)合成频率:方波的生成在上一步完成0~232-1寻址后,需要对地址进行比较、划分,得到一个方波信号。这类似于AD9850内部的比较器,通过输出的正弦波于门限电压做比较,得到一定频率下的方波。这里设计的Verilog HDL代码如下:代码1‑7 方波的生成1.//------------------------------------------------------  2.//RTL2: Equal division of the Frequency division clock  3.reg cnt_equal;  4.always@(posedge clk or negedge rst_n)  5.begin  6.    if(!rst_n)  7.        cnt_equal <= 0;  8.    else if(cnt < 32'h7FFF_FFFF)  9.        cnt_equal <= 0;  10.    else  11.        cnt_equal <= 1;  12.end32’h7FFF_FFFF为232-1的中点,因此它可以作为“门限电压”,来实现合成频率后的方波输出。(4)分频时钟使能信号的生成。在FPGA中,除了全局时钟外,不允许用其他门控时钟来驱动电路,不然不易于综合电路,而且也无法保证电路的稳定性。因此,为了便于后续模块的调用,需要生成使能时钟信号。这里采用 “边沿检测技术”。代码如下:代码1‑8 分频时钟使能信号的生成1.//------------------------------------------------------  2.//RTL3: Generate enable clock for clock  3.reg cnt_equal_r;  4.always@(posedge clk or negedge rst_n)  5.begin  6.    if(!rst_n)  7.        cnt_equal_r <= 0;  8.    else  9.        cnt_equal_r <= cnt_equal;  10.end  11.assign  divide_clken = (~cnt_equal_r & cnt_equal) ? 1'b1 : 1'b0;   12.assign  divide_clk = cnt_equal_r;这个分频器在后续使用中会慢慢验证,在此不会进验证(其实本人已经验证过了),有兴趣的可以自己编写程序进行验证。完整的代码及调用方式如下代码1‑9 完整的任意分频器设计代码1.//****************************************************************************//  2.//# @Author: 碎碎思  3.//# @Date:   2017-04-22 16:50:30  4.//# @Last Modified by:   zlk  5.//# @WeChat Official Account: OpenFPGA  6.//# @Last Modified time: 2017-04-22 09:19:50  7.//# Description:   8.//# @Modification History: 2017-04-22 09:19:50  9.//# Date                By             Version             Change Description:   10.//# ========================================================================= #  11.//# 2017-04-22 09:19:50  12.//# ========================================================================= #  13.//# |                                                                       | #  14.//# |                                OpenFPGA                               | #  15.//****************************************************************************//  16.`timescale 1ns/1ns  17.module  precise_divider  18.#(  19.    //DEVIDE_CNT = 42.94967296 * fo  20.//  parameter       DEVIDE_CNT = 32'd175921860  //256000bps * 16  21.//  parameter       DEVIDE_CNT = 32'd87960930   //128000bps * 16  22.//  parameter       DEVIDE_CNT = 32'd79164837   //115200bps * 16  23.    parameter       DEVIDE_CNT = 32'd6597070    //9600bps * 16  24.)  25.(  26.    //global clock  27.    input           clk,  28.    input           rst_n,  29.      30.    //user interface  31.    output          divide_clk,  32.    output          divide_clken  33.);  34.  35.//------------------------------------------------------  36.//RTL1: Precise fractional frequency for uart bps clock   37.reg [31:0]  cnt;  38.always@(posedge clk or negedge rst_n)  39.begin  40.    if(!rst_n)  41.        cnt <= 0;  42.    else  43.        cnt <= cnt + DEVIDE_CNT;       44.end  45.  46.//------------------------------------------------------  47.//RTL2: Equal division of the Frequency division clock  48.reg cnt_equal;  49.always@(posedge clk or negedge rst_n)  50.begin  51.    if(!rst_n)  52.        cnt_equal <= 0;  53.    else if(cnt < 32'h7FFF_FFFF)  54.        cnt_equal <= 0;  55.    else  56.        cnt_equal <= 1;  57.end  58.  59.//------------------------------------------------------  60.//RTL3: Generate enable clock for clock  61.reg cnt_equal_r;  62.always@(posedge clk or negedge rst_n)  63.begin  64.    if(!rst_n)  65.        cnt_equal_r <= 0;  66.    else  67.        cnt_equal_r <= cnt_equal;  68.end  69.assign  divide_clken = (~cnt_equal_r & cnt_equal) ? 1'b1 : 1'b0;   70.assign  divide_clk = cnt_equal_r;  71.  72.  73.endmodule代码1‑10 调用完整的任意分频器设计代码示例1.wire    divide_clken;  2.precise_divider   3.#(  4.    //DEVIDE_CNT = 42.94967296 * fo  5.      6.//  .DEVIDE_CNT (32'd175921860) //256000bps * 16      7.//  .DEVIDE_CNT (32'd87960930)  //128000bps * 16  8.//  .DEVIDE_CNT (32'd79164837)  //115200bps * 16  9.    .DEVIDE_CNT (32'd6597070)   //9600bps * 16  10.)  11.u_precise_divider  12.(  13.    //global  14.    .clk                (clk_ref),      //100MHz clock  15.    .rst_n              (sys_rst_n),    //global reset  16.      17.    //user interface  18.    .divide_clk         (divide_clk),  19.    .divide_clken       (divide_clken)  20.);

(0)

相关推荐

  • 二进制转BCD码

    应用: 用fpga实现对数码管显示,以前通常的方法是进行整除和取余进行运算,但是fpga并不擅长乘法除法运算,所以可以用BCD码来转换. BCD码:通俗的可以理解为用四位二进制数表示一位十进制数字.例 ...

  • 【精品博文】详细解析基于FPGA(DDS)的正弦波发生器

    [主题]:详细解析基于FPGA(DDS)的正弦波发生器 [作者]:LinCoding [时间]:2016.12.27 [声明]:转载.引用,请注明出处 我们都知道FPGA是一个数字器件,那么在通信领域 ...

  • 【精品博文】详细解析基于FPGA的任意分频

    赢一个双肩背包 有多难? 戳一下试试看! →_→ 长摁识别 [主题]:详细解析基于FPGA的任意分频 [作者]:LinCoding [时间]:2016.11.28 对于FPGA而言,分频极其重要,不多 ...

  • 【精品博文】详细解析基于FPGA的串口通信

    赢一个双肩背包 有多难? 戳一下试试看! →_→ 长摁识别 [主题]:详细解析基于FPGA的串口通信 [作者]:LinCoding [时间]:2016.11.28 串口通信,用的实在太广泛了,原理也很 ...

  • 一天一个设计实例-基于FPGA的模数、数模转换器应用设计

    基于FPGA的模数.数模转换器应用设计 本节设计采用黑金ADDA模块,模块硬件结构如下: 图7‑32 硬件结构 数模转换( DA) 电路 如硬件结构图所示, DA 电路由高速 DA 芯片. 7 阶巴特 ...

  • 一天一个设计实例-基于FPGA的数模转换器应用设计

    基于FPGA的数模转换器应用设计 1.1.1带 EEPROM 存储器的 12 位MCP4725应用设计 7.4.1.1 MCP4725简介 MCP4725 是低功耗.高精度.单通道的 12 位缓冲电压 ...

  • 一天一个设计实例-基于FPGA的模数转换器应用设计

    基于FPGA的模数转换器应用设计 1.1.1八通道AD7606应用设计 7.3.1.1 AD7606简介 AD7606 是一款集成式 8 通道数据采集系统,片内集成输入放大器.过压保护电路.二阶模拟抗 ...

  • 一天一个设计实例-AD转换器原理

    AD转换器原理 A/D 转换器的基本原理 图7‑2 A/D转换器功能示意图 A/D转换器(Analog-to-Digital Converter)又叫模/数转换器,即是将模拟信号(电压或是电流的形式) ...

  • 一天一个设计实例-LCD12864的应用设计

    LCD12864的应用设计 LCD12864的应用基本和LCD1602的自定义字库非常类似,下面就简单介绍下LCD12864. 12864 中文 汉字图形点阵液晶显示模块,可显示汉字及图形,内置 81 ...

  • 一天一个设计实例-​LCD1602的应用设计

    LCD1602的应用设计 1.1.1LCD1602的简介 工业字符型液晶,能够同时显示16x02即32个字符.(16列2行) 图6‑16 LCD1602实物图 注:为了表示的方便 ,后文皆以1表示高电 ...

  • 一天一个设计实例-LED显示模块设计

    LED显示模块设计 LED点阵模块指的是利用封装8*8的模块组合点元板形成模块,而LED模组应用中一般指两类产品:一种是用插灯或表贴封装做成的单元板,常用户外门头单红屏.户外全彩屏,室内全彩屏等:另外 ...

  • 一天一个设计实例-GPIO PWM应用

    GPIO PWM 1.1.1PWM简介 脉冲宽度调制脉冲宽度调制(PWM),是英文"Pulse Width Modulation"的缩写,简称脉宽调制,是利用微处理器的数字输出来对 ...

  • 一天一个设计实例-PS/2键盘及鼠标的应用设计

    PS/2键盘及鼠标的应用设计 1.1.1键盘与单次操作 PS/2接口用于许多现代的鼠标和键盘,由IBM最初开发和使用.物理上的PS/2接口有两种类型的连接器:5脚的DIN和6脚的mini-DIN.图1 ...