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

Subversion Repositories aemb

[/] [aemb/] [trunk/] [rtl/] [verilog/] [aeMB2_ctrl.v] - Rev 120

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

/* $Id: aeMB2_ctrl.v,v 1.2 2008-04-20 16:34:32 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/>.
*/
 
/**
 * Instruction Decode & Control
 * @file aeMB2_ctrl.v
 
 * This is the data decoder that will control the command signals and
   operand fetch. 
 
 */
 
module aeMB2_ctrl (/*AUTOARG*/
   // Outputs
   opa_of, opb_of, opd_of, opc_of, ra_of, rd_of, imm_of, rd_ex,
   mux_of, mux_ex, hzd_bpc, hzd_fwd,
   // Inputs
   opa_if, opb_if, opd_if, bra_ex, rpc_if, alu_ex, ich_dat, gclk,
   grst, dena, iena, gpha
   );
   parameter AEMB_HTX = 1;   
 
   // EX CONTROL
   output [31:0] opa_of;
   output [31:0] opb_of;
   output [31:0] opd_of;
   output [5:0]  opc_of;   
   output [4:0]  ra_of,
		 //rb_of,
		 rd_of;
   output [15:0] imm_of;   
   output [4:0]	 rd_ex;   
 
   // REGS
   input [31:0]  opa_if,
		 opb_if,
		 opd_if;   
 
   // WB CONTROL
   output [2:0]  mux_of,
		 mux_ex;   
 
   // INTERNAL
   input [1:0] 	 bra_ex;   
   input [31:2]  rpc_if;   
   input [31:0]  alu_ex;   
   input [31:0]  ich_dat;
 
   output 	 hzd_bpc;   
   output 	 hzd_fwd;
 
   // SYSTEM
   input 	 gclk,
		 grst,
		 dena,
		 iena,
		 gpha;   
 
   /*AUTOREG*/
   // Beginning of automatic regs (for this module's undeclared outputs)
   reg [15:0]		imm_of;
   reg [2:0]		mux_ex;
   reg [2:0]		mux_of;
   reg [31:0]		opa_of;
   reg [31:0]		opb_of;
   reg [5:0]		opc_of;
   reg [31:0]		opd_of;
   reg [4:0]		ra_of;
   reg [4:0]		rd_ex;
   reg [4:0]		rd_of;
   // End of automatics
 
   wire [1:0] 		mux_opa, mux_opb, mux_opd;   
 
   // translate signals
   wire [4:0] 		wRD, wRA, wRB;
   wire [5:0] 		wOPC;
   wire [15:0] 		wIMM;
   wire [31:0] 		imm_if;
 
   assign 		{wOPC, wRD, wRA, wIMM} = ich_dat;
   assign 		wRB = wIMM[15:11];
 
   // decode main opgroups
 
   wire 		fSFT = (wOPC == 6'o44);
   wire 		fLOG = ({wOPC[5:4],wOPC[2]} == 3'o4);      
   wire 		fMUL = (wOPC == 6'o20) | (wOPC == 6'o30);
   wire 		fBSF = (wOPC == 6'o21) | (wOPC == 6'o31);
   wire 		fDIV = (wOPC == 6'o22);   
   wire 		fRTD = (wOPC == 6'o55);
   wire 		fBCC = (wOPC == 6'o47) | (wOPC == 6'o57);
   wire 		fBRU = (wOPC == 6'o46) | (wOPC == 6'o56);
   wire 		fBRA = fBRU & wRA[3];      
   wire 		fIMM = (wOPC == 6'o54);
   wire 		fMOV = (wOPC == 6'o45);      
   wire 		fLOD = ({wOPC[5:4],wOPC[2]} == 3'o6);
   wire 		fSTR = ({wOPC[5:4],wOPC[2]} == 3'o7);
   wire 		fLDST = (wOPC[5:4] == 2'o3);   
   wire 		fPUT = (wOPC == 6'o33) & wRB[4];
   wire 		fGET = (wOPC == 6'o33) & !wRB[4];   
 
 
   // control signals
   wire [31:0] 		wXCEOP = 32'hBA2D0020; // Vector 0x20
   wire [31:0] 		wINTOP = 32'hB9CE0010; // Vector 0x10   
   wire [31:0] 		wNOPOP = 32'h88000000; // branch-no-delay/stall
 
   localparam [2:0] 	MUX_ALU = 3'o7,		
			MUX_SFR = 3'o5,
			MUX_BSF = 3'o4,
			MUX_MUL = 3'o3,
			MUX_MEM = 3'o2,
			MUX_RPC = 3'o1,
			MUX_NOP = 3'o0;   
 
   always @(posedge gclk)
     if (grst) begin
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	imm_of <= 16'h0;
	mux_of <= 3'h0;
	opc_of <= 6'h0;
	ra_of <= 5'h0;
	rd_of <= 5'h0;
	// End of automatics
     end else if (dena) begin
 
	mux_of <= #1 
		  (hzd_bpc | hzd_fwd) ? MUX_NOP :
		  (fMOV) ? MUX_SFR :
		  (fMUL) ? MUX_MUL :
		  (fBSF) ? MUX_BSF :
		  (fLOD | fGET) ? MUX_MEM :
		  (fBRU) ? MUX_RPC :
		  (fSTR | fRTD | fBCC) ? MUX_NOP :
		  (|wRD) ? MUX_ALU :
		  MUX_NOP;
 
	opc_of <= #1 
		  (hzd_bpc | hzd_fwd) ? 6'o42 : 
		  wOPC;
 
	rd_of <= #1 wRD;	
	ra_of <= #1 wRA;
	//rb_of <= #1 wRB;
	imm_of <= #1 wIMM;
 
     end
 
 
   // immediate implementation
   reg [15:0] 		rIMM0, rIMM1;
   reg 			rFIM0, rFIM1;
   wire 		wFIMH = (gpha & AEMB_HTX[0]) ? rFIM1 : rFIM0;   
   wire [15:0]		wIMMH = (gpha & AEMB_HTX[0]) ? rIMM1 : rIMM0;
 
   assign 		imm_if[15:0] = wIMM;
   assign 		imm_if[31:16] = (wFIMH) ? wIMMH :
					{(16){wIMM[15]}};
 
   always @(posedge gclk)
     if (grst) begin
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	rFIM0 <= 1'h0;
	rFIM1 <= 1'h0;
	rIMM0 <= 16'h0;
	rIMM1 <= 16'h0;
	// End of automatics
     end else if (dena) begin
	if (gpha) begin
	   rFIM1 <= #1 fIMM & !hzd_bpc;
	   rIMM1 <= #1 wIMM;	   
	end else begin
	   rFIM0 <= #1 fIMM & !hzd_bpc;
	   rIMM0 <= #1 wIMM;	   
	end	
     end   
 
 
   // operand latch   
   reg 			wrb_ex;
   reg 			fwd_ex;   
 
   wire 		opb_fwd, opa_fwd, opd_fwd;
 
   assign 		mux_opb = {wOPC[3], opb_fwd};
   assign 		opb_fwd = (wRB == rd_ex) & 
				  fwd_ex & wrb_ex;   
 
   assign 		mux_opa = {(fBRU|fBCC), opa_fwd};
   assign 		opa_fwd = (wRA == rd_ex) & 
				  fwd_ex & wrb_ex;
 
   assign 		mux_opd = {fBCC, opd_fwd};		
   assign 		opd_fwd = (((wRA == rd_ex) & fBCC) |
				   ((wRD == rd_ex) & fSTR)) &
				  fwd_ex & wrb_ex;   
 
   reg [2:0] 		mux_mx;
 
   always @(posedge gclk)
     if (grst) begin
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	fwd_ex <= 1'h0;
	mux_ex <= 3'h0;
	mux_mx <= 3'h0;
	rd_ex <= 5'h0;
	wrb_ex <= 1'h0;
	// End of automatics
     end else if (dena) begin
	wrb_ex <= #1 |rd_of & |mux_of; // FIXME: check mux	
	fwd_ex <= #1 |mux_of; // FIXME: check mux
 
	mux_mx <= #1 mux_ex;	
	mux_ex <= #1 mux_of;	
	rd_ex <= #1 rd_of;	
     end
 
 
   always @(posedge gclk)
     if (grst) begin
	/*AUTORESET*/
	// Beginning of autoreset for uninitialized flops
	opa_of <= 32'h0;
	opb_of <= 32'h0;
	opd_of <= 32'h0;
	// End of automatics
 
     end else if (dena) begin
 
	case (mux_opd)
	  2'o2: opd_of <= #1 opa_if; // BCC
	  2'o1: opd_of <= #1 alu_ex; // FWD
	  2'o0: opd_of <= #1 opd_if; // SXX
	  2'o3: opd_of <= #1 alu_ex; // FWD	  	  
	endcase // case (mux_opd)	
 
	case (mux_opb)
	  2'o0: opb_of <= #1 opb_if;
	  2'o1: opb_of <= #1 alu_ex;
	  2'o2: opb_of <= #1 imm_if;
	  2'o3: opb_of <= #1 imm_if;	  
	  //default: 32'hX;
	endcase // case (mux_opb)	
 
	case (mux_opa)
	  2'o0: opa_of <= #1 opa_if;
	  2'o1: opa_of <= #1 alu_ex;
	  2'o2: opa_of <= #1 {rpc_if, 2'o0};
	  2'o3: opa_of <= #1 {rpc_if, 2'o0};	  
	endcase // case (mux_opa)	
 
     end
 
   // Hazard Detection
   wire 		wFMUL = (mux_ex == MUX_MUL);
   wire 		wFBSF = (mux_ex == MUX_BSF);
   wire 		wFMEM = (mux_ex == MUX_MEM);
   wire 		wFMOV = (mux_ex == MUX_SFR);   
 
   assign 		hzd_fwd = (opd_fwd | opa_fwd | opb_fwd) & 
				  (wFMUL | wFBSF | wFMEM | wFMOV);      
   assign 		hzd_bpc = (bra_ex[1] & !bra_ex[0]);
 
endmodule // aeMB2_ctrl
 
// $Log: not supported by cvs2svn $
// 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.