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

Subversion Repositories aemb

[/] [aemb/] [tags/] [AEMB_7_05/] [rtl/] [verilog/] [aeMB_decode.v] - Rev 206

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

/*
 * $Id: aeMB_decode.v,v 1.9 2007-05-17 09:08:21 sybreon Exp $
 * 
 * AEMB Instruction Decoder
 * Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net>
 *  
 * This library 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 2.1 of
 * the License, or (at your option) any later version.
 * 
 * This library 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 this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 *
 * DESCRIPTION
 * Instruction decoder
 *
 * HISTORY
 * $Log: not supported by cvs2svn $
 * Revision 1.8  2007/04/30 15:58:31  sybreon
 * Fixed minor data hazard bug spotted by Matt Ettus.
 *
 * Revision 1.7  2007/04/27 04:23:17  sybreon
 * Removed some unnecessary bubble control.
 *
 * Revision 1.6  2007/04/27 00:23:55  sybreon
 * Added code documentation.
 * Improved size & speed of rtl/verilog/aeMB_aslu.v
 *
 * Revision 1.5  2007/04/25 22:15:04  sybreon
 * Added support for 8-bit and 16-bit data types.
 *
 * Revision 1.4  2007/04/11 04:30:43  sybreon
 * Added pipeline stalling from incomplete bus cycles.
 * Separated sync and async portions of code.
 *
 * Revision 1.3  2007/04/04 06:12:27  sybreon
 * Fixed minor bugs
 *
 * Revision 1.2  2007/04/03 14:46:26  sybreon
 * Fixed endian correction issues on data bus.
 *
 * Revision 1.1  2007/03/09 17:52:17  sybreon
 * initial import
 *
 */
 
