概述
二、基于Simulink产生HDL代码
1、功能描述
在这个教程中,首先给出一个基于MATLAB的脉冲检测算法,该算法使用一个匹配滤波器从接收信号中检测一个已知的波形,并且获取波形的峰值。该算法普遍应用于雷达或者无线通信系统中。
2、MATLAB 标准的匹配滤波算法
% Setup
clear; clc; close all;
% Create pulse to detect
rng('default'); % rng('default') 将 rand、randi 和 randn 使用的随机数生成器的设置重置为其默认值。这样,会生成相同的随机数,就好像您重新启动了 MATLAB。默认设置是种子为 0 的梅森旋转生成器。
PulseLen = 64;
theta = rand(PulseLen,1); % X = rand 返回一个在区间 (0,1) 内均匀分布的随机数
pulse = exp(1i*2*pi*theta); % Y = exp(X) 为数组 X 中的每个元素返回指数 ex。
% Insert pulse to Tx signal
rng('shuffle'); % rng('shuffle') 根据当前时间为随机数生成器提供种子。
TxLen = 5000;
PulseLoc = randi(TxLen-PulseLen*2); % X = randi(imax) 返回一个介于 1 和 imax 之间的伪随机整数标量。
TxSignal = zeros(TxLen,1);
TxSignal(PulseLoc:PulseLoc+PulseLen-1) = pulse; % 插入脉冲
% Create Rx signal by adding noise
Noise = complex(randn(TxLen,1),randn(TxLen,1)); % z = complex(a,b) 通过两个实数输入创建一个复数输出 z,这样 z = a + bi。
RxSignal = TxSignal + Noise;
% Scale Rx signal to +/- one
scale1 = max([abs(real(RxSignal)); abs(imag(RxSignal))]);
RxSignal = RxSignal/scale1;
% Create matched filter coefficients
CorrFilter = conj(flip(pulse))/PulseLen; % Zc = conj(Z) 返回 Z 中每个元素的复共轭。频域取共轭相当于时域共轭对称部分不变,共轭反对称部分取反(也就是乘以-1)
% Correlate Rx signal against matched filter
FilterOut = filter(CorrFilter,1,RxSignal); % y = filter(b,a,x) 使用由分子和分母系数 b 和 a 定义的有理传递函数 对输入数据 x 进行滤波。
% Find peak magnitude & location
[peak, location] = max(abs(FilterOut)); % 获得最大值的位置以及大小
% Print results
figure(1)
subplot(311); plot(real(TxSignal)); title('Tx Signal (real)');
subplot(312); plot(real(RxSignal)); title('Rx Signal (real)');
t = 1:length(FilterOut);
str = sprintf('Peak found at %d with a value of %.3d',location,peak);
subplot(313); plot(t,abs(FilterOut),location,peak,'o'); title(str);
程序运行结果如下图:
TxSignal:原始的脉冲信号;
RxSignal:叠加了高斯白噪声后的信号;
FilterOut:匹配滤波后信号输出。
3、FPGA上实现算法
3.1 软件要求
-
MATLAB® (R2019b)
-
Simulink®
-
Fixed-Point Designer
-
MATLAB Coder
-
HDL Coder
-
Signal Processing Toolbox
-
DSP System Toolbox
-
Xilinx® Vivado® 2017.4(其它版本也可,只是综合结果不同)
3.2 实现步骤
3.2.1 创建算法的Simulink模型
-
运行第二步的程序初始化该步骤需要的参数;
-
创建一个Simulink模型命名为pulse_detector_v1.slx;
-
添加一个Signal From Workspace 模块并在信号栏填写RxSignal表示从MATLAB工作空间中获得该信号。
-
使用 Discrete FIR Filter模块实现匹配滤波函数以步骤2的匹配滤波系数CorrFilter作为该模块的滤波系数
-
命名滤波器的输出信号为filter_out并且使能信号的数据日志记录
-
仿真停止时间设置为SimTime(SimTime = length(RxSignal) + WindowLen)
-
编写Simulink测试脚本pulse_detector_v1_tb.mlx并运行到第16行,验证Simulink滤波器的输出和第2步中输出之间的误差
% Simulate model and compare results to reference if iscolumn(CorrFilter) % 确定输入是否为列向量 CorrFilter = transpose(CorrFilter); % need row vector for filter block end SimTime = length(RxSignal) + WindowLen; % Simulate model slout = sim('pulse_detector_v1'); % simOut = sim(model) 使用现有模型配置参数对指定模型进行仿真,并将结果返回为 Simulink.SimulationOutput 对象 % Correlation filter output FilterOutSL = getLogged(slout,'filter_out'); compareData(real(FilterOut),real(FilterOutSL),{2 3 1},'ML vs SL correlator output (re)'); compareData(imag(FilterOut),imag(FilterOutSL),{2 3 2},'ML vs SL correlator output (im)'); % 运行到此处 % Magnitude squared output MagSqSL = getLogged(slout,'mag_sq_out'); % Get the object a signal interface element compareData(MagSqOut,MagSqSL,{2 3 3},'ML vs SL mag-squared output'); % Peak value MidSampleSL = getLogged(slout,'mid_sample'); Detected = getLogged(slout,'detected'); PeakSL = MidSampleSL(Detected>0); fprintf('nPeak location = %d, magnitude = %.3d using global maxn',location,peak); fprintf('Peak location = %d, mag-squared = %.3d using local maxn',location_2,peak_2); fprintf('Peak mag-squared from Simulink = %.3d, error = %.3dn',PeakSL,abs(peak_2-PeakSL)); % % Copyright 2020 The MathWorks, Inc. % function signal_val = getLogged(simout_obj,signal_name) logsout = simout_obj.logsout; if isempty(logsout) error('No logged signal found. Make sure ''%s'' is logged in the model',... signal_name); end sig = logsout.getElement(signal_name); if isempty(sig) error('Signal ''%s'' not found. Make sure it is logged and named correctly.',... signal_name); end signal_val = squeeze(sig.Values.Data); end
image-20200626101926772
-
回顾第2步中硬件友好的峰值检测算法,在滤波器模块的输出,调用下列模块实现求幅度的平方
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YbwvnJnh-1596073099912)(typora-user-images/image-20200626103203614.png)]
输出输入的实部和虚部
实部和虚部分别求平方
求和模块进行实部和虚部求和得到信号的幅度的平方。
-
封装第8步的模块为一个子系统并命名为Compute Power标记子系统的输出为mag_sq_out。
-
显示信号的维度和信号的数据类型
-
连接mag_sq_out到一个Tapped Delay模块作为滑动窗口的缓冲。设置延时的长度为滑动窗口的长度WindowLen
-
使用MATLAB Function block完成剩下的硬件友好峰值检测算法,从pulse_detector_reference.mlx中粘贴代码到这个block,如下截图所示。点击下图所示的Edit Data按钮取消勾选Windowlen可调选项
-
添加一个Constant block并设置threshold作为阈值
-
连接constant, tapped delay and MATLAB function blocks,封装这三个模块作为一个子系统并命名为Local Peak,并将输出信号命名为mid_sample和detected并使能数据日志
-
连接一个 Unit Delay Enabled Synchronous模块到子系统的输出来锁存峰值当detected为1时,再连接一个单位延时模块到Display模块
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8q2s6ePD-1596073099920)(FPGA.assets/image-20200626170836135.png)]
-
至此Simulink仿真模型就搭建好了
-
运行 pulse_detector_v1_tb.mlx比较Similink的输出与MATLAB参考代码的输出,观察MATLAB和Simulink之间的误差,使用detected输出来指示峰值的位置
3.2.2 实现硬件结构
-
复制当前Simulink模块为pulse_detector_v2.slx
-
执行MATLAB命令hdlsetup(‘pulse_detector_v2’),配置模型设置兼容HDL代码生成
-
打包滤波模块( the filter block,)、功率计算模块(the Compute Power)、峰值子系统(Local Peak)子系统作为顶层子系统命名为Pulse Detector这个顶层子系统就是要产生HDL代码的部分
-
从Signal From Workspace 模块中添加一个输入有效的信号并且在信号栏输入 true(size(RxSignal)),该信号作为Pulse Detector子系统的第二输入
在Pulse Detector子系统中第一个输入命名为data_in,第二个输入命名为valid_in,添加一个新的输出端口valid_out
-
使用一个Discrete FIR Filter HDL Optimized模块代替原有的滤波模块,同样滤波系数选择CorrFilter,命名输出数据信号名为filter_out并使能记录这个信号,连接valid_in到FIR valid_input,连接FIR valid output端口到valid_out端口,命名FIR valid out为filter_valid并记录
-
输入输出添加Delay模块作寄存器
-
添加一个Terminator模块终结输出端口***valid_out***
-
运行pulse_detector_v2_tb.mlx来仿真这个模块,比较Simulink输出和MATLAB参考输出
3.2.3 转换设计为定点
-
保存当前Simulink模块为pulse_detector_v3.slx
-
顶层模块添加一个Data Type Conversion转换模块在RxSignal信号后,设置输出的数据类型为DT_input,DT_input在测试脚本中被定义为fixdt(1,16,14) 代表-1到1中的数
-
改变滤波器的系数为DT_coeff,DT_coeff被定义为fixdt(1,18),常量的分数长度未被指定时可以自动确定
-
在计算功率子系统中添加一个Data Type Conversion模块设置输出的数据类型为DT_filter,保持整数的范围,设置字长度为18位;加法器后面添加一个Data Type Conversion模块,输出类型设置为DT_power
-
在Local Peak子系统中添加Data Type Duplicate模块,连接一个端口到阈值常量模块和另一个端口到tapped delay模块输出;设置阈值常量模块输出的数据类型到Inherit via back propagation
-
终于没有错误了,但是出现了下述警告可以忽略
-
比较定点模型和MATLAB参考模型之间的误差
3.2.4 生成和综合HDL代码
-
检查模型的HDL兼容性
设置顶层子系统Pulse Detector为DUT(HDL Code Toolstrip > unpin > click on subsystem
> pin)
-
生成MATLAB的代码和报告
在MATLAB中运行一下命令添加Xilinx Vivado 2017.4到系统路径
hdlsetuptoolpath(‘ToolName’,‘Xilinx Vivado’,‘ToolPath’,‘D:XilinxVivado2017.4bin’);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2e5D9Dcj-1596073099933)(FPGA.assets/image-20200626215844002.png)]
启动HDL Workflow Advisor为DUT子系统
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C9tG07FU-1596073099935)(FPGA.assets/image-20200626220715509.png)]
-
在3.2步 (right-click on step 3.2 > Run to Selected Task)
产生如下图所示的HDL代码和报告
-
执行4.1步生成Xilinx Vivado工程
最后
以上就是微笑冷风为你收集整理的基于Simulink产生HDL代码(可直接生成VIVADO工程和测试文件)二、基于Simulink产生HDL代码的全部内容,希望文章能够帮你解决基于Simulink产生HDL代码(可直接生成VIVADO工程和测试文件)二、基于Simulink产生HDL代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复