📄 fpu.v
字号:
//--------------------------------------------------------------------------------
// Design Name: FPU32
// File Name: fpuv1.v
// Function: The following program implements a 32-Bit (Single Precision) Floating Point Unit
// for the following operations:
// abs.fmt, add.fmt, div.fmt, mul.fmt, neg.fmt, sub.fmt
// by checking the operand code received and doing the respective operations.
// Date: October 07th, 2007
//---------------------------------------------------------------------------------
module FPU32 (
AInput, // Input port of 32 bits A
BInput, // Input pot of 32 bits B
OpCode, // Operation code of 6 bits
Clock, // Sincronous Clock
Reset, // Reset
Output, // Operation Output of 32 bits
Overflow, // Overflow indicator of 1 bit
Zero // Zero indicator of 1 bit
);
// ---------------------------- Input ports ----------------------------
input OpCode;
input AInput;
input BInput;
input Clock;
input Reset;
// ---------------------------- Output ports ----------------------------
output Overflow;
output Zero;
output Output;
// ---------------------------- Type of Input ports ----------------------------
wire [5:0] OpCode;
wire [31:0] AInput;
wire [31:0] BInput;
wire Clock;
wire Reset;
// ---------------------------- Type of Output ports ----------------------------
reg Overflow;
reg Zero;
reg [31:0] Output;
// -------------------------- Temporaries --------------------------
reg [47:0] mantRes;
reg [7:0] expRes;
reg sgnRes;
reg [31:0] res;
reg [32:0] res2;
reg [63:0] res3;
reg [31:0] res4;
reg [31:0] ext;
reg [31:0] reg1;
reg [31:0] reg2;
reg [31:0] Bigger;
reg [31:0] Smaller;
integer i = 0;
integer j=0;
// ----------------------------------------------------
// Code Starts Here
// ----------------------------------------------------
// Include the definition of all the ALU Operations
`include "OperationsFP.v" // File "OperationsFP.v" contains all operation codes
always @ (posedge Clock)
begin: FPU // begin FPU Block
if(Reset == 1)
begin
// If the reset is on, it will clear each output
Output = 0;
Overflow = 0;
Zero = 0;
end
else
begin
case(OpCode)
C_ABS_fmt: begin // ABSOLUTE VALUE OF A FP NUMBER
res = AInput;
res[31] = 0;
Output = res;
Overflow = 0;
Zero = (Output[30:0] == 0) ? 1 : 0;
end // case: C_ABS_fmt
C_ADD_fmt: begin
if(AInput[30:23] > BInput[30:23]) // E1 > E2 ?
begin
Bigger = AInput;
Smaller = BInput;
end
else if(AInput[30:23] < BInput[30:23]) // E1 < E2 ?
begin
Smaller = AInput;
Bigger = BInput;
end
else // E1 = E2 ?
begin
if(AInput[22:0] > BInput[22:0]) // M1 > M2 ?
begin
Bigger = AInput;
Smaller = BInput;
end
else if(AInput[22:0] < BInput[22:0]) // M1 < M2 ?
begin
Smaller = AInput;
Bigger = BInput;
end
else // M1 = M2 ?
begin
Bigger = AInput; // M1 = M2
Smaller = BInput;// So |Bigger| = |Smaller|
end
end // else: !if(AInput[30:23] < BInput[30:23])
expRes = Bigger[30:23];
if((Bigger[31] ^ Smaller[31]) == 0)
begin
mantRes = {1'b1,Bigger[22:0]} + ({1'b1,Smaller[22:0]} >> (Bigger[30:23]-Smaller[30:23]));
end
else
begin
mantRes = {1'b1,Bigger[22:0]} - ({1'b1,Smaller[22:0]} >> (Bigger[30:23]-Smaller[30:23]));
end
if(mantRes[24] == 1)
begin
mantRes = mantRes >> 1;
expRes = expRes + 1;
end
else
begin
for(i=23;i>=0;i=i-1)
begin
if(mantRes[i] == 1)
begin
j = i;
i = -1;
end
end
if(i == -1)
begin
expRes = 0;
end
else
begin
mantRes = mantRes << (23-j);
expRes = expRes - (23-j);
end
end // else: !if(mantRes[24] == 1)
res = {Bigger[31],expRes,mantRes[22:0]};
Output = res;
Zero = (Output[30:0] == 0) ? 1 : 0;
end // case: C_ADD_fmt
C_DIV_fmt: begin
if((AInput[30:0] == 0) || (BInput[30:0] == 0))
begin
if(AInput[22:0] == 0)
begin
if(BInput[22:0] == 0)
begin
Output = 32'h7FC00000; // 0/0 produces NaN
Overflow = 1;
Zero = 0;
end
else
begin
res = (AInput[31] ^ BInput[31]) << 31;
Output = res;
Overflow = 0;
Zero = 1;
end // else: !if(BInput[22:0] == 0)
end // if (AInput[22:0] == 0)
else
begin
if(BInput[22:0] == 0)
begin
res = {(AInput[31] ^ BInput[31]),8'hFF,23'b0}; // Num/0 produces +- Infinity
Overflow = 0;
Zero = 0;
end
end // else: !if(AInput[22:0] == 0)
end // if ((AInput[30:0] == 0) || (BInput[30:0] == 0))
else
begin
if((AInput == 32'h7FC00000) || (BInput == 32'h7FC00000))
begin
Output = 32'h7FC00000; // If any input is originally NaN, the resulting output is NaN
Overflow = 1;
Zero = 0;
end
else
begin
mantRes = ({1'b1,AInput[22:0],24'h000000} / {1'b1,BInput[22:0]});
expRes = (AInput[30:23] - BInput[30:23]) + 127;
sgnRes = AInput[31] ^ BInput[31];
j = 24;
for(i=24;i>=23;i=i-1)
begin
if(mantRes[i] == 1)
begin
j = i;
i = 0;
end
end
mantRes = mantRes >> (j-23);
expRes = expRes - (24-j); //New exponent = Old exponent + # of shifts
res = {sgnRes,expRes,mantRes[22:0]};
Output = res;
Overflow = 0;
Zero = (Output[30:0] == 0) ? 1 : 0;
end // else: !if((AInput == 32'hFFFFFFFF) || (BInput == 32'hFFFFFFFF))
end // else: !if((AInput[30:0] == 0) || (BInput[30:0] == 0))
end // case: C_DIV_fmt
C_MUL_fmt: begin
if((AInput[30:0] == 0) || (BInput[30:0] == 0))
begin
res = (AInput[31] ^ BInput[31]) << 31;
Output = res;
Overflow = 0;
Zero = 1;
end
else
begin
if((AInput == 32'hFFFFFFFF) || (BInput == 32'hFFFFFFFF))
begin
Output = 32'hFFFFFFFF;
Overflow = 1;
Zero = 0;
end
else
begin
mantRes = ({1'b1,AInput[22:0]} * {1'b1,BInput[22:0]});
expRes = AInput[30:23] + (BInput[30:23] - 127);
sgnRes = AInput[31] ^ BInput[31];
j = 47;
for(i=47;i>=46;i=i-1)
begin
if(mantRes[i] == 1)
begin
j = i;
i = 0;
end
end
mantRes = mantRes >> (j-23);
expRes = expRes + (j-46); //New exponent = Old exponent + # of shifts
res = {sgnRes,expRes,mantRes[22:0]};
Output = res;
Overflow = 0;
Zero = (Output[30:0] == 0) ? 1 : 0;
end // else: !if((AInput == 32'hFFFFFFFF) || (BInput == 32'hFFFFFFFF))
end // else: !if((AInput[30:0] == 0) || (BInput[30:0] == 0))
end // case: C_MUL_fmt
C_NEG_fmt: begin // NEGATED VALUE OF A FP NUMBER
res = AInput;
res[31] = ~AInput[31];
Output = res;
Overflow = 0;
Zero = (Output[30:0] == 0) ? 1 : 0;
end // case: C_NEG_fmt
C_SUB_fmt: begin
if(AInput[30:23] > BInput[30:23]) // E1 > E2 ?
begin
Bigger = AInput;
Smaller = BInput;
Smaller[31] = ~Smaller[31];
end
else if(AInput[30:23] < BInput[30:23]) // E1 < E2 ?
begin
Smaller = AInput;
Bigger = BInput;
Bigger[31] = ~Bigger[31];
end
else // E1 = E2 ?
begin
if(AInput[22:0] > BInput[22:0]) // M1 > M2 ?
begin
Bigger = AInput;
Smaller = BInput;
Smaller[31] = ~Smaller[31];
end
else if(AInput[22:0] < BInput[22:0]) // M1 < M2 ?
begin
Smaller = AInput;
Bigger = BInput;
Bigger[31] = ~Bigger[31];
end
else // M1 = M2 ?
begin
Bigger = AInput; // M1 = M2
Smaller = BInput;// So |Bigger| = |Smaller|
Smaller[31] = ~Smaller[31];
end
end // else: !if(AInput[30:23] < BInput[30:23])
expRes = Bigger[30:23];
if((Bigger[31] ^ Smaller[31]) == 0)
begin
mantRes = {1'b1,Bigger[22:0]} + ({1'b1,Smaller[22:0]} >> (Bigger[30:23]-Smaller[30:23]));
end
else
begin
mantRes = {1'b1,Bigger[22:0]} - ({1'b1,Smaller[22:0]} >> (Bigger[30:23]-Smaller[30:23]));
end
if(mantRes[24] == 1)
begin
mantRes = mantRes >> 1;
expRes = expRes + 1;
end
else
begin
for(i=23;i>=0;i=i-1)
begin
if(mantRes[i] == 1)
begin
j = i;
i = -1;
end
end
if(i == -1)
begin
expRes = 0;
end
else
begin
mantRes = mantRes << (23-j);
expRes = expRes - (23-j);
end
end // else: !if(mantRes[24] == 1)
res = {Bigger[31],expRes,mantRes[22:0]};
Output = res;
Zero = (Output[30:0] == 0) ? 1 : 0;
end // case: C_SUB_fmt
endcase // case(OpCode)
end // else: !if(Reset == 1)
end // block: FPU
endmodule // FPU32
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -