⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fpu.v

📁 MIPS CPU tested in Icarus Verilog
💻 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 + -