OpenCores
URL https://opencores.org/ocsvn/Aquarius/Aquarius/trunk

Subversion Repositories Aquarius

[/] [Aquarius/] [trunk/] [verilog/] [mult.v] - Rev 12

Compare with Previous | Blame | View Log

//======================================================
// Aquarius Project
//    SuperH-2 ISA Compatible RISC CPU
//------------------------------------------------------
// Module      : Multiplier Unit
//------------------------------------------------------
// File        : mult.v
// Library     : none
// Description : Multiplier Unit in CPU.
// Simulator   : Icarus Verilog (Cygwin)
// Synthesizer : Xilinx XST (Windows XP)
// Author      : Thorn Aitch
//------------------------------------------------------
// Revision Number : 1
// Date of Change  : 19th August 2002
// Creator         : Thorn Aitch
// Description     : Initial Design				  
//------------------------------------------------------
// Revision Number : 2
// Date of Change  : 30th April 2003
// Modifier        : Thorn Aitch
// Description     : Release Version 1.0
//======================================================
// Copyright (C) 2002-2003, Thorn Aitch
//
// Designs can be altered while keeping list of
// modifications "the same as in GNU" No money can
// be earned by selling the designs themselves, but
// anyone can get money by selling the implementation
// of the design, such as ICs based on some cores, 
// boards based on some schematics or Layouts, and
// even GUI interfaces to text mode drivers.
// "The same as GPL SW" Any update to the design
// should be documented and returned to the design. 
// Any derivative work based on the IP should be free
// under OpenIP License. Derivative work means any
// update, change or improvement on the design. 
// Any work based on the design can be either made
// free under OpenIP license or protected by any other
// license. Work based on the design means any work uses
// the OpenIP Licensed core as a building black without
// changing anything on it with any other blocks to
// produce larger design.  There is NO WARRANTY on the
// functionality or performance of the design on the
// real hardware implementation.
// On the other hand, the SuperH-2 ISA (Instruction Set
// Architecture) executed by Aquarius is rigidly
// the property of Renesas Corp. Then you have all 
// responsibility to judge if there are not any 
// infringements to Renesas's rights regarding your 
// Aquarius adoption into your design. 
// By adopting Aquarius, the user assumes all 
// responsibility for its use.
// This project may cause any damages around you, for 
// example, loss of properties, data, money, profits,
// life, or business etc. By adopting this source, 
// the user assumes all responsibility for its use.
//======================================================
 
`include "timescale.v"
`include "defines.v"
 
//****************************
// Multiply Unit Specification
//****************************
// This unit handles following multiplier related operations. 
//   DMULS.L
//   DMULU.L
//   MAC.L
//   MAC.W
//   MUL.L
//   MULS.W
//   MULU.W
// Physical multiplier size is 32bit*16bit->48bit.
// Then, 32x32 operations are executed in 2 cycles.
 
//*************************************************
// Module Definition
//*************************************************
module mult(
    // system signal
    CLK, RST,
    // command
    SLOT, MULCOM1, MULCOM2, MAC_S, WRMACH, WRMACL,
    // input data
    MACIN1, MACIN2,
    // output data
    MACH, MACL,
    // busy signal
    MAC_BUSY
    );
 
//-------------------
// Module I/O Signals
//-------------------
    input  CLK;           // clock
    input  RST;           // reset
    input  SLOT;          // cpu pipe slot
    input  MULCOM1;       // M1 latch command
    input  [7:0] MULCOM2; // M2 latch and mult engage command
                          // NOP      0 0000000 00
                          // DMULS.L  1 0111101 BD
                          // DMULU.L  1 0110101 B5
                          // MAC.L    1 0001111 8F
                          // MAC.W    1 1001111 CF
                          // MUL.L    1 0000111 87
                          // MULS.W   1 0101111 AF
                          // MULU.W   1 0101110 AE
    input  MAC_S;         // S-bit in SR
    input  WRMACH, WRMACL;// write MACH and MACL directly from data path
    input  [31:0] MACIN1; // input data 1
    input  [31:0] MACIN2; // input data 2
    output [31:0] MACH;   // output MACH
    output [31:0] MACL;   // output MACL
    output MAC_BUSY;      // busy signal (negate at final operation state)
 
//-----------------
// Internal Signals
//-----------------
    reg  [31:0] M1;   // input data1 latch
    reg  [31:0] M2;   // input data2 latch
    reg  [31:0] MB;   // input data 2 buffer to implement continuous MAC.L instruction
    reg  SELA;        // 0:A=M1, 1:A=MB
    reg  [31:0] A;    // A=M1 or A=MB (selected by SELA)
    reg  [31:0] B;    // B=M2
    reg  SHIFT;       // use lower(0)/upper(1) 16bit of B; use unshifted(0)/16bit-shifted(1) PM
    reg  SIGN;        // 0:unsigned, 1:signed (multipier operation)
    reg  SIZE;        // if 32*32 then 1, 16*16 then 0
    reg  [30:0] AH;   // lower 31bit of A
    reg  [15:0] BH;   // upper 16bit of B(0) or lower 16bit of B(1)
    reg  [46:0] ABH;  // output of Multiplier(31x16) (=A * BH) (calculated as unsigned)
    reg  [32:0] ABH2; // modified ABH
    reg  [31:0] P2;   // if signed32*32, ~SHIFT&A[31]&B[31:0], if signed16*16, ~SHIFT&A[31]&{B[15:0]:16'h0000}
    reg  [31:0] P3;   // if signed32*32, ~SHIFT&B[31]&A[31:0], if signed16*16, ~SHIFT&B[15]&A[31:0]
    reg  [31:0] P23;  // P2 + P3
    reg  [32:0] P23S; // if SIGN, ~P23, else P23
    reg  [47:0] PM;   // multiplier output (partial result) with sign
    reg  [63:0] C;    // one of the adder inputs
    reg  ZH;          // if final result is 16bit, adder input from MACH is forced to zero 
    reg  [1:0] ADD;   // 00:ADD, 10:ADDS48, 11:ADDS32 (adder functions regarding saturation)
    reg  [63:0] ADDRESULT;  // pure adder result
    reg  [63:0] ADDRESULT2; // saturated result
    reg  SAT;         // whether saturation has occured or not (to or 0001 to MACH)
    reg  LATMACH;     // latch signal of MACH by state machine
    reg  LATMACL;     // latch signal of MACL by state machine
    reg  [31:0] MACH; // actual MACH
    reg  [31:0] MACL; // actual MACL
    reg  MAC_BUSY;    // busy signal (negate at final operation state)
    reg  [3:0] STATE;     // control state
    reg  [3:0] NEXTSTATE; // next state
    reg  MAC_DISPATCH;    // mult can accept next new operation
 
//-------------------
// Main State Machine
//-------------------
    // state machine F/F
    always @(posedge CLK or posedge RST)
    begin
        if (RST == 1'b1)
            STATE <= `NOP;
        else if (MAC_DISPATCH & SLOT)
            begin                
                case(MULCOM2)
                    8'h00   : STATE <= `NOP;
                    8'hBD   : STATE <= `DMULSL;
                    8'hB5   : STATE <= `DMULUL;
                    8'h8F   : if (MAC_S == 1'b0)
                                  STATE <= `MACL0;
                              else
                                  STATE <= `MACLS;
                    8'hCF   : if (MAC_S == 1'b0)
                                  STATE <= `MACW;
                              else
                                  STATE <= `MACWS;
                    8'h87   : STATE <= `MULL;
                    8'hAF   : STATE <= `MULSW;
                    8'hAE   : STATE <= `MULUW;
                    default : STATE <= `NOP;
                endcase
            end
        else if (MAC_DISPATCH & ~SLOT)
            STATE <= `NOP;
        else if (~MAC_DISPATCH)
            STATE <= NEXTSTATE;
    end
 
