目录
1.1.1 vivado安装System Generator
本章节首先介绍FPGA进行DSP开发所需要的软件环境,及其安装方式,接着介绍完整的FPGA数字信号处理开发流程
DSP学习教程参考B站视频
1. System Generator安装
System Generator是Xilinx公司进行数字信号处理开发的一种设计工具,它通过将Xilinx开发的一些模块嵌入到Simulink的库中,可以在Simulink中进行定点仿真,可以设置定点信号的类型,这样就可以比较定点仿真与浮点仿真的区别。并且可以生成HDL文件,或者网表,可以在ISE中进行调用。或者直接生成比特流下载文件。能够加快DSP系统的开发进度。
参考:
(一)初识System Generator(安装+使用) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/330926863
1.1 system generator的安装
注意:System Generator版本必须与vivado版本保持一致,同时你使用的matlab版本需要兼容安装的System Generator版本。
版本兼容信息需要在安装MATLAB或者Vivado时进行相关的查询,具体可以在ug973(13/81页,每个版本不同)官方文档中查询
我所处的开发环境:
- Win10
- matlabR2021b
- vivado2018.3
因此我需要首先查阅vivado18.03的用户手册
进入用户手册后,查阅该版本对于第三方软件兼容性的说明
从上方的图可以看到MATLAB版本可以兼容R2017a,R2017b和R2018a,不过更高版本的当然也可以了,我用的就是R2021b,旧版本的不太清楚在使用的时候会不会出什么问题,可以自己尝试.当然要兼容ug973这个文件里没有的版本还需要对一个文件做下修改,不然System Generator会不支持自己版本的MATLAB,具体修改方式见1.1.2章节
1.1.1 vivado安装System Generator
System Generator是在安装VIVADO时就可选的,如果安装VIVADO的时候没安,就自己再补安下,可以看以下的操作步骤,安装过程参考
(一)初识System Generator(安装+使用) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/330926863
我的vivado2018.3之前是没有安装该套件的,因此我需要安装System Generator for DSP。
安装好之后程序会自动寻找本机中的matlab
由于matlab的版本与vivado不一致,因此无法找到对应版本的matlab,接下来我将会修改配置文件来使得System Generator添加2021b版本的matlab
1.1.2 System Generator配置
首先查看matlab的版本信息
matlab软件版本为2021b ,在matlab命令行输入下面的命令即可获得安装路径:
接着打开vivado的安装路径,找到ml_supported.xml文件,然后编辑,往里面添加你自己MATLAB版本的信息
添加完后,保存,然后打开System Generator 2018.3 MATLAB Configurator,在开始菜单中的Xilinx Design Tools下可以找到。 添加matlab安装路径即可
点击apply即可成功安装~
1.3 启动
- 首先在开始菜单选择System Generator,双击运行,该程序自动打开matlab
- 在matlab中启动Sumulink
- 选择blank model建立新模型
- 选择Simulink库中的Xilinx Blockset
注意:如果库中没找到这个Xilinx Blockset的话说明你的vivado与matlab不匹配,或者System Generator没有成功安装。
2. FPGA-DSP开发流程
2.1 FPGA-DSP 开发流程介绍
第2期 - 开发流程 - 基于FPGA的数字信号处理系统开发笔记_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1SK4y1s7nS/?spm_id_from=333.999.0.0&vd_source=71acea6682c8121539b919e1e8ca93ef基于Matlab的完整FPGA-DSP开发流程如下:
注意:ILA回传给matlab的数据,每次最大回传深度为2^17,超过这一最大值后,ILA无法一次性传回所有数据。同时ILA是使用的自身FPGA资源,因此当ILA消耗过多资源时可能会使得FPGA时序或运行速度无法满足要求。
上面的流程图可以理解为下面红色注释
一般情况下,Simulink的设计与vivado仿真结果一致
2.2 FPGA-DSP 实际开发流程
目标:首先使用matlab进行预设计,设计出预期想要达到的结果,接着使用Simulink搭建,来实现我们的预设计。
1. 软件启动
首先启动vivado软件,再通过system generator来启动matlab
正确启动后的matlab命令行内显示如下字样
在父文件夹(DSP_learn)中创建三个文件夹,分别保存我们的不同类型文件
2. matlab编写
- .m文件脚本编写
%% DSP 开发过程学习
% 参考教程 https://www.bilibili.com/video/BV1SK4y1s7nS/?p=2&spm_id_from=pageDriver&vd_source=71acea6682c8121539b919e1e8ca93ef
%----------------------------------------------------------------------------------------------------------------------------
clc;clear all;close all;
%% system parameters
N = 1024;% samples
Fs = 10000; % sample rate kHz
Ts = 1/Fs;
%% Input
A =1;
t = (0:1024-1)*Ts;
f = 50;
n = Fs/f;%一个周期内的样本点数
x = A*sin(2*pi*f*t);
% figure
figure(1)
plot(t,x);
hold on
%% Multiply,add,delay
C = 2;
D = n/2;%延迟半个时钟周期的样本点
y_mul = zeros(1,N);
y_delay = zeros(1,N);
y_add = zeros(1,N);
y_out = zeros(1,N);
% y_0 = C*x;这种方式在FPGA中不适用,FPGA不是矩阵运算,而是按照时钟信号进行循环运算的
for i = 1:N
%乘法
y_mul(i) = C*x(i); %在FPGA中,一次CLK信号完成一次乘法操作,因此我们在matlab编写的时候也需要使用循环乘积的形式,即for循环
%延迟,当i大于延迟条件D时,可以开始延迟
if(i>D)
y_delay(i) = y_mul(i-D);
end
y_add = y_delay + y_mul;
end
y_out = y_add;
figure(1)
plot(t,y_out);
legend('input signal','output signal')
输出预设计图像:
半个周期后的sin函数由于图像时延了半个周期并相互叠加,因此波峰波谷相互抵消。
3. Simulink仿真
参考视频教程17:00
注意:在接好连线后,我们需要显示端口数据类型(ports data types),参考mathwork官网教程(与视频中的修改方式不同,原因是matlab的版本不一致)
牢记:把仿真变量放在matlab中,Simulink的构建只是调用matlab工作区中的变量
-
Simulink输入信号
我们需要将matlab工作区的参数作为输入信号传递给simulink,因此我们需首先在.m文件中添加我们需要传递的输入信号参数,该参数应该包含了输入信号x及其离散的时间样本点,(第一列为时间,第二列为信号值)添加的代码如下:
%% Simulink 输入信号变量
x_in(:,1) = 1:N;%第一列为时间序列
x_in(:,2) = x;%第二列为输入信号
Simulink中设置如下:
我们给这个模块连接一个示波器,运行1024个样本点,检查是否和我们matlab仿真的输入信号x一致
-
乘法器
matlab代码 | Simulink实现 |
![]() | ![]() |
-
时延器
matlab代码 | Simulink实现 |
![]() | ![]() |
-
累加器
matlab代码 | Simulink实现 | Simulink实现 |
![]() | ![]() | ![]() |
-
输出示波器设置
-
完整的Simulink设计
注意每一个连线之间的数据类型,matlab的双精度浮点输入给FPGA时,通过input gateway转换成定点数,FPGA输出给matlab同理。参考我的这篇文章(97条消息) 【FPGA-DSP】第一期:DSP基础_fpga中的dsp模块_༜黎明之光༜的博客-CSDN博客https://blog.csdn.net/weixin_44810982/article/details/129748023但是,值得注意的是输入input getway的数据类型是fix_16_14,然而输出output getway是fix_33_28,两者位宽并不一致,因此我们需要对输出进行截位操作来让位宽保持一致。添加了截位模块(Convert)后的设计如下
-
仿真
仿真点数(停止时间)仍然为1024个点,仿真结果如下:
matlab仿真图像 | 截位前的Simulink图像 | 截位后的Simulink图像 |
| ![]() | ![]() |
4. Vivado
4.1 Simulink设计导出为Vivado工程
将第三章中的设计输出,并在vivado中查看结果
双击图标
注意:如果导出不成功的话可能是因为Vivado没有导入许可证,我在生成vivado文件的时候就遇到了这问题 。
4.2 Vivado仿真测试
4.2.1 导入vicado工程文件
4.2.2 综合
4.2.3 仿真
注意:我们使用system generator时,在matlab simulink中已经根据我们的输入输出生成了testbench文件,因此我们直接运行就好
因此直接运行行为仿真即可,仿真结果如下:
易知,这与matlab的Simulink中的结果一致,但当我们将vivado生成的bit流文件下载到开发板的时候往往容易出现问题。下面就简要讲一下通过ROM实现vivado文件下载到FPGA开发板。
5. 基于ROM的Simulink输入方式(便于下载)
5.1 Simulink设计
我们需要将Simulink的输入(From Workspace)修改为通过ROM的方式输入,这样所有的数据都以.coe文件的形式存在ROM的IP核中。Simulink中修改方式如下:
注意:示波器(Scope)的输入信号必须通过input/output getway,不能直接与FPGA内部接线。因为这里设计数据的转换,不能直接连接。
新添加的模块解释如下:
ROM | Counter |
![]() | ![]() |
ROM存储matlab工作区中输入信号x的1024个值,Counter从0~1023循环计数作为地址信号来访问ROM对应地址中变量x的值。因此当Counter从0计数到1023意味着ROM输出了一次完整的x信号,包含1024个数据点。
示波器的输出结果如下:
5.2 Vivado仿真
5.2.1 导入vivado工程
按照刚才的方式在Simulink中生成vivado工程文件,再通过vivado打开文件,同理。
5.2.2 添加ILA ip核
![]() | ![]() |
注意:我们使用ILA ip核只需要对输入输出数据进行分析,输入信号深度为1024,同时由于FPGA的输入输出均为fix_16_14(16bit)因此第二页probe0/1均为16bit位宽
5.2.3 ip核例化
在顶层模块中添加我们的ip核
同时将输入信号修改为线网型变量(wire)
5.2.4 RTL分析
更进一步的,System Generator生成的IP核如下图所示
5.2.5 管脚约束
我们只有一个时钟信号作为输入, System Generator IP核中生成的波形不作为输出信号,仅作为FPGA内部ILA逻辑分析仪的输入信号,因此我们需要添加的管脚约束仅有CLK一个
添加管脚约束如下:
CLK对印的管脚参考自己的FPGA开发板说明书
5.3 下载
生成bit流文件烧写进我们的FPGA开发板
5.3.1 开发板连接
5.3.2 ILA 验证
下载好bit流文件后,vivado会自动打开ILA窗口
注意:自从vivado2017.4以后都取消了ila波形仿真图的real setting,因此查看定点数时需要通过修改matlab代码或者使用modelsim联调。
到此为止,说明我们的理论设计全链路全部完成。但是如果我们想对FPGA进行进一步分析,如FPGA内部数据导出,详见下一章
6. FPGA数据分析
我们对ILA 的数据进行回传分析,导出数据方法如下:
- 首先在ILA窗口中将波形的数据类型修改为有符号的十进制
- 接着再导出数据
导出之后,该csv文件会出现在vivado的工程文件夹中
然后复制到matlab工作文件夹中
对csv文件进行读取,读取代码如下:
%% ILA csv文件matlab读取
% 参考教程 https://www.bilibili.com/video/BV1SK4y1s7nS/?p=2&spm_id_from=pageDriver&vd_source=71acea6682c8121539b919e1e8ca93ef
%----------------------------------------------------------------------------------------------------------------------------
%% 所需输入参数
N = 1024;%深度
m = 16;%位宽 fix_16_14
%% 导入数据(ILA 数据需设置为有符号十进制)
row = 1;
col_i = 3;%第四列
col_o = 4;%第五列
input_0 = csvread('iladata.csv',row,col_i,[row,col_i,row+N-1,col_i]);
output_0 = csvread('iladata.csv',row,col_o,[row,col_o,row+N-1,col_o]);
% 导出了16位的数据,其中第1位为符号位,整数1位,14个小数位
%% 数据处理
%提取符号位,并将其去掉
input_1 = abs(input_0);
output_1 = abs(output_0);
signed_i = input_0./input_1;
signed_i(find(isnan(signed_i)==1))=0;%去除掉符号位后,变成15位二进制数
signed_o = output_0./output_1;
signed_o(find(isnan(signed_o)==1))=0;%去除掉符号位后,变成15位二进制数
% 十进制转化为2进制
input_1_b = dec2bin(input_1);
output_1_b = dec2bin(output_1);
input_int = input_1_b(:,1);
input_dec = input_1_b(:,2:15);%第一位为整数,后2~15位均为小数
output_int = output_1_b(:,1);
output_dec = output_1_b(:,2:15);
input_I = bin2dec(input_int); %整数位
input_D = zeros(N,1); %小数位
%将小数位2进制转换为十进制小数
for i =1:N
for j = 1:14
input_D(i) = input_D(i) + 2^(-j)*str2num(input_dec(i,j));
end
end
% 输入信号plot
input = signed_i.*(input_I+input_D);
figure(1)
subplot (2,1,1)
plot(input );
%% 输出信号
output_I = bin2dec(output_int); %整数位
output_D = zeros(N,1); %小数位
%将小数位2进制转换为十进制小数
for i =1:N
for j = 1:14
output_D(i) = output_D(i) + 2^(-j)*str2num(output_dec(i,j));
end
end
% 输出信号plot
output = signed_o.*(output_I+output_D);
figure(1)
subplot (2,1,2)
plot(output );
输出结果如下:
可知,数据导出的图像与ILA图像保持一致,但与只使用matlab仿真存在相位差异,这是正常现象,因为FPGA存在时延等非理想因素,与matlab仿真会存在误差,但是波形一致即可。