带符号整数乘法器设计

1.设计思路

        本文主要讲解带符号整数乘法器设计思路,以及verilog电路实现 。

1.1 补码表示

        有符号数表示都是使用补码表示,我们都知道,正数的补码是它本身,负数的补码是对应正数取法加一。对于一个4bit整数,如果表示无符号整数,它的范围是0-15;如果表示有符号整数。它的范围是-8到7。4bit表示有符号整数如下表:

二进制十进制
4'b00000
4'b00011
4'b00102
4'b00113
4'b01004
4'b01015
4'b01106
4'b01117
4'b1000-8
4'b1001-7
4'b1010-6
4'b1011-5
4'b1100-4
4'b1101-3
4'b1110-2
4'b1111-1

1.2 乘法器设计思路 

根据上表,可以得到对于两个4bit带符号数A4=a3a2a1a0,B4=b3b2b1b0

A4=-a3*2^3+a2*2^2+a1*2^1+a0*2^0  例:A4=4'b1111=-1 = -8+4+2+1=-1

B4=-b3*2^3+b2*2^2+b1*2^1+b0*2^0  例:B4=4‘b1010=-6 = -8+0+2+0=-6

注意:1bit乘法器本质上就是与(&)操作。

        根据上面化简关系,A4=-a3*2^3+A3,其中,A3可以表示为使用低三位表示的无符号整数A3=a2a1a0。由此,可以推导出如下表达式:

A4*B4=(-a3*2^3+A3)*(-b3*2^3+B3)=a3b3*2^6 - a3B3*2^3 - b3A3*2^3 + A3B3 

A3B3=(a2a1a0)*(b2b1b0)

a3B3*2^3=a3(b2b1b0)*2^3 这里乘2^3可以理解为左移3位

b3B3*2^3表示方法与上图类似如下表

        对 - a3B3*2^3 - b3A3*2^3重新整理,可以得到(-a3B3-b3A3)*2^3,再利用-x=~x+1(~表示取反)得到如下图: 

由上述推到最终可以得到如下结果:

A4*B4=(-a3*2^3+A3)*(-b3*2^3+B3)=a3b3*2^6 - a3B3*2^3 - b3A3*2^3 + A3B3 

 2.电路实现

        具体代码如下:数据位宽通过参数化定义,但是最后结果计算,需要要实验一个逻辑的累加器,目前这个部分没有办法参数化处理,如果有人有好的思路,希望可以交流。

/*
有符号乘法基本算法如下(以4bit有符号数为例子):
A4=a3a2a1a0    用十进制表示:A4=-a3*2^3 + a2*2^2 + a1*2^1 + a0*2^0 = -a3*2^3 + A3 ;
B4=b3b2b1b0    用十进制表示:B4=-b3*2^3 + b2*2^2 + b1*2^1 + b0*2^0 = -b3*2^3 + B3 ;
A4*B4 = (-a3*2^3 + A3) * (-b3*2^3 + B3) = a3b3*x^6 -a3B3*2^3 -A3b3*2^3 + A3B3 

补充:1bit乘法相当于and操作     A  B   S
                               0  0   0
                               0  1   0
                               1  0   0
                               1  1   1      
              a3b3*x^6
-a3B3*2^3 = -(a3b0*2^3 + a3b1*2^4 + a3b2*2^5)
-A3b3*2^3 = -(b3a0*2^3 + b3a1*2^4 + b3a2*2^5) 
A3B3= (a2a1a0)*(b2b1b0) = (a2a1a0)*b0 + (a2a1a0)*b1*2^1 + (a2a1a0)*b2*2^2 ;


    7       6       5       4       3       2       1       0
                                            a2b0    a1b0    a0b0
                                    a2b1    a1b1    a0b1
                            a2b2    a1b2    a0b2
                            -A3b3*2^3
                            -a3B3*2^3
+                           a3b3*x^6

继续推  将-A3b3*2^3 写成 -(a0b3*2^3 + a1b3*2^4 + a2b3*2^5)

    7       6       5       4       3       2       1       0
                                            a2b0    a1b0    a0b0
                                    a2b1    a1b1    a0b1
                            a2b2    a1b2    a0b2
                   -a2b3   -a1b3   -a0b3
                            -a3B3*2^3
+                           a3b3*x^6

继续推  将-a3B3*2^3 写成-(a3b0*2^3 + a3b1*2^4 + a3b2*2^5) 这里斜着写

    7       6       5       4       3       2       1       0
                                   -a3b0    a2b0    a1b0    a0b0
                           -a3b1    a2b1    a1b1    a0b1
                   -a3b2   a2b2    a1b2    a0b2
                   -a2b3   -a1b3   -a0b3
+                           a3b3*x^6

继续推  将a3b3*x^6 写到最后一行 

    7       6       5       4       3       2       1       0
                                   -a3b0    a2b0    a1b0    a0b0
                           -a3b1    a2b1    a1b1    a0b1
                   -a3b2    a2b2    a1b2    a0b2
            a3b3   -a2b3   -a1b3   -a0b3

如何去掉负号 :对于二进制表示的数 -x = ~x + 1 
-a3B3*2^3 -A3b3*2^3 = (-a3B3 -A3b3)*2^3  = (~a3B3 +1 + ~A3b3 +1)*2^3   2^3先不考虑
(~a3B3 +1 + ~A3b3 +1)表示为

        4       3       2       1       0
                1      ~a3b2   ~a3b1   ~a3b0
                1      ~b3a2   ~b3a1   ~b3a0
                0       0       0       1
                0       0       0       1
转换为   
        4       3       2       1       0
                1      ~a3b2   ~a3b1   ~a3b0
                1      ~b3a2   ~b3a1   ~b3a0
                0       0       1       0
转换为   
        4       3       2       1       0
                0      ~a3b2   ~a3b1   ~a3b0
                0      ~b3a2   ~b3a1   ~b3a0
        1       0       0       1       0
转换为  乘2^3 左移3位 
        7       6       5       4       3       2       1       0
                0      ~a3b2   ~a3b1   ~a3b0
                0      ~b3a2   ~b3a1   ~b3a0
        1       0       0       1       0   


将这个结果带入到之前表达式中
    7       6       5       4       3       2       1       0
                                   -a3b0    a2b0    a1b0    a0b0
                           -a3b1    a2b1    a1b1    a0b1
                   -a3b2    a2b2    a1b2    a0b2
            a3b3   -a2b3   -a1b3   -a0b3
转变为
    7       6       5       4       3       2       1       0
                            1      ~a3b0    a2b0    a1b0    a0b0
                           ~a3b1    a2b1    a1b1    a0b1
                   ~a3b2    a2b2    a1b2    a0b2
    1       a3b3   ~a2b3   ~a1b3   ~a0b3
*/

