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

Subversion Repositories aemb

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 77 to Rev 78
    Reverse comparison

Rev 77 → Rev 78

/trunk/rtl/verilog/aeMB2_edk32.v
1,4 → 1,4
/* $Id: aeMB2_edk32.v,v 1.1 2007-12-07 18:58:51 sybreon Exp $
/* $Id: aeMB2_edk32.v,v 1.2 2007-12-11 00:43:17 sybreon Exp $
**
** AEMB2 HI-PERFORMANCE CPU
**
17,21 → 17,542
** 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/>.
** License along with AEMB. If not, see <http://www.gnu.org/licenses/>.
*/
 
 
 
module aeMB2_edk32 (/*AUTOARG*/);
 
module aeMB2_edk32 (/*AUTOARG*/
// Outputs
iwb_wre_o, iwb_stb_o, iwb_adr_o, dwb_wre_o, dwb_stb_o, dwb_sel_o,
dwb_dat_o, dwb_cyc_o, dwb_adr_o, cwb_wre_o, cwb_tga_o, cwb_stb_o,
cwb_sel_o, cwb_dat_o, cwb_adr_o,
// Inputs
sys_rst_i, sys_int_i, sys_clk_i, iwb_dat_i, iwb_ack_i, dwb_dat_i,
dwb_ack_i, cwb_dat_i, cwb_ack_i
);
parameter IWB = 32; ///< instruction wishbone address space
parameter DWB = 32; ///< data wishbone address space
 
parameter TXE = 1; ///< thread execution extension
parameter LUT = 1; ///< further speed optimisation
parameter MUL = 1; ///< enable hardware multiplier
parameter BSF = 1; ///< enable barrel shifter
parameter FSL = 1; ///< enable FSL bus
parameter DIV = 0; ///< enable hardware divider
/*AUTOOUTPUT*/
// Beginning of automatic outputs (from unused autoinst outputs)
output [6:2] cwb_adr_o; // From aslu of aeMB2_aslu.v
output [31:0] cwb_dat_o; // From regf of aeMB2_regf.v
output [3:0] cwb_sel_o; // From aslu of aeMB2_aslu.v
output cwb_stb_o; // From sysc of aeMB2_sysc.v
output [1:0] cwb_tga_o; // From aslu of aeMB2_aslu.v
output cwb_wre_o; // From sysc of aeMB2_sysc.v
output [DWB-1:2] dwb_adr_o; // From aslu of aeMB2_aslu.v
output dwb_cyc_o; // From sysc of aeMB2_sysc.v
output [31:0] dwb_dat_o; // From regf of aeMB2_regf.v
output [3:0] dwb_sel_o; // From aslu of aeMB2_aslu.v
output dwb_stb_o; // From sysc of aeMB2_sysc.v
output dwb_wre_o; // From sysc of aeMB2_sysc.v
output [IWB-1:2] iwb_adr_o; // From bpcu of aeMB2_bpcu.v
output iwb_stb_o; // From sysc of aeMB2_sysc.v
output iwb_wre_o; // From sysc of aeMB2_sysc.v
// End of automatics
/*AUTOINPUT*/
// Beginning of automatic inputs (from unused autoinst inputs)
input cwb_ack_i; // To sysc of aeMB2_sysc.v, ...
input [31:0] cwb_dat_i; // To regf of aeMB2_regf.v
input dwb_ack_i; // To sysc of aeMB2_sysc.v, ...
input [31:0] dwb_dat_i; // To regf of aeMB2_regf.v
input iwb_ack_i; // To sysc of aeMB2_sysc.v, ...
input [31:0] iwb_dat_i; // To bpcu of aeMB2_bpcu.v
input sys_clk_i; // To sysc of aeMB2_sysc.v
input sys_int_i; // To sysc of aeMB2_sysc.v
input sys_rst_i; // To sysc of aeMB2_sysc.v
// End of automatics
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire clk_i; // From sysc of aeMB2_sysc.v
wire ena_i; // From sysc of aeMB2_sysc.v
wire pha_i; // From sysc of aeMB2_sysc.v
wire [10:0] rALT_IF; // From bpcu of aeMB2_bpcu.v
wire [2:0] rALU_OF; // From idmx of aeMB2_idmx.v
wire [1:0] rBRA; // From bpcu of aeMB2_bpcu.v
wire [15:0] rIMM_IF; // From bpcu of aeMB2_bpcu.v
wire [15:0] rIMM_OF; // From idmx of aeMB2_idmx.v
wire rINT; // From sysc of aeMB2_sysc.v
wire rMSR_BE; // From aslu of aeMB2_aslu.v
wire rMSR_BIP; // From aslu of aeMB2_aslu.v
wire rMSR_IE; // From aslu of aeMB2_aslu.v
wire [31:0] rMUL_MA; // From aslu of aeMB2_aslu.v
wire [31:0] rOPA_OF; // From opmx of aeMB2_opmx.v
wire [31:0] rOPB_OF; // From opmx of aeMB2_opmx.v
wire [5:0] rOPC_IF; // From bpcu of aeMB2_bpcu.v
wire [5:0] rOPC_OF; // From idmx of aeMB2_idmx.v
wire [2:0] rOPD_EX; // From idmx of aeMB2_idmx.v
wire [2:0] rOPD_MA; // From idmx of aeMB2_idmx.v
wire [31:0] rOPM_OF; // From opmx of aeMB2_opmx.v
wire [31:0] rOPX_OF; // From opmx of aeMB2_opmx.v
wire [31:2] rPC_IF; // From bpcu of aeMB2_bpcu.v
wire [31:2] rPC_MA; // From bpcu of aeMB2_bpcu.v
wire [31:2] rPC_OF; // From bpcu of aeMB2_bpcu.v
wire [4:0] rRA_IF; // From bpcu of aeMB2_bpcu.v
wire [4:0] rRA_OF; // From idmx of aeMB2_idmx.v
wire [4:0] rRB_IF; // From bpcu of aeMB2_bpcu.v
wire [4:0] rRD_EX; // From idmx of aeMB2_idmx.v
wire [4:0] rRD_IF; // From bpcu of aeMB2_bpcu.v
wire [4:0] rRD_MA; // From idmx of aeMB2_idmx.v
wire [4:0] rRD_OF; // From idmx of aeMB2_idmx.v
wire [31:0] rREGA_OF; // From regf of aeMB2_regf.v
wire [31:0] rREGB_OF; // From regf of aeMB2_regf.v
wire [31:0] rREGD_OF; // From regf of aeMB2_regf.v
wire [31:0] rRES_EX; // From aslu of aeMB2_aslu.v
wire [31:0] rRES_MA; // From aslu of aeMB2_aslu.v
wire [3:0] rSEL_MA; // From aslu of aeMB2_aslu.v
wire rXCE; // From sysc of aeMB2_sysc.v
wire rst_i; // From sysc of aeMB2_sysc.v
// End of automatics
 
/* aeMB2_sysc AUTO_TEMPLATE (
.clk_o(clk_i),
.rst_o(rst_i),
.ena_o(ena_i),
.pha_o(pha_i),
)*/
 
/* System/Interrupt Control */
aeMB2_sysc
#(/*AUTOINSTPARAM*/
// Parameters
.TXE (TXE))
sysc (/*AUTOINST*/
// Outputs
.iwb_stb_o (iwb_stb_o),
.iwb_wre_o (iwb_wre_o),
.dwb_cyc_o (dwb_cyc_o),
.dwb_stb_o (dwb_stb_o),
.dwb_wre_o (dwb_wre_o),
.cwb_stb_o (cwb_stb_o),
.cwb_wre_o (cwb_wre_o),
.rINT (rINT),
.rXCE (rXCE),
.pha_o (pha_i), // Templated
.clk_o (clk_i), // Templated
.rst_o (rst_i), // Templated
.ena_o (ena_i), // Templated
// Inputs
.rOPC_IF (rOPC_IF[5:0]),
.iwb_ack_i (iwb_ack_i),
.dwb_ack_i (dwb_ack_i),
.cwb_ack_i (cwb_ack_i),
.rOPC_OF (rOPC_OF[5:0]),
.rRA_OF (rRA_OF[4:0]),
.rIMM_OF (rIMM_OF[15:0]),
.rMSR_BE (rMSR_BE),
.rMSR_BIP (rMSR_BIP),
.rMSR_IE (rMSR_IE),
.sys_int_i (sys_int_i),
.sys_clk_i (sys_clk_i),
.sys_rst_i (sys_rst_i));
 
/* Register file */
 
aeMB2_regf
#(/*AUTOINSTPARAM*/
// Parameters
.TXE (TXE))
regf (/*AUTOINST*/
// Outputs
.dwb_dat_o (dwb_dat_o[31:0]),
.cwb_dat_o (cwb_dat_o[31:0]),
.rREGD_OF (rREGD_OF[31:0]),
.rREGA_OF (rREGA_OF[31:0]),
.rREGB_OF (rREGB_OF[31:0]),
// Inputs
.dwb_dat_i (dwb_dat_i[31:0]),
.dwb_ack_i (dwb_ack_i),
.cwb_dat_i (cwb_dat_i[31:0]),
.cwb_ack_i (cwb_ack_i),
.rRA_IF (rRA_IF[4:0]),
.rRB_IF (rRB_IF[4:0]),
.rRD_IF (rRD_IF[4:0]),
.rRD_MA (rRD_MA[4:0]),
.rOPM_OF (rOPM_OF[31:0]),
.rOPA_OF (rOPA_OF[31:0]),
.rOPC_OF (rOPC_OF[5:0]),
.rPC_MA (rPC_MA[31:2]),
.rMUL_MA (rMUL_MA[31:0]),
.rRES_MA (rRES_MA[31:0]),
.rOPD_MA (rOPD_MA[2:0]),
.rSEL_MA (rSEL_MA[3:0]),
.clk_i (clk_i),
.rst_i (rst_i),
.ena_i (ena_i),
.pha_i (pha_i));
 
