verilog语言设计的32位输入使用Booth两位一乘和华莱士树的定点补码乘法器(附参考仿真文件)

系统描述采用两位Booth编码和华莱士树的补码乘法器是如何处理 [ − x ] 补 [-x]_{补} [x] [ − 2 x ] 补 [-2x]_{补} [2x]的部分积的:

解决方式大致如下面代码所示:

    generate 
        for(i=1;i<=16;i=i+1)begin
            assign  Nsum[i-1] = {64{y[2*i-1]==3'b000}} & 64'b0                                          |
                                {64{y[2*i-1]==3'b001}} & {{34-2*i{    A[31]}},    A,{2*i-2{1'b0}}}      |
                                {64{y[2*i-1]==3'b010}} & {{34-2*i{    A[31]}},    A,{2*i-2{1'b0}}}      |
                                {64{y[2*i-1]==3'b011}} & {{33-2*i{    A[31]}},    A,{2*i-1{1'b0}}}      |
                                {64{y[2*i-1]==3'b100}} & {{34-2*i{rev2A[31]}},rev2A,{2*i-2{1'b1}}}      |
                                {64{y[2*i-1]==3'b101}} & {{34-2*i{ revA[31]}}, revA,{2*i-2{1'b1}}}      |
                                {64{y[2*i-1]==3'b110}} & {{34-2*i{ revA[31]}}, revA,{2*i-2{1'b1}}}      |
                                {64{y[2*i-1]==3'b111}} & 64'b0                                          ;
            assign  Csum[i-1][0] = { 1{y[2*i-1]==3'b100}} & 1'b1    |
                                   { 1{y[2*i-1]==3'b101}} & 1'b1    |
                                   { 1{y[2*i-1]==3'b110}} & 1'b1    ;                  
        end
    endgenerate
    assign Csum[16][0] = 1'b0;

在代码中,大致体现了补码的部分积处理方法。对于减去 [ x ] 补 [x]_{补} [x]的部分,可以视作加上 [ x ] 补 [x]_{补} [x]的反码,最后再在末尾 + 1 +1 +1

具体代码实现如上,首先 y y y数组存储的是 y i + 1 , y i , y i − 1 y_{i+1},y_{i},y_{i-1} yi+1,yi,yi1的三位码。利用对三位码译码,从而得到相对应的操作,对于三位码100/101/110存在补码减法,可以看到拼接的计算数为A的取反或者A左移1位然后取反,这样就把加上反码的部分完成了。

对于末尾 + 1 +1 +1的部分,在华莱士树中,对于16位乘法,其每位至少包含6个全加器。对于32位乘法,全加器个数则为14。这样子做可以保证对于首位,其有6/14个空闲的进位要求,这至少可满足 n − 2 n-2 n2个末尾加法操作,剩下的两个一个用在C和S的加法器进位输入,一个用在C左移一位的0号位置上,就满足了减去操作的补码部分积处理。

用verilog语言设计一个32位输入宽度的定点补码乘法器,要求使用booth两位一乘和华莱士树:

主要设计思想是,在华莱士树中设计了十七个全加器(实际上可以只设计14个),但是为了方便代码书写,我用了16个。一共分为五层,第一层6个,第二层4个,第三层2个,第四层1个,第五层1个。这样的话,所有减去部分积操作的 + 1 +1 +1都可以直接放入进位输入。

乘法器代码如下:

`timescale 1ns / 1ps
module mul(
    input [31:0] mul1,
    input [31:0] mul2,
    output [63:0] ans,
    output cmp
);
    wire [63:0]  cmpans;
    wire [63:0]  A_cmp;
    wire [63:0]  B_cmp;
    assign A_cmp = {{32{mul1[31]}},mul1};
    assign B_cmp = {{32{mul2[31]}},mul2};

    assign cmpans = A_cmp*B_cmp;
    assign cmp = cmpans == ans;

    wire [31: 0] A;  
    wire [31: 0] A_w;   
    wire [31: 0] A_2; 
    wire [31: 0] revA;
    wire [31: 0] rev2A;
    wire [31: 0] B;
    wire [31: 0] B_w;
    wire [63: 0] Nsum [15: 0];
    wire [64: 0] Csum [16: 0];
    wire [63: 0] Ssum [16: 0];
    wire [ 2: 0] y[31: 0];
    assign A = mul1;
    assign revA = ~A;
    assign A_2  = ~(A<<1);
    assign rev2A= A_2;
    assign B = mul2;
    genvar i;
    genvar j;
    generate 
        assign y[1] = {B[1],B[0],1'b0};
        for(i=3;i<=31;i=i+2)begin
            assign y[i]= {B[i],B[i-1],B[i-2]};
        end
    endgenerate
    generate 
        for(i=1;i<=16;i=i+1)begin
            assign  Nsum[i-1] = {64{y[2*i-1]==3'b000}} & 64'b0                                          |
                                {64{y[2*i-1]==3'b001}} & {{34-2*i{    A[31]}},    A,{2*i-2{1'b0}}}      |
                                {64{y[2*i-1]==3'b010}} & {{34-2*i{    A[31]}},    A,{2*i-2{1'b0}}}      |
                                {64{y[2*i-1]==3'b011}} & {{33-2*i{    A[31]}},    A,{2*i-1{1'b0}}}      |
                                {64{y[2*i-1]==3'b100}} & {{34-2*i{rev2A[31]}},rev2A,{2*i-2{1'b1}}}      |
                                {64{y[2*i-1]==3'b101}} & {{34-2*i{ revA[31]}}, revA,{2*i-2{1'b1}}}      |
                                {64{y[2*i-1]==3'b110}} & {{34-2*i{ revA[31]}}, revA,{2*i-2{1'b1}}}      |
                                {64{y[2*i-1]==3'b111}} & 64'b0                                          ;
            assign  Csum[i-1][0] = { 1{y[2*i-1]==3'b100}} & 1'b1    |
                                   { 1{y[2*i-1]==3'b101}} & 1'b1    |
                                   { 1{y[2*i-1]==3'b110}} & 1'b1    ;                  
        end
    endgenerate
    assign Csum[16][0] = 1'b0;
    generate 
        for(i=1;i<=64;i=i+1)begin
            addr  addr0(.a(Nsum[  0][i-1]),.b(Nsum[  1][i-1]),.cin(Nsum[  2][i-1]),.s(Ssum[ 0][i-1]),.cout(Csum[ 0][i]));
            addr  addr1(.a(Nsum[  3][i-1]),.b(Nsum[  4][i-1]),.cin(Nsum[  5][i-1]),.s(Ssum[ 1][i-1]),.cout(Csum[ 1][i]));
            addr  addr2(.a(Nsum[  6][i-1]),.b(Nsum[  7][i-1]),.cin(Nsum[  8][i-1]),.s(Ssum[ 2][i-1]),.cout(Csum[ 2][i]));
            addr  addr3(.a(Nsum[  9][i-1]),.b(Nsum[ 10][i-1]),.cin(Nsum[ 11][i-1]),.s(Ssum[ 3][i-1]),.cout(Csum[ 3][i]));
            addr  addr4(.a(Nsum[ 12][i-1]),.b(Nsum[ 13][i-1]),.cin(Nsum[ 14][i-1]),.s(Ssum[ 4][i-1]),.cout(Csum[ 4][i]));
            addr  addr5(.a(Nsum[ 15][i-1]),.b(1'b0          ),.cin(1'b0          ),.s(Ssum[ 5][i-1]),.cout(Csum[ 5][i]));
            addr  addr6(.a(Ssum[  0][i-1]),.b(Ssum[  1][i-1]),.cin(Ssum[  2][i-1]),.s(Ssum[ 6][i-1]),.cout(Csum[ 6][i]));
            addr  addr7(.a(Ssum[  3][i-1]),.b(Ssum[  4][i-1]),.cin(Ssum[  5][i-1]),.s(Ssum[ 7][i-1]),.cout(Csum[ 7][i]));
            addr  addr8(.a(Csum[  0][i-1]),.b(Csum[  1][i-1]),.cin(Csum[  2][i-1]),.s(Ssum[ 8][i-1]),.cout(Csum[ 8][i]));
            addr  addr9(.a(Csum[  3][i-1]),.b(Csum[  4][i-1]),.cin(Csum[  5][i-1]),.s(Ssum[ 9][i-1]),.cout(Csum[ 9][i]));
            addr addr10(.a(Ssum[  6][i-1]),.b(Ssum[  7][i-1]),.cin(Ssum[  8][i-1]),.s(Ssum[10][i-1]),.cout(Csum[10][i]));
            addr addr11(.a(Ssum[  9][i-1]),.b(Csum[  6][i-1]),.cin(Csum[  7][i-1]),.s(Ssum[11][i-1]),.cout(Csum[11][i]));
            addr addr12(.a(Csum[  8][i-1]),.b(Csum[  9][i-1]),.cin(1'b0          ),.s(Ssum[12][i-1]),.cout(Csum[12][i]));
            addr addr13(.a(Ssum[ 10][i-1]),.b(Ssum[ 11][i-1]),.cin(Ssum[ 12][i-1]),.s(Ssum[13][i-1]),.cout(Csum[13][i]));
            addr addr14(.a(Csum[ 10][i-1]),.b(Csum[ 11][i-1]),.cin(Csum[ 12][i-1]),.s(Ssum[14][i-1]),.cout(Csum[14][i]));
            addr addr15(.a(Ssum[ 13][i-1]),.b(Ssum[ 14][i-1]),.cin(Csum[ 13][i-1]),.s(Ssum[15][i-1]),.cout(Csum[15][i]));
            addr addr16(.a(Ssum[ 15][i-1]),.b(Csum[ 14][i-1]),.cin(Csum[ 15][i-1]),.s(Ssum[16][i-1]),.cout(Csum[16][i]));
        end
    endgenerate
    assign ans = (Ssum[16] + Csum[16]);
endmodule

module addr(
    input a,
    input b,
    input cin,
    output s,
    output cout
);
    assign {cout,s} = a+b+cin;
endmodule

利用随机数生成的仿真文件如下:

`timescale 1ns / 1ps

module mul_tb();
reg  [31: 0] mul1;
reg  [31: 0] mul2;
wire [63: 0] ans;
wire cmp;
mul mul_top(
    .mul1(mul1),
    .mul2(mul2),
    .ans(ans),
    .cmp(cmp)
);
initial begin
    mul1=4'h2;
    mul2=4'h2;
end
always begin
    #2;
    mul1=$random();
    mul2=$random();
end      
endmodule

运行后的波形如图,可以看到用verilog自带的乘法和手写的乘法器结果相同:
在这里插入图片描述


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值