2012年10月30日 星期二

P11-20 4bit X 4bitt booth multiplierbit4 為 正負號

P11-20  4bit X 4bitt booth multiplier

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)
______________________
       00001100
Booth為了求快而發明了這種解決方法,他將一群的位元分成以1作為開始,中間,結尾:
如果我們局限在只看兩個位元,根據兩個位元的值,我們得到符合前面圖中的狀況:
現行位元現行位元之右邊位元解釋範例
10一群1的開始000011110002
11一群1的中間000011110002
01一群1的結束000011110002
00一群0的中間000011110002
Booth演算法一次看乘數的兩個位元
  • 依照目前與先前位元的不同,執行下面工作:
    • 00: 字串0的中間部份,不需要算術運算
    • 01: 字串1的結尾,所以將被乘數加到乘積的左半部
    • 10: 字串1的開端,所以從乘積的左半部減去被乘數
    • 11: 字串1的中間部份,所以不需要算術運算
  • 如同前面的演算法,將乘積暫存器右移1位元
在準備好開始之前,將虛構位元0放在最右邊位元的右邊。將乘積右移時,因為我們是處理有號數字,必須保留中間過程結果的正負符號,所以當乘積向右移時,擴展其符號。因此第一次重覆迴圈的乘積暫存器右移1位元時,將(111001110)2轉換成(111100111)2,不是(011100111)2,這種移位稱為算術右移(arithemetic right shift),有別於邏輯右移。
例如:以Booth演算法執行負數乘法 (0010)2X(1101)2=(11111010)2或2X(-3)=-6
重覆次數步驟被乘數暫存器乘積暫存器
0起始值00100000 1101 0
110=>乘積暫存器=乘積暫存器-被乘數暫存器00101110 1101 0
乘積暫存器右移00101111 0110 1
201=>乘積暫存器=乘積暫存器+被乘數暫存器00100001 0110 1
乘積暫存器右移00101111 1011 0
310=>乘積暫存器=乘積暫存器-被乘數暫存器00101110 1011 0
乘積暫存器右移00101111 0101 1
411=>不做任何事00101111 0101 1
乘積暫存器右移00101111 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



沒有留言:

張貼留言

2024_09 作業3 以Node-Red 為主

 2024_09 作業3  (以Node-Red 為主  Arduino 可能需要配合修改 ) Arduino 可能需要修改的部分 1)mqtt broker  2) 主題Topic (發行 接收) 3) WIFI ssid , password const char br...