/* Branch/Programme Counter Unit */
aeMB2_bpcu
#(/*AUTOINSTPARAM*/
// Parameters
.IWB (IWB),
.TXE (TXE),
.LUT (LUT))
bpcu (/*AUTOINST*/
// Outputs
.iwb_adr_o (iwb_adr_o[IWB-1:2]),
.rPC_OF (rPC_OF[31:2]),
.rPC_MA (rPC_MA[31:2]),
.rPC_IF (rPC_IF[31:2]),
.rIMM_IF (rIMM_IF[15:0]),
.rALT_IF (rALT_IF[10:0]),
.rOPC_IF (rOPC_IF[5:0]),
.rRD_IF (rRD_IF[4:0]),
.rRA_IF (rRA_IF[4:0]),
.rRB_IF (rRB_IF[4:0]),
.rBRA (rBRA[1:0]),
// Inputs
.iwb_dat_i (iwb_dat_i[31:0]),
.iwb_ack_i (iwb_ack_i),
.rOPX_OF (rOPX_OF[31:0]),
.rOPC_OF (rOPC_OF[5:0]),
.rRA_OF (rRA_OF[4:0]),
.rRD_OF (rRD_OF[4:0]),
.rRES_EX (rRES_EX[31:0]),
.rRD_EX (rRD_EX[4:0]),
.rOPD_EX (rOPD_EX[2:0]),
.clk_i (clk_i),
.rst_i (rst_i),
.ena_i (ena_i),
.pha_i (pha_i));
 
/* Operand Fetch Mux */
aeMB2_opmx
#(/*AUTOINSTPARAM*/
// Parameters
.TXE (TXE),
.LUT (LUT))
opmx (/*AUTOINST*/
// Outputs
.rOPM_OF (rOPM_OF[31:0]),
.rOPX_OF (rOPX_OF[31:0]),
.rOPA_OF (rOPA_OF[31:0]),
.rOPB_OF (rOPB_OF[31:0]),
// Inputs
.rRES_EX (rRES_EX[31:0]),
.rRD_EX (rRD_EX[4:0]),
.rOPD_EX (rOPD_EX[1:0]),
.rOPC_IF (rOPC_IF[5:0]),
.rIMM_IF (rIMM_IF[15:0]),
.rPC_IF (rPC_IF[31:2]),
.rRD_IF (rRD_IF[4:0]),
.rRA_IF (rRA_IF[4:0]),
.rRB_IF (rRB_IF[4:0]),
.rREGD_OF (rREGD_OF[31:0]),
.rREGA_OF (rREGA_OF[31:0]),
.rREGB_OF (rREGB_OF[31:0]),
.rBRA (rBRA[1:0]),
.pha_i (pha_i),
.clk_i (clk_i),
.rst_i (rst_i),
.ena_i (ena_i));
 
/* Instruction Decode Mux */
aeMB2_idmx
#(/*AUTOINSTPARAM*/
// Parameters
.TXE (TXE),
.MUL (MUL),
.BSF (BSF),
.DIV (DIV),
.FSL (FSL))
idmx (/*AUTOINST*/
// Outputs
.rIMM_OF (rIMM_OF[15:0]),
.rOPC_OF (rOPC_OF[5:0]),
.rRA_OF (rRA_OF[4:0]),
.rRD_OF (rRD_OF[4:0]),
.rRD_EX (rRD_EX[4:0]),
.rRD_MA (rRD_MA[4:0]),
.rOPD_EX (rOPD_EX[2:0]),
.rOPD_MA (rOPD_MA[2:0]),
.rALU_OF (rALU_OF[2:0]),
// Inputs
.rBRA (rBRA[1:0]),
.rXCE (rXCE),
.rINT (rINT),
.rIMM_IF (rIMM_IF[15:0]),
.rALT_IF (rALT_IF[10:0]),
.rOPC_IF (rOPC_IF[5:0]),
.rRA_IF (rRA_IF[4:0]),
.rRB_IF (rRB_IF[4:0]),
.rRD_IF (rRD_IF[4:0]),
.pha_i (pha_i),
.clk_i (clk_i),
.rst_i (rst_i),
.ena_i (ena_i));
 
 
/* Arithmetic Shift Logic Unit */
 
aeMB2_aslu
#(/*AUTOINSTPARAM*/
// Parameters
.DWB (DWB),
.MUL (MUL),
.BSF (BSF),
.FSL (FSL),
.TXE (TXE),
.LUT (LUT))
aslu (/*AUTOINST*/
// Outputs
.dwb_adr_o (dwb_adr_o[DWB-1:2]),
.dwb_sel_o (dwb_sel_o[3:0]),
.rSEL_MA (rSEL_MA[3:0]),
.cwb_adr_o (cwb_adr_o[6:2]),
.cwb_tga_o (cwb_tga_o[1:0]),
.cwb_sel_o (cwb_sel_o[3:0]),
.rMUL_MA (rMUL_MA[31:0]),
.rRES_MA (rRES_MA[31:0]),
.rRES_EX (rRES_EX[31:0]),
.rMSR_IE (rMSR_IE),
.rMSR_BE (rMSR_BE),
.rMSR_BIP (rMSR_BIP),
// Inputs
.rIMM_OF (rIMM_OF[15:0]),
.rALU_OF (rALU_OF[2:0]),
.rOPC_OF (rOPC_OF[5:0]),
.rRA_OF (rRA_OF[4:0]),
.rRD_OF (rRD_OF[4:0]),
.rPC_OF (rPC_OF[31:2]),
.rOPA_OF (rOPA_OF[31:0]),
.rOPB_OF (rOPB_OF[31:0]),
.pha_i (pha_i),
.clk_i (clk_i),
.rst_i (rst_i),
.ena_i (ena_i));
// synopsys translate_off
`ifdef AEMB2_SIMULATION_KERNEL
wire [31:0] iwb_adr = {iwb_adr_o, 2'd0};
wire [31:0] dwb_adr = {dwb_adr_o, 2'd0};
wire [3:0] wMSR = dut.aslu.wMSR[3:0];
always @(posedge clk_i) if (ena_i) begin
 
$write ("\n", ($stime/10));
$writeh (" T", pha_i);
$writeh(" PC=", iwb_adr);
$writeh ("\t| ");
case (rOPC_IF)
6'o00: if (rRD_IF == 0) $write(" "); else $write("ADD");
6'o01: $write("RSUB");
6'o02: $write("ADDC");
6'o03: $write("RSUBC");
6'o04: $write("ADDK");
6'o05: case (rIMM_IF[1:0])
2'o0: $write("RSUBK");
2'o1: $write("CMP");
2'o3: $write("CMPU");
default: $write("XXX");
endcase // case (rIMM_IF[1:0])
6'o06: $write("ADDKC");
6'o07: $write("RSUBKC");
6'o10: $write("ADDI");
6'o11: $write("RSUBI");
6'o12: $write("ADDIC");
6'o13: $write("RSUBIC");
6'o14: $write("ADDIK");
6'o15: $write("RSUBIK");
6'o16: $write("ADDIKC");
6'o17: $write("RSUBIKC");
 
6'o20: $write("MUL");
6'o21: case (rALT_IF[10:9])
2'o0: $write("BSRL");
2'o1: $write("BSRA");
2'o2: $write("BSLL");
default: $write("XXX");
endcase // case (rALT_IF[10:9])
6'o22: $write("IDIV");
 
6'o30: $write("MULI");
6'o31: case (rALT_IF[10:9])
2'o0: $write("BSRLI");
2'o1: $write("BSRAI");
2'o2: $write("BSLLI");
default: $write("XXX");
endcase // case (rALT_IF[10:9])
6'o33: case (rRB_IF[4:2])
3'o0: $write("GET");
3'o4: $write("PUT");
3'o2: $write("NGET");
3'o6: $write("NPUT");
3'o1: $write("CGET");
3'o5: $write("CPUT");
3'o3: $write("NCGET");
3'o7: $write("NCPUT");
endcase // case (rRB_IF[4:2])
 
6'o40: $write("OR");
6'o41: $write("AND");
6'o42: if (rRD_IF == 0) $write(" "); else $write("XOR");
6'o43: $write("ANDN");
6'o44: case (rIMM_IF[6:5])
2'o0: $write("SRA");
2'o1: $write("SRC");
2'o2: $write("SRL");
2'o3: if (rIMM_IF[0]) $write("SEXT16"); else $write("SEXT8");
endcase // case (rIMM_IF[6:5])
6'o45: $write("MOV");
6'o46: case (rRA_IF[3:2])
3'o0: $write("BR");
3'o1: $write("BRL");
3'o2: $write("BRA");
3'o3: $write("BRAL");
endcase // case (rRA_IF[3:2])
6'o47: case (rRD_IF[2:0])
3'o0: $write("BEQ");
3'o1: $write("BNE");
3'o2: $write("BLT");
3'o3: $write("BLE");
3'o4: $write("BGT");
3'o5: $write("BGE");
default: $write("XXX");
endcase // case (rRD_IF[2:0])
6'o50: $write("ORI");
6'o51: $write("ANDI");
6'o52: $write("XORI");
6'o53: $write("ANDNI");
6'o54: $write("IMMI");
6'o55: case (rRD_IF[1:0])
2'o0: $write("RTSD");
2'o1: $write("RTID");
2'o2: $write("RTBD");
default: $write("XXX");
endcase // case (rRD_IF[1:0])
6'o56: case (rRA_IF[3:2])
3'o0: $write("BRI");
3'o1: $write("BRLI");
3'o2: $write("BRAI");
3'o3: $write("BRALI");
endcase // case (rRA_IF[3:2])
6'o57: case (rRD_IF[2:0])
3'o0: $write("BEQI");
3'o1: $write("BNEI");
3'o2: $write("BLTI");
3'o3: $write("BLEI");
3'o4: $write("BGTI");
3'o5: $write("BGEI");
default: $write("XXX");
endcase // case (rRD_IF[2:0])
6'o60: $write("LBU");
6'o61: $write("LHU");
6'o62: $write("LW");
6'o64: $write("SB");
6'o65: $write("SH");
6'o66: $write("SW");
6'o70: $write("LBUI");
6'o71: $write("LHUI");
6'o72: $write("LWI");
6'o74: $write("SBI");
6'o75: $write("SHI");
6'o76: $write("SWI");
 
default: $write("XXX");
endcase // case (rOPC_IF)
 
case (rOPC_IF[3])
1'b1: $writeh("\t r",rRD_IF,", r",rRA_IF,", h",rIMM_IF);
1'b0: $writeh("\t r",rRD_IF,", r",rRA_IF,", r",rRB_IF," ");
endcase // case (rOPC_IF[3])
 
if (dut.bpcu.fHAZARD)
$write ("*");
// ALU
$write("\t|");
$writeh(" A=",rOPA_OF);
$writeh(" B=",rOPB_OF);
$writeh(" C=",rOPX_OF);
$writeh(" M=",rOPM_OF);
$writeh(" MSR=", wMSR," ");
 
case (rALU_OF)
3'o0: if (dwb_stb_o)
$write(" RAM");
else
$write(" ADD");
3'o1: $write(" LOG");
3'o2: $write(" SFT");
3'o3: $write(" MOV");
3'o4: $write(" MUL");
3'o5: $write(" BSF");
default: $write(" XXX");
endcase // case (rALU_OF)
 
// MA
$write ("\t| ");
if (dwb_stb_o)
$writeh("@",rRES_EX);
else
$writeh("=",rRES_EX);
 
case (rBRA)
2'b00: $write(" ");
2'b01: $write(".");
2'b10: $write("-");
2'b11: $write("+");
endcase // case (rBRA)
// WRITEBACK
$write("\t|");
if (regf.fWRE) begin
case (rOPD_MA)
2'o2: begin
if (rSEL_MA != 4'h0) $writeh("R",rRD_MA,"=RAM(",regf.rREGD,")");
if (rSEL_MA == 4'h0) $writeh("R",rRD_MA,"=FSL(",regf.rREGD,")");
end
2'o1: $writeh("R",rRD_MA,"=LNK(",regf.rREGD,")");
2'o0: $writeh("R",rRD_MA,"=ALU(",regf.rREGD,")");
endcase // case (rOPD_MA)
end
 
/*
// STORE
if (dwb_stb_o & dwb_wre_o) begin
$writeh("RAM(", dwb_adr ,")=", dwb_dat_o);
case (dwb_sel_o)
4'hF: $write(":L");
4'h3,4'hC: $write(":W");
4'h1,4'h2,4'h4,4'h8: $write(":B");
endcase // case (dwb_sel_o)
end
*/
end // if (ena_i)
`endif // `ifdef AEMB_SIMULATION_KERNEL
// synopsys translate_on
endmodule // aeMB2_edk32
 
