VIVADO中的IP核在MATLAB中仿真

项目简述

我们都会用MATLAB进行算法验证,但是经常会发现如果VIVADO中调用了IP核,那么最终会发现VIVADO与MATLAB之间的数据不可以统一的对应起来。那么,MATLAB验证的效果就会大大下降,那么可不可以想办法将VIVADO中的IP核封装成一个函数在MATLAB中调用呢?答案是可以的。这篇博客主要以FFT的IP核为例讲解封装成一个函数并且成功在MATLAB中调用。

本次实验所使用的软硬件工具如下:
1、VIVADO 2019.1
2、MATLAB 2015b
3、VS2015

VIVADO建立FFT IP核

首先建立VIVADO工程,然后选择FFT IP核开始定制
在这里插入图片描述
这里定制一下IP的信息,这里需要注意定制IP的信息与MATLAB中调用的文件的设置需要一样,这样才可以将MATLAB中的数据与VIVADO相对应。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
上面每步定制的意思我们在前面讲解FFT IP的时候已经进行了相应的讲解,需要学习的同学可以查阅前面的文章,这里我们不再赘述。最后点击生成FFT 的IP核。这里特别要注意,数据的输入输出是AXI-Stream格式的数据,也就是说是以字节对齐的,比如所输入数据实部12位、虚部11位,那么在输入数据线上的表示就是实部16位、虚部16位。这也是很多初学者不明白数据位宽与自己设置不一样的原因。

MATLAB调用FFT IP核

上面我们已经生成了FFT IP,然后再生成目录的cmodel文件中有相应的文件,但是需要我们提前编译一下,这里选择的编译环境是VS2015。cmodel中的文件有两个,如下:
在这里插入图片描述
上面的是linux系统,下面的是windos系统。我们将下面的文件进行解压放到MATLAB的文件夹中。然后打开MATLAB切换到相应的文件夹下:
在这里插入图片描述
然后再MATLAB的命令行输入 run make_xfft_v9_1_mex,然后出现如下结果:
在这里插入图片描述
在生成文件中多出了.mexw64后缀的文件证明我们生成相应的MATLAB函数成功。然后查阅技术手册,会发现函数的调用主要有以下几个端口:
在这里插入图片描述

函数调用的输出如下:

上面的参数在使用的时候要与VIVADO的IP定制的时候相一致,那么在MATLAB中调用该函数的时候才可以与VIVADO中仿真出来的结果相一致。而且前面我们定制IP的时候选择的是可以实施配置,那么只需要我们MATLAB与VIVADO实时配置的参数相一致,MATLAB与VIVADO两个输出的结果完全一致,最终实现了VIVADO中的IP核在MATLAB中调用的现象。
在这里插入图片描述
下面以FFT为例给出相应的代码:

clc;
clear all;
addpath(genpath(pwd));
sim_options = struct(...
    'MODE',        '2k'   ...         %fft模式  1k 2k 4k 8k
    );
tx_nFrame=1;
%------------------------------------------------------------------------------
% Parameters Definition
%------------------------------------------------------------------------------
switch sim_options.MODE
    case '1k'
        NFFT   = 1024;       % FFT number of points
    case '2k'
        NFFT   = 2048;       % FFT number of points
    case '4k'
        NFFT   = 4096;       % FFT number of points
    case '8k'
        NFFT   = 8192;       % FFT number of points
    otherwise, error('sim_options UNKNOWN MODE');
end
%------------------------------------------------------------------------------
% Input arguments checking
%------------------------------------------------------------------------------
q_in =  quantizer( 'mode','fixed','roundmod', 'floor','overflowmode','wrap','format',[12 11]);
q_out = quantizer( 'mode','fixed','roundmod', 'floor','overflowmode','wrap','format',[12 11]);
%gen data 


% DataIn_x = -1+2*rand(1,NFFT);
% DataIn_x = quantize(q_in,DataIn_x);
% 
% fid1 = fopen('RE_DATA.txt','w');
% fprintf(fid1,'%d\n',DataIn_x*2^11);
% 
% DataIn_y = -1+2*rand(1,NFFT);
% DataIn_y = quantize(q_in,DataIn_y);
% 
% fid1 = fopen('IM_DATA.txt','w');
% fprintf(fid1,'%d\n',DataIn_y*2^11);


fid1 = fopen('RE_DATA.txt','r');
DataIn_x = fscanf(fid1,'%d');

fid1 = fopen('IM_DATA.txt','r');
DataIn_y = fscanf(fid1,'%d');

DataIn = DataIn_x/2^11 + DataIn_y/2^11*1i;
DataIn = DataIn.';

% fid1 = fopen('com_data_in.txt','w');
% fprintf(fid1,'%d\n',imag(DataIn)*2^11);
%------------------------------------------------------------------------------
% Procedure
%------------------------------------------------------------------------------
fftDI = DataIn;

fftDO = zeros(size(DataIn,1), NFFT);
DataOut = zeros(size(DataIn,1), NFFT);

% IFFT
for numfft = 1:size(fftDI,1)
    fftDO(numfft,:) = fft_cmodel(fftDI(numfft,:),12,0);
    DataOut(numfft,:) = quantize(q_out,fftDO(numfft,:));
end
%==================================================================================
%                 t2_tx_removepadding
%==================================================================================
fft_data_com =DataOut(:)*2^11;

fft_cmodel代码:

function [output,blkexp,overflow] = fft_cmodel(input,INPUT_WIDTH,direction)
 
% Generics for this smoke test
generics.C_NFFT_MAX=11;
generics.C_ARCH = 1;
generics.C_HAS_NFFT = 1;
generics.C_USE_FLT_PT = 0;
generics.C_INPUT_WIDTH = 12; % Must be 32 if C_USE_FLT_PT = 1
generics.C_TWIDDLE_WIDTH = 16; % Must be 24 or 25 if C_USE_FLT_PT = 1
generics.C_HAS_SCALING = 1; % Set to 0 if C_USE_FLT_PT = 1
generics.C_HAS_BFP = 0; % Set to 0 if C_USE_FLT_PT = 1
generics.C_HAS_ROUNDING = 1; % Set to 0 if C_USE_FLT_PT = 1

channels = 1;

q =  quantizer( 'mode','fixed','roundmod', 'convergent','overflowmode','saturate','format',[generics.C_INPUT_WIDTH, generics.C_INPUT_WIDTH-1]);

input = quantize(q,input);

nfft = log2(length(input));

if generics.C_ARCH == 1 || generics.C_ARCH == 3
scaling_sch = ones(1,floor(nfft/2)) * 2;
if mod(nfft,2) == 1
  scaling_sch = [scaling_sch 1];
end
else
scaling_sch = ones(1,nfft);
end

% Run the MEX function

 [output, blkexp, overflow] = xfft_v9_1_bitacc_mex(generics, nfft, input, scaling_sch, direction);


上面便是在MATLAB中调用VIVADO中的IP核的代码,最主要的就是下面的模块:
在这里插入图片描述
其余的代码都是构建这个函数的输入变量。上面的代码模块大家不懂也没有关系,这篇博客主要是为了让大家了解VIVADO中的IP如何在MATLAB中仿真。其中这种功能最主要的参考就是本IP的技术手册中model部分,如下:
在这里插入图片描述

小结

要想验证上面结果的正确性,我们需要将上面输出的结果与VIVADO中的相互对比,但是这里就涉及到了FFT的实时配置,这在我们之后的博客中进行讲解。

总结

创作不易,认为文章有帮助的同学们可以关注、点赞、转发支持。为行业贡献及其微小的一部分。或者对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章