FIR滤波器代码及仿真设计

上文 fpga数字信号处理之滤波器2_使用dsp48e1的fir滤波器设计完成了结构设计:
根据这一结构,假定要设计一个满速率的fir滤波器,滤波器系数为:[3,13,27,58,62,204,47,546,233,1465,3260,3260,1465,233,546,47,204,62,58,27,13,3],滤波器总共22个系数,对称结构,所以有效系数11个。
以输入数据为自加数为例,根据结构可以得到数据摆放格式如下,clk0时刻的计算公式为:(500+521)*c0+(501+520)*c1+......+(510+511)*c10;clk1时刻的计算公式为:(501+522)*c0+(502+521)*c1+......+(511+512)*c10;....
据此,设计fir代码如下:
代码设置三个参数,数据位宽、系数个数、系数增益,其中系数个数决定代码中乘法器的个数及代码的处理时延,系数增益是系数给数据带来的增益,在数据输出的时候要通过截位截掉。
// ============================================================// file name: cm_fir_top// version : v1.0// data : 2023/3/4// author : fpga干货分享// ============================================================// 功能:fir滤波器代码// coef = // delay : 4+c_coef_num*2// ============================================================`timescale 1ns/100psmodule cm_fir_top #( parameter c_data_width = 16 , parameter c_coef_num = 11 , ///有效系数个数 parameter c_coef_cut_num = 12 ) ///四舍五入使用的0.5大小( input wire i_sys_clk , /// 工作时钟 input wire i_rst_in , /// 复位 input wire [c_data_width-1:0] i_data_in , /// 数据输入 output reg [c_data_width-1:0] o_data_out /// 数据输出);// ============================================================// 内部参数// ============================================================localparam c_coef_05 = 2**c_coef_cut_num ;// ============================================================// 变量// ============================================================reg [c_data_width-1:0] s_data_in[c_coef_num*2-1:0] ;wire [17:0] s_coef[c_coef_num-1:0] ;wire [47:0] s_pcout[c_coef_num-1:0] ;wire [47:0] s_dsp_out[c_coef_num-1:0] ;然后就是主代码,使用assign给系数赋值,然后根据系数个数缓存输入数据,用于fir滤波器的卷积操作。随后例化第一个dsp,u0_cm_dsp48e1,该滤波器作为级联滤波器组的开头乘法器,没有级联输入,但是使用c端口作为假四舍五入预加的输入,随后使用generate根据滤波器系数个数生成级联dsp组,最后将最后一级滤波器的输出进行截位,得到最终结果。
// ============================================================// main code// ============================================================assign s_coef[0 ] = 18'd3 ;assign s_coef[1 ] = 18'd13 ;assign s_coef[2 ] = -18'd27 ;assign s_coef[3 ] = -18'd58 ;assign s_coef[4 ] = 18'd62 ;assign s_coef[5 ] = 18'd204 ;assign s_coef[6 ] = -18'd47 ;assign s_coef[7 ] = -18'd546 ;assign s_coef[8 ] = -18'd233 ;assign s_coef[9 ] = 18'd1465 ;assign s_coef[10] = 18'd3260 ;always@(posedge i_sys_clk) s_data_in[0] <= i_data_in ;genvar i;generate for(i=1;i< c_coef_num*2;i=i+1) begin always@(posedge i_sys_clk) s_data_in[i] <= s_data_in[i-1]; endendgeneratecm_dsp48e1 #( .c_data_with_a (c_data_width ), .c_data_with_b (18 ), .c_data_with_c (32 ), .c_data_with_d (c_data_width ))u0_cm_dsp48e1( .i_clk (i_sys_clk ) , // clk .i_rst (i_rst_in ) , // rst .i_a (s_data_in[0] ) , // [29:0] .i_b (s_coef[0 ] ) , // [17:0] .i_c (c_coef_05 ) , // [47:0] .i_d (s_data_in[c_coef_num*2-1] ) , // [24:0] .i_pcin (48'd0 ) , // [47:0] 只能直连pcout .i_alumode (4'd0 ) , // [3:0] .i_inmode (5'b00101 ) , // [4:0] .i_opmode (7'b0110101 ) , // [6:0] c + (a+d)*b .o_p ( ) , // [47:0] .o_pcout (s_pcout[0] ) // [47:0] 只能直连pcin );genvar j;generate for(j=1;j< c_coef_num;j=j+1) begin cm_dsp48e1 #( .c_data_with_a (c_data_width ), .c_data_with_b (18 ), .c_data_with_c (32 ), .c_data_with_d (c_data_width ) ) u1_cm_dsp48e1( .i_clk (i_sys_clk ) , // clk .i_rst (i_rst_in ) , // rst .i_a (s_data_in[2*j] ) , // [29:0] .i_b (s_coef[j ] ) , // [17:0] .i_c (32'd0 ) , // [47:0] .i_d (s_data_in[c_coef_num*2-1] ) , // [24:0] .i_pcin (s_pcout[j-1] ) , // [47:0] 只能直连pcout .i_alumode (4'd0 ) , // [3:0] .i_inmode (5'b00101 ) , // [4:0] .i_opmode (7'b0010101 ) , // [6:0] pcin + (a+d)*b .o_p (s_dsp_out[j] ) , // [47:0] .o_pcout (s_pcout[j] ) // [47:0] 只能直连pcin ); endendgeneratealways@(posedge i_sys_clk) o_data_out <= s_dsp_out[c_coef_num-1][c_coef_cut_num+1+:c_data_width] ;endmodule仿真tb如下,可使用自加数或者单音作为输入:
// ============================================================// file name: cm_fir_top// version : v1.0// data : 2023/3/4// author : fpga干货分享// ============================================================// 功能:fir滤波器代码// delay : 20clk// ============================================================`timescale 1ns/100psmodule tb_cm_fir_top ; parameter c_data_width = 16 ; parameter c_coef_num = 11 ; ///有效系数个数 parameter c_coef_cut_num = 12 ; ///四舍五入使用的0.5大小 reg i_sys_clk ; /// 工作时钟 reg i_rst_in ; /// 复位 reg [c_data_width-1:0] i_data_in ; /// 数据输入 wire [c_data_width-1:0] o_data_out ; /// 数据输出,从start开始连续输出,位宽按照最大能力输出 reg [31:0] s_clk_cnt ;initial begin i_sys_clk = 'd1; i_rst_in = 'd1; i_data_in = 'd0; s_clk_cnt = 'd0; #1000; i_rst_in = 'd0; endalways #1 i_sys_clk = ~i_sys_clk;always @(posedge i_sys_clk) s_clk_cnt <= s_clk_cnt + 'd1;/// 自加数always @(posedge i_sys_clk) i_data_in <= i_data_in + 'd1;///单音// always @(posedge i_sys_clk) // i_data_in <= $sin(2*3.14*s_clk_cnt/512)*8192;cm_fir_top #( .c_data_width ( c_data_width ) , .c_coef_num ( c_coef_num ) , ///有效系数个数 .c_coef_cut_num ( c_coef_cut_num ) ) ///四舍五入使用的0.5大小cm_fir_top( .i_sys_clk ( i_sys_clk ) , /// 工作时钟 .i_rst_in ( i_rst_in ) , /// 复位 .i_data_in ( i_data_in ) , /// 数据输入 .o_data_out ( o_data_out ) /// 数据输出,从start开始连续输出,位宽按照最大能力输出);endmodule使用自加数仿真对数如下:
输入输出:
dsp输入数据摆放:
python或者excel计算的结果:
使用单音仿真结果如下:

仪表放大器运放CLC1200与AD620参数的对比
在设计阶段降低组装成本的10种故障安全方法
中国终端厂商能否在今年抓住新的发展机遇进行翻身
AD19如何使用强大的自动布线功能
航母下水,大飞机起飞:我们的征途是星辰大海
FIR滤波器代码及仿真设计
工业机器人多样化需求的阻碍
5G建设促进集成电路进口迅猛增长,Q1季度湖南进口额达41.4亿人民币
黑磷电化学制备及其储能应用领域获新突破
R课堂 | DC-DC转换器实机验证
三极管放大电路的常见分析方法
GaN晶体管与其驱动器的封装集成消除了共源电感
与其畏惧人工智能还不如做到自我约束
MCS51单片机的排序程序(ASM源代码)
RIGOL DG4000系列函数/任意波形发生器家族增添新成员
2022年半导体硅片行业研究报告
国内智能汽车产业发展面临三方面挑战
全球显微镜市场规模将进一步扩大,市场规模已经达24亿美元
200万招聘博士,意欲何为?
英飞凌IGBT模块封装