bit4 為 正負號
(+7) * (+7) = +49 (31H) 最大正數
~(-7) * (+7) = -49 (CFH) 最大負數
CFH = -49D 2'S complement
源自於
http://www.cis.nctu.edu.tw/~info27/ch4/multiple.htm#Booth演算法
Booth演算法
處理有號數字的最簡單方法是:首先將乘數與被乘數轉換成正數然後記住原來的正負號。而一種較簡潔的有號數字相乘的解決方法是Booth's algorithm。其構想來自下面觀察:只要具有加法與減法的能力,計算乘積應該有很多方法。假設我們想要計算(2)10X(6)10或(0010)2X(0110)2:
(0010)2 X (0110)2 ______________________ + 0000 移位(乘數是0) + 0010 相加(乘數是1) + 0010 相加(乘數是1) + 0000 移位(乘數是0) ______________________ 00001100
Booth觀察到:能夠執行加法或減法的ALU,可以用一種以上的方法得到相同的結果。如
(6)10=(-2)10+(8)10或(0110)2=(-0010)2+(1000)2
當第一次遇到1時,可以用減法取代一串的1,當遇到最後一個1後面的0時,再加上被乘數,例如:
(0010)2 X (0110)2 ______________________ + 0000 移位(乘數是0) + 0010 相減(乘數的第一個1) + 0000 移位(字串1的中間) + 0010 相加(上一步驟是最後一個1) ______________________ 00001100Booth為了求快而發明了這種解決方法,他將一群的位元分成以1作為開始,中間,結尾:
現行位元 | 現行位元之右邊位元 | 解釋 | 範例 |
1 | 0 | 一群1的開始 | 000011110002 |
1 | 1 | 一群1的中間 | 000011110002 |
0 | 1 | 一群1的結束 | 000011110002 |
0 | 0 | 一群0的中間 | 000011110002 |
- 依照目前與先前位元的不同,執行下面工作:
- 00: 字串0的中間部份,不需要算術運算
- 01: 字串1的結尾,所以將被乘數加到乘積的左半部
- 10: 字串1的開端,所以從乘積的左半部減去被乘數
- 11: 字串1的中間部份,所以不需要算術運算
- 如同前面的演算法,將乘積暫存器右移1位元
例如:以Booth演算法執行負數乘法 (0010)2X(1101)2=(11111010)2或2X(-3)=-6
重覆次數 | 步驟 | 被乘數暫存器 | 乘積暫存器 |
0 | 起始值 | 0010 | 0000 1101 0 |
1 | 10=>乘積暫存器=乘積暫存器-被乘數暫存器 | 0010 | 1110 1101 0 |
乘積暫存器右移 | 0010 | 1111 0110 1 | |
2 | 01=>乘積暫存器=乘積暫存器+被乘數暫存器 | 0010 | 0001 0110 1 |
乘積暫存器右移 | 0010 | 1111 1011 0 | |
3 | 10=>乘積暫存器=乘積暫存器-被乘數暫存器 | 0010 | 1110 1011 0 |
乘積暫存器右移 | 0010 | 1111 0101 1 | |
4 | 11=>不做任何事 | 0010 | 1111 0101 1 |
乘積暫存器右移 | 0010 | 1111 1010 1 |
module booth4x4(SW, LEDR, LEDG , CLOCK_50 ,KEY ,HEX0 ,HEX1 ,HEX2,HEX3 );
input [17:0] SW; // toggle switches
input [7:0] KEY; // Push bottom
input CLOCK_50; //Clock 27MHz , 50Mhz
output [17:0] LEDR; // red LEDS
output [8:0] LEDG; // green LEDs
output [6:0] HEX0,HEX1,HEX2,HEX3; //7-segment display
//set original program input , output
// M,x,y);
//input [3:0] x,y;
//output [7:0] M;
reg [5:0]psum1,psum2;
reg[5:0]temp;
reg [7:0] M;
wire [3:0]x,y;
wire [7:0] segout0; //HEX 0
wire [7:0] segout1; //HEX 1
assign x=SW[3:0];
assign y=SW[7:4];
assign LEDR[7:0]=SW[7:0];
//======================================
always@(x or y)
begin
case(y[1:0])
2'b00:
psum1=6'b000000;
2'b01:
psum1={x[3],x[3],x[3:0]};
2'b10:
begin
temp=~{x[3],x[3:0],1'b0}+1'b1;
if(x==4'b1000)
psum1={1'b0,x[3:0],1'b0};
else
psum1=temp;
end
2'b11:
begin
temp=~{x[3],x[3],x[3:0]}+1'b1;
if(x==4'b1000)
psum1={2'b00,x[3:0]};
else
psum1=temp;
end
default:
psum1=6'b000000;
endcase
//======================================
case(y[3:1])
3'b000:
psum2=6'b000000;
3'b001:
psum2={x[3],x[3],x[3:0]};
3'b010:
psum2={x[3],x[3],x[3:0]};
3'b011:
psum2={x[3],x[3:0],1'b0};
3'b100:
begin
temp=~{x[3],x[3:0],1'b0}+1'b1;
if(x==4'b1000)
psum2={1'b0,x[3:0],1'b0};
else
psum2=temp;
end
3'b101:
begin
temp=~{x[3],x[3],x[3:0]}+1'b1;
if(x==4'b1000)
psum2={2'b00,x[3:0]};
else
psum2=temp;
end
3'b110:
begin
temp=~{x[3],x[3],x[3:0]}+1'b1;
if(x==4'b1000)
psum2={2'b00,x[3:0]};
else
psum2=temp;
end
3'b111:
psum2=6'b000000;
default:
psum2=6'b000000;
endcase
M[1:0]=psum1[1:0];
M[7:2]={psum1[5],psum1[5],psum1[5:2]}+psum2;
end
_7seg UUT0(.hex((M[3:0])),
.seg(segout0));
_7seg UUT1(.hex((M[7:4])),
.seg(segout1));
assign HEX0=segout0[6:0];
assign HEX1=segout1[6:0];
endmodule
//-----------------------------------------
//Common-cathod seven segment display
//using case.....endcase statement
//Filename : sevenseg_case.v
//-----------------------------------------
module _7seg(hex , seg);
input [3:0] hex;
output [7:0] seg;
reg [7:0] seg;
// segment encoding
// 0
// ---
// 5 | | 1
// --- <- 6
// 4 | | 2
// ---
// 3
always @(hex)
begin
case (hex)
// Dot point is always disable
4'b0001 : seg = 8'b11111001; //1 = F9H
4'b0010 : seg = 8'b10100100; //2 = A4H
4'b0011 : seg = 8'b10110000; //3 = B0H
4'b0100 : seg = 8'b10011001; //4 = 99H
4'b0101 : seg = 8'b10010010; //5 = 92H
4'b0110 : seg = 8'b10000010; //6 = 82H
4'b0111 : seg = 8'b11111000; //7 = F8H
4'b1000 : seg = 8'b10000000; //8 = 80H
4'b1001 : seg = 8'b10010000; //9 = 90H
4'b1010 : seg = 8'b10001000; //A = 88H
4'b1011 : seg = 8'b10000011; //b = 83H
4'b1100 : seg = 8'b11000110; //C = C6H
4'b1101 : seg = 8'b10100001; //d = A1H
4'b1110 : seg = 8'b10000110; //E = 86H
4'b1111 : seg = 8'b10001110; //F = 8EH
default : seg = 8'b11000000; //0 = C0H
endcase
end
endmodule
沒有留言:
張貼留言