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

  • 相关阅读:
    VScode 修改中文字体
    missing KW_END at ')' near '<EOF>'
    SQL inner join, join, left join, right join, full outer join
    SQL字符替换函数translater, replace
    SQL COOKBOOK SQL经典实例代码 笔记第一章代码
    sqlcook sql经典实例 emp dept 创建语句
    dateutil 2.5.0 is the minimum required version python
    安装postgresql后找不到服务 postgresql service
    Postgres psql: 致命错误: 角色 "postgres" 不存在
    【西北师大-2108Java】第十六次作业成绩汇总
  • 原文地址:https://www.cnblogs.com/fydeblog/p/6748998.html
Copyright © 2011-2022 走看看