/* $Log: not supported by cvs2svn $ */
/* $Log: not supported by cvs2svn $
/* Revision 1.1 2007/12/07 18:58:51 sybreon
/* initial
/* */
/trunk/rtl/verilog/aeMB2_bpcu.v
0,0 → 1,241
/* $Id: aeMB2_bpcu.v,v 1.1 2007-12-11 00:43:17 sybreon Exp $
**
** AEMB2 BRANCH/PROGRAMME COUNTER
**
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <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/>.
*/
 
module aeMB2_bpcu (/*AUTOARG*/
// Outputs
iwb_adr_o, rPC_OF, rPC_MA, rPC_IF, rIMM_IF, rALT_IF, rOPC_IF,
rRD_IF, rRA_IF, rRB_IF, rBRA,
// Inputs
iwb_dat_i, iwb_ack_i, rOPX_OF, rOPC_OF, rRA_OF, rRD_OF, rRES_EX,
rRD_EX, rOPD_EX, clk_i, rst_i, ena_i, pha_i
);
parameter IWB = 32;
parameter TXE = 1;
parameter LUT = 1;
// IWB
output [IWB-1:2] iwb_adr_o;
input [31:0] iwb_dat_i;
input iwb_ack_i;
// PIPELINE
output [31:2] rPC_OF,
rPC_MA,
rPC_IF;
output [15:0] rIMM_IF;
output [10:0] rALT_IF;
output [5:0] rOPC_IF;
output [4:0] rRD_IF,
rRA_IF,
rRB_IF;
 
// BRANCH DETECTION
output [1:0] rBRA; ///< {branch, delay}
input [31:0] rOPX_OF; // BCC op test
input [5:0] rOPC_OF;
input [4:0] rRA_OF,
rRD_OF;
input [31:0] rRES_EX;
 
