📄 mult.v
字号:
//======================================================
// 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -