关于VIVADO FIR Compiler的设计与使用

 

1、MATLAB的FIR使用参照官方文档

FIR 滤波器设计 - MATLAB & Simulink - MathWorks 中国

一般选用I类的FIR的滤波器。

2、matlab输出FIR滤波器抽头系数

%可复制进MATLAB R2016a以上版本使用

clear;

%设计一个带通滤波器。

%采样频率越高,所需要的阶数n也就越高,FPGA资源使用量越高,

%可以适当减少,但考虑到奈奎斯特采样定理,采样频率必须大于两倍的截止频率

fs=2.5*10^6;%单位Hz

%滤波器系数量化分辨率位数,位数越大,实际频响越接近理想频响,但会增加FPGA资源使用量

qm=16;

%过渡带 [50K 100K 400K 450K] 单位Hz

fc=[50*10^3 100*10^3 400*10^3 450*10^3];

%三个数表示了50K~100K,100K~400K,400K~450KHz三个频带中理想的幅度值

mag=[0 1 0];

%设置通带误差容限a1及阻带误差容限a2,a3,通带没有特别需求通常设置为0.3,即-3dB

%通带最大衰减 = 20*log10(1-a2) dB

%阻带最小衰减 = 20*log10(1-a1) dB

%阻带最小衰减 = 20*log10(1-a3) dB

a1=0.001;a2=0.3;a3=0.001;

dev=[a1 a2 a3];

%采用凯塞窗函数获取满足要求的最小滤波器阶数,阶数大小影响FPGA资源使用量

[n,~,~,~] = kaiserord(fc,mag,dev,fs);

%firpm函数的频段向量,新增0与fs/2

fpm=[0 fc(1) fc(2) fc(3) fc(4) fs/2];

%firpm函数的幅值向量,与上述频段向量一一对应即可

magpm=[0 0 1 1 0 0 ];

%频率归一化

wnpm=fpm*2/fs;

%为满足I型FIR滤波器,将n选择为偶数

n=n + rem(n,2);

%采用firpm函数设计最优滤波器

h_pm=firpm(n,wnpm,magpm);

%计算得出的系数向量归一化

h_pm = h_pm/max(abs(h_pm));

%量化滤波系数为12bit有符号整数

q_pm=round(h_pm*(2^(qm-1)-1));

%将生成的滤波器系数数据写入FPGA所需的coe文件中

fid=fopen('.\fir_coe.coe','w');

fprintf(fid, 'RADIX=10;\n');%生成索引

fprintf(fid, 'COEFDATA = \n');

for i = 1:n+1

if i == n+1

fprintf(fid,'%d;', q_pm(i));

else

fprintf(fid,'%d,', q_pm(i));

end

end

fclose(fid);

%获取量化前后滤波器的幅频响应数据

m_pm=20*log10(abs(fft(h_pm,1024)));

m_pm=m_pm-max(m_pm);

q_pm=20*log10(abs(fft(q_pm,1024)));

q_pm=q_pm-max(q_pm);

%设置幅频响应的横坐标单位为MHz

x_f = (0:(fs/length(m_pm)):fs/2)/10^6;

%只显示正频率部分的幅频响应

mf_pm=m_pm(1:length(x_f)); %未量化时理想幅值

mf_qm=q_pm(1:length(x_f)); %量化后的实际幅值

%由于量化后取整的操作,可能导致频响变化,为作对比将其打印

%绘制幅频响应曲线

plot(x_f,mf_pm,'--',x_f,mf_qm,'-');

xlabel('频率(MHz)');ylabel('幅度(dB)');

legend('未量化','12位量化');

grid;

3、VIVADO FIR Compiler

官方文档TDATA • FIR Compiler (PG149) • Reader • AMD Adaptive Computing Documentation Portal (xilinx.com)

1

  1. :选择Filter Options页面
  2. :选择.coe文件,这里的.coe文件与上述MATLAB程序生成的文件不一致,由于上述的阶数n过长,会导致综合编译时间过长,故使用另外的.coe文件,文件内容如下。

RADIX=10;

COEFDATA =

-29,-91,-166,-194,-135,-45,-88,-371,-727,-724,-36,1130,2047,2047,1130,-36,-724,-727,-371,-88,-45,-135,-194,-166,-91,-29,-18,-54,-44,-32,-141,-110,-28,-295,-185,90,-625,-235,2047,2047,-235,-625,90,-185,-295,-28,-110,-141,-32,-44,-54,-18;

频响如下

该内容中含有2组的FIR抽头系数。

  1. :如果.coe文件中只含有1组滤波器系数,这里填入1;2组系数则填2,以此类推。程序运行过程中可通过特定接口选择不同组的系数,用以切换不同需求的频率响应。这里选择了2组。
  2. :勾选选择是否使用重新加载系数。与上述切换不同组的系数相同,最终目的都是为了切换不同需求的频率响应,但过程有所不同。与③相同,这里的重新装填的系数可以来自预先存储于FPGA内部的寄存器,不同的是,它也可来自与外部通信接收得到的数据,或者来自FPGA内部计算。将准备好的数据再通过特定接口送入FIR滤波器。目前还未有相关需求,暂未实现此部分功能。
  3. :默认选择Single Rate。
  4. :选择Freq.Response页面
  5. :如果②③步骤中选择了多组滤波器系数,则在这里可以选择不同的组别,观察不同的频率响应函数。如图最大增益大约为80dB,这是因为系数量化成为了12bit的二进制数据,12bit二进制数最大值为12’d4095,20*lg(4095) ≈ 72.25dB,接近图像上的频响曲线波峰。

