目录
1. System Generator安装
1.1 system generator的安装
1.1.1 vivado安装System Generator
1.1.2 System Generator配置
1.3 启动
2. FPGA-DSP开发流程
2.1 FPGA-DSP 开发流程介绍
2.2 FPGA-DSP 实际开发流程
1. 软件启动
2. matlab编写
3. Simulink仿真
Simulink输入信号
乘法器
时延器
累加器
输出示波器设置
完整的Simulink设计
仿真
4. Vivado
4.1 Simulink设计导出为Vivado工程
4.2 Vivado仿真测试
4.2.1 导入vicado工程文件
编辑
4.2.2 综合
4.2.3 仿真
5. 基于ROM的Simulink输入方式(便于下载)
5.1 Simulink设计
5.2 Vivado仿真
5.2.1 导入vivado工程
5.2.2 添加ILA ip核
5.2.3 ip核例化
5.2.4 RTL分析
5.2.5 管脚约束
5.3 下载
5.3.1 开发板连接
5.3.2 ILA 验证
6. FPGA数据分析
本章节首先介绍FPGA进行DSP开发所需要的软件环境,及其安装方式,接着介绍完整的FPGA数字信号处理开发流程
DSP学习教程参考B站视频
System Generator是Xilinx公司进行数字信号处理开发的一种设计工具,它通过将Xilinx开发的一些模块嵌入到Simulink的库中,可以在Simulink中进行定点仿真,可以设置定点信号的类型,这样就可以比较定点仿真与浮点仿真的区别。并且可以生成HDL文件,或者网表,可以在ISE中进行调用。或者直接生成比特流下载文件。能够加快DSP系统的开发进度。
参考:
(112条消息) System Generator从入门到放弃(一)-安装与使用_system gengerator_碎碎思的博客-CSDN博客https://blog.csdn.net/Pieces_thinking/article/details/83656686
(一)初识System Generator(安装+使用) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/330926863
注意:System Generator版本必须与vivado版本保持一致,同时你使用的matlab版本需要兼容安装的System Generator版本。
版本兼容信息需要在安装MATLAB或者Vivado时进行相关的查询,具体可以在ug973(13/81页,每个版本不同)官方文档中查询
我所处的开发环境:
因此我需要首先查阅vivado18.03的用户手册
进入用户手册后,查阅该版本对于第三方软件兼容性的说明
从上方的图可以看到MATLAB版本可以兼容R2017a,R2017b和R2018a,不过更高版本的当然也可以了,我用的就是R2021b,旧版本的不太清楚在使用的时候会不会出什么问题,可以自己尝试.当然要兼容ug973这个文件里没有的版本还需要对一个文件做下修改,不然System Generator会不支持自己版本的MATLAB,具体修改方式见1.1.2章节
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
首先查看matlab的版本信息
matlab软件版本为2021b ,在matlab命令行输入下面的命令即可获得安装路径:
接着打开vivado的安装路径,找到ml_supported.xml文件,然后编辑,往里面添加你自己MATLAB版本的信息
添加完后,保存,然后打开System Generator 2018.3 MATLAB Configurator,在开始菜单中的Xilinx Design Tools下可以找到。 添加matlab安装路径即可
点击apply即可成功安装~
注意:如果库中没找到这个Xilinx Blockset的话说明你的vivado与matlab不匹配,或者System Generator没有成功安装。
第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仿真结果一致
目标:首先使用matlab进行预设计,设计出预期想要达到的结果,接着使用Simulink搭建,来实现我们的预设计。
首先启动vivado软件,再通过system generator来启动matlab
正确启动后的matlab命令行内显示如下字样
在父文件夹(DSP_learn)中创建三个文件夹,分别保存我们的不同类型文件
%% 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函数由于图像时延了半个周期并相互叠加,因此波峰波谷相互抵消。
参考视频教程17:00
注意:在接好连线后,我们需要显示端口数据类型(ports data types),参考mathwork官网教程(与视频中的修改方式不同,原因是matlab的版本不一致)
牢记:把仿真变量放在matlab中,Simulink的构建只是调用matlab工作区中的变量
我们需要将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实现 |
注意每一个连线之间的数据类型,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图像 |
将第三章中的设计输出,并在vivado中查看结果
双击图标
注意:如果导出不成功的话可能是因为Vivado没有导入许可证,我在生成vivado文件的时候就遇到了这问题 。
参考解决方法:(98条消息) (一) vivado2018.3安装注册指南_vivado注册 2035_jacktwan的博客-CSDN博客https://blog.csdn.net/weixin_42668358/article/details/125512721
注意:我们使用system generator时,在matlab simulink中已经根据我们的输入输出生成了testbench文件,因此我们直接运行就好
因此直接运行行为仿真即可,仿真结果如下:
易知,这与matlab的Simulink中的结果一致,但当我们将vivado生成的bit流文件下载到开发板的时候往往容易出现问题。下面就简要讲一下通过ROM实现vivado文件下载到FPGA开发板。
我们需要将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个数据点。
示波器的输出结果如下:
按照刚才的方式在Simulink中生成vivado工程文件,再通过vivado打开文件,同理。
注意:我们使用ILA ip核只需要对输入输出数据进行分析,输入信号深度为1024,同时由于FPGA的输入输出均为fix_16_14(16bit)因此第二页probe0/1均为16bit位宽
在顶层模块中添加我们的ip核
同时将输入信号修改为线网型变量(wire)
更进一步的,System Generator生成的IP核如下图所示
我们只有一个时钟信号作为输入, System Generator IP核中生成的波形不作为输出信号,仅作为FPGA内部ILA逻辑分析仪的输入信号,因此我们需要添加的管脚约束仅有CLK一个
添加管脚约束如下:
生成bit流文件烧写进我们的FPGA开发板
下载好bit流文件后,vivado会自动打开ILA窗口
注意:自从vivado2017.4以后都取消了ila波形仿真图的real setting,因此查看定点数时需要通过修改matlab代码或者使用modelsim联调。
到此为止,说明我们的理论设计全链路全部完成。但是如果我们想对FPGA进行进一步分析,如FPGA内部数据导出,详见下一章
我们对ILA 的数据进行回传分析,导出数据方法如下:
导出之后,该csv文件会出现在vivado的工程文件夹中
然后复制到matlab工作文件夹中
%% 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仿真会存在误差,但是波形一致即可。