万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)

Vivado for Linux环境配置(基于VMWare+Ubuntu22)与 DDS+FIR滤波器实战

目录

  • Ubuntu22部署与虚拟机必要配置
    • Linux版本比较
    • VMWare共享文件夹配置(※)
    • VMWare网卡配置(可选)
  • Vivado for Linux安装
  • 实验概述
    • 实验原理
      • 直接数字频率合成(Direct Digital Synthesis,DDS)
      • 有限长单位冲激响应(Finite Impulse Response, FIR)滤波器
      • Xilinx内置逻辑分析仪(Integrated Logic Analyzer, ILA)
      • 锁相环时钟管理器(Phase-Locked-Loop, PLL)
    • 实验流程(框图)
    • 实验细节
      • Matlab滤波器设计工具(Filter Designer APP)
      • Matlab任意内容coe生成脚本
      • 初始化Vivado工程
      • Clocking Wizard IP Core 6.0
      • FIR Compiler IP Core 7.2
      • Binary Counter IP Core 12.0
      • Distributed Memory Generator(DMG) IP Core 8.0
      • ILA IP Core 6.2
      • Block Design
      • Constraint and configuration
      • Hardware Manager Debugging
      • 实验现象
  • 过程中遇到的问题、解决方法和启发
    • 适当地设置测试点
    • 从错误的波形中获得启发
    • 避免重复考虑问题
  • 总结

Ubuntu22部署与虚拟机必要配置

Linux版本比较

目前发行的主要版本包括RHEL、Debian及其派生版本,这里选用Ubuntu22 LTS(长期支持版本)有以下几个原因:

  1. Ubuntu具有所有Linux版本最好的图形界面支持
  2. 有成熟的公司进行维护,而非社区运营,并已有大量的优质学习资源
  3. 对非商用目的免费
  4. Xilinx官方的偏好

当然Ubuntu也有其劣势,如性能利用率较低、内核稳定性较差等,但相比于其优势,这些可能存在的缺点对于日常开发工作的影响可以忽略不计。

Ubuntu官方网站的账号注册、ISO镜像下载和VMWare安装Ubuntu系统在此不过多赘述,网上已有许多文档提供解答,例如以下博客即可供参考(已包括VMWare Tools安装):

VMware&Ubuntu安装

切记!!!关注Xilinx官方对Vivado对Linux版本的要求,血的教训!!!

VMWare共享文件夹配置(※)

  1. 在主机的资源管理器下创建待共享的文件夹
  2. 在主机的资源管理器中配置
  3. 在VMWare中安装VMWare Tools,利用HGFS挂载共享文件夹

详细步骤可参考以下博客:
共享文件夹配置

VMWare虚拟网卡配置(可选)

主要推荐使用NAT模式,桥接模式基于我本机的Wifi网卡还没成功过。
具体操作可参考如下博客:
https://blog.csdn.net/xuqingda/article/details/124033331

Vivado for Linux安装

参考此官方文档:
Vivado安装说明

实验概述

实验原理

直接数字频率合成(Direct Digital Synthesis,DDS)

原理是利用一个包含数字波形信息的存储块(可以是RAM/ROM),利用一定的逻辑读取该存储块的数据并输出,经过DA转换后得到模拟波形。

相比于其他波形生成方式,DDS的优缺点分析:
  • 优点:

    1. 精度高:DDS合成器能够产生非常准确的输出信号,其频率和相位精度很高,适用于需要精确控制的应用,如通信、测量和精密仪器。

    2. 频率可编程:DDS可以轻松实现频率的可编程,只需改变相应的寄存器值即可。这使得DDS非常适合需要频率切换的应用,如无线电通信、雷达和频谱分析仪器。

    3. 稳定性好:DDS合成器通常具有稳定的频率和相位,不受温度和环境变化的影响。这对需要长时间运行的应用非常有利。

    4. 低相位噪声:DDS合成器通常具有较低的相位噪声,适用于需要低噪声的应用,如通信和雷达系统。

  • 缺点:

    1. 相位跳变:DDS在频率切换时可能会出现相位跳变,这可能会引入干扰,因此在某些应用中需要特殊的处理来减小相位跳变的影响。

    2. 硬件成本:较高精度和更高频率的DDS合成器通常需要复杂的硬件和高速时钟源,这可能会增加成本和功耗。

    3. 动态范围:DDS的动态范围可能受到限制,尤其是在高频率下。对于需要大动态范围的应用,可能需要额外的信号处理步骤。