`timescale 1ns/1ps

module signed_mul 
#(
    parameter    DATA_LEN = 8 
)
(
    input  [ DATA_LEN -1   : 0 ] signed_mul_a_i    ,
    input  [ DATA_LEN -1   : 0 ] signed_mul_b_i    ,

    output [ DATA_LEN*2 -1 : 0 ] signed_mul_s_o    
);

wire [ DATA_LEN -1 : 0 ] a_bi [ DATA_LEN -1 : 0 ] ;

//-----------------------------------------------------------------------
//----每一行计算
//-----------------------------------------------------------------------
generate
    genvar i ;
    genvar j ;

    //AB
    for( i=0 ; i < DATA_LEN - 1 ; i=i+1 )begin
        for( j=0 ; j < DATA_LEN - 1 ; j=j+1)begin
            assign a_bi[i][j] = signed_mul_a_i[i] & signed_mul_b_i[j] ;
        end
    end

    //A4*B4 = (-a3*2^3 + A3) * (-b3*2^3 + B3) = a3b3*x^6 -a3B3*2^3 -A3b3*2^3 + A3B3 
    //aB
    for( i=0 ; i < DATA_LEN - 1 ; i=i+1 )begin
        assign a_bi[i][DATA_LEN - 1] = ~(signed_mul_a_i[DATA_LEN - 1] & signed_mul_b_i[i]) ;
    end

    //Ab
    for( i=0 ; i < DATA_LEN - 1 ; i=i+1 )begin
        assign a_bi[DATA_LEN - 1][i] = ~(signed_mul_a_i[i] & signed_mul_b_i[DATA_LEN - 1]) ;
    end

    //ab
    assign a_bi[DATA_LEN - 1][DATA_LEN - 1] = signed_mul_a_i[DATA_LEN - 1] & signed_mul_b_i[DATA_LEN - 1] ;

endgenerate

//-----------------------------------------------------------------------
//----求和
//-----------------------------------------------------------------------
wire [DATA_LEN*2 -1 : 0]add_sum[DATA_LEN -1 : 0];

generate
    genvar k ;

    assign add_sum[0] = {1'b1 , a_bi[0][DATA_LEN - 1] , a_bi[0][DATA_LEN - 2 : 0]} ;
    for( k=1 ; k<DATA_LEN-1 ; k=k+1 )begin
        assign add_sum[k] = { a_bi[k][DATA_LEN - 1] , a_bi[k][DATA_LEN - 2 : 0] } << k ;
    end
    assign add_sum[DATA_LEN - 1] = { 1'b1 , a_bi[DATA_LEN - 1][DATA_LEN - 1] , a_bi[DATA_LEN - 1][DATA_LEN - 2 : 0] } << (DATA_LEN - 1) ;

endgenerate

//根据实际多少位需要自己添加  可以使用类似于累加器  但是循环好像并不好写
assign signed_mul_s_o = add_sum[0] + add_sum[1] + add_sum[2] + add_sum[3] +
                        add_sum[4] + add_sum[5] + add_sum[6] + add_sum[7]   ;

endmodule //signed_mul

3.仿真验证

3.1验证代码

`timescale 1ns/1ps

module signed_mul_tb;

// Parameters
localparam  DATA_LEN = 8;

//Ports
reg [ DATA_LEN -1   : 0 ] signed_mul_a_i;
reg [ DATA_LEN -1   : 0 ] signed_mul_b_i;
wire [ DATA_LEN*2 -1 : 0 ] signed_mul_s_o;

signed_mul # (
    .DATA_LEN(DATA_LEN)
  )
  signed_mul_inst (
    .signed_mul_a_i(signed_mul_a_i),
    .signed_mul_b_i(signed_mul_b_i),
    .signed_mul_s_o(signed_mul_s_o)
);

integer i;
integer j;

initial begin
    signed_mul_a_i = 8'hff ;
    signed_mul_b_i = 8'hff ;
    #40;
    signed_mul_a_i = 8'h1  ;
    signed_mul_b_i = 8'hff ;
    #40;
    for(i=0 ; i<256 ; i=i+1 )begin
        for(j=0 ; j<256 ; j=j+1)begin
            signed_mul_a_i = i ;
            signed_mul_b_i = j ;
            #20 ;
        end
    end

    #100;
    $stop;
end

endmodule

3.2 验证结果

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值