• FPGA之资源优化思想的运用


       很多不安于现状的年轻人心中都有一个明确的目标,并最终为之留下了心酸和泪水而走上了成功的道路。如今我就觉得自己挺年轻的,不过我并没有像他们那么的努力。为了实现梦想,对得起自己,从现在开始我要向他们学习拼搏、执着的精神。哪怕前方的路途再怎么曲折、不平坦,我也要硬着头皮走下去。好了,该回归正题了~~~

       我常常对自己说:“因为我不会,所以要学别人的东西。但是不要只是学习它的内容,而更重要的是它的精髓、灵魂。”接下来,将以复数相乘的事例来说明资源优化的思想。现在给出两个复数Ar+Aij和Br+Bij,他们的乘法可表示为

    1112

    如果按照上述表达式来实现电路的话,它将需要4个乘法器。当然,若以并行结构来实现,将是速度最快的方案,但也是最耗资源的方案。为了优化资源,我们还可以继续将表达式化为

    13

    这样一来,只需要3个乘法器和一些额外的加减运算就可实现复数乘法了。我们这样做的目的是在某些设计中(比如OFDM通信基带的设计中需要许多复数乘法器)可以节省宝贵的专用乘法器资源,有利于改善设计的资源消耗。

       介绍了理论的东西之后,总得将它设计成电路。首先,了解下Quartus II中乘法器IP核的调用,点击菜单“Tool--->MegaWizard Plug-In Manager”,将出现IP核调用向导,如下图所示:

    1

    选择第一项,创建新的宏功能模块,Next。。

    2

    (1)选择乘法器IP核;(2)设置器件型号;(3)设置生成文件为Verilog HDL类型;(4)输入文件名和存放的路径。Next。。

    3

    设置输入数据的位宽,其他选项默认就可以了。Next。。

    4

    设置乘法器为有符号类型,Next。。

    5

    设置输入到输出延时一个时钟周期(当然也可以为其他,视情况而定),勾选时钟使能,优化选项默认,Next。。

    6

    直接Next。。

    7

    Finish。。将弹出如下对话:

    8

    在这里选择Yes。如果选择No,则需要手动添加文件。至此,IP核的调用完毕。

    接下来,就可以在设计的源文件中例化该IP核了。为此,我自己写了简单的例程,希望大家可以看得明白。

    /*******************************************************
    Author       :  crazyBird
    Filename     :  Complex_Multiplier.v
    Data         :  2015-3-4
    Description  :  Multiplier of complex data. 
    ********************************************************/
    `timescale 1ns/1ps
    module Complex_Multiplier
    (
        input               Clk,                    //global clock
        input               Rst_n,                  //global reset
        input               InputEnable,            //input enable
        input       [ 7:0]  DataInARe,DataInAIm,    //input data
        input       [ 7:0]  DataInBRe,DataInBIm, 
        output reg          OutputEnable,           //output valid
        output reg  [15:0]  DataOutRe,DataOutIm     //output data
    );  
    //-----------------------------------------
    //input buffer
    reg [7:0] BufferDataARe;
    reg [7:0] BufferDataAIm;
    reg [7:0] BufferDataBRe;
    reg [7:0] BufferDataBIm;
    reg       BufferEnable;
    
    always @(posedge Clk or negedge Rst_n)
    begin
        if(!Rst_n)
            begin
            BufferDataARe <= 8'b0;
            BufferDataAIm <= 8'b0;
            BufferDataBRe <= 8'b0;
            BufferDataBIm <= 8'b0;
            BufferEnable  <= 1'b0;
            end
        else
            begin
            if(InputEnable)
                begin
                BufferDataARe <= DataInARe;
                BufferDataAIm <= DataInAIm;
                BufferDataBRe <= DataInBRe;
                BufferDataBIm <= DataInBIm;
                BufferEnable  <= 1'b1;
                end
            else
                begin
                BufferDataARe <= 8'b0;
                BufferDataAIm <= 8'b0;
                BufferDataBRe <= 8'b0;
                BufferDataBIm <= 8'b0;
                BufferEnable  <= 1'b0;
                end
         end
    end
    //------------------------------------------
    //compute Ar+Ai,Ar-Ai,Br+Bi
    reg [8:0] TempSumA;         //Ar+Ai  
    reg [8:0] TempDifferenceA;  //Ar-Ai
    reg [8:0] TempSumB;         //Br+Bi
    reg [7:0] TempARe;          //Ar
    reg [7:0] TempBRe;          //Br
    reg [7:0] TempBIm;          //Bi
    reg       Temp_En;
    
    always @(posedge Clk or negedge Rst_n)
    begin
        if(!Rst_n)
            begin
            Temp_En         <= 1'b0;
            TempSumA        <= 9'b0;         //Ar+Ai
            TempDifferenceA <= 9'b0;         //Ar-Ai
            TempSumB        <= 9'b0;         //Br+Bi
            TempARe         <= 8'b0;
            TempBRe         <= 8'b0;
            TempBIm         <= 8'b0;
            end
        else
            begin
            if(BufferEnable)  
                begin
                Temp_En         <= 1'b1;
                TempSumA        <= {BufferDataARe[7],BufferDataARe}+{BufferDataAIm[7],BufferDataAIm};        //signal data add
                TempDifferenceA <= {BufferDataARe[7],BufferDataARe}-{BufferDataAIm[7],BufferDataAIm};        //signal data sub
                TempSumB        <= {BufferDataBRe[7],BufferDataBRe}+{BufferDataBIm[7],BufferDataBIm};       
                TempARe         <= BufferDataARe;
                TempBRe         <= BufferDataBRe;
                TempBIm         <= BufferDataBIm;
                end
            else
                begin
                Temp_En         <= 1'b0;
                TempSumA        <= 9'b0;
                TempDifferenceA <= 9'b0;
                TempSumB        <= 9'b0;
                TempARe         <= 8'b0;
                TempBRe         <= 8'b0;
                TempBIm         <= 8'b0;
                end
            end
    end
    //-------------------------------------------
    //instance of IP core
    wire [16:0] SumA_mult_Bi;
    wire [16:0] DifferenceA_mult_Br;
    wire [16:0] SumB_mult_Ar;
    
    //compute Bi*(Ar+Ai)
    width9_multiply_width8 SumAmultiplyBr 
    (
        .clock (Clk         ),
        .dataa (TempSumA    ),
        .datab (TempBIm     ),    
        .clken (Temp_En     ),
        .result(SumA_mult_Bi)
    );
         
    //compute Ar*(Br+Bi)
    width9_multiply_width8 SumBmultiplyAr 
    (
        .clock (Clk         ),
        .dataa (TempSumB    ),
        .datab (TempARe     ),
        .clken (Temp_En     ),
        .result(SumB_mult_Ar)
    );
    
    //compute Br*(Ar-Ai)
    width9_multiply_width8 DifferenceAmultiplyBi
    (
        .clock (Clk                ),
        .dataa (TempDifferenceA    ),
        .datab (TempBRe            ),
        .clken (Temp_En            ),
        .result(DifferenceA_mult_Br)
    );
    //------------------------------------------
    //valid data output flag
    reg       rdy;
    
    always @(posedge Clk or negedge Rst_n)
    begin
        if(!Rst_n)
            rdy <= 1'b0;
        else    
            rdy <= Temp_En;
    end 
    //------------------------------------------
    //compute Ar*(Br+Bi)- Br*(Ar-Ai) and Ar*(Br+Bi)- Bi*(Ar+Ai)
    reg [17:0]  TempRe;
    reg [17:0]  TempIm;
    reg         TempEnable;
    
    always @(posedge Clk or negedge Rst_n)
    begin
        if(!Rst_n)
            begin
            TempRe     <= 18'b0;
            TempIm     <= 18'b0;
            TempEnable <= 1'b0;
            end
        else
            begin    
            if(rdy)
                begin
                TempRe     <= {SumB_mult_Ar[16],SumB_mult_Ar}-{SumA_mult_Bi[16],SumA_mult_Bi};                //signal data sub 
                TempIm     <= {SumB_mult_Ar[16],SumB_mult_Ar}-{DifferenceA_mult_Br[16],DifferenceA_mult_Br};
                TempEnable <= 1'b1;
                end
            else
                begin
                TempRe     <= 18'b0;
                TempIm     <= 18'b0;
                TempEnable <= 1'b0;
                end
            end
    end
    //-----------------------------------------------------------------------------
    //output data         
    always @(posedge Clk or negedge Rst_n)
    begin
        if(!Rst_n)
            begin
            DataOutRe    <= 16'b0;
            DataOutIm    <= 16'b0;
            OutputEnable <= 1'b0;
            end
        else
            begin
            if(TempEnable)
                begin
                DataOutRe    <= {TempRe[17],TempRe[14:0]};
                DataOutIm    <= {TempIm[17],TempIm[14:0]};
                OutputEnable <= 1'b1;
                end
            else
                begin
                DataOutRe    <= 16'b0;
                DataOutIm    <= 16'b0;
                OutputEnable <= 1'b0;
                end
            end
    end                        
    
    endmodule

    测试代码如下:

    /*******************************************************
    Author       :  crazyBird
    Filename     :  Complex_Multiplier_tb.v
    Data         :  2015-3-4
    Description  :  Simulation of Complex_Multiplier. 
    ********************************************************/
    `timescale 1ns/1ps
    module Complex_Multiplier_tb;
    reg         Clk;
    reg         Rst_n;
    reg         InputEnable;              
    reg  [ 7:0] DataInARe;
    reg  [ 7:0] DataInAIm;    
    reg  [ 7:0] DataInBRe;
    reg  [ 7:0] DataInBIm; 
    wire        OutputEnable;              
    wire [15:0] DataOutRe;
    wire [15:0] DataOutIm;
    
    Complex_Multiplier u_Complex_Multiplier
    (
        .Clk         (Clk         ),
        .Rst_n       (Rst_n       ),
        .InputEnable (InputEnable ),
        .DataInARe   (DataInARe   ),
        .DataInAIm   (DataInAIm   ),
        .DataInBRe   (DataInBRe   ),
        .DataInBIm   (DataInBIm   ),
        .OutputEnable(OutputEnable),
        .DataOutRe   (DataOutRe   ),
        .DataOutIm   (DataOutIm   )
    );
    //-------------------------------------
    //clock generate module
    localparam PERIOD = 20;    //50MHz
    initial    
    begin
        Clk = 0;
        forever  #(PERIOD/2)    
        Clk = ~Clk;
    end
    
    task task_reset;
    begin
        Rst_n = 0;
        repeat(2) @(negedge Clk);
        Rst_n = 1;
    end
    endtask
    //----------------------------------------
    //testbench of the RTL
    initial
    begin
        task_reset;
        @(negedge Clk);
        InputEnable = 1'b1;              
        DataInARe = 8'b1010_1010;
        DataInAIm = 8'b0101_0101;    
        DataInBRe = 8'b1111_0000;
        DataInBIm = 8'b0000_1111;
        @(negedge Clk);
        InputEnable = 1'b0;              
        DataInARe = 8'b0;
        DataInAIm = 8'b0;    
        DataInBRe = 8'b0;
        DataInBIm = 8'b0;
        repeat(10)@(negedge Clk);
        InputEnable = 1'b1;              
        DataInARe = 8'b1011_1110;
        DataInAIm = 8'b1101_0001;    
        DataInBRe = 8'b1000_0110;
        DataInBIm = 8'b0100_1001;
        @(negedge Clk);
        InputEnable = 1'b0;              
        DataInARe = 8'b0;
        DataInAIm = 8'b0;    
        DataInBRe = 8'b0;
        DataInBIm = 8'b0;
    end
    
    endmodule

    仿真结果如下所示:

    14

    由仿真时序图可以验证本设计是正确的。第一次用Windows Live Writer的多种技巧,折腾了好久,好困啊,发发就睡了。晚安,88*^_^*

  • 相关阅读:
    iptables学习笔记_____摘自朱双印个人日志 ____http://www.zsythink.net/
    使用xmanager图形化远程连接rhel6
    powerdesigner
    CentOS和RedHat Linux的区别
    win7防火墙端口开放
    微服务 环境问题处理
    lombok
    pl/sql Devloper 如何查看表结构
    pl/sql Devloper使用
    luogu P4231 三步必杀
  • 原文地址:https://www.cnblogs.com/CrazyBirdLin/p/4312266.html
Copyright © 2020-2023  润新知