diff options
Diffstat (limited to 'fpga/usrp2/opencores/aemb')
21 files changed, 3523 insertions, 0 deletions
| diff --git a/fpga/usrp2/opencores/aemb/doc/aeMB_datasheet.pdf b/fpga/usrp2/opencores/aemb/doc/aeMB_datasheet.pdfBinary files differ new file mode 100644 index 000000000..5b26ac319 --- /dev/null +++ b/fpga/usrp2/opencores/aemb/doc/aeMB_datasheet.pdf diff --git a/fpga/usrp2/opencores/aemb/rtl/verilog/.gitignore b/fpga/usrp2/opencores/aemb/rtl/verilog/.gitignore new file mode 100644 index 000000000..6b09f5cc9 --- /dev/null +++ b/fpga/usrp2/opencores/aemb/rtl/verilog/.gitignore @@ -0,0 +1 @@ +/aeMB2* diff --git a/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v new file mode 100644 index 000000000..81587e25c --- /dev/null +++ b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_bpcu.v @@ -0,0 +1,185 @@ +// $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 = gena ? xIPC[IW-1:2] :  rIPC[IW-1:2]; //IJB +    +   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; +	rIPC <= 30'h3fffffff; // DWORD aligned address  +	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/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_core.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_core.v new file mode 100644 index 000000000..20ce9852e --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v new file mode 100644 index 000000000..6c066d5d9 --- /dev/null +++ b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_core_BE.v @@ -0,0 +1,71 @@ + +// 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, +     // Instruction port +     output [ISIZ-1:0] if_adr, +     input [31:0] if_dat, +     // Data port +     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); + + +   wire [ISIZ-1:0] iwb_adr_o; +   wire [31:0] 	   iwb_dat_i; +   wire 	   iwb_ack_i; +   wire 	   iwb_stb_o; +    +   assign dwb_cyc_o = dwb_stb_o; +   assign iwb_ack_i = 1'b1; +   assign if_adr = iwb_adr_o[ISIZ-1:0]; +   assign iwb_dat_i = if_dat; + +   // Note some "wishbone" instruction fetch signals pruned on external interface +   // but not propogated change deep into aeMB. +   aeMB_edk32 #(.IW(ISIZ),.DW(DSIZ),.MUL(MUL),.BSF(BSF)) +     aeMB_edk32 (.sys_clk_i(sys_clk_i),  +		 .sys_rst_i(sys_rst_i), +		 // Instruction Port +		 .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), +		 // Data port +		 .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/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_ctrl.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_ctrl.v new file mode 100644 index 000000000..88d4e51ce --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_edk32.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_edk32.v new file mode 100644 index 000000000..8bf4f7cac --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_ibuf.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_ibuf.v new file mode 100644 index 000000000..a4edf1d90 --- /dev/null +++ b/fpga/usrp2/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 (gena & !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. +*/ diff --git a/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_regf.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_regf.v new file mode 100644 index 000000000..7fe108957 --- /dev/null +++ b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_regf.v @@ -0,0 +1,244 @@ +// $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. +    +   //synthesis attribute ram_style of mARAM is distributed +   reg [31:0] 	 mARAM[0:31];  +   //synthesis attribute ram_style of mBRAM is distributed +   reg [31:0] 	 mBRAM[0:31]; +   //synthesis attribute ram_style of mDRAM is distributed +   reg [31:0] 	 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/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_sim.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_sim.v new file mode 100644 index 000000000..83248e4ba --- /dev/null +++ b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_sim.v @@ -0,0 +1,312 @@ +/* $Id: aeMB_sim.v,v 1.2 2008/06/06 09:36:02 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}; + + +   `ifdef AEMB_SIM_KERNEL +   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) +   `endif //  `ifdef AEMB_SIM_KERNEL +    +   // synopsys translate_on +    +endmodule // aeMB_sim + +/*  + $Log: aeMB_sim.v,v $ + Revision 1.2  2008/06/06 09:36:02  sybreon + single thread design + + 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/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_xecu.v b/fpga/usrp2/opencores/aemb/rtl/verilog/aeMB_xecu.v new file mode 100644 index 000000000..5de2ea619 --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/sim/.gitignore b/fpga/usrp2/opencores/aemb/sim/.gitignore new file mode 100644 index 000000000..4ef5da542 --- /dev/null +++ b/fpga/usrp2/opencores/aemb/sim/.gitignore @@ -0,0 +1,4 @@ +/*.bin +/*.dump +/*.vcd +/*.rom diff --git a/fpga/usrp2/opencores/aemb/sim/CODE_DEBUG.sav b/fpga/usrp2/opencores/aemb/sim/CODE_DEBUG.sav new file mode 100644 index 000000000..f777173c4 --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/sim/cversim b/fpga/usrp2/opencores/aemb/sim/cversim new file mode 100755 index 000000000..0dbb7aea1 --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/sim/iversim b/fpga/usrp2/opencores/aemb/sim/iversim new file mode 100755 index 000000000..9d2384b5a --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/sim/verilog/aemb2.v b/fpga/usrp2/opencores/aemb/sim/verilog/aemb2.v new file mode 100644 index 000000000..bda1704e3 --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/sim/verilog/edk32.v b/fpga/usrp2/opencores/aemb/sim/verilog/edk32.v new file mode 100644 index 000000000..68465e9e0 --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/sw/c/aeMB_testbench.c b/fpga/usrp2/opencores/aemb/sw/c/aeMB_testbench.c new file mode 100644 index 000000000..c3402e0ef --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/sw/c/endian-test.c b/fpga/usrp2/opencores/aemb/sw/c/endian-test.c new file mode 100644 index 000000000..b585f7a30 --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/sw/c/libaemb.h b/fpga/usrp2/opencores/aemb/sw/c/libaemb.h new file mode 100644 index 000000000..329a327a1 --- /dev/null +++ b/fpga/usrp2/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/fpga/usrp2/opencores/aemb/sw/gccrom b/fpga/usrp2/opencores/aemb/sw/gccrom new file mode 100755 index 000000000..f6e581f1f --- /dev/null +++ b/fpga/usrp2/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 | 