参数:
  • 位深度:每个采样点的位深,单位bit,决定了DDS的量化精度
  • 存储深度:存储单元总共能够容纳的采样点点数,无量纲数
  • 频率分辨率:DDS能够调整的最小的频率增量,单位Hz
频率字计算公式:

频率字 = (输出频率 / 参考时钟频率) * 2N,其中N为存储深度的位数,即N位对应2N个采样点数。


有限长单位冲激响应(Finite Impulse Response, FIR)滤波器

详情请见数字信号处理课本或以下知乎链接:
FIR滤波器初步


Xilinx内置逻辑分析仪(Integrated Logic Analyzer, ILA)

为方便开发者观察工程输出的信号以及工程内部的信号细节,Xilinx的Vivado套件中提供了ILA的IP核,相当于一个硬件逻辑分析仪,是基于物理电路和实时系统的,省去了额外购买逻辑分析仪或者混合信号示波器的麻烦,代价是增加了逻辑和存储资源的开销。

具体文档请见Xilinx官方:
Xilinx ILA说明


锁相环时钟管理器(Phase-Locked-Loop, PLL)

用于时钟管理的PLL由鉴相器、环路滤波器、压控振荡器和两个分频器组成,通过分频器使得输出频率与参考频率的按比例锁定,达到倍频/分频的目的,再Vivado中没有独立的PLL IP核心,而是集成在Clocking Wizard里的PLL方式选项。

万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第1张图片


实验流程

万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第2张图片

实验细节

Matlab滤波器设计工具(Filter Designer APP)

在工具栏的APP选项卡中打开Filter Builder(滤波器设计工具)

  1. 选择滤波器类型,输入参数。例程中我选择低通滤波器,截止频率10MHz
    万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第3张图片

  2. 输入阶数、配置量化精度、定点转化等

  3. 选择生成文件->Xilinx COE文件
    万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第4张图片

  4. 经由共享文件夹导入虚拟机工程

注意!!以上的每一部分都需要跟后面Vivado中FIR IP核的设置完全对应!!

Matlab COE查找表生成脚本

代码如下:可生成包含任意数值序列的COE文件,注释都已经较为详细

N=2^8; % 数据位数
s_p=0:255;
Mem_depth = 256; % 存储深度
Mem_width = 8; 
sin_data=sin(2*pi*s_p/N);

for i=1:length(sin_data)
    if(sin_data(i)>0)
        sin_data(i)=1;
    else
        sin_data(i)=0;
    end
end

% plot(sin_data);
% hold on;
% plot(sin_data);

% Signed Dec to Bin
fix_p_sin_data=fix(sin_data*((N / 2) -1));
for i=1:N
    if fix_p_sin_data(i)<0
        fix_p_sin_data(i)=N+fix_p_sin_data(i);    
    else
        fix_p_sin_data(i)=fix_p_sin_data(i);
    end
end

fid=fopen('sp_ram_256x8.mif','w+');
fprintf(fid,'WIDTH=%d;\n', Mem_width);
fprintf(fid,'DEPTH=%d;\n',Mem_depth);
fprintf(fid,'ADDRESS_RADIX=UNS;\n');
fprintf(fid,'DATA_RADIX=UNS;\n');
fprintf(fid,'CONTENT BEGIN \n');
for i=1:N
    fprintf(fid,'%d:%d; \n',i-1,fix_p_sin_data(i));
end
fprintf(fid,'END; \n');
fclose(fid);
 
fid=fopen('sp_ram_256x8_sqare.coe','w+');
fprintf(fid,'memory_initialization_radix=10;\n'); 
fprintf(fid,'memory_initialization_vector= \n'); 
for i=1:N
    if i == N
        fprintf(fid,'%d; ',fix_p_sin_data(i)); 
    else
        fprintf(fid,'%d, ',fix_p_sin_data(i));
    end
