zoukankan      html  css  js  c++  java
  • 基于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

  • 相关阅读:
    phalcon之视图缓存
    Java NIO框架Netty教程(一) – Hello Netty
    setsockopt的作用
    支持向量机通俗导论(理解SVM的三层境地)
    quartz中的corn表达式(转)
    Applet 数字签名技术全然攻略
    SJTU 3001. 二哥的幸运
    OGRE之跳出漫长的编译等待
    VB.NET 数组的定义 动态使用 多维数组
    【Python】用Python的“结巴”模块进行分词
  • 原文地址:https://www.cnblogs.com/fydeblog/p/6748998.html
Copyright © 2011-2022 走看看