我是靠谱客的博主 微笑冷风,最近开发中收集的这篇文章主要介绍基于Simulink产生HDL代码(可直接生成VIVADO工程和测试文件)二、基于Simulink产生HDL代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

二、基于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模型

  1. 运行第二步的程序初始化该步骤需要的参数;

  2. 创建一个Simulink模型命名为pulse_detector_v1.slx;

  3. 添加一个Signal From Workspace 模块并在信号栏填写RxSignal表示从MATLAB工作空间中获得该信号。

  4. 使用 Discrete FIR Filter模块实现匹配滤波函数以步骤2的匹配滤波系数CorrFilter作为该模块的滤波系数

  5. 命名滤波器的输出信号为filter_out并且使能信号的数据日志记录

  6. 仿真停止时间设置为SimTime(SimTime = length(RxSignal) + WindowLen)

  7. 编写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

  8. 回顾第2步中硬件友好的峰值检测算法,在滤波器模块的输出,调用下列模块实现求幅度的平方

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YbwvnJnh-1596073099912)(typora-user-images/image-20200626103203614.png)]

    输出输入的实部和虚部

    实部和虚部分别求平方

    求和模块进行实部和虚部求和得到信号的幅度的平方。

  9. 封装第8步的模块为一个子系统并命名为Compute Power标记子系统的输出为mag_sq_out。

  10. 显示信号的维度和信号的数据类型

  11. 连接mag_sq_out到一个Tapped Delay模块作为滑动窗口的缓冲。设置延时的长度为滑动窗口的长度WindowLen

  12. 使用MATLAB Function block完成剩下的硬件友好峰值检测算法,从pulse_detector_reference.mlx中粘贴代码到这个block,如下截图所示。点击下图所示的Edit Data按钮取消勾选Windowlen可调选项

  13. 添加一个Constant block并设置threshold作为阈值

  14. 连接constant, tapped delay and MATLAB function blocks,封装这三个模块作为一个子系统并命名为Local Peak,并将输出信号命名为mid_sampledetected并使能数据日志

  15. 连接一个 Unit Delay Enabled Synchronous模块到子系统的输出来锁存峰值当detected1时,再连接一个单位延时模块到Display模块

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8q2s6ePD-1596073099920)(FPGA.assets/image-20200626170836135.png)]

  16. 至此Simulink仿真模型就搭建好了

  17. 运行 pulse_detector_v1_tb.mlx比较Similink的输出与MATLAB参考代码的输出,观察MATLAB和Simulink之间的误差,使用detected输出来指示峰值的位置

3.2.2 实现硬件结构

  1. 复制当前Simulink模块为pulse_detector_v2.slx

  2. 执行MATLAB命令hdlsetup(‘pulse_detector_v2’),配置模型设置兼容HDL代码生成

  3. 打包滤波模块( the filter block,)、功率计算模块(the Compute Power)、峰值子系统(Local Peak)子系统作为顶层子系统命名为Pulse Detector这个顶层子系统就是要产生HDL代码的部分

  4. Signal From Workspace 模块中添加一个输入有效的信号并且在信号栏输入 true(size(RxSignal)),该信号作为Pulse Detector子系统的第二输入

    Pulse Detector子系统中第一个输入命名为data_in,第二个输入命名为valid_in,添加一个新的输出端口valid_out

  5. 使用一个Discrete FIR Filter HDL Optimized模块代替原有的滤波模块,同样滤波系数选择CorrFilter,命名输出数据信号名为filter_out并使能记录这个信号,连接valid_in到FIR valid_input,连接FIR valid output端口到valid_out端口,命名FIR valid out为filter_valid并记录

  6. 输入输出添加Delay模块作寄存器

  7. 添加一个Terminator模块终结输出端口***valid_out***

  8. 运行pulse_detector_v2_tb.mlx来仿真这个模块,比较Simulink输出和MATLAB参考输出

3.2.3 转换设计为定点

  1. 保存当前Simulink模块为pulse_detector_v3.slx

  2. 顶层模块添加一个Data Type Conversion转换模块在RxSignal信号后,设置输出的数据类型为DT_input,DT_input在测试脚本中被定义为fixdt(1,16,14) 代表-1到1中的数

  3. 改变滤波器的系数为DT_coeff,DT_coeff被定义为fixdt(1,18),常量的分数长度未被指定时可以自动确定

  4. 在计算功率子系统中添加一个Data Type Conversion模块设置输出的数据类型为DT_filter,保持整数的范围,设置字长度为18位;加法器后面添加一个Data Type Conversion模块,输出类型设置为DT_power

  5. Local Peak子系统中添加Data Type Duplicate模块,连接一个端口到阈值常量模块和另一个端口到tapped delay模块输出;设置阈值常量模块输出的数据类型到Inherit via back propagation

  6. 终于没有错误了,但是出现了下述警告可以忽略

  7. 比较定点模型和MATLAB参考模型之间的误差

3.2.4 生成和综合HDL代码

  1. 检查模型的HDL兼容性

    设置顶层子系统Pulse Detector为DUT(HDL Code Toolstrip > unpin > click on subsystem

    > pin)

  2. 生成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. 3.2步 (right-click on step 3.2 > Run to Selected Task)

    产生如下图所示的HDL代码和报告

  4. 执行4.1步生成Xilinx Vivado工程

最后

以上就是微笑冷风为你收集整理的基于Simulink产生HDL代码(可直接生成VIVADO工程和测试文件)二、基于Simulink产生HDL代码的全部内容,希望文章能够帮你解决基于Simulink产生HDL代码(可直接生成VIVADO工程和测试文件)二、基于Simulink产生HDL代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部