基于Matlab中Simulink生成FPGA-Verilog语言及联合Vivado的仿真(以卡尔曼-Kalman滤波器为例)

一、简介

  此内容基于博文:基于Matlab Hdl Coder实现FPGA程序开发(卡尔曼滤波算法实现)实现,Simulink仿真构建参考于上链接中。
  本博文解决了上博文中无法生成Verilog语言的问题,并对于自动生成的Verilog——testbench文件进行了优化——通过matlab产生信号及白噪声,并将信号数据载入到Vivado-tb文件中,最终通过vivado软件自带仿真器进行观察。

二、在Simulink中生成Verilog语言

1、在Simulink中建立Kalman滤波器仿真

  此处进行简单演示,建立好的Kalman滤波器模型如下图所示。

2、将Kalman滤波器部分打包

  将创建好的滤波器模型打包为一个模块,便于之后将此模块转换为Verilog语言——全选后点击“create subsystem”;

  生成模块后可添加信号及示波器观察Kalman功能是否正常。

3、生成Verilog程序

3.1、参数配置

  1、点击simulation进行Model Configuration Parameters配置;

  2、点击Solver,将Solver selection_Type改为Fixed-step,其余默认,点击apply应用;

  3、点击Hardware Implementation,将Device vendor设置为ASIC/FPGA,其余默认,点击apply应用;

  4、设置芯片型号及时钟频率,其余默认,点击apply应用;

  5、将复位电平设置为低电平有效,其余默认,点击OK完成参数配置。

  6、关联Vivado软件,进行联合编译:在matlab命令窗口输入命令,hdlsetuptoolpath (‘ToolName’,‘…’,‘ToolPath’,‘…’),具体用法可右键参照帮助。

3.2、HDL Code代码生成

  1、Code–HDL Code–HDL W… A… 打开工作区,进行相关配置,并检查错误;

  2、选择Kalman模块,生成相应程序;

  3、在工作区1.1中将综合工具选为相应编译器,之前的相关配置会自动填充,之后点Apply应用;在1.2中将时钟频率设为相应频率,Apply即可;

  4、右击Set Target ,Run All完成此部分设定;

  5、在3.1.1中,将语言选择为Verilog;在3.1.5中,将Generate RTL code和Generate test bench勾选;在3.2中,勾选Generate RTL Code与Generate Testbench,点击Apply;在3.3中勾选Skip This Task;其余默认即可,记得完成每一步配置后点击Apply;然后Run all第3部分;

  6、此时3.2部分会报错,这里点击下图所示,将实数检查设为none/warning(因为Verilog语言在综合时不允许有浮点数存在,所以会报错,我们这里仅进行仿真,所以忽略此错误);

  7、再次Run All第三部分,完成Verilog程序生成;(因为我们这里仅进行了仿真所以不需要进行Run第4部分综合编译,且生成的程序中存在real类型变量,不能进行综合)。

三、Vivado中实现Kalman滤波仿真

1、在Vivado中创建工程并将Kalman.v与Kalman_tb.v文件添加到工程中

2、在Matlab中生成波形文件,代码如下

  其中cosy_dig为叠加了白噪声的混合信号。

fc          = 0.25e6 ;      % 中心频率
Fs          = 50e6 ;        % 采样频率
T           = 1/fc ;        % 信号周期
Num         = Fs * T ;      % 周期内信号采样点数
t           = (0:Num-1)/Fs ;      % 离散时间

cosn        = cos(2*pi*fc*t) ;    % 信号

snr=10;
px_dBW=10;
pn_W=10^((px_dBW-snr)/10);
n=sqrt(pn_W)*randn(1,length(cosn));%噪声

y1=mapminmax(cosn+n);
cosy_dig    = floor((2^11-1) * y1 + 2^11) ;        %幅值扩展到 0~4095
cosy_dig1    = floor((2^11-1) * n + 2^11) ;        %幅值扩展到 0~4095
cosy_dig2    = floor((2^11-1) * cosn + 2^11) ;     %幅值扩展到 0~4095

fid         = fopen('E:\JXR\FPGA\matlab\Kalman1\whitenosie.dat', 'wt') ;  %写数据文件
fprintf(fid, '%x\n',cosy_dig1) ;
fclose(fid) ;

fid1         = fopen('E:\JXR\FPGA\matlab\Kalman1\sin.dat', 'wt') ;  %写数据文件
fprintf(fid1, '%x\n', cosy_dig2) ;
fclose(fid1) ;

fid2         = fopen('E:\JXR\FPGA\matlab\Kalman1\cosy_dig.dat', 'wt') ;  %写数据文件
fprintf(fid2, '%x\n', cosy_dig) ;
fclose(fid2) ;


figure('name','混合信号时域波形');
subplot(221);plot(cosy_dig1);hold on ;
subplot(222);plot(t,cosy_dig2) ;hold on ;
subplot(223);plot(t,y1) ;hold on ;
subplot(224);plot(t,cosy_dig) ;

3、重写tb仿真文件

  生成的tb文件很乱,我这里重新写了tb文件,并将matlab中生成的波形数据载入,具体代码如下:

`timescale 1ns / 1ps

module Kalman_tb;

  parameter    NIN  =12 ;  //matlab中生成文件数据位宽为12

    reg              clk;        
    reg              rstn;      
    reg              en; 
    reg              [63:0] In1; 
    wire                 ce_out;     
    wire             [63:0] Out1;
        
 //============== 200MHz clk generating=======================
    localparam   T200M_HALF    = 2.5000;
    initial begin
        clk = 1'b0 ;
        forever begin
            # T200M_HALF clk = ~clk ;
        end
    end    
  //========reset and finish=============
    initial begin
        rstn = 1'b0 ;
        # 30 ;
        rstn = 1'b1 ;
        # (T200M_HALF * 2 * 2000) ;
        $finish ;
    end   
//=====read cos data into register ========                     
    parameter    SIN_DATA_NUM = 200 ;
    reg          [NIN-1:0] stimulus1 [0: SIN_DATA_NUM-1] ;
    integer      i ;

    initial begin
        $readmemh("E:/JXR/FPGA/matlab/Kalman1/cosy_dig.dat", stimulus1) ;    //提取加噪声后的波形数据
        i         = 0 ;
        en        = 0 ;
       In1  =0;
        # 200 ;
        forever begin
            @(negedge clk) begin
                en          = 1 ;
                In1         = stimulus1[i] ;
                if (i == SIN_DATA_NUM-1) begin
                    i = 0 ;
                end
                else begin
                    i = i + 1 ;
                end
            end
        end
    end

Kalman Kalman_u(
    .clk        (clk),
    .reset      (rstn),
    .clk_enable (en),
    .In1        (In1),
    .ce_out     (ce_out),
    .Out1       (Out1)
);
 
endmodule  // kalman_tb

4、Vivado中仿真编译

  仿真结果如下所示:

四、小结

  比较初步的实现了simulink仿真转换为Verilog语言程序在vivado中的Kalman滤波仿真,不足之处是程序中变量均为real型,不能综合编译烧录于实际硬件中,还有待改进,望能共同交流协作。

猜你喜欢

转载自blog.csdn.net/m0_51426340/article/details/129839261