2

  1. :选择Channel Specification页面
  2. :默认Basic,还未研究advance功能
  3. :交错通道数量设,增加数量会增加DSP资源的消耗,此次设定为16个
  4. :并行通道数量设定,本质上是例化了多个FIR滤波器,大大增加了FPGA资源使用量
  5. :关于采样的设定,默认选择频率采样。
  6. :采样频率为前述的2.5MHz
  7. :工作频率决定了时分复用下可容纳的交错通道数量,这里设定为FPGA工作频率100MHz,最多可容纳100MHz/2.5MHz=40个交错通道。

3

  1. :选择Implementation页
  2. :.coe文件中准备好的是整型的系数,故选择整型系数
  3. :MATLAB计算的时候以及确定抽头系数的分辨率为12bit,即位宽是12bit。
  4. :输入的波形数据带符号位
  5. :输入的波形数据包括符号位在内位宽为16bit
  6. :输出的波形数据为全精度

4

  1. :选择Interface页面
  2. :将TLAST选为Packet Framing,在输入数据时可作标记,在滤波完成输出的时候也会在相应的地方标记,根据官方文档,其用意是为简化逻辑设计。
  3. :TUSER输入都选择Channel ID Field,由于存在时分复用,故需要它作为标记,就目前使用情况可不使用TLAST,只使用TUSER,TUSER为位宽为log2(通道数),上述设定了位宽为16bit,这里TUSER为4bit的0~15。在输入通道0的数据时,将TUSER置为0;在输入通道1的数据时,将TUSER置为1,依此类推。
  4. :TUSER输出同理
  5. :配置通道默认选择向量
  6. :默认选择单端
  7. :勾选低电平复位
  8. :勾选后在复位时也将所有数据向量包括波形数据等复位
  9. :选择Implementation Details页面。可以看到各个接口的详细的数据分配。例如S_AXIS_DATA-TDATA中,可以看到0~15代表了16个通道,16bit全字段都代表了输入的波形数据。

5

  1. :Summary页面中再核验一遍设置
  2. :IP Symbol中可以查看模块的完整接口

4、输入数据源

使用MATLAB产生,代码如下:

clear;

%输出sin函数频率 = FIR采样频率/(div*2) 现基频 2500K/50*2 = 25K

div = 50;

%实际上想要做2^16的分辨率sin函数,

%但是归一化后输出取值在-1~1,差值为2,故2^16的分辨率实际只需要2^15

limit = 2^15;

data_length = 100; %数据长度

if data_length < 2*div

data_length = 2*div;

end

y_pre =zeros(1,div*2);

%y_hex =zeros(1,div*2);

x = 0 : pi/div : (data_length/div)*pi-pi/div;

%可以增加需要叠加的频率信号,合成多种频率的信号

y=1*sin(24*x) + 0.1*sin(2*x) + 0.1*sin(40*x);

y_max = max(abs(y));

y = y/y_max; %归一化

y=fix(y*(limit-1));

plot(x,y);

for j = 1:data_length

if y(j) < 0

y_pre(j)= y(j) + limit*2;

else

y_pre(j) = y(j);

end

end

%plot(x,y_pre);

y_hex=dec2hex(y_pre);

fid=fopen('.\sin_test.txt','w');

for i = 1:data_length

fprintf(fid,'%c%c%c%c\n', y_hex(i,1), y_hex(i,2), y_hex(i,3), y_hex(i,4));

end

fclose(fid);

5、接口时序

1 输入交错通道的波形数据

数据通道中,上电后等待tready被FIR模块拉高,而后可拉高tvaild发送数据,tuser也随之开始递增,根据tuser的不同,表示发送不同通道的数据,当发送最后一个通道的数据即tuser=4‘hf时,tlast被拉高,如果拉高时机不对,incorrect将会被置1表示数据错误。

前述有计算过此FIR模块最多可容纳100MHz/2.5MHz=40个交错通道,即每40个系统时钟周期中每个交错通道都必须完成一次采样,故上述时序图的行为必须在每40个时钟周期完成一次,不能缩短也不能延长。否则,根据FIR模块的构成,将会导致输出数据混乱。

2 输入配置通道数据

配置通道同理。从3、VIVADO FIR Compiler中的4-⑨可以了解到tdata的最低位0或1的选择控制FIR系数选择。

3 输出交错通道的波形数据

输出数据tvalid被拉高时有效,此时根据tuser值,将tdata归为相应通道的数据。代码如下。

filter_signal[m_axis_data_tuser] <= m_axis_data_tdata;

6、仿真结果

频响如下

上图红色字体表明了该通道输入的波形频率成分,右侧波形为滤波后的波形结果。可以看到滤波效果良好。

posted @ 2024-06-21 12:02  Akinohara  阅读(804)  评论(0编辑  收藏  举报