URL
https://opencores.org/ocsvn/aemb/aemb/trunk
Subversion Repositories aemb
Compare Revisions
- This comparison shows the changes necessary to convert path
/aemb/branches/AEMB2_712/rtl
- from Rev 77 to Rev 191
- ↔ Reverse comparison
Rev 77 → Rev 191
/verilog/aeMB2_edk32.v
0,0 → 1,37
/* $Id: aeMB2_edk32.v,v 1.1 2007-12-07 18:58:51 sybreon Exp $ |
** |
** AEMB2 HI-PERFORMANCE CPU |
** |
** 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_edk32 (/*AUTOARG*/); |
|
parameter IWB = 32; ///< instruction wishbone address space |
parameter DWB = 32; ///< data wishbone address space |
parameter MUL = 1; ///< enable hardware multiplier |
parameter BSF = 1; ///< enable barrel shifter |
parameter DIV = 0; ///< enable hardware divider |
|
|
|
endmodule // aeMB2_edk32 |
|
/* $Log: not supported by cvs2svn $ */ |
/verilog/aeMB_edk32.v
0,0 → 1,470
// $Id: aeMB_edk32.v,v 1.11 2007-11-30 17:08:29 sybreon Exp $ |
// |
// AEMB EDK 3.2 Compatible Core |
// |
// 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/>. |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.10 2007/11/16 21:52:03 sybreon |
// Added fsl_tag_o to FSL bus (tag either address or data). |
// |
// Revision 1.9 2007/11/14 23:19:24 sybreon |
// Fixed minor typo. |
// |
// Revision 1.8 2007/11/14 22:14:34 sybreon |
// Changed interrupt handling system (reported by M. Ettus). |
// |
// Revision 1.7 2007/11/10 16:39:38 sybreon |
// Upgraded license to LGPLv3. |
// Significant performance optimisations. |
// |
// Revision 1.6 2007/11/09 20:51:52 sybreon |
// Added GET/PUT support through a FSL bus. |
// |
// Revision 1.5 2007/11/08 17:48:14 sybreon |
// Fixed data WISHBONE arbitration problem (reported by J Lee). |
// |
// Revision 1.4 2007/11/08 14:17:47 sybreon |
// Parameterised optional components. |
// |
// Revision 1.3 2007/11/03 08:34:55 sybreon |
// Minor code cleanup. |
// |
// Revision 1.2 2007/11/02 19:20:58 sybreon |
// Added better (beta) interrupt support. |
// Changed MSR_IE to disabled at reset as per MB docs. |
// |
// Revision 1.1 2007/11/02 03:25:40 sybreon |
// New EDK 3.2 compatible design with optional barrel-shifter and multiplier. |
// Fixed various minor data hazard bugs. |
// Code compatible with -O0/1/2/3/s generated code. |
// |
|
module aeMB_edk32 (/*AUTOARG*/ |
// Outputs |
iwb_stb_o, iwb_adr_o, fsl_wre_o, fsl_tag_o, fsl_stb_o, fsl_dat_o, |
fsl_adr_o, dwb_wre_o, dwb_stb_o, dwb_sel_o, dwb_dat_o, dwb_adr_o, |
// Inputs |
sys_int_i, iwb_dat_i, iwb_ack_i, fsl_dat_i, fsl_ack_i, dwb_dat_i, |
dwb_ack_i, sys_clk_i, sys_rst_i |
); |
// Bus widths |
parameter IW = 32; /// Instruction bus address width |
parameter DW = 32; /// Data bus address width |
|
// Optional functions |
parameter MUL = 1; // Multiplier |
parameter BSF = 1; // Barrel Shifter |
|
/*AUTOOUTPUT*/ |
// Beginning of automatic outputs (from unused autoinst outputs) |
output [DW-1:2] dwb_adr_o; // From xecu of aeMB_xecu.v |
output [31:0] dwb_dat_o; // From regf of aeMB_regf.v |
output [3:0] dwb_sel_o; // From xecu of aeMB_xecu.v |
output dwb_stb_o; // From ctrl of aeMB_ctrl.v |
output dwb_wre_o; // From ctrl of aeMB_ctrl.v |
output [6:2] fsl_adr_o; // From xecu of aeMB_xecu.v |
output [31:0] fsl_dat_o; // From regf of aeMB_regf.v |
output fsl_stb_o; // From ctrl of aeMB_ctrl.v |
output [1:0] fsl_tag_o; // From xecu of aeMB_xecu.v |
output fsl_wre_o; // From ctrl of aeMB_ctrl.v |
output [IW-1:2] iwb_adr_o; // From bpcu of aeMB_bpcu.v |
output iwb_stb_o; // From ibuf of aeMB_ibuf.v |
// End of automatics |
/*AUTOINPUT*/ |
// Beginning of automatic inputs (from unused autoinst inputs) |
input dwb_ack_i; // To ctrl of aeMB_ctrl.v |
input [31:0] dwb_dat_i; // To regf of aeMB_regf.v |
input fsl_ack_i; // To ctrl of aeMB_ctrl.v |
input [31:0] fsl_dat_i; // To regf of aeMB_regf.v |
input iwb_ack_i; // To ibuf of aeMB_ibuf.v, ... |
input [31:0] iwb_dat_i; // To ibuf of aeMB_ibuf.v |
input sys_int_i; // To ibuf of aeMB_ibuf.v |
// End of automatics |
/*AUTOWIRE*/ |
// Beginning of automatic wires (for undeclared instantiated-module outputs) |
wire [10:0] rALT; // From ibuf of aeMB_ibuf.v |
wire rBRA; // From bpcu of aeMB_bpcu.v |
wire rDLY; // From bpcu of aeMB_bpcu.v |
wire [31:0] rDWBDI; // From regf of aeMB_regf.v |
wire [3:0] rDWBSEL; // From xecu of aeMB_xecu.v |
wire [15:0] rIMM; // From ibuf of aeMB_ibuf.v |
wire rMSR_BIP; // From xecu of aeMB_xecu.v |
wire rMSR_IE; // From xecu of aeMB_xecu.v |
wire [1:0] rMXALT; // From ctrl of aeMB_ctrl.v |
wire [2:0] rMXALU; // From ctrl of aeMB_ctrl.v |
wire [1:0] rMXDST; // From ctrl of aeMB_ctrl.v |
wire [1:0] rMXSRC; // From ctrl of aeMB_ctrl.v |
wire [1:0] rMXTGT; // From ctrl of aeMB_ctrl.v |
wire [5:0] rOPC; // From ibuf of aeMB_ibuf.v |
wire [31:2] rPC; // From bpcu of aeMB_bpcu.v |
wire [31:2] rPCLNK; // From bpcu of aeMB_bpcu.v |
wire [4:0] rRA; // From ibuf of aeMB_ibuf.v |
wire [4:0] rRB; // From ibuf of aeMB_ibuf.v |
wire [4:0] rRD; // From ibuf of aeMB_ibuf.v |
wire [31:0] rREGA; // From regf of aeMB_regf.v |
wire [31:0] rREGB; // From regf of aeMB_regf.v |
wire [31:0] rRESULT; // From xecu of aeMB_xecu.v |
wire [4:0] rRW; // From ctrl of aeMB_ctrl.v |
wire [31:0] rSIMM; // From ibuf of aeMB_ibuf.v |
wire [31:0] xIREG; // From ibuf of aeMB_ibuf.v |
// End of automatics |
|
input sys_clk_i; |
input sys_rst_i; |
|
wire grst = sys_rst_i; |
wire gclk = sys_clk_i; |
wire gena = !((dwb_stb_o ^ dwb_ack_i) | (fsl_stb_o ^ fsl_ack_i) | !iwb_ack_i); |
|
// --- INSTANTIATIONS ------------------------------------- |
|
aeMB_ibuf |
ibuf (/*AUTOINST*/ |
// Outputs |
.rIMM (rIMM[15:0]), |
.rRA (rRA[4:0]), |
.rRD (rRD[4:0]), |
.rRB (rRB[4:0]), |
.rALT (rALT[10:0]), |
.rOPC (rOPC[5:0]), |
.rSIMM (rSIMM[31:0]), |
.xIREG (xIREG[31:0]), |
.iwb_stb_o (iwb_stb_o), |
// Inputs |
.rBRA (rBRA), |
.rMSR_IE (rMSR_IE), |
.rMSR_BIP (rMSR_BIP), |
.iwb_dat_i (iwb_dat_i[31:0]), |
.iwb_ack_i (iwb_ack_i), |
.sys_int_i (sys_int_i), |
.gclk (gclk), |
.grst (grst), |
.gena (gena)); |
|
aeMB_ctrl |
ctrl (/*AUTOINST*/ |
// Outputs |
.rMXDST (rMXDST[1:0]), |
.rMXSRC (rMXSRC[1:0]), |
.rMXTGT (rMXTGT[1:0]), |
.rMXALT (rMXALT[1:0]), |
.rMXALU (rMXALU[2:0]), |
.rRW (rRW[4:0]), |
.dwb_stb_o (dwb_stb_o), |
.dwb_wre_o (dwb_wre_o), |
.fsl_stb_o (fsl_stb_o), |
.fsl_wre_o (fsl_wre_o), |
// Inputs |
.rDLY (rDLY), |
.rIMM (rIMM[15:0]), |
.rALT (rALT[10:0]), |
.rOPC (rOPC[5:0]), |
.rRD (rRD[4:0]), |
.rRA (rRA[4:0]), |
.rRB (rRB[4:0]), |
.rPC (rPC[31:2]), |
.rBRA (rBRA), |
.rMSR_IE (rMSR_IE), |
.xIREG (xIREG[31:0]), |
.dwb_ack_i (dwb_ack_i), |
.iwb_ack_i (iwb_ack_i), |
.fsl_ack_i (fsl_ack_i), |
.gclk (gclk), |
.grst (grst), |
.gena (gena)); |
|
aeMB_bpcu #(IW) |
bpcu (/*AUTOINST*/ |
// Outputs |
.iwb_adr_o (iwb_adr_o[IW-1:2]), |
.rPC (rPC[31:2]), |
.rPCLNK (rPCLNK[31:2]), |
.rBRA (rBRA), |
.rDLY (rDLY), |
// Inputs |
.rMXALT (rMXALT[1:0]), |
.rOPC (rOPC[5:0]), |
.rRD (rRD[4:0]), |
.rRA (rRA[4:0]), |
.rRESULT (rRESULT[31:0]), |
.rDWBDI (rDWBDI[31:0]), |
.rREGA (rREGA[31:0]), |
.gclk (gclk), |
.grst (grst), |
.gena (gena)); |
|
aeMB_regf |
regf (/*AUTOINST*/ |
// Outputs |
.rREGA (rREGA[31:0]), |
.rREGB (rREGB[31:0]), |
.rDWBDI (rDWBDI[31:0]), |
.dwb_dat_o (dwb_dat_o[31:0]), |
.fsl_dat_o (fsl_dat_o[31:0]), |
// Inputs |
.rOPC (rOPC[5:0]), |
.rRA (rRA[4:0]), |
.rRB (rRB[4:0]), |
.rRW (rRW[4:0]), |
.rRD (rRD[4:0]), |
.rMXDST (rMXDST[1:0]), |
.rPCLNK (rPCLNK[31:2]), |
.rRESULT (rRESULT[31:0]), |
.rDWBSEL (rDWBSEL[3:0]), |
.rBRA (rBRA), |
.rDLY (rDLY), |
.dwb_dat_i (dwb_dat_i[31:0]), |
.fsl_dat_i (fsl_dat_i[31:0]), |
.gclk (gclk), |
.grst (grst), |
.gena (gena)); |
|
aeMB_xecu #(DW, MUL, BSF) |
xecu (/*AUTOINST*/ |
// Outputs |
.dwb_adr_o (dwb_adr_o[DW-1:2]), |
.dwb_sel_o (dwb_sel_o[3:0]), |
.fsl_adr_o (fsl_adr_o[6:2]), |
.fsl_tag_o (fsl_tag_o[1:0]), |
.rRESULT (rRESULT[31:0]), |
.rDWBSEL (rDWBSEL[3:0]), |
.rMSR_IE (rMSR_IE), |
.rMSR_BIP (rMSR_BIP), |
// Inputs |
.rREGA (rREGA[31:0]), |
.rREGB (rREGB[31:0]), |
.rMXSRC (rMXSRC[1:0]), |
.rMXTGT (rMXTGT[1:0]), |
.rRA (rRA[4:0]), |
.rRB (rRB[4:0]), |
.rMXALU (rMXALU[2:0]), |
.rBRA (rBRA), |
.rDLY (rDLY), |
.rALT (rALT[10:0]), |
.rSIMM (rSIMM[31:0]), |
.rIMM (rIMM[15:0]), |
.rOPC (rOPC[5:0]), |
.rRD (rRD[4:0]), |
.rDWBDI (rDWBDI[31:0]), |
.rPC (rPC[31:2]), |
.gclk (gclk), |
.grst (grst), |
.gena (gena)); |
|
|
// --- SIMULATION KERNEL ---------------------------------- |
// synopsys translate_off |
|
`ifdef AEMB_SIMULATION_KERNEL |
|
wire [IW-1:0] iwb_adr = {iwb_adr_o, 2'd0}; |
wire [DW-1:0] dwb_adr = {dwb_adr_o,2'd0}; |
wire [1:0] wBRA = {rBRA, rDLY}; |
wire [3:0] wMSR = {xecu.rMSR_BIP, xecu.rMSR_C, xecu.rMSR_IE, xecu.rMSR_BE}; |
|
always @(posedge gclk) if (gena) begin |
|
$write ("\n", ($stime/10)); |
$writeh (" PC=", iwb_adr ); |
$writeh ("\t"); |
|
case (wBRA) |
2'b00: $write(" "); |
2'b01: $write("."); |
2'b10: $write("-"); |
2'b11: $write("+"); |
endcase // case (wBRA) |
|
case (rOPC) |
6'o00: if (rRD == 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[1:0]) |
2'o0: $write("RSUBK"); |
2'o1: $write("CMP"); |
2'o3: $write("CMPU"); |
default: $write("XXX"); |
endcase // case (rIMM[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[10:9]) |
2'o0: $write("BSRL"); |
2'o1: $write("BSRA"); |
2'o2: $write("BSLL"); |
default: $write("XXX"); |
endcase // case (rALT[10:9]) |
6'o22: $write("IDIV"); |
|
6'o30: $write("MULI"); |
6'o31: case (rALT[10:9]) |
2'o0: $write("BSRLI"); |
2'o1: $write("BSRAI"); |
2'o2: $write("BSLLI"); |
default: $write("XXX"); |
endcase // case (rALT[10:9]) |
6'o33: case (rRB[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[4:2]) |
|
6'o40: $write("OR"); |
6'o41: $write("AND"); |
6'o42: if (rRD == 0) $write(" "); else $write("XOR"); |
6'o43: $write("ANDN"); |
6'o44: case (rIMM[6:5]) |
2'o0: $write("SRA"); |
2'o1: $write("SRC"); |
2'o2: $write("SRL"); |
2'o3: if (rIMM[0]) $write("SEXT16"); else $write("SEXT8"); |
endcase // case (rIMM[6:5]) |
|
6'o45: $write("MOV"); |
6'o46: case (rRA[3:2]) |
3'o0: $write("BR"); |
3'o1: $write("BRL"); |
3'o2: $write("BRA"); |
3'o3: $write("BRAL"); |
endcase // case (rRA[3:2]) |
|
6'o47: case (rRD[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[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[1:0]) |
2'o0: $write("RTSD"); |
2'o1: $write("RTID"); |
2'o2: $write("RTBD"); |
default: $write("XXX"); |
endcase // case (rRD[1:0]) |
6'o56: case (rRA[3:2]) |
3'o0: $write("BRI"); |
3'o1: $write("BRLI"); |
3'o2: $write("BRAI"); |
3'o3: $write("BRALI"); |
endcase // case (rRA[3:2]) |
6'o57: case (rRD[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[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) |
|
case (rOPC[3]) |
1'b1: $writeh("\tr",rRD,", r",rRA,", h",rIMM); |
1'b0: $writeh("\tr",rRD,", r",rRA,", r",rRB," "); |
endcase // case (rOPC[3]) |
|
|
// ALU |
$write("\t"); |
$writeh(" A=",xecu.rOPA); |
$writeh(" B=",xecu.rOPB); |
|
case (rMXALU) |
3'o0: $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 (rMXALU) |
$writeh("=h",xecu.xRESULT); |
|
// WRITEBACK |
$writeh("\tSR=", wMSR," "); |
|
if (regf.fRDWE) begin |
case (rMXDST) |
2'o2: begin |
if (dwb_stb_o) $writeh("R",rRW,"=RAM(h",regf.xWDAT,")"); |
if (fsl_stb_o) $writeh("R",rRW,"=FSL(h",regf.xWDAT,")"); |
end |
2'o1: $writeh("R",rRW,"=LNK(h",regf.xWDAT,")"); |
2'o0: $writeh("R",rRW,"=ALU(h",regf.xWDAT,")"); |
endcase // case (rMXDST) |
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 (gena) |
|
`endif // `ifdef AEMB_SIMULATION_KERNEL |
// synopsys translate_on |
|
endmodule // aeMB_edk32 |
/verilog/aeMB_ctrl.v
0,0 → 1,333
// $Id: aeMB_ctrl.v,v 1.10 2007-11-30 16:44:40 sybreon Exp $ |
// |
// AEMB CONTROL 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/>. |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.9 2007/11/15 09:26:43 sybreon |
// Fixed minor typo causing synthesis failure. |
// |
// Revision 1.8 2007/11/14 23:19:24 sybreon |
// Fixed minor typo. |
// |
// Revision 1.7 2007/11/14 22:14:34 sybreon |
// Changed interrupt handling system (reported by M. Ettus). |
// |
// Revision 1.6 2007/11/10 16:39:38 sybreon |
// Upgraded license to LGPLv3. |
// Significant performance optimisations. |
// |
// Revision 1.5 2007/11/09 20:51:52 sybreon |
// Added GET/PUT support through a FSL bus. |
// |
// Revision 1.4 2007/11/08 17:48:14 sybreon |
// Fixed data WISHBONE arbitration problem (reported by J Lee). |
// |
// Revision 1.3 2007/11/08 14:17:47 sybreon |
// Parameterised optional components. |
// |
// Revision 1.2 2007/11/02 19:20:58 sybreon |
// Added better (beta) interrupt support. |
// Changed MSR_IE to disabled at reset as per MB docs. |
// |
// Revision 1.1 2007/11/02 03:25:40 sybreon |
// New EDK 3.2 compatible design with optional barrel-shifter and multiplier. |
// Fixed various minor data hazard bugs. |
// Code compatible with -O0/1/2/3/s generated code. |
// |
|
module aeMB_ctrl (/*AUTOARG*/ |
// Outputs |
rMXDST, rMXSRC, rMXTGT, rMXALT, rMXALU, rRW, dwb_stb_o, dwb_wre_o, |
fsl_stb_o, fsl_wre_o, |
// Inputs |
rDLY, rIMM, rALT, rOPC, rRD, rRA, rRB, rPC, rBRA, rMSR_IE, xIREG, |
dwb_ack_i, iwb_ack_i, fsl_ack_i, gclk, grst, gena |
); |
// INTERNAL |
//output [31:2] rPCLNK; |
output [1:0] rMXDST; |
output [1:0] rMXSRC, rMXTGT, rMXALT; |
output [2:0] rMXALU; |
output [4:0] rRW; |
|
input rDLY; |
input [15:0] rIMM; |
input [10:0] rALT; |
input [5:0] rOPC; |
input [4:0] rRD, rRA, rRB; |
input [31:2] rPC; |
input rBRA; |
input rMSR_IE; |
input [31:0] xIREG; |
|
// DATA WISHBONE |
output dwb_stb_o; |
output dwb_wre_o; |
input dwb_ack_i; |
|
// INST WISHBONE |
input iwb_ack_i; |
|
// FSL WISHBONE |
output fsl_stb_o; |
output fsl_wre_o; |
input fsl_ack_i; |
|
// SYSTEM |
input gclk, grst, gena; |
|
// --- DECODE INSTRUCTIONS |
// TODO: Simplify |
|
wire [5:0] wOPC; |
wire [4:0] wRD, wRA, wRB; |
wire [10:0] wALT; |
|
assign {wOPC, wRD, wRA, wRB, wALT} = xIREG; // FIXME: Endian |
|
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]); |
|
wire fPUT = (rOPC == 6'o33) & rRB[4]; |
wire fGET = (rOPC == 6'o33) & !rRB[4]; |
|
|
wire wSFT = (wOPC == 6'o44); |
wire wLOG = ({wOPC[5:4],wOPC[2]} == 3'o4); |
|
wire wMUL = (wOPC == 6'o20) | (wOPC == 6'o30); |
wire wBSF = (wOPC == 6'o21) | (wOPC == 6'o31); |
wire wDIV = (wOPC == 6'o22); |
|
wire wRTD = (wOPC == 6'o55); |
wire wBCC = (wOPC == 6'o47) | (wOPC == 6'o57); |
wire wBRU = (wOPC == 6'o46) | (wOPC == 6'o56); |
wire wBRA = wBRU & wRA[3]; |
|
wire wIMM = (wOPC == 6'o54); |
wire wMOV = (wOPC == 6'o45); |
|
wire wLOD = ({wOPC[5:4],wOPC[2]} == 3'o6); |
wire wSTR = ({wOPC[5:4],wOPC[2]} == 3'o7); |
wire wLDST = (&wOPC[5:4]); |
|
wire wPUT = (wOPC == 6'o33) & wRB[4]; |
wire wGET = (wOPC == 6'o33) & !wRB[4]; |
|
|
// --- BRANCH SLOT REGISTERS --------------------------- |
|
reg [31:2] rPCLNK, xPCLNK; |
reg [1:0] rMXDST, xMXDST; |
reg [4:0] rRW, xRW; |
|
reg [1:0] rMXSRC, xMXSRC; |
reg [1:0] rMXTGT, xMXTGT; |
reg [1:0] rMXALT, xMXALT; |
|
|
// --- OPERAND SELECTOR --------------------------------- |
|
wire wRDWE = |xRW; |
wire wAFWD_M = (xRW == wRA) & (xMXDST == 2'o2) & wRDWE; |
wire wBFWD_M = (xRW == wRB) & (xMXDST == 2'o2) & wRDWE; |
wire wAFWD_R = (xRW == wRA) & (xMXDST == 2'o0) & wRDWE; |
wire wBFWD_R = (xRW == wRB) & (xMXDST == 2'o0) & wRDWE; |
|
always @(/*AUTOSENSE*/rBRA or wAFWD_M or wAFWD_R or wBCC or wBFWD_M |
or wBFWD_R or wBRU or wOPC) |
//if (rBRA | |rXCE) begin |
if (rBRA) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
xMXALT <= 2'h0; |
xMXSRC <= 2'h0; |
xMXTGT <= 2'h0; |
// End of automatics |
end else begin |
xMXSRC <= (wBRU | wBCC) ? 2'o3 : // PC |
(wAFWD_M) ? 2'o2 : // RAM |
(wAFWD_R) ? 2'o1 : // FWD |
2'o0; // REG |
xMXTGT <= (wOPC[3]) ? 2'o3 : // IMM |
(wBFWD_M) ? 2'o2 : // RAM |
(wBFWD_R) ? 2'o1 : // FWD |
2'o0; // REG |
xMXALT <= (wAFWD_M) ? 2'o2 : // RAM |
(wAFWD_R) ? 2'o1 : // FWD |
2'o0; // REG |
end // else: !if(rBRA) |
|
// --- ALU CONTROL --------------------------------------- |
|
reg [2:0] rMXALU, xMXALU; |
|
always @(/*AUTOSENSE*/rBRA or wBRA or wBSF or wDIV or wLOG or wMOV |
or wMUL or wSFT) |
//if (rBRA | |rXCE) begin |
if (rBRA) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
xMXALU <= 3'h0; |
// End of automatics |
end else begin |
xMXALU <= (wBRA | wMOV) ? 3'o3 : |
(wSFT) ? 3'o2 : |
(wLOG) ? 3'o1 : |
(wMUL) ? 3'o4 : |
(wBSF) ? 3'o5 : |
(wDIV) ? 3'o6 : |
3'o0; |
end // else: !if(rBRA) |
|
// --- DELAY SLOT REGISTERS ------------------------------ |
|
wire fSKIP = (rBRA & !rDLY); |
|
always @(/*AUTOSENSE*/fBCC or fBRU or fGET or fLOD or fRTD or fSKIP |
or fSTR or rRD) |
if (fSKIP) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
xMXDST <= 2'h0; |
xRW <= 5'h0; |
// End of automatics |
end else begin |
xMXDST <= (fSTR | fRTD | fBCC) ? 2'o3 : |
(fLOD | fGET) ? 2'o2 : |
(fBRU) ? 2'o1 : |
2'o0; |
xRW <= rRD; |
end // else: !if(fSKIP) |
|
|
// --- DATA WISHBONE ---------------------------------- |
|
wire fDACK = !(dwb_stb_o ^ dwb_ack_i); |
|
reg rDWBSTB, xDWBSTB; |
reg rDWBWRE, xDWBWRE; |
|
assign dwb_stb_o = rDWBSTB; |
assign dwb_wre_o = rDWBWRE; |
|
|
always @(/*AUTOSENSE*/fLOD or fSKIP or fSTR or iwb_ack_i) |
//if (fSKIP | |rXCE) begin |
if (fSKIP) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
xDWBSTB <= 1'h0; |
xDWBWRE <= 1'h0; |
// End of automatics |
end else begin |
xDWBSTB <= (fLOD | fSTR) & iwb_ack_i; |
xDWBWRE <= fSTR & iwb_ack_i; |
end |
|
always @(posedge gclk) |
if (grst) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
rDWBSTB <= 1'h0; |
rDWBWRE <= 1'h0; |
// End of automatics |
end else if (fDACK) begin |
rDWBSTB <= #1 xDWBSTB; |
rDWBWRE <= #1 xDWBWRE; |
end |
|
|
// --- FSL WISHBONE ----------------------------------- |
|
wire fFACK = !(fsl_stb_o ^ fsl_ack_i); |
|
reg rFSLSTB, xFSLSTB; |
reg rFSLWRE, xFSLWRE; |
|
assign fsl_stb_o = rFSLSTB; |
assign fsl_wre_o = rFSLWRE; |
|
always @(/*AUTOSENSE*/fGET or fPUT or fSKIP or iwb_ack_i) |
//if (fSKIP | |rXCE) begin |
if (fSKIP) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
xFSLSTB <= 1'h0; |
xFSLWRE <= 1'h0; |
// End of automatics |
end else begin |
xFSLSTB <= (fPUT | fGET) & iwb_ack_i; |
xFSLWRE <= fPUT & iwb_ack_i; |
end |
|
always @(posedge gclk) |
if (grst) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
rFSLSTB <= 1'h0; |
rFSLWRE <= 1'h0; |
// End of automatics |
end else if (fFACK) begin |
rFSLSTB <= #1 xFSLSTB; |
rFSLWRE <= #1 xFSLWRE; |
end |
|
// --- PIPELINE CONTROL DELAY ---------------------------- |
|
always @(posedge gclk) |
if (grst) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
rMXALT <= 2'h0; |
rMXALU <= 3'h0; |
rMXDST <= 2'h0; |
rMXSRC <= 2'h0; |
rMXTGT <= 2'h0; |
rRW <= 5'h0; |
// End of automatics |
end else if (gena) begin // if (grst) |
//rPCLNK <= #1 xPCLNK; |
rMXDST <= #1 xMXDST; |
rRW <= #1 xRW; |
rMXSRC <= #1 xMXSRC; |
rMXTGT <= #1 xMXTGT; |
rMXALT <= #1 xMXALT; |
rMXALU <= #1 xMXALU; |
end |
|
|
endmodule // aeMB_ctrl |
/verilog/aeMB_xecu.v
0,0 → 1,376
// $Id: aeMB_xecu.v,v 1.9 2007-11-30 16:42:51 sybreon Exp $ |
// |
// AEMB MAIN EXECUTION ALU |
// |
// 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/>. |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.8 2007/11/16 21:52:03 sybreon |
// Added fsl_tag_o to FSL bus (tag either address or data). |
// |
// Revision 1.7 2007/11/14 22:14:34 sybreon |
// Changed interrupt handling system (reported by M. Ettus). |
// |
// Revision 1.6 2007/11/10 16:39:38 sybreon |
// Upgraded license to LGPLv3. |
// Significant performance optimisations. |
// |
// Revision 1.5 2007/11/09 20:51:52 sybreon |
// Added GET/PUT support through a FSL bus. |
// |
// Revision 1.4 2007/11/08 14:17:47 sybreon |
// Parameterised optional components. |
// |
// Revision 1.3 2007/11/03 08:34:55 sybreon |
// Minor code cleanup. |
// |
// Revision 1.2 2007/11/02 19:20:58 sybreon |
// Added better (beta) interrupt support. |
// Changed MSR_IE to disabled at reset as per MB docs. |
// |
// Revision 1.1 2007/11/02 03:25:41 sybreon |
// New EDK 3.2 compatible design with optional barrel-shifter and multiplier. |
// Fixed various minor data hazard bugs. |
// Code compatible with -O0/1/2/3/s generated code. |
// |
|
module aeMB_xecu (/*AUTOARG*/ |
// Outputs |
dwb_adr_o, dwb_sel_o, fsl_adr_o, fsl_tag_o, rRESULT, rDWBSEL, |
rMSR_IE, rMSR_BIP, |
// Inputs |
rREGA, rREGB, rMXSRC, rMXTGT, rRA, rRB, rMXALU, rBRA, rDLY, rALT, |
rSIMM, rIMM, rOPC, rRD, rDWBDI, rPC, gclk, grst, gena |
); |
parameter DW=32; |
|
parameter MUL=0; |
parameter BSF=0; |
|
// DATA WISHBONE |
output [DW-1:2] dwb_adr_o; |
output [3:0] dwb_sel_o; |
|
// FSL WISHBONE |
output [6:2] fsl_adr_o; |
output [1:0] fsl_tag_o; |
|
// INTERNAL |
output [31:0] rRESULT; |
output [3:0] rDWBSEL; |
output rMSR_IE; |
output rMSR_BIP; |
input [31:0] rREGA, rREGB; |
input [1:0] rMXSRC, rMXTGT; |
input [4:0] rRA, rRB; |
input [2:0] rMXALU; |
input rBRA, rDLY; |
input [10:0] rALT; |
|
input [31:0] rSIMM; |
input [15:0] rIMM; |
input [5:0] rOPC; |
input [4:0] rRD; |
input [31:0] rDWBDI; |
input [31:2] rPC; |
|
// SYSTEM |
input gclk, grst, gena; |
|
reg rMSR_C, xMSR_C; |
reg rMSR_IE, xMSR_IE; |
reg rMSR_BE, xMSR_BE; |
reg rMSR_BIP, xMSR_BIP; |
|
wire fSKIP = rBRA & !rDLY; |
|
// --- OPERAND SELECT |
|
reg [31:0] rOPA, rOPB; |
always @(/*AUTOSENSE*/rDWBDI or rMXSRC or rPC or rREGA or rRESULT) |
case (rMXSRC) |
2'o0: rOPA <= rREGA; |
2'o1: rOPA <= rRESULT; |
2'o2: rOPA <= rDWBDI; |
2'o3: rOPA <= {rPC, 2'o0}; |
endcase // case (rMXSRC) |
|
always @(/*AUTOSENSE*/rDWBDI or rMXTGT or rREGB or rRESULT or rSIMM) |
case (rMXTGT) |
2'o0: rOPB <= rREGB; |
2'o1: rOPB <= rRESULT; |
2'o2: rOPB <= rDWBDI; |
2'o3: rOPB <= rSIMM; |
endcase // case (rMXTGT) |
|
// --- ADD/SUB SELECTOR ---- |
// FIXME: Redesign |
// TODO: Refactor |
// TODO: Verify signed compare |
|
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 [31:0] wMSR = {rMSR_C, 3'o0, |
20'h0ED32, |
4'h0, rMSR_BIP, rMSR_C, rMSR_IE, rMSR_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 or rRA |
or wMSR) |
rRES_MOV <= (fMFSR) ? wMSR : |
(fMFPC) ? rPC : |
(rRA[3]) ? rOPB : |
rOPA; |
|
// --- MULTIPLIER ------------------------------------------ |
// TODO: 2 stage multiplier |
|
reg [31:0] rRES_MUL; |
always @(/*AUTOSENSE*/rOPA or rOPB) begin |
rRES_MUL <= (rOPA * rOPB); |
end |
|
// --- BARREL SHIFTER -------------------------------------- |
|
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 ----------------- |
|
// C |
wire fMTS = (rOPC == 6'o45) & rIMM[14]; |
wire fADDC = ({rOPC[5:4], rOPC[2]} == 3'o0); |
|
always @(/*AUTOSENSE*/fADDC or fMTS or fSKIP or rMSR_C or rMXALU |
or rOPA or rRES_ADDC or rRES_SFTC) |
//if (fSKIP | |rXCE) begin |
if (fSKIP) begin |
xMSR_C <= rMSR_C; |
end else |
case (rMXALU) |
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 |
|
// 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 @(/*AUTOSENSE*/fINT or fMTS or fRTID or rMSR_IE or rOPA) |
xMSR_IE <= (fINT) ? 1'b0 : |
(fRTID) ? 1'b1 : |
(fMTS) ? rOPA[1] : |
rMSR_IE; |
|
always @(/*AUTOSENSE*/fBRK or fMTS or fRTBD or rMSR_BIP or rOPA) |
xMSR_BIP <= (fBRK) ? 1'b1 : |
(fRTBD) ? 1'b0 : |
(fMTS) ? rOPA[3] : |
rMSR_BIP; |
|
always @(/*AUTOSENSE*/fMTS or rMSR_BE or rOPA) |
xMSR_BE <= (fMTS) ? rOPA[0] : rMSR_BE; |
|
// --- RESULT SELECTOR ------------------------------------------- |
// Selects results from functional units. |
reg [31:0] rRESULT, xRESULT; |
|
// RESULT |
always @(/*AUTOSENSE*/fSKIP or rMXALU or rRES_ADD or rRES_BSF |
or rRES_LOG or rRES_MOV or rRES_MUL or rRES_SFT) |
if (fSKIP) |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
xRESULT <= 32'h0; |
// End of automatics |
else |
case (rMXALU) |
3'o0: xRESULT <= rRES_ADD; |
3'o1: xRESULT <= rRES_LOG; |
3'o2: xRESULT <= rRES_SFT; |
3'o3: xRESULT <= rRES_MOV; |
3'o4: xRESULT <= (MUL) ? rRES_MUL : 32'hX; |
3'o5: xRESULT <= (BSF) ? rRES_BSF : 32'hX; |
default: xRESULT <= 32'hX; |
endcase // case (rMXALU) |
|
// --- DATA WISHBONE ----- |
|
reg [3:0] rDWBSEL, xDWBSEL; |
assign dwb_adr_o = rRESULT[DW-1:2]; |
assign dwb_sel_o = rDWBSEL; |
|
always @(/*AUTOSENSE*/rOPC or wADD) |
case (rOPC[1:0]) |
2'o0: case (wADD[1:0]) // 8'bit |
2'o0: xDWBSEL <= 4'h8; |
2'o1: xDWBSEL <= 4'h4; |
2'o2: xDWBSEL <= 4'h2; |
2'o3: xDWBSEL <= 4'h1; |
endcase // case (wADD[1:0]) |
2'o1: xDWBSEL <= (wADD[1]) ? 4'h3 : 4'hC; // 16'bit |
2'o2: xDWBSEL <= 4'hF; // 32'bit |
2'o3: xDWBSEL <= 4'h0; // FSL |
endcase // case (rOPC[1:0]) |
|
// --- FSL WISHBONE -------------------- |
|
reg [14:2] rFSLADR, xFSLADR; |
|
assign {fsl_adr_o, fsl_tag_o} = rFSLADR[8:2]; |
|
always @(/*AUTOSENSE*/rALT or rRB) begin |
xFSLADR <= {rALT, rRB[3:2]}; |
end |
|
// --- SYNC --- |
|
always @(posedge gclk) |
if (grst) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
rDWBSEL <= 4'h0; |
rFSLADR <= 13'h0; |
rMSR_BE <= 1'h0; |
rMSR_BIP <= 1'h0; |
rMSR_C <= 1'h0; |
rMSR_IE <= 1'h0; |
rRESULT <= 32'h0; |
// End of automatics |
end else if (gena) begin |
rRESULT <= #1 xRESULT; |
rDWBSEL <= #1 xDWBSEL; |
rMSR_C <= #1 xMSR_C; |
rMSR_IE <= #1 xMSR_IE; |
rMSR_BE <= #1 xMSR_BE; |
rMSR_BIP <= #1 xMSR_BIP; |
rFSLADR <= #1 xFSLADR; |
end |
|
endmodule // aeMB_xecu |
/verilog/aeMB_core.v
0,0 → 1,134
// $Id: aeMB_core.v,v 1.9 2007-11-23 14:06:41 sybreon Exp $ |
// |
// AEMB 32'bit RISC MICROPROCESSOR CORE |
// |
// 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/>. |
// |
// HISTORY |
// $Log: not supported by cvs2svn $ |
// Revision 1.8 2007/10/22 19:12:59 sybreon |
// Made some changes to the interrupt control. In some cases, the interrupt logic waits forever and doesn't execute. Bug was discovered by M. Ettus. |
// |
// Revision 1.7 2007/05/30 18:44:30 sybreon |
// Added interrupt support. |
// |
// Revision 1.6 2007/05/17 09:08:21 sybreon |
// Removed asynchronous reset signal. |
// |
// Revision 1.5 2007/04/27 00:23:55 sybreon |
// Added code documentation. |
// Improved size & speed of rtl/verilog/aeMB_aslu.v |
// |
// Revision 1.4 2007/04/25 22:15:04 sybreon |
// Added support for 8-bit and 16-bit data types. |
// |
// Revision 1.3 2007/04/11 04:30:43 sybreon |
// Added pipeline stalling from incomplete bus cycles. |
// Separated sync and async portions of code. |
// |
// Revision 1.2 2007/04/04 06:13:23 sybreon |
// Removed unused signals |
// |
// Revision 1.1 2007/03/09 17:52:17 sybreon |
// initial import |
// |
|
|
module aeMB_core (/*AUTOARG*/ |
// Outputs |
iwb_stb_o, iwb_adr_o, fsl_wre_o, fsl_tag_o, fsl_stb_o, fsl_dat_o, |
fsl_adr_o, dwb_wre_o, dwb_stb_o, dwb_sel_o, dwb_dat_o, dwb_adr_o, |
// Inputs |
sys_rst_i, sys_int_i, sys_clk_i, iwb_dat_i, iwb_ack_i, fsl_dat_i, |
fsl_ack_i, dwb_dat_i, dwb_ack_i |
); |
// Instruction WB address space |
parameter ISIZ = 32; |
// Data WB address space |
parameter DSIZ = 32; |
// Multiplier |
parameter MUL = 1; |
// Barrel Shifter |
parameter BSF = 1; |
|
/*AUTOOUTPUT*/ |
// Beginning of automatic outputs (from unused autoinst outputs) |
output [DSIZ-1:2] dwb_adr_o; // From edk32 of aeMB_edk32.v |
output [31:0] dwb_dat_o; // From edk32 of aeMB_edk32.v |
output [3:0] dwb_sel_o; // From edk32 of aeMB_edk32.v |
output dwb_stb_o; // From edk32 of aeMB_edk32.v |
output dwb_wre_o; // From edk32 of aeMB_edk32.v |
output [6:2] fsl_adr_o; // From edk32 of aeMB_edk32.v |
output [31:0] fsl_dat_o; // From edk32 of aeMB_edk32.v |
output fsl_stb_o; // From edk32 of aeMB_edk32.v |
output [1:0] fsl_tag_o; // From edk32 of aeMB_edk32.v |
output fsl_wre_o; // From edk32 of aeMB_edk32.v |
output [ISIZ-1:2] iwb_adr_o; // From edk32 of aeMB_edk32.v |
output iwb_stb_o; // From edk32 of aeMB_edk32.v |
// End of automatics |
/*AUTOINPUT*/ |
// Beginning of automatic inputs (from unused autoinst inputs) |
input dwb_ack_i; // To edk32 of aeMB_edk32.v |
input [31:0] dwb_dat_i; // To edk32 of aeMB_edk32.v |
input fsl_ack_i; // To edk32 of aeMB_edk32.v |
input [31:0] fsl_dat_i; // To edk32 of aeMB_edk32.v |
input iwb_ack_i; // To edk32 of aeMB_edk32.v |
input [31:0] iwb_dat_i; // To edk32 of aeMB_edk32.v |
input sys_clk_i; // To edk32 of aeMB_edk32.v |
input sys_int_i; // To edk32 of aeMB_edk32.v |
input sys_rst_i; // To edk32 of aeMB_edk32.v |
// End of automatics |
/*AUTOWIRE*/ |
|
// INSTANTIATIONS ///////////////////////////////////////////////////////////////// |
|
/* |
aeMB_edk32 AUTO_TEMPLATE ( |
.dwb_adr_o(dwb_adr_o[DSIZ-1:2]), |
.iwb_adr_o(iwb_adr_o[ISIZ-1:2]), |
); |
*/ |
|
aeMB_edk32 #(ISIZ, DSIZ, MUL, BSF) |
edk32 (/*AUTOINST*/ |
// Outputs |
.dwb_adr_o (dwb_adr_o[DSIZ-1:2]), // Templated |
.dwb_dat_o (dwb_dat_o[31:0]), |
.dwb_sel_o (dwb_sel_o[3:0]), |
.dwb_stb_o (dwb_stb_o), |
.dwb_wre_o (dwb_wre_o), |
.fsl_adr_o (fsl_adr_o[6:2]), |
.fsl_dat_o (fsl_dat_o[31:0]), |
.fsl_stb_o (fsl_stb_o), |
.fsl_tag_o (fsl_tag_o[1:0]), |
.fsl_wre_o (fsl_wre_o), |
.iwb_adr_o (iwb_adr_o[ISIZ-1:2]), // Templated |
.iwb_stb_o (iwb_stb_o), |
// Inputs |
.dwb_ack_i (dwb_ack_i), |
.dwb_dat_i (dwb_dat_i[31:0]), |
.fsl_ack_i (fsl_ack_i), |
.fsl_dat_i (fsl_dat_i[31:0]), |
.iwb_ack_i (iwb_ack_i), |
.iwb_dat_i (iwb_dat_i[31:0]), |
.sys_int_i (sys_int_i), |
.sys_clk_i (sys_clk_i), |
.sys_rst_i (sys_rst_i)); |
|
|
endmodule // aeMB_core |
/verilog/aeMB_ibuf.v
0,0 → 1,156
// $Id: aeMB_ibuf.v,v 1.7 2007-11-22 15:11:15 sybreon Exp $ |
// |
// AEMB INSTRUCTION BUFFER |
// |
// 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/>. |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.6 2007/11/14 23:39:51 sybreon |
// Fixed interrupt signal synchronisation. |
// |
// Revision 1.5 2007/11/14 22:14:34 sybreon |
// Changed interrupt handling system (reported by M. Ettus). |
// |
// Revision 1.4 2007/11/10 16:39:38 sybreon |
// Upgraded license to LGPLv3. |
// Significant performance optimisations. |
// |
// Revision 1.3 2007/11/03 08:34:55 sybreon |
// Minor code cleanup. |
// |
// Revision 1.2 2007/11/02 19:20:58 sybreon |
// Added better (beta) interrupt support. |
// Changed MSR_IE to disabled at reset as per MB docs. |
// |
// Revision 1.1 2007/11/02 03:25:40 sybreon |
// New EDK 3.2 compatible design with optional barrel-shifter and multiplier. |
// Fixed various minor data hazard bugs. |
// Code compatible with -O0/1/2/3/s generated code. |
// |
|
module aeMB_ibuf (/*AUTOARG*/ |
// Outputs |
rIMM, rRA, rRD, rRB, rALT, rOPC, rSIMM, xIREG, iwb_stb_o, |
// Inputs |
rBRA, rMSR_IE, rMSR_BIP, iwb_dat_i, iwb_ack_i, sys_int_i, gclk, |
grst, gena |
); |
// INTERNAL |
output [15:0] rIMM; |
output [4:0] rRA, rRD, rRB; |
output [10:0] rALT; |
output [5:0] rOPC; |
output [31:0] rSIMM; |
output [31:0] xIREG; |
|
input rBRA; |
//input [1:0] rXCE; |
input rMSR_IE; |
input rMSR_BIP; |
|
// INST WISHBONE |
output iwb_stb_o; |
input [31:0] iwb_dat_i; |
input iwb_ack_i; |
|
// SYSTEM |
input sys_int_i; |
|
// SYSTEM |
input gclk, grst, gena; |
|
reg [15:0] rIMM; |
reg [4:0] rRA, rRD; |
reg [5:0] rOPC; |
|
// FIXME: Endian |
wire [31:0] wIDAT = iwb_dat_i; |
assign {rRB, rALT} = rIMM; |
|
// TODO: Assign to FIFO not full. |
assign iwb_stb_o = 1'b1; |
|
reg [31:0] rSIMM, xSIMM; |
|
wire [31:0] wXCEOP = 32'hBA2D0008; // Vector 0x08 |
wire [31:0] wINTOP = 32'hB9CE0010; // Vector 0x10 |
wire [31:0] wBRKOP = 32'hBA0C0018; // Vector 0x18 |
wire [31:0] wBRAOP = 32'h88000000; // NOP for branches |
|
wire [31:0] wIREG = {rOPC, rRD, rRA, rRB, rALT}; |
reg [31:0] xIREG; |
|
|
// --- INTERRUPT LATCH -------------------------------------- |
// Debounce and latch onto the positive level. This is independent |
// of the pipeline so that stalls do not affect it. |
|
reg rFINT; |
reg [1:0] rDINT; |
wire wSHOT = rDINT[0]; |
|
always @(posedge gclk) |
if (grst) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
rDINT <= 2'h0; |
rFINT <= 1'h0; |
// End of automatics |
end else if (rMSR_IE) begin |
rDINT <= #1 {rDINT[0], sys_int_i}; |
rFINT <= #1 (wIREG == wINTOP) ? 1'b0 : (rFINT | wSHOT); |
end |
|
wire fIMM = (rOPC == 6'o54); |
wire fRTD = (rOPC == 6'o55); |
wire fBRU = ((rOPC == 6'o46) | (rOPC == 6'o56)); |
wire fBCC = ((rOPC == 6'o47) | (rOPC == 6'o57)); |
|
// --- DELAY SLOT ------------------------------------------- |
|
always @(/*AUTOSENSE*/fBCC or fBRU or fIMM or fRTD or rBRA or rFINT |
or wBRAOP or wIDAT or wINTOP) begin |
xIREG <= (rBRA) ? wBRAOP : |
(!fIMM & rFINT & !fRTD & !fBRU & !fBCC) ? wINTOP : |
wIDAT; |
end |
|
always @(/*AUTOSENSE*/fIMM or rBRA or rIMM or wIDAT or xIREG) begin |
xSIMM <= (!fIMM | rBRA) ? { {(16){xIREG[15]}}, xIREG[15:0]} : |
{rIMM, wIDAT[15:0]}; |
end |
|
// --- PIPELINE -------------------------------------------- |
|
always @(posedge gclk) |
if (grst) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
rIMM <= 16'h0; |
rOPC <= 6'h0; |
rRA <= 5'h0; |
rRD <= 5'h0; |
rSIMM <= 32'h0; |
// End of automatics |
end else if (gena) begin |
{rOPC, rRD, rRA, rIMM} <= #1 xIREG; |
rSIMM <= #1 xSIMM; |
end |
|
|
endmodule // aeMB_ibuf |
/verilog/aeMB_bpcu.v
0,0 → 1,181
// $Id: aeMB_bpcu.v,v 1.4 2007-11-14 22:14:34 sybreon Exp $ |
// |
// AEMB BRANCH PROGRAMME COUNTER 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/>. |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.3 2007/11/10 16:39:38 sybreon |
// Upgraded license to LGPLv3. |
// Significant performance optimisations. |
// |
// Revision 1.2 2007/11/02 19:20:58 sybreon |
// Added better (beta) interrupt support. |
// Changed MSR_IE to disabled at reset as per MB docs. |
// |
// Revision 1.1 2007/11/02 03:25:39 sybreon |
// New EDK 3.2 compatible design with optional barrel-shifter and multiplier. |
// Fixed various minor data hazard bugs. |
// Code compatible with -O0/1/2/3/s generated code. |
// |
|
module aeMB_bpcu (/*AUTOARG*/ |
// Outputs |
iwb_adr_o, rPC, rPCLNK, rBRA, rDLY, |
// Inputs |
rMXALT, rOPC, rRD, rRA, rRESULT, rDWBDI, rREGA, gclk, grst, gena |
); |
parameter IW = 24; |
|
// INST WISHBONE |
output [IW-1:2] iwb_adr_o; |
|
// INTERNAL |
output [31:2] rPC, rPCLNK; |
output rBRA; |
output rDLY; |
//output [1:0] rATOM; |
//output [1:0] xATOM; |
|
input [1:0] rMXALT; |
input [5:0] rOPC; |
input [4:0] rRD, rRA; |
input [31:0] rRESULT; // ALU |
input [31:0] rDWBDI; // RAM |
input [31:0] rREGA; |
//input [1:0] rXCE; |
|
// SYSTEM |
input gclk, grst, gena; |
|
// --- BRANCH CONTROL -------------------------------------------- |
// Controls the branch and delay flags |
|
wire fRTD = (rOPC == 6'o55); |
wire fBCC = (rOPC == 6'o47) | (rOPC == 6'o57); |
wire fBRU = (rOPC == 6'o46) | (rOPC == 6'o56); |
|
wire [31:0] wREGA; |
assign wREGA = (rMXALT == 2'o2) ? rDWBDI : |
(rMXALT == 2'o1) ? rRESULT : |
rREGA; |
|
wire wBEQ = (wREGA == 32'd0); |
wire wBNE = ~wBEQ; |
wire wBLT = wREGA[31]; |
wire wBLE = wBLT | wBEQ; |
wire wBGE = ~wBLT; |
wire wBGT = ~wBLE; |
|
reg xXCC; |
always @(/*AUTOSENSE*/rRD or wBEQ or wBGE or wBGT or wBLE or wBLT |
or wBNE) |
case (rRD[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[2:0]) |
|
reg rBRA, xBRA; |
reg rDLY, xDLY; |
wire fSKIP = rBRA & !rDLY; |
|
always @(/*AUTOSENSE*/fBCC or fBRU or fRTD or rBRA or rRA or rRD |
or xXCC) |
//if (rBRA | |rXCE) begin |
if (rBRA) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
xBRA <= 1'h0; |
xDLY <= 1'h0; |
// End of automatics |
end else begin |
xDLY <= (fBRU & rRA[4]) | (fBCC & rRD[4]) | fRTD; |
xBRA <= (fRTD | fBRU) ? 1'b1 : |
(fBCC) ? xXCC : |
1'b0; |
end |
|
// --- PC PIPELINE ------------------------------------------------ |
// PC and related changes |
|
reg [31:2] rIPC, xIPC; |
reg [31:2] rPC, xPC; |
reg [31:2] rPCLNK, xPCLNK; |
|
assign iwb_adr_o = rIPC[IW-1:2]; |
|
always @(/*AUTOSENSE*/rBRA or rIPC or rPC or rRESULT) begin |
//xPCLNK <= (^rATOM) ? rPC : rPC; |
xPCLNK <= rPC; |
//xPC <= (^rATOM) ? rIPC : rRESULT[31:2]; |
xPC <= rIPC; |
//xIPC <= (rBRA) ? rRESULT[31:2] : (rIPC + 1); |
/* |
case (rXCE) |
2'o1: xIPC <= 30'h2; |
2'o2: xIPC <= 30'h4; |
2'o3: xIPC <= 30'h6; |
default: xIPC <= (rBRA) ? rRESULT[31:2] : (rIPC + 1); |
endcase // case (rXCE) |
*/ |
xIPC <= (rBRA) ? rRESULT[31:2] : (rIPC + 1); |
end |
|
// --- ATOMIC CONTROL --------------------------------------------- |
// This is used to indicate 'safe' instruction borders. |
|
wire wIMM = (rOPC == 6'o54) & !fSKIP; |
wire wRTD = (rOPC == 6'o55) & !fSKIP; |
wire wBCC = xXCC & ((rOPC == 6'o47) | (rOPC == 6'o57)) & !fSKIP; |
wire wBRU = ((rOPC == 6'o46) | (rOPC == 6'o56)) & !fSKIP; |
|
wire fATOM = ~(wIMM | wRTD | wBCC | wBRU | rBRA); |
reg [1:0] rATOM, xATOM; |
|
always @(/*AUTOSENSE*/fATOM or rATOM) |
xATOM <= {rATOM[0], (rATOM[0] ^ fATOM)}; |
|
|
// --- SYNC PIPELINE ---------------------------------------------- |
|
always @(posedge gclk) |
if (grst) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
rATOM <= 2'h0; |
rBRA <= 1'h0; |
rDLY <= 1'h0; |
rIPC <= 30'h0; |
rPC <= 30'h0; |
rPCLNK <= 30'h0; |
// End of automatics |
end else if (gena) begin |
rIPC <= #1 xIPC; |
rBRA <= #1 xBRA; |
rPC <= #1 xPC; |
rPCLNK <= #1 xPCLNK; |
rDLY <= #1 xDLY; |
rATOM <= #1 xATOM; |
end |
|
endmodule // aeMB_bpcu |
/verilog/aeMB_regf.v
0,0 → 1,237
// $Id: aeMB_regf.v,v 1.3 2007-11-10 16:39:38 sybreon Exp $ |
// |
// AEMB 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/>. |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.2 2007/11/09 20:51:52 sybreon |
// Added GET/PUT support through a FSL bus. |
// |
// Revision 1.1 2007/11/02 03:25:41 sybreon |
// New EDK 3.2 compatible design with optional barrel-shifter and multiplier. |
// Fixed various minor data hazard bugs. |
// Code compatible with -O0/1/2/3/s generated code. |
// |
|
module aeMB_regf (/*AUTOARG*/ |
// Outputs |
rREGA, rREGB, rDWBDI, dwb_dat_o, fsl_dat_o, |
// Inputs |
rOPC, rRA, rRB, rRW, rRD, rMXDST, rPCLNK, rRESULT, rDWBSEL, rBRA, |
rDLY, dwb_dat_i, fsl_dat_i, gclk, grst, gena |
); |
// INTERNAL |
output [31:0] rREGA, rREGB; |
output [31:0] rDWBDI; |
input [5:0] rOPC; |
input [4:0] rRA, rRB, rRW, rRD; |
input [1:0] rMXDST; |
input [31:2] rPCLNK; |
input [31:0] rRESULT; |
input [3:0] rDWBSEL; |
input rBRA, rDLY; |
|
// DATA WISHBONE |
output [31:0] dwb_dat_o; |
input [31:0] dwb_dat_i; |
|
// FSL WISHBONE |
output [31:0] fsl_dat_o; |
input [31:0] fsl_dat_i; |
|
// SYSTEM |
input gclk, grst, gena; |
|
// --- LOAD SIZER ---------------------------------------------- |
// Moves the data bytes around depending on the size of the |
// operation. |
|
wire [31:0] wDWBDI = dwb_dat_i; // FIXME: Endian |
wire [31:0] wFSLDI = fsl_dat_i; // FIXME: Endian |
|
reg [31:0] rDWBDI; |
reg [1:0] rSIZ; |
|
always @(/*AUTOSENSE*/rDWBSEL or wDWBDI or wFSLDI) begin |
/* 51.2 |
case (rSIZ) |
// FSL |
2'o3: rDWBDI <= wFSLDI; |
// 32'bit |
2'o2: rDWBDI <= wDWBDI; |
// 16'bit |
2'o1: case (rRESULT[1]) |
1'b0: rDWBDI <= {16'd0, wDWBDI[31:16]}; |
1'b1: rDWBDI <= {16'd0, wDWBDI[15:0]}; |
endcase // case (rRESULT[1]) |
// 8'bit |
2'o0: case (rRESULT[1:0]) |
2'o0: rDWBDI <= {24'd0, wDWBDI[31:24]}; |
2'o1: rDWBDI <= {24'd0, wDWBDI[23:16]}; |
2'o2: rDWBDI <= {24'd0, wDWBDI[15:8]}; |
2'o3: rDWBDI <= {24'd0, wDWBDI[7:0]}; |
endcase // case (rRESULT[1:0]) |
endcase // case (rSIZ) |
*/ |
|
/* 50.6 |
case ({rSIZ, rRESULT[1:0]}) |
// FSL |
4'hC, 4'hD, 4'hE, 4'hF: rDWBDI <= wFSLDI; |
// 32'bit |
4'h8: rDWBDI <= wDWBDI; |
// 16'bit |
4'h4: rDWBDI <= {16'd0, wDWBDI[31:16]}; |
4'h6: rDWBDI <= {16'd0, wDWBDI[15:0]}; |
// 8'bit |
4'h0: rDWBDI <= {24'd0, wDWBDI[31:24]}; |
4'h1: rDWBDI <= {24'd0, wDWBDI[23:16]}; |
4'h2: rDWBDI <= {24'd0, wDWBDI[15:8]}; |
4'h3: rDWBDI <= {24'd0, wDWBDI[7:0]}; |
default: rDWBDI <= 32'hX; |
endcase // case (rSIZ) |
*/ |
|
// 52.0 |
case (rDWBSEL) |
// 8'bit |
4'h8: rDWBDI <= {24'd0, wDWBDI[31:24]}; |
4'h4: rDWBDI <= {24'd0, wDWBDI[23:16]}; |
4'h2: rDWBDI <= {24'd0, wDWBDI[15:8]}; |
4'h1: rDWBDI <= {24'd0, wDWBDI[7:0]}; |
// 16'bit |
4'hC: rDWBDI <= {16'd0, wDWBDI[31:16]}; |
4'h3: rDWBDI <= {16'd0, wDWBDI[15:0]}; |
// 32'bit |
4'hF: rDWBDI <= wDWBDI; |
// FSL |
4'h0: rDWBDI <= wFSLDI; |
// Undefined |
default: rDWBDI <= 32'hX; |
endcase |
|
end |
|
always @(posedge gclk) |
if (grst) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
rSIZ <= 2'h0; |
// End of automatics |
end else if (gena) begin |
rSIZ <= rOPC[1:0]; |
end |
|
// --- GENERAL PURPOSE REGISTERS (R0-R31) ----------------------- |
// LUT RAM implementation is smaller and faster. R0 gets written |
// during reset with 0x00 and doesn't change after. |
|
reg [31:0] mARAM[0:31], |
mBRAM[0:31], |
mDRAM[0:31]; |
|
wire [31:0] rREGW = mDRAM[rRW]; |
wire [31:0] rREGD = mDRAM[rRD]; |
assign rREGA = mARAM[rRA]; |
assign rREGB = mBRAM[rRB]; |
|
wire fRDWE = |rRW; |
|
reg [31:0] xWDAT; |
|
always @(/*AUTOSENSE*/rDWBDI or rMXDST or rPCLNK or rREGW |
or rRESULT) |
case (rMXDST) |
2'o2: xWDAT <= rDWBDI; |
2'o1: xWDAT <= {rPCLNK, 2'o0}; |
2'o0: xWDAT <= rRESULT; |
2'o3: xWDAT <= rREGW; // No change |
endcase // case (rMXDST) |
|
always @(posedge gclk) |
if (grst | fRDWE) begin |
mARAM[rRW] <= xWDAT; |
mBRAM[rRW] <= xWDAT; |
mDRAM[rRW] <= xWDAT; |
end |
|
// --- STORE SIZER --------------------------------------------- |
// Replicates the data bytes across depending on the size of the |
// operation. |
|
reg [31:0] rDWBDO, xDWBDO; |
|
wire [31:0] xFSL; |
wire fFFWD_M = (rRA == rRW) & (rMXDST == 2'o2) & fRDWE; |
wire fFFWD_R = (rRA == rRW) & (rMXDST == 2'o0) & fRDWE; |
|
assign fsl_dat_o = rDWBDO; |
assign xFSL = (fFFWD_M) ? rDWBDI : |
(fFFWD_R) ? rRESULT : |
rREGA; |
|
wire [31:0] xDST; |
wire fDFWD_M = (rRW == rRD) & (rMXDST == 2'o2) & fRDWE; |
wire fDFWD_R = (rRW == rRD) & (rMXDST == 2'o0) & fRDWE; |
|
assign dwb_dat_o = rDWBDO; |
assign xDST = (fDFWD_M) ? rDWBDI : |
(fDFWD_R) ? rRESULT : |
rREGD; |
|
always @(/*AUTOSENSE*/rOPC or xDST or xFSL) |
case (rOPC[1:0]) |
// 8'bit |
2'h0: xDWBDO <= {(4){xDST[7:0]}}; |
// 16'bit |
2'h1: xDWBDO <= {(2){xDST[15:0]}}; |
// 32'bit |
2'h2: xDWBDO <= xDST; |
// FSL |
2'h3: xDWBDO <= xFSL; |
//default: xDWBDO <= 32'hX; |
endcase // case (rOPC[1:0]) |
|
always @(posedge gclk) |
if (grst) begin |
/*AUTORESET*/ |
// Beginning of autoreset for uninitialized flops |
rDWBDO <= 32'h0; |
// End of automatics |
end else if (gena) begin |
rDWBDO <= #1 xDWBDO; |
end |
|
// --- SIMULATION ONLY ------------------------------------------ |
// Randomise memory to simulate real-world memory |
// synopsys translate_off |
|
integer i; |
initial begin |
for (i=0; i<32; i=i+1) begin |
mARAM[i] <= $random; |
mBRAM[i] <= $random; |
mDRAM[i] <= $random; |
end |
end |
|
// synopsys translate_on |
|
|
endmodule // aeMB_regf |