diff options
Diffstat (limited to 'opencores/aemb')
51 files changed, 3571 insertions, 0 deletions
diff --git a/opencores/aemb/CVS/Entries b/opencores/aemb/CVS/Entries new file mode 100644 index 000000000..093a9a86a --- /dev/null +++ b/opencores/aemb/CVS/Entries @@ -0,0 +1,4 @@ +D/rtl//// +D/sim//// +D/sw//// +D/doc//// diff --git a/opencores/aemb/CVS/Repository b/opencores/aemb/CVS/Repository new file mode 100644 index 000000000..967f2cedf --- /dev/null +++ b/opencores/aemb/CVS/Repository @@ -0,0 +1 @@ +aemb diff --git a/opencores/aemb/CVS/Root b/opencores/aemb/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/aemb/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/aemb/CVS/Template b/opencores/aemb/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/aemb/CVS/Template diff --git a/opencores/aemb/doc/CVS/Entries b/opencores/aemb/doc/CVS/Entries new file mode 100644 index 000000000..16bb46ac6 --- /dev/null +++ b/opencores/aemb/doc/CVS/Entries @@ -0,0 +1,2 @@ +/aeMB_datasheet.pdf/1.3/Tue Jan 15 18:38:57 2008/-kb/ +D diff --git a/opencores/aemb/doc/CVS/Repository b/opencores/aemb/doc/CVS/Repository new file mode 100644 index 000000000..41df302a9 --- /dev/null +++ b/opencores/aemb/doc/CVS/Repository @@ -0,0 +1 @@ +aemb/doc diff --git a/opencores/aemb/doc/CVS/Root b/opencores/aemb/doc/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/aemb/doc/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/aemb/doc/CVS/Template b/opencores/aemb/doc/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/aemb/doc/CVS/Template diff --git a/opencores/aemb/doc/aeMB_datasheet.pdf b/opencores/aemb/doc/aeMB_datasheet.pdf Binary files differnew file mode 100644 index 000000000..5b26ac319 --- /dev/null +++ b/opencores/aemb/doc/aeMB_datasheet.pdf diff --git a/opencores/aemb/rtl/CVS/Entries b/opencores/aemb/rtl/CVS/Entries new file mode 100644 index 000000000..428c5622d --- /dev/null +++ b/opencores/aemb/rtl/CVS/Entries @@ -0,0 +1 @@ +D/verilog//// diff --git a/opencores/aemb/rtl/CVS/Repository b/opencores/aemb/rtl/CVS/Repository new file mode 100644 index 000000000..e2c1eab77 --- /dev/null +++ b/opencores/aemb/rtl/CVS/Repository @@ -0,0 +1 @@ +aemb/rtl diff --git a/opencores/aemb/rtl/CVS/Root b/opencores/aemb/rtl/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/aemb/rtl/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/aemb/rtl/CVS/Template b/opencores/aemb/rtl/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/aemb/rtl/CVS/Template diff --git a/opencores/aemb/rtl/verilog/CVS/Entries b/opencores/aemb/rtl/verilog/CVS/Entries new file mode 100644 index 000000000..ad3a7dea6 --- /dev/null +++ b/opencores/aemb/rtl/verilog/CVS/Entries @@ -0,0 +1,38 @@ +/aeMB_bpcu.v/1.4/Mon Feb 4 17:16:00 2008// +/aeMB_core.v/1.9/Mon Feb 4 17:16:00 2008// +/aeMB_ctrl.v/1.10/Mon Feb 4 17:16:00 2008// +/aeMB_edk32.v/1.14/Mon Feb 4 17:16:00 2008// +/aeMB_ibuf.v/1.10/Tue May 20 17:45:01 2008// +/aeMB_regf.v/1.3/Mon Feb 4 17:16:00 2008// +/aeMB_sim.v/1.1/Mon Feb 4 17:16:00 2008// +/aeMB_xecu.v/1.12/Tue May 20 17:48:57 2008// +/aeMB2_aslu.v/1.10/Tue May 20 18:13:50 2008// +/aeMB2_bpcu.v/1.5/Tue May 20 18:13:50 2008// +/aeMB2_brcc.v/1.3/Tue May 20 18:13:50 2008// +/aeMB2_bsft.v/1.3/Tue May 20 18:13:50 2008// +/aeMB2_ctrl.v/1.7/Tue May 20 18:13:51 2008// +/aeMB2_dparam.v/1.1/Tue May 20 18:13:51 2008// +/aeMB2_dwbif.v/1.7/Tue May 20 18:13:51 2008// +/aeMB2_edk32.v/1.8/Tue May 20 18:13:51 2008// +/aeMB2_edk62.v/1.8/Tue May 20 18:13:51 2008// +/aeMB2_exec.v/1.4/Tue May 20 18:13:51 2008// +/aeMB2_gprf.v/1.4/Tue May 20 18:13:51 2008// +/aeMB2_iche.v/1.5/Tue May 20 18:13:51 2008// +/aeMB2_idmx.v/1.5/Tue May 20 18:13:51 2008// +/aeMB2_intu.v/1.7/Tue May 20 18:13:51 2008// +/aeMB2_iwbif.v/1.5/Tue May 20 18:13:51 2008// +/aeMB2_memif.v/1.3/Tue May 20 18:13:51 2008// +/aeMB2_mult.v/1.5/Tue May 20 18:13:51 2008// +/aeMB2_ofid.v/1.2/Tue May 20 18:13:51 2008// +/aeMB2_opmx.v/1.3/Tue May 20 18:13:51 2008// +/aeMB2_pipe.v/1.4/Tue May 20 18:13:51 2008// +/aeMB2_regf.v/1.3/Tue May 20 18:13:51 2008// +/aeMB2_regs.v/1.4/Tue May 20 18:13:51 2008// +/aeMB2_sfrf.v/1.2/Tue May 20 18:13:51 2008// +/aeMB2_sim.v/1.2/Tue May 20 18:13:51 2008// +/aeMB2_sparam.v/1.2/Tue May 20 18:13:51 2008// +/aeMB2_spsram.v/1.1/Tue May 20 18:13:51 2008// +/aeMB2_sysc.v/1.5/Tue May 20 18:13:51 2008// +/aeMB2_tpsram.v/1.3/Tue May 20 18:13:51 2008// +/aeMB2_xslif.v/1.7/Tue May 20 18:13:52 2008// +D diff --git a/opencores/aemb/rtl/verilog/CVS/Repository b/opencores/aemb/rtl/verilog/CVS/Repository new file mode 100644 index 000000000..a9de19556 --- /dev/null +++ b/opencores/aemb/rtl/verilog/CVS/Repository @@ -0,0 +1 @@ +aemb/rtl/verilog diff --git a/opencores/aemb/rtl/verilog/CVS/Root b/opencores/aemb/rtl/verilog/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/aemb/rtl/verilog/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/aemb/rtl/verilog/CVS/Template b/opencores/aemb/rtl/verilog/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/aemb/rtl/verilog/CVS/Template diff --git a/opencores/aemb/rtl/verilog/aeMB_bpcu.v b/opencores/aemb/rtl/verilog/aeMB_bpcu.v new file mode 100644 index 000000000..a7c686e7e --- /dev/null +++ b/opencores/aemb/rtl/verilog/aeMB_bpcu.v @@ -0,0 +1,184 @@ +// $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: aeMB_bpcu.v,v $ +// Revision 1.4 2007/11/14 22:14:34 sybreon +// Changed interrupt handling system (reported by M. Ettus). +// +// 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 diff --git a/opencores/aemb/rtl/verilog/aeMB_core.v b/opencores/aemb/rtl/verilog/aeMB_core.v new file mode 100644 index 000000000..20ce9852e --- /dev/null +++ b/opencores/aemb/rtl/verilog/aeMB_core.v @@ -0,0 +1,137 @@ +// $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: aeMB_core.v,v $ +// Revision 1.9 2007/11/23 14:06:41 sybreon +// Old version deprecated. +// +// 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 diff --git a/opencores/aemb/rtl/verilog/aeMB_core_BE.v b/opencores/aemb/rtl/verilog/aeMB_core_BE.v new file mode 100644 index 000000000..9ffa20ff2 --- /dev/null +++ b/opencores/aemb/rtl/verilog/aeMB_core_BE.v @@ -0,0 +1,62 @@ + +// Wrapper for aeMB core: +// Drive wb_cyc_o (just tied to wb_stb_o for now) +// Make input reset active high (like the signal name makes it sound....) +// No longer needed +// Make it big-endian like the standard MicroBlaze + +module aeMB_core_BE + #(parameter ISIZ=32, parameter DSIZ=32, + parameter MUL=0, parameter BSF=0) + (input sys_clk_i, + input sys_rst_i, + + output iwb_stb_o, + output [ISIZ-1:0] iwb_adr_o, + input [31:0] iwb_dat_i, + input iwb_ack_i, + + output dwb_we_o, + output dwb_stb_o, + output [DSIZ-1:0] dwb_adr_o, + output [31:0] dwb_dat_o, + input [31:0] dwb_dat_i, + input dwb_ack_i, + output [3:0] dwb_sel_o, + output dwb_cyc_o, + + input sys_int_i, + input sys_exc_i); + + assign dwb_cyc_o = dwb_stb_o; + + aeMB_edk32 #(.IW(ISIZ),.DW(DSIZ),.MUL(MUL),.BSF(BSF)) + aeMB_edk32 (.sys_clk_i(sys_clk_i), + .sys_rst_i(sys_rst_i), + + .iwb_stb_o(iwb_stb_o), + .iwb_adr_o(iwb_adr_o[ISIZ-1:2]), + .iwb_ack_i(iwb_ack_i), + .iwb_dat_i(iwb_dat_i), + + .dwb_wre_o(dwb_we_o), + .dwb_stb_o(dwb_stb_o), + .dwb_adr_o(dwb_adr_o[DSIZ-1:2]), + .dwb_ack_i(dwb_ack_i), + .dwb_sel_o(dwb_sel_o), + .dwb_dat_i(dwb_dat_i), + .dwb_dat_o(dwb_dat_o), + + .fsl_wre_o(), + .fsl_tag_o(), + .fsl_stb_o(), + .fsl_dat_o(), + .fsl_adr_o(), + .fsl_dat_i(32'b0), + .fsl_ack_i(1'b0), + .sys_int_i(sys_int_i) ); + + assign iwb_adr_o[1:0] = 2'b0; + assign dwb_adr_o[1:0] = 2'b0; + +endmodule // aeMB_core_BE diff --git a/opencores/aemb/rtl/verilog/aeMB_ctrl.v b/opencores/aemb/rtl/verilog/aeMB_ctrl.v new file mode 100644 index 000000000..88d4e51ce --- /dev/null +++ b/opencores/aemb/rtl/verilog/aeMB_ctrl.v @@ -0,0 +1,336 @@ +// $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: aeMB_ctrl.v,v $ +// Revision 1.10 2007/11/30 16:44:40 sybreon +// Minor code cleanup. +// +// 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 diff --git a/opencores/aemb/rtl/verilog/aeMB_edk32.v b/opencores/aemb/rtl/verilog/aeMB_edk32.v new file mode 100644 index 000000000..8bf4f7cac --- /dev/null +++ b/opencores/aemb/rtl/verilog/aeMB_edk32.v @@ -0,0 +1,289 @@ +/* $Id: aeMB_edk32.v,v 1.14 2008/01/19 16:01:22 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/>. +*/ + +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 = 0; // 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 rSTALL; // 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) & !rSTALL; + wire oena = ((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]), + .rSTALL (rSTALL), + .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), + .oena (oena)); + + 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]), + .rSTALL (rSTALL), + .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)); + + +endmodule // aeMB_edk32 + +/* + $Log: aeMB_edk32.v,v $ + Revision 1.14 2008/01/19 16:01:22 sybreon + Patched problem where memory access followed by dual cycle instructions were not stalling correctly (submitted by M. Ettus) + + Revision 1.13 2007/12/25 22:15:09 sybreon + Stalls pipeline on MUL/BSF instructions results in minor speed improvements. + + Revision 1.12 2007/12/23 20:40:44 sybreon + Abstracted simulation kernel (aeMB_sim) to split simulation models from synthesis models. + + Revision 1.11 2007/11/30 17:08:29 sybreon + Moved simulation kernel into code. + + 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. +*/
\ No newline at end of file diff --git a/opencores/aemb/rtl/verilog/aeMB_ibuf.v b/opencores/aemb/rtl/verilog/aeMB_ibuf.v new file mode 100644 index 000000000..b3e37c448 --- /dev/null +++ b/opencores/aemb/rtl/verilog/aeMB_ibuf.v @@ -0,0 +1,192 @@ +/* $Id: aeMB_ibuf.v,v 1.10 2008/01/21 01:02:26 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/>. +*/ + +module aeMB_ibuf (/*AUTOARG*/ + // Outputs + rIMM, rRA, rRD, rRB, rALT, rOPC, rSIMM, xIREG, rSTALL, iwb_stb_o, + // Inputs + rBRA, rMSR_IE, rMSR_BIP, iwb_dat_i, iwb_ack_i, sys_int_i, gclk, + grst, gena, oena + ); + // 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; + output rSTALL; + + 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, oena; + + 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; + reg rSTALL; + + 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 begin + if (rMSR_IE) + rDINT <= #1 + {rDINT[0], sys_int_i}; + + rFINT <= #1 + //(wIREG == wINTOP) ? 1'b0 : + (rFINT | wSHOT) & rMSR_IE; + 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 + + // --- STALL FOR MUL/BSF ----------------------------------- + + wire [5:0] wOPC = xIREG[31:26]; + + wire fMUL = (wOPC == 6'o20) | (wOPC == 6'o30); + wire fBSF = (wOPC == 6'o21) | (wOPC == 6'o31); + + always @(posedge gclk) + if (grst) begin + /*AUTORESET*/ + // Beginning of autoreset for uninitialized flops + rSTALL <= 1'h0; + // End of automatics + end else begin + rSTALL <= #1 (!rSTALL & (fMUL | fBSF)) | (oena & rSTALL); + end + +endmodule // aeMB_ibuf + +/* + $Log: aeMB_ibuf.v,v $ + Revision 1.10 2008/01/21 01:02:26 sybreon + Patch interrupt bug. + + Revision 1.9 2008/01/19 16:01:22 sybreon + Patched problem where memory access followed by dual cycle instructions were not stalling correctly (submitted by M. Ettus) + + Revision 1.8 2007/12/25 22:15:09 sybreon + Stalls pipeline on MUL/BSF instructions results in minor speed improvements. + + Revision 1.7 2007/11/22 15:11:15 sybreon + Change interrupt to positive level triggered interrupts. + + 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. +*/
\ No newline at end of file diff --git a/opencores/aemb/rtl/verilog/aeMB_regf.v b/opencores/aemb/rtl/verilog/aeMB_regf.v new file mode 100644 index 000000000..9ac45299b --- /dev/null +++ b/opencores/aemb/rtl/verilog/aeMB_regf.v @@ -0,0 +1,241 @@ +// $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: aeMB_regf.v,v $ +// Revision 1.3 2007/11/10 16:39:38 sybreon +// Upgraded license to LGPLv3. +// Significant performance optimisations. +// +// 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 diff --git a/opencores/aemb/rtl/verilog/aeMB_sim.v b/opencores/aemb/rtl/verilog/aeMB_sim.v new file mode 100644 index 000000000..1e70a6317 --- /dev/null +++ b/opencores/aemb/rtl/verilog/aeMB_sim.v @@ -0,0 +1,306 @@ +/* $Id: aeMB_sim.v,v 1.1 2007/12/23 20:40:45 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/>. +*/ + +module aeMB_sim (/*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 + ); + // 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 cpu of aeMB_edk32.v + output [31:0] dwb_dat_o; // From cpu of aeMB_edk32.v + output [3:0] dwb_sel_o; // From cpu of aeMB_edk32.v + output dwb_stb_o; // From cpu of aeMB_edk32.v + output dwb_wre_o; // From cpu of aeMB_edk32.v + output [6:2] fsl_adr_o; // From cpu of aeMB_edk32.v + output [31:0] fsl_dat_o; // From cpu of aeMB_edk32.v + output fsl_stb_o; // From cpu of aeMB_edk32.v + output [1:0] fsl_tag_o; // From cpu of aeMB_edk32.v + output fsl_wre_o; // From cpu of aeMB_edk32.v + output [IW-1:2] iwb_adr_o; // From cpu of aeMB_edk32.v + output iwb_stb_o; // From cpu of aeMB_edk32.v + // End of automatics + /*AUTOINPUT*/ + // Beginning of automatic inputs (from unused autoinst inputs) + input dwb_ack_i; // To cpu of aeMB_edk32.v + input [31:0] dwb_dat_i; // To cpu of aeMB_edk32.v + input fsl_ack_i; // To cpu of aeMB_edk32.v + input [31:0] fsl_dat_i; // To cpu of aeMB_edk32.v + input iwb_ack_i; // To cpu of aeMB_edk32.v + input [31:0] iwb_dat_i; // To cpu of aeMB_edk32.v + input sys_clk_i; // To cpu of aeMB_edk32.v + input sys_int_i; // To cpu of aeMB_edk32.v + input sys_rst_i; // To cpu of aeMB_edk32.v + // End of automatics + /*AUTOWIRE*/ + + aeMB_edk32 + #(/*AUTOINSTPARAM*/ + // Parameters + .IW (IW), + .DW (DW), + .MUL (MUL), + .BSF (BSF)) + cpu + (/*AUTOINST*/ + // Outputs + .dwb_adr_o (dwb_adr_o[DW-1:2]), + .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[IW-1:2]), + .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)); + + // --- SIMULATION KERNEL ---------------------------------- + // synopsys translate_off + + 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 = {cpu.rBRA, cpu.rDLY}; + wire [3:0] wMSR = {cpu.xecu.rMSR_BIP, cpu.xecu.rMSR_C, cpu.xecu.rMSR_IE, cpu.xecu.rMSR_BE}; + + always @(posedge cpu.gclk) begin + if (cpu.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 (cpu.wBRA) + + case (cpu.rOPC) + 6'o00: if (cpu.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 (cpu.rIMM[1:0]) + 2'o0: $write("RSUBK"); + 2'o1: $write("CMP"); + 2'o3: $write("CMPU"); + default: $write("XXX"); + endcase // case (cpu.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 (cpu.rALT[10:9]) + 2'o0: $write("BSRL"); + 2'o1: $write("BSRA"); + 2'o2: $write("BSLL"); + default: $write("XXX"); + endcase // case (cpu.rALT[10:9]) + 6'o22: $write("IDIV"); + + 6'o30: $write("MULI"); + 6'o31: case (cpu.rALT[10:9]) + 2'o0: $write("BSRLI"); + 2'o1: $write("BSRAI"); + 2'o2: $write("BSLLI"); + default: $write("XXX"); + endcase // case (cpu.rALT[10:9]) + 6'o33: case (cpu.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 (cpu.rRB[4:2]) + + 6'o40: $write("OR"); + 6'o41: $write("AND"); + 6'o42: if (cpu.rRD == 0) $write(" "); else $write("XOR"); + 6'o43: $write("ANDN"); + 6'o44: case (cpu.rIMM[6:5]) + 2'o0: $write("SRA"); + 2'o1: $write("SRC"); + 2'o2: $write("SRL"); + 2'o3: if (cpu.rIMM[0]) $write("SEXT16"); else $write("SEXT8"); + endcase // case (cpu.rIMM[6:5]) + + 6'o45: $write("MOV"); + 6'o46: case (cpu.rRA[3:2]) + 3'o0: $write("BR"); + 3'o1: $write("BRL"); + 3'o2: $write("BRA"); + 3'o3: $write("BRAL"); + endcase // case (cpu.rRA[3:2]) + + 6'o47: case (cpu.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 (cpu.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 (cpu.rRD[1:0]) + 2'o0: $write("RTSD"); + 2'o1: $write("RTID"); + 2'o2: $write("RTBD"); + default: $write("XXX"); + endcase // case (cpu.rRD[1:0]) + 6'o56: case (cpu.rRA[3:2]) + 3'o0: $write("BRI"); + 3'o1: $write("BRLI"); + 3'o2: $write("BRAI"); + 3'o3: $write("BRALI"); + endcase // case (cpu.rRA[3:2]) + 6'o57: case (cpu.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 (cpu.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 (cpu.rOPC) + + case (cpu.rOPC[3]) + 1'b1: $writeh("\tr",cpu.rRD,", r",cpu.rRA,", h",cpu.rIMM); + 1'b0: $writeh("\tr",cpu.rRD,", r",cpu.rRA,", r",cpu.rRB," "); + endcase // case (cpu.rOPC[3]) + + + // ALU + $write("\t"); + $writeh(" A=",cpu.xecu.rOPA); + $writeh(" B=",cpu.xecu.rOPB); + + case (cpu.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 (cpu.rMXALU) + $writeh("=h",cpu.xecu.xRESULT); + + // WRITEBACK + $writeh("\tSR=", wMSR," "); + + if (cpu.regf.fRDWE) begin + case (cpu.rMXDST) + 2'o2: begin + if (dwb_stb_o) $writeh("R",cpu.rRW,"=RAM(h",cpu.regf.xWDAT,")"); + if (fsl_stb_o) $writeh("R",cpu.rRW,"=FSL(h",cpu.regf.xWDAT,")"); + end + 2'o1: $writeh("R",cpu.rRW,"=LNK(h",cpu.regf.xWDAT,")"); + 2'o0: $writeh("R",cpu.rRW,"=ALU(h",cpu.regf.xWDAT,")"); + endcase // case (cpu.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 (cpu.gena) + + end // always @ (posedge cpu.gclk) + + // synopsys translate_on + +endmodule // aeMB_sim + +/* + $Log: aeMB_sim.v,v $ + Revision 1.1 2007/12/23 20:40:45 sybreon + Abstracted simulation kernel (aeMB_sim) to split simulation models from synthesis models. + + */
\ No newline at end of file diff --git a/opencores/aemb/rtl/verilog/aeMB_xecu.v b/opencores/aemb/rtl/verilog/aeMB_xecu.v new file mode 100644 index 000000000..5de2ea619 --- /dev/null +++ b/opencores/aemb/rtl/verilog/aeMB_xecu.v @@ -0,0 +1,412 @@ +/* $Id: aeMB_xecu.v,v 1.12 2008/05/11 13:48:46 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/>. +*/ + +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, + rSTALL, 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 rSTALL; + 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 ---- + + reg rRES_ADDC; + reg [31:0] rRES_ADD; + + wire [31:0] wADD; + wire wADC; + + wire fCCC = !rOPC[5] & rOPC[1]; // & !rOPC[4] + wire fSUB = !rOPC[5] & rOPC[0]; // & !rOPC[4] + wire fCMP = !rOPC[3] & rIMM[1]; // unsigned only + wire wCMP = (fCMP) ? !wADC : wADD[31]; // cmpu adjust + + wire [31:0] wOPA = (fSUB) ? ~rOPA : rOPA; + wire wOPC = (fCCC) ? rMSR_C : fSUB; + + assign {wADC, wADD} = (rOPB + wOPA) + wOPC; // add carry + + always @(/*AUTOSENSE*/wADC or wADD or wCMP) begin + {rRES_ADDC, rRES_ADD} <= #1 {wADC, wCMP, wADD[30:0]}; // add with carry + end + + // --- 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, rRES_MUL0, xRES_MUL; + always @(/*AUTOSENSE*/rOPA or rOPB) begin + xRES_MUL <= (rOPA * rOPB); + end + + always @(posedge gclk) + if (grst) begin + /*AUTORESET*/ + // Beginning of autoreset for uninitialized flops + rRES_MUL <= 32'h0; + // End of automatics + end else if (rSTALL) begin + rRES_MUL <= #1 xRES_MUL; + 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]) + + reg [31:0] rBSRL, rBSRA, rBSLL; + + always @(posedge gclk) + if (grst) begin + /*AUTORESET*/ + // Beginning of autoreset for uninitialized flops + rBSLL <= 32'h0; + rBSRA <= 32'h0; + rBSRL <= 32'h0; + // End of automatics + end else if (rSTALL) begin + rBSRL <= #1 xBSRL; + rBSRA <= #1 xBSRA; + rBSLL <= #1 xBSLL; + end + + always @(/*AUTOSENSE*/rALT or rBSLL or rBSRA or rBSRL) + case (rALT[10:9]) + 2'd0: rRES_BSF <= rBSRL; + 2'd1: rRES_BSF <= rBSRA; + 2'd2: rRES_BSF <= rBSLL; + default: rRES_BSF <= 32'hX; + endcase // case (rALT[10:9]) + + + // --- MSR REGISTER ----------------- + + // C + wire fMTS = (rOPC == 6'o45) & rIMM[14] & !fSKIP; + 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 // case (rMXALU) + + // IE/BIP/BE + wire fRTID = (rOPC == 6'o55) & rRD[0] & !fSKIP; + wire fRTBD = (rOPC == 6'o55) & rRD[1] & !fSKIP; + 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 // if (grst) + 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 + +/* + $Log: aeMB_xecu.v,v $ + Revision 1.12 2008/05/11 13:48:46 sybreon + Backported Adder from AEMB2_EDK62. + Fixes 64-bit math problem reported by M. Ettus. + + Revision 1.11 2008/01/19 15:57:36 sybreon + Fix MTS during interrupt vectoring bug (reported by M. Ettus). + + Revision 1.10 2007/12/25 22:15:09 sybreon + Stalls pipeline on MUL/BSF instructions results in minor speed improvements. + + Revision 1.9 2007/11/30 16:42:51 sybreon + Minor code cleanup. + + 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. + +*/
\ No newline at end of file diff --git a/opencores/aemb/sim/CODE_DEBUG.sav b/opencores/aemb/sim/CODE_DEBUG.sav new file mode 100644 index 000000000..f777173c4 --- /dev/null +++ b/opencores/aemb/sim/CODE_DEBUG.sav @@ -0,0 +1,16 @@ +[size] 1400 971 +[pos] -1 -1 +*-5.188574 2727 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +@28 +testbench.dut.dwb_we_o +@22 +testbench.dut.dwb_sel_o[3:0] +testbench.dut.dwb_adr_o[15:0] +@28 +testbench.dut.sys_clk_i +@22 +testbench.dut.dwb_dat_o[31:0] +@821 +testbench.dut.dwb_dat_i[31:0] +@22 +testbench.dut.dwb_dat_i[31:0] diff --git a/opencores/aemb/sim/CVS/Entries b/opencores/aemb/sim/CVS/Entries new file mode 100644 index 000000000..bf457ae67 --- /dev/null +++ b/opencores/aemb/sim/CVS/Entries @@ -0,0 +1,3 @@ +D/verilog//// +/cversim/1.5/Tue Jan 15 18:38:57 2008// +/iversim/1.5/Tue Jan 15 18:38:57 2008// diff --git a/opencores/aemb/sim/CVS/Repository b/opencores/aemb/sim/CVS/Repository new file mode 100644 index 000000000..c6bd1aa80 --- /dev/null +++ b/opencores/aemb/sim/CVS/Repository @@ -0,0 +1 @@ +aemb/sim diff --git a/opencores/aemb/sim/CVS/Root b/opencores/aemb/sim/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/aemb/sim/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/aemb/sim/CVS/Template b/opencores/aemb/sim/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/aemb/sim/CVS/Template diff --git a/opencores/aemb/sim/cversim b/opencores/aemb/sim/cversim new file mode 100755 index 000000000..0dbb7aea1 --- /dev/null +++ b/opencores/aemb/sim/cversim @@ -0,0 +1,22 @@ +#!/bin/sh +# $Id: cversim,v 1.5 2007/12/11 00:44:30 sybreon Exp $ +# $Log: cversim,v $ +# Revision 1.5 2007/12/11 00:44:30 sybreon +# Modified for AEMB2 +# +# Revision 1.4 2007/11/30 17:08:30 sybreon +# Moved simulation kernel into code. +# +# Revision 1.3 2007/11/05 10:59:31 sybreon +# Added random seed for simulation. +# +# Revision 1.2 2007/04/12 20:21:33 sybreon +# Moved testbench into /sim/verilog. +# Simulation cleanups. +# +# Revision 1.1 2007/03/09 17:41:55 sybreon +# initial import +# +RANDOM=$(date +%s) +echo "parameter randseed = $RANDOM;" > random.v +cver -q -w +define+AEMBX_SIMULATION_KERNEL $@ ../rtl/verilog/*.v diff --git a/opencores/aemb/sim/iversim b/opencores/aemb/sim/iversim new file mode 100755 index 000000000..9d2384b5a --- /dev/null +++ b/opencores/aemb/sim/iversim @@ -0,0 +1,21 @@ +#!/bin/sh +# $Id: iversim,v 1.5 2007/12/11 00:44:30 sybreon Exp $ +# $Log: iversim,v $ +# Revision 1.5 2007/12/11 00:44:30 sybreon +# Modified for AEMB2 +# +# Revision 1.4 2007/11/30 17:08:30 sybreon +# Moved simulation kernel into code. +# +# Revision 1.3 2007/11/09 20:50:51 sybreon +# Added log output to iverilog.log +# +# Revision 1.2 2007/11/05 10:59:31 sybreon +# Added random seed for simulation. +# +# Revision 1.1 2007/03/09 17:41:55 sybreon +# initial import +# +RANDOM=$(date +%s) +echo "parameter randseed = $RANDOM;" > random.v +iverilog $@ -DAEMBX_SIMULATION_KERNEL ../rtl/verilog/*.v && vvp -l iverilog.log a.out && rm a.out diff --git a/opencores/aemb/sim/verilog/CVS/Entries b/opencores/aemb/sim/verilog/CVS/Entries new file mode 100644 index 000000000..34e896e80 --- /dev/null +++ b/opencores/aemb/sim/verilog/CVS/Entries @@ -0,0 +1,3 @@ +/aemb2.v/1.3/Tue Jan 15 18:38:57 2008// +/edk32.v/1.12/Tue Jan 15 18:38:57 2008// +D diff --git a/opencores/aemb/sim/verilog/CVS/Repository b/opencores/aemb/sim/verilog/CVS/Repository new file mode 100644 index 000000000..ff3eabf2d --- /dev/null +++ b/opencores/aemb/sim/verilog/CVS/Repository @@ -0,0 +1 @@ +aemb/sim/verilog diff --git a/opencores/aemb/sim/verilog/CVS/Root b/opencores/aemb/sim/verilog/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/aemb/sim/verilog/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/aemb/sim/verilog/CVS/Template b/opencores/aemb/sim/verilog/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/aemb/sim/verilog/CVS/Template diff --git a/opencores/aemb/sim/verilog/aemb2.v b/opencores/aemb/sim/verilog/aemb2.v new file mode 100644 index 000000000..bda1704e3 --- /dev/null +++ b/opencores/aemb/sim/verilog/aemb2.v @@ -0,0 +1,242 @@ +/* $Id: aemb2.v,v 1.3 2007/12/28 21:44:50 sybreon Exp $ +** +** AEMB2 TEST BENCH +** 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 (); + parameter IWB=16; + parameter DWB=16; + + parameter TXE = 0; ///< thread execution enable + + parameter MUL = 1; ///< enable hardware multiplier + parameter BSF = 1; ///< enable barrel shifter + parameter FSL = 1; ///< enable FSL bus + parameter DIV = 0; ///< enable hardware divider + +`include "random.v" + + /*AUTOWIRE*/ + // Beginning of automatic wires (for undeclared instantiated-module outputs) + wire [6:2] cwb_adr_o; // From dut of aeMB2_sim.v + wire [31:0] cwb_dat_o; // From dut of aeMB2_sim.v + wire [3:0] cwb_sel_o; // From dut of aeMB2_sim.v + wire cwb_stb_o; // From dut of aeMB2_sim.v + wire [1:0] cwb_tga_o; // From dut of aeMB2_sim.v + wire cwb_wre_o; // From dut of aeMB2_sim.v + wire [DWB-1:2] dwb_adr_o; // From dut of aeMB2_sim.v + wire dwb_cyc_o; // From dut of aeMB2_sim.v + wire [31:0] dwb_dat_o; // From dut of aeMB2_sim.v + wire [3:0] dwb_sel_o; // From dut of aeMB2_sim.v + wire dwb_stb_o; // From dut of aeMB2_sim.v + wire dwb_tga_o; // From dut of aeMB2_sim.v + wire dwb_wre_o; // From dut of aeMB2_sim.v + wire [IWB-1:2] iwb_adr_o; // From dut of aeMB2_sim.v + wire iwb_stb_o; // From dut of aeMB2_sim.v + wire iwb_tga_o; // From dut of aeMB2_sim.v + wire iwb_wre_o; // From dut of aeMB2_sim.v + // End of automatics + /*AUTOREGINPUT*/ + // Beginning of automatic reg inputs (for undeclared instantiated-module inputs) + reg cwb_ack_i; // To dut of aeMB2_sim.v + reg dwb_ack_i; // To dut of aeMB2_sim.v + reg iwb_ack_i; // To dut of aeMB2_sim.v + reg sys_clk_i; // To dut of aeMB2_sim.v + reg sys_int_i; // To dut of aeMB2_sim.v + reg sys_rst_i; // To dut of aeMB2_sim.v + // End of automatics + + // INITIAL SETUP ////////////////////////////////////////////////////// + + //reg sys_clk_i, sys_rst_i, sys_int_i, sys_exc_i; + reg svc; + integer inttime; + integer seed; + integer theend; + + always #5 sys_clk_i = ~sys_clk_i; + + initial begin + //$dumpfile("dump.vcd"); + //$dumpvars(1,dut, dut.bpcu); + end + + initial begin + seed = randseed; + theend = 0; + svc = 0; + sys_clk_i = $random(seed); + sys_rst_i = 1; + sys_int_i = 0; + #50 sys_rst_i = 0; + #3500000 $finish; + end + + // FAKE MEMORY //////////////////////////////////////////////////////// + + reg [31:0] rom [0:65535]; + reg [31:0] ram[0:65535]; + reg [31:0] dwblat; + reg [15:2] dadr, iadr; + + wire [31:0] dwb_dat_t = ram[dwb_adr_o]; + wire [31:0] iwb_dat_i = rom[iadr]; + wire [31:0] dwb_dat_i = ram[dadr]; + wire [31:0] cwb_dat_i = cwb_adr_o; + +`ifdef POSEDGE +`else // !`ifdef POSEDGE + + always @(negedge sys_clk_i) + if (sys_rst_i) begin + /*AUTORESET*/ + // Beginning of autoreset for uninitialized flops + cwb_ack_i <= 1'h0; + dwb_ack_i <= 1'h0; + iwb_ack_i <= 1'h0; + // End of automatics + end else begin + iwb_ack_i <= #1 iwb_stb_o; + dwb_ack_i <= #1 dwb_stb_o; + cwb_ack_i <= #1 cwb_stb_o; + end // else: !if(sys_rst_i) + + always @(negedge sys_clk_i) begin + iadr <= #1 iwb_adr_o; + dadr <= #1 dwb_adr_o; + + if (dwb_wre_o & dwb_stb_o) begin + case (dwb_sel_o) + 4'h1: ram[dwb_adr_o] <= {dwb_dat_t[31:8], dwb_dat_o[7:0]}; + 4'h2: ram[dwb_adr_o] <= {dwb_dat_t[31:16], dwb_dat_o[15:8], dwb_dat_t[7:0]}; + 4'h4: ram[dwb_adr_o] <= {dwb_dat_t[31:24], dwb_dat_o[23:16], dwb_dat_t[15:0]}; + 4'h8: ram[dwb_adr_o] <= {dwb_dat_o[31:24], dwb_dat_t[23:0]}; + 4'h3: ram[dwb_adr_o] <= {dwb_dat_t[31:16], dwb_dat_o[15:0]}; + 4'hC: ram[dwb_adr_o] <= {dwb_dat_o[31:16], dwb_dat_t[15:0]}; + 4'hF: ram[dwb_adr_o] <= {dwb_dat_o}; + endcase // case (dwb_sel_o) + end // if (dwb_we_o & dwb_stb_o) + end // always @ (negedge sys_clk_i) + +`endif // !`ifdef POSEDGE + + + integer i; + initial begin + for (i=0;i<65535;i=i+1) begin + ram[i] <= $random; + end + #1 $readmemh("dump.vmem",rom); + #1 $readmemh("dump.vmem",ram); + end + + // DISPLAY OUTPUTS /////////////////////////////////////////////////// + + integer rnd; + + always @(posedge sys_clk_i) begin + + // Interrupt Monitors + if (!dut.sim.rMSR_IE) begin + rnd = $random % 30; + inttime = $stime + 1000 + (rnd*rnd * 10); + end + if ($stime > inttime) begin + sys_int_i = 1; + svc = 0; + end + if (($stime > inttime + 500) && !svc) begin + $display("\n\t*** INTERRUPT TIMEOUT ***", inttime); + $finish; + end + if (dwb_wre_o & (dwb_dat_o == "RTNI")) sys_int_i = 0; + /* + if (dut.regf.fRDWE && (dut.rRD == 5'h0e) && !svc && dut.gena) begin + svc = 1; + //$display("\nLATENCY: ", ($stime - inttime)/10); + end + */ + + // Pass/Fail Monitors + if (dwb_wre_o & (dwb_dat_o == "FAIL")) begin + $display("\n\tFAIL"); + $finish; + end + + if (iwb_dat_i == 32'hb8000000) begin + theend = theend + 1; + end + + if (theend == 5) begin + $display("\n\t*** PASSED ALL TESTS ***"); + $finish; + end + + end // always @ (posedge sys_clk_i) + + // INTERNAL WIRING //////////////////////////////////////////////////// + + aeMB2_sim + #(/*AUTOINSTPARAM*/ + // Parameters + .IWB (IWB), + .DWB (DWB), + .TXE (TXE), + .MUL (MUL), + .BSF (BSF), + .FSL (FSL), + .DIV (DIV)) + dut (/*AUTOINST*/ + // Outputs + .cwb_adr_o (cwb_adr_o[6:2]), + .cwb_dat_o (cwb_dat_o[31:0]), + .cwb_sel_o (cwb_sel_o[3:0]), + .cwb_stb_o (cwb_stb_o), + .cwb_tga_o (cwb_tga_o[1:0]), + .cwb_wre_o (cwb_wre_o), + .dwb_adr_o (dwb_adr_o[DWB-1:2]), + .dwb_cyc_o (dwb_cyc_o), + .dwb_dat_o (dwb_dat_o[31:0]), + .dwb_sel_o (dwb_sel_o[3:0]), + .dwb_stb_o (dwb_stb_o), + .dwb_tga_o (dwb_tga_o), + .dwb_wre_o (dwb_wre_o), + .iwb_adr_o (iwb_adr_o[IWB-1:2]), + .iwb_stb_o (iwb_stb_o), + .iwb_tga_o (iwb_tga_o), + .iwb_wre_o (iwb_wre_o), + // Inputs + .cwb_ack_i (cwb_ack_i), + .cwb_dat_i (cwb_dat_i[31:0]), + .dwb_ack_i (dwb_ack_i), + .dwb_dat_i (dwb_dat_i[31:0]), + .iwb_ack_i (iwb_ack_i), + .iwb_dat_i (iwb_dat_i[31:0]), + .sys_clk_i (sys_clk_i), + .sys_int_i (sys_int_i), + .sys_rst_i (sys_rst_i)); + +endmodule // edk32 + +/* $Log $ */ + +// Local Variables: +// verilog-library-directories:("." "../../rtl/verilog/") +// verilog-library-files:("") +// End: diff --git a/opencores/aemb/sim/verilog/edk32.v b/opencores/aemb/sim/verilog/edk32.v new file mode 100644 index 000000000..68465e9e0 --- /dev/null +++ b/opencores/aemb/sim/verilog/edk32.v @@ -0,0 +1,288 @@ +/* $Id: edk32.v,v 1.12 2007/12/23 20:40:51 sybreon Exp $ +** +** AEMB EDK 3.2 Compatible Core TEST +** 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/>. +*/ + +`define AEMB_SIMULATION_KERNEL + +module edk32 (); + +`include "random.v" + + // INITIAL SETUP ////////////////////////////////////////////////////// + + reg sys_clk_i, sys_rst_i, sys_int_i, sys_exc_i; + reg svc; + integer inttime; + integer seed; + integer theend; + + always #5 sys_clk_i = ~sys_clk_i; + + initial begin + //$dumpfile("dump.vcd"); + //$dumpvars(1,dut); + end + + initial begin + seed = randseed; + theend = 0; + svc = 0; + sys_clk_i = $random(seed); + sys_rst_i = 1; + sys_int_i = 0; + sys_exc_i = 0; + #50 sys_rst_i = 0; + end + + initial fork + //inttime $display("FSADFASDFSDAF"); + //#10000 sys_int_i = 1; + //#1100 sys_int_i = 0; + //#100000 $displayh("\nTest Completed."); + //#4000 $finish; + join + + + // FAKE MEMORY //////////////////////////////////////////////////////// + + wire fsl_stb_o; + wire fsl_wre_o; + wire [31:0] fsl_dat_o; + wire [31:0] fsl_dat_i; + wire [6:2] fsl_adr_o; + + wire [15:2] iwb_adr_o; + wire iwb_stb_o; + wire dwb_stb_o; + reg [31:0] rom [0:65535]; + wire [31:0] iwb_dat_i; + reg iwb_ack_i, dwb_ack_i, fsl_ack_i; + + reg [31:0] ram[0:65535]; + wire [31:0] dwb_dat_i; + reg [31:0] dwblat; + wire dwb_we_o; + reg [15:2] dadr,iadr; + wire [3:0] dwb_sel_o; + wire [31:0] dwb_dat_o; + wire [15:2] dwb_adr_o; + wire [31:0] dwb_dat_t; + + initial begin + dwb_ack_i = 0; + iwb_ack_i = 0; + fsl_ack_i = 0; + end + + assign dwb_dat_t = ram[dwb_adr_o]; + assign iwb_dat_i = ram[iadr]; + assign dwb_dat_i = ram[dadr]; + assign fsl_dat_i = fsl_adr_o; + +`ifdef POSEDGE + + always @(posedge sys_clk_i) + if (sys_rst_i) begin + /*AUTORESET*/ + // Beginning of autoreset for uninitialized flops + dwb_ack_i <= 1'h0; + fsl_ack_i <= 1'h0; + iwb_ack_i <= 1'h0; + // End of automatics + end else begin + iwb_ack_i <= #1 iwb_stb_o ^ iwb_ack_i; + dwb_ack_i <= #1 dwb_stb_o ^ dwb_ack_i; + fsl_ack_i <= #1 fsl_stb_o ^ fsl_ack_i; + end // else: !if(sys_rst_i) + + always @(posedge sys_clk_i) begin + iadr <= #1 iwb_adr_o; + dadr <= #1 dwb_adr_o; + + if (dwb_we_o & dwb_stb_o) begin + case (dwb_sel_o) + 4'h1: ram[dwb_adr_o] <= {dwb_dat_t[31:8], dwb_dat_o[7:0]}; + 4'h2: ram[dwb_adr_o] <= {dwb_dat_t[31:16], dwb_dat_o[15:8], dwb_dat_t[7:0]}; + 4'h4: ram[dwb_adr_o] <= {dwb_dat_t[31:24], dwb_dat_o[23:16], dwb_dat_t[15:0]}; + 4'h8: ram[dwb_adr_o] <= {dwb_dat_o[31:24], dwb_dat_t[23:0]}; + 4'h3: ram[dwb_adr_o] <= {dwb_dat_t[31:16], dwb_dat_o[15:0]}; + 4'hC: ram[dwb_adr_o] <= {dwb_dat_o[31:16], dwb_dat_t[15:0]}; + 4'hF: ram[dwb_adr_o] <= {dwb_dat_o}; + endcase // case (dwb_sel_o) + end // if (dwb_we_o & dwb_stb_o) + end // always @ (posedge sys_clk_i) + +`else // !`ifdef POSEDGE + + always @(negedge sys_clk_i) + if (sys_rst_i) begin + /*AUTORESET*/ + // Beginning of autoreset for uninitialized flops + dwb_ack_i <= 1'h0; + fsl_ack_i <= 1'h0; + iwb_ack_i <= 1'h0; + // End of automatics + end else begin + iwb_ack_i <= #1 iwb_stb_o; + dwb_ack_i <= #1 dwb_stb_o; + fsl_ack_i <= #1 fsl_stb_o; + end // else: !if(sys_rst_i) + + always @(negedge sys_clk_i) begin + iadr <= #1 iwb_adr_o; + dadr <= #1 dwb_adr_o; + + if (dwb_we_o & dwb_stb_o) begin + case (dwb_sel_o) + 4'h1: ram[dwb_adr_o] <= {dwb_dat_t[31:8], dwb_dat_o[7:0]}; + 4'h2: ram[dwb_adr_o] <= {dwb_dat_t[31:16], dwb_dat_o[15:8], dwb_dat_t[7:0]}; + 4'h4: ram[dwb_adr_o] <= {dwb_dat_t[31:24], dwb_dat_o[23:16], dwb_dat_t[15:0]}; + 4'h8: ram[dwb_adr_o] <= {dwb_dat_o[31:24], dwb_dat_t[23:0]}; + 4'h3: ram[dwb_adr_o] <= {dwb_dat_t[31:16], dwb_dat_o[15:0]}; + 4'hC: ram[dwb_adr_o] <= {dwb_dat_o[31:16], dwb_dat_t[15:0]}; + 4'hF: ram[dwb_adr_o] <= {dwb_dat_o}; + endcase // case (dwb_sel_o) + end // if (dwb_we_o & dwb_stb_o) + end // always @ (negedge sys_clk_i) + +`endif // !`ifdef POSEDGE + + + integer i; + initial begin + for (i=0;i<65535;i=i+1) begin + ram[i] <= $random; + end + #1 $readmemh("dump.vmem",ram); + end + + // DISPLAY OUTPUTS /////////////////////////////////////////////////// + + integer rnd; + + always @(posedge sys_clk_i) begin + + // Interrupt Monitors + if (!dut.cpu.rMSR_IE) begin + rnd = $random % 30; + inttime = $stime + 1000 + (rnd*rnd * 10); + end + if ($stime > inttime) begin + sys_int_i = 1; + svc = 0; + end + if (($stime > inttime + 500) && !svc) begin + $display("\n\t*** INTERRUPT TIMEOUT ***", inttime); + $finish; + end + if (dwb_we_o & (dwb_dat_o == "RTNI")) sys_int_i = 0; + if (dut.cpu.regf.fRDWE && (dut.cpu.rRD == 5'h0e) && !svc && dut.cpu.gena) begin + svc = 1; + //$display("\nLATENCY: ", ($stime - inttime)/10); + end + + // Pass/Fail Monitors + if (dwb_we_o & (dwb_dat_o == "FAIL")) begin + $display("\n\tFAIL"); + $finish; + end + + if (iwb_dat_i == 32'hb8000000) begin + theend = theend + 1; + end + + if (theend == 5) begin + $display("\n\t*** PASSED ALL TESTS ***"); + $finish; + end + end // always @ (posedge sys_clk_i) + + // INTERNAL WIRING //////////////////////////////////////////////////// + + aeMB_sim #(16,16) + dut ( + .sys_int_i(sys_int_i), + .dwb_ack_i(dwb_ack_i), + .dwb_stb_o(dwb_stb_o), + .dwb_adr_o(dwb_adr_o), + .dwb_dat_o(dwb_dat_o), + .dwb_dat_i(dwb_dat_i), + .dwb_wre_o(dwb_we_o), + .dwb_sel_o(dwb_sel_o), + + .fsl_ack_i(fsl_ack_i), + .fsl_stb_o(fsl_stb_o), + .fsl_adr_o(fsl_adr_o), + .fsl_dat_o(fsl_dat_o), + .fsl_dat_i(fsl_dat_i), + .fsl_wre_o(fsl_we_o), + + .iwb_adr_o(iwb_adr_o), + .iwb_dat_i(iwb_dat_i), + .iwb_stb_o(iwb_stb_o), + .iwb_ack_i(iwb_ack_i), + .sys_clk_i(sys_clk_i), + .sys_rst_i(sys_rst_i) + ); + +endmodule // edk32 + +/* + $Log: edk32.v,v $ + Revision 1.12 2007/12/23 20:40:51 sybreon + Abstracted simulation kernel (aeMB_sim) to split simulation models from synthesis models. + + Revision 1.11 2007/12/11 00:44:31 sybreon + Modified for AEMB2 + + Revision 1.10 2007/11/30 17:08:30 sybreon + Moved simulation kernel into code. + + Revision 1.9 2007/11/20 18:36:00 sybreon + Removed unnecessary byte acrobatics with VMEM data. + + Revision 1.8 2007/11/18 19:41:45 sybreon + Minor simulation fixes. + + Revision 1.7 2007/11/14 22:11:41 sybreon + Added posedge/negedge bus interface. + Modified interrupt test system. + + Revision 1.6 2007/11/13 23:37:28 sybreon + Updated simulation to also check BRI 0x00 instruction. + + Revision 1.5 2007/11/09 20:51:53 sybreon + Added GET/PUT support through a FSL bus. + + Revision 1.4 2007/11/08 14:18:00 sybreon + Parameterised optional components. + + Revision 1.3 2007/11/05 10:59:31 sybreon + Added random seed for simulation. + + Revision 1.2 2007/11/02 19:16:10 sybreon + Added interrupt simulation. + Changed "human readable" simulation output. + + Revision 1.1 2007/11/02 03:25:45 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. + */
\ No newline at end of file diff --git a/opencores/aemb/sw/CVS/Entries b/opencores/aemb/sw/CVS/Entries new file mode 100644 index 000000000..45725bed9 --- /dev/null +++ b/opencores/aemb/sw/CVS/Entries @@ -0,0 +1,2 @@ +D/c//// +/gccrom/1.13/Sun Jan 20 19:47:57 2008// diff --git a/opencores/aemb/sw/CVS/Repository b/opencores/aemb/sw/CVS/Repository new file mode 100644 index 000000000..6de31b8b0 --- /dev/null +++ b/opencores/aemb/sw/CVS/Repository @@ -0,0 +1 @@ +aemb/sw diff --git a/opencores/aemb/sw/CVS/Root b/opencores/aemb/sw/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/aemb/sw/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/aemb/sw/CVS/Template b/opencores/aemb/sw/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/aemb/sw/CVS/Template diff --git a/opencores/aemb/sw/c/CVS/Entries b/opencores/aemb/sw/c/CVS/Entries new file mode 100644 index 000000000..4867b6318 --- /dev/null +++ b/opencores/aemb/sw/c/CVS/Entries @@ -0,0 +1,3 @@ +/aeMB_testbench.c/1.14/Tue Jan 15 18:38:57 2008// +/libaemb.h/1.3/Tue Jan 15 18:38:57 2008// +D diff --git a/opencores/aemb/sw/c/CVS/Repository b/opencores/aemb/sw/c/CVS/Repository new file mode 100644 index 000000000..86c411d03 --- /dev/null +++ b/opencores/aemb/sw/c/CVS/Repository @@ -0,0 +1 @@ +aemb/sw/c diff --git a/opencores/aemb/sw/c/CVS/Root b/opencores/aemb/sw/c/CVS/Root new file mode 100644 index 000000000..44b2aa23b --- /dev/null +++ b/opencores/aemb/sw/c/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous diff --git a/opencores/aemb/sw/c/CVS/Template b/opencores/aemb/sw/c/CVS/Template new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/opencores/aemb/sw/c/CVS/Template diff --git a/opencores/aemb/sw/c/aeMB_testbench.c b/opencores/aemb/sw/c/aeMB_testbench.c new file mode 100644 index 000000000..c3402e0ef --- /dev/null +++ b/opencores/aemb/sw/c/aeMB_testbench.c @@ -0,0 +1,385 @@ +/* $Id: aeMB_testbench.c,v 1.14 2007/12/28 21:44:04 sybreon Exp $ +** +** AEMB Function Verification C Testbench +** 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 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 General Public +** License for more details. +** +** You should have received a copy of the GNU General Public License +** along with AEMB. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <malloc.h> +#include <errno.h> +#include <reent.h> + +#include "libaemb.h" + +/** + INTERRUPT TEST + + This tests for the following: + - Pointer addressing + - Interrupt handling + */ + +void __attribute__ ((interrupt_handler)) int_handler(); +volatile int service = 0xDEADDEAD; + +void int_service() +{ + int* pio = (int*)0xFFFFFFFC; + *pio = 0x52544E49; // "INTR" + service = 0; +} + +void int_handler() +{ + int_service(); +} + +/** + INTERRUPT TEST ROUTINE +*/ +int int_test () +{ + // Delay loop until hardware interrupt triggers + volatile int i; + for (i=0; i < 999; i++) { + if (service == 0) return 0; + }; + + return -1; +} + +/** + FIBONACCI TEST + http://en.literateprograms.org/Fibonacci_numbers_(C) + + This tests for the following: + - Recursion & Iteration + - 32/16/8-bit data handling +*/ + +unsigned int fib_slow(unsigned int n) +{ + return n < 2 ? n : fib_slow(n-1) + fib_slow(n-2); +} + +unsigned int fib_fast(unsigned int n) +{ + unsigned int a[3]; + unsigned int *p=a; + unsigned int i; + + for(i=0; i<=n; ++i) { + if(i<2) *p=i; + else { + if(p==a) *p=*(a+1)+*(a+2); + else if(p==a+1) *p=*a+*(a+2); + else *p=*a+*(a+1); + } + if(++p>a+2) p=a; + } + + return p==a?*(p+2):*(p-1); +} + +int fib_test(int max) { + unsigned int n; + unsigned int fast, slow; + // 32-bit LUT + unsigned int fib_lut32[] = { + 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233 + }; + // 16-bit LUT + unsigned short fib_lut16[] = { + 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233 + }; + // 8-bit LUT + unsigned char fib_lut8[] = { + 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233 + }; + + for (n=0;n<max;n++) { + slow = fib_slow(n); + fast = fib_fast(n); + if ((slow != fast) || + (fast != fib_lut32[n]) || + (fast != fib_lut16[n]) || + (fast != fib_lut8[n])) { + return -1; + } + } + return 0; +} + +/** + EUCLIDEAN TEST + http://en.literateprograms.org/Euclidean_algorithm_(C) + + This tests for the following: + - Modulo arithmetic + - Goto +*/ + +int euclid_gcd(int a, int b) { + if (b > a) goto b_larger; + while (1) { + a = a % b; + if (a == 0) return b; + b_larger: + b = b % a; + if (b == 0) return a; + } +} + +int euclid_test(int max) +{ + int n; + int euclid; + // Random Numbers + int euclid_a[] = { + 1804289383, 1681692777, 1957747793, 719885386, 596516649, + 1025202362, 783368690, 2044897763, 1365180540, 304089172, + 35005211, 294702567, 336465782, 278722862 + }; + int euclid_b[] = { + 846930886, 1714636915, 424238335, 1649760492, 1189641421, + 1350490027, 1102520059, 1967513926, 1540383426, 1303455736, + 521595368, 1726956429, 861021530, 233665123 + }; + + // GCD + int euclid_lut[] = { + 1, 1, 1, 2, 1, 1, 1, 1, 6, 4, 1, 3, 2, 1 + }; + + for (n=0;n<max;n++) { + euclid = euclid_gcd(euclid_a[n],euclid_b[n]); + if (euclid != euclid_lut[n]) { + return -1; + } + } + return 0; +} + +/** + NEWTON-RHAPSON + http://en.literateprograms.org/Newton-Raphson's_method_for_root_finding_(C) + + This tests for the following: + - Multiplication & Division + - Floating point arithmetic + - Integer to Float conversion +*/ + +float newton_sqrt(float n) +{ + float x = 0.0; + float xn = 0.0; + int iters = 0; + int i; + for (i = 0; i <= (int)n; ++i) + { + float val = i*i-n; + if (val == 0.0) + return i; + if (val > 0.0) + { + xn = (i+(i-1))/2.0; + break; + } + } + while (!(iters++ >= 100 + || x == xn)) + { + x = xn; + xn = x - (x * x - n) / (2 * x); + } + return xn; +} + +int newton_test (int max) { + int n; + float newt; + // 32-bit LUT + float newt_lut[] = { + 0.000000000000000000000000, + 1.000000000000000000000000, + 1.414213538169860839843750, + 1.732050776481628417968750, + 2.000000000000000000000000, + 2.236068010330200195312500, + 2.449489831924438476562500, + 2.645751237869262695312500, + 2.828427076339721679687500, + 3.000000000000000000000000, + 3.162277698516845703125000, + 3.316624879837036132812500, + 3.464101552963256835937500, + 3.605551242828369140625000, + 3.741657495498657226562500 + }; + + for (n=0;n<max;n++) { + newt = newton_sqrt(n); + if (newt != newt_lut[n]) { + return -1; + } + } + return 0; +} + + +/** + FSL TEST ROUTINE +*/ + +int fsl_test () +{ + // TEST FSL1 ONLY + int FSL = 0xCAFEF00D; + + asm ("PUT %0, RFSL1" :: "r"(FSL)); + asm ("GET %0, RFSL1" : "=r"(FSL)); + + if (FSL != 0x01) return -1; + + asm ("PUT %0, RFSL31" :: "r"(FSL)); + asm ("GET %0, RFSL31" : "=r"(FSL)); + + if (FSL != 0x1F) return -1; + + return 0; +} + +// static int errnum; +/* +int *__errno () +{ + return &_REENT->_errno; + // return &errnum; +} +*/ + +int malloc_test() +{ + void *alloc; + + alloc = (void *)malloc(256); // allocate 32 bytes + + if (alloc == NULL) + return -1; + else + return (int) alloc; +} + +/** + MAIN TEST PROGRAMME + + This is the main test procedure. It will output signals onto the + MPI port that is checked by the testbench. + */ + +int main () +{ + // Message Passing Port + int* mpi = (int*)0xFFFFFFFF; + + // Number of each test to run + int max = 10; + + // lock T0 if it's multi-threaded + /* + if ((aemb_isthreaded() == 0) && (aemb_isthread1() != 0)) { + while (1) { + asm volatile ("nop;"); + } + } + */ + + // Enable Global Interrupts + aemb_enable_interrupt(); + + // INT TEST + //if (int_test() == -1) { *mpi = 0x4641494C; } + + // TEST MALLOC + if (malloc_test() == -1) { *mpi = 0x4641494C; } + + // FSL TEST + //if (fsl_test() == -1) { *mpi = 0x4641494C; } + + // Fibonacci Test + if (fib_test(max) == -1) { *mpi = 0x4641494C; } + + // Euclid Test + if (euclid_test(max) == -1) { *mpi = 0x4641494C; } + + // Newton-Rhapson Test + if (newton_test(max) == -1) { *mpi = 0x4641494C; } + + // Disable Global Interrupts + aemb_disable_interrupt(); + + // ALL PASSED + return 0; +} + +/* + HISTORY + $Log: aeMB_testbench.c,v $ + Revision 1.14 2007/12/28 21:44:04 sybreon + Added malloc() test + + Revision 1.13 2007/12/11 00:44:31 sybreon + Modified for AEMB2 + + Revision 1.12 2007/11/18 19:41:45 sybreon + Minor simulation fixes. + + Revision 1.11 2007/11/14 23:41:06 sybreon + Fixed minor interrupt test typo. + + Revision 1.10 2007/11/14 22:12:02 sybreon + Added interrupt test routine. + + Revision 1.9 2007/11/09 20:51:53 sybreon + Added GET/PUT support through a FSL bus. + + Revision 1.8 2007/11/03 08:40:18 sybreon + Minor code cleanup. + + Revision 1.7 2007/11/02 18:32:19 sybreon + Enable MSR_IE with software. + + Revision 1.6 2007/04/30 15:57:10 sybreon + Removed byte acrobatics. + + Revision 1.5 2007/04/27 15:17:59 sybreon + Added code documentation. + Added new tests that test floating point, modulo arithmetic and multiplication/division. + + Revision 1.4 2007/04/25 22:15:05 sybreon + Added support for 8-bit and 16-bit data types. + + Revision 1.3 2007/04/04 14:09:04 sybreon + Added initial interrupt/exception support. + + Revision 1.2 2007/04/04 06:07:45 sybreon + Fixed C code bug which passes the test + + Revision 1.1 2007/03/09 17:41:57 sybreon + initial import +*/ diff --git a/opencores/aemb/sw/c/endian-test.c b/opencores/aemb/sw/c/endian-test.c new file mode 100644 index 000000000..b585f7a30 --- /dev/null +++ b/opencores/aemb/sw/c/endian-test.c @@ -0,0 +1,86 @@ + +#include "memory_map.h" + +int main() { + char *p = (char *)0x4000; + short *q = (short *)0x5000; + int *r= (int *)0x6000; + + int *output = (int *)0x7000; + + char s; + short t; + int u; + + // Write + // Bytes + *p = (char)1; + p++; + *p = (char)2; + p++; + *p = (char)3; + p++; + *p = (char)4; + p++; + *p = (char)5; + + // Words + *q = (short) 0x1112; + q++; + *q = (short) 0x1314; + q++; + *q = (short) 0x1516; + + // Double Words + *r = 0x21222324; + r++; + *r = 0x25262728; + r++; + *r = 0x292a2b2c; + + + // Read + p = (char *)0x6000; + s = *p; + if(s == 0x21) + *output = 0x53534150; // PASS + else + *output = 0x4C494146; // FAIL + + p = (char *)0x6001; + s = *p; + if(s == 0x22) + *output = 0x53534150; // PASS + else + *output = 0x4C494146; // FAIL + + p = (char *)0x6002; + s = *p; + if(s == 0x23) + *output = 0x53534150; // PASS + else + *output = 0x4C494146; // FAIL + + + p = (char *)0x6003; + s = *p; + if(s == 0x24) + *output = 0x53534150; // PASS + else + *output = 0x4C494146; // FAIL + + q = (short *)0x4000; + t = *q; + if(t == 0x0102) + *output = 0x53534150; // PASS + else + *output = 0x4C494146; // FAIL + + r = (int *)0x4000; + u = *r; + if(u == 0x01020304) + *output = 0x53534150; // PASS + else + *output = 0x4C494146; // FAIL + +} diff --git a/opencores/aemb/sw/c/libaemb.h b/opencores/aemb/sw/c/libaemb.h new file mode 100644 index 000000000..329a327a1 --- /dev/null +++ b/opencores/aemb/sw/c/libaemb.h @@ -0,0 +1,218 @@ +/* $Id: libaemb.h,v 1.3 2007/12/16 03:26:37 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 0x0100 +#define AEMB_TXP 0x0400 +#define AEMB_TX0 0x0300 +#define AEMB_TX1 0x0700 +#define AEMB_MSK 0x0F00 + +#define AEMB_BIP 0x0008 +#define AEMB_CCC 0x0004 +#define AEMB_ITE 0x0002 +#define AEMB_BLE 0x0001 + + +// Linker symbols +extern void* _STACK_SIZE; +extern void* _stack_end; + + +void aemb_hook_init () asm ("_program_init"); +void aemb_hook_clean () asm ("_program_clean"); + +inline void aemb_enable_interrupt (); +inline void aemb_disable_interrupt (); +inline int aemb_isthread1(); +inline int aemb_isthread0(); +inline int aemb_isthreaded(); + +/*! +* 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 +*/ + +void aemb_hook_init () +{ + int msr, tmp; + int stk_end, stk_siz; + + /* + // Check to see if hardware threads are enabled + if (((msr & AEMB_TXE) != AEMB_TXE) || + // Check to see if second thread is started + ((msr & AEMB_TX1) == AEMB_TX1)) return; + */ + //return; + asm volatile ("mfs %0, rmsr;" + // Check for BIP + "andi %1, %0, %5;" + "xori %1, %1, %5;" + "beqi %1, 44;" + + // Check for TXE + "andi %1, %0, %2;" + "xori %1, %1, %2;" + "bnei %1, 36;" + + // Check for TX1 + "andi %1, %0, %3;" + "xori %1, %1, %3;" + "beqi %1, 20;" + + // reallocate stack pointer for T0 + "ori %1, r0, %4;" + "sra %1, %1;" + "rsubk r1, %1, r1;" + + // reboot the machine + //"brki r0, _crtinit;" + "brid 0;" + "nop;" + + // clear BIP + "andni %1, %0, %5;" + "mts rmsr, %1;" + + :"=r"(msr), "=r"(tmp) + :"i"(AEMB_TXE), "i"(AEMB_TX1), "i"(&_STACK_SIZE), "i"(AEMB_BIP) + ); + +} + +/*! + Undo the changes made by programme init +*/ + +void aemb_hook_clean () +{ + int msr, tmp; + int stk_end, stk_siz; + + /* + // Check to see if hardware threads are enabled + if (((msr & AEMB_TXE) != AEMB_TXE) || + // Check to see if second thread is started + ((msr & AEMB_TX1) == AEMB_TX1)) return; + */ + return; + asm volatile ("mfs %0, rmsr;" + "andi %1, %0, %2;" + "xori %1, %1, %2;" + "bnei %1, 28;" + "andi %1, %0, %3;" + "xori %1, %1, %3;" + "beqi %1, 16;" + + // reallocate stack pointer for T0 + "ori %1, r0, %4;" + "sra %1, %1;" + "addk r1, %1, r1;" + + :"=r"(msr), "=r"(tmp) + :"i"(AEMB_TXE), "i"(AEMB_TX1), "i"(&_STACK_SIZE) + ); + + +} + +/* Checks if it's T1, and returns 0 if true */ + +int aemb_isthread1 () +{ + int msr, tmp, res; + asm volatile ("mfs %0, rmsr;" + "andi %1, %0, %3;" + "xori %1, %1, %3;" + :"=r"(msr), "=r"(tmp) + :"i"(AEMB_TXE), "i"(AEMB_TXP) + ); + return tmp; +} + +/* Checks if it's T0, and returns 0 if true */ + +int aemb_isthread0 () +{ + int msr, tmp, res; + asm volatile ("mfs %0, rmsr;" + "andi %1, %0, %3;" + "xori %1, %1, %2;" + :"=r"(msr), "=r"(tmp) + :"i"(AEMB_TXP), "i"(AEMB_MSK) + ); + return tmp; +} + +/* Checks if TXE is available, and returns 0 if true */ + +int aemb_isthreaded () +{ + int msr, tmp, res; + asm volatile ("mfs %0, rmsr;" + "andi %1, %0, %2;" + "xori %1, %1, %2;" + :"=r"(msr), "=r"(tmp) + :"i"(AEMB_TXE), "i"(AEMB_MSK) + ); + return tmp; +} + +#endif + +/* $Log: libaemb.h,v $ +/* Revision 1.3 2007/12/16 03:26:37 sybreon +/* Made T0 loop. +/* +/* Revision 1.1 2007/12/11 00:44:04 sybreon +/* initial import +/* */ diff --git a/opencores/aemb/sw/gccrom b/opencores/aemb/sw/gccrom new file mode 100755 index 000000000..f6e581f1f --- /dev/null +++ b/opencores/aemb/sw/gccrom @@ -0,0 +1,62 @@ +#!/bin/sh +# $Id: gccrom,v 1.13 2008/01/19 16:42:54 sybreon Exp $ + +# Compile using C++ pre-processor +mb-g++ -g -Wl,-defsym -Wl,_HEAP_SIZE=0x800 -mxl-soft-div -msoft-float -mxl-barrel-shift -mno-xl-soft-mul -mno-clearbss $@ -o rom.elf -lc_m_bs -lm_m_bs && \ + +# Create a text listing of the compiled code +mb-objdump -DSC rom.elf > rom.dump && \ + +# Convert the ELF file to an SREC file +mb-objcopy -O srec rom.elf rom.srec && \ + +# Generate a Verilog VMEM file from the SREC file +srec_cat rom.srec -o ../sim/dump.vmem -vmem 32 && \ + +# Cleanup code +rm rom.srec && \ + +# Say Cheeze! +echo "ROM generated" + +# $Log: gccrom,v $ +# Revision 1.13 2008/01/19 16:42:54 sybreon +# Uses multiplier + barrel shifter as default. +# +# Revision 1.12 2007/12/11 00:44:32 sybreon +# Modified for AEMB2 +# +# Revision 1.11 2007/11/30 17:09:27 sybreon +# Minor code cleanup. +# +# Revision 1.10 2007/11/20 18:35:34 sybreon +# Generate VMEM instead of HEX dumps of programme. +# +# Revision 1.9 2007/11/18 19:41:46 sybreon +# Minor simulation fixes. +# +# Revision 1.8 2007/11/09 20:52:37 sybreon +# Added some compilation optimisations. +# +# Revision 1.7 2007/11/04 05:16:25 sybreon +# Added -msoft-float and -mxl-soft-div compiler flags. +# +# Revision 1.6 2007/11/02 03:25:46 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. +# +# Revision 1.5 2007/10/22 19:14:38 sybreon +# Recommended to compile code with -O2/3/s +# +# Revision 1.4 2007/04/30 15:57:31 sybreon +# Modified compilation sequence. +# +# Revision 1.3 2007/04/25 22:15:06 sybreon +# Added support for 8-bit and 16-bit data types. +# +# Revision 1.2 2007/04/04 06:14:39 sybreon +# Minor changes +# +# Revision 1.1 2007/03/09 17:41:56 sybreon +# initial import |