搜索网站的软件,购物网站怎么做推广,网站建设考核标准,用邮箱做网站前言#xff1a;复习大学课程中数字信号处理的内容#xff0c;尽管学了很多理论知识#xff0c;但与实际的联系还是比较少#xff0c;也就是说学到的知识不能很好地运用于实践#xff0c;所以我打算对理论知识进行验证#xff0c;从MATLAB和FPGA入手#xff0c;完成滤波…前言复习大学课程中数字信号处理的内容尽管学了很多理论知识但与实际的联系还是比较少也就是说学到的知识不能很好地运用于实践所以我打算对理论知识进行验证从MATLAB和FPGA入手完成滤波器的设计体会模拟信号数字处理的过程同时也对这个过程进行记录方便回顾和完善。
设计一个FIR带通滤波器截止频率为2400Hz和3600Hz阻带最小衰减20dB以上测试信号为1K、2K、3K、4K、5Khz的混频信号要求3KHz信号顺利通过而过滤其他频率信号。
思路
1、设计该滤波器采样频率应该为信号最高频率的2倍以上我设计的采样频率为40khz采用凯赛窗设计FIR带通滤波器通过matlab仿真得到该滤波器的幅频响应 该滤波器在2KHz处的衰减将近60dB在1K、4K、5KHz处的衰减也达到了40dB,基本符合设计要求但为了达到这样的效果该滤波器的长度被我增加到了64阶数为63故它的成本较高。
Matlab代码如下
fs 40*10^3;
N 64;
window kaiser(N);
fp [2400*2/fs 3600*2/fs];
b fir1(N-1,fp,bandpass,window);
2、使用FPGA产生测试信号使用quartus Ⅱ软件的NCO ip核可以产生不同频率的正弦波信号下面以1KHz正弦波为例 相位累加器为32位宽角度分辨率位宽16位幅度位宽10位输入时钟为板载时钟50M输出1KHz的正弦信号完成配置后生成ip核实例化后产生1Khz的正弦波信号代码如下
wire signed [9:0] sin_1k;
nco nco_inst1
(.out_valid(),.fsin_o(sin_1k),.phi_inc_i(32d85_899),.reset_n(1b1),.clken(1b1),.clk(sys_clk)
);
生成的波形如下 3、verilog代码中采用全串行结构设计FIR滤波器由于matlab设计出的FIR滤波器一定是线性相位结构并且具有对称性故可采用以下结构图设计滤波器 采样率为40KHz故数据输入频率为40KHz则滤波器时钟CLK为1.28MHz该时钟可通过由PLL ip核产生。由于滤波器系数的对称性故只需要对32个滤波器系数与输入数据进行累加乘运算就可以实现滤波功能 为了实现该算法首先需要生成一个乘法器ip核完成乘法运算配置如下 该乘法器输入位宽分别为14bit和12bit并且为有符号型例化该乘法器将加和数据与滤波器系数输入获得一次乘法输出代码如下
mult mult_inst
(.clock ( clk ),.dataa (dataa),.datab ( datab ),.result ( Mout )
);
结构图所示的是一个15阶的全串行FIR滤波器结构而我设计的滤波器为63阶虽然阶数不同但核心的算法相同。由于数据输入频率为40KHz故滤波器时钟频率应该为40KHz * 32 1.28MHz这样才能保证在输入一个新数据前完成32次乘运算也就是输出一个y(n)。具体算法如下
首先产生一个周期为32的计数器count每一个CLK上升沿到来count自增1故每当count归0相当于时间经过了40KHz。
verilog代码如下
reg [4:0] count;
always(posedge clk or negedge sys_rst)if(sys_rst 1b0)count 5d0;elsecount count 1b1; 然后将新输入的数据保存到寄存器中这里采用了移位寄存器保存64个对称的数据verilog代码如下
reg signed [12:0] xin_reg[0:63];
reg [5:0]i,j;
always(posedge clk or negedge sys_rst)if(sys_rst 1b0)beginfor(i0;i63;ii1)xin_reg[i] 13d0;endelsebeginif(count 5d31)beginfor(j0;j63;jj1)xin_reg[j1] xin_reg[j];xin_reg[0] xin;endend
这里定义了64给个有符号的13位寄存器分别存储输入的数据。 接着完成两个对称数据相加例如x(n)x(n-63)… 并且将其结果送入乘法器同时乘法器另一个乘数端口送入对应的滤波器系数例如h(0)… 由于代码过长这里只展示部分其他同理verilog代码如下
always(posedge clk or negedge sys_rst)if(sys_rst 1b0)beginadda 13d0;addb 13d0;datab 12d0;endelsebeginif(count 5d0)beginadda {xin_reg[0][12],xin_reg[0]};addb {xin_reg[63][12],xin_reg[63]};datab -12d74;end………endassign dataa adda addb;
至此完成了一次乘法器的输出而滤波器的输出是由32个类似的输出累加得到由于乘法器的输入位宽分别为14bit和12bit故输出位宽为26bit对32个输出累加的话需要扩展5位故滤波器输出为31bit的有符号数verilog代码如下
reg signed [30:0] sum;
reg signed [30:0] Yout;
always(posedge clk or negedge sys_rst)if(sys_rst 1b0)beginsum 31d0;Yout 31d0;endelseif(count 5d2)beginYout sum;sum Mout;endelsesum sum Mout;assign out Yout;
需要说明的是因为在count 0时给两个加数赋值和给滤波器系数赋值而真正获得新的数据是在count 1时故在count 1时将两个乘数送入乘法器而我配置的乘法器有一级流水线所以乘法器输出在count 2的时候通过以上分析可以明白为什么在count 2时才会将乘法器输出Mout送给sum而其他时刻是进行累加运算至于何时将累加和送给输出呢同理由于count的周期为32所以从count 2 到count 31 到 count 0 再到count 1刚好完成一个周期也就是32次累加乘运算所以在count 2时(注意D触发器的延时当count 2时此时的sum为count 1时的sum加上count 1时的Mout所以仍然是32个数据的求和而不是33个数据之和)将滤波数据送出应该特别注意上面括号中的分析可以对比波形理解触发器的延时特性。 最后编写板载测试文件将滤波器的输出(有符号的31位数据)转换为DA模块的8位无符号DA数据然后将DA模块时钟和8位数据送到模块中完成板载输出测试verilog代码如下
module boardtst
(input wire sys_clk ,input wire sys_rst ,output wire [7:0] DA ,output wire DA_clk
);wire signed [30:0] yout;
fullserial_filter u3
(.clk (clk_1p28M) ,.sys_rst (sys_rst) ,.xin (sin_wave) , .out (yout)
);
assign DA yout[30:23] 8d128;
assign DA_clk sys_clk;
这里要注意的是有符号数据如何转化成无符号数据因为滤波器输出为31位的有符号输出而DA模块接收的是8位的无符号型故应该截取高8位这相当于将数据右移了23位然后再加上128于是完成有符号到无符号的转换。
下面是测试信号与滤波后的信号
测试信号 滤波后输出信号 可以看到虽然将3KHz的信号分离了出来但波形并不平滑这是由于采样速率和转换频率较低造成的。
需要补充的是滤波器系数的量化位宽会影响到滤波器的性能通过matlab仿真观察 可以看出与未量化相比8bit量化已经很好地满足了滤波器的性能要求故使用FPGA设计该滤波器时将乘法器的输入设置成14bit与8bit就已经足够了。
Matlab代码如下
b8 round(b/max(abs(b))*(2^7-1));
b12 round(b/max(abs(b))*(2^11-1));
b14 round(b/max(abs(b))*(2^13-1));pm 20*log10(abs(fft(b,1024)));pm pm - max(pm);
pm8 20*log10(abs(fft(b8,1024)));pm8 pm8 - max(pm8);
pm1220*log10(abs(fft(b12,1024)));pm12pm12-max(pm12;
pm1420*log10(abs(fft(b14,1024)));pm14pm14-max(pm14;x_f [0:fs/length(pm):fs/2];mfpm pm(1:length(x_f));
mfpm8 pm8(1:length(x_f));
mfpm12 pm12(1:length(x_f));
mfpm14 pm14(1:length(x_f));plot(x_f,mfpm,-,x_f,mfpm8,.-,x_f,mfpm12,x,x_f,mfpm14,--);
xlabel(hz);ylabel(db);
legend(未量化,8比特量化,12比特量化,14比特量化);
grid;
至此完成了设计目标但该实验仍有很多不足敬请大家批评指正 参考文献
[1] 夏宇闻.Verilog数字系统设计教程(第三版).北京北京航空航天大学出版社2013
[2] 杜勇.数字滤波器的MATLAB与FPGA实现——Altera/Verilog版第二版.北京电子工业出版社2019