提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
Xilinx FIR IP作为一个信号处理的IP,考虑到了如何在matlab和C模型环境下如何模拟该IP核的输入输出数据,运用Xilinx FIR IP的模型,我们无需考虑时序有关的问题就可以对输入输出进行大样本的验证,而不是通过modelsim去进行仿真。相对于matlab和C环境下的仿真效率比在modelsim上效率高千百倍,最重要的是,modelsim出来的结果和matlab或者C模型只要参数设置一致,那么输入输出会是完全一致的。因此很多大型工程,尤其是做芯片,都有一个C或者matlab模型进行支撑,通过C模型来指导verilog设计。
在于pg149文档的第五章。
介绍了C模型和matlab模型,C模型的话暂时还没研究,这里主要记录下matlab模型的使用,以及自带例程的运行。
matlab模型使用起来也很简单,每次例化了一个FIR ip核之后,ip核的文件夹会带一个cmodel的文件夹。
里面包含了这两个压缩文件,lin64是在linux下使用,nt64是在windows下使用。我们解压nt64压缩文件后,也就看到了上表格中红色方框中的这些文件了。
首先,我们需要在matlab中运行 make_fir_compiler_v7_2_mex 这个文件,会生成一个fir_compiler_v7_2_bitacc_mex.mexw64这样的文件,然后,在运行 run_fir_compiler_v7_2_mex,这样matlab例程就可以运行起来的了。
还有一些详细的函数说明可以参照数据手册说的,直接通过看例程也可以快速了解该模型的使用,这里就不多说了。
注意,我这里用的是matlab2019b,操作系统是win10,vivado2019.2
run_fir_compiler_v7_2_mex 文件中自带5个例子。
公共参数
fft_size = 4096; %FFT分析点数 data_samples = 4096; %数据采样点数 window_name = @hamming; %窗函数
下面是使用其他窗函数的定义,
@barthannwin @bartlett @blackman @blackmanharris @bohmanwin @chebwin @flattopwin @gausswin @hamming @hann @kaiser @nuttallwin @parzenwin @rectwin @taylorwin @triang @tukeywin
使用这种@方法,实际上使用一个参数固定的典型窗函数,例如@hamming
对于系数的幅频响应分析方法
fr_filter = fft(config1.coeff,fft_size); plot(20*log10(abs(fr_filter(1:fft_size/2))./max(abs(fr_filter)))); grid on;
IP核中使用的是,没有归一化的:
plot(20*log10(abs(fr_filter(1:fft_size/2))));
而Xilinx IP核中的图:
这两个图是一样的
默认设置的系数就是这个:
% Constants fft_size = 4096; data_samples = 4096; window_name = @hamming; %window_name = @rectwin; %矩形窗 % Create default filter disp('---------------------------------------------------------------------'); disp('INFO: Create default filter'); disp('---------------------------------------------------------------------'); fir1 = fir_compiler_v7_2_bitacc() config1 = get_configuration(fir1); % Create an input data vector % - Scaled to match the default models data format; Fix16_0 disp('INFO: Generate input data...'); data_in = 16e3*(sin(0.5*[1:1:data_samples])+sin(2*[1:1:data_samples])); % Filter data disp('INFO: Filter...'); data_out = filter(fir1,data_in); % Plot normalized filter response, input data and output data disp('INFO: Plot filter response, input data and output data'); fr_filter = fft(config1.coeff,fft_size); fr_data_in = fft(data_in.*window(window_name,data_samples)',fft_size); %fr_data_in = fft(data_in,fft_size); fr_data_out = fft(data_out.*window(window_name,data_samples)',fft_size); %fr_data_out = fft(data_out,fft_size); figure; plot(20*log10(abs(fr_filter(1:fft_size/2))./max(abs(fr_filter)))); hold on; grid on; plot(20*log10(abs(fr_data_in(1:fft_size/2))./max(abs(fr_data_in))),'r'); plot(20*log10(abs(fr_data_out(1:fft_size/2))./max(abs(fr_data_out))),'g'); legend('Filter','Data in','Data out'); title('Default filter configuration'); disp('Press any key to continue...'); pause;
看绿色的曲线,经过滤波器后,幅度正好到达滤波器的包络处
% Constants fft_size = 4096; data_samples = 4096; window_name = @hamming; %window_name = @rectwin; %矩形窗 % Create 2 channel upsampling filter disp('---------------------------------------------------------------------'); disp('INFO: Create 2 channel upsampling filter'); disp('---------------------------------------------------------------------'); disp('Press any key to continue...'); pause; fir3 = fir_compiler_v7_2_bitacc('filter_type',1,'interp_rate',2,'num_channels',2) config3 = get_configuration(fir3); % Create input data vector % - Scaled to match the default models data format; Fix16_0 disp('INFO: Generate input data...'); clear data_in; data_in(1,:) = 16e3*(sin(0.5*[1:1:data_samples/2])); data_in(2,:) = 8e3*(sin(0.2*[1:1:data_samples/2])); % Create upsampled data with no filtering for comparison data_up(1,:) = upsample(data_in(1,:),2); % 实际上是数据中间补0 data_up(2,:) = upsample(data_in(2,:),2); % 实际上是数据中间补0 % Filter data disp('INFO: Filter...'); data_out = filter(fir3,data_in); % Plot normalized filter response, input data and output data disp('INFO: Plot filter response, input data and output data'); wndw(1,:) = window(window_name,data_samples/2); wndw(2,:) = window(window_name,data_samples/2); wndw_up(1,:) = window(window_name,data_samples); wndw_up(2,:) = window(window_name,data_samples); fr_filter = fft(config3.coeff,fft_size); fr_data_in = fft(data_in.*wndw,fft_size,2); fr_data_up = fft(data_up.*wndw_up,fft_size,2); fr_data_out = fft(data_out.*wndw_up,fft_size,2); figure; subplot(3,1,1); plot(20*log10(abs(fr_data_in(1,1:fft_size/2))./max(max(abs(fr_data_in)))),'b'); hold on; grid on; plot(20*log10(abs(fr_data_in(2,1:fft_size/2))./max(max(abs(fr_data_in)))),'r'); legend('Data In (ch1)','Data In (ch2)'); title('Input data'); subplot(3,1,2); plot(20*log10(abs(fr_data_up(1,1:fft_size/2))./max(max(abs(fr_data_up)))),'g'); hold on; grid on; plot(20*log10(abs(fr_data_up(2,1:fft_size/2))./max(max(abs(fr_data_up)))),'c'); legend('Data upsampled (ch1)','Data upsampled (ch2)'); title('Upsampled no filtering'); subplot(3,1,3); plot(20*log10(abs(fr_filter(1:fft_size/2))./max(abs(fr_filter))),'b'); hold on; grid on; plot(20*log10(abs(fr_data_out(1,1:fft_size/2))./max(max(abs(fr_data_out)))),'r'); plot(20*log10(abs(fr_data_out(2,1:fft_size/2))./max(max(abs(fr_data_out)))),'g'); legend('Filter','Data upsampled (ch1)','Data upsampled (ch2)'); title('Upsampled plus filtering'); disp('Press any key to continue...'); pause;
函数: cfirpm
b = cfirpm(n,f,@fresp) n 阶数 f [0 FP FS 1] @lowpass 的一个用法
% Constants fft_size = 4096; data_samples = 4096; window_name = @hamming; %window_name = @rectwin; %矩形窗 % Create filter using coefficients created by firpm % - Coefficients will be quantized by the FIR Compiler object disp('---------------------------------------------------------------------'); disp('INFO: Create filter using coefficients generated by cfirpm'); disp('---------------------------------------------------------------------'); disp('Press any key to continue...'); pause; disp('INFO: Creating coefficients...'); fl = 99; f = [0,0.2,0.3,1]; coeff = cfirpm(fl,f,@lowpass); disp('INFO: Creating filter quantizing coefficients to Fix16_15 ...'); fir4 = fir_compiler_v7_2_bitacc('coeff',coeff,'num_coeffs',fl+1,'coeff_width',16,'coeff_fract_width',15,'data_width',16,'data_fract_width',14) config4 = get_configuration(fir4); % Plot source and quantized filter coefficients disp('INFO: Plot quantized coefficients vs source coefficients'); figure; fr_filter = fft(config4.coeff,fft_size); fr_filter_quant= fft(filter(fir4,[1,zeros(1,fl)]),fft_size); %这个语句 filter(fir4,[1,zeros(1,fl)]) %等价于 %coeff1 = round(coeff*2^15)/2^15; 2^15 与coeff_fract_width参数对应 %还没搞清楚为什么 %plot(filter(fir4,[1,zeros(1,fl)]) - coeff1) plot(20*log10(abs(fr_filter(1:fft_size/2))./max(abs(fr_filter))),'b'); hold on; grid on; plot(20*log10(abs(fr_filter_quant(1:fft_size/2))./max(abs(fr_filter_quant))),'r'); legend('Source Coefficients','Quantized Coefficients'); title('Coefficient Quantization'); disp('Press any key to continue...'); pause; % Create an input data vector disp('INFO: Generate input data...'); clear data_in; data_in = sin(0.5*[1:1:data_samples])+sin(2*[1:1:data_samples]); % Filter data disp('INFO: Filter...'); data_out = filter(fir4,data_in); % Plot normalized filter response, input data and output data disp('INFO: Plot filter response, input data and output data'); fr_data_in = fft(data_in.*window(window_name,data_samples)',fft_size); fr_data_out = fft(data_out.*window(window_name,data_samples)',fft_size); figure; plot(20*log10(abs(fr_filter_quant(1:fft_size/2))./max(abs(fr_filter_quant)))); hold on; grid on; plot(20*log10(abs(fr_data_in(1:fft_size/2))./max(abs(fr_data_in))),'r'); plot(20*log10(abs(fr_data_out(1:fft_size/2))./max(abs(fr_data_out))),'g'); legend('Filter','Data in','Data out'); title('Filter using quantized coefficients'); disp('Press any key to continue...'); pause;
量化后与没有量化幅频响应对比