第5章 CHAPTER 5 IP的应用 在电子信息领域,IP(Intellectual Property)是指具有知识产权的功能模块。 Quartus Prime内嵌了许多功能IP,面向Intel公司的可编程逻辑器件进行了优化,设计者可以应用这些IP设定参数以满足自己的设计需求,不但能够提高设计效率,而且能够增强系统的可靠性。 资源决定方法。本章首先介绍Quartus Prime中内嵌IP的分类以及定制方法,然后结合DDS信号源和等精度频率计的设计讲述IP的应用。 图51IP目录 5.1 微课视频 5.1基本功能IP Quartus Prime中内嵌的IP可以在IP Catalog中查阅和定制,分为基本功能(Basic Functions)、数字信号处理(DSP)、接口协议(Interface Protocols)、存储器接口和控制器(Memory Interfaces and Controllers)、处理器和外围设备(Processors and Peripherals)和大学计划项目(University Program)6种类型,如图51所示。其中每种类型又包含多个子类型,如表51所示,而子类型中包含数量不等的功能IP。 表51IP的分类 IP类型子类型功 能 说 明 基本功能 Arithmetic算术运算类,包含LPM_COUNTER、LPM_MULT和LPM_DIVIDE等26个IP Bridges and Adapters桥和适配器,包含Memory Mapped Clock; PLLs and Resets时钟、锁相环和复位类,包含PLL Intel FPGA IP等3个IP Configuration and Programming配置与编程类,包含Serial Flash Loader Intel FPGA IP等15个IP I/O接口类,包含ALTDLL等9个IP Miscellaneous其他类,包含LPM_MUX等6个IP On Chip Memory片上存储器,包含FIFO等7个IP Simulation; Debug and Verification仿真、调度和验证类,包含38个IP 续表 IP类型子类型功 能 说 明 数字信号处理 Error Detection and Correction误码检测与纠正,包含Viterbi等5个IP Filters滤波器类,包含CIC和FIR Ⅱ Floating Point浮点类,包含组合和时序两个IP Signal Generation信号产生类,包含NCO Transforms信号变换类,包含FFT 接口协议 Audio and Video音频与视频类,包含4个IP Ethernet以太网类,包含1G多速率以太网等两个IP PCI ExpressPCIE接口IP Serial串行接口类,包含4个IP 存储器接口和控制器Memory Interfaces with ALTMEMPHY存储器接口类,包含DDR和DDR2 处理器和外围设备 Coprocessors协处理器类,包含Nios II用户定制指令IP Peripherals外围设备类,包含I2C等3个IP 大学计划项目 Audio & Video音频与视频类,包含1602等3个IP Clock时钟类,包含4个IP Communications通信类,包含RS232 UART等两个IP Generic IO通用I/O类,包含PS2、USB控制器等4个IP Memory存储器类,包含SRAM和SSRAM Quartus Prime内嵌的基本功能IP如表52所示,大致可分为两种类型: ①原Altera公司提供的IP,以ALT开头标注的,如ALTPLL、ALTFP_MULT和ALTFP_DIV等; ②参数化模块库(Library of Parameterized Modules)中的IP,以LPM开头标注的,如LPM_COUNTER、LPM_MULT和LPM_DEVIDE等。 表52基本功能IP IP类型子类型IP名称功 能 说 明 基本功能 Arithmetic Clock; PLLs and Resets Miscellaneous ALTFP_ABS浮点绝对值函数 ALTFP_ADD_SUB浮点加/减函数 ALTFP_COMPARE浮点比较器 ALTFP_CONVERT浮点转换器 ALTFP_DIV浮点除法器 ALTFP_EXP浮点指数函数 ALTFP_LOG浮点自然对数函数 ALTFP_MULT浮点乘法器 ALTFP_SINCOS浮点正弦/余弦函数 ALTFP_SQRT浮点平方根模块 ALTPLL锁相环模块 LPM_CLSHIFT参数化组合逻辑转换 LPM_ADD_SUB参数化加/减模块 LPM_COMPARE参数化比较器 LPM_COUNTER参数化计数器 LPM_DEVIDE参数化除法器 续表 IP类型子类型IP名称功 能 说 明 基本功能Miscellaneous On Chip Memory LPM_MULT参数化乘法器 LPM_DECODE参数化译码器 LPM_MUX参数化数据选择器 LPM_SHIFTREG参数化移位寄存器 LPM_CONSTANT参数化常数存储器 ROM: 1PORT单口ROM ROM: 2PORT双口ROM RAM: 1PORT单口RAM RAM: 2PORT双口RAM Shift Register(RAMbased)移位寄存器 需要说明的是,Quartus Prime内嵌的IP中,一类是免费的,如浮点运算、普通运算、三角函数、基本存储器类IP、配置类IP、PLL、所有的桥接组件、FPGA内嵌的Cortex ARM硬核和Nios II软核(不含源码)等; 另一类是收费的,如以太网软IP、PCIE软IP、RapidIO和视频图像处理IP以及DDR/DDR2/DDR3软IP、256位AES硬件加密IP等,使用这些IP应确保有相应的授权许可(License)。具体信息可查阅IP相关文档。 5.2 微课视频 5.2IP的定制方法 应用Quartus Prime中的IP Catalog可以很方便地引导用户定制IP。定制完成后,IP Catalog默认生成HDL目标文件(.v或.vhd),同时还能够生成图形符号文件(.bsf)、HDL例化模板文件(_inst.v或_inst.vhd)和Verilog黑盒文件(_bb.v)等多种文件类型供用户选择,如表53所示。 表53IP Catalog生成文件类型 文件类型说明 .v宏功能模块的Verilog HDL例化文件 .vhd宏功能模块的VHDL例化文件 .ppfPin Planner端口文件 .inc宏功能模块封装文件中AHDL Include文件 .cmpVHDL组件声明文件(Component Declaration File) .bsf原理图设计中使用的图形符号文件 _inst.v宏功能模块的Verilog HDL例化模板 _inst.vhd宏功能模块的VHDL例化模板 _bb.vVerilog HDL 黑盒文件,用于综合时指定端口的方向 锁相环(PhaseLocked Loop,PLL)是一种闭环电子电路,能够应用外部参考信号控制环路内部振荡器的频率和相位,合成出不同频率的信号,在数字系统中用来实现时钟的倍频、分频、占空比调整和移相等功能。 本节以定制锁相环IP,由DE2115开发板提供的50MHz晶振信号产生4选1数据选择器测试所需要的4路输入信号以及逻辑分析仪Signal Tap Logic Analyzer所需要的时钟为目标,说明IP的定制方法。 设4选1数据选择器的4路输入信号d0、d1、d2和d3的频率分别为4MHz、3MHz、2MHz和1MHz,逻辑分析仪的时钟频率为100MHz。 定制锁相环IP的具体步骤如下。 (1) 在Quartus Prime开发环境中,执行Tools→IP Catalog菜单命令进入IP目录。选择Basic Functions→Clocks; PLLS and Resets→PLL→ALTPLL,如图52所示,双击启动IP应用向导开始定制锁相环。 (2) 在弹出的Save IP Variation对话框中输入定制锁相环的名称,选择输出HDL的语言类型,并确认输出文件存放的工程目录。本例为测试4选1数据选择器定制锁相环,因此设置IP存放的目录为4选1数据选择器工程目录(C:/EDA_lab),定制的锁相环IP文件名为PLL_for_MUX4to1_tst,输出HDL的语言类型为Verilog,如图53所示。 图52锁相环定制向导(1) 图53锁相环定制向导(2) (3) 单击图53中的OK按钮进入锁相环参数设置界面,用于指定锁相环输入时钟、锁相环类型和工作模式、附加端口、锁相环的带宽以及输出信号频率等参数。 DE2115开发板的时钟电路如图54所示,由板上50MHz有源晶振为FPGA提供3路时钟信号,同时由两个SMA接口为FPGA提供外接时钟输入和时钟输出。 图54DE2115开发板时钟电路 设置锁相环ATLPLL的输入时钟频率为50MHz,实现器件为Cyclone IV E系列FPGA,速度等级为7,如图55所示。 图55锁相环定制向导(3) (4) 单击Next按钮进入锁相环附加端口配置界面,根据需要选择是否为锁相环添加异步复位端(areset)和输出锁定标志(locked)。测试数据选择器只需产生信号而不需要锁定,因此取消勾选相应的复选框,如图56所示。 图56锁相环定制向导(4) (5) 单击Next按钮进入锁相环带宽配置界面,选择是否需要指定锁相环的带宽,如图57所示。保持选择默认选项(Auto)不变。 图57锁相环定制向导(5) (6) 单击Next按钮进入锁相环附加时钟配置界面,如图58所示,选择是否为锁相环添加第2个输入时钟源并添加输入源选择端。保持选择默认选项(不添加)不变。 图58锁相环定制向导(6) (7) 连续单击Next按钮进入输出c0参数设置界面。选择使用输出信号c0,并设置频率为4MHz,相位偏移为0°,如图59所示。 图59锁相环定制向导(7) 锁相环输出信号的频率也可以通过设置乘法因子和除法因子指定。输出信号频率与输入时钟源频率以及乘法因子和除法因子的关系为 输出信号频率=乘法因子除法因子×输入时钟源频率 需要注意的是,不同系列FPGA器件中内置锁相环的性能不同。在定制锁相环时,输出信号频率不能超出锁相环的性能范围。Cyclone Ⅱ~Ⅳ系列FPGA内置锁相环的特性参数如表54所示。可以看出,Cyclone Ⅳ系列FPGA内置锁相环输出信号的频率范围为2kHz~1000MHz。 表54Cyclone系列锁相环特性参数 FPGA系列下限频率上限频率 Cyclone Ⅱ10MHz400MHz Cyclone Ⅲ2kHz1300MHz Cyclone Ⅳ2kHz1000MHz (8) 单击Next按钮进入输出c1参数设置界面。选择使用输出c1,并设置乘法因子为3,除法因子为50,相位偏移为0°,如图510所示,即设置输出c1的频率为3MHz。 图510锁相环定制向导(8) 同理,选择使用输出c2和c3,并设置c2和c3的频率分别为2MHz和1MHz。 (9) 单击Next按钮进入输出c4参数设置界面。选择使用输出c4,并指定c4频率为100MHz,如图511所示。 图511定制锁相环向导(9) (10) 连续单击Next按钮进入锁相环定制文件生成界面,如图512所示,通过勾选相应文件选择需要生成的文件类型,其中灰色表示默认生成的文件。若需要在原理图设计中调用定制的锁相环,则需要勾选图形符号文件pll_for_MUX4to1_tst.bsf; 若需要通过例化方式调用锁相环,则需要pll_for_MUX4to1_tst_inst.v文件; 若需要通过第三方软件进行综合,则需要pll_for_MUX4to1_tst_bb.v文件,将锁相环模块作为黑盒进行例化。 图512锁相环定制向导(10) 生成文件选择完成后,单击Finish按钮完成锁相环的定制过程。 (11) 在Quartus Prime主界面中,执行Project→Add/Remove Files in Project菜单命令,在弹出的对话框中可以看到锁相环模块PLL_for_MUX4to1_tst.qip已经添加到工程中,如图513所示。因此,在设计工程中可以通过图形符号或Verilog例化方式调用定制好的锁相环。 图513已添加的IP文件 5.3a 微课视频 5.3b 微课视频 5.3c 微课视频 5.3DDS信号源的设计 信号源是常用的电子仪器,能够输出正弦、脉冲、调制和扫频等多种类型信号,作为电子系统的激励源或噪声源,用于测量系统的振幅特性、频率特性、传输特性和其他电参数,或者用于测量元器件的特性和参数。 直接数字频率合成器(Direct Digital Synthesizer,DDS)应用数字技术实现信号源,具有控制灵活、分辨率高和稳定性好等优点。 DDS信号源的基本结构如图514所示,由相位累加器、波形存储器、D/A转换器和低通滤波器4部分组成,其中相位累加器和波形存储器应用数字方法实现。 图514DDS信号源的基本结构 DDS信号源的工作原理是相位累加器在时钟脉冲的作用下进行相位循环累加,输出相位序列。波形存储器以相位累加器输出的相位序列作为地址,从存储器中查询相应的波形数据后依次输出。D/A转换器和低通滤波器则用于将波形存储器输出的数字信号还原为模拟信号。 图515正弦DDS的实现原理 正弦相位累加的原理可以通过图515来解释。在一个正弦周期(0~2π)上均匀采样2n个点(对应最小的相位增量为2π/2n),并将采样点的正弦模拟幅度值经过量化与编码转换为数字量后存入ROM中。然后,在时钟脉冲的作用下: (1) 依次输出每个采样点(对应相位增量N=1)的幅值时,那么经过2n个时钟才能输出一个完整的正弦波,因此输出正弦信号的周期为时钟周期的2n倍,即输出正弦信号的频率为时钟频率的1/2n; (2) 每隔一个点输出一个采样点(对应相位增量N=2)的幅值时,则经过2n/2个时钟就能输出一个完整的正弦波,输出正弦信号的周期为时钟周期的2n-1倍,即输出正弦信号的频率为时钟频率的2/2n; (3) 每隔两个点输出一个采样点(对应相位增量N=3)的幅值时,则经过2n/3个时钟就能输出一个完整的正弦波,因此输出正弦信号的周期为时钟周期的2n/3倍,即输出正弦信号的频率为时钟频率的3/2n。 以此类推,可推出DDS输出正弦信号的频率fOUT与时钟脉冲频率fclk之间的关系为 fOUT=fclk2n×N 其中,N为相位增量,通常称为频率控制字。 本节以设计能够输出100Hz~25.5kHz,步进为100Hz的DDS正弦信号源为目标,讲述ROM IP在数字系统设计中的应用。 分析①频率范围为100Hz~25.5kHz,步进为100Hz的正弦信号共有255种频率值,因此需要用8位频率控制字(因为27<255<28)进行控制; ②为了保证输出正弦信号无失真,根据奈奎斯特采样定理,每个正弦周期至少应输出2个及以上的采样点,才能恢复出正弦波,而且输出的采样点数越多,越有利于后续低通滤波器的设计。但是,采样点数越多,所需要的存储容量越大,消耗的FPGA存储资源越多,因此需要折中考虑。当输出25.5kHz正弦波时,若设计每个周期输出16个采样点,则DDS信号源的时钟频率至少应取25.5kHz×16=408kHz。 根据上述分析,取DDS时钟脉冲fclk为409.6kHz,n=12和8位频率控制字时,能够输出的正弦波信号的频率恰好为100Hz~25.5kHz,步进为100Hz。 为了节约FPGA片上有限的存储资源,对图516所示的正弦信号进行采样时,只存储第1象限(0~π/2)的正弦采样值,然后利用正弦波结构的对称性,映射出第2~4象限(π/2~2π)的正弦函数值。 本例中的相位累加器设计、正弦ROM的定制以及输出数据的校正都是按照这种思路处理的。 图516正弦波波形 设计过程正弦DDS信号源设计方案如图517所示。在时钟脉冲的作用下,12位相位累加器以频率控制字为步长进行相位循环累加,输出10位相位值,然后将相位累加器输出的10位相位值序列作为正弦ROM的地址,查询预先存放在ROM中正弦波的第1象限1024个采样数据输出数字化正弦幅值序列,ROM输出的数据校正后经过8位D/A转换器转换为时间连续的信号,再经过低通滤波器输出正弦模拟信号。 图517正弦DDS信号源设计方案 基于上述设计方案,应用FPGA实现DDS信号源时,需要应用Verilog HDL描述相位累加器和定制正弦ROM。在设计之前,先建立新工程(设工程名为DDS_sin4096x8b),以便设计和定制过程中产生的相关文件能够添加到工程中。 5.3.1相位累加器的设计 相位累加器在时钟脉冲的作用下,将加法器输出的相位值与频率控制字循环累加,以保持相位的连续变化,从而保证输出波形的连续性。 取n=12时,应采用12位二进制相位累加器。只存储1/4周期正弦采样数据时,相位累加器只需要输出10位相位序列值和正弦数据是否需要反相的标志。因此,实现相位累加的Verilog代码参考如下。 module phase_adder12b(clk,rst_n,phase_step,phase_out,datinv); input clk,rst_n; // DDS时钟及复位信号 input [7:0] phase_step ; // 频率控制字 output reg [9:0] phase_out; // 相位输出 output reg datinv; // 数据反相标志 // 内部变量定义 reg [11:0] cnt; // 相位累加寄存器 // 时序逻辑过程,相位累加 always @( posedge clk or negedge rst_n ) if ( !rst_n ) cnt <= 12'b0; else cnt <= cnt + phase_step; // 组合逻辑过程,定义输出 always @( cnt ) case ( cnt[11:10] ) 2'b00: begin phase_out = cnt[9:0]; datinv = 0; end // 第1象限 2'b01: begin phase_out = ~cnt[9:0]; datinv = 0; end // 第2象限 2'b10: begin phase_out = cnt[9:0]; datinv = 1; end // 第3象限 2'b11: begin phase_out = ~cnt[9:0]; datinv = 1; end // 第4象限 default: begin phase_out = cnt[9:0]; datinv = 0; end endcase endmodule 以phase_adder12b.v文件建立工程并进行编译和综合后,执行Files→Create∠Update→Create Symbol Files for Current File菜单命令,为模块phase_adder12b.v生成图形符号文件phase_adder12b.bsf,以便在顶层设计中调用。 5.3.2正弦ROM的定制 正弦ROM用于实现“相位幅度”的转换,根据正弦波的相位值输出相应的幅度值。1024×8位正弦ROM可以定制单口ROM IP实现。 在定制ROM之前,首先需要创建存储器初始化文件,以便在定制ROM过程中能够加载正弦采样数据。 1. 创建存储器初始化文件 Quartus Prime支持两种格式的存储器初始化文件: MIF(Memory Initialization File)文件格式和HEX(Hexadecimal)文件格式。 1) MIF文件 MIF为原Altera公司定义的纯文本格式的存储器初始化文件,可以用任何文本编辑器(如记事本)进行编辑。 1024×8位的MIF文件格式如下。 -- 说明部分略 WIDTH= 8 ; // 定义存储数据的位宽,以十进制数表示 DEPTH= 1024 ; // 定义存储单元的总数,以十进制数表示 ADDRESS_RADIX=BIN/DEC/HEX/UNS; // 定义地址基数 DATA_RADIX=BIN/DEC//HEX/UNS; // 定义数据基数 /*BIN表示二进制数, DEC表示十进制数, HEX表示十六进制数, UNS表示无符号十进制数 */ CONTENT BEGIN // 描述存储单元及数值 单元0 : 数值0; // 单元号: 存储数值 单元1 : 数值1; 单元2 : 数值2; … 单元1023: 数值1023; END; 图518设置存储器单元数和位数 MIF文件格式可以在Quartus Prime中生成。在Quartus Prime环境下新建存储器初始化文件,在弹出的如图518所示的对话框中的Number of words和Word size文本框中分别设置存储器的单元数和存储数据的位宽,先建立一个空白的.mif文件,然后将初始化数据填入后保存即可。 存储器初始化文件还可以直接应用C程序生成。将一个正弦周期均匀采样4096个点,计算并存储第1象限的1024个采样点数据。每个采样点的数据用8位无符号二进制数表示。生成1024×8位正弦ROM初始化数据文件(设文件名为sin1024x8b.mif)的C程序参考如下。 #include// 包含算术运算库 #include// 包含标准输入/输出库 #define PI 3.1415926 // 定义PI为3.1415926 // 存储器初始化文件名和路径定义 #define PATH "c:/EDA_lab/sin1024x8b.mif" int main (void) { float x; // 定义浮点变量,用于保存正弦计算值 unsigned char sin8b; // 定义8位无符号整型变量,用于保存正弦变换值 FILE* fp_mif; // 定义文件指针 unsigned int i; // 定义循环变量 // 打开存储器初始化文件 fp_mif=fopen(PATH,"w+"); // 添加文件信息头 fprintf(fp_mif,"WIDTH=8;\n"); fprintf(fp_mif,"DEPTH=1024;\n"); fprintf(fp_mif,"ADDRESS_RADIX=UNS;\n"); fprintf(fp_mif,"DATA_RADIX=UNS;\n"); fprintf(fp_mif,"CONTENT BEGIN\n"); // 计算并保存地址和正弦数据 for (i=0;i<1024;i++) // 输出1024个点 { x=sin(2*PI*i/4096); // 采样4096个点 sin8b=(int)((x+1)*255/2); // 转换为8位无符号数 fprintf(fp_mif,"%4d : %3d;\n",i,sin8b); //保存地址和数据 } // 写入结束标志 fprintf(fp_mif,"END;\n"); // 关闭文件返回 fclose(fp_mif); return 0; } 存储器初始化文件也可以应用MATLAB软件生成。生成1024×8位正弦采样数据初始化文件sin1024x8b.mif的m代码参考如下。 fp=fopen('C:\EDA_lab\sin1024x8b.mif','w+'); fprintf(fp,'WIDTH=8;\r\n'); fprintf(fp,'DEPTH=1024;\r\n'); fprintf(fp,'ADDRESS_RADIX=HEX;\r\n'); fprintf(fp,'DATA_RADIX=HEX;\r\n'); fprintf(fp,'CONTENT BEGIN\r\n'); for i=0:1023 fprintf(fp,'%4x:%4x;\n,i,round((0.5+0.5*sin(2*pi*i/4096))*255); fprintf(fp,'END;\n'); fclose(fp); 在Quartus Prime开发环境下分别打开C程序和MATLAB生成的存储器初始化文件sin1024x8b.mif。初始化文件的数据片段如图519所示。 图519存储器初始化数据文件 2) HEX文件 HEX是Intel公司定义的通用数据文件格式,既可以在Quartus Prime中直接生成,也可以将.mif文件转换为.hex文件。 直接生成.hex文件的方法: 在Quartus Prime环境下新建一个空白HEX文件(设文件名为sin1024x8b.hex),然后将C程序/MATLAB生成的正弦采样数据填入sin1024x8b.hex中保存即可。 实现.mif文件到.hex文件转换的方法: 在Quartus Prime中先打开.mif文件,再另存为.hex文件。 需要注意的是,基于向量波形方法仿真含有ROM的数字系统时,既可以应用.mif文件加载存储器初始化数据,也可以应用.hex文件加载存储器初始化数据。但是,基于testbench仿真含有ROM的数字系统时,只能应用.hex文件加载存储器初始化数据。因此,用C程序生成存储器初始化后,如果需要应用testbench进行仿真,还需要在Quartus Prime环境下将.mif存储器初始化文件转换为.hex文件格式。 2. 定制ROM 存储器初始化文件生成之后,按照以下步骤定制正弦波ROM。 (1) 打开Quartus Prime,执行Tools→IP Catalog菜单命令进入IP目录,如图520所示。 图520正弦ROM定制向导(1) (2) 双击IP Catalog中Basic Functions栏下On Chip Memory中的ROM: 1PORT,开始定制单口ROM。 (3) 在弹出的Save IP Variation对话框中,输入保存定制ROM的名称,选择输出HDL的语言类型,并确认输出文件将保存在DDS工程目录中。 本例中设定输出文件存放的目录为C:/EDA_lab,输出文件名为sin_rom_quarter,输出HDL的语言类型为Verilog,如图521所示。 图521正弦ROM定制向导(2) (4) 单击图521中的OK按钮进入设置ROM存储单元数和位宽界面。 设置ROM的单元数为1024(在下拉列表中选择或直接输入),位宽为8位,时钟模式为单时钟,Auto实现方式,如图522所示。 图522正弦波ROM定制向导(3) (5) 单击Next按钮进入添加功能端口界面。取消勾选'q' output port选项以取消ROM的输出寄存功能,如图523所示。 图523正弦ROM定制向导(4) (6) 单击Next按钮进入添加存储器初始化文件对话框。首先选择“Yes,use this file for memory content data”单选项,然后单击Browse按钮查找并选中已经生成好的初始化文件sin1024x8b.mif(或sin1024x8b.hex),如图524所示,确认加入。 图524正弦ROM定制向导(5) (7) 单击Next按钮两次进入输出文件生成界面,如图525所示。勾选sin_rom_quarter.bsf选择输出图形符号文件,以便在顶层设计中通过原理图方式调用。单击Finish按钮完成定制过程。 图525正弦ROM定制向导(6) (8) 执行Project→Add/Remove Files in Project菜单命令,可以看到已经加入工程中的sin_rom_quarter.qip IP文件,如图526所示。 图526正弦ROM定制向导(7) 5.3.3输出数据的校正 由于正弦ROM中只存储了第1象限的正弦采样数据值,因此,需要对ROM输出的正弦数据进行校正才能映射出完整的正弦周期数据序列。 对正弦数据进行校正的Verilog代码参考如下。 module sin_dat_adj ( input [7:0] din, // 第1象限正弦序列输入 input datflag, // 数据校正标志 output wire [7:0] dout // 正弦序列数输出 ); // datflag=1时按位取反,映射出第3、4象限的正弦数据 assign dout = datflag? ~din : din; endmodule 将上述代码经编辑综合后封装成图形符号文件(sin_dat_adj.bsf),以便在DDS信号源顶层电路设计中调用。 另外,如果在sin_dat_adj模块的对外端口中添加如下输出口和相应的端口赋值语句,则可以输出与正弦信号同频的方波信号。 output wire squ_out, // 输出端口 assign squ_out = datflag; // 端口赋值语句 5.3.4顶层电路设计 DDS正弦信号源的顶层电路应用原理图进行设计。 打开Quartus Prime,新建设计文件并选择Design Files栏下的Block Diagram/Schematic Files,打开原理图编辑窗口。在编辑窗口的空白处双击,单击Name栏右侧的浏览按钮,依次调入相位累加器phase_adder12b.bsf、正弦波存储器sin_rom_quarter.bsf和输出数据校正模块sin_dat_adj.bsf的图形符号,按图517的设计方案连接成如图527所示的顶层设计电路,并将顶层原理图文件保存为DDS_sin4096x12b.bsf(顶层设计文件必须与工程同名)。 图527DDS正弦信号源顶层设计电路 1. 仿真分析 建立向量波形文件,添加信号源时钟DDS_clk、复位信号RST_n、频率控制字Fstep和正弦输出序列sin_out为需要观测的信号。执行Edit→Set End Time菜单命令,将仿真结束时间设置为81.92μs(因为81.92μs/2/10ns=4096,对应一个正弦基波周期)。设置Fstep为8进行仿真,得到如图528所示的仿真结果。 图528正弦DDS信号源仿真波形 从仿真波形可以看出,输出正弦序列幅值与采样值一致。若将输出的正弦序列幅值经过D/A转换和低通滤波,就可以还原为正弦模拟信号。 2. Signal Tap Logic Analyzer测试 定制锁相环ALTPLL输出409.6kHz方波(c0和c1),分别作为DDS信号源的时钟和逻辑分析仪的采样时钟。建立如图529所示的DDS信号源测试电路。 图529DDS信号源测试电路 设置锁相环的输入时钟为50MHz。将频率控制字Fstep[7:0]锁定到DE2115开发板的SW7~SW0上,将复位信号锁定到DE2115开发板的KEY0上,将正弦序列输出sin_out[7:0]锁定到GPIO[11]~[25]单号引脚上。具体的锁定信息如图530所示。 图530DDS信号源测试电路引脚锁定信息 新建逻辑分析仪文件(打开Signal Tap Logic Analyzer File),添加DDS时钟(PLL_for_DDS的c0)、频率控制字Fstep[7:0]、相位累加器输出phase_out[9:0]和正弦序列输出sin_out[7:0]为需要观测的信号,如图531所示。 图531添加需要观测信号 设置逻辑分析仪的采样时钟为409.6kHz(PLL_for_DDS中的c1),采样深度为128kb,重新编译工程并下载到FPGA中,设置频率控制字Fstep为8并启动逻辑分析仪进行分析,设置相位累加器输出phase_out和正弦序列输出sin_out为unsigned line chart显示方式,得到如图532所示的测试波形。可以看出,DDS功能正确。 图532DDS信号源逻辑分析波形 需要说明的是,Quartus Prime提供了功能强大的数控振荡器(Numerically Controlled Oscillator,NCO)IP,用户只需要对NCO IP进行简单的配置,就可以方便地生成单路或双通道高精度离散正弦波和余弦波,在信号处理、数字通信和电力电子等领域有着重要的应用。有兴趣的读者可查阅Intel公司的相关文档学习NCO的使用方法。 5.3.5D/A转换及滤波电路 D/A转换电路用于将FPGA输出的正弦幅值序列转换为时间上连续、幅值上离散的信号,再通过低通滤波器还原为正弦模拟信号。 由于正弦采样数据为8位无符号二进制数,因此需要用8位D/A转换器进行转换。 DAC0832为集成8位D/A转换器,电流建立时间为1μs。因此,在不考虑外接运放特性的情况下,DAC0832理论上的最高输入速率为106次/s。正弦DDS信号源的时钟频率为409.6kHz,即每秒输出409600个数据,所以DAC0832能够满足设计要求。 DAC0832内部结构如图533所示,由8位输入寄存器、8位DAC寄存器和8位梯形电阻网络D/A转换器3部分组成。其中,8位输入寄存器由ILE、CS′和WR′1信号控制,8位DAC寄存器由WR′2和XFER′信号控制。 DAC0832可设置为双缓冲、单缓冲或直通3种工作模式。当ILE、CS′和WR′1信号均有效时,锁存允许信号LE′1无效,因此外部待转换的二进制数DI7~DI0通过输入寄存器到达DAC寄存器的输入端。当WR′2和XFER′信号均有效时,锁存允许信号LE′2无效,输入寄存器的数据通过DAC寄存器到达D/A转换器的输入端,开始进行D/A转换。 图533DAC0832内部结构 DAC0832为电流输出型DAC,还需要应用IV转换电路将输出电流转换为电压。 应用DAC0832设计的DDS信号源D/A转换和滤波电路如图534所示,先将FPGA输出的8位正弦幅值序列sin_out[7:0]经过DAC0832(设置为直通工作模式)转换为电流信号IOUT,再应用运放将输出电流IOUT转换为电压,最后通过RC低通滤波电路,即可得到正弦模拟信号vo。 图534D/A转换与滤波电路 由于输出正弦信号的最高频率为25.5kHz,因此设置低通滤波器的上限频率为25.5/0.707≈36kHz即可满足设计要求。经计算,取C=0.01μF,R≈440Ω。 需要说明的是,当集成D/A转换器的速率不能满足设计要求,或者成本太高时,可以应用如图535所示的双级权电阻网络D/A转换原理电路搭建D/A转换器,选择合适的运放满足设计需求。图535中8R电阻可用4个2R电阻串联实现,4R电阻可用两个2R电阻串联实现,而R电阻可用2个2R电阻并联实现,R/2电阻可用4个2R电阻并联实现,以方便权电阻网络设计。 另外,在对驱动能力要求不高的应用场合,还可以省去图535中的运放和反馈电阻,优点是不但能够节约电路成本,并且D/A转换的速度不再受运放的性能限制,但缺点是D/A转换器的驱动能力不强。 DDS信号源以其输出频率可控、精度高和稳定性好等优点在电子系统设计中广泛应用。例如,在2019年电子设计竞赛D题(简易电路特性测试仪)中,需要应用DDS信号源为放大电路提供交流输入信号,如图536所示,以测量放大电路的输入电阻、输出电阻、电压增益以及通频带等特性参数。电路特性测试仪的具体任务要求可从全国电子设计竞赛官网(nuedc.xjtu.edu.cn)下载。设计思路和实现方法留给读者思考和实践。 图535双级权电路网络D/A转换器 图536简易电路特性测试仪 5.3.6功能扩展及应用 如果将DDS信号源中应用的单口ROM扩展为图537所示的双口ROM,同时改写相位累加器代码以驱动双口ROM输出双路正弦数据,再添加相位初值控制字以设置两个通道的相位差,则可实现双频、相差可调的双通道DDS信号源,可用于信号的调制与解调等应用场合。 图537双口ROM 双路正弦DDS信号源的相位累加器描述代码参考如下。 module bichannel_phase_adder12b ( input ch1_clk,ch2_clk, // 双路时钟信号 input rst_n, // 复位信号 input [7:0] freq_word1,freq_word2, // 8位频率控制字 input [11:0] phase_value1,phase_value2, // 12位相位初值控制字 output reg [9:0] rom_addr1,rom_addr2, // 10位ROM地址输出 output reg datinv1,datinv2 // 数据是否反相标志 ); // 内部线网和变量定义 reg [11:0] cnt1,cnt2; wire [11:0] phase_out1,phase_out2; // 相位累加输出 assign phase_out1 = cnt1 + phase_value1; assign phase_out2 = cnt2 + phase_value2; // 时序逻辑过程,通道1相位累加 always @( posedge ch1_clk or negedge rst_n ) if ( !rst_n ) cnt1 <= 12'b0; else cnt1 <= cnt1 + freq_word1; // 时序逻辑过程,通道2相位累加 always @( posedge ch2_clk or negedge rst_n ) if ( !rst_n ) cnt2 <= 12'b0; else cnt2 <= cnt2 + freq_word2; // 组合逻辑过程,通道1输出 always @( phase_out1 ) case ( phase_out1[11:10] ) 2'b00: begin rom_addr1 = phase_out1[9:0]; datinv1 = 0; end 2'b01: begin rom_addr1 = ~phase_out1[9:0]; datinv1 = 0; end 2'b10: begin rom_addr1 = phase_out1[9:0]; datinv1 = 1; end 2'b11: begin rom_addr1 = ~phase_out1[9:0]; datinv1 = 1; end default: begin rom_addr1 = phase_out1[9:0]; datinv1 = 0; end endcase // 组合逻辑过程,通道2输出 always @( phase_out2 ) case ( phase_out2[11:10] ) 2'b00: begin rom_addr2 = phase_out2[9:0]; datinv2 = 0; end 2'b01: begin rom_addr2 = ~phase_out2[9:0]; datinv2 = 0; end 2'b10: begin rom_addr2 = phase_out2[9:0]; datinv2 = 1; end 2'b11: begin rom_addr2 = ~phase_out2[9:0]; datinv2 = 1; end default: begin rom_addr2 = phase_out2[9:0]; datinv2 = 0; end endcase endmodule 综合上述代码,并封装为图形符号,然后将相位累加模块bichannel_phase_adder12b、双口ROM和数据校正模块sin_dat_adj连接成如图538所示的双通道DDS顶层设计电路。 图538双通道DDS顶层设计电路 由于单个正弦周期共采样了4096个点,对应正弦相位为360°,因此两个相邻采样点之间对应的相位增量为360°/4096=0.087890625°,由此可以推算出正弦波的相差与相位初值差数之间的关系,如表55所示。所以,需要产生相差为90°的正交信号时,应设置双路信号的相位初值之差为1024。 表55相差与相位初值关系 要求相差初值差数 十进制十六进制 要求相差 初值差数 十进制十六进制 0°00001802048800 45°5122002252560A00 90°10244002703072C00 135°15366003153584E00 在双通道DDS信号源的测试过程中,为了能够在线(online)设置正弦波的输出频率和相差,需要定制参数化常数存储器IP为频率控制字freq_word1和freq_word2、相位初值phase_value1和phase_value2提供输入值。 定制参数化常数存储器IP的具体步骤如下。 图539常数寄存器定制向导(1) (1) 执行IP Catalog命令进入IP目录。双击Basic Functions栏下Miscellaneous中的LPM_CONSTANT,如图539所示,启动参数化常数存储器IP的定制过程。 (2) 在Save IP Variation对话框中设置IP变量文件名为Fword1,如图540所示,然后单击OK按钮进入IP参数设置界面。 图540常数寄存器定制向导(2) 图541常数寄存器定制向导(3) (3) 在如图541所示的IP参数设置界面中,将Fword1的位宽设置为8,常数值设置为8,例化ID名设置为FWD1,并勾选Allow InSystem Memory Content Editor to capture and update content independently of the system clock选项,以便在逻辑分析仪工作过程中能够应用InSystem Memory Content Editor在线捕获和更新常数值。 (4) 连续单击Next按钮跳过仿真网表生成步骤,进入IP输出文件生成界面,如图542所示。勾选图形符号文件Fword1.bsf,以便在顶层原理图电路中调用。 单击Finish按钮完成Fword1的定制过程。 按相同的步骤定制Fword2、Pvalue1和Pvalue2,分别将例化ID名设置为FWD2、PVL1和PVL2。Fword2的值设置为8,而Pvalue1和Pvalue2的位宽设置为12,常数值设置为0。 将参数化常量Fword1和Fword2、Pvalue和Pvalue2分别与顶层设计电路中的频率控制字freq_word1和freq_word2、相位初值phase_value1和phase_value2相连,如图538所示,即设置DDS输出双路初始相位均为0°的800Hz正弦波。编译并综合顶层设计电路,并完成引脚锁定。 新建逻辑分析仪文件,设置采样时钟为409.6kHz(应用PLL_for_DDS中的c1),采样深度设置为16k。添加累位累加器输出地址rom_addr1和rom_addr2,以及双口ROM输出的正弦序列sinout1和sinout2为需要观测的信号。 重新编译工程后下载到FPGA中,启动逻辑分析仪进行分析,设置正弦序列sinout1和sinout2为unsigned line chart显示方式,得到如图543所示的逻辑分析波形。从图543中的地址和数据以及通道波形可以看出,双通道正弦信号同相。 图542常数寄存器定制向导(4) 图543双通道DDS逻辑分析波形(1) 在Quartus Prime开发环境下,执行Tools→InSystem Memory Content Editor菜单命令启动在系统存储器数据编辑器,初始界面如图544所示。 单击图544中的Setup按钮建立USBBlaster连接,然后执行Processing→Read Data from InSystem Memory菜单命令(或者直接按F5快捷键)依次读入参数化常量FWD1和FWD2、PVL1和PVL2的存储数据,如图545所示。 选中PLV2的数值000,修改为(十六进制)400,如图546所示。然后执行Processing→Write Data to InSystem Memory菜单命令(或者直接按F7快捷键)将修改后的常量值写回到PLV2中。 参数修改完成后,返回逻辑分析仪重新进行分析,得到如图547所示的波形。从图547中的地址和数据的对应关系以及通道波形可以看出,双通道正弦信号正交。 需要说明的是,InSystem Memory Content Editor主要用于读取和更新ROM/RAM中的存储数据。在DDS信号源的设计过程中,在定制ROM时需要勾选Allow InSystem Memory Content Editor to capture and update content independently of the system clock选项(见图524),才能应用在系统(InSystem)存储器数据编辑器读取和编辑ROM中的存储数据,如图548所示,实现存储数据的在线更新。 图544在系统存储器数据编辑器初始界面 图545读取常量值 图546写回常量值 图547双通道DDS逻辑分析波形(2) 双通道DDS信号源能够产生不同相差、不同频率的双路信号。产生同频的正交信号时,可实现信号的正交调制与解调。2013年电子设计竞赛E题(简易频率特性测试仪的系统结构)如图549所示,需要应用正交信号实现网络幅频特性和相频特性的测量。 另外,如果将DDS正弦信号源与PWM相结合,还可以实现脉冲宽度按正弦规律变化的正弦脉宽调制波(Sinusoidal PWM,SPWM)。在电力电子技术中,相对于空间矢量、随机 图548DDS信号源ROM中的存储数据 采样和自然采样等其他类型的PWM,SPWM的谐波分量最小,因此广泛应用于电机调速和变频电源等应用场合。 图549频率特性分析仪系统结构 SPWM波产生原理如图550所示,其中三角波称为载波,正弦波称为调制波。将三角波幅度与正弦波幅度进行比较,当三角波幅度大于正弦波幅度时输出为低电平,三角波幅度小于正弦幅度时输出为高电平,即可得到占空比随正弦信号变化的SPWM。一般将三角波与正弦波的频率之比称为载波比。 图550SPWM波产生原理 应用FPGA产生SPWM的数字系统结构如图551所示,其中锁相环输出两路时钟信号,一路作为三角波产生模块的时钟,另一路作为正弦波产生模块的时钟。CNT10b模块为10位二进制计数器,DDS正弦信号源和三角波信号源每周期存储1024点,每个采样点的幅值用10位二进制数表示。 图551SPWM顶层设计电路 三角波产生模块triang_wave_gen的Verilog代码参考如下。 module triang_wave_gen ( cnt_in, tri_out); input [9:0] cnt_in; output wire [9:0] tri_out; // 条件操作符描述 assign tri_out = ( cnt_in<10'd512 ) ? cnt_in[9:0] <<1 : ( cnt_in == 10'd512 ) ? 10'd1023: (11'd1024-cnt_in)<<1 ; SPWM波产生模块spwm_gen的Verilog代码参考如下。 module spwm_gen (clk,data1,data2,spwm_out); input clk; input [9:0] data1; input [9:0] data2; output reg spwm_out; // 数值比较过程 always @ ( posedge clk ) if ( data1>data2 ) spwm_out <= 0; else spwm_out <= 1; endmodule 需要产生频率为30Hz,载波比为30的SWPM时,正弦波时钟信号的频率应设置为30Hz×1024=30.72kHz,三角波时钟信号的频率应为30.72kHz×30=0.9144MHz。 新建逻辑分析仪文件,以每周期采样4个载波点计算,则应设置采样时钟为30×30×4=3600Hz(从PLL_for_DDS的c2口输出),采样深度设置为128k。添加SPWM产生模块的时钟clk、三角波和正弦波的输入信号data1和data2,以及SPWM波的输出spwm_out为需要观测的信号。 重新编译工程后下载到FPGA,启动逻辑分析仪进行分析,设置data1和data2为unsigned line chart显示方式,得到如图552所示的逻辑分析仪波形。可以看出,系统能够输出SPWM。 图552SPWM电路逻辑分析波形 若用SPWM驱动DE2115开发板上的发光二极管,则能够控制发光二极管的亮度周期变化(习惯上称为呼吸灯)。若应用3组SPWM控制一组红、绿、蓝三基色发光二极管,则可以通过相位差组调节灯光的色调和亮度。 5.4a 微课视频 5.4b 微课视频 5.4c 微课视频 5.4等精度频率计的设计 第3章和第4章中讲述的数字频率计均基于直接测频法设计。 直接测频法通过统计在固定时间内被测信号的脉冲数,从而计算出被测信号的频率值。由于闸门信号的作用时间与被测信号不一定同步,在计数过程中可能会存在一个脉冲的计数误差,所以被测信号的频率越低,测频的相对误差越大。虽然可以通过加长闸门信号的作用时间减小测量误差,但是存在着测量实时性和测量精度之间的矛盾。 等精度频率计通过控制闸门的作用时间与被测信号同步消除了直接测频法中的计数误差,因而从理论上讲,在被测信号频率范围内测频精度是恒定的。 本节以设计能够测量信号的频率范围为1Hz~100MHz,频率测量的相对误差不大于0.01%的等精度频率计为目标,进一步说明IP在数字系统设计中的应用。频率测量结果仍用8位数码管显示。 要求等精度频率计的测频误差δmax不大于0.01%时,若取标准信号频率为96MHz(周期约为10.42ns),则要求闸门的作用时间最短为 Td=Ts/δmax=1.042×10-80.0001≈1.042×10-4s 即闸门的作用时间大于104.2μs即可满足测量精度要求。为方便主控电路设计,等精度频率计闸门的作用时间仍设计为1s。 等精度测频的原理电路如第1章图14所示,总体设计方案如图553所示,其中主控电路、标准信号产生电路、频率测量与计算电路以及数值转换与显示译码电路都可以在FPGA中实现。 图553等精度频率计总体设计方案 标准信号产生电路通过定制锁相环模块ALTPLL实现,将DE2115开发板提供的50MHz晶振锁定到96MHz。另外,锁相环输出10MHz信号以方便分频器设计。锁相环定制的具体方法和步骤参看5.2节。 5.4.1主控电路设计 主控电路与直接测频法中的主控电路功能完全相同,用于产生计数器的复位信号CLR′和闸门信号CNTEN,以及显示译码电路所需要的锁存允许信号LE。 主控电路可以直接应用Verilog HDL进行描述。取时钟频率为8Hz,闸门信号的作用时间为1s时,描述主控电路的Verilog代码参考如下。 module fp_ctrl (input clk, // 时钟,8Hz output reg clr_n, // 计数器清零信号 output reg cnt_en, // 闸门信号,作用时间为1s output reg le // 锁存允许信号,高电平有效 ); // 计数变量定义 reg [3:0] q; // 十进制计数逻辑描述 always @( posedge clk ) if ( q >= 4'd9 ) q <= 4'b0000; else q <= q + 1'b1; // 控制信号生成过程 always @( q ) case ( q ) 4'b0000 : begin clr_n = 0; cnt_en = 0; le = 0; end 4'b0001 : begin clr_n = 1; cnt_en = 1; le = 0; end 4'b0010 : begin clr_n = 1; cnt_en = 1; le = 0; end 4'b0011 : begin clr_n = 1; cnt_en = 1; le = 0; end 4'b0100 : begin clr_n = 1; cnt_en = 1; le = 0; end 4'b0101 : begin clr_n = 1; cnt_en = 1; le = 0; end 4'b0110 : begin clr_n = 1; cnt_en = 1; le = 0; end 4'b0111 : begin clr_n = 1; cnt_en = 1; le = 0; end 4'b1000 : begin clr_n = 1; cnt_en = 1; le = 0; end 4'b1001 : begin clr_n = 1; cnt_en = 0; le = 1; end default: begin clr_n = 1; cnt_en = 0; le = 0; end endcase endmodule 新建工程,将fp_ctrl模块经过编译与综合后封装成图形符号以便在频率计顶层设计电路中调用。 5.4.2频率测量与计算电路设计 频率测量与计算电路实现的原理电路如图554所示。当闸门信号G跳变为高电平后,必须等到被测信号FX的有效沿到来时,通过D触发器将SG置1后才能对标准信号和被测信号同时进行计数。当闸门信号G跳变为低电平后,同样需要等到被测信号FX的有效沿到来时,通过D触发器将SG置0后才停止对标准信号和被测信号的计数。在主控电路的作用下锁存计数值,然后应用乘法器和除法器计算被测信号的频率值。 图554频率测量与计算电路 应用原理图设计频率计顶层电路时,D触发器可以直接调用primitives图形符号库中的D触发器实现。若应用结构化方式描述频率计顶层电路,则根据功能直接应用Verilog描述D触发器。 module DFF_mk(g,fx,sg); input g,fx; output reg sg; // 行为描述 always @(posedge fx) sg <= g; endmodule 当闸门时间取1s,应用96MHz标准信号时,若要测量100MHz的信号,则标准计数器和测频计数器至少需要采用27位二进制计数器(因为226<108<227)实现,同时还需要为计数器添加异步复位端CLR′和计数允许控制端ENA,以便与主控电路连接。 为了与乘法器IP和除法器IP的参数相匹配,标准计数器和测频计数器均设计为28位二进制计数器。 标准计数器的Verilog描述代码参考如下。 module FScnt(FSCLK,CLR_n,ENA,FSQ); input FSCLK,CLR_n,ENA; output reg [27:0] FSQ; // 计数过程 always @(posedge FSCLK or negedge CLR_n) if ( !CLR_n ) FSQ <= 28'b0; else if ( ENA ) FSQ <= FSQ+1'b1; endmodule 测频计数器的Verilog描述代码参考如下。 module FXcnt(FXCLK,CLR_n,ENA,FXQ); input FXCLK,CLR_n,ENA; output reg [27:0] FXQ; // 计数过程 always @(posedge FXCLK or negedge CLR_n) if ( !CLR_n ) FXQ <= 28'b0; else if (ENA) FXQ <= FXQ+1'b1; endmodule 图555乘法器定制向导(1) 新建工程,分别将FScnt和FXcnt计数器模块经过编译、综合与适配后封装成图形符号以便在频率计顶层设计电路中调用。 频率计算电路中所需要的乘法器通过定制参数化乘法器IPLPM_MULT 实现,其中乘法器的输入定制为28位无符号二进制数,乘法结果定制为56位无符号二进制数。 在Quartus Prime主界面中执行Tools→IP Catalog菜单命令打开IP目录,选择Basic Functions栏下Arithmetic中的LPM_MULT,如图555所示。 双击LPM_MULT,打开乘法器IP定制向导界面,取乘法器模块名为fmult,被乘数与乘数均定制为28位无符号二进制数,如图556所示。 图556乘法器定制向导(2) 单击Next按钮,进入乘数参数设置界面。设置乘数为常数96000000(96MHz),如图557所示,其余参数保持不变。 图557乘法器定制向导(3) 连续单击Next按钮进入IP文件生成界面,如图558所示。勾选fmult.bsf,表示需要生成图形符号文件,以便在频率计顶层设计电路中调用。如果应用结构化方式描述顶层设计电路,则应勾选fmult_inst.v以生成乘法器例化模板文件。 图558乘法器定制向导(4) 单击Finish按钮完成乘法器IP定制过程。 频率计算电路中所需要的除法器通过定制参数化除法器IPLPM_DIVIDE实现。取除法器模块名为fdiv,被除数和除数分别定制为56位和28位无符号二进制数,则商数和余数分别为56位和28位无符号二进制数。 除法器的定制方法和步骤与乘法器定制相同,因此不再赘述。 将除法器fdiv输出的56位商数和28位余数应用锁存器latch84锁存后输出28位商数和28位余数。取锁存允许端口名为EN,则描述锁存器的Verilog代码参考如下。 module latch84 (en,din56,din28,dout28a,dout28b); input en; input [55:0] din56; input [27:0] din28; output reg [27:0] dout28a; output reg [27:0] dout28b; // 锁存输出过程 always @(en,din56,din28) if ( en ) begin dout28a <= din56[27:0]; dout28b <= din28; end endmodule 新建工程,将latch84模块编译与综合后封装成图形符号以便在顶层设计电路中调用。 5.4.3数值转换与显示译码电路设计 由于频率测量与计算电路输出的频率值为二进制数,因此还需要应用转换电路将二进制频率值转换为BCD码,才能进行显示译码以驱动数码管显示频率值。 将二进制数转换为BCD码从理论上可以应用整除和取余运算来实现。但是,这种方法需要多次应用除法,因而会消耗大量的FPGA内部资源。因此,需要寻求实现二进制数到BCD码转换的高效算法。 下面从原理上进行分析。 将二进制数转换为BCD码的基本原理是按照其位权展开式展开,然后将各部分相加即可得到等值的十进制数,即 (dn-1dn-2…d1d0)2=(dn-1×2n-1+dn-2×2n-2+…+d1×21+d0×20)10 位权展开式可以进一步整理为 (dn-1dn-2…d1d0)2= ((((dn-1×2+dn-2)×2+…)×2+d1)×2+d0)10 该式说明,将n位二进制数按位权展开式展开求和时,式中的2i(i=n-1,…,n-2,…,0)可以应用连续乘2运算i次实现。由于Verilog HDL中的逻辑左移操作相当于乘2运算,因此2i可以转化为左移i次实现。 由于BCD码是用二值数码表示的十进制数,有0000~1001共10个取值组合,分别表示十制数的0~9,其运算规则为逢十进一,而4位二进制数共有0000~1111共16种取值,其运算规则为逢十六进一。对于BCD码,当数码大于9时应由低位向高位产生进位; 但是对于4位二进制数,只有当数值大于15时才会产生进位。因此,在对数值进行移位前,需要进行修正,才能确保逻辑左移后得到正确的BCD码。 下面讨论具体的修正方法。 BCD码逢十进一,而10/2=5,所以左移前需要判断每4位数值是否大于或等于5。如果数值大于或等于5,就需要在移位前给相应的数值加上6/2=3,这样左移时会跳过1010~1111这6个取值组合而得到正确的BCD码。例如,移位前若数值为0110(对应十进制数6),加3得到1001,左移后数码值为10010,看作BCD码时,为十进制数12。将这种二进制数转换为BCD码的方法称为移位加3算法(Shift and Add 3 Algorithm)。 综上所述,应用移位加3算法将二进制数转换为BCD码的具体方法是: 对于n位二进制数,需要将数值左移n次。每次移位前需要先判断移入的每4位数值是否大于或等于5,大于或等于5时应给相应的数值位加3修正,然后再进行移位。继续判断直到移完n次为止。 将8位二进制数11111111转换为3位BCD码的具体转换步骤如表56所示。 表568位二进制数转换为BCD码的具体步骤 转换操作 转换缓存区8位二进制数 高4位中4位低4位高字节低字节 1 1 1 11 1 1 1 第1次左移11 1 1 11 1 1 第2次左移1 11 1 1 11 1 第3次左移1 1 11 1 1 11 加3修正1 0 1 01 1 1 11 第4次左移10 1 0 11 1 1 1 加3修正11 0 0 01 1 1 1 第5次左移1 10 0 0 11 1 1 第6次左移1 1 00 0 1 11 1 加3修正1 0 0 10 0 1 11 1 第7次左移10 0 1 00 1 1 11 加3修正10 0 1 01 0 1 01 第8次左移1 00 1 0 10 1 0 1 转换结果255BCD码 在等精度频率计的设计中,应用移位加3算法,将28位二进制除法商和余数转换为8位BCD码的Verilog代码参考如下。 module BIN28toBCD( BINdata, BCDout ); input [27:0] BINdata; // 28位二进制数输入 output wire [31:0] BCDout; // 8位十进制码输出 // 内部变量定义 reg [31:0] BCDtmp; // 32位移位缓存区 integer i; // 循环变量 // 输出定义 assign BCDout = BCDtmp; // 转换过程,移位加3算法 always @( BINdata ) begin BCDtmp = 32'b0; // 移位缓存区清零 for( i = 0; i<28 ; i = i + 1 ) begin // 移位前修正 if (BCDtmp[31:28] >= 5) BCDtmp[31:28] = BCDtmp[31:28] + 3; if (BCDtmp[27:24] >= 5) BCDtmp[27:24] = BCDtmp[27:24] + 3; if (BCDtmp[23:20] >= 5) BCDtmp[23:20] = BCDtmp[23:20] + 3; if (BCDtmp[19:16] >= 5) BCDtmp[19:16] = BCDtmp[19:16] + 3; if (BCDtmp[15:12] >= 5) BCDtmp[15:12] = BCDtmp[15:12] + 3; if (BCDtmp[11:8] >= 5) BCDtmp[11:8] = BCDtmp[11:8] + 3; if (BCDtmp[7:4] >= 5) BCDtmp[7:4] = BCDtmp[7:4] + 3; if (BCDtmp[3:0] >= 5) BCDtmp[3:0] = BCDtmp[3:0] + 3; // 逻辑左移,应用拼接操作符实现 BCDtmp[31:0] = { BCDtmp[30:0],BINdata[27-i] }; end end endmodule 为了提高频率显示的准确度,定义频率大于或等于10kHz时以8位整数的形式显示; 频率小于10kHz且大于或等于1kHz时以“4位整数+4位小数”的形式显示; 频率小于1kHz且大于或等于100Hz时以“3位整数+5位小数”的形式显示; 而频率小于100Hz时以“2位整数+6位小数”的形式显示。调用BIN28toBCD.v模块,实现数值转换与显示译码的Verilog代码参考如下。 module HEX7_8 ( input [27:0] iBIN28a,iBIN28b,// 除法商和余数输入 output wire [6:0]oSEG7,oSEG6,oSEG5,oSEG4, // 数码管驱动信号 oSEG3,oSEG2,oSEG1,oSEG0, output reg[2:0]DPoints,// 小数点驱动信号 output regOV_LED// 超量程指示信号 ); // 内部线网和变量定义 wire[31:0]BCD32a,BCD32b;// 商数BCD码,余数BCD码 reg[31:0]DispBCD;// 显示BCD码 // 数值转换 BIN28toBCD x1(iBIN28a,BCD32a);// 二进制商数转换为BCD码 BIN28toBCD x2(iBIN28b,BCD32b);// 二进制余数转换为BCD码 // 根据频率值自动切换显示格式 always@( iBIN28a ) begin if ( iBIN28a >= 100_000_000 )// 如果频率大于或等于100MHz OV_LED = 1'b1;// 超量程指示信号亮 else OV_LED = 1'b0;// 超量程指示信号灭 if ( iBIN28a >= 10000 ) begin// 如果频率大于或等于10kHz DispBCD = BCD32a[31:0];// 取8位商数 DPoint = 3'b000;// 不显示小数点 end else if ( iBIN28a >= 1000 ) begin// 如果频率大于或等于1kHz DispBCD = {BCD32a[15:0],BCD32b[31:16]}; // 取4位商数和4位余数 DPoints = 3'b001;// 显示低位小数点 end else if ( iBIN28a >= 100 ) begin// 如果频率大于或等于100Hz DispBCD = {BCD32a[11:0],BCD32b[31:12]}; // 取3位商数和5位余数 DPoints = 3'b010;// 显示中位小数点 end else begin// 否则,频率小于100Hz DispBCD = {BCD32a[7:0],BCD32b[31:8]};// 取2位商数和6位余数 DPoints = 3'b100;// 显示高位小数点 end end // 例化显示译码模块 CD4511s U7( .le(1'b0), .bcd(DispBCD[31:28]), .seg7(oSEG7)); CD4511s U6( .le(1'b0), .bcd(DispBCD[27:24]), .seg7(oSEG6)); CD4511s U5( .le(1'b0), .bcd(DispBCD[23:20]), .seg7(oSEG5)); CD4511s U4( .le(1'b0), .bcd(DispBCD[19:16]), .seg7(oSEG4)); CD4511s U3( .le(1'b0), .bcd(DispBCD[15:12]), .seg7(oSEG3)); CD4511s U2( .le(1'b0), .bcd(DispBCD[11:8]),.seg7(oSEG2)); CD4511s U1( .le(1'b0), .bcd(DispBCD[7:4]),.seg7(oSEG1)); CD4511s U0( .le(1'b0), .bcd(DispBCD[3:0]),.seg7(oSEG0)); endmodule 新建工程,将HEX7_8.v模块经过编译与综合后封装成原理图符号以便在频率计顶层设计电路中调用。 5.4.4顶层电路设计 等精度频率计的顶层设计电路如图559所示,其中锁相环输出96MHz(c0)和2kHz(c1) 的信号,分别作为计数器标准频率信号FSCLK和8Hz分频基准信号。当待测信号FX1Hz_100MHz的频率超过100MHz时,超量程指示灯OV_LED 亮,指示被测信号的频率超量程。 图559等精度频率计顶层设计电路 需要说明的是,顶层设计电路中的分频器模块fp2kHz_8Hz用于将锁相环输出的2kHz方波分频为8Hz,为主控电路(fp_ctrl模块)提供时钟。描述分频器的Verilog代码参考如下。 module fp2kHz_8Hz(clk,fp_out); input clk; output reg fp_out; // 参数定义 localparam N = 250; // 计数变量定义 reg [7:0] cnt; // 分频过程 always @ (posedge clk) if ( cnt