Line 1... |
Line 1... |
/* $Id: aeMB2_bpcu.v,v 1.1 2007-12-11 00:43:17 sybreon Exp $
|
/* $Id: aeMB2_bpcu.v,v 1.2 2007-12-12 19:16:59 sybreon Exp $
|
**
|
**
|
** AEMB2 BRANCH/PROGRAMME COUNTER
|
** AEMB2 BRANCH/PROGRAMME COUNTER
|
**
|
**
|
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net>
|
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net>
|
**
|
**
|
Line 20... |
Line 20... |
** License along with AEMB. If not, see <http://www.gnu.org/licenses/>.
|
** License along with AEMB. If not, see <http://www.gnu.org/licenses/>.
|
*/
|
*/
|
|
|
module aeMB2_bpcu (/*AUTOARG*/
|
module aeMB2_bpcu (/*AUTOARG*/
|
// Outputs
|
// Outputs
|
iwb_adr_o, rPC_OF, rPC_MA, rPC_IF, rIMM_IF, rALT_IF, rOPC_IF,
|
iwb_adr_o, rPC_MA, rPC_IF, rIMM_IF, rALT_IF, rOPC_IF, rRD_IF,
|
rRD_IF, rRA_IF, rRB_IF, rBRA,
|
rRA_IF, rRB_IF, rBRA,
|
// Inputs
|
// Inputs
|
iwb_dat_i, iwb_ack_i, rOPX_OF, rOPC_OF, rRA_OF, rRD_OF, rRES_EX,
|
iwb_dat_i, iwb_ack_i, rOPX_OF, rOPC_OF, rRA_OF, rRD_OF, rRES_EX,
|
rRD_EX, rOPD_EX, clk_i, rst_i, ena_i, pha_i
|
rRD_EX, rOPD_EX, rMSR_TXE, clk_i, rst_i, ena_i, pha_i
|
);
|
);
|
parameter IWB = 32;
|
parameter IWB = 32;
|
parameter TXE = 1;
|
parameter TXE = 1;
|
parameter LUT = 1;
|
|
|
|
// IWB
|
// IWB
|
output [IWB-1:2] iwb_adr_o;
|
output [IWB-1:2] iwb_adr_o;
|
input [31:0] iwb_dat_i;
|
input [31:0] iwb_dat_i;
|
input iwb_ack_i;
|
input iwb_ack_i;
|
|
|
// PIPELINE
|
// PIPELINE
|
output [31:2] rPC_OF,
|
output [31:2] //rPC_OF,
|
rPC_MA,
|
rPC_MA,
|
rPC_IF;
|
rPC_IF;
|
output [15:0] rIMM_IF;
|
output [15:0] rIMM_IF;
|
output [10:0] rALT_IF;
|
output [10:0] rALT_IF;
|
output [5:0] rOPC_IF;
|
output [5:0] rOPC_IF;
|
output [4:0] rRD_IF,
|
output [4:0] rRD_IF,
|
rRA_IF,
|
rRA_IF,
|
rRB_IF;
|
rRB_IF;
|
|
|
// BRANCH DETECTION
|
// BRANCH DETECTION
|
output [1:0] rBRA; ///< {branch, delay}
|
output [1:0] rBRA; // {branch, delay}
|
input [31:0] rOPX_OF; // BCC op test
|
input [31:0] rOPX_OF; // BCC op test
|
input [5:0] rOPC_OF;
|
input [5:0] rOPC_OF;
|
input [4:0] rRA_OF,
|
input [4:0] rRA_OF,
|
rRD_OF;
|
rRD_OF;
|
input [31:0] rRES_EX;
|
input [31:0] rRES_EX;
|
Line 59... |
Line 58... |
// MEMORY HAZARD DETECTION
|
// MEMORY HAZARD DETECTION
|
input [4:0] rRD_EX; ///< RD
|
input [4:0] rRD_EX; ///< RD
|
input [2:0] rOPD_EX; ///< data register source (ALU, MEM/FSL, PC)
|
input [2:0] rOPD_EX; ///< data register source (ALU, MEM/FSL, PC)
|
|
|
// SYSTEM
|
// SYSTEM
|
|
input rMSR_TXE;
|
input clk_i,
|
input clk_i,
|
rst_i,
|
rst_i,
|
ena_i,
|
ena_i,
|
pha_i;
|
pha_i;
|
|
|
Line 75... |
Line 75... |
reg [31:2] rPC_MA;
|
reg [31:2] rPC_MA;
|
reg [4:0] rRA_IF;
|
reg [4:0] rRA_IF;
|
reg [4:0] rRD_IF;
|
reg [4:0] rRD_IF;
|
// End of automatics
|
// End of automatics
|
|
|
|
|
/* Partial decoding */
|
/* Partial decoding */
|
wire [5:0] rOPC = rOPC_IF;
|
wire [5:0] rOPC = rOPC_IF;
|
wire [4:0] rRA = rRA_IF;
|
wire [4:0] rRA = rRA_IF;
|
wire [4:0] rRB = rRB_IF;
|
wire [4:0] rRB = rRB_IF;
|
wire fSFT = (rOPC == 6'o44);
|
wire fSFT = (rOPC == 6'o44);
|
Line 101... |
Line 100... |
|
|
/* Select the PC. */
|
/* Select the PC. */
|
|
|
reg [31:2] rPC, // PC
|
reg [31:2] rPC, // PC
|
rPC0, rPC1, // register based
|
rPC0, rPC1, // register based
|
rPCL[0:TXE]; // LUT based
|
rPCL[0:1]; // LUT based
|
|
|
wire [31:2] wPCSEL = (pha_i) ? rPC0 : (TXE) ? rPC1 : 30'hX;
|
wire [31:2] wPCNXT = (pha_i) ? rPC0 : (TXE) ? rPC1 : 30'hX;
|
wire [31:2] wPCNXT = (LUT) ? rPCL[!pha_i] : wPCSEL;
|
|
wire [31:2] wPCINC = (rPC + 1);
|
wire [31:2] wPCINC = (rPC + 1);
|
|
|
/* Check for RW data hazard */
|
/* Check for RW data hazard */
|
// TODO: Optimise
|
// TODO: Optimise
|
|
|
Line 116... |
Line 114... |
wire fMULT = (rOPD_EX == 3'o3);
|
wire fMULT = (rOPD_EX == 3'o3);
|
wire fWRE = |rRD_EX;
|
wire fWRE = |rRD_EX;
|
wire fOPBHZD = (rRB_IF == rRD_EX) & (fLOAD | fMULT) & !fMOV & !rOPC_IF[3] & fWRE;
|
wire fOPBHZD = (rRB_IF == rRD_EX) & (fLOAD | fMULT) & !fMOV & !rOPC_IF[3] & fWRE;
|
wire fOPAHZD = (rRA_IF == rRD_EX) & (fLOAD | fMULT) & !fBRU & fWRE;
|
wire fOPAHZD = (rRA_IF == rRD_EX) & (fLOAD | fMULT) & !fBRU & fWRE;
|
wire fOPDHZD = (rRD_IF == rRD_EX) & (fLOAD | fMULT) & fSTR & fWRE;
|
wire fOPDHZD = (rRD_IF == rRD_EX) & (fLOAD | fMULT) & fSTR & fWRE;
|
wire fHAZARD = fOPBHZD | fOPAHZD | fOPDHZD;
|
wire fHZD = fOPBHZD | fOPAHZD | fOPDHZD;
|
|
|
|
/*
|
|
IWB PC OUTPUT
|
|
|
/* Output the new PC for IWB */
|
This is part of the address generation stage. It pre-selects the
|
|
next PC to fetch depending on whether it's a branch, retry or
|
|
normal. A retry happens during a special hazard */
|
|
|
wire [1:0] wIPCMX = {fHAZARD, rBRA[1]};
|
wire [1:0] wIPCMX = {fHZD, rBRA[1]};
|
assign iwb_adr_o = rPC[IWB-1:2];
|
assign iwb_adr_o = rPC[IWB-1:2];
|
|
|
always @ (posedge clk_i)
|
always @ (posedge clk_i)
|
if (rst_i) begin
|
if (rst_i) begin
|
rPC <= {(30){1'b1}};
|
rPC <= {(30){1'b1}};
|
Line 136... |
Line 139... |
2'o2 : rPC <= #1 rPC_IF[IWB-1:2]; // retry/stall
|
2'o2 : rPC <= #1 rPC_IF[IWB-1:2]; // retry/stall
|
default: rPC <= {(IWB-2){1'bX}}; // undefined
|
default: rPC <= {(IWB-2){1'bX}}; // undefined
|
endcase // case (wIPCMX)
|
endcase // case (wIPCMX)
|
end
|
end
|
|
|
/* Inbcrement the PC */
|
/*
|
|
PC INCREMENT
|
|
|
|
This will store the next PC in a holding register until it is
|
|
needed during the next AG stage. */
|
|
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
if (rst_i) begin
|
if (rst_i) begin
|
/*AUTORESET*/
|
/*AUTORESET*/
|
// Beginning of autoreset for uninitialized flops
|
// Beginning of autoreset for uninitialized flops
|
rPC0 <= 30'h0;
|
rPC0 <= 30'h0;
|
rPC1 <= 30'h0;
|
rPC1 <= 30'h0;
|
// End of automatics
|
// End of automatics
|
end else if (ena_i) begin
|
end else begin
|
if (pha_i)
|
if (pha_i & ena_i & rMSR_TXE) rPC1 <= #1 wPCINC;
|
rPC1 <= #1 wPCINC;
|
if (!pha_i & ena_i) rPC0 <= #1 wPCINC;
|
else
|
|
rPC0 <= #1 wPCINC;
|
|
end
|
end
|
|
|
always @(posedge clk_i)
|
/*
|
if (ena_i | rst_i) begin
|
INSTRUCTION LATCH
|
rPCL[pha_i] <= #1 wPCINC;
|
|
end
|
|
|
|
/* Latch onto instruction word */
|
This latches onto the instruction. It may not work correctly if
|
|
there is a pipeline stall. */
|
|
|
reg [31:2] rPC_OF, rPC_EX;
|
reg [31:2] rPC_OF, rPC_EX;
|
assign {rRB_IF, rALT_IF} = rIMM_IF;
|
assign {rRB_IF, rALT_IF} = rIMM_IF;
|
|
|
always @(posedge clk_i)
|
always @(posedge clk_i)
|
Line 174... |
Line 179... |
// End of automatics
|
// End of automatics
|
end else if (ena_i & iwb_ack_i) begin
|
end else if (ena_i & iwb_ack_i) begin
|
{rOPC_IF, rRD_IF, rRA_IF, rIMM_IF} <= #1 iwb_dat_i;
|
{rOPC_IF, rRD_IF, rRA_IF, rIMM_IF} <= #1 iwb_dat_i;
|
end
|
end
|
|
|
always @(posedge clk_i)
|
/*
|
if (rst_i) begin
|
PC PIPELINE
|
|
|
|
This merely passes the PC down so that it is available during
|
|
branch instructions. This may be modified to use a shift register.
|
|
*/
|
|
|
|
always @(posedge clk_i) if (rst_i) begin
|
/*AUTORESET*/
|
/*AUTORESET*/
|
// Beginning of autoreset for uninitialized flops
|
// Beginning of autoreset for uninitialized flops
|
rPC_EX <= 30'h0;
|
rPC_EX <= 30'h0;
|
rPC_IF <= 30'h0;
|
rPC_IF <= 30'h0;
|
rPC_MA <= 30'h0;
|
rPC_MA <= 30'h0;
|
Line 189... |
Line 200... |
// TODO: Stuff inside a small LUT FIFO
|
// TODO: Stuff inside a small LUT FIFO
|
{rPC_MA, rPC_EX, rPC_OF, rPC_IF} <= #1 {rPC_EX, rPC_OF, rPC_IF, rPC};
|
{rPC_MA, rPC_EX, rPC_OF, rPC_IF} <= #1 {rPC_EX, rPC_OF, rPC_IF, rPC};
|
end
|
end
|
|
|
/* Branch Control */
|
/* Branch Control */
|
|
|
wire wRTD = (rOPC_OF == 6'o55);
|
wire wRTD = (rOPC_OF == 6'o55);
|
wire wBCC = (rOPC_OF == 6'o47) | (rOPC_OF == 6'o57);
|
wire wBCC = (rOPC_OF == 6'o47) | (rOPC_OF == 6'o57);
|
wire wBRU = (rOPC_OF == 6'o46) | (rOPC_OF == 6'o56);
|
wire wBRU = (rOPC_OF == 6'o46) | (rOPC_OF == 6'o56);
|
|
|
wire wBEQ = (rOPX_OF == 32'd0);
|
wire wBEQ = (rOPX_OF == 32'd0);
|
Line 201... |
Line 213... |
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_OF or wBEQ or wBGE or wBGT or wBLE
|
always @(/*AUTOSENSE*/rRD_OF or wBEQ or wBGE or wBGT or wBLE
|
or wBLT or wBNE)
|
or wBLT or wBNE)
|
case (rRD_OF[2:0])
|
case (rRD_OF[2:0])
|
3'o0: xXCC <= wBEQ;
|
3'o0: xXCC <= wBEQ;
|
3'o1: xXCC <= wBNE;
|
3'o1: xXCC <= wBNE;
|
Line 224... |
Line 237... |
end else if(ena_i) begin
|
end else if(ena_i) begin
|
rBRA[1] <= #1 wRTD | wBRU | (wBCC & xXCC);
|
rBRA[1] <= #1 wRTD | wBRU | (wBCC & xXCC);
|
rBRA[0] <= #1 (wBRU & rRA_OF[4]) | (wBCC & rRD_OF[4]) | wRTD;
|
rBRA[0] <= #1 (wBRU & rRA_OF[4]) | (wBCC & rRD_OF[4]) | wRTD;
|
end
|
end
|
|
|
// synopsys translate_off
|
|
integer r;
|
|
initial begin
|
|
for (r=0; r<TXE; r=r+1) begin
|
|
rPCL[r] <= $random;
|
|
end
|
|
end
|
|
|
|
// synopsys translate_on
|
|
|
|
endmodule // aeMB2_bpcu
|
endmodule // aeMB2_bpcu
|
|
|
/* $Log: not supported by cvs2svn $ */
|
|
No newline at end of file
|
No newline at end of file
|
|
/* $Log: not supported by cvs2svn $
|
|
/* Revision 1.1 2007/12/11 00:43:17 sybreon
|
|
/* initial import
|
|
/* */
|
No newline at end of file
|
No newline at end of file
|