FPGA基于Verilog语言的有符号乘法运算及时钟工作频率的优化

                       FPGA基于Verilog语言的有符号乘法运算及时钟工作频率的优化

0   背景

        最近程序涉及到有符号数的乘法运算,且乘法因子的位宽超过单个DSP48E支持的位宽(25*18),当然如果采用多个DSP48E级联的模式,则可以进行位宽拓展。 程序中两个有符号的乘法因子的位宽分别为A【38:0】,B【9:0】,程序中直接采用二者相乘的方式进行乘法运算(C <=  A*B;);发现ISE综合后,该模块的最大时钟工作频率Fmax约为155MHz,这个明显不是DSP48E最好的性能。

 

1   原因分析

       于是分析,当乘法因子的位宽较大时,为什么直接采用C <=  A*B;方式时,会降低模块的最大时钟工作频率Fmax。通过查看Synthesis Report综合后的报告时,发现了原因所在,见下图所示。

    由上图可知,Mult_n04231(DSP48E)的输出PCOUT级联到Mult_n04232(DSP48E)的输入PINT,同理,......。由此可知,ISE综合C <=  A*B;程序时,采用的就是DSP48E的级联模式。采用DSP48E级联模式计算较大位宽乘法运算,优缺点如下

优点:  由于级联模式,只需一个时钟周期即可运算出C的结果,具有低延时;

缺点:  多个DSP48E级联时,其本质上逻辑阶数会增加,从而造成乘法运算路径所需的时间周期变大,故降低模块的最大时钟工作频率Fmax。

 

2   解决方法

     解决思路: 上文中乘数A的位宽较大,为A【38:0】,既然A位宽超过单个DSP48E支持的上限位宽25bit,那么可以将它人为拆分为2个位宽较小的部分即可。具体步骤见下文。

步骤1:   较大位宽数据拆分2个较小位宽数据A1【21:0】,A2【17:0】。

        举例说明:  reg signed [38 : 0]  A;      reg signed [21 : 0] A1;  reg signed [17 : 0] A2;

        A1  <=   A[38:17];     // A1是A的高位部分,A1的符号取决于A的符号;
        A2  <=   {1'b0,  A[16:0]};     // A2是A的低位部分,A2符号始终为正,故用1'b0表示,原因网友可自行分析。

步骤2: 2个较小位宽拆分后的数据分别进行乘法运算

        C1<=A1 * B;   C2<=A2 * B;
 

步骤3:将高位部分的乘法运算结果需要进行相应的移位操作(移动位数为 低位部分的位宽)

        C3    <= {C1, 17'h0};    C2保持不变;
 

步骤4:将C2和C3两部分运算结果相加之和,即可得到最终的结果。   C  <=  C3 + C2。  

 

3  实验测试

    将C <=  A*B;该代码经过上述思路进行优化后,得到最终的实现结果,ISE综合后,得到的该模块最大时钟工作频率Fmax由上文约155MHz提升为290MHz,很接近DSP48E的上限工作频率,且由下图所示,DSP48E没有采用级联模式了。

同时,为了验证程序优化后的乘法运算的正确性,我单独采用一个小程序进行简单的验证,验证结果如下图所示。

        上图中,绿色部分multfac0,multfac1为两个乘法因子,然后将multfac0拆分为multfac0_part0,multfac0_part1两部分分别进行乘法运算,过程如前文所述。最终结果显示:mult_rslt[15:0]为优化后的有符号乘法运算结果,mult_rslt_prev[15:0]为优化前的有符号乘法运算结果。对比可知,二者计算结果相同,前文优化思路满足设计要求(但是首次输出运算结果有3个时钟的延迟)。

结论:优化后的方法能够提高模块的Fmax,那么该方法的优缺点如下。(事情都有两面性!!!)

优点:能够提高模块的最大时钟频率Fmax。  

缺点:因为优化后的思路采用3级流水线模式,故第一次运算结果会存在3个时钟的延时;

此外,有网友可能会想,优化后的方法能否减少DSP48E的使用数量?   答案是不能的,可自行分析与仿真测试。

 

后记

       我在编写上述的测试小程序过程中,遇到一个有意思的错误现象。 INTERNAL_ERROR:Xst:cmain.c:3423:1.29

由于是第一次遇到,隐约感觉是代码的问题造成ISE在综合时,出现了错误,这个明显不是语法错误,且该错误不影响程序的仿真。  查找Xilinx官网的解答,发现造成该错误的原因有很多可能性,我这边应该是代码的问题造成的。

于是逐步检查,发现了问题原因: 不同位宽的有符号数不能直接赋值;但是不同位宽的有符号数可以直接加法或乘法运算后再赋值。

举例如下:  reg signed [47 : 0]  q0;      reg signed [26 : 0] q1, q2;    

always@(posedge clk) begin  q0  <=  q1; end    则:ISE在综合时会报错 INTERNAL_ERROR:Xst:cmain.c:3423:1.29

但是,always@(posedge clk) begin  q0  <=  q1 + q2;  则综合时就没有问题。

原因在于:ISE综合时,会自动将q1,q2的位宽按照q0位宽进行扩展,然后进行运算。  但是为什么直接赋值就不可以,这个我暂时也不能理解ISE工具的原理,如果有网友知晓,请指教,谢谢!!!

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值