基于FPGA的IIR滤波器
基于FPGA的IIR滤波器
by方阳
版权声明:本文为博主原创文章,转载请指明转载地址
http://www.cnblogs.com/fydeblog/p/6748998.html
1.说明
写了那么多数字图像处理的,再写点其他的吧,今天写点FPGA的东西,是之前EDA做的综合大实验,拿出来和大家分享分享!
先说一下,此篇文章是基于你有IIR滤波器的原理和FPGA语言(也就是Verilog HDL)基础上的!至于IIR滤波器的原理和Verilog HDL语言,我这里就不说了,网上有一大堆的资料可以观看,IIR可以看数字信号处理的书或直接百度,Verilog HDL推荐《Hello,FPGA》!
申明一下,这边博客很长,请做好心理准备!!!
要感谢的人:感谢电子发烧网的牛哥哥要炸天的指导,感谢小梅哥的指导,感谢Hello FPGA团队的书籍!!!感谢,感谢,感谢!!!
说明:这个IIR滤波器我是用小梅哥的芯航线FPGA开发板——cyclone IV E EP4CE10F1708实现的,还用了他的ADDA模块——集成TLC1544 ADC采集芯片和TLC5620 DAC 输出芯片,软件平台是quartus13.0,测试用的是信号发生器和示波器。
这个共有一个顶层文件,十一个子文件,子文件其中一个是IIR滤波器的顶层文件。拓扑图如下:
2.参考代码
相应的代码如下
2.1 顶层文件
IIR_FY_TOP.V
module IIR_FY_TOP ( Clk, Rst_n, TLC5620_CLK, TLC5620_DATA, TLC5620_LOAD, TLC5620_LDAC, TLV1544_SDO, TLV1544_SDI, TLV1544_SCLK, TLV1544_NCS, TLV1544_FS, TLV1544_EOC ); input Clk; input Rst_n; output TLC5620_CLK; output TLC5620_DATA; output TLC5620_LOAD; output TLC5620_LDAC; input TLV1544_SDO; output TLV1544_SDI; output TLV1544_SCLK; output TLV1544_NCS; output TLV1544_FS; input TLV1544_EOC; wire AD_DONE; wire [9:0]ADC_DATA; wire DATA_Valid; wire [10:0]CtrlWord; wire signed[15:0] din; wire signed[15:0] dout; TLV1544_CTRL TLV1544_CTRL0( .Clk(Clk), .Rst_n(Rst_n), .Do_Conv(1'b1), //开始转换使能信号 .AD_DONE(AD_DONE), //转换完成信号 .ADC_CHSEL(4'b0), //通道选择 .ADC_DATA(ADC_DATA), //采样结果 .DATA_Valid(DATA_Valid), .TLV1544_SDO(TLV1544_SDO), .TLV1544_SDI(TLV1544_SDI), .TLV1544_SCLK(TLV1544_SCLK), .TLV1544_NCS(TLV1544_NCS), .TLV1544_FS(TLV1544_FS), .TLV1544_EOC(TLV1544_EOC) ); ADC_to_filter ADC_to_filter0( .ADC_DATA(ADC_DATA), .din(din) ); myiir myiir0( .rst(Rst_n), .clk(Clk), .din(din), .dout(dout), .din_valid(DATA_Valid), .dout_valid() ); filter_to_DAC filter_to_DAC0( .dout(dout), .CtrlWord(CtrlWord) ); TLC5620_CTRL TLC5620_CTRL0( .Clk(Clk), .Rst_n(Rst_n), .UpdateReq(1'b1), .CtrlWord(CtrlWord), .UpdateDone(), .TLC5620_CLK(TLC5620_CLK), .TLC5620_DATA(TLC5620_DATA), .TLC5620_LOAD(TLC5620_LOAD), .TLC5620_LDAC(TLC5620_LDAC) ); endmodule
2.2 TLV1544驱动
TLV1544_CTRL.V
module TLV1544_CTRL( Clk, Rst_n, Do_Conv, //开始转换使能信号 AD_DONE, //转换完成信号 ADC_CHSEL, //通道选择 ADC_DATA, //采样结果 DATA_Valid, TLV1544_SDO, TLV1544_SDI, TLV1544_SCLK, TLV1544_NCS, TLV1544_FS, TLV1544_EOC ); input Clk; input Rst_n; input Do_Conv; //开始转换使能信号 input [3:0]ADC_CHSEL; //通道选择 output reg [9:0]ADC_DATA; //采样结果 output reg AD_DONE; //转换完成信号 output reg DATA_Valid; input TLV1544_SDO; input TLV1544_EOC; output reg TLV1544_SDI; output reg TLV1544_SCLK; output reg TLV1544_NCS; output wire TLV1544_FS; assign TLV1544_FS = 1'b1; reg [7:0] LSM_CNT;//序列计数器 reg [9:0] rADC_DATA; always@(posedge Clk or negedge Rst_n) if(!Rst_n) LSM_CNT <= 8'd0; else if(LSM_CNT <204 && (TLV1544_EOC == 1'b1) && (Do_Conv || LSM_CNT > 8'd0)) LSM_CNT <= LSM_CNT + 1'b1; else if(LSM_CNT < 204 && (TLV1544_EOC == 1'b0)) LSM_CNT <= LSM_CNT; else if(LSM_CNT == 204 && (TLV1544_EOC == 1'b1)) LSM_CNT <= 8'd0; always@(posedge Clk or negedge Rst_n) if(!Rst_n)begin rADC_DATA <= 10'd0; TLV1544_SDI <= 1'b0; TLV1544_SCLK <= 1'b0; TLV1544_NCS <= 1'b1; AD_DONE <= 1'b0; DATA_Valid <= 1'b0; ADC_DATA <= 10'd0; end else begin case(LSM_CNT) 0: begin rADC_DATA <= 10'd0; TLV1544_SDI <= 1'b0; TLV1544_SCLK <= 1'b0; TLV1544_NCS <= 1'b1; AD_DONE <= 1'b0; end 1: begin TLV1544_NCS <= 1'b0; TLV1544_SDI <= ADC_CHSEL[3]; end 9: begin TLV1544_SCLK <= 1'b1; rADC_DATA[9] <= TLV1544_SDO; end 19: begin TLV1544_SDI <= ADC_CHSEL[2]; TLV1544_SCLK <= 1'b0; end 29: begin TLV1544_SCLK <= 1'b1; rADC_DATA[8] <= TLV1544_SDO; end 39: begin TLV1544_SDI <= ADC_CHSEL[1]; TLV1544_SCLK <= 1'b0; end 49: begin TLV1544_SCLK <= 1'b1; rADC_DATA[7] <= TLV1544_SDO; end 59: begin TLV1544_SDI <= ADC_CHSEL[0]; TLV1544_SCLK <= 1'b0; end 69: begin TLV1544_SCLK <= 1'b1; rADC_DATA[6] <= TLV1544_SDO; end 79:TLV1544_SCLK <= 1'b0; 89: begin TLV1544_SCLK <= 1'b1; rADC_DATA[5] <= TLV1544_SDO; end 99:TLV1544_SCLK <= 1'b0; 109: begin TLV1544_SCLK <= 1'b1; rADC_DATA[4] <= TLV1544_SDO; end 119:TLV1544_SCLK <= 1'b0; 129: begin TLV1544_SCLK <= 1'b1; rADC_DATA[3] <= TLV1544_SDO; end 139:TLV1544_SCLK <= 1'b0; 149: begin TLV1544_SCLK <= 1'b1; rADC_DATA[2] <= TLV1544_SDO; end 159:TLV1544_SCLK <= 1'b0; 169: begin TLV1544_SCLK <= 1'b1; rADC_DATA[1] <= TLV1544_SDO; end 179:TLV1544_SCLK <= 1'b0; 189: begin TLV1544_SCLK <= 1'b1; //rADC_DATA[0] <= TLV1544_SDO; if(TLV1544_EOC) DATA_Valid <= 1'b1; else DATA_Valid <= 1'b0; ADC_DATA <= {rADC_DATA[9:1],TLV1544_SDO}; end 199: begin TLV1544_SCLK <= 1'b0; TLV1544_NCS <= 1'b1; end 204:AD_DONE <= 1'b1; default:DATA_Valid <= 1'b0; endcase end endmodule
2.3 ADC转filter模块
ADC_to_filter.V
module ADC_to_filter ( ADC_DATA, din ); input [9:0]ADC_DATA; output signed[15:0]din; assign din = ADC_DATA<<6; endmodule
2.4 myiir模块
myiir.V
module myiir( rst, clk, din, dout, din_valid, dout_valid, ); input rst; input clk; input signed[15:0] din; input din_valid; output reg signed[15:0] dout; output reg dout_valid; wire signed[15:0] dout1; wire signed[15:0] dout2; wire signed[15:0] dout3; wire signed[15:0] dout4; wire signed[15:0] dout5; wire signed[15:0] dout_reg; wire din_valid1; wire dout_valid1; wire din_valid2; wire dout_valid2; wire din_valid3; wire dout_valid3; wire din_valid4; wire dout_valid4; wire din_valid5; wire dout_valid5; wire din_valid6; wire dout_valid6; assign din_valid1=din_valid; assign din_valid2=dout_valid1; assign din_valid3=dout_valid2; assign din_valid4=dout_valid3; assign din_valid5=dout_valid4; assign din_valid6=dout_valid5; //assign dout_prevalid=dout_valid1; myiir_first_step U1( .rst(rst), .clk(clk), .din(din), .dout(dout1), .din_valid(din_valid1), .dout_valid(dout_valid1) ); myiir_second_step U2( .rst(rst), .clk(clk), .din(dout1), .dout(dout2), .din_valid(din_valid2), .dout_valid(dout_valid2) ); myiir_third_step U3( .rst(rst), .clk(clk), .din(dout2), .dout(dout3), .din_valid(din_valid3), .dout_valid(dout_valid3) ); myiir_fourth_step U4( .rst(rst), .clk(clk), .din(dout3), .dout(dout4), .din_valid(din_valid4), .dout_valid(dout_valid4) ); myiir_fifth_step U5( .rst(rst), .clk(clk), .din(dout4), .dout(dout5), .din_valid(din_valid5), .dout_valid(dout_valid5) ); myiir_sixth_step U6( .rst(rst), .clk(clk), .din(dout5), .dout(dout_reg), .din_valid(din_valid6), .dout_valid(dout_valid6) ); always @(negedge rst,posedge clk) begin if(!rst) begin dout<=16'd0; dout_valid=1'b0; end else if(dout_valid6) begin dout_valid=1'b1; dout<=dout_reg; end else begin dout<=dout; dout_valid=1'b0; end end endmodule
2.5 filter转DAC模块
filter_to_DAC.V
module filter_to_DAC ( dout, CtrlWord ); input signed[15:0] dout; output [10:0]CtrlWord; assign CtrlWord[7:0]=dout[7:0]; assign CtrlWord[10:8]=3'b0; endmodule
2.6 TLC5620驱动
TLC5620_CTRL.V
module TLC5620_CTRL( Clk, Rst_n, UpdateReq, CtrlWord, UpdateDone, TLC5620_CLK, TLC5620_DATA, TLC5620_LOAD, TLC5620_LDAC ); input Clk; input Rst_n; input UpdateReq; input [10:0]CtrlWord; output reg UpdateDone; output reg TLC5620_CLK; output reg TLC5620_DATA; output reg TLC5620_LOAD; output reg TLC5620_LDAC; reg [9:0] Cnt; always@(posedge Clk or negedge Rst_n) if(!Rst_n) Cnt <= 10'd0; else if(UpdateReq == 1 | (Cnt != 10'd0))begin if(Cnt == 10'd820) Cnt <= 10'd0; else Cnt <= Cnt + 10'd1; end else Cnt <= 10'd0; always@(posedge Clk or negedge Rst_n) if(!Rst_n)begin TLC5620_CLK <= 1'b0; TLC5620_DATA <= 1'b0; TLC5620_LOAD <= 1'b0; TLC5620_LDAC <= 1'b0; UpdateDone <= 1'b0; end else begin case(Cnt) 0: begin TLC5620_CLK <= 1'b0; TLC5620_DATA <= 1'b0; TLC5620_LOAD <= 1'b1; TLC5620_LDAC <= 1'b0; UpdateDone <= 1'b0; end 10: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[10]; end 40: TLC5620_CLK <= 1'b0; 70: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[9]; end 100: TLC5620_CLK <= 1'b0; 130: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[8]; end 160: TLC5620_CLK <= 1'b0; 190: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[7]; end 220: TLC5620_CLK <= 1'b0; 250: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[6]; end 280: TLC5620_CLK <= 1'b0; 310: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[5]; end 340: TLC5620_CLK <= 1'b0; 370: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[4]; end 400: TLC5620_CLK <= 1'b0; 430: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[3]; end 460: TLC5620_CLK <= 1'b0; 490: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[2]; end 520: TLC5620_CLK <= 1'b0; 550: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[1]; end 580: TLC5620_CLK <= 1'b0; 610: begin TLC5620_CLK <= 1'b1; TLC5620_DATA <= CtrlWord[0]; end 640: TLC5620_CLK <= 1'b0; 670:TLC5620_LOAD <= 1'b0; 800:TLC5620_LOAD <= 1'b1; 820:UpdateDone <= 1'b1; default:; endcase end endmodule
2.7 myiir_first_step模块
myiir_first_step.V
module myiir_first_step( rst, clk, din, dout, din_valid, dout_valid ); parameter b0=16145; parameter b1=-23383; parameter b2=16145; parameter a1=-26283; parameter a2=14526; input rst; input clk; input signed[15:0] din; input din_valid; output signed[15:0] dout; output dout_valid; reg[4:0] cState,nState; reg signed[15:0] x_reg0; reg signed[15:0] x_reg1; reg signed[31:0] x_mul1; reg signed[31:0] x_mul2; reg signed[31:0] x_mul3; wire signed[15:0] x_int_mul1; wire signed[15:0] x_int_mul2; wire signed[15:0] x_int_mul3; reg signed[17:0] x_sum; wire signed[15:0] x_temp; reg signed[15:0] y_reg0; reg signed[15:0] y_reg1; reg signed[31:0] y_mul1; reg signed[31:0] y_mul2; wire signed[15:0] y_int_mul1; wire signed[15:0] y_int_mul2; reg signed[16:0] y_sum; wire signed[15:0] y_temp; reg signed[16:0] dout_sum; wire signed[15:0] dout_temp; always @(negedge rst,posedge clk) begin if(!rst) begin cState<=0; end else begin cState<=nState; end end always @(*) begin case(cState) 0:if(din_valid) begin nState<=1; end else begin nState<=0; end 1:nState<=2; 2:nState<=3; 3:nState<=4; 4:nState<=5; 5:nState<=6; 6:nState<=0; default:nState<=nState; endcase end always @(*) begin if(rst) begin case(cState) 1:x_mul1=b0*din; 2:begin x_mul2=b1*x_reg0; y_mul1=a1*y_reg0; end 3:begin x_mul3=b2*x_reg1; y_mul2=a2*y_reg1; end 4:begin x_sum=x_int_mul1+x_int_mul2+x_int_mul3; y_sum=y_int_mul1+y_int_mul2; end 5:dout_sum=x_temp-y_temp; default:; endcase end end always @(cState) begin if(rst) begin if(cState==4) begin x_reg0<=din; x_reg1<=x_reg0; end else begin x_reg0<=x_reg0; x_reg1<=x_reg1; end end else begin x_reg0<=16'd0; x_reg1<=16'd0; end end always @(cState) begin if(rst) begin if(cState==6) begin y_reg0<=dout; y_reg1<=y_reg0; end else begin y_reg0<=y_reg0; y_reg1<=y_reg1; end end else begin y_reg0<=16'd0; y_reg1<=16'd0; end end assign x_int_mul1=(x_mul1[31]^x_mul1[30])?x_mul1[31:16]:x_mul1[30:15]; assign x_int_mul2=(x_mul2[31]^x_mul2[30])?x_mul2[31:16]:x_mul2[30:15]; assign x_int_mul3=(x_mul3[31]^x_mul3[30])?x_mul3[31:16]:x_mul3[30:15]; assign x_temp=(x_sum[17:15]==3'b000||x_sum[17:15]==3'b111)?x_sum[15:0]:(x_sum[17])?16'h8000:16'h7fff; assign y_int_mul1=(y_mul1[31]^y_mul1[30])?y_mul1[31:16]:y_mul1[30:15]; assign y_int_mul2=(y_mul2[31]^y_mul2[30])?y_mul2[31:16]:y_mul2[30:15]; assign y_temp=(y_sum[16:15]==2'b00||y_sum[16:15]==2'b11)?y_sum[15:0]:(y_sum[16])?16'h8000:16'h7fff; assign dout_temp=(dout_sum[16:15]==2'b00||dout_sum[16:15]==2'b11)?dout_sum[15:0]:(dout_sum[16])?16'h8000:16'h7fff; assign dout=(!rst)?16'd0:dout_temp; assign dout_valid=(cState==6 && nState==0)?1'b1:1'b0; endmodule
2.8 myiir_second_step模块
myiir_second_step.V
module myiir_second_step( rst, clk, din, dout, din_valid, dout_valid ); parameter b0=13569; parameter b1=-18494; parameter b2=13569; parameter a1=-19700; parameter a2=9712; input rst; input clk; input signed[15:0] din; input din_valid; output signed[15:0] dout; output dout_valid; reg[4:0] cState,nState; reg signed[15:0] x_reg0; reg signed[15:0] x_reg1; reg signed[31:0] x_mul1; reg signed[31:0] x_mul2; reg signed[31:0] x_mul3; wire signed[15:0] x_int_mul1; wire signed[15:0] x_int_mul2; wire signed[15:0] x_int_mul3; reg signed[17:0] x_sum; wire signed[15:0] x_temp; reg signed[15:0] y_reg0; reg signed[15:0] y_reg1; reg signed[31:0] y_mul1; reg signed[31:0] y_mul2; wire signed[15:0] y_int_mul1; wire signed[15:0] y_int_mul2; reg signed[16:0] y_sum; wire signed[15:0] y_temp; reg signed[16:0] dout_sum; wire signed[15:0] dout_temp; always @(negedge rst,posedge clk) begin if(!rst) begin cState<=0; end else begin cState<=nState; end end always @(*) begin case(cState) 0:if(din_valid) begin nState<=1; end else begin nState<=0; end 1:nState<=2; 2:nState<=3; 3:nState<=4; 4:nState<=5; 5:nState<=6; 6:nState<=0; default:nState<=nState; endcase end always @(*) begin if(rst) begin case(cState) 1:x_mul1=b0*din; 2:begin x_mul2=b1*x_reg0; y_mul1=a1*y_reg0; end 3:begin x_mul3=b2*x_reg1; y_mul2=a2*y_reg1; end 4:begin x_sum=x_int_mul1+x_int_mul2+x_int_mul3; y_sum=y_int_mul1+y_int_mul2; end 5: dout_sum=x_temp-y_temp; default:; endcase end end assign x_int_mul1=(x_mul1[31]^x_mul1[30])?x_mul1[31:16]:x_mul1[30:15]; assign x_int_mul2=(x_mul2[31]^x_mul2[30])?x_mul2[31:16]:x_mul2[30:15]; assign x_int_mul3=(x_mul3[31]^x_mul3[30])?x_mul3[31:16]:x_mul3[30:15]; assign x_temp=(x_sum[17:15]==3'b000||x_sum[17:15]==3'b111)?x_sum[15:0]:(x_sum[17])?16'h8000:16'h7fff; assign y_int_mul1=(y_mul1[31]^y_mul1[30])?y_mul1[31:16]:y_mul1[30:15]; assign y_int_mul2=(y_mul2[31]^y_mul2[30])?y_mul2[31:16]:y_mul2[30:15]; assign y_temp=(y_sum[16:15]==2'b00||y_sum[16:15]==2'b11)?y_sum[15:0]:(y_sum[16])?16'h8000:16'h7fff; assign dout_temp=(dout_sum[16:15]==2'b00||dout_sum[16:15]==2'b11)?dout_sum[15:0]:(dout_sum[16])?16'h8000:16'h7fff; assign dout=(!rst)?16'd0:dout_temp; always @(cState) begin if(rst) begin if(cState==4) begin x_reg0<=din; x_reg1<=x_reg0; end else begin x_reg0<=x_reg0; x_reg1<=x_reg1; end end else begin x_reg0<=16'd0; x_reg1<=16'd0; end end always @(cState) begin if(rst) begin if(cState==6) begin y_reg0<=dout; y_reg1<=y_reg0; end else begin y_reg0<=y_reg0; y_reg1<=y_reg1; end end else begin y_reg0<=16'd0; y_reg1<=16'd0; end end assign dout_valid=(cState==6 && nState==0)?1'b1:1'b0; endmodule
2.9 myiir_third_step模块
myiir_third_step.V
module myiir_third_step( rst, clk, din, dout, din_valid, dout_valid ); parameter b0=10302; parameter b1=-11731; parameter b2=10302; parameter a1=-11633; parameter a2=5561; input rst; input clk; input signed[15:0] din; input din_valid; output signed[15:0] dout; output dout_valid; reg[4:0] cState,nState; reg signed[15:0] x_reg0; reg signed[15:0] x_reg1; reg signed[31:0] x_mul1; reg signed[31:0] x_mul2; reg signed[31:0] x_mul3; wire signed[15:0] x_int_mul1; wire signed[15:0] x_int_mul2; wire signed[15:0] x_int_mul3; reg signed[17:0] x_sum; wire signed[15:0] x_temp; reg signed[15:0] y_reg0; reg signed[15:0] y_reg1; reg signed[31:0] y_mul1; reg signed[31:0] y_mul2; wire signed[15:0] y_int_mul1; wire signed[15:0] y_int_mul2; reg signed[16:0] y_sum; wire signed[15:0] y_temp; reg signed[16:0] dout_sum; wire signed[15:0] dout_temp; always @(negedge rst,posedge clk) begin if(!rst) begin cState<=0; end else begin cState<=nState; end end always @(*) begin case(cState) 0:if(din_valid) begin nState<=1; end else begin nState<=0; end 1:nState<=2; 2:nState<=3; 3:nState<=4; 4:nState<=5; 5:nState<=6; 6:nState<=0; default:nState<=nState; endcase end always @(*) begin if(rst) begin case(cState) 1:x_mul1=b0*din; 2:begin x_mul2=b1*x_reg0; y_mul1=a1*y_reg0; end 3:begin x_mul3=b2*x_reg1; y_mul2=a2*y_reg1; end 4:begin x_sum=x_int_mul1+x_int_mul2+x_int_mul3; y_sum=y_int_mul1+y_int_mul2; end 5: dout_sum=x_temp-y_temp; default:; endcase end end assign x_int_mul1=(x_mul1[31]^x_mul1[30])?x_mul1[31:16]:x_mul1[30:15]; assign x_int_mul2=(x_mul2[31]^x_mul2[30])?x_mul2[31:16]:x_mul2[30:15]; assign x_int_mul3=(x_mul3[31]^x_mul3[30])?x_mul3[31:16]:x_mul3[30:15]; assign x_temp=(x_sum[17:15]==3'b000||x_sum[17:15]==3'b111)?x_sum[15:0]:(x_sum[17])?16'h8000:16'h7fff; assign y_int_mul1=(y_mul1[31]^y_mul1[30])?y_mul1[31:16]:y_mul1[30:15]; assign y_int_mul2=(y_mul2[31]^y_mul2[30])?y_mul2[31:16]:y_mul2[30:15]; assign y_temp=(y_sum[16:15]==2'b00||y_sum[16:15]==2'b11)?y_sum[15:0]:(y_sum[16])?16'h8000:16'h7fff; assign dout_temp=(dout_sum[16:15]==2'b00||dout_sum[16:15]==2'b11)?dout_sum[15:0]:(dout_sum[16])?16'h8000:16'h7fff; assign dout=(!rst)?16'd0:dout_temp; always @(cState) begin if(rst) begin if(cState==4) begin x_reg0<=din; x_reg1<=x_reg0; end else begin x_reg0<=x_reg0; x_reg1<=x_reg1; end end else begin x_reg0<=16'd0; x_reg1<=16'd0; end end always @(cState) begin if(rst) begin if(cState==6) begin y_reg0<=dout; y_reg1<=y_reg0; end else begin y_reg0<=y_reg0; y_reg1<=y_reg1; end end else begin y_reg0<=16'd0; y_reg1<=16'd0; end end assign dout_valid=(cState==6 && nState==0)?1'b1:1'b0; endmodule
2.10 myiir_fourth_step模块
myiir_fourth_step.V
module myiir_fourth_step( rst, clk, din, dout, din_valid, dout_valid ); parameter b0=6724; parameter b1=-4060; parameter b2=6724; parameter a1=-7317; parameter a2=2520; input rst; input clk; input signed[15:0] din; input din_valid; output signed[15:0] dout; output dout_valid; reg[4:0] cState,nState; reg signed[15:0] x_reg0; reg signed[15:0] x_reg1; reg signed[31:0] x_mul1; reg signed[31:0] x_mul2; reg signed[31:0] x_mul3; wire signed[15:0] x_int_mul1; wire signed[15:0] x_int_mul2; wire signed[15:0] x_int_mul3; reg signed[17:0] x_sum; wire signed[15:0] x_temp; reg signed[15:0] y_reg0; reg signed[15:0] y_reg1; reg signed[31:0] y_mul1; reg signed[31:0] y_mul2; wire signed[15:0] y_int_mul1; wire signed[15:0] y_int_mul2; reg signed[16:0] y_sum; wire signed[15:0] y_temp; reg signed[16:0] dout_sum; wire signed[15:0] dout_temp; always @(negedge rst,posedge clk) begin if(!rst) begin cState<=0; end else begin cState<=nState; end end always @(*) begin case(cState) 0:if(din_valid) begin nState<=1; end else begin nState<=0; end 1:nState<=2; 2:nState<=3; 3:nState<=4; 4:nState<=5; 5:nState<=6; 6:nState<=0; default:nState<=nState; endcase end always @(*) begin if(rst) begin case(cState) 1:x_mul1=b0*din; 2:begin x_mul2=b1*x_reg0; y_mul1=a1*y_reg0; end 3:begin x_mul3=b2*x_reg1; y_mul2=a2*y_reg1; end 4:begin x_sum=x_int_mul1+x_int_mul2+x_int_mul3; y_sum=y_int_mul1+y_int_mul2; end 5: dout_sum=x_temp-y_temp; default:; endcase end end assign x_int_mul1=(x_mul1[31]^x_mul1[30])?x_mul1[31:16]:x_mul1[30:15]; assign x_int_mul2=(x_mul2[31]^x_mul2[30])?x_mul2[31:16]:x_mul2[30:15]; assign x_int_mul3=(x_mul3[31]^x_mul3[30])?x_mul3[31:16]:x_mul3[30:15]; assign x_temp=(x_sum[17:15]==3'b000||x_sum[17:15]==3'b111)?x_sum[15:0]:(x_sum[17])?16'h8000:16'h7fff; assign y_int_mul1=(y_mul1[31]^y_mul1[30])?y_mul1[31:16]:y_mul1[30:15]; assign y_int_mul2=(y_mul2[31]^y_mul2[30])?y_mul2[31:16]:y_mul2[30:15]; assign y_temp=(y_sum[16:15]==2'b00||y_sum[16:15]==2'b11)?y_sum[15:0]:(y_sum[16])?16'h8000:16'h7fff; assign dout_temp=(dout_sum[16:15]==2'b00||dout_sum[16:15]==2'b11)?dout_sum[15:0]:(dout_sum[16])?16'h8000:16'h7fff; assign dout=(!rst)?16'd0:dout_temp; always @(cState) begin if(rst) begin case(cState) 4: begin x_reg0<=din; x_reg1<=x_reg0; end default:begin x_reg0<=x_reg0; x_reg1<=x_reg1; end endcase end else begin x_reg0<=16'd0; x_reg1<=16'd0; end end always @(cState) begin if(rst) begin if(cState==6) begin y_reg0<=dout; y_reg1<=y_reg0; end else begin y_reg0<=y_reg0; y_reg1<=y_reg1; end end else begin y_reg0<=16'd0; y_reg1<=16'd0; end end assign dout_valid=(cState==6 && nState==0)?1'b1:1'b0; endmodule
2.11 myiir_fifth_step模块
myiir_fifth_step.V
module myiir_fifth_step( rst, clk, din, dout, din_valid, dout_valid ); parameter b0=3736; parameter b1=-2448; parameter b2=3736; parameter a1=-3526; parameter a2=921; input rst; input clk; input signed[15:0] din; input din_valid; output signed[15:0] dout; output dout_valid; reg[4:0] cState,nState; reg signed[15:0] x_reg0; reg signed[15:0] x_reg1; reg signed[31:0] x_mul1; reg signed[31:0] x_mul2; reg signed[31:0] x_mul3; wire signed[15:0] x_int_mul1; wire signed[15:0] x_int_mul2; wire signed[15:0] x_int_mul3; reg signed[17:0] x_sum; wire signed[15:0] x_temp; reg signed[15:0] y_reg0; reg signed[15:0] y_reg1; reg signed[31:0] y_mul1; reg signed[31:0] y_mul2; wire signed[15:0] y_int_mul1; wire signed[15:0] y_int_mul2; reg signed[16:0] y_sum; wire signed[15:0] y_temp; reg signed[16:0] dout_sum; wire signed[15:0] dout_temp; always @(negedge rst,posedge clk) begin if(!rst) begin cState<=0; end else begin cState<=nState; end end always @(*) begin case(cState) 0:if(din_valid) begin nState<=1; end else begin nState<=0; end 1:nState<=2; 2:nState<=3; 3:nState<=4; 4:nState<=5; 5:nState<=6; 6:nState<=0; default:nState<=nState; endcase end always @(*) begin if(rst) begin case(cState) 1:x_mul1=b0*din; 2:begin x_mul2=b1*x_reg0; y_mul1=a1*y_reg0; end 3:begin x_mul3=b2*x_reg1; y_mul2=a2*y_reg1; end 4:begin x_sum=x_int_mul1+x_int_mul2+x_int_mul3; y_sum=y_int_mul1+y_int_mul2; end 5: dout_sum=x_temp-y_temp; default:; endcase end end assign x_int_mul1=(x_mul1[31]^x_mul1[30])?x_mul1[31:16]:x_mul1[30:15]; assign x_int_mul2=(x_mul2[31]^x_mul2[30])?x_mul2[31:16]:x_mul2[30:15]; assign x_int_mul3=(x_mul3[31]^x_mul3[30])?x_mul3[31:16]:x_mul3[30:15]; assign x_temp=(x_sum[17:15]==3'b000||x_sum[17:15]==3'b111)?x_sum[15:0]:(x_sum[17])?16'h8000:16'h7fff; assign y_int_mul1=(y_mul1[31]^y_mul1[30])?y_mul1[31:16]:y_mul1[30:15]; assign y_int_mul2=(y_mul2[31]^y_mul2[30])?y_mul2[31:16]:y_mul2[30:15]; assign y_temp=(y_sum[16:15]==2'b00||y_sum[16:15]==2'b11)?y_sum[15:0]:(y_sum[16])?16'h8000:16'h7fff; assign dout_temp=(dout_sum[16:15]==2'b00||dout_sum[16:15]==2'b11)?dout_sum[15:0]:(dout_sum[16])?16'h8000:16'h7fff; assign dout=(!rst)?16'd0:dout_temp; always @(cState) begin if(rst) begin case(cState) 4: begin x_reg0<=din; x_reg1<=x_reg0; end default:begin x_reg0<=x_reg0; x_reg1<=x_reg1; end endcase end else begin x_reg0<=16'd0; x_reg1<=16'd0; end end always @(cState) begin if(rst) begin if(cState==6) begin y_reg0<=dout; y_reg1<=y_reg0; end else begin y_reg0<=y_reg0; y_reg1<=y_reg1; end end else begin y_reg0<=16'd0; y_reg1<=16'd0; end end assign dout_valid=(cState==6 && nState==0)?1'b1:1'b0; endmodule
2.12 myiir_sixth_step模块
myiir_sixth_step.V
module myiir_sixth_step( rst, clk, din, dout, din_valid, dout_valid ); parameter b0=9119; parameter b1=9119; parameter a1=-4044; input rst; input clk; input signed[15:0] din; input din_valid; output signed[15:0] dout; output dout_valid; reg[4:0] cState,nState; reg signed[15:0] x_reg0; reg signed[31:0] x_mul1; reg signed[31:0] x_mul2; wire signed[15:0] x_int_mul1; wire signed[15:0] x_int_mul2; reg signed[16:0] x_sum; wire signed[15:0] x_temp; reg signed[15:0] y_reg0; reg signed[31:0] y_mul1; wire signed[15:0] y_int_mul1; reg signed[16:0] dout_sum; wire signed[15:0] dout_temp; always @(negedge rst,posedge clk) begin if(!rst) begin cState<=0; end else begin cState<=nState; end end always @(*) begin case(cState) 0:if(din_valid) begin nState<=1; end else begin nState<=0; end 1:nState<=2; 2:nState<=3; 3:nState<=4; 4:nState<=5; 5:nState<=0; default:nState<=0; endcase end always @(*) begin if(rst) begin case(cState) 1:x_mul1=b0*din; 2:begin x_mul2=b1*x_reg0; y_mul1=a1*y_reg0; end 3:begin x_sum=x_int_mul1+x_int_mul2; end 4:begin dout_sum=x_temp-y_int_mul1; end default:; endcase end end assign x_int_mul1=(x_mul1[31]^x_mul1[30])?x_mul1[31:16]:x_mul1[30:15]; assign x_int_mul2=(x_mul2[31]^x_mul2[30])?x_mul2[31:16]:x_mul2[30:15]; assign x_temp=(x_sum[16:15]==2'b00||x_sum[16:15]==2'b11)?x_sum[15:0]:(x_sum[16])?16'h8000:16'h7fff; assign y_int_mul1=(y_mul1[31]^y_mul1[30])?y_mul1[31:16]:y_mul1[30:15]; assign dout_temp=(dout_sum[16:15]==2'b00||dout_sum[16:15]==2'b11)?dout_sum[15:0]:(dout_sum[16])?16'h8000:16'h7fff; assign dout=(!rst)?16'd0:dout_temp; always @(cState) begin if(rst) begin if(cState==4) begin x_reg0<=din; end else begin x_reg0<=x_reg0; end end else begin x_reg0<=16'd0; end end always @(cState) begin if(rst) begin if(cState==5) begin y_reg0<=dout; end else begin y_reg0<=y_reg0; end end else begin y_reg0<=16'd0; end end assign dout_valid=(cState==5 && nState==0)?1'b1:1'b0; endmodule
代码到这里终于结束了!辛苦观看。。
3.仿真与引脚分配
3.1 仿真
实验使用modelsim进行仿真,从matlab获得量化后的输入波形文件,经过仿真后得到滤波后的波形。
3.2 引脚分配
4.心得
本次实验好艰辛啊!从最开始的晕头晕脑,到最后有效果,时间挺长的,但确实学到了许多!通过这次实验,不仅更加熟练地学习到了FPGA设计的流程,更加深了数字信号处理滤波器的设计和实现!重要是坚持!!!
5.视频地址
前篇
http://v.youku.com/v_show/id_XMjcyMjkwNDY3Mg==.html
后篇
http://v.youku.com/v_show/id_XMjcyMjkyOTYzMg==.html
end