撒萌萌

 

二进制乘法器(转)

二进制乘法器的主要操作就是加发法操作和移位操作。

我们知道计算机存储数据都是以二进制形式进行存储的,以4位数为例解释一下被乘数和乘数如何操作,首先把被乘数扩展成2倍的位宽,高4位为0,低4位为被乘数,结果为8为0,

先检测乘数的最低位,如果是1,则被乘数和结果想加,然后乘数右移,被乘数左移,如果是0,则被乘数左移,乘数右移。依次类推。

如下图:开始,product=00000000,Mcand=00000110,

    Mer[0]==1,product==product+Mcand==00000110;Mer=0010,Mcand==00001100;

    Mer[0]==0,Mer==0001,Mcand==00011000;

    Mer[0]==1,product==product+Mcand==00011110;Mer=0000,Mcand==00110000;

    Mer[0]==0,Mcand==01100000,Mer==0000;

end,product==00011110

 

 

代码入下:

 1 module multiplier (clk,rst_n,multiplier,multiplicand,start,done,product);
2 input clk;//50M
3 input rst_n;
4 input [7:0]multiplier;
5 input [7:0]multiplicand;
6 input start;
7 output done;
8 output [15:0]product;
9
10 /************************************/
11
12
13 /***********************************/
14 reg [2:0]i;
15 reg isdone;
16 reg [15:0]temp;
17 reg isneg;
18 reg [7:0]Mer;
19 reg [15:0]Mcand;
20 reg [2:0]cnt;
21 always @ (posedge clk or negedge rst_n)
22 if(!rst_n) begin
23 i<=1'b0;
24 isdone<=1'b0;
25 temp<=16'd0;
26 Mer<=8'd0;
27 Mcand<=1'b0;
28 isneg<=1'b0;
29 cnt<=1'b0;
30 end
31 else if (start)
32 case (i)
33 0:
34 begin i<=i+1'b1;
35 isneg<=multiplier[7]^multiplicand[7];
36 Mer<=multiplier[7]?(~multiplier+1'b1):multiplier;
37 Mcand<={multiplicand[7]?(~multiplicand+1'b1):multiplicand}&16'h00ff;
38 temp<=16'd0;
39 cnt<=1'b0;
40 end
41 1:
42 if(cnt==6) i<=3'd3;
43 else if (Mer[0]) begin temp<=temp+Mcand;
44 i<=i+1'b1;
45
46 end
47 else i<=i+1'b1;
48
49 2: begin Mer<=Mer>>1;
50 Mcand<=Mcand<<1;
51 i<=i-1'b1;
52 cnt<=cnt+1'b1;
53 end
54 3:begin isdone<=1'b1;
55 i<=i+1'b1;
56 end
57 4:begin isdone<=1'b0;
58 i<=1'b0;
59 end
60 default :i<=3'b000;
61 endcase
62 /*************************************/
63
64
65 /*************************************/
66 assign done=isdone;
67 assign product=isneg?(~temp+1'b1):temp;
68 /*************************************/
69 endmodule

 

41-48行用于执行加法操作,49-53用于执行移位操作。


 

测试代码无变化,如下:

  1 `timescale 1 ns/ 1 ps
2 module multiplier_vlg_tst();
3 reg clk;
4 reg [7:0] multiplicand;
5 reg [7:0] multiplier;
6 reg rst_n;
7 reg start;
8 wire done;
9 wire [15:0] product;
10 multiplier i1 (
11
12 .clk(clk),
13 .done(done),
14 .multiplicand(multiplicand),
15 .multiplier(multiplier),
16 .product(product),
17 .rst_n(rst_n),
18 .start(start)
19 );
20 /*******************************/
21 initial
22 begin
23 rst_n=0;
24 #30;
25 rst_n=1;
26 clk=1;
27 forever #10 clk=~clk;
28 end
29 /*******************************/
30 reg [3:0]i;
31 always @(posedge clk or negedge rst_n)
32 if (!rst_n)
33 begin i<=4'd0;
34 start<=1'b0;
35 multiplier<=8'd0;
36 multiplicand<=8'd0;
37 end
38 else
39 case(i)
40 0:
41 if (done)
42 begin start<=1'b0;
43 i<=i+1'b1;
44 end
45 else begin
46 multiplier<=8'd2;
47 multiplicand<=8'd10;
48 start<=1'b1;
49 end
50 1:
51 if (done)
52 begin start<=1'b0;
53 i<=i+1'b1;
54 end
55 else begin
56 multiplier<=8'd10;
57 multiplicand<=8'd2;
58 start<=1'b1;
59 end
60 2:
61 if (done)
62 begin start<=1'b0;
63 i<=i+1'b1;
64 end
65 else begin
66 multiplier<=8'd20;
67 multiplicand<=8'd5;
68 start<=1'b1;
69 end
70 3:
71 if (done)
72 begin start<=1'b0;
73 i<=i+1'b1;
74 end
75 else begin
76 multiplier<=8'd2;
77 multiplicand<=8'b11110110; //-10
78 start<=1'b1;
79 end
80 4:
81 if (done)
82 begin start<=1'b0;
83 i<=i+1'b1;
84 end
85 else begin
86 multiplier<=8'b11111110; //-2
87 multiplicand<=8'd10;
88 start<=1'b1;
89 end
90 5:
91 if (done)
92 begin start<=1'b0;
93 i<=i+1'b1;
94 end
95 else begin
96 multiplier<=8'b11110110; //-10
97 multiplicand<=8'd2;
98 start<=1'b1;
99 end
100 6:
101 if (done)
102 begin start<=1'b0;
103 i<=i+1'b1;
104 end
105 else begin
106 multiplier<=8'b11111110; //-2
107 multiplicand<=8'b11110110; //-10
108 start<=1'b1;
109 end
110 7:
111 if (done)
112 begin start<=1'b0;
113 i<=i+1'b1;
114 end
115 else begin
116 multiplier<=8'b11110110; //-10
117 multiplicand<=8'b11111110; //-2
118 start<=1'b1;
119 end
120 8:i<=4'd8;
121 default:i<=4'd8;
122 endcase
123 /**********************************/
124
125 endmodule

仿真结果:

 

结果看出:8位有符号的数,7位标志数的大小,一位符号位,所以每一位数据都要进行加和移操作耗2个时钟周期,共消耗2*7=14个时钟周期。所以无论8位多大的数都消耗14个时钟周期用于计算。

修改之后二进制乘法器

1 module multiplier (clk,rst_n,multiplier,multiplicand,start,done,product);
2 input clk;//50M
3 input rst_n;
4 input [7:0]multiplier;
5 input [7:0]multiplicand;
6 input start;
7 output done;
8 output [15:0]product;
9
10 /************************************/
11
12
13 /***********************************/
14 reg [1:0]i;
15 reg isdone;
16 reg [15:0]temp;
17 reg isneg;
18 reg [7:0]Mer;
19 reg [15:0]Mcand;
20 reg [2:0]cnt;
21 always @ (posedge clk or negedge rst_n)
22  if(!rst_n) begin
23                   i<=1'b0;
24                   isdone<=1'b0;
25                   temp<=16'd0;
26                   Mer<=8'd0;
27                   Mcand<=1'b0;
28                   isneg<=1'b0;
29                   cnt<=1'b0;
30                   end
31          else if (start)
32            case (i)
33              0:
34               begin i<=i+1'b1;
35                     isneg<=multiplier[7]^multiplicand[7];
36                     Mer<=multiplier[7]?(~multiplier+1'b1):multiplier;
37                     Mcand<={multiplicand[7]?(~multiplicand+1'b1):multiplicand}&16'h00ff;
38                     temp<=16'd0;
39                     cnt<=1'b0;
40                     end
41               1:
42                if(cnt==6) i<=2'd2;
43                else if (Mer[0]) begin temp<=temp+Mcand;
44                                         Mer<=Mer>>1;
45                                       Mcand<=Mcand<<1;
46                                       cnt<=cnt+1'b1;
47                                     end
48                      else begin
49                             Mer<=Mer>>1;
50                             Mcand<=Mcand<<1;
51                             cnt<=cnt+1'b1;
52                             end
53            
54               2:begin isdone<=1'b1;
55                        i<=i+1'b1;
56                        end
57               3:begin isdone<=1'b0;
58                        i<=1'b0;
59                        end
60                default :i<=2'b00;
61                endcase
62 /*************************************/
63
64
65 /*************************************/
66 assign done=isdone;
67 assign product=isneg?(~temp+1'b1):temp;
68 /*************************************/
69endmodule

41-53行把加法和移位放在一起。

测试代码无变化,如下:

  1 `timescale 1 ns/ 1 ps
2 module multiplier_vlg_tst();
3 reg clk;
4 reg [7:0] multiplicand;
5 reg [7:0] multiplier;
6 reg rst_n;
7 reg start;
8 wire done;
9 wire [15:0] product;
10 multiplier i1 (
11
12 .clk(clk),
13 .done(done),
14 .multiplicand(multiplicand),
15 .multiplier(multiplier),
16 .product(product),
17 .rst_n(rst_n),
18 .start(start)
19 );
20 /*******************************/
21 initial
22 begin
23 rst_n=0;
24 #30;
25 rst_n=1;
26 clk=1;
27 forever #10 clk=~clk;
28 end
29 /*******************************/
30 reg [3:0]i;
31 always @(posedge clk or negedge rst_n)
32 if (!rst_n)
33 begin i<=4'd0;
34 start<=1'b0;
35 multiplier<=8'd0;
36 multiplicand<=8'd0;
37 end
38 else
39 case(i)
40 0:
41 if (done)
42 begin start<=1'b0;
43 i<=i+1'b1;
44 end
45 else begin
46 multiplier<=8'd2;
47 multiplicand<=8'd10;
48 start<=1'b1;
49 end
50 1:
51 if (done)
52 begin start<=1'b0;
53 i<=i+1'b1;
54 end
55 else begin
56 multiplier<=8'd10;
57 multiplicand<=8'd2;
58 start<=1'b1;
59 end
60 2:
61 if (done)
62 begin start<=1'b0;
63 i<=i+1'b1;
64 end
65 else begin
66 multiplier<=8'd20;
67 multiplicand<=8'd5;
68 start<=1'b1;
69 end
70 3:
71 if (done)
72 begin start<=1'b0;
73 i<=i+1'b1;
74 end
75 else begin
76 multiplier<=8'd2;
77 multiplicand<=8'b11110110; //-10
78 start<=1'b1;
79 end
80 4:
81 if (done)
82 begin start<=1'b0;
83 i<=i+1'b1;
84 end
85 else begin
86 multiplier<=8'b11111110; //-2
87 multiplicand<=8'd10;
88 start<=1'b1;
89 end
90 5:
91 if (done)
92 begin start<=1'b0;
93 i<=i+1'b1;
94 end
95 else begin
96 multiplier<=8'b11110110; //-10
97 multiplicand<=8'd2;
98 start<=1'b1;
99 end
100 6:
101 if (done)
102 begin start<=1'b0;
103 i<=i+1'b1;
104 end
105 else begin
106 multiplier<=8'b11111110; //-2
107 multiplicand<=8'b11110110; //-10
108 start<=1'b1;
109 end
110 7:
111 if (done)
112 begin start<=1'b0;
113 i<=i+1'b1;
114 end
115 else begin
116 multiplier<=8'b11110110; //-10
117 multiplicand<=8'b11111110; //-2
118 start<=1'b1;
119 end
120 8:i<=4'd8;
121 default:i<=4'd8;
122 endcase
123 /**********************************/
124
125 endmodule

 

仿真结果:

从结果中可以看出只消耗了7个时钟周期用于计算,比前面的二进制加法器的用于计算消耗的时钟周期少了一倍。

 

 

Booth乘法器

它是对乘数重新编码,以减少乘法运算所需要的加法运算次数,他是只对乘数重新编码,而被乘数保持不变。得到的形式称为基4重新编码或比特对编码。使用booth乘法可以对两个数直接相乘,不需要考虑正数和负数。

具体操作:以8位为例

Product定义为17为用于保存结果,初始为product={8’b0,乘数,1’b0}

定义两个8位寄存器:A和B,A=被乘数,B=被乘数取反加1;

如果product最低两位为,01,product高8位加A,然后product右移一位;

如果product最低两位为10,product高8位加B,然后product右移一位;

如果product最低两位为11或00, product右移一位;

直到8位右移结束。

posted on 2011-12-15 14:33  撒萌萌  阅读(6344)  评论(0编辑  收藏  举报

导航