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 $ */ |