// MEMORY HAZARD DETECTION
input [4:0] rRD_EX; ///< RD
input [2:0] rOPD_EX; ///< data register source (ALU, MEM/FSL, PC)
// SYSTEM
input clk_i,
rst_i,
ena_i,
pha_i;
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [1:0] rBRA;
reg [15:0] rIMM_IF;
reg [5:0] rOPC_IF;
reg [31:2] rPC_IF;
reg [31:2] rPC_MA;
reg [4:0] rRA_IF;
reg [4:0] rRD_IF;
// End of automatics
 
 
/* Partial decoding */
wire [5:0] rOPC = rOPC_IF;
wire [4:0] rRA = rRA_IF;
wire [4:0] rRB = rRB_IF;
wire fSFT = (rOPC == 6'o44);
wire fLOG = ({rOPC[5:4],rOPC[2]} == 3'o4);
wire fMUL = (rOPC == 6'o20) | (rOPC == 6'o30);
wire fBSF = (rOPC == 6'o21) | (rOPC == 6'o31);
wire fDIV = (rOPC == 6'o22);
wire fRTD = (rOPC == 6'o55);
wire fBCC = (rOPC == 6'o47) | (rOPC == 6'o57);
wire fBRU = (rOPC == 6'o46) | (rOPC == 6'o56);
wire fBRA = fBRU & rRA[3];
wire fIMM = (rOPC == 6'o54);
wire fMOV = (rOPC == 6'o45);
wire fLOD = ({rOPC[5:4],rOPC[2]} == 3'o6);
wire fSTR = ({rOPC[5:4],rOPC[2]} == 3'o7);
wire fLDST = (rOPC[5:4] == 2'o3);
wire fPUT = (rOPC == 6'o33) & rRB[4];
wire fGET = (rOPC == 6'o33) & !rRB[4];
/* Select the PC. */
reg [31:2] rPC, // PC
rPC0, rPC1, // register based
rPCL[0:TXE]; // LUT based
 
wire [31:2] wPCSEL = (pha_i) ? rPC0 : (TXE) ? rPC1 : 30'hX;
wire [31:2] wPCNXT = (LUT) ? rPCL[!pha_i] : wPCSEL;
wire [31:2] wPCINC = (rPC + 1);
/* Check for RW data hazard */
// TODO: Optimise
 
wire fLOAD = (rOPD_EX == 3'o2);
wire fMULT = (rOPD_EX == 3'o3);
wire fWRE = |rRD_EX;
wire fOPBHZD = (rRB_IF == rRD_EX) & (fLOAD | fMULT) & !fMOV & !rOPC_IF[3] & fWRE;
wire fOPAHZD = (rRA_IF == rRD_EX) & (fLOAD | fMULT) & !fBRU & fWRE;
wire fOPDHZD = (rRD_IF == rRD_EX) & (fLOAD | fMULT) & fSTR & fWRE;
wire fHAZARD = fOPBHZD | fOPAHZD | fOPDHZD;
 
/* Output the new PC for IWB */
wire [1:0] wIPCMX = {fHAZARD, rBRA[1]};
assign iwb_adr_o = rPC[IWB-1:2];
always @ (posedge clk_i)
if (rst_i) begin
rPC <= {(30){1'b1}};
/*AUTORESET*/
end else if (ena_i) begin
case (wIPCMX)
2'o0 : rPC <= #1 wPCNXT[IWB-1:2]; // normal
2'o1 : rPC <= #1 rRES_EX[IWB-1:2]; // branch/return/break
2'o2 : rPC <= #1 rPC_IF[IWB-1:2]; // retry/stall
default: rPC <= {(IWB-2){1'bX}}; // undefined
endcase // case (wIPCMX)
end
 
/* Inbcrement the PC */
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rPC0 <= 30'h0;
rPC1 <= 30'h0;
// End of automatics
end else if (ena_i) begin
if (pha_i)
rPC1 <= #1 wPCINC;
else
rPC0 <= #1 wPCINC;
end
always @(posedge clk_i)
if (ena_i | rst_i) begin
rPCL[pha_i] <= #1 wPCINC;
end
 
/* Latch onto instruction word */
reg [31:2] rPC_OF, rPC_EX;
assign {rRB_IF, rALT_IF} = rIMM_IF;
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rIMM_IF <= 16'h0;
rOPC_IF <= 6'h0;
rRA_IF <= 5'h0;
rRD_IF <= 5'h0;
// End of automatics
end else if (ena_i & iwb_ack_i) begin
{rOPC_IF, rRD_IF, rRA_IF, rIMM_IF} <= #1 iwb_dat_i;
end
 
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rPC_EX <= 30'h0;
rPC_IF <= 30'h0;
rPC_MA <= 30'h0;
rPC_OF <= 30'h0;
// End of automatics
end else if (ena_i) begin
// TODO: Stuff inside a small LUT FIFO
{rPC_MA, rPC_EX, rPC_OF, rPC_IF} <= #1 {rPC_EX, rPC_OF, rPC_IF, rPC};
end
 
/* Branch Control */
wire wRTD = (rOPC_OF == 6'o55);
wire wBCC = (rOPC_OF == 6'o47) | (rOPC_OF == 6'o57);
wire wBRU = (rOPC_OF == 6'o46) | (rOPC_OF == 6'o56);
wire wBEQ = (rOPX_OF == 32'd0);
wire wBNE = ~wBEQ;
wire wBLT = rOPX_OF[31];
wire wBLE = wBLT | wBEQ;
wire wBGE = ~wBLT;
wire wBGT = ~wBLE;
 
reg xXCC;
always @(/*AUTOSENSE*/rRD_OF or wBEQ or wBGE or wBGT or wBLE
or wBLT or wBNE)
case (rRD_OF[2:0])
3'o0: xXCC <= wBEQ;
3'o1: xXCC <= wBNE;
3'o2: xXCC <= wBLT;
3'o3: xXCC <= wBLE;
3'o4: xXCC <= wBGT;
3'o5: xXCC <= wBGE;
default: xXCC <= 1'bX;
endcase // case (rRD_OF[2:0])
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rBRA <= 2'h0;
// End of automatics
end else if(ena_i) begin
rBRA[1] <= #1 wRTD | wBRU | (wBCC & xXCC);
rBRA[0] <= #1 (wBRU & rRA_OF[4]) | (wBCC & rRD_OF[4]) | wRTD;
end
// synopsys translate_off
integer r;
initial begin
for (r=0; r<TXE; r=r+1) begin
rPCL[r] <= $random;
end
end
 
// synopsys translate_on
endmodule // aeMB2_bpcu
 
/* $Log: not supported by cvs2svn $ */
/trunk/rtl/verilog/aeMB2_idmx.v
0,0 → 1,194
/* $Id: aeMB2_idmx.v,v 1.1 2007-12-11 00:43:17 sybreon Exp $
**
** AEMB2 INSTRUCTION DECODE MUX
**
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <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/>.
*/
 
module aeMB2_idmx (/*AUTOARG*/
// Outputs
rIMM_OF, rOPC_OF, rRA_OF, rRD_OF, rRD_EX, rRD_MA, rOPD_EX, rOPD_MA,
rALU_OF,
// Inputs
rBRA, rXCE, rINT, rIMM_IF, rALT_IF, rOPC_IF, rRA_IF, rRB_IF,
rRD_IF, pha_i, clk_i, rst_i, ena_i
);
parameter TXE = 1;
parameter MUL = 1;
parameter BSF = 1;
parameter DIV = 0;
parameter FSL = 1;
output [15:0] rIMM_OF;
output [5:0] rOPC_OF;
output [4:0] rRA_OF,
rRD_OF;
output [4:0] rRD_EX,
rRD_MA;
output [2:0] rOPD_EX,
rOPD_MA;
output [2:0] rALU_OF; // addsub, logic, bshift, sext, mul, mov, ldst
 
input [1:0] rBRA;
input rXCE,
rINT;
input [15:0] rIMM_IF;
input [10:0] rALT_IF;
input [5:0] rOPC_IF;
input [4:0] rRA_IF,
rRB_IF,
rRD_IF;
input pha_i,
clk_i,
rst_i,
ena_i;
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [2:0] rALU_OF;
reg [15:0] rIMM_OF;
reg [5:0] rOPC_OF;
reg [2:0] rOPD_EX;
reg [2:0] rOPD_MA;
reg [4:0] rRA_OF;
reg [4:0] rRD_EX;
reg [4:0] rRD_MA;
reg [4:0] rRD_OF;
// End of automatics
 
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
/* Partial decoding */
wire [5:0] rOPC = rOPC_IF;
wire [4:0] rRA = rRA_IF;
wire [4:0] rRB = rRB_IF;
wire fSFT = (rOPC == 6'o44);
wire fLOG = ({rOPC[5:4],rOPC[2]} == 3'o4);
wire fMUL = (rOPC == 6'o20) | (rOPC == 6'o30);
wire fBSF = (rOPC == 6'o21) | (rOPC == 6'o31);
wire fDIV = (rOPC == 6'o22);
wire fRTD = (rOPC == 6'o55);
wire fBCC = (rOPC == 6'o47) | (rOPC == 6'o57);
wire fBRU = (rOPC == 6'o46) | (rOPC == 6'o56);
wire fBRA = fBRU & rRA[3];
wire fIMM = (rOPC == 6'o54);
wire fMOV = (rOPC == 6'o45);
wire fLOD = ({rOPC[5:4],rOPC[2]} == 3'o6);
wire fSTR = ({rOPC[5:4],rOPC[2]} == 3'o7);
wire fLDST = (rOPC[5:4] == 2'o3);
wire fPUT = (rOPC == 6'o33) & rRB[4];
wire fGET = (rOPC == 6'o33) & !rRB[4];
/* Hazard detection */
 
wire fLOAD = (rOPD_EX == 3'o2);
wire fMULT = (rOPD_EX == 3'o3);
wire fWRE = |rRD_EX;
wire fOPBHZD = (rRB_IF == rRD_EX) & (fLOAD | fMULT) & !fMOV & !rOPC_IF[3] & fWRE;
wire fOPAHZD = (rRA_IF == rRD_EX) & (fLOAD | fMULT) & !fBRU & fWRE;
wire fOPDHZD = (rRD_IF == rRD_EX) & (fLOAD | fMULT) & fSTR & fWRE;
wire fHAZARD = fOPBHZD | fOPAHZD | fOPDHZD;
wire fSKIP = (rBRA == 2'o2) | // non-delay branch
!(TXE | pha_i) |
fOPBHZD | fOPAHZD; // hazards
 
/* ALU Selector */
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rALU_OF <= 3'h0;
// End of automatics
end else if (ena_i) begin
rALU_OF <= #1
(fSKIP) ? 3'o1 :
(fBRA | fMOV) ? 3'o3 :
(fSFT) ? 3'o2 :
(fLOG) ? 3'o1 :
(fMUL) ? 3'o4 :
(fBSF) ? 3'o5 :
//(fDIV) ? 3'o6 :
3'o0;
end
 
/* WB Selector */
 
reg [2:0] rOPD_OF;
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rOPD_EX <= 3'h0;
rOPD_MA <= 3'h0;
rOPD_OF <= 3'h0;
// End of automatics
end else if (ena_i) begin
rOPD_MA <= #1 rOPD_EX;
rOPD_EX <= #1 rOPD_OF;
rOPD_OF <= #1
(fSKIP) ? 3'o7:
(fSTR | fRTD | fBCC) ? 3'o7 : // STR/RTD/BCC
(fLOD | fGET) ? 3'o2 : // RAM/FSL
(fBRU) ? 3'o1 : // PCLNK
(fMUL) ? 3'o3 : // MUL
//(fBSF) ? 3'o4 : // BSF
(|rRD_IF) ? 3'o0 : // ALU
3'o7; // ALU
end
/* Passthrough */
 
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rIMM_OF <= 16'h0;
rOPC_OF <= 6'h0;
rRA_OF <= 5'h0;
rRD_EX <= 5'h0;
rRD_MA <= 5'h0;
rRD_OF <= 5'h0;
// End of automatics
end else if (ena_i) begin
rRD_MA <= #1 rRD_EX;
rRD_EX <= #1 rRD_OF;
// TODO: Interrrupt/Exception
case (fSKIP)
2'o0: {rOPC_OF, rRD_OF, rRA_OF, rIMM_OF} <= #1 {rOPC_IF, rRD_IF, rRA_IF, rIMM_IF};
2'o1: {rOPC_OF, rRD_OF, rRA_OF, rIMM_OF} <= #1 wNOPOP; // delay/stall
default: {rOPC_OF, rRD_OF, rRA_OF} <= #1 16'hX;
endcase // case (fSKIP)
end
endmodule // aeMB2_idmx
 
/* $Log: not supported by cvs2svn $ */
/trunk/rtl/verilog/aeMB2_sysc.v
0,0 → 1,209
/* $Id: aeMB2_sysc.v,v 1.1 2007-12-11 00:43:17 sybreon Exp $
**
** AEMB2 SYSTEM CONTROL
**
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <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/>.
*/
 
module aeMB2_sysc (/*AUTOARG*/
// Outputs
iwb_stb_o, iwb_wre_o, dwb_cyc_o, dwb_stb_o, dwb_wre_o, cwb_stb_o,
cwb_wre_o, rINT, rXCE, pha_o, clk_o, rst_o, ena_o,
// Inputs
rOPC_IF, iwb_ack_i, dwb_ack_i, cwb_ack_i, rOPC_OF, rRA_OF, rIMM_OF,
rMSR_BE, rMSR_BIP, rMSR_IE, sys_int_i, sys_clk_i, sys_rst_i
);
parameter TXE = 1;
// INTERNAL
input [5:0] rOPC_IF;
// EXTERNAL
output iwb_stb_o,
iwb_wre_o,
dwb_cyc_o,
dwb_stb_o,
dwb_wre_o,
cwb_stb_o,
cwb_wre_o;
input iwb_ack_i,
dwb_ack_i,
cwb_ack_i;
// INTERNAL
output rINT,
rXCE;
input [5:0] rOPC_OF;
input [4:0] rRA_OF;
input [15:0] rIMM_OF;
input rMSR_BE,
rMSR_BIP,
rMSR_IE;
output pha_o,
clk_o,
rst_o,
ena_o;
// SYSTEM
input sys_int_i,
sys_clk_i,
sys_rst_i;
 
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg cwb_stb_o;
reg cwb_wre_o;
reg dwb_cyc_o;
reg dwb_stb_o;
reg dwb_wre_o;
reg iwb_stb_o;
reg pha_o;
reg rINT;
reg rXCE;
reg rst_o;
// End of automatics
 
/* Partial decoding */
wire [5:0] rOPC = rOPC_OF;
wire [4:0] rRA = rRA_OF;
wire [4:0] rRB = rIMM_OF[15:11];
wire fSFT = (rOPC == 6'o44);
wire fLOG = ({rOPC[5:4],rOPC[2]} == 3'o4);
wire fMUL = (rOPC == 6'o20) | (rOPC == 6'o30);
wire fBSF = (rOPC == 6'o21) | (rOPC == 6'o31);
wire fDIV = (rOPC == 6'o22);
wire fRTD = (rOPC == 6'o55);
wire fBCC = (rOPC == 6'o47) | (rOPC == 6'o57);
wire fBRU = (rOPC == 6'o46) | (rOPC == 6'o56);
wire fBRA = fBRU & rRA[3];
wire fIMM = (rOPC == 6'o54);
wire fMOV = (rOPC == 6'o45);
wire fLOD = ({rOPC[5:4],rOPC[2]} == 3'o6);
wire fSTR = ({rOPC[5:4],rOPC[2]} == 3'o7);
wire fLDST = (rOPC[5:4] == 2'o3);
wire fPUT = (rOPC == 6'o33) & rRB[4];
wire fGET = (rOPC == 6'o33) & !rRB[4];
/* instantiate a clock manager if necessary */
assign clk_o = sys_clk_i;
 
/* delay the reset signal for POR */
always @(posedge clk_o)
if (sys_rst_i) begin
rst_o <= 1'b1;
end else if (!pha_o) begin
rst_o <= #1 1'b0;
end
 
/* calculate the async enable signal */
assign ena_o = !((cwb_ack_i ^ cwb_stb_o) | // FSL clean
(dwb_ack_i ^ dwb_stb_o) | // DWB clean
(iwb_ack_i ^ iwb_stb_o)); // IWB clean
 
 
/* Toggle the FGMT phase. This toggles twice during POR to reset
/* the various RAM locations (for a LUT based optimisation). */
always @(posedge clk_o)
if (sys_rst_i) begin
pha_o <= 1'b1;
/*AUTORESET*/
end else if (ena_o) begin
pha_o <= #1 !pha_o;
end
 
/* Level triggered interrupt latch flag */
 
// check for interrupt acknowledge
wire fINTACK = ena_o & (rOPC_OF == 6'o56) & (rRA_OF == 5'h0D);
always @(posedge clk_o)
if (rst_o) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rINT <= 1'h0;
// End of automatics
end else if (rMSR_IE) begin
rINT <= #1 rINT | sys_int_i & !fINTACK;
end
 
/* Hardwre exception catcher */
 
// check for exception acknowledge
wire fXCEACK = ena_o & (rOPC_OF == 6'o56) & (rRA_OF == 5'h0F);
 
// check for invalid instruction
wire fILLEGAL;
assign fILLEGAL = ({rOPC_IF[5:4],rOPC_IF[1:0]} == 4'hF) | // LD/ST
((rOPC_IF[5:3] == 3'o3) &
((rOPC_OF[2:0] != 3'o2) |
(rOPC_OF[2]))) | // GET/PUT
((rOPC_IF[5:3] == 3'o2) &
(rOPC_IF[2:1] != 2'o0)) // MUL/BSF
;
always @(posedge clk_o)
if (rst_o) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rINT <= 1'h0;
// End of automatics
end else if (rMSR_IE) begin
rINT <= #1 rINT | sys_int_i & !fINTACK;
end
/* Handle wishbone handshakes */
assign iwb_wre_o = 1'b0;
always @(posedge clk_o)
if (rst_o) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
cwb_stb_o <= 1'h0;
cwb_wre_o <= 1'h0;
dwb_cyc_o <= 1'h0;
dwb_stb_o <= 1'h0;
dwb_wre_o <= 1'h0;
iwb_stb_o <= 1'h0;
// End of automatics
end else begin
iwb_stb_o <= #1 (TXE[0] | pha_o);
 
dwb_cyc_o <= #1 fLOD | fSTR | rMSR_BE;
dwb_stb_o <= #1 fLOD | fSTR;
dwb_wre_o <= #1 fSTR;
cwb_stb_o <= #1 fGET | fPUT;
cwb_wre_o <= #1 fPUT;
end
 
endmodule // aeMB2_sysc
 
/* $Log: not supported by cvs2svn $ */
/trunk/rtl/verilog/aeMB2_opmx.v
0,0 → 1,206
/* $Id: aeMB2_opmx.v,v 1.1 2007-12-11 00:43:17 sybreon Exp $
**
** AEMB2 OPERAND FETCH MUX
**
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <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/>.
*/
 
module aeMB2_opmx (/*AUTOARG*/
// Outputs
rOPM_OF, rOPX_OF, rOPA_OF, rOPB_OF,
// Inputs
rRES_EX, rRD_EX, rOPD_EX, rOPC_IF, rIMM_IF, rPC_IF, rRD_IF, rRA_IF,
rRB_IF, rREGD_OF, rREGA_OF, rREGB_OF, rBRA, pha_i, clk_i, rst_i,
ena_i
);
parameter TXE = 1;
parameter LUT = 1;
 
//output [31:2] rPC_OF;
output [31:0] rOPM_OF, // used for store
rOPX_OF, // used for BCC checking
rOPA_OF, // OPA as per ISA
rOPB_OF; // OPB as per ISA
 
input [31:0] rRES_EX;
input [4:0] rRD_EX;
input [1:0] rOPD_EX;
input [5:0] rOPC_IF;
input [15:0] rIMM_IF;
input [31:2] rPC_IF;
input [4:0] rRD_IF,
rRA_IF,
rRB_IF;
input [31:0] rREGD_OF,
rREGA_OF,
rREGB_OF;
 
input [1:0] rBRA;
// SYSTEM
input pha_i,
clk_i,
rst_i,
ena_i;
 
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [31:0] rOPA_OF;
reg [31:0] rOPB_OF;
reg [31:0] rOPM_OF;
reg [31:0] rOPX_OF;
// End of automatics
 
wire fSKP = (rBRA == 2'b10); // branch without delay
 
/* Partial decoding */
wire [5:0] rOPC = rOPC_IF;
wire [4:0] rRA = rRA_IF;
wire [4:0] rRB = rRB_IF;
wire fSFT = (rOPC == 6'o44);
wire fLOG = ({rOPC[5:4],rOPC[2]} == 3'o4);
wire fMUL = (rOPC == 6'o20) | (rOPC == 6'o30);
wire fBSF = (rOPC == 6'o21) | (rOPC == 6'o31);
wire fDIV = (rOPC == 6'o22);
wire fRTD = (rOPC == 6'o55);
wire fBCC = (rOPC == 6'o47) | (rOPC == 6'o57);
wire fBRU = (rOPC == 6'o46) | (rOPC == 6'o56);
wire fBRA = fBRU & rRA[3];
wire fIMM = (rOPC == 6'o54);
wire fMOV = (rOPC == 6'o45);
wire fLOD = ({rOPC[5:4],rOPC[2]} == 3'o6);
wire fSTR = ({rOPC[5:4],rOPC[2]} == 3'o7);
wire fLDST = (rOPC[5:4] == 2'o3);
wire fPUT = (rOPC == 6'o33) & rRB[4];
wire fGET = (rOPC == 6'o33) & !rRB[4];
/* IMMI implementation */
reg [15:0] rIMM0, rIMM1, rIMML[0:TXE];
reg rFIM0, rFIM1, rFIML[0:TXE];
wire [15:0] wIMM = rIMML[!pha_i];
wire [31:0] wSIMM;
 
wire rFIMX = (pha_i) ? rFIM0 : (TXE) ? rFIM1 : 1'bX;
wire rFIM = (LUT) ? rFIML[!pha_i] : rFIMX;
 
wire [15:0] rIMMX = (pha_i) ? rIMM0 : (TXE) ? rIMM1 : 16'hX;
wire [15:0] rIMM = (LUT) ? rIMML[!pha_i] : rIMMX;
assign wSIMM[15:0] = rIMM_IF[15:0];
assign wSIMM[31:16] = (rFIM) ?
{rIMM} :
{(16){rIMM_IF[15]}};
always @(posedge clk_i)
if (rst_i) 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 (ena_i) begin
if (pha_i) begin
rFIM0 <= #1 fIMM & !fSKP;
rIMM0 <= #1 rIMM_IF;
end else begin
rFIM1 <= #1 fIMM & !fSKP;
rIMM1 <= #1 rIMM_IF;
end
end
always @(posedge clk_i)
if (ena_i) begin
rFIML[!pha_i] <= #1 fIMM & !fSKP;
rIMML[!pha_i] <= #1 rIMM_IF;
end
 
/* Latch onto the operand */
// TODO: Optimise
wire fALU = (rOPD_EX == 3'o0);
wire fWRE = |rRD_EX;
wire wOPBFWD = !rOPC_IF[3] & (rRB_IF == rRD_EX) & fALU & !fMOV & fWRE;
wire wOPAFWD = !(fBRU|fBCC) & (rRA_IF == rRD_EX) & fALU & fWRE;
wire wOPXFWD = (fBCC) & (rRA_IF == rRD_EX) & fALU & fWRE;
wire wOPMFWD = (rRD_IF == rRD_EX) & fALU & fWRE;
wire [1:0] wOPB_MX = {rOPC_IF[3], wOPBFWD};
wire [1:0] wOPA_MX = {fBRU|fBCC, wOPAFWD};
wire [1:0] wOPX_MX = {fBCC, wOPXFWD};
wire [1:0] wOPM_MX = {fSTR, wOPMFWD};
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rOPA_OF <= 32'h0;
rOPB_OF <= 32'h0;
rOPM_OF <= 32'h0;
rOPX_OF <= 32'h0;
// End of automatics
end else if (ena_i) begin
 
case (wOPX_MX)
// BCC
2'o2: rOPX_OF <= #1 rREGA_OF; // reg
2'o3: rOPX_OF <= #1 rRES_EX; // forward
default: rOPX_OF <= #1 32'hX;
endcase // case (wOPX_MX)
 
case (wOPM_MX)
2'o2: rOPM_OF <= #1 rREGD_OF; // reg
2'o3: rOPM_OF <= #1 rRES_EX; // forward
default: rOPM_OF <= #1 32'hX;
endcase // case (wOPM_MX)
// OP B
case (wOPB_MX)
2'o0: rOPB_OF <= #1 rREGB_OF; // reg
2'o1: rOPB_OF <= #1 rRES_EX; // forward
2'o2: rOPB_OF <= #1 wSIMM; // immediate
default: rOPB_OF <= #1 32'hX;
endcase // case (wOPB_MX)
case (wOPA_MX)
2'o0: rOPA_OF <= #1 rREGA_OF; // reg
2'o1: rOPA_OF <= #1 rRES_EX; // forward
2'o2: rOPA_OF <= #1 {rPC_IF, 2'd0}; // pc
default: rOPA_OF <= #1 32'hX;
endcase // case (wOPA_MX)
 
end
 
// synopsys translate_off
integer r;
initial begin
for (r=0; r<TXE; r=r+1) begin
rFIML[r] <= $random;
rIMML[r] <= $random;
end
end
// synopsys translate_on
endmodule // aeMB2_opmx
 
/* $Log: not supported by cvs2svn $ */
/trunk/rtl/verilog/aeMB2_regf.v
0,0 → 1,205
/* $Id: aeMB2_regf.v,v 1.1 2007-12-11 00:43:17 sybreon Exp $
**
** AEMB2 REGISTER FILE
**
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <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/>.
*/
 
module aeMB2_regf (/*AUTOARG*/
// Outputs
dwb_dat_o, cwb_dat_o, rREGD_OF, rREGA_OF, rREGB_OF,
// Inputs
dwb_dat_i, dwb_ack_i, cwb_dat_i, cwb_ack_i, rRA_IF, rRB_IF, rRD_IF,
rRD_MA, rOPM_OF, rOPA_OF, rOPC_OF, rPC_MA, rMUL_MA, rRES_MA,
rOPD_MA, rSEL_MA, clk_i, rst_i, ena_i, pha_i
);
parameter TXE = 0;
 
// DWB
output [31:0] dwb_dat_o;
input [31:0] dwb_dat_i;
input dwb_ack_i;
// FSL
output [31:0] cwb_dat_o;
input [31:0] cwb_dat_i;
input cwb_ack_i;
// INTERNAL
output [31:0] rREGD_OF,
rREGA_OF,
rREGB_OF;
 
input [4:0] rRA_IF,
rRB_IF,
rRD_IF,
rRD_MA;
 
input [31:0] rOPM_OF;
input [31:0] rOPA_OF;
input [5:0] rOPC_OF;
input [31:2] rPC_MA; ///< link PC
input [31:0] rMUL_MA; ///< multiplier 2nd stage
input [31:0] rRES_MA;
 
input [2:0] rOPD_MA;
input [3:0] rSEL_MA; ///< data select info
// SYSTEM
input clk_i,
rst_i,
ena_i,
pha_i;
 
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [31:0] cwb_dat_o;
reg [31:0] dwb_dat_o;
// End of automatics
 
 
/* Latch FSL/RAM. This is done on completion of a bus cycle,
/* regardless of the pipeline status. */
reg [31:0] rCWB_MA,
rDWB_MA;
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rCWB_MA <= 32'h0;
rDWB_MA <= 32'h0;
// End of automatics
end else begin
if (dwb_ack_i) rDWB_MA <= #1 dwb_dat_i;
if (cwb_ack_i) rCWB_MA <= #1 cwb_dat_i;
end
/* Load resizer */
reg [31:0] rMEM;
always @(/*AUTOSENSE*/rCWB_MA or rDWB_MA or rSEL_MA) begin
case (rSEL_MA)
// 8'bits
4'h8: rMEM <= {24'd0, rDWB_MA[31:24]};
4'h4: rMEM <= {24'd0, rDWB_MA[23:16]};
4'h2: rMEM <= {24'd0, rDWB_MA[15:8]};
4'h1: rMEM <= {24'd0, rDWB_MA[7:0]};
// 16'bits
4'hC: rMEM <= {16'd0, rDWB_MA[31:16]};
4'h3: rMEM <= {16'd0, rDWB_MA[15:0]};
// 32'bits
4'h0: rMEM <= rCWB_MA;
4'hF: rMEM <= rDWB_MA;
default: rMEM <= 32'hX;
endcase // case (rSEL_MA)
end
 
/* Select the data source */
wire [31:0] wREGW;
reg [31:0] rREGD;
always @(/*AUTOSENSE*/rMEM or rMUL_MA or rOPD_MA or rPC_MA
or rRES_MA or wREGW)
case (rOPD_MA)
3'o0: rREGD <= rRES_MA; // ALU
3'o1: rREGD <= {rPC_MA, 2'o0}; // PCLNK
3'o2: rREGD <= rMEM; // RAM/FSL
3'o3: rREGD <= rMUL_MA; // Multiplier
3'o7: rREGD <= wREGW; // Unchanged
default: rREGD <= 32'hX; // Undefined
endcase // case (rOPD_MA)
 
/* Write enable */
 
wire fWRE = (ena_i & |rRD_MA) | rst_i;
/*
* 2-Bank Dual-Port Register File.
* This is implemented as distributed RAM in an FPGA.
*/
reg [31:0] rRAMA [(32<<TXE)-1:0],
rRAMB [(32<<TXE)-1:0],
rRAMD [(32<<TXE)-1:0];
 
wire [TXE+4:0] wRA = {!pha_i, rRA_IF};
wire [TXE+4:0] wRB = {!pha_i, rRB_IF};
wire [TXE+4:0] wRD = {!pha_i, rRD_IF};
wire [TXE+4:0] wRW = {pha_i, rRD_MA};
assign rREGA_OF = rRAMA[wRA];
assign rREGB_OF = rRAMB[wRB];
assign rREGD_OF = rRAMD[wRD];
assign wREGW = rRAMD[wRW];
always @(posedge clk_i)
if (fWRE) begin
rRAMA[wRW] <= #1 rREGD;
rRAMB[wRW] <= #1 rREGD;
rRAMD[wRW] <= #1 rREGD;
end
/* Store resizer */
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
cwb_dat_o <= 32'h0;
dwb_dat_o <= 32'h0;
// End of automatics
end else if (ena_i) begin
case (rOPC_OF[1:0])
2'o0: dwb_dat_o <= #1 {(4){rOPM_OF[7:0]}};
2'o1: dwb_dat_o <= #1 {(2){rOPM_OF[15:0]}};
2'o2: dwb_dat_o <= #1 rOPM_OF;
default: dwb_dat_o <= #1 32'hX;
endcase // case (rOPC_OF[1:0])
 
case (rOPC_OF[1:0])
2'o3: cwb_dat_o <= #1 rOPA_OF;
default: cwb_dat_o <= #1 32'hX;
endcase // case (rOPC_OF[1:0])
 
end
// synopsys translate_off
/* random initial condition */
integer r;
initial begin
for (r=0; r<128; r=r+1) begin
rRAMA[r] <= $random;
rRAMB[r] <= $random;
rRAMD[r] <= $random;
end
end
 
/* simulation kernel */
// synopsys translate_on
endmodule // aeMB2_regf
 
/* $Log: not supported by cvs2svn $ */
/trunk/rtl/verilog/aeMB2_aslu.v
0,0 → 1,398
/* $Id: aeMB2_aslu.v,v 1.1 2007-12-11 00:43:17 sybreon Exp $
**
** AEMB2 INTEGER ARITHMETIC SHIFT LOGIC UNIT
**
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <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/>.
*/
 
module aeMB2_aslu (/*AUTOARG*/
// Outputs
dwb_adr_o, dwb_sel_o, rSEL_MA, cwb_adr_o, cwb_tga_o, cwb_sel_o,
rMUL_MA, rRES_MA, rRES_EX, rMSR_IE, rMSR_BE, rMSR_BIP,
// Inputs
rIMM_OF, rALU_OF, rOPC_OF, rRA_OF, rRD_OF, rPC_OF, rOPA_OF,
rOPB_OF, pha_i, clk_i, rst_i, ena_i
);
 
parameter DWB = 32;
parameter MUL = 0;
parameter BSF = 1;
parameter FSL = 1;
 
parameter TXE = 1;
parameter LUT = 1;
// DWB
output [DWB-1:2] dwb_adr_o;
output [3:0] dwb_sel_o;
output [3:0] rSEL_MA;
// FSL
output [6:2] cwb_adr_o;
output [1:0] cwb_tga_o;
output [3:0] cwb_sel_o;
 
// PIPELINE
output [31:0] rMUL_MA;
output [31:0] rRES_MA,
rRES_EX;
 
output rMSR_IE,
rMSR_BE,
rMSR_BIP;
input [15:0] rIMM_OF;
input [2:0] rALU_OF;
input [5:0] rOPC_OF;
input [4:0] rRA_OF,
rRD_OF;
input [31:2] rPC_OF;
input [31:0] rOPA_OF, // RA, PC
rOPB_OF; // RB, IMM
// SYSTEM
input pha_i,
clk_i,
rst_i,
ena_i;
 
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [6:2] cwb_adr_o;
reg [3:0] cwb_sel_o;
reg [1:0] cwb_tga_o;
reg [DWB-1:2] dwb_adr_o;
reg [3:0] dwb_sel_o;
reg rMSR_BE;
reg rMSR_BIP;
reg rMSR_IE;
reg [31:0] rMUL_MA;
reg [31:0] rRES_EX;
reg [31:0] rRES_MA;
reg [3:0] rSEL_MA;
// End of automatics
 
reg rMSR_C0,
rMSR_C1,
rMSR_CL[0:TXE];
wire [4:0] rRD = rRD_OF;
wire [31:0] rOPA = rOPA_OF;
wire [31:0] rOPB = rOPB_OF;
wire [5:0] rOPC = rOPC_OF;
wire [4:0] rRA = rRA_OF;
wire [15:0] rIMM = rIMM_OF;
wire [10:0] rALT = rIMM_OF[10:0];
// --- ADD/SUB SELECTOR ----
// FIXME: Redesign
// TODO: Refactor
// TODO: Verify signed compare
 
wire rMSR_CX = (!pha_i) ? rMSR_C0 : (TXE) ? rMSR_C1 : 1'bX;
wire rMSR_C = (LUT) ? rMSR_CL[pha_i] : rMSR_CX;
wire wADDC, wSUBC, wRES_AC, wCMPC, wOPC;
wire [31:0] wADD, wSUB, wRES_A, wCMP, wOPX;
wire wCMPU = (rOPA > rOPB);
wire wCMPF = (rIMM[1]) ? wCMPU :
((wCMPU & ~(rOPB[31] ^ rOPA[31])) | (rOPB[31] & ~rOPA[31]));
assign {wCMPC,wCMP} = {wSUBC,wCMPF,wSUB[30:0]};
assign wOPX = (rOPC[0] & !rOPC[5]) ? ~rOPA : rOPA ;
assign wOPC = ((rMSR_C & rOPC[1]) | (rOPC[0] & !rOPC[1])) & (!rOPC[5] & ~&rOPC[5:4]);
assign {wSUBC,wSUB} = {wADDC,wADD};
assign {wADDC,wADD} = (rOPB + wOPX) + wOPC;
reg rRES_ADDC;
reg [31:0] rRES_ADD;
always @(rIMM or rOPC or wADD or wADDC or wCMP
or wCMPC or wSUB or wSUBC)
case ({rOPC[3],rOPC[0],rIMM[0]})
4'h2, 4'h6, 4'h7: {rRES_ADDC,rRES_ADD} <= #1 {~wSUBC,wSUB}; // SUB
4'h3: {rRES_ADDC,rRES_ADD} <= #1 {~wCMPC,wCMP}; // CMP
default: {rRES_ADDC,rRES_ADD} <= #1 {wADDC,wADD};
endcase // case ({rOPC[3],rOPC[0],rIMM[0]})
 
// --- LOGIC SELECTOR --------------------------------------
 
reg [31:0] rRES_LOG;
always @(/*AUTOSENSE*/rOPA or rOPB or rOPC)
case (rOPC[1:0])
2'o0: rRES_LOG <= #1 rOPA | rOPB;
2'o1: rRES_LOG <= #1 rOPA & rOPB;
2'o2: rRES_LOG <= #1 rOPA ^ rOPB;
2'o3: rRES_LOG <= #1 rOPA & ~rOPB;
endcase // case (rOPC[1:0])
 
// --- SHIFTER SELECTOR ------------------------------------
reg [31:0] rRES_SFT;
reg rRES_SFTC;
always @(/*AUTOSENSE*/rIMM or rMSR_C or rOPA)
case (rIMM[6:5])
2'o0: {rRES_SFT, rRES_SFTC} <= #1 {rOPA[31],rOPA[31:0]};
2'o1: {rRES_SFT, rRES_SFTC} <= #1 {rMSR_C,rOPA[31:0]};
2'o2: {rRES_SFT, rRES_SFTC} <= #1 {1'b0,rOPA[31:0]};
2'o3: {rRES_SFT, rRES_SFTC} <= #1 (rIMM[0]) ? { {(16){rOPA[15]}}, rOPA[15:0], rMSR_C} :
{ {(24){rOPA[7]}}, rOPA[7:0], rMSR_C};
endcase // case (rIMM[6:5])
 
// --- MOVE SELECTOR ---------------------------------------
 
wire wTXE = (TXE) ? 2'd1 : 2'd0;
wire [31:0] wMSR = {rMSR_C, // MSR_CC
pha_i, // Current phase
!pha_i, // Current phase
wTXE, // Thread Execution Enabled
4'h0, // Reserved
8'hAE, // Vendor
8'h32, // Version
4'h0, // Reserved
rMSR_BIP, // MSR_BIP
rMSR_C, // MSR_C
rMSR_IE, // MSR_IE
rMSR_BE}; // MSR_BE
wire fMFSR = (rOPC == 6'o45) & !rIMM[14] & rIMM[0];
wire fMFPC = (rOPC == 6'o45) & !rIMM[14] & !rIMM[0];
reg [31:0] rRES_MOV;
always @(/*AUTOSENSE*/fMFPC or fMFSR or rOPA or rOPB or rPC_OF
or rRA or wMSR)
rRES_MOV <= (fMFSR) ? wMSR :
(fMFPC) ? {rPC_OF, 2'd0} :
(rRA[3]) ? rOPB :
rOPA;
// --- MULTIPLIER ------------------------------------------
// 2-stage
reg [31:0] rRES_MUL;
always @(posedge clk_i) begin
rMUL_MA <= (MUL) ? rRES_MUL : 32'hX;
rRES_MUL <= (rOPA * rOPB);
end
 
// --- BARREL SHIFTER --------------------------------------
// 1-stage
reg [31:0] rRES_BSF;
reg [31:0] xBSRL, xBSRA, xBSLL;
// Infer a logical left barrel shifter.
always @(/*AUTOSENSE*/rOPA or rOPB)
xBSLL <= rOPA << rOPB[4:0];
// Infer a logical right barrel shifter.
always @(/*AUTOSENSE*/rOPA or rOPB)
xBSRL <= rOPA >> rOPB[4:0];
 
// Infer a arithmetic right barrel shifter.
always @(/*AUTOSENSE*/rOPA or rOPB)
case (rOPB[4:0])
5'd00: xBSRA <= rOPA;
5'd01: xBSRA <= {{(1){rOPA[31]}}, rOPA[31:1]};
5'd02: xBSRA <= {{(2){rOPA[31]}}, rOPA[31:2]};
5'd03: xBSRA <= {{(3){rOPA[31]}}, rOPA[31:3]};
5'd04: xBSRA <= {{(4){rOPA[31]}}, rOPA[31:4]};
5'd05: xBSRA <= {{(5){rOPA[31]}}, rOPA[31:5]};
5'd06: xBSRA <= {{(6){rOPA[31]}}, rOPA[31:6]};
5'd07: xBSRA <= {{(7){rOPA[31]}}, rOPA[31:7]};
5'd08: xBSRA <= {{(8){rOPA[31]}}, rOPA[31:8]};
5'd09: xBSRA <= {{(9){rOPA[31]}}, rOPA[31:9]};
5'd10: xBSRA <= {{(10){rOPA[31]}}, rOPA[31:10]};
5'd11: xBSRA <= {{(11){rOPA[31]}}, rOPA[31:11]};
5'd12: xBSRA <= {{(12){rOPA[31]}}, rOPA[31:12]};
5'd13: xBSRA <= {{(13){rOPA[31]}}, rOPA[31:13]};
5'd14: xBSRA <= {{(14){rOPA[31]}}, rOPA[31:14]};
5'd15: xBSRA <= {{(15){rOPA[31]}}, rOPA[31:15]};
5'd16: xBSRA <= {{(16){rOPA[31]}}, rOPA[31:16]};
5'd17: xBSRA <= {{(17){rOPA[31]}}, rOPA[31:17]};
5'd18: xBSRA <= {{(18){rOPA[31]}}, rOPA[31:18]};
5'd19: xBSRA <= {{(19){rOPA[31]}}, rOPA[31:19]};
5'd20: xBSRA <= {{(20){rOPA[31]}}, rOPA[31:20]};
5'd21: xBSRA <= {{(21){rOPA[31]}}, rOPA[31:21]};
5'd22: xBSRA <= {{(22){rOPA[31]}}, rOPA[31:22]};
5'd23: xBSRA <= {{(23){rOPA[31]}}, rOPA[31:23]};
5'd24: xBSRA <= {{(24){rOPA[31]}}, rOPA[31:24]};
5'd25: xBSRA <= {{(25){rOPA[31]}}, rOPA[31:25]};
5'd26: xBSRA <= {{(26){rOPA[31]}}, rOPA[31:26]};
5'd27: xBSRA <= {{(27){rOPA[31]}}, rOPA[31:27]};
5'd28: xBSRA <= {{(28){rOPA[31]}}, rOPA[31:28]};
5'd29: xBSRA <= {{(29){rOPA[31]}}, rOPA[31:29]};
5'd30: xBSRA <= {{(30){rOPA[31]}}, rOPA[31:30]};
5'd31: xBSRA <= {{(31){rOPA[31]}}, rOPA[31]};
endcase // case (rOPB[4:0])
 
always @(/*AUTOSENSE*/rALT or xBSLL or xBSRA or xBSRL)
case (rALT[10:9])
2'd0: rRES_BSF <= xBSRL;
2'd1: rRES_BSF <= xBSRA;
2'd2: rRES_BSF <= xBSLL;
default: rRES_BSF <= 32'hX;
endcase // case (rALT[10:9])
 
 
// --- MSR REGISTER -----------------
reg xMSR_C;
// C
wire fMTS = (rOPC == 6'o45) & rIMM[14];
wire fADDC = ({rOPC[5:4], rOPC[2]} == 3'o0);
always @(/*AUTOSENSE*/fADDC or fMTS or rALU_OF or rMSR_C or rOPA
or rRES_ADDC or rRES_SFTC)
case (rALU_OF)
3'o0: xMSR_C <= (fADDC) ? rRES_ADDC : rMSR_C;
3'o1: xMSR_C <= rMSR_C; // LOGIC
3'o2: xMSR_C <= rRES_SFTC; // SHIFT
3'o3: xMSR_C <= (fMTS) ? rOPA[2] : rMSR_C;
3'o4: xMSR_C <= rMSR_C;
3'o5: xMSR_C <= rMSR_C;
default: xMSR_C <= 1'hX;
endcase
 
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rMSR_C0 <= 1'h0;
rMSR_C1 <= 1'h0;
// End of automatics
end else if (ena_i) begin
if (pha_i)
rMSR_C1 <= #1 xMSR_C;
else
rMSR_C0 <= #1 xMSR_C;
end
always @(posedge clk_i)
if (ena_i)
rMSR_CL[pha_i] <= xMSR_C;
// IE/BIP/BE
wire fRTID = (rOPC == 6'o55) & rRD[0];
wire fRTBD = (rOPC == 6'o55) & rRD[1];
wire fBRK = ((rOPC == 6'o56) | (rOPC == 6'o66)) & (rRA == 5'hC);
wire fINT = ((rOPC == 6'o56) | (rOPC == 6'o66)) & (rRA == 5'hE);
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rMSR_BE <= 1'h0;
rMSR_BIP <= 1'h0;
rMSR_IE <= 1'h0;
// End of automatics
end else if (ena_i) begin
rMSR_IE <= #1
(fINT) ? 1'b0 :
(fRTID) ? 1'b1 :
(fMTS) ? rOPA[1] :
rMSR_IE;
rMSR_BIP <= #1
(fBRK) ? 1'b1 :
(fRTBD) ? 1'b0 :
(fMTS) ? rOPA[3] :
rMSR_BIP;
rMSR_BE <= #1
(fMTS) ? rOPA[0] : rMSR_BE;
end
 
// --- RESULT SELECTOR -------------------------------------------
// Selects results from functional units.
 
// RESULT
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
rRES_EX <= 32'h0;
rRES_MA <= 32'h0;
// End of automatics
end else if (ena_i) begin
rRES_MA <= #1 rRES_EX;
case (rALU_OF)
3'o0: rRES_EX <= #1 rRES_ADD;
3'o1: rRES_EX <= #1 rRES_LOG;
3'o2: rRES_EX <= #1 rRES_SFT;
3'o3: rRES_EX <= #1 rRES_MOV;
//3'o4: rRES_EX <= (MUL) ? rRES_MUL : 32'hX;
3'o5: rRES_EX <= #1 (BSF) ? rRES_BSF : 32'hX;
default: rRES_EX <= #1 32'hX;
endcase // case (rALU_OF)
end // if (ena_i)
// --- DATA/FSL WISHBONE -----
 
always @(posedge clk_i)
if (rst_i) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
cwb_adr_o <= 5'h0;
cwb_sel_o <= 4'h0;
cwb_tga_o <= 2'h0;
dwb_adr_o <= {(1+(DWB-1)-(2)){1'b0}};
dwb_sel_o <= 4'h0;
rSEL_MA <= 4'h0;
// End of automatics
end else if (ena_i) begin
rSEL_MA <= #1 dwb_sel_o;
dwb_adr_o <= #1 wADD[DWB-1:2];
case (rOPC[1:0])
2'o0: case (wADD[1:0]) // 8'bit
2'o0: dwb_sel_o <= #1 4'h8;
2'o1: dwb_sel_o <= #1 4'h4;
2'o2: dwb_sel_o <= #1 4'h2;
2'o3: dwb_sel_o <= #1 4'h1;
endcase // case (wADD[1:0])
2'o1: dwb_sel_o <= #1 (wADD[1]) ? 4'h3 : 4'hC; // 16'bit
2'o2: dwb_sel_o <= #1 4'hF; // 32'bit
2'o3: dwb_sel_o <= #1 4'h0; // FSL
endcase // case (rOPC[1:0])
 
{cwb_adr_o, cwb_tga_o} <= #1 {rIMM_OF[4:0], rIMM_OF[15:14]};
cwb_sel_o <= #1 {(4){ &rOPC[1:0]}};
end // if (ena_i)
 
// synopsys translate_off
integer r;
initial begin
for (r=0; r<TXE; r=r+1) begin
rMSR_CL[r] <= $random;
end
end
// synopsys translate_on
endmodule // aeMB2_aslu
 
/* $Log: not supported by cvs2svn $ */
/trunk/sw/c/libaemb.h
0,0 → 1,157
/* $Id: libaemb.h,v 1.1 2007-12-11 00:44:04 sybreon Exp $
**
** AEMB2 CUSTOM LIBRARY
**
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <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/>.
*/
 
#ifndef LIBAEMB_H
#define LIBAEMB_H
 
#define AEMB_TXE 0x10000000
#define AEMB_TX0 0x20000000
#define AEMB_TX1 0x40000000
#define AEMB_BIP 0x00000008
 
void aemb_reboot () asm ("_program_init");
inline void aemb_enable_interrupt ();
inline void aemb_disable_interrupt ();
inline int aemb_isthread1();
inline int aemb_isthread0();
 
/*!
* Assembly macro to enable MSR_IE
*/
void aemb_enable_interrupt ()
{
int msr, tmp;
asm volatile ("mfs %0, rmsr;"
"ori %1, %0, 0x02;"
"mts rmsr, %1;"
: "=r"(msr)
: "r" (tmp)
);
}
 
/*!
* Assembly macro to disable MSR_IE
*/
void aemb_disable_interrupt ()
{
int msr, tmp;
asm volatile ("mfs %0, rmsr;"
"andi %1, %0, 0xFD;"
"mts rmsr, %1;"
: "=r"(msr)
: "r" (tmp)
);
}
 
/*!
* Bootstrap Hook Override
 
* It re-sizes the stack, allocates half to each thread and reboots.
*/
 
void aemb_reboot ()
{
asm volatile (// Checks for TXE & BIP flags
"mfs r4, rmsr;"
"andi r3, r4, 0x10000008;"
"andi r6, r4, 0x40000000;"
"xori r18, r3, 0x10000000;"
"beqi r18, 20;"
"andi r4, r4, -9;"
"mts rmsr, r4;"
 
// Returns when TXE=0 || BIP=1
"rtsd r15, 8;"
"nop;"
 
// Calculate new stack
"addik r3, r0, _STACK_SIZE;"
"addik r5, r0, _stack;"
"beqid r6, 12;"
"sra r3, r3;"
"rsubk r5, r3, r5;"
"addik r5, r5, -16;"
 
// Re-allocate stack
"or r1, r0, r5;"
"ori r4, r4, 8;"
"mts rmsr, r4;"
 
// Reboot
"brlid r15, _crtinit;"
"nop;"
"brai exit;"
);
}
 
/*
void aemb_reboot ()
{
int stk_end, stk_siz;
int msr, tmp;
asm volatile ("mfs %0, rmsr;":"=r"(msr));
if ((msr & AEMB_BIP) || !(msr & AEMB_TXE))
{
msr &= ~AEMB_BIP;
asm volatile ("mts rmsr, %0;"::"r"(msr));
}
else
{
asm ("la %0, r0, _stack;" : "=r"(stk_end));
asm ("la %0, r0, _STACK_SIZE;" : "=r"(stk_siz));
 
if (msr & AEMB_TX1) stk_end -= (stk_siz >> 1);
 
stk_end -= 16;
 
asm ("or r1, r0, %0;" :: "r"(stk_end));
 
msr |= AEMB_BIP;
asm volatile ("mts rmsr, %0;"::"r"(msr));
 
asm ("brlid r15, _crtinit;"
"nop;"
"brai exit;"
);
}
}
*/
 
int aemb_isthread1 ()
{
int msr;
asm volatile ("mfs %0, rmsr;":"=r"(msr));
return (msr & AEMB_TX1);
}
 
int aemb_isthread0 ()
{
int msr;
asm volatile ("mfs %0, rmsr;":"=r"(msr));
return (msr & AEMB_TX0);
}
 
#endif
 
/* $Log: not supported by cvs2svn $ */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.