FPGA之资源优化思想的运用

摘要:
接下来,将以复数相乘的事例来说明资源优化的思想。为了优化资源,我们还可以继续将表达式化为这样一来,只需要3个乘法器和一些额外的加减运算就可实现复数乘法了。我们这样做的目的是在某些设计中可以节省宝贵的专用乘法器资源,有利于改善设计的资源消耗。设置乘法器为有符号类型,Next。。至此,IP核的调用完毕。接下来,就可以在设计的源文件中例化该IP核了。

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

我常常对自己说:“因为我不会,所以要学别人的东西。但是不要只是学习它的内容,而更重要的是它的精髓、灵魂。”接下来,将以复数相乘的事例来说明资源优化的思想。现在给出两个复数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
moduleComplex_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;
regBufferEnable;

always @(posedge Clk or negedgeRst_n)
begin
    if(!Rst_n)
        beginBufferDataARe <= 8'b0;
        BufferDataAIm <= 8'b0;
        BufferDataBRe <= 8'b0;
        BufferDataBIm <= 8'b0;
        BufferEnable  <= 1'b0;
        end
    else
        begin
        if(InputEnable)
            beginBufferDataARe <=DataInARe;
            BufferDataAIm <=DataInAIm;
            BufferDataBRe <=DataInBRe;
            BufferDataBIm <=DataInBIm;
            BufferEnable  <= 1'b1;
            end
        else
            beginBufferDataARe <= 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
regTemp_En;

always @(posedge Clk or negedgeRst_n)
begin
    if(!Rst_n)
        beginTemp_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)  
            beginTemp_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
            beginTemp_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
regrdy;

always @(posedge Clk or negedgeRst_n)
begin
    if(!Rst_n)
        rdy <= 1'b0;
    elserdy <=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;
regTempEnable;

always @(posedge Clk or negedgeRst_n)
begin
    if(!Rst_n)
        beginTempRe     <= 18'b0;
        TempIm     <= 18'b0;
        TempEnable <= 1'b0;
        end
    else
        begin    
        if(rdy)
            beginTempRe     <= {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
            beginTempRe     <= 18'b0;
            TempIm     <= 18'b0;
            TempEnable <= 1'b0;
            end
        end
end
//-----------------------------------------------------------------------------
//output data         
always @(posedge Clk or negedgeRst_n)
begin
    if(!Rst_n)
        beginDataOutRe    <= 16'b0;
        DataOutIm    <= 16'b0;
        OutputEnable <= 1'b0;
        end
    else
        begin
        if(TempEnable)
            beginDataOutRe    <= {TempRe[17],TempRe[14:0]};
            DataOutIm    <= {TempIm[17],TempIm[14:0]};
            OutputEnable <= 1'b1;
            end
        else
            beginDataOutRe    <= 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
moduleComplex_Multiplier_tb;
regClk;
regRst_n;
regInputEnable;              
reg  [ 7:0] DataInARe;
reg  [ 7:0] DataInAIm;    
reg  [ 7:0] DataInBRe;
reg  [ 7:0] DataInBIm; 
wireOutputEnable;              
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    
beginClk = 0;
    forever  #(PERIOD/2)    
    Clk = ~Clk;
end

tasktask_reset;
beginRst_n = 0;
    repeat(2) @(negedgeClk);
    Rst_n = 1;
endendtask
//----------------------------------------
//testbench of the RTL
initial
begintask_reset;
    @(negedgeClk);
    InputEnable = 1'b1;              
    DataInARe = 8'b1010_1010;
    DataInAIm = 8'b0101_0101;    
    DataInBRe = 8'b1111_0000;
    DataInBIm = 8'b0000_1111;
    @(negedgeClk);
    InputEnable = 1'b0;              
    DataInARe = 8'b0;
    DataInAIm = 8'b0;    
    DataInBRe = 8'b0;
    DataInBIm = 8'b0;
    repeat(10)@(negedgeClk);
    InputEnable = 1'b1;              
    DataInARe = 8'b1011_1110;
    DataInAIm = 8'b1101_0001;    
    DataInBRe = 8'b1000_0110;
    DataInBIm = 8'b0100_1001;
    @(negedgeClk);
    InputEnable = 1'b0;              
    DataInARe = 8'b0;
    DataInAIm = 8'b0;    
    DataInBRe = 8'b0;
    DataInBIm = 8'b0;
end

endmodule

仿真结果如下所示:

14

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

免责声明:文章转载自《FPGA之资源优化思想的运用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Django测试pytestredis集群之REDIS CLUSTER下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

FPGA配置方式

首先介绍下AS、PS、JTAG三种模式的区别。 AS模式: 烧到FPGA的配置芯片里保存的,FPGA器件每次上电时,作为控制器从配置器件EPCS主动发出读取数据信号,从而把EPCS的数据读入FPGA中,实现对FPGA的编程,该方法适用于不需要经常升级的场合; PS模式:EPCS作为控制器件,把FPGA当做存储器,把数据写人到FPGA中,实现对FPGA的编程...

GPU 、APU、CUDA、TPU、FPGA介绍

购买显卡主要关注:显存、带宽和浮点运算数量 GPU :图形处理器(英语:Graphics Processing Unit,缩写:GPU),又称显示核心、视觉处理器、显示芯片,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上图像运算工作的微处理器。 用途是将计算机系统所需要的显示信息进行转换驱动,并向显示器提供行扫描信号,控制显...

FPGA 移交代码学习——Map错误 ODDR2 使用问题

这段时间一直忙贴片生产相关事情,又是搬家,都没有什么时间好好整整。 前人移交过来的记录仪代码,发现一个BUG , 1 wire [8:0] fchk_shift_r1 = fenergy_chk<<1; 2 wire [9:0] fchk_shift_r2 = fenergy_chk<<2; 3 wire [10:0]fchk_sh...

深入理解CPU和异构计算芯片GPU/FPGA/ASIC (上篇)

随着互联网用户的快速增长,数据体量的急剧膨胀,数据中心对计算的需求也在迅猛上涨。诸如深度学习在线预测、直播中的视频转码、图片压缩解压缩以及HTTPS加密等各类应用对计算的需求已远远超出了传统CPU处理器的能力所及。摩尔定律失效的今天,关注“新“成员(GPUFPGAASIC)为数据中心带来的体系架构变革,为业务配上一台动力十足的发动机。 1 异构计算:WHY...

FPGA综合工具--Synplify Pro的常用选项及命令

最近要用到Synplify,但以前没使用过,无基础,找到一篇帖子,隧保存下来。 本文转自:http://blog.sina.com.cn/s/blog_65fe490d0100v8ax.html Synplify 使用过程中最常用的选项及命令的介绍。一、 状态机相关(1)FSM Compiler Option  FSM Compiler是一个全局选项。勾选...

随便谈谈网络通讯延迟和应用

首先丢出2个简单定理。   定理1 任何所谓的软件编程本质上都是面向硬件编程   定理2 任何软件操作的根本延迟受制于硬件循环所需要的时间   计算机作为一个输入输出设备,本质上就是3个步骤,输入、处理、输出。计算机之间的通讯媒介,无非有线无线,其实主要是取决于介质和通讯方式。   如果是有无线的场合,包括WiFi或者是无线电RF还是所谓的5G,都在这个...