// $Id: aeMB_bpcu.v,v 1.4 2007-11-14 22:14:34 sybreon Exp $
|
// $Id: aeMB_bpcu.v,v 1.4 2007-11-14 22:14:34 sybreon Exp $
|
//
|
//
|
// AEMB BRANCH PROGRAMME COUNTER UNIT
|
// AEMB BRANCH PROGRAMME COUNTER UNIT
|
//
|
//
|
// 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.3 2007/11/10 16:39:38 sybreon
|
// Revision 1.3 2007/11/10 16:39:38 sybreon
|
// Upgraded license to LGPLv3.
|
// Upgraded license to LGPLv3.
|
// Significant performance optimisations.
|
// Significant performance optimisations.
|
//
|
//
|
// Revision 1.2 2007/11/02 19:20:58 sybreon
|
// Revision 1.2 2007/11/02 19:20:58 sybreon
|
// Added better (beta) interrupt support.
|
// Added better (beta) interrupt support.
|
// Changed MSR_IE to disabled at reset as per MB docs.
|
// Changed MSR_IE to disabled at reset as per MB docs.
|
//
|
//
|
// Revision 1.1 2007/11/02 03:25:39 sybreon
|
// Revision 1.1 2007/11/02 03:25:39 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_bpcu (/*AUTOARG*/
|
module aeMB_bpcu (/*AUTOARG*/
|
// Outputs
|
// Outputs
|
iwb_adr_o, rPC, rPCLNK, rBRA, rDLY,
|
iwb_adr_o, rPC, rPCLNK, rBRA, rDLY,
|
// Inputs
|
// Inputs
|
rMXALT, rOPC, rRD, rRA, rRESULT, rDWBDI, rREGA, gclk, grst, gena
|
rMXALT, rOPC, rRD, rRA, rRESULT, rDWBDI, rREGA, gclk, grst, gena
|
);
|
);
|
parameter IW = 24;
|
parameter IW = 24;
|
|
|
// INST WISHBONE
|
// INST WISHBONE
|
output [IW-1:2] iwb_adr_o;
|
output [IW-1:2] iwb_adr_o;
|
|
|
// INTERNAL
|
// INTERNAL
|
output [31:2] rPC, rPCLNK;
|
output [31:2] rPC, rPCLNK;
|
output rBRA;
|
output rBRA;
|
output rDLY;
|
output rDLY;
|
//output [1:0] rATOM;
|
//output [1:0] rATOM;
|
//output [1:0] xATOM;
|
//output [1:0] xATOM;
|
|
|
input [1:0] rMXALT;
|
input [1:0] rMXALT;
|
input [5:0] rOPC;
|
input [5:0] rOPC;
|
input [4:0] rRD, rRA;
|
input [4:0] rRD, rRA;
|
input [31:0] rRESULT; // ALU
|
input [31:0] rRESULT; // ALU
|
input [31:0] rDWBDI; // RAM
|
input [31:0] rDWBDI; // RAM
|
input [31:0] rREGA;
|
input [31:0] rREGA;
|
//input [1:0] rXCE;
|
//input [1:0] rXCE;
|
|
|
// SYSTEM
|
// SYSTEM
|
input gclk, grst, gena;
|
input gclk, grst, gena;
|
|
|
// --- BRANCH CONTROL --------------------------------------------
|
// --- BRANCH CONTROL --------------------------------------------
|
// Controls the branch and delay flags
|
// Controls the branch and delay flags
|
|
|
wire fRTD = (rOPC == 6'o55);
|
wire fRTD = (rOPC == 6'o55);
|
wire fBCC = (rOPC == 6'o47) | (rOPC == 6'o57);
|
wire fBCC = (rOPC == 6'o47) | (rOPC == 6'o57);
|
wire fBRU = (rOPC == 6'o46) | (rOPC == 6'o56);
|
wire fBRU = (rOPC == 6'o46) | (rOPC == 6'o56);
|
|
|
wire [31:0] wREGA;
|
wire [31:0] wREGA;
|
assign wREGA = (rMXALT == 2'o2) ? rDWBDI :
|
assign wREGA = (rMXALT == 2'o2) ? rDWBDI :
|
(rMXALT == 2'o1) ? rRESULT :
|
(rMXALT == 2'o1) ? rRESULT :
|
rREGA;
|
rREGA;
|
|
|
wire wBEQ = (wREGA == 32'd0);
|
wire wBEQ = (wREGA == 32'd0);
|
wire wBNE = ~wBEQ;
|
wire wBNE = ~wBEQ;
|
wire wBLT = wREGA[31];
|
wire wBLT = wREGA[31];
|
wire wBLE = wBLT | wBEQ;
|
wire wBLE = wBLT | wBEQ;
|
wire wBGE = ~wBLT;
|
wire wBGE = ~wBLT;
|
wire wBGT = ~wBLE;
|
wire wBGT = ~wBLE;
|
|
|
reg xXCC;
|
reg xXCC;
|
always @(/*AUTOSENSE*/rRD or wBEQ or wBGE or wBGT or wBLE or wBLT
|
always @(/*AUTOSENSE*/rRD or wBEQ or wBGE or wBGT or wBLE or wBLT
|
or wBNE)
|
or wBNE)
|
case (rRD[2:0])
|
case (rRD[2:0])
|
3'o0: xXCC <= wBEQ;
|
3'o0: xXCC <= wBEQ;
|
3'o1: xXCC <= wBNE;
|
3'o1: xXCC <= wBNE;
|
3'o2: xXCC <= wBLT;
|
3'o2: xXCC <= wBLT;
|
3'o3: xXCC <= wBLE;
|
3'o3: xXCC <= wBLE;
|
3'o4: xXCC <= wBGT;
|
3'o4: xXCC <= wBGT;
|
3'o5: xXCC <= wBGE;
|
3'o5: xXCC <= wBGE;
|
default: xXCC <= 1'bX;
|
default: xXCC <= 1'bX;
|
endcase // case (rRD[2:0])
|
endcase // case (rRD[2:0])
|
|
|
reg rBRA, xBRA;
|
reg rBRA, xBRA;
|
reg rDLY, xDLY;
|
reg rDLY, xDLY;
|
wire fSKIP = rBRA & !rDLY;
|
wire fSKIP = rBRA & !rDLY;
|
|
|
always @(/*AUTOSENSE*/fBCC or fBRU or fRTD or rBRA or rRA or rRD
|
always @(/*AUTOSENSE*/fBCC or fBRU or fRTD or rBRA or rRA or rRD
|
or xXCC)
|
or xXCC)
|
//if (rBRA | |rXCE) begin
|
//if (rBRA | |rXCE) begin
|
if (rBRA) begin
|
if (rBRA) begin
|
/*AUTORESET*/
|
/*AUTORESET*/
|
// Beginning of autoreset for uninitialized flops
|
// Beginning of autoreset for uninitialized flops
|
xBRA <= 1'h0;
|
xBRA <= 1'h0;
|
xDLY <= 1'h0;
|
xDLY <= 1'h0;
|
// End of automatics
|
// End of automatics
|
end else begin
|
end else begin
|
xDLY <= (fBRU & rRA[4]) | (fBCC & rRD[4]) | fRTD;
|
xDLY <= (fBRU & rRA[4]) | (fBCC & rRD[4]) | fRTD;
|
xBRA <= (fRTD | fBRU) ? 1'b1 :
|
xBRA <= (fRTD | fBRU) ? 1'b1 :
|
(fBCC) ? xXCC :
|
(fBCC) ? xXCC :
|
1'b0;
|
1'b0;
|
end
|
end
|
|
|
// --- PC PIPELINE ------------------------------------------------
|
// --- PC PIPELINE ------------------------------------------------
|
// PC and related changes
|
// PC and related changes
|
|
|
reg [31:2] rIPC, xIPC;
|
reg [31:2] rIPC, xIPC;
|
reg [31:2] rPC, xPC;
|
reg [31:2] rPC, xPC;
|
reg [31:2] rPCLNK, xPCLNK;
|
reg [31:2] rPCLNK, xPCLNK;
|
|
|
assign iwb_adr_o = rIPC[IW-1:2];
|
assign iwb_adr_o = rIPC[IW-1:2];
|
|
|
always @(/*AUTOSENSE*/rBRA or rIPC or rPC or rRESULT) begin
|
always @(/*AUTOSENSE*/rBRA or rIPC or rPC or rRESULT) begin
|
//xPCLNK <= (^rATOM) ? rPC : rPC;
|
//xPCLNK <= (^rATOM) ? rPC : rPC;
|
xPCLNK <= rPC;
|
xPCLNK <= rPC;
|
//xPC <= (^rATOM) ? rIPC : rRESULT[31:2];
|
//xPC <= (^rATOM) ? rIPC : rRESULT[31:2];
|
xPC <= rIPC;
|
xPC <= rIPC;
|
//xIPC <= (rBRA) ? rRESULT[31:2] : (rIPC + 1);
|
//xIPC <= (rBRA) ? rRESULT[31:2] : (rIPC + 1);
|
/*
|
/*
|
case (rXCE)
|
case (rXCE)
|
2'o1: xIPC <= 30'h2;
|
2'o1: xIPC <= 30'h2;
|
2'o2: xIPC <= 30'h4;
|
2'o2: xIPC <= 30'h4;
|
2'o3: xIPC <= 30'h6;
|
2'o3: xIPC <= 30'h6;
|
default: xIPC <= (rBRA) ? rRESULT[31:2] : (rIPC + 1);
|
default: xIPC <= (rBRA) ? rRESULT[31:2] : (rIPC + 1);
|
endcase // case (rXCE)
|
endcase // case (rXCE)
|
*/
|
*/
|
xIPC <= (rBRA) ? rRESULT[31:2] : (rIPC + 1);
|
xIPC <= (rBRA) ? rRESULT[31:2] : (rIPC + 1);
|
end
|
end
|
|
|
// --- ATOMIC CONTROL ---------------------------------------------
|
// --- ATOMIC CONTROL ---------------------------------------------
|
// This is used to indicate 'safe' instruction borders.
|
// This is used to indicate 'safe' instruction borders.
|
|
|
wire wIMM = (rOPC == 6'o54) & !fSKIP;
|
wire wIMM = (rOPC == 6'o54) & !fSKIP;
|
wire wRTD = (rOPC == 6'o55) & !fSKIP;
|
wire wRTD = (rOPC == 6'o55) & !fSKIP;
|
wire wBCC = xXCC & ((rOPC == 6'o47) | (rOPC == 6'o57)) & !fSKIP;
|
wire wBCC = xXCC & ((rOPC == 6'o47) | (rOPC == 6'o57)) & !fSKIP;
|
wire wBRU = ((rOPC == 6'o46) | (rOPC == 6'o56)) & !fSKIP;
|
wire wBRU = ((rOPC == 6'o46) | (rOPC == 6'o56)) & !fSKIP;
|
|
|
wire fATOM = ~(wIMM | wRTD | wBCC | wBRU | rBRA);
|
wire fATOM = ~(wIMM | wRTD | wBCC | wBRU | rBRA);
|
reg [1:0] rATOM, xATOM;
|
reg [1:0] rATOM, xATOM;
|
|
|
always @(/*AUTOSENSE*/fATOM or rATOM)
|
always @(/*AUTOSENSE*/fATOM or rATOM)
|
xATOM <= {rATOM[0], (rATOM[0] ^ fATOM)};
|
xATOM <= {rATOM[0], (rATOM[0] ^ fATOM)};
|
|
|
|
|
// --- SYNC PIPELINE ----------------------------------------------
|
// --- SYNC PIPELINE ----------------------------------------------
|
|
|
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
|
rATOM <= 2'h0;
|
rATOM <= 2'h0;
|
rBRA <= 1'h0;
|
rBRA <= 1'h0;
|
rDLY <= 1'h0;
|
rDLY <= 1'h0;
|
rIPC <= 30'h0;
|
rIPC <= 30'h0;
|
rPC <= 30'h0;
|
rPC <= 30'h0;
|
rPCLNK <= 30'h0;
|
rPCLNK <= 30'h0;
|
// End of automatics
|
// End of automatics
|
end else if (gena) begin
|
end else if (gena) begin
|
rIPC <= #1 xIPC;
|
rIPC <= #1 xIPC;
|
rBRA <= #1 xBRA;
|
rBRA <= #1 xBRA;
|
rPC <= #1 xPC;
|
rPC <= #1 xPC;
|
rPCLNK <= #1 xPCLNK;
|
rPCLNK <= #1 xPCLNK;
|
rDLY <= #1 xDLY;
|
rDLY <= #1 xDLY;
|
rATOM <= #1 xATOM;
|
rATOM <= #1 xATOM;
|
end
|
end
|
|
|
endmodule // aeMB_bpcu
|
endmodule // aeMB_bpcu
|
|
|