zoukankan      html  css  js  c++  java
  • 八位右移位乘法器

    八位右移位乘法器

    虚假的右移位

    其实移位总是相对的,所以右移还是有左移的成分。

    左移位乘法器很好理解,因为在列竖式的时候就能看明白,符合我们的常规思维:

    image-20201110164456963

    也就是说,每一次乘法之后,只要把对应的部分积左移相应的位数,再相加,就可以得到最终的结果,这个过程像极了小学二年级的乘法课,非常的直观了,这里不做赘述~

    那么什么是右移呢?我听到有同学说,把乘数和被乘数换一下就是了,像这样:

    image-20201110170450444

    运算顺序从右往左,理论上结果是正确的,就是看起来有点别扭,我们把它转过来:

    image-20201110171651354

    这下应该看明白了吧,无非是最后的结果再加移位一次,从而实现一个“虚假的右移位”

    真正的右移位

    真正的右移位,其实是针对小数计算而言的,我们计算整数乘法的时候,习惯性的左移,根本原因是我们习惯了整数的小数点在最右侧,只要不超过那个小数点,就可以直接相加得结果。

    而小数计算,因为小数点在左边的缘故,在计算机当中,就可以根据小数点位置不变的思想,来将部分积右移,从而实现一个右移乘法器。这种思想所成的乘法器,也成为定点乘法器

    以二进制小数计算“0.1101 x 0.1011”为例:

    image-20201110171651354

    由图可以看出,最后一位的结果并不参与移位相加的运算,什么意思呢?

    我们再画详细点:

    image-20201110192743010

    计算时,每次得到的部分积,都会与上一次得到的部分积相加,而每次相加结果的最后一位不参与运算,可直接右移转存,则部分积占用的空间显然比左移运算小多了。这样说,想必应该足够明白了吧?

    设计文件(方式一)

    知道了上述原理,我们来写一个右移位的乘法器,逻辑很清晰,每次根据乘数位是否为0进行判断,如果是0,则部分积=前一步的部分积+0,如果是1,则部分积=前一步的部分积+被乘数,同时每次将部分积的最低位存储至结果的低位中,最后一次的部分积则为结果的高位。

    实现代码如下:

    module mul_8_1(result,mul1,mul2);
        input wire[7:0] mul1;
        input wire[7:0] mul2;
        output reg[15:0] res;
        reg [7:0] A;        //部分积
        integer i;
        reg [7:0] temp_x;   //乘法运算时,被乘数与乘数最后一位的积的最后一位不参与最后的加法运算,将其右移另存。
        always @ (*)
        begin
            A=0;
            for (i=0;i<8;i=i+1)
                begin
                    if(mul2[i]) A=A+{1'b0,mul1};      //部分积移位前可能会比乘数多一位
                    else A=A+9'b000000000;
                    temp_x[i]=A[0];
                    A=A>>1;
                end
                res={A,temp_x};
        end
    endmodule
    

    RTL级电路综合中却很少使用for循环语句。主要原因就是for循环会被综合器展开为所有变量情况的执行语句,每个变量独立占用寄存器资源,每条执行语句并不能有效地复用硬件逻辑资源,造成巨大的资源浪费。也就是说,for语句循环几次,就是将相同的电路复制几次。循环次数越多,综合电路占用面积越大,综合就越慢。

    所以我们稍微改改写法,就可以解决for循环了。

    综合电路

    23个元件,32IO口,202根线

    image-20201110195053083

    设计文件(方式二)

    所幸八位的乘法器也并不算复杂,可以写一个并行计算的部分积。这样也就解决了for循环的问题。

    `define size 8
    module mul_8_1(
        input wire [`size - 1:0] mul1,mul2,
        output wire [2*`size - 1:0] res
        );
        wire [`size : 0] A[0:`size-1];
        wire [`size -1 : 0] low_pro;
    
        assign A[0] = mul2[0] ? {1'b0,mul1} : 9'd0;
        assign A[1] = mul2[1] ? ((A[0]>>1) + {1'b0,mul1}) : ((A[0]>>1) + 9'd0);
        assign A[2] = mul2[2] ? ((A[1]>>1) + {1'b0,mul1}) : ((A[1]>>1) + 9'd0);
        assign A[3] = mul2[3] ? ((A[2]>>1) + {1'b0,mul1}) : ((A[2]>>1) + 9'd0);
        assign A[4] = mul2[4] ? ((A[3]>>1) + {1'b0,mul1}) : ((A[3]>>1) + 9'd0);
        assign A[5] = mul2[5] ? ((A[4]>>1) + {1'b0,mul1}) : ((A[4]>>1) + 9'd0);
        assign A[6] = mul2[6] ? ((A[5]>>1) + {1'b0,mul1}) : ((A[5]>>1) + 9'd0);
        assign A[7] = mul2[7] ? ((A[6]>>1) + {1'b0,mul1}) : ((A[6]>>1) + 9'd0);
    
        assign low_pro[0] = A[0][0];
        assign low_pro[1] = A[1][0];
        assign low_pro[2] = A[2][0];
        assign low_pro[3] = A[3][0];
        assign low_pro[4] = A[4][0];
        assign low_pro[5] = A[5][0];
        assign low_pro[6] = A[6][0];
        assign low_pro[7] = A[7][0];
    
        assign res = {(A[7] >> 1),low_pro};
    endmodule
    

    综合电路

    23个元件,32IO口,224根线,和使用for循环的方式相比,多了几根线??!

    好吧果然是我的能力问题,有见解的朋友们请务必说一下,我想学!

    image-20201110194747053

    测试文件

    由于两个都是乘法器,输入和输出端口都一样,则可以用同样的测试文件进行测试:

    module mul_tb(
        );
        reg [7:0] mul1,mul2;
        wire [15:0] res;
        reg clk;
        initial begin
            mul1 <= 8'd7;
            mul2 <= 8'd3;
            clk <= 0;
        end
    
        always # 10 clk = ~clk;
        always @ (posedge clk) begin
            mul2 <= mul2 + 1'b1;
        end
    
        mul_8_1 try(.mul1(mul1),.mul2(mul2),.res(res),);
    endmodule
    

    仿真波形

    调成无符号十进制数进行观察,如图所示,7x7=497x8=56,结果正确。

    image-20201110200652246

  • 相关阅读:
    LeetCode 791. 自定义字符串排序
    LeetCode 725. 分隔链表
    LeetCode 445. 两数相加 II
    LeetCode 354. 俄罗斯套娃信封问题
    LeetCode 338. 比特位计数
    LeetCode 318. 最大单词长度乘积
    LeetCode 300. 最长上升子序列
    蚂蚁金服研发面经
    Consul etcd ZooKeeper euerka 对比
    Java并发机制的底层实现原理之volatile应用,初学者误看!
  • 原文地址:https://www.cnblogs.com/mxdon/p/13959134.html
Copyright © 2011-2022 走看看