// $Id: aeMB_regf.v,v 1.3 2007-11-10 16:39:38 sybreon Exp $
|
// $Id: aeMB_regf.v,v 1.3 2007-11-10 16:39:38 sybreon Exp $
|
//
|
//
|
// AEMB REGISTER FILE
|
// AEMB REGISTER FILE
|
//
|
//
|
// Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net>
|
// Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net>
|
//
|
//
|
// This file is part of AEMB.
|
// This file is part of AEMB.
|
//
|
//
|
// AEMB is free software: you can redistribute it and/or modify it
|
// AEMB is free software: you can redistribute it and/or modify it
|
// under the terms of the GNU Lesser General Public License as
|
// under the terms of the GNU Lesser General Public License as
|
// published by the Free Software Foundation, either version 3 of the
|
// published by the Free Software Foundation, either version 3 of the
|
// License, or (at your option) any later version.
|
// License, or (at your option) any later version.
|
//
|
//
|
// AEMB is distributed in the hope that it will be useful, but WITHOUT
|
// AEMB is distributed in the hope that it will be useful, but WITHOUT
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
// Public License for more details.
|
// Public License for more details.
|
//
|
//
|
// You should have received a copy of the GNU Lesser General Public
|
// You should have received a copy of the GNU Lesser General Public
|
// License along with AEMB. If not, see <http://www.gnu.org/licenses/>.
|
// License along with AEMB. If not, see <http://www.gnu.org/licenses/>.
|
//
|
//
|
// $Log: not supported by cvs2svn $
|
// $Log: not supported by cvs2svn $
|
// Revision 1.2 2007/11/09 20:51:52 sybreon
|
// Revision 1.2 2007/11/09 20:51:52 sybreon
|
// Added GET/PUT support through a FSL bus.
|
// Added GET/PUT support through a FSL bus.
|
//
|
//
|
// Revision 1.1 2007/11/02 03:25:41 sybreon
|
// Revision 1.1 2007/11/02 03:25:41 sybreon
|
// New EDK 3.2 compatible design with optional barrel-shifter and multiplier.
|
// New EDK 3.2 compatible design with optional barrel-shifter and multiplier.
|
// Fixed various minor data hazard bugs.
|
// Fixed various minor data hazard bugs.
|
// Code compatible with -O0/1/2/3/s generated code.
|
// Code compatible with -O0/1/2/3/s generated code.
|
//
|
//
|
|
|
module aeMB_regf (/*AUTOARG*/
|
module aeMB_regf (/*AUTOARG*/
|
// Outputs
|
// Outputs
|
rREGA, rREGB, rDWBDI, dwb_dat_o, fsl_dat_o,
|
rREGA, rREGB, rDWBDI, dwb_dat_o, fsl_dat_o,
|
// Inputs
|
// Inputs
|
rOPC, rRA, rRB, rRW, rRD, rMXDST, rPCLNK, rRESULT, rDWBSEL, rBRA,
|
rOPC, rRA, rRB, rRW, rRD, rMXDST, rPCLNK, rRESULT, rDWBSEL, rBRA,
|
rDLY, dwb_dat_i, fsl_dat_i, gclk, grst, gena
|
rDLY, dwb_dat_i, fsl_dat_i, gclk, grst, gena
|
);
|
);
|
// INTERNAL
|
// INTERNAL
|
output [31:0] rREGA, rREGB;
|
output [31:0] rREGA, rREGB;
|
output [31:0] rDWBDI;
|
output [31:0] rDWBDI;
|
input [5:0] rOPC;
|
input [5:0] rOPC;
|
input [4:0] rRA, rRB, rRW, rRD;
|
input [4:0] rRA, rRB, rRW, rRD;
|
input [1:0] rMXDST;
|
input [1:0] rMXDST;
|
input [31:2] rPCLNK;
|
input [31:2] rPCLNK;
|
input [31:0] rRESULT;
|
input [31:0] rRESULT;
|
input [3:0] rDWBSEL;
|
input [3:0] rDWBSEL;
|
input rBRA, rDLY;
|
input rBRA, rDLY;
|
|
|
// DATA WISHBONE
|
// DATA WISHBONE
|
output [31:0] dwb_dat_o;
|
output [31:0] dwb_dat_o;
|
input [31:0] dwb_dat_i;
|
input [31:0] dwb_dat_i;
|
|
|
// FSL WISHBONE
|
// FSL WISHBONE
|
output [31:0] fsl_dat_o;
|
output [31:0] fsl_dat_o;
|
input [31:0] fsl_dat_i;
|
input [31:0] fsl_dat_i;
|
|
|
// SYSTEM
|
// SYSTEM
|
input gclk, grst, gena;
|
input gclk, grst, gena;
|
|
|
// --- LOAD SIZER ----------------------------------------------
|
// --- LOAD SIZER ----------------------------------------------
|
// Moves the data bytes around depending on the size of the
|
// Moves the data bytes around depending on the size of the
|
// operation.
|
// operation.
|
|
|
wire [31:0] wDWBDI = dwb_dat_i; // FIXME: Endian
|
wire [31:0] wDWBDI = dwb_dat_i; // FIXME: Endian
|
wire [31:0] wFSLDI = fsl_dat_i; // FIXME: Endian
|
wire [31:0] wFSLDI = fsl_dat_i; // FIXME: Endian
|
|
|
reg [31:0] rDWBDI;
|
reg [31:0] rDWBDI;
|
reg [1:0] rSIZ;
|
reg [1:0] rSIZ;
|
|
|
always @(/*AUTOSENSE*/rDWBSEL or wDWBDI or wFSLDI) begin
|
always @(/*AUTOSENSE*/rDWBSEL or wDWBDI or wFSLDI) begin
|
/* 51.2
|
/* 51.2
|
case (rSIZ)
|
case (rSIZ)
|
// FSL
|
// FSL
|
2'o3: rDWBDI <= wFSLDI;
|
2'o3: rDWBDI <= wFSLDI;
|
// 32'bit
|
// 32'bit
|
2'o2: rDWBDI <= wDWBDI;
|
2'o2: rDWBDI <= wDWBDI;
|
// 16'bit
|
// 16'bit
|
2'o1: case (rRESULT[1])
|
2'o1: case (rRESULT[1])
|
1'b0: rDWBDI <= {16'd0, wDWBDI[31:16]};
|
1'b0: rDWBDI <= {16'd0, wDWBDI[31:16]};
|
1'b1: rDWBDI <= {16'd0, wDWBDI[15:0]};
|
1'b1: rDWBDI <= {16'd0, wDWBDI[15:0]};
|
endcase // case (rRESULT[1])
|
endcase // case (rRESULT[1])
|
// 8'bit
|
// 8'bit
|
2'o0: case (rRESULT[1:0])
|
2'o0: case (rRESULT[1:0])
|
2'o0: rDWBDI <= {24'd0, wDWBDI[31:24]};
|
2'o0: rDWBDI <= {24'd0, wDWBDI[31:24]};
|
2'o1: rDWBDI <= {24'd0, wDWBDI[23:16]};
|
2'o1: rDWBDI <= {24'd0, wDWBDI[23:16]};
|
2'o2: rDWBDI <= {24'd0, wDWBDI[15:8]};
|
2'o2: rDWBDI <= {24'd0, wDWBDI[15:8]};
|
2'o3: rDWBDI <= {24'd0, wDWBDI[7:0]};
|
2'o3: rDWBDI <= {24'd0, wDWBDI[7:0]};
|
endcase // case (rRESULT[1:0])
|
endcase // case (rRESULT[1:0])
|
endcase // case (rSIZ)
|
endcase // case (rSIZ)
|
*/
|
*/
|
|
|
/* 50.6
|
/* 50.6
|
case ({rSIZ, rRESULT[1:0]})
|
case ({rSIZ, rRESULT[1:0]})
|
// FSL
|
// FSL
|
4'hC, 4'hD, 4'hE, 4'hF: rDWBDI <= wFSLDI;
|
4'hC, 4'hD, 4'hE, 4'hF: rDWBDI <= wFSLDI;
|
// 32'bit
|
// 32'bit
|
4'h8: rDWBDI <= wDWBDI;
|
4'h8: rDWBDI <= wDWBDI;
|
// 16'bit
|
// 16'bit
|
4'h4: rDWBDI <= {16'd0, wDWBDI[31:16]};
|
4'h4: rDWBDI <= {16'd0, wDWBDI[31:16]};
|
4'h6: rDWBDI <= {16'd0, wDWBDI[15:0]};
|
4'h6: rDWBDI <= {16'd0, wDWBDI[15:0]};
|
// 8'bit
|
// 8'bit
|
4'h0: rDWBDI <= {24'd0, wDWBDI[31:24]};
|
4'h0: rDWBDI <= {24'd0, wDWBDI[31:24]};
|
4'h1: rDWBDI <= {24'd0, wDWBDI[23:16]};
|
4'h1: rDWBDI <= {24'd0, wDWBDI[23:16]};
|
4'h2: rDWBDI <= {24'd0, wDWBDI[15:8]};
|
4'h2: rDWBDI <= {24'd0, wDWBDI[15:8]};
|
4'h3: rDWBDI <= {24'd0, wDWBDI[7:0]};
|
4'h3: rDWBDI <= {24'd0, wDWBDI[7:0]};
|
default: rDWBDI <= 32'hX;
|
default: rDWBDI <= 32'hX;
|
endcase // case (rSIZ)
|
endcase // case (rSIZ)
|
*/
|
*/
|
|
|
// 52.0
|
// 52.0
|
case (rDWBSEL)
|
case (rDWBSEL)
|
// 8'bit
|
// 8'bit
|
4'h8: rDWBDI <= {24'd0, wDWBDI[31:24]};
|
4'h8: rDWBDI <= {24'd0, wDWBDI[31:24]};
|
4'h4: rDWBDI <= {24'd0, wDWBDI[23:16]};
|
4'h4: rDWBDI <= {24'd0, wDWBDI[23:16]};
|
4'h2: rDWBDI <= {24'd0, wDWBDI[15:8]};
|
4'h2: rDWBDI <= {24'd0, wDWBDI[15:8]};
|
4'h1: rDWBDI <= {24'd0, wDWBDI[7:0]};
|
4'h1: rDWBDI <= {24'd0, wDWBDI[7:0]};
|
// 16'bit
|
// 16'bit
|
4'hC: rDWBDI <= {16'd0, wDWBDI[31:16]};
|
4'hC: rDWBDI <= {16'd0, wDWBDI[31:16]};
|
4'h3: rDWBDI <= {16'd0, wDWBDI[15:0]};
|
4'h3: rDWBDI <= {16'd0, wDWBDI[15:0]};
|
// 32'bit
|
// 32'bit
|
4'hF: rDWBDI <= wDWBDI;
|
4'hF: rDWBDI <= wDWBDI;
|
// FSL
|
// FSL
|
4'h0: rDWBDI <= wFSLDI;
|
4'h0: rDWBDI <= wFSLDI;
|
// Undefined
|
// Undefined
|
default: rDWBDI <= 32'hX;
|
default: rDWBDI <= 32'hX;
|
endcase
|
endcase
|
|
|
end
|
end
|
|
|
always @(posedge gclk)
|
always @(posedge gclk)
|
if (grst) begin
|
if (grst) begin
|
/*AUTORESET*/
|
/*AUTORESET*/
|
// Beginning of autoreset for uninitialized flops
|
// Beginning of autoreset for uninitialized flops
|
rSIZ <= 2'h0;
|
rSIZ <= 2'h0;
|
// End of automatics
|
// End of automatics
|
end else if (gena) begin
|
end else if (gena) begin
|
rSIZ <= rOPC[1:0];
|
rSIZ <= rOPC[1:0];
|
end
|
end
|
|
|
// --- GENERAL PURPOSE REGISTERS (R0-R31) -----------------------
|
// --- GENERAL PURPOSE REGISTERS (R0-R31) -----------------------
|
// LUT RAM implementation is smaller and faster. R0 gets written
|
// LUT RAM implementation is smaller and faster. R0 gets written
|
// during reset with 0x00 and doesn't change after.
|
// during reset with 0x00 and doesn't change after.
|
|
|
reg [31:0] mARAM[0:31],
|
reg [31:0] mARAM[0:31],
|
mBRAM[0:31],
|
mBRAM[0:31],
|
mDRAM[0:31];
|
mDRAM[0:31];
|
|
|
wire [31:0] rREGW = mDRAM[rRW];
|
wire [31:0] rREGW = mDRAM[rRW];
|
wire [31:0] rREGD = mDRAM[rRD];
|
wire [31:0] rREGD = mDRAM[rRD];
|
assign rREGA = mARAM[rRA];
|
assign rREGA = mARAM[rRA];
|
assign rREGB = mBRAM[rRB];
|
assign rREGB = mBRAM[rRB];
|
|
|
wire fRDWE = |rRW;
|
wire fRDWE = |rRW;
|
|
|
reg [31:0] xWDAT;
|
reg [31:0] xWDAT;
|
|
|
always @(/*AUTOSENSE*/rDWBDI or rMXDST or rPCLNK or rREGW
|
always @(/*AUTOSENSE*/rDWBDI or rMXDST or rPCLNK or rREGW
|
or rRESULT)
|
or rRESULT)
|
case (rMXDST)
|
case (rMXDST)
|
2'o2: xWDAT <= rDWBDI;
|
2'o2: xWDAT <= rDWBDI;
|
2'o1: xWDAT <= {rPCLNK, 2'o0};
|
2'o1: xWDAT <= {rPCLNK, 2'o0};
|
2'o0: xWDAT <= rRESULT;
|
2'o0: xWDAT <= rRESULT;
|
2'o3: xWDAT <= rREGW; // No change
|
2'o3: xWDAT <= rREGW; // No change
|
endcase // case (rMXDST)
|
endcase // case (rMXDST)
|
|
|
always @(posedge gclk)
|
always @(posedge gclk)
|
if (grst | fRDWE) begin
|
if (grst | fRDWE) begin
|
mARAM[rRW] <= xWDAT;
|
mARAM[rRW] <= xWDAT;
|
mBRAM[rRW] <= xWDAT;
|
mBRAM[rRW] <= xWDAT;
|
mDRAM[rRW] <= xWDAT;
|
mDRAM[rRW] <= xWDAT;
|
end
|
end
|
|
|
// --- STORE SIZER ---------------------------------------------
|
// --- STORE SIZER ---------------------------------------------
|
// Replicates the data bytes across depending on the size of the
|
// Replicates the data bytes across depending on the size of the
|
// operation.
|
// operation.
|
|
|
reg [31:0] rDWBDO, xDWBDO;
|
reg [31:0] rDWBDO, xDWBDO;
|
|
|
wire [31:0] xFSL;
|
wire [31:0] xFSL;
|
wire fFFWD_M = (rRA == rRW) & (rMXDST == 2'o2) & fRDWE;
|
wire fFFWD_M = (rRA == rRW) & (rMXDST == 2'o2) & fRDWE;
|
wire fFFWD_R = (rRA == rRW) & (rMXDST == 2'o0) & fRDWE;
|
wire fFFWD_R = (rRA == rRW) & (rMXDST == 2'o0) & fRDWE;
|
|
|
assign fsl_dat_o = rDWBDO;
|
assign fsl_dat_o = rDWBDO;
|
assign xFSL = (fFFWD_M) ? rDWBDI :
|
assign xFSL = (fFFWD_M) ? rDWBDI :
|
(fFFWD_R) ? rRESULT :
|
(fFFWD_R) ? rRESULT :
|
rREGA;
|
rREGA;
|
|
|
wire [31:0] xDST;
|
wire [31:0] xDST;
|
wire fDFWD_M = (rRW == rRD) & (rMXDST == 2'o2) & fRDWE;
|
wire fDFWD_M = (rRW == rRD) & (rMXDST == 2'o2) & fRDWE;
|
wire fDFWD_R = (rRW == rRD) & (rMXDST == 2'o0) & fRDWE;
|
wire fDFWD_R = (rRW == rRD) & (rMXDST == 2'o0) & fRDWE;
|
|
|
assign dwb_dat_o = rDWBDO;
|
assign dwb_dat_o = rDWBDO;
|
assign xDST = (fDFWD_M) ? rDWBDI :
|
assign xDST = (fDFWD_M) ? rDWBDI :
|
(fDFWD_R) ? rRESULT :
|
(fDFWD_R) ? rRESULT :
|
rREGD;
|
rREGD;
|
|
|
always @(/*AUTOSENSE*/rOPC or xDST or xFSL)
|
always @(/*AUTOSENSE*/rOPC or xDST or xFSL)
|
case (rOPC[1:0])
|
case (rOPC[1:0])
|
// 8'bit
|
// 8'bit
|
2'h0: xDWBDO <= {(4){xDST[7:0]}};
|
2'h0: xDWBDO <= {(4){xDST[7:0]}};
|
// 16'bit
|
// 16'bit
|
2'h1: xDWBDO <= {(2){xDST[15:0]}};
|
2'h1: xDWBDO <= {(2){xDST[15:0]}};
|
// 32'bit
|
// 32'bit
|
2'h2: xDWBDO <= xDST;
|
2'h2: xDWBDO <= xDST;
|
// FSL
|
// FSL
|
2'h3: xDWBDO <= xFSL;
|
2'h3: xDWBDO <= xFSL;
|
//default: xDWBDO <= 32'hX;
|
//default: xDWBDO <= 32'hX;
|
endcase // case (rOPC[1:0])
|
endcase // case (rOPC[1:0])
|
|
|
always @(posedge gclk)
|
always @(posedge gclk)
|
if (grst) begin
|
if (grst) begin
|
/*AUTORESET*/
|
/*AUTORESET*/
|
// Beginning of autoreset for uninitialized flops
|
// Beginning of autoreset for uninitialized flops
|
rDWBDO <= 32'h0;
|
rDWBDO <= 32'h0;
|
// End of automatics
|
// End of automatics
|
end else if (gena) begin
|
end else if (gena) begin
|
rDWBDO <= #1 xDWBDO;
|
rDWBDO <= #1 xDWBDO;
|
end
|
end
|
|
|
// --- SIMULATION ONLY ------------------------------------------
|
// --- SIMULATION ONLY ------------------------------------------
|
// Randomise memory to simulate real-world memory
|
// Randomise memory to simulate real-world memory
|
// synopsys translate_off
|
// synopsys translate_off
|
|
|
integer i;
|
integer i;
|
initial begin
|
initial begin
|
for (i=0; i<32; i=i+1) begin
|
for (i=0; i<32; i=i+1) begin
|
mARAM[i] <= $random;
|
mARAM[i] <= $random;
|
mBRAM[i] <= $random;
|
mBRAM[i] <= $random;
|
mDRAM[i] <= $random;
|
mDRAM[i] <= $random;
|
end
|
end
|
end
|
end
|
|
|
// synopsys translate_on
|
// synopsys translate_on
|
|
|
|
|
endmodule // aeMB_regf
|
endmodule // aeMB_regf
|
|
|