end

最后将会得到一个sp_ram_256x8_sqare.coe文件,同样将其拷贝至Vivado工程目录下以备调用。


以下操作都是基于Vivado平台,需要读者自行建立和配置Vivado工程。本例程是基于Xilinx ZYNQ XC7Z020-CLG400芯片以及Alinx 7020板卡搭建的工程,读者请自行按手册和自己的产品文档建立对应兼容的工程。

Block Design

建立工程完毕后打开并新建一个Block Design文件,并点击图纸上方的加号在设计中添加IP核(不要用IP Catalog,那个方式是IP核综合后再进行主程序HDL设计)
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第5张图片

Clocking Wizard 6.0

主要的参数有:实现方式、参考时钟输入频率、输出频率。

实验引入PLL的目的是为了更好地贴近实际应用情况,掌握时钟树的管理和配置,同时适当加强例程的深度和复杂性。

配置按如下步骤:
实现方式采用PLL,即锁相环(该FPGA内置4个高性能锁相环)。输入参考时钟为板载50M晶振。
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第6张图片
输出时钟选择1路100MHz,并点击确定。
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第7张图片

FIR Compiler 7.2

主要的参数有:输入输出位深、参考时钟频率、系数矩阵数据。
在此将滤波器系数源选择COE File,并导入Filter Builder生成的COE文件。
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第8张图片
设置同步时钟的参数,这里使用Clocking Wizard输出的100MHz时钟源。
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第9张图片
设置系数以及输入、输出数据的类型(模式)和位深,输入需与Distributed Memory Generator的输出严格对映。
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第10张图片

Binary Counter 12.0

主要的参数有:实现方式、位数、单位时钟周期增量、计数方向。
分别设置上述三个参数即可,实现原理可以选择用逻辑单元或者DSP单元,性能差别不大,主要看资源占用率。计数位数需要跟DMG的地址位数一致,由于本次操作为遍历存储块,即每周期读取1次,故增量设置为1,方向为自增。

生成的波形频率计算为:256/100M=2.56MHz

万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第11张图片

Distributed Memory Generator 8.0 (DMG 8.0)

在这里需要补充说明的一点是有关DMG和BMG(Block Memory Generator):
块存储器生成器(BRAM):
BRAM是Xilinx FPGA中的一种内存类型,它被组织成固定大小的块。BMG允许创建根据设计要求定制的BRAM结构。可以配置BRAM生成器以创建单口、双口或真双口内存,具有不同的数据宽度和深度,通常用于需要高速随机访问内存的任务。
分布式存储器生成器(DRAM):
DRAM是一种分布在FPGA结构中而不是组织成固定大小块的内存类型。DMG允许创建基于FPGA结构中的查找表(LUT)的自定义分布式内存结构。与BRAM相比,分布式内存结构在内存大小和组织方面更加灵活,通常用于查找表和小型缓冲内存等功能。

由此可见本实验选用DRAM或者BRAM均可,由于性能开销不大,配置DMG相对较为简单,因此本例程以DMG为例。
主要的参数有:存储单元类型、数据位深和长度、数据源、寄存器加载。
本例中实现的是256个8位数据的ROM,采用COE文件导入,输入输出均寄存(优化时序性能)。

参数需要与MATLAB查找表生成脚本一致

万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第12张图片
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第13张图片
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第14张图片

ILA 6.2

主要的参数有:通道数、存储深度、各通道位深。
各参数与被测信号对应即可,存储深度选4096足够。
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第15张图片
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第16张图片
最终连接完成的模块设计如下图所示:
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第17张图片


为了便于入门的理解且考虑到该项目的规模较小,本次设计采用Block Design的模式,以后的更新会在文末附上Verilog HDL的代码。由于不包含用户逻辑,所以这次敲Verilog主要是练习例化和路由。

Constraint and configuration