module aeMB_decode (/*AUTOARG*/
   // Outputs
   rSIMM, rMXALU, rMXSRC, rMXTGT, rRA, rRB, rRD, rOPC, rIMM, rDWBSTB,
   rDWBWE, rDLY, rLNK, rBRA, rRWE, rMXLDST, dwb_stb_o, dwb_we_o,
   // Inputs
   sDWBDAT, rDWBSEL, rREGA, rRESULT, iwb_dat_i, nclk, prst, drun,
   frun, prun
   );
   // Internal I/F
   output [31:0] rSIMM;
   output [1:0]  rMXALU;
   output [1:0]  rMXSRC, rMXTGT;
   output [4:0]  rRA, rRB, rRD;
   output [5:0]  rOPC;   
   output [15:0] rIMM;
   output 	 rDWBSTB, rDWBWE;
   output 	 rDLY, rLNK, rBRA, rRWE;
   output [1:0]  rMXLDST;
   input [31:0]  sDWBDAT;   
   input [3:0] 	 rDWBSEL;   
   input [31:0]  rREGA, rRESULT;
 
   // External I/F
   input [31:0]  iwb_dat_i;
   output 	 dwb_stb_o, dwb_we_o;
 
   // System I/F
   input 	 nclk, prst, drun, frun, prun;
 
   /**
    rOPC/rRD/rRA/rRB/rIMM
    ---------------------
    Instruction latch for the different fields of the instruction
    ISA. This part may be changed in the future to incorporate an
    instruction cache.
 
    FIXME: Endian correction!
    TODO: Modify this for block RAM based instruction cache.
    */
   wire [31:0] 	 wIREG;
   assign 	 wIREG = iwb_dat_i;   
 
   wire [5:0] 	 wOPC = wIREG[31:26];
   wire [4:0] 	 wRD = wIREG[25:21];
   wire [4:0] 	 wRA = wIREG[20:16];
   wire [4:0] 	 wRB = wIREG[15:11];   
   wire [15:0] 	 wIMM = wIREG[15:0];
 
   reg [5:0] 	 rOPC;
   reg [4:0] 	 rRD, rRA, rRB;
   reg [15:0] 	 rIMM;
   reg [5:0] 	 xOPC;
   reg [4:0] 	 xRD, xRA, xRB;
   reg [15:0] 	 xIMM;
 
   /*
   assign 	 rOPC = wOPC;
   assign 	 rRA = wRA;
   assign 	 rRB = wRB;
   assign 	 rRD = wRD;
   assign 	 rIMM = wIMM;   
   */
 
   always @(/*AUTOSENSE*/frun or wIMM or wOPC or wRA or wRB or wRD)
     if (frun) begin
	xOPC <= wOPC;
	xRD <= wRD;
	xRA <= wRA;
	xRB <= wRB;
	xIMM <= wIMM;	
     end else begin
	xOPC <= 6'o40;	
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	xIMM <= 16'h0;
	xRA <= 5'h0;
	xRB <= 5'h0;
	xRD <= 5'h0;
	// End of automatics
     end // else: !if(frun)
 
   /**
    Opcode Groups
    -------------
    Start decoding by breaking up the opcode into groups. This should
    infer a bunch of decoders on appropriate synthesis tools.
    */
 
   wire 	 fGH0 = (wOPC[5:3] == 3'o0);
   wire 	 fGH1 = (wOPC[5:3] == 3'o1);
   wire 	 fGH2 = (wOPC[5:3] == 3'o2);
   wire 	 fGH3 = (wOPC[5:3] == 3'o3);
   wire 	 fGH4 = (wOPC[5:3] == 3'o4);
   wire 	 fGH5 = (wOPC[5:3] == 3'o5);
   wire 	 fGH6 = (wOPC[5:3] == 3'o6);
   wire 	 fGH7 = (wOPC[5:3] == 3'o7);
   wire 	 fGL0 = (wOPC[2:0] == 3'o0);
   wire 	 fGL1 = (wOPC[2:0] == 3'o1);
   wire 	 fGL2 = (wOPC[2:0] == 3'o2);
   wire 	 fGL3 = (wOPC[2:0] == 3'o3);
   wire 	 fGL4 = (wOPC[2:0] == 3'o4);
   wire 	 fGL5 = (wOPC[2:0] == 3'o5);
   wire 	 fGL6 = (wOPC[2:0] == 3'o6);
   wire 	 fGL7 = (wOPC[2:0] == 3'o7);
 
   /*
    Main Decoder
    ------------
    As there aren't many instruction groups to decode, we will decode
    all the instruction families here.
    */
 
   wire 	 fADD = ({wOPC[5:4],wOPC[0]} == 3'o0);
   wire 	 fSUB = ({wOPC[5:4],wOPC[0]} == 3'o1);   
   wire 	 fLOGIC = ({wOPC[5:4],wOPC[2]} == 3'o4);
   wire 	 fMUL = ({wOPC[5:4]} == 3'o1);
 
   wire 	 fLD = ({wOPC[5:4],wOPC[2]} == 3'o6);
   wire 	 fST = ({wOPC[5:4],wOPC[2]} == 3'o7);
 
   wire 	 fBCC = (wOPC[5:4] == 2'b10) & fGL7;
   wire 	 fBRU = (wOPC[5:4] == 2'b10) & fGL6;
   wire 	 fBRA = fBRU & wRA[3];   
 
   wire 	 fSHIFT = fGH4 & fGL4;
   wire 	 fIMM = fGH5 & fGL4;
   wire 	 fRET = fGH5 & fGL5;
   wire 	 fMISC = fGH4 & fGL5;
 
   /**
    MXALU
    -----
    This signal controls the MXALU mux inside the ASLU unit.
    */
 
   reg [1:0] 	 rMXALU, xMXALU;
   always @(/*AUTOSENSE*/fBRA or fLOGIC or fSHIFT) begin // frun
      xMXALU <= //(!fNBR) ? 2'o0 :
		(fSHIFT) ? 2'o2 :
		(fLOGIC) ? 2'o1 :
		(fBRA) ? 2'o3 :
		2'o0;	
   end
 
   /**
    BCC/BRA/RET
    -----------
    This signal controls the associated muxes for BRANCH, DELAY and
    LINK operations.
    */
 
   reg 		 rMXDLY,rMXLNK,xMXDLY,xMXLNK;
   reg [1:0] 	 rMXBRA,xMXBRA;
   always @(/*AUTOSENSE*/fBCC or fBRU or fRET or frun or wRA or wRD)
     if (frun) begin
	xMXBRA <=  //(!fNBR) ? 2'o0 :
		  (fBCC) ? 2'o3 :
		  (fRET) ? 2'o1 :
		  (fBRU) ? 2'o2 :
		  2'o0;	
	xMXDLY <=  //(!fNBR) ? 1'b0 :
		  (fBCC) ? wRD[4] :
		  (fRET) ? 1'b1 :
		  (fBRU) ? wRA[4] :
		  1'b0;
     end else begin // if (frun)
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	xMXBRA <= 2'h0;
	xMXDLY <= 1'h0;
	// End of automatics
     end // else: !if(frun)
 
   always @(/*AUTOSENSE*/fBRU or wRA) begin
      xMXLNK <=  //(!fNBR) ? 1'b0 :
		 (fBRU) ? wRA[2] : 1'b0;	
   end
 
   /**
    LD/ST
    -----
    This signal controls the mux that controls the LOAD and STORE
    operations.
    */
 
   reg [1:0] 	  rMXLDST,xMXLDST;
   always @(/*AUTOSENSE*/fLD or fST or frun)
     if (frun) begin
	xMXLDST <= //(!fNBR) ? 2'o0 :
		   (fLD) ? 2'o2 :
		   (fST) ? 2'o3 :
		   2'o0;	
     end else begin
	/*UTORESET*/
	// Beginning of autoreset for uninitialized flops
	xMXLDST <= 2'h0;
	// End of automatics
     end // else: !if(frun)
 
   /** 
    SRC/TGT
    -------
    Controls the muxes that select the appropriate sources for the A,
    B and D operands. All data hazards are resolved here.    
    */
 
   reg [1:0] 	  rMXSRC, rMXTGT, rMXALT, xMXSRC,xMXTGT,xMXALT;
   wire 	  fRWE = (|rRD) & !(&rMXBRA) & !(|rMXLDST);
 
   always @(/*AUTOSENSE*/fBCC or fBRU or fRWE or rMXLDST or rRD
	    or wOPC or wRA or wRB) begin // frun
      xMXSRC <= //(!fNBR) ? 2'o0 :
		(fBRU|fBCC) ? 2'o1 : // PC
		((rRD == wRA) & (rMXLDST == 2'o2)) ? 2'o3 : // DWB
		((rRD == wRA) & fRWE) ? 2'o2 : // FWD
		2'o0; // RA
      xMXTGT <= //(!fNBR) ? 2'o0 :
		(wOPC[3]) ? 2'o1 : // IMM
		((rRD == wRB) & (rMXLDST == 2'o2)) ? 2'o3 : // DWB
		((rRD == wRB) & fRWE) ? 2'o2 : // FWD
		2'o0;	// RB
      xMXALT <= //(!fNBR) ? 2'o0 :
		//(fBRU|fBCC) ? 2'o1 : // PC
		((rRD == wRA) & (rMXLDST == 2'o2)) ? 2'o3 : // DWB
		((rRD == wRA) & fRWE) ? 2'o2 : // FWD
		2'o0; // RA
   end // always @ (...
 
   /**
    IMM Latching
    ------------
    The logic to generate either a full 32-bit or sign extended 32-bit
    immediate is done here.
    */
 
   reg [31:0] 	 rSIMM, xSIMM;
   reg [15:0] 	 rIMMHI, xIMMHI;   
   reg 		 rFIMM, xFIMM;
 
   always @(/*AUTOSENSE*/fIMM or rFIMM or rIMMHI or wIMM) begin // frun
      xSIMM <= (rFIMM) ? {rIMMHI,wIMM} : {{(16){wIMM[15]}},wIMM};
      xFIMM <= fIMM;	
      xIMMHI <= (fIMM) ? wIMM : rIMMHI;	      
   end
 
   /**
    COMPARATOR
    ----------
    This performs the comparison for conditional branches. It handles
    the necessary data hazards. It generates a branch flag that is
    used by the execution stage.
    */
 
   wire [31:0] wREGA =
	       (rMXALT == 2'o3) ? sDWBDAT :
	       (rMXALT == 2'o2) ? rRESULT :
	       rREGA;   
 
   wire        wBEQ = (wREGA == 32'd0);
   wire        wBNE = ~wBEQ;
   wire        wBLT = wREGA[31];
   wire        wBLE = wBLT | wBEQ;   
   wire        wBGE = ~wBLT;
   wire        wBGT = ~wBLE;   
 
   reg 	       rBCC;   
   always @(/*AUTOSENSE*/rRD or wBEQ or wBGE or wBGT or wBLE or wBLT
	    or wBNE)
     case (rRD[2:0])
       3'o0: rBCC <= wBEQ;
       3'o1: rBCC <= wBNE;
       3'o2: rBCC <= wBLT;
       3'o3: rBCC <= wBLE;
       3'o4: rBCC <= wBGT;
       3'o5: rBCC <= wBGE;
       default: rBCC <= 1'b0;
     endcase // case (rRD[2:0])
 
   /**
    Branch Signals
    --------------
    This controls the generation of the BRANCH, DELAY and LINK
    signals.
    */
 
   reg 	       rBRA, rDLY, rLNK, xBRA, xDLY, xLNK;
   always @(/*AUTOSENSE*/drun or rBCC or rMXBRA or rMXDLY or rMXLNK)
     if (drun) begin
	case (rMXBRA)
	  2'o0: xBRA <= 1'b0;
	  2'o3: xBRA <= rBCC;
	  default: xBRA <= 1'b1;	  
	endcase // case (rMXBRA)
 
	case (rMXBRA)
	  2'o0: xDLY <= 1'b0;	  
	  2'o3: xDLY <= rBCC & rMXDLY;
	  default: xDLY <= rMXDLY;
	endcase // case (rMXBRA)
 
	case (rMXBRA)
	  2'o2: xLNK <= rMXLNK;	  
	  default: xLNK <= 1'b0;
	endcase // case (rMXBRA)
     end else begin // if (drun)
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	xBRA <= 1'h0;
	xDLY <= 1'h0;
	xLNK <= 1'h0;
	// End of automatics
     end // else: !if(drun)
 
   /**
    MXRWE
    -----
    This signal controls the flag that determines whether a D register
    is open for writing.
    */
 
   reg 		 rRWE, xRWE;
   wire 	 wRWE = |rRD;   
   always @(/*AUTOSENSE*/drun or rMXBRA or rMXLDST or wRWE)
     if (drun) begin
	case (rMXBRA)
	  default: xRWE <= 1'b0;	 
	  2'o2: xRWE <= wRWE ^ rMXLDST[0];
	  2'o0: xRWE <= wRWE;	  
	endcase // case (rMXBRA)
     end else begin
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	xRWE <= 1'h0;
	// End of automatics
     end // else: !if(drun)
 
   /**
    Data WISHBONE Bus
    -----------------
    The STB and WE signals for the DWB are decoded here depending on
    the LOAD/STORE control signal.    
    */
 
   reg rDWBSTB, rDWBWE, xDWBSTB, xDWBWE;
   assign dwb_stb_o = rDWBSTB;
   assign dwb_we_o = rDWBWE;
 
   always @(/*AUTOSENSE*/drun or rMXLDST)
     if (drun) begin
	xDWBSTB <= rMXLDST[1];
	xDWBWE <= rMXLDST[0];
     end else begin
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	xDWBSTB <= 1'h0;
	xDWBWE <= 1'h0;
	// End of automatics
     end
 
   // PIPELINE REGISTERS ///////////////////////////////////////////////
 
   always @(negedge nclk)
     if (prst) begin
	//rOPC <= 6'o40;	
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	rBRA <= 1'h0;
	rDLY <= 1'h0;
	rDWBSTB <= 1'h0;
	rDWBWE <= 1'h0;
	rFIMM <= 1'h0;
	rIMM <= 16'h0;
	rIMMHI <= 16'h0;
	rLNK <= 1'h0;
	rMXALT <= 2'h0;
	rMXALU <= 2'h0;
	rMXBRA <= 2'h0;
	rMXDLY <= 1'h0;
	rMXLDST <= 2'h0;
	rMXLNK <= 1'h0;
	rMXSRC <= 2'h0;
	rMXTGT <= 2'h0;
	rOPC <= 6'h0;
	rRA <= 5'h0;
	rRB <= 5'h0;
	rRD <= 5'h0;
	rRWE <= 1'h0;
	rSIMM <= 32'h0;
	// End of automatics
     end else if (prun) begin // if (prst)
	rIMM <= #1 xIMM;
	rOPC <= #1 xOPC;
	rRA <= #1 xRA;
	rRB <= #1 xRB;
	rRD <= #1 xRD;
 
	rMXALU <= #1 xMXALU;
	rMXBRA <= #1 xMXBRA;
	rMXDLY <= #1 xMXDLY;
	rMXLNK <= #1 xMXLNK;
	rMXLDST <= #1 xMXLDST;
 
	rMXSRC <= #1 xMXSRC;
	rMXTGT <= #1 xMXTGT;
	rMXALT <= #1 xMXALT;
 
	rSIMM <= #1 xSIMM;
	rFIMM <= #1 xFIMM;
	rIMMHI <= #1 xIMMHI;	
 
	rBRA <= #1 xBRA;
	rDLY <= #1 xDLY;
	rLNK <= #1 xLNK;
	rRWE <= #1 xRWE;
	rDWBSTB <= #1 xDWBSTB;
	rDWBWE <= #1 xDWBWE;	
     end // if (prun)
 
endmodule // aeMB_decode
 
// Local Variables:
// verilog-library-directories:(".")
// verilog-library-files:("")
// End:

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.