码迷,mamicode.com
首页 > 其他好文 > 详细

FPGA之资源优化思想的运用

时间:2015-03-04 06:15:45      阅读:328      评论:0      收藏:0      [点我收藏+]

标签:

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

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

技术分享技术分享

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

技术分享

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

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

技术分享

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

技术分享

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

技术分享

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

技术分享

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

技术分享

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

技术分享

直接Next。。

技术分享

Finish。。将弹出如下对话:

技术分享

在这里选择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 <= 8b0;
        BufferDataAIm <= 8b0;
        BufferDataBRe <= 8b0;
        BufferDataBIm <= 8b0;
        BufferEnable  <= 1b0;
        end
    else
        begin
        if(InputEnable)
            begin
            BufferDataARe <= DataInARe;
            BufferDataAIm <= DataInAIm;
            BufferDataBRe <= DataInBRe;
            BufferDataBIm <= DataInBIm;
            BufferEnable  <= 1b1;
            end
        else
            begin
            BufferDataARe <= 8b0;
            BufferDataAIm <= 8b0;
            BufferDataBRe <= 8b0;
            BufferDataBIm <= 8b0;
            BufferEnable  <= 1b0;
            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         <= 1b0;
        TempSumA        <= 9b0;         //Ar+Ai
        TempDifferenceA <= 9b0;         //Ar-Ai
        TempSumB        <= 9b0;         //Br+Bi
        TempARe         <= 8b0;
        TempBRe         <= 8b0;
        TempBIm         <= 8b0;
        end
    else
        begin
        if(BufferEnable)  
            begin
            Temp_En         <= 1b1;
            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         <= 1b0;
            TempSumA        <= 9b0;
            TempDifferenceA <= 9b0;
            TempSumB        <= 9b0;
            TempARe         <= 8b0;
            TempBRe         <= 8b0;
            TempBIm         <= 8b0;
            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 <= 1b0;
    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     <= 18b0;
        TempIm     <= 18b0;
        TempEnable <= 1b0;
        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 <= 1b1;
            end
        else
            begin
            TempRe     <= 18b0;
            TempIm     <= 18b0;
            TempEnable <= 1b0;
            end
        end
end
//-----------------------------------------------------------------------------
//output data         
always @(posedge Clk or negedge Rst_n)
begin
    if(!Rst_n)
        begin
        DataOutRe    <= 16b0;
        DataOutIm    <= 16b0;
        OutputEnable <= 1b0;
        end
    else
        begin
        if(TempEnable)
            begin
            DataOutRe    <= {TempRe[17],TempRe[14:0]};
            DataOutIm    <= {TempIm[17],TempIm[14:0]};
            OutputEnable <= 1b1;
            end
        else
            begin
            DataOutRe    <= 16b0;
            DataOutIm    <= 16b0;
            OutputEnable <= 1b0;
            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 = 1b1;              
    DataInARe = 8b1010_1010;
    DataInAIm = 8b0101_0101;    
    DataInBRe = 8b1111_0000;
    DataInBIm = 8b0000_1111;
    @(negedge Clk);
    InputEnable = 1b0;              
    DataInARe = 8b0;
    DataInAIm = 8b0;    
    DataInBRe = 8b0;
    DataInBIm = 8b0;
    repeat(10)@(negedge Clk);
    InputEnable = 1b1;              
    DataInARe = 8b1011_1110;
    DataInAIm = 8b1101_0001;    
    DataInBRe = 8b1000_0110;
    DataInBIm = 8b0100_1001;
    @(negedge Clk);
    InputEnable = 1b0;              
    DataInARe = 8b0;
    DataInAIm = 8b0;    
    DataInBRe = 8b0;
    DataInBIm = 8b0;
end

endmodule

仿真结果如下所示:

技术分享

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

FPGA之资源优化思想的运用

标签:

原文地址:http://www.cnblogs.com/CrazyBirdLin/p/4312266.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!