//------------------
// State Transistion
//------------------
// NOP     : A=M1, BH=LowerB, unsign MULT, C=PM,                > NOP
//
// DMULSL  : A=M1, BH=LowerB, signed MULT, C=PM,       MAC<=ADD > DMULSL2
// DMULSL2 : A=M1, BH=upperB, signed MULT, C=(PM<<16), MAC<=ADD > NOP
//
// DMULUL  : A=M1, BH=LowerB, unsign MULT, C=PM,       MAC<=ADD > DMULUL2
// DMULUL2 : A=M1, BH=upperB, unsign MULT, C=(PM<<16), MAC<=ADD > NOP
//
// MACL0   : A=MB, BH=LowerB, signed MULT, C=PM,       MAC<=ADD > MACL2
// MACL2   : A=MB, BH=upperB, signed MULT, C=(PM<<16), MAC<=ADD > NOP
 
// MACLS   : A=MB, BH=LowerB, signed MULT, C=PM,       MAC<=ADDS48 > MACL2
// MACLS2  : A=MB, BH=upperB, signed MULT, C=(PM<<16), MAC<=ADDS48 > NOP
 
// MACW    : A=M1, BH=LowerB, signed MULT, C=PM,       MAC<=ADD > NOP
 
// MACWS   : A=M1, BH=LowerB, signed MULT, C=PM,       MACL<=ADDS32 > NOP
//                                                               if saturate, MACH|=0001
 
// MULL    : A=M1, BH=LowerB, signed MULT, C=PM,       MACL<=ADD > MULL2
// MULL2   : A=M1, BH=upperB, signed MULT, C=(PM<<16), MACL<=ADD > NOP
 
// MULSW   : A=M1, BH=LowerB, signed MULT, C=PM,       MACL<=ADD > NOP
 
