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

Subversion Repositories aemb

[/] [aemb/] [trunk/] [rtl/] [verilog/] [aeMB2_intu.v] - Rev 200

Go to most recent revision | Compare with Previous | Blame | View Log

/* $Id: aeMB2_intu.v,v 1.7 2008-05-01 12:00:18 sybreon Exp $
**
** AEMB2 EDK 6.2 COMPATIBLE CORE
** Copyright (C) 2004-2008 Shawn Tan <shawn.tan@aeste.net>
**  
** This file is part of AEMB.
**
** AEMB is free software: you can redistribute it and/or modify it
** under the terms of the GNU Lesser General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** AEMB is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
** or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
** Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with AEMB. If not, see <http:**www.gnu.org/licenses/>.
*/
/**
 * One Cycle Integer Unit
 * @file aeMB2_intu.v
 
 * This implements a single cycle integer unit. It performs all basic
   arithmetic, shift, and logic operations. 
 
 */
 
module aeMB2_intu (/*AUTOARG*/
   // Outputs
   mem_ex, bpc_ex, alu_ex, alu_mx, msr_ex, sfr_mx,
   // Inputs
   opc_of, opa_of, opb_of, opd_of, imm_of, rd_of, ra_of, gclk, grst,
   dena, gpha
   );
   parameter AEMB_DWB = 32;   
   parameter AEMB_IWB = 32;
   parameter AEMB_HTX = 1;
 
   output [31:2] mem_ex;
   output [31:2] bpc_ex;   
 
   output [31:0] alu_ex,
		 alu_mx;   
 
   //input [2:0] 	 mux_of;   
   input [5:0] 	 opc_of;
   input [31:0]  opa_of;
   input [31:0]  opb_of;
   input [31:0]  opd_of;   
   input [15:0]  imm_of;
   input [4:0] 	 rd_of,
		 ra_of;   
   output [7:0]  msr_ex;   
   output [31:0] sfr_mx;   
 
   // SYS signals
   input 	 gclk,
		 grst,
		 dena,
		 gpha;      
 
   /*AUTOREG*/
   // Beginning of automatic regs (for this module's undeclared outputs)
   reg [31:0]		alu_ex;
   reg [31:0]		alu_mx;
   reg [31:2]		bpc_ex;
   reg [31:2]		mem_ex;
   reg [31:0]		sfr_mx;
   // End of automatics
 
   localparam [2:0] 	MUX_SFR = 3'o7,
			MUX_BSF = 3'o6,
			MUX_MUL = 3'o5,
			MUX_MEM = 3'o4,
 
			MUX_RPC = 3'o2,
			MUX_ALU = 3'o1,
			MUX_NOP = 3'o0;   
 
   reg 			rMSR_C,
			rMSR_CC,
			rMSR_MTX,
			rMSR_DTE, 
			rMSR_ITE,
			rMSR_BIP, 
			rMSR_IE,
			rMSR_BE;   
 
   // Infer a ADD with carry cell because ADDSUB cannot be inferred
   // across technologies.
 
   reg [31:0] 		add_ex;
   reg 			add_c;
 
   wire [31:0] 		wADD;
   wire 		wADC;
 
   wire 		fCCC = !opc_of[5] & opc_of[1]; // & !opc_of[4]
   wire 		fSUB = !opc_of[5] & opc_of[0]; // & !opc_of[4]
   wire 		fCMP = !opc_of[3] & imm_of[1]; // unsigned only
   wire 		wCMP = (fCMP) ? !wADC : wADD[31]; // cmpu adjust
 
   wire [31:0] 		wOPA = (fSUB) ? ~opa_of : opa_of;
   wire 		wOPC = (fCCC) ? rMSR_CC : fSUB;
 
   assign 		{wADC, wADD} = (opb_of + wOPA) + wOPC; // add carry
 
   always @(/*AUTOSENSE*/wADC or wADD or wCMP) begin
      {add_c, add_ex} <= #1 {wADC, wCMP, wADD[30:0]}; // add with carry
   end
 
   // SHIFT/LOGIC/MOVE
   reg [31:0] 		slm_ex;
 
   always @(/*AUTOSENSE*/imm_of or opa_of or opb_of or opc_of
	    or rMSR_CC)
     case (opc_of[2:0])
       // LOGIC
       3'o0: slm_ex <= #1 opa_of | opb_of;
       3'o1: slm_ex <= #1 opa_of & opb_of;
       3'o2: slm_ex <= #1 opa_of ^ opb_of;
       3'o3: slm_ex <= #1 opa_of & ~opb_of;
       // SHIFT/SEXT
       3'o4: case ({imm_of[6:5],imm_of[0]})
	       3'o1: slm_ex <= #1 {opa_of[31],opa_of[31:1]}; // SRA
	       3'o3: slm_ex <= #1 {rMSR_CC,opa_of[31:1]}; // SRC
	       3'o5: slm_ex <= #1 {1'b0,opa_of[31:1]}; // SRL
	       3'o6: slm_ex <= #1 {{(24){opa_of[7]}}, opa_of[7:0]}; // SEXT8
	       3'o7: slm_ex <= #1  {{(16){opa_of[15]}}, opa_of[15:0]}; // SEXT16
	       default: slm_ex <= #1 32'hX;
	     endcase // case ({imm_of[6:5],imm_of[0]})
       // MFS/MTS/MSET/MCLR
       //3'o5: slm_ex <= #1 sfr_of;       
       // BRL (PC from SFR)
       //3'o6: slm_ex <= #1 sfr_of;
       default: slm_ex <= #1 32'hX;       
     endcase // case (opc_of[2:0])
 
   // ALU RESULT
   always @(posedge gclk)
     if (grst) begin
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	alu_ex <= 32'h0;
	alu_mx <= 32'h0;
	bpc_ex <= 30'h0;
	mem_ex <= 30'h0;
	// End of automatics
     end else if (dena) begin
	alu_mx <= #1 alu_ex;
	alu_ex <= #1 (opc_of[5]) ? slm_ex : add_ex;	
	mem_ex <= #1 wADD[AEMB_DWB-1:2]; // LXX/SXX	
	bpc_ex <= #1 
		  (!opc_of[0] & ra_of[3]) ? // check for BRA
		  opb_of[AEMB_IWB-1:2] : // BRA only
		  wADD[AEMB_IWB-1:2]; // RTD/BCC/BR
     end
 
   // MSR SECTION
 
   /*
    MSR REGISTER
 
    We should keep common configuration bits in the lower 16-bits of
    the MSR in order to avoid using the IMMI instruction.
 
    MSR bits
    31 - CC (carry copy)    
    30 - HTE (hardware thread enabled)
    29 - PHA (current phase)
 
    7  - DTE (data cache enable)       
    5  - ITE (instruction cache enable)    
    4  - MTX (hardware mutex bit)
    3  - BIP (break in progress)
    2  - C (carry flag)
    1  - IE (interrupt enable)
    0  - BE (bus-lock enable)        
    */
 
   assign msr_ex = {
		    rMSR_DTE,
		    1'b0,
		    rMSR_ITE,
		    rMSR_MTX,
		    rMSR_BIP,
		    rMSR_C,
		    rMSR_IE,
		    rMSR_BE 
		    };
 
   // MSRSET/MSRCLR (small ALU)
   wire [7:0] wRES = (ra_of[0]) ? 
	      (msr_ex[7:0]) & ~imm_of[7:0] : // MSRCLR
	      (msr_ex[7:0]) | imm_of[7:0]; // MSRSET      
 
   // 0 - Break
   // 1 - Interrupt
   // 2 - Exception
   // 3 - Reserved
   wire       fRTID = (opc_of == 6'o55) & rd_of[0];
   wire       fRTBD = (opc_of == 6'o55) & rd_of[1];
 
   wire       fBRKI = (opc_of == 6'o56) & (ra_of[4:0] == 5'hD);
   wire       fBRKB = ((opc_of == 6'o46) | (opc_of == 6'o56)) & (ra_of[4:0] == 5'hC);
 
   wire       fMOV = (opc_of == 6'o45);
   wire       fMTS = fMOV & &imm_of[15:14];
   wire       fMOP = fMOV & ~|imm_of[15:14];   
 
   reg [31:0] sfr_ex;
 
   always @(posedge gclk)
     if (grst) begin
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	rMSR_BE <= 1'h0;
	rMSR_BIP <= 1'h0;
	rMSR_DTE <= 1'h0;
	rMSR_IE <= 1'h0;
	rMSR_ITE <= 1'h0;
	rMSR_MTX <= 1'h0;
	sfr_ex <= 32'h0;
	sfr_mx <= 32'h0;
	// End of automatics
     end else if (dena) begin // if (grst)
	sfr_mx <= #1 sfr_ex;	
	sfr_ex <= #1
		  {rMSR_CC,
		   AEMB_HTX[0],
		   gpha,
		   21'd0,
		   rMSR_DTE,
		   1'b0,
		   rMSR_ITE,
		   rMSR_MTX,
		   rMSR_BIP,
		   rMSR_CC,
		   rMSR_IE,
		   rMSR_BE 
		   };
 
	rMSR_DTE <= #1
		   (fMTS) ? opa_of[7] :
		   (fMOP) ? wRES[7] :
		   rMSR_DTE;	
 
	rMSR_ITE <= #1
		   (fMTS) ? opa_of[5] :
		   (fMOP) ? wRES[5] :
		   rMSR_ITE;
 
	rMSR_MTX <= #1
		   (fMTS) ? opa_of[4] :
		   (fMOP) ? wRES[4] :
		   rMSR_MTX;	
 
	rMSR_BE <= #1
		   (fMTS) ? opa_of[0] :
		   (fMOP) ? wRES[0] :
		   rMSR_BE;	
 
	rMSR_IE <= #1
		   (fBRKI) ? 1'b0 :
		   (fRTID) ? 1'b1 :
		   (fMTS) ? opa_of[1] :
		   (fMOP) ? wRES[1] :
		   rMSR_IE;			
 
	rMSR_BIP <= #1
		    (fBRKB) ? 1'b1 :
		    (fRTBD) ? 1'b0 :
		    (fMTS) ? opa_of[3] :
		    (fMOP) ? wRES[3] :
		    rMSR_BIP;
	/*
 
	case ({fMTS, fMOP})
	  2'o2: {rMSR_DTE,
		 rMSR_ITE,
		 rMSR_MTX,
		 rMSR_BE} <= #1 {opa_of[7],
				 opa_of[5],
				 opa_of[4],
				 opa_of[0]};	  
	  2'o1: {rMSR_DTE,
		 rMSR_ITE,
		 rMSR_MTX,
		 rMSR_BE} <= #1 {wRES[7],
				 wRES[5],
				 wRES[4],
				 wRES[0]};	  
	  default: {rMSR_DTE,
		    rMSR_ITE,
		    rMSR_MTX,
		    rMSR_BE} <= #1 {rMSR_DTE,
				    rMSR_ITE,
				    rMSR_MTX,
				    rMSR_BE};	  
	endcase // case ({fMTS, fMOP})
 
	case ({fMTS, fMOP})
	  2'o2: {rMSR_BIP,
		 rMSR_IE} <= #1 {opa_of[3],
				 opa_of[1]};
	  2'o1: {rMSR_BIP,
		 rMSR_IE} <= #1 {wRES[3],
				 wRES[1]};
	  default: begin
	     rMSR_BIP <= #1 (fBRKB | fRTBD) ? !rMSR_BIP : rMSR_BIP;	     
	     rMSR_IE <= #1 (fBRKI | fRTID) ? !rMSR_IE : rMSR_IE;
	  end
	endcase // case ({fMTS, fMOP})
	 */
     end // if (dena)
 
   // BARREL C
   wire fADDSUB = !opc_of[5] & !opc_of[4] & !opc_of[2];
   // (opc_of[5:2] == 4'h0) | (opc_of[5:2] == 4'h2);
   wire fSHIFT  = (opc_of == 6'o44) & &imm_of[6:5];   
 
   always @(posedge gclk)
     if (grst) begin
	/*AUTORESET*/
     end else if (dena) begin
     end
 
   always @(posedge gclk)
     if (grst) begin
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	rMSR_C <= 1'h0;
	rMSR_CC <= 1'h0;
	// End of automatics
     end else if (dena) begin
	rMSR_CC <= #1 rMSR_C;
 
	rMSR_C <= #1
		  (fMTS) ? opa_of[2] :
		  (fMOP) ? wRES[2] :
		  (fSHIFT) ? opa_of[0] : // SRA/SRL/SRC
		  (fADDSUB) ? add_c : // ADD/SUB/ADDC/SUBC
		  rMSR_CC;
 
	/*
	case ({fMTS,fMOP,fSHIFT,fADDSUB})
	  4'h8: rMSR_C <= #1 opa_of[2];
	  4'h4: rMSR_C <= #1 wRES[2];
	  4'h2: rMSR_C <= #1 opa_of[0];
	  4'h1: rMSR_C <= #1 add_c;	  
	  default: rMSR_C <= #1 rMSR_CC;	  
	endcase // case ({fMTS,fMOP,fSHIFT,fADDSUB})	
	*/
     end
 
endmodule // aeMB2_intu
 
/*
 $Log: not supported by cvs2svn $
 Revision 1.6  2008/04/28 08:15:25  sybreon
 Optimisations.
 
 Revision 1.5  2008/04/26 17:57:43  sybreon
 Minor performance improvements.
 
 Revision 1.4  2008/04/26 01:09:06  sybreon
 Passes basic tests. Minor documentation changes to make it compatible with iverilog pre-processor.
 
 Revision 1.3  2008/04/23 14:18:30  sybreon
 Fixed CMP bug.
 
 Revision 1.2  2008/04/21 12:11:38  sybreon
 Passes arithmetic tests with single thread.
 
 Revision 1.1  2008/04/18 00:21:52  sybreon
 Initial import.
*/
 

Go to most recent revision | 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.