基于FPGA的FIR滤波器设计
一、MATLAB滤波器工具介绍
二、设计实例
三、编程思路
四、仿真结果
五、程序
1 //============================================================= 2 // 3 // ---Author: 橘子哥哥 4 // ---QQ : 1073273114 5 // ---Wechat: 15870894502 6 // ---create:2022-04-26 10:53:12 7 // 8 //============================================================= 9 `define COE_NUM 68 10 `define DAT_WIDTH 16 11 `define COE_WIDTH 20 12 module fir_filter( 13 input wire clk, 14 input wire rst_n, 15 input wire filter_vld, 16 input wire [`DAT_WIDTH-1:0] in_dat, 17 output wire [`DAT_WIDTH-1:0] out_dat 18 ); 19 20 //*********************************假设这里是奇数阶,也就是有偶数个抽头系数,并且这偶数个抽头系数是对称的*********************************// 21 //因为抽头系数多为小数,所以这里的抽头系数是乘以了1_048_576,最后将结果右移20位就得到正确结果了 22 reg [`DAT_WIDTH-1:0] in_reg [`COE_NUM-1:0]; //暂存输入待滤波处理的数据 23 wire [`COE_WIDTH-1:0] coe_reg [`COE_NUM/2-1:0]; //存放抽头系数 24 wire [`COE_NUM/2-1:0] coe_reg_sign; //存放抽头系数的符号位 25 wire [`DAT_WIDTH+`COE_WIDTH-1:0] coe_x_indat [`COE_NUM/2-1:0]; //存放x(n)*h(n)的结果 26 wire [`DAT_WIDTH+`COE_WIDTH-1:0] coe_x_indat_sign [`COE_NUM/2-1:0]; //将x(n)*h(n)的结果根据h(n)的符号加上正负号 27 28 wire [`DAT_WIDTH+`COE_WIDTH+`COE_NUM/2-1:0] out_dat_pre;//存放卷积的结果,还要右移20位 29 30 //***************************设置抽头系数***************************// 31 assign coe_reg[0]='d690; 32 assign coe_reg_sign[0]=0; 33 34 assign coe_reg[1]='d729; 35 assign coe_reg_sign[1]=1; 36 37 assign coe_reg[2]='d0; 38 assign coe_reg_sign[2]=0; 39 40 assign coe_reg[3]='d929; 41 assign coe_reg_sign[3]=0; 42 43 assign coe_reg[4]='d1097; 44 assign coe_reg_sign[4]=1; 45 46 assign coe_reg[5]='d0; 47 assign coe_reg_sign[5]=0; 48 49 assign coe_reg[6]='d1585; 50 assign coe_reg_sign[6]=0; 51 52 assign coe_reg[7]='d1914; 53 assign coe_reg_sign[7]=1; 54 55 assign coe_reg[8]='d0; 56 assign coe_reg_sign[8]=0; 57 58 assign coe_reg[9]='d2763; 59 assign coe_reg_sign[9]=0; 60 61 assign coe_reg[10]='d3293; 62 assign coe_reg_sign[10]=1; 63 64 assign coe_reg[11]='d0; 65 assign coe_reg_sign[11]=0; 66 67 assign coe_reg[12]='d4593; 68 assign coe_reg_sign[12]=0; 69 70 assign coe_reg[13]='d5377; 71 assign coe_reg_sign[13]=1; 72 73 assign coe_reg[14]='d0; 74 assign coe_reg_sign[14]=0; 75 76 assign coe_reg[15]='d7259; 77 assign coe_reg_sign[15]=0; 78 79 assign coe_reg[16]='d8381; 80 assign coe_reg_sign[16]=1; 81 82 assign coe_reg[17]='d0; 83 assign coe_reg_sign[17]=0; 84 85 assign coe_reg[18]='d11068; 86 assign coe_reg_sign[18]=0; 87 88 assign coe_reg[19]='d12680; 89 assign coe_reg_sign[19]=1; 90 91 assign coe_reg[20]='d0; 92 assign coe_reg_sign[20]=0; 93 94 assign coe_reg[21]='d16608; 95 assign coe_reg_sign[21]=0; 96 97 assign coe_reg[22]='d19030; 98 assign coe_reg_sign[22]=1; 99 100 assign coe_reg[23]='d0; 101 assign coe_reg_sign[23]=0; 102 103 assign coe_reg[24]='d25219; 104 assign coe_reg_sign[24]=0; 105 106 assign coe_reg[25]='d290281; 107 assign coe_reg_sign[25]=1; 108 109 assign coe_reg[26]='d0; 110 assign coe_reg_sign[26]=0; 111 112 assign coe_reg[27]='d40768; 113 assign coe_reg_sign[27]=0; 114 115 assign coe_reg[28]='d49389; 116 assign coe_reg_sign[28]=1; 117 118 assign coe_reg[29]='d0; 119 assign coe_reg_sign[29]=0; 120 121 assign coe_reg[30]='d80524; 122 assign coe_reg_sign[30]=0; 123 124 assign coe_reg[31]='d114117; 125 assign coe_reg_sign[31]=1; 126 127 assign coe_reg[32]='d0; 128 assign coe_reg_sign[32]=0; 129 130 assign coe_reg[33]='d577569; 131 assign coe_reg_sign[33]=0; 132 133 134 135 136 assign out_dat=out_dat_pre>>20; //右移20位取得滤波后的结果 137 138 always@(posedge clk or negedge rst_n) 139 if(!rst_n) 140 begin 141 in_reg[0]<='d0; 142 end 143 else if(filter_vld) 144 begin 145 in_reg[0]<=in_dat; 146 end 147 else 148 begin 149 in_reg[0]<='d0; 150 end 151 152 //将输出的值进行移位操作 153 genvar i; 154 generate 155 for(i=1;i<`COE_NUM;i=i+1) 156 begin : xnshift 157 always@(posedge clk or negedge rst_n) 158 if(!rst_n) 159 begin 160 in_reg[i]<='d0; 161 end 162 else if(filter_vld) 163 begin 164 in_reg[i]<=in_reg[i-1]; 165 end 166 else 167 begin 168 in_reg[i]<='d0; 169 end 170 end 171 endgenerate 172 173 //例化乘法器,因为抽头系数存在对称性,所以只需要一半的乘法器 174 genvar j; 175 generate 176 for(j=0;j<`COE_NUM/2;j=j+1) 177 begin : mul_ope 178 mul_16bx20b inst_mul_16bx20b ( 179 .CLK(clk), // input wire CLK 180 .A(in_reg[j]+in_reg[`COE_NUM-1-j]), // input wire [15 : 0] A 181 .B(coe_reg[j]), // input wire [19 : 0] B 182 .P(coe_x_indat[j]) // output wire [35 : 0] P 183 ); 184 end 185 endgenerate 186 187 //将乘法器的结果加上符号位 188 genvar k; 189 generate 190 for(k=0;k<`COE_NUM/2;k=k+1) 191 begin : mul_sign 192 assign coe_x_indat_sign[k]=coe_reg_sign[k]?(~coe_x_indat[k]+1):coe_x_indat[k]; 193 end 194 endgenerate 195 196 //累加和 197 assign out_dat_pre=coe_x_indat_sign[0] 198 +coe_x_indat_sign[1] 199 +coe_x_indat_sign[2] 200 +coe_x_indat_sign[3] 201 +coe_x_indat_sign[4] 202 +coe_x_indat_sign[5] 203 +coe_x_indat_sign[6] 204 +coe_x_indat_sign[7] 205 +coe_x_indat_sign[8] 206 +coe_x_indat_sign[9] 207 +coe_x_indat_sign[10] 208 +coe_x_indat_sign[11] 209 +coe_x_indat_sign[12] 210 +coe_x_indat_sign[13] 211 +coe_x_indat_sign[14] 212 +coe_x_indat_sign[15] 213 +coe_x_indat_sign[16] 214 +coe_x_indat_sign[17] 215 +coe_x_indat_sign[18] 216 +coe_x_indat_sign[19] 217 +coe_x_indat_sign[20] 218 +coe_x_indat_sign[21] 219 +coe_x_indat_sign[22] 220 +coe_x_indat_sign[23] 221 +coe_x_indat_sign[24] 222 +coe_x_indat_sign[25] 223 +coe_x_indat_sign[26] 224 +coe_x_indat_sign[27] 225 +coe_x_indat_sign[28] 226 +coe_x_indat_sign[29] 227 +coe_x_indat_sign[30] 228 +coe_x_indat_sign[31] 229 +coe_x_indat_sign[32] 230 +coe_x_indat_sign[33]; 231 232 233 endmodule