// MULUW   : A=M1, BH=LowerB, unsign MULT, C=PM,       MACL<=ADD > NOP
 
    always @(STATE or SLOT or MULCOM2 or MAC_S)
    begin 
        case (STATE)
            `NOP    :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_000_00_000;
                      MAC_BUSY <= 1'b0;
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            `DMULSL :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_011_00_110;
                      MAC_BUSY <= 1'b1;
                      MAC_DISPATCH <= 1'b0;
                      NEXTSTATE <= `DMULSL2;
                     end
            `DMULSL2:begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_111_00_110;
                      MAC_BUSY <= 1'b0;
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            `DMULUL :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_001_00_110;
                      MAC_BUSY <= 1'b1;
                      MAC_DISPATCH <= 1'b0;
                      NEXTSTATE <= `DMULUL2;
                     end
            `DMULUL2:begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_101_00_110;
                      MAC_BUSY <= 1'b0;    
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            `MACL0  :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b1_011_00_110;
                      MAC_BUSY <= 1'b1;     
                      MAC_DISPATCH <= 1'b0;
                      NEXTSTATE <= `MACL2;
                     end
            `MACL2  :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b1_111_00_110;
                      MAC_BUSY <= 1'b0;    
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            `MACLS  :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b1_011_10_110;
                      MAC_BUSY <= 1'b1;     
                      MAC_DISPATCH <= 1'b0;
                      NEXTSTATE <= `MACLS2;
                     end
            `MACLS2 :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b1_111_10_110;
                      MAC_BUSY <= 1'b0;    
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            `MACW   :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_010_00_110;
                      MAC_BUSY <= 1'b1;    
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            `MACWS  :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_010_11_011;
                      MAC_BUSY <= 1'b0;     
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            `MULL   :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_011_00_011;
                      MAC_BUSY <= 1'b1;     
                      MAC_DISPATCH <= 1'b0;
                      NEXTSTATE <= `MULL2;
                     end
            `MULL2  :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_111_00_011;
                      MAC_BUSY <= 1'b0;    
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            `MULSW  :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_010_00_011;
                      MAC_BUSY <= 1'b0;     
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            `MULUW  :begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_000_00_011;
                      MAC_BUSY <= 1'b0;     
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
            default : begin
                      {SELA,SHIFT,SIGN,SIZE,ADD,LATMACH,LATMACL,ZH}<=9'b0_000_00_000;
                      MAC_BUSY <= 1'b0;     
                      MAC_DISPATCH <= 1'b1;
                      NEXTSTATE <= `NOP;
                     end
        endcase
    end
 
//-----------------------------------------
// Data Path
//-----------------------------------------
 
//---
// M1
//---
    always @(posedge CLK)
    begin
        if (SLOT & MULCOM1)
	   begin
            M1 <= MACIN1;
        end
    end
 
//-------
// M2
// B (=M2)
//-------
    always @(posedge CLK)
    begin
        if (SLOT & MULCOM2[7])
	   begin
            M2 <= MACIN2;
        end
    end
 
    always @(M2) B <= M2;
 
//---
// MB
//---
// if SLOT and MULCOM2=MACL, do latch M1.
    always @(posedge CLK)
    begin
        if (SLOT & MULCOM2[7] & (MULCOM2[5:0] == 6'b001111))
	   begin
            MB <= M1;
        end
    end
 
//--------
//Select A
//--------
    always @(SELA or M1 or MB)
    begin
        if (SELA)
            A <= MB;
         else
            A <= M1;
    end
 
//---------------------------------------
// lower 31bit of A	(input to Multiplier)
//---------------------------------------
    always @(A or SIZE)
    begin
	   if (SIZE == 1'b0)
	       AH <= {16'h0000,A[14:0]};
	   else
	       AH <= A[30:0];
    end
 
//---------------------------------------
// upper/lower of B (input to Multiplier)
//---------------------------------------
    always @(B or SHIFT or SIZE)
    begin
        if (SIZE == 1'b0)
		  BH <= {1'b0,B[14:0]};
        else if (SHIFT == 1'b0)
            BH <= B[15:0];
        else
            BH <= {1'b0,B[30:16]};
    end
 
//-----------
// Multiplier
//----------
    always @(AH or BH)
    begin
        ABH[46:0] <= AH[30:0] * BH[15:0]; // 31bit * 16bit -> 47bit
    end
 
//---
// PM
//---
    always @(SHIFT or SIZE or A or B)
    begin
        if (SHIFT)
	       begin
			 P2 <= {1'b0, (A[31])? B[30:0]:31'h00000000};
			 P3 <= {1'b0, (B[31])? A[30:0]:31'h00000000};
		  end
	   else if(~SIZE)
	       begin
			 P2 <= {17'h00000, (A[15])? B[14:0]:15'h0000};
			 P3 <= {17'h00000, (B[15])? A[14:0]:15'h0000};
		  end
	   else
	       begin
			 P2 <= 32'h00000000;
			 P3 <= 32'h00000000;
		  end
    end
 
    always @(P2 or P3)
    begin
        P23 <= P2 + P3;
    end
 
    always @(ABH or SHIFT or SIZE or A or B)
    begin
        if (SIZE == 1'b0)
	       ABH2 <= {17'h00000,(A[15] & B[15]),ABH[29:15]};
        else if (SHIFT == 1'b0)
            ABH2 <= {1'b0, ABH[46:15]};
	   else
	       ABH2 <= {1'b0,(A[31] & B[31]),ABH[45:15]};
    end
 
    always @(P23 or SIGN)
    begin
        if (SIGN == 1'b0)
	       P23S <= {1'b0, P23};
	   else
	       P23S <= {1'b1,~P23};
    end
 
    always @(P23S or ABH or ABH2 or SIGN)
    begin
	   PM[47:15] <= ABH2[32:0] + P23S + SIGN;
	   PM[14: 0] <= ABH[14: 0];
    end
 
//---------
// Select C
//---------
    always @(PM or SHIFT or SIZE)
    begin
        if (SHIFT == 1'b0)
            if (~SIZE & PM[47])
                C <= {16'hffff, PM};
            else 
                C <= {16'h0000, PM};
        else
            C <= {PM, 16'h0000};
    end
 
//-------------------------------------
// 64bit ADDER with Satulating function
//-------------------------------------
//
// Essential of Saturate Operation [ MAC[64] + C[64] ]
//
//   +S     |             Left plane shows value of MAC.
//     \    |             "+S" is + side saturate value (ex.00007FFF).
//      \  <P>            "-S" is - side saturate value (ex.FFFF8000).
//  <P'> \  |             Addition of plus C rotates MAC value counterclockwise.
//        \ |             Addition of minus C rotates MAC value clockwise.                                                     
// 7F..    \|     00..
// -------------------    Region<M'> : MAC=80000000~FFFF7FFF
// 80..    /|     FF..    Region<M > : MAC=FFFF8000~FFFFFFFF
//        / |             Region<P > : MAC=00000000~00007FFF
//  <M'> /  |             Region<P'> : MAC=00008000~7FFFFFFF
//      /  <M>  
//     /    |             Note that initial MAC value may be in any region.
//   -S     |             And value C may also be 00000000~FFFFFFFF.
//                                            
// ===========================================
// Initial_MAC  Rotation(C)  MAC+C  Result_MAC
// ===========================================
//     P            +          P     OK      
//     P            +          P'    00007FFF
//     P            +          M'    00007FFF
//     P            +          M     00007FFF 
// -------------------------------------------
//     P'           +          P     00007FFF Impossible      
//     P'           +          P'    00007FFF
//     P'           +          M'    00007FFF
//     P'           +          M     00007FFF 
// -------------------------------------------
//     M'           +          P     OK      
//     M'           +          P'    00007FFF Imposible
//     M'           +          M'    FFFF8000
//     M'           +          M     OK       
// -------------------------------------------
//     M            +          P     OK      
//     M            +          P'    00007FFF
//     M            +          M'    00007FFF Impossible
//     M            +          M     OK       
// ===========================================
//     P            -          P     OK      
//     P            -          P'    FFFF8000 Impossible
//     P            -          M'    FFFF8000
//     P            -          M     OK 
// -------------------------------------------
//     P'           -          P     OK      
//     P'           -          P'    00007FFF
//     P'           -          M'    FFFF8000 Impossible
//     P'           -          M     OK 
// -------------------------------------------
//     M'           -          P     FFFF8000      
//     M'           -          P'    FFFF8000
//     M'           -          M'    FFFF8000
//     M'           -          M     FFFF8000 Impossible       
// -------------------------------------------
//     M            -          P     FFFF8000      
//     M            -          P'    FFFF8000
//     M            -          M'    FFFF8000
//     M            -          M     OK       
// ===========================================
 
// Again, Compactly...                               
// ===========================================
// Initial_MAC  Rotation(C)  MAC+C  Result_MAC
// ===========================================
//     P /M        +/-        P /M  OK      
//     P /M        +/-        P'/M' 00007FFF/FFFF8000
//     P /M        +/-        M'/P' 00007FFF/FFFF8000
//     P /M        +/-        M /P  00007FFF/FFFF8000
// -------------------------------------------
//     P'/M'       +/-        P /M  Impossible = Don't care      
//     P'/M'       +/-        P'/M' 00007FFF/FFFF8000
//     P'/M'       +/-        M'/P' 00007FFF/FFFF8000
//     P'/M'       +/-        M /P  00007FFF/FFFF8000
// -------------------------------------------
//     M'/P'       +/-        P /M  OK      
//     M'/P'       +/-        P'/M' Impossible = Don't care
//     M'/P'       +/-        M'/P' FFFF8000/00007FFF <--caution !
//     M'/P'       +/-        M /P  OK       
// -------------------------------------------
//     M /P        +/-        P /M  OK      
//     M /P        +/-        P'/M' 00007FFF/FFFF8000
//     M /P        +/-        M'/P' Impossible = Don't care
//     M /P        +/-        M /P  OK       
// ===========================================
 
// Again, Much Compactly...                                  
// ===========================================
// Initial_MAC  Rotation(C)  MAC+C  Result_MAC
// ===========================================
//     P /M        +/-        P /M  OK      
//     P /M        +/-        P'/M' 00007FFF/FFFF8000
//     P /M        +/-        - /+  00007FFF/FFFF8000
// -------------------------------------------
//     P'/M'       +/-        P /M  Impossible = Don't care      
//     P'/M'       +/-        P'/M' 00007FFF/FFFF8000
//     P'/M'       +/-        - /+  00007FFF/FFFF8000
// -------------------------------------------
//     M'/P'       +/-        P /M  OK 
//     - /+        +/-        M'/P' FFFF8000/00007FFF <--caution !
//     M'/P'       +/-        M /P  OK       
// -------------------------------------------
//     M /P        +/-        P /M  OK      
//     - /+        +/-        P'/M' 00007FFF/FFFF8000
//     M /P        +/-        M /P  OK       
// ===========================================
 
// Again, Much Compactly...                                  
// ===========================================
// Initial_MAC  Rotation(C)  MAC+C  Result_MAC
// ===========================================
//     + /-        +/-        P /M  OK      
//     + /-        +/-        P'/M' 00007FFF/FFFF8000
//     + /-        +/-        - /+  00007FFF/FFFF8000
// -------------------------------------------
//     - /+        +/-        P /M  OK 
//     - /+        +/-        M'/P' FFFF8000/00007FFF <--caution !
//     - /+        +/-        M /P  OK       
//     - /+        +/-        P'/M' 00007FFF/FFFF8000
// ===========================================
 
// Again, Much Compactly...                                  
// ===========================================
// Initial_MAC  Rotation(C)  MAC+C  Result_MAC
// ===========================================
//     * /*        +/-        P /M  OK      
//     * /*        +/-        P'/M' 00007FFF/FFFF8000
//     + /-        +/-        - /+  00007FFF/FFFF8000
//     - /+        +/-        M'/P' FFFF8000/00007FFF <--caution !
//     - /+        +/-        M /P  OK       
// ===========================================
 
    always @(C or MACH or MACL or ZH)
    begin
        ADDRESULT <= C + {((ZH == 1'b0) ? MACH : 32'h00000000), MACL};
    end
 
    reg [1:0] RESULT_REGION48; //00:P, 01:P', 10:M, 11:M'
    reg       RESULT_REGION32; //0:P, 1:M, No P'/M' region in case of 32bit saturation.
    always @(ADDRESULT)
    begin
        RESULT_REGION48[1] <=  ADDRESULT[63];
        RESULT_REGION32    <=  ADDRESULT[31];
        if (ADDRESULT[63] == 1'b0)
          //RESULT_REGION48[0] <= (ADDRESULT[63:47] >= 17'h00001);
		  RESULT_REGION48[0] <= (ADDRESULT[63:47] != 17'h00000);
        else
          //RESULT_REGION48[0] <= (ADDRESULT[63:47] <= 17'hFFFFE);
		  RESULT_REGION48[0] <= (ADDRESULT[63:47] != 17'hFFFFF);
    end
 
    always @(ADDRESULT or C or MACH or MACL or ADD or RESULT_REGION48 or RESULT_REGION32)
    begin
        case(ADD)
            2'b00   : begin // ADD
                          ADDRESULT2 <= ADDRESULT;
                          SAT <= 1'b0;
                      end
            2'b10   : begin // ADDS48
                          if (~C[63]) // + rotation
                              case ({MACH[31], RESULT_REGION48})
                                  3'b000 : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //+,P
                                  3'b001 : {ADDRESULT2,SAT} <= {64'h00007FFFFFFFFFFF,1'b1}; //+,P'
                                  3'b010 : {ADDRESULT2,SAT} <= {64'h00007FFFFFFFFFFF,1'b1}; //+,M
                                  3'b011 : {ADDRESULT2,SAT} <= {64'h00007FFFFFFFFFFF,1'b1}; //+,M'
                                  3'b100 : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //-,P
                                  3'b101 : {ADDRESULT2,SAT} <= {64'h00007FFFFFFFFFFF,1'b1}; //-,P'
                                  3'b110 : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //-,M
                                  3'b111 : {ADDRESULT2,SAT} <= {64'hFFFF800000000000,1'b1}; //-,M'
                                  default: {ADDRESULT2,SAT} <= {64'hxxxxxxxxxxxxxxxx,1'bx};
                              endcase
                          else        // - rotation
                              case ({MACH[31], RESULT_REGION48})
                                  3'b000 : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //+,P
                                  3'b001 : {ADDRESULT2,SAT} <= {64'h00007FFFFFFFFFFF,1'b1}; //+,P'
                                  3'b010 : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //+,M
                                  3'b011 : {ADDRESULT2,SAT} <= {64'hFFFF800000000000,1'b1}; //+,M'
                                  3'b100 : {ADDRESULT2,SAT} <= {64'hFFFF800000000000,1'b1}; //-,P
                                  3'b101 : {ADDRESULT2,SAT} <= {64'hFFFF800000000000,1'b1}; //-,P'
                                  3'b110 : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //-,M
                                  3'b111 : {ADDRESULT2,SAT} <= {64'hFFFF800000000000,1'b1}; //-,M'
                                  default: {ADDRESULT2,SAT} <= {64'hxxxxxxxxxxxxxxxx,1'bx};
                              endcase
                      end
            2'b11   : begin // ADDS32
                          if (~C[31]) // + rotation
                              case ({MACL[31], RESULT_REGION32})
                                  2'b00  : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //+,P
                                  2'b01  : {ADDRESULT2,SAT} <= {64'h000000007FFFFFFF,1'b1}; //+,M
                                  2'b10  : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //-,P
                                  2'b11  : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //-,M
                                  default: {ADDRESULT2,SAT} <= {64'hxxxxxxxxxxxxxxxx,1'bx};
                              endcase
                          else        // - rotation
                              case ({MACL[31], RESULT_REGION32})
                                  2'b00  : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //+,P
                                  2'b01  : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //+,M
                                  2'b10  : {ADDRESULT2,SAT} <= {64'hFFFFFFFF80000000,1'b1}; //-,P
                                  2'b11  : {ADDRESULT2,SAT} <= {ADDRESULT,1'b0};            //-,M
                                  default: {ADDRESULT2,SAT} <= {64'hxxxxxxxxxxxxxxxx,1'bx};
                              endcase
                      end
            default : begin 
                          ADDRESULT2 <= 64'hxxxxxxxxxxxxxxxx;
                          SAT <= 1'b0;
                      end
        endcase
    end
 
//-----
// MACH
//-----
// Clear condition of MACH: following command do not clear MACH
                          // MAC.L    1 0001111 8F
                          // MAC.W    1 1001111 CF
                          // MUL.L    1 0000111 87
                          // MULS.W   1 0101111 AF
                          // MULU.W   1 0101110 AE
// Should do saturating operation 
    always @(posedge CLK)
    begin
        if (SLOT & WRMACH)
            MACH <= MACIN1;
        else if (SLOT & MULCOM2[7] 
                 & (MULCOM2[5:0] != 6'b001111) 
                 & (MULCOM2[6:0] != 7'b0000111)
                 & (MULCOM2[6:0] != 7'b0101111) 
                 & (MULCOM2[6:0] != 7'b0101110)
           )
            begin
                MACH <= 32'h00000000;
            end
        else if ((STATE == `MACWS) && (SAT == 1'b1))
            begin
                MACH <= MACH | 32'h00000001;
            end
        else if (LATMACH == 1'b1)
            begin
                MACH <= ADDRESULT2[63:32];
            end
    end
 
//-----
// MACL
//-----
// Clear condition of MACL: following command do not clear MACL
                          // MAC.L    1 0001111 8F
                          // MAC.W    1 1001111 CF
    always @(posedge CLK)
    begin
        if (SLOT & WRMACL)
            MACL <= MACIN2;
        else if (SLOT & MULCOM2[7] & (MULCOM2[5:0] != 6'b001111))
            begin
                MACL <= 32'h00000000;
            end
        else if (LATMACL == 1'b1)
            begin
                MACL <= ADDRESULT2[31:0];
            end
    end
 
//======================================================
  endmodule
//======================================================

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.