对Block Design进行综合(Synthesis),点击Run Synthesis
在已综合工程中打开(Open Synthesized Design)约束向导和I/O Ports(管脚约束)

在约束向导中输入50MHz板载时钟后直接跳至结尾:
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第18张图片

在I/O Ports中按下图设计:
复位端口按手册配置至PL KEY1(高有效),查看板卡手册得知端口是上拉3.5V,因此是按下取消复位,使能程序;反之松开是停止程序。
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第19张图片

万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第20张图片
最后将会生成.xdc约束文件用作实现时的约束,在Source的Constraints的文件夹下打开即可查看和修改。
所有内容添加完成后即可开始Implementation(实现)。
依次点击左侧流程栏中的Run Implementation, Generate Bitstream, Open Hardware Manager, 进入下一步。此时系统的管脚、时钟分配已经完成,并且已经准备好用于写入硬件的比特流。

Hardware Manager Debugging

首先确认硬件板卡已连接至虚拟机(在VMWare顶栏的虚拟机 -> 可移动设备中查看板卡的连接状态(连接主机/连接虚拟机))

选择Open target -> Auto Connect
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第21张图片
同样在项目顶部的绿色栏或左侧流程栏中选择Program device,若是已经本地经过综合实现的工程,默认已经选好比特流文件和Debug文件,直接点击Program即可。

实验现象

点击Waveform - hw_ila_1菜单栏的加号(Add Probe),全选所有信号。
部分信号需参考如下设定:

  • 除m_axis_data_tvalid信号,所有信号进行如下设置(模拟显示)
    万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第22张图片
  • blk_mem_gen_0_douta需要点击上图中出现的Analog Settings, 勾选Interpolation style中的Hold选项。

按下PL KEY1并点击运行图标(Run trigger for this ILA core),即可得到如下结果,大功告成。
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第23张图片
由上至下分别为数据有效标志位、DDS生成信号、计数信号(DDS地址/相位信号)、FIR滤波后信号。


过程中遇到的问题、解决方法和启发

这是例程构建早期的一次仿真,观察BMG的输出,ROM中加载的同样是方波,但在此看到三角波的原因是ILA模拟显示设置不正确,应在Analog Settings中调整为hold(保持)模式,这样在时钟前进时收到同样的信号会被解释成保持同样电平而不是离散点之间的连接。
万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第24张图片
这是例程构建中期的一次仿真,由滤波后的图像可大致反推FIR接收到的应该是一系列脉冲信号,但BMG输出的是一个很明确的方波信号(当然有些竞争冒险的现象)。

万字长文解析DDS+FIR滤波器FPGA实战(基于VMWare+Ubuntu22+Vivado+Zynq7000@AX7020)_第25张图片
当时真是百思不得其解,之后发现可能是BMG的问题,遂换成DMG则试验成功,但具体原理仍不太清楚。这个问题大概花了我半天的时间调试BMG的各种参数,但仍然不起作用。最后干脆换了个更简单的实现方式,即DMG,直接用查找表和逻辑实现,结构更简单,一般而言错误的概率更低。
当然学到最后仍应该思考这个问题,但在实验的过程中应该首先以功能和结果为目标,花过多时间在自己认知意外的问题上很容易陷入困境导致实验难以继续进展。

总结

本次实验中完成了DDS和FIR的FPGA实现,较为简单的原理在实现的过程中遇到了些问题,这也提醒了我们实践的重要性,有些在理论上并不关心的东西反而是工程中最终要的环节(比如浮点转定点、位数和深度匹配等等)。也许我们知道DSP和计算机原理的理论,但单纯记忆课本并不会理解并真正注意到它;实验同时也开拓了我的思路,并且告诉我解决问题的方法都不是一成不变的。
当然结尾也遗留下来了一些问题,我相信每个疑问和解答都是下一次开始实验的动力和目标。
希望本文能帮助到初学FPGA或者初次接触Xilinx套件的同学们,上手难度适中又能有所收获。希望各位看官老爷们点赞收藏关注一键三连,你们的支持是我创作和更新博客的最大动力!

你可能感兴趣的:(Zynq7000,fpga开发,信号处理)