URL
https://opencores.org/ocsvn/aemb/aemb/trunk
Subversion Repositories aemb
[/] [aemb/] [branches/] [DEV_SYBREON/] [rtl/] [verilog/] [aeMB2_bpcu.v] - Rev 78
Go to most recent revision | Compare with Previous | Blame | View Log
/* $Id: aeMB2_bpcu.v,v 1.1 2007-12-11 00:43:17 sybreon Exp $ ** ** AEMB2 BRANCH/PROGRAMME COUNTER ** ** 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_bpcu (/*AUTOARG*/ // Outputs iwb_adr_o, rPC_OF, rPC_MA, rPC_IF, rIMM_IF, rALT_IF, rOPC_IF, rRD_IF, rRA_IF, rRB_IF, rBRA, // Inputs 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 ); parameter IWB = 32; parameter TXE = 1; parameter LUT = 1; // IWB output [IWB-1:2] iwb_adr_o; input [31:0] iwb_dat_i; input iwb_ack_i; // PIPELINE output [31:2] rPC_OF, rPC_MA, rPC_IF; output [15:0] rIMM_IF; output [10:0] rALT_IF; output [5:0] rOPC_IF; output [4:0] rRD_IF, rRA_IF, rRB_IF; // BRANCH DETECTION output [1:0] rBRA; ///< {branch, delay} input [31:0] rOPX_OF; // BCC op test input [5:0] rOPC_OF; input [4:0] rRA_OF, rRD_OF; input [31:0] rRES_EX; // MEMORY HAZARD DETECTION input [4:0] rRD_EX; ///< RD input [2:0] rOPD_EX; ///< data register source (ALU, MEM/FSL, PC) // SYSTEM input clk_i, rst_i, ena_i, pha_i; /*AUTOREG*/ // Beginning of automatic regs (for this module's undeclared outputs) reg [1:0] rBRA; reg [15:0] rIMM_IF; reg [5:0] rOPC_IF; reg [31:2] rPC_IF; reg [31:2] rPC_MA; reg [4:0] rRA_IF; reg [4:0] rRD_IF; // End of automatics /* Partial decoding */ wire [5:0] rOPC = rOPC_IF; wire [4:0] rRA = rRA_IF; wire [4:0] rRB = rRB_IF; 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] == 2'o3); wire fPUT = (rOPC == 6'o33) & rRB[4]; wire fGET = (rOPC == 6'o33) & !rRB[4]; /* Select the PC. */ reg [31:2] rPC, // PC rPC0, rPC1, // register based rPCL[0:TXE]; // LUT based wire [31:2] wPCSEL = (pha_i) ? rPC0 : (TXE) ? rPC1 : 30'hX; wire [31:2] wPCNXT = (LUT) ? rPCL[!pha_i] : wPCSEL; wire [31:2] wPCINC = (rPC + 1); /* Check for RW data hazard */ // TODO: Optimise wire fLOAD = (rOPD_EX == 3'o2); wire fMULT = (rOPD_EX == 3'o3); wire fWRE = |rRD_EX; wire fOPBHZD = (rRB_IF == rRD_EX) & (fLOAD | fMULT) & !fMOV & !rOPC_IF[3] & fWRE; wire fOPAHZD = (rRA_IF == rRD_EX) & (fLOAD | fMULT) & !fBRU & fWRE; wire fOPDHZD = (rRD_IF == rRD_EX) & (fLOAD | fMULT) & fSTR & fWRE; wire fHAZARD = fOPBHZD | fOPAHZD | fOPDHZD; /* Output the new PC for IWB */ wire [1:0] wIPCMX = {fHAZARD, rBRA[1]}; assign iwb_adr_o = rPC[IWB-1:2]; always @ (posedge clk_i) if (rst_i) begin rPC <= {(30){1'b1}}; /*AUTORESET*/ end else if (ena_i) begin case (wIPCMX) 2'o0 : rPC <= #1 wPCNXT[IWB-1:2]; // normal 2'o1 : rPC <= #1 rRES_EX[IWB-1:2]; // branch/return/break 2'o2 : rPC <= #1 rPC_IF[IWB-1:2]; // retry/stall default: rPC <= {(IWB-2){1'bX}}; // undefined endcase // case (wIPCMX) end /* Inbcrement the PC */ always @(posedge clk_i) if (rst_i) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rPC0 <= 30'h0; rPC1 <= 30'h0; // End of automatics end else if (ena_i) begin if (pha_i) rPC1 <= #1 wPCINC; else rPC0 <= #1 wPCINC; end always @(posedge clk_i) if (ena_i | rst_i) begin rPCL[pha_i] <= #1 wPCINC; end /* Latch onto instruction word */ reg [31:2] rPC_OF, rPC_EX; assign {rRB_IF, rALT_IF} = rIMM_IF; always @(posedge clk_i) if (rst_i) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rIMM_IF <= 16'h0; rOPC_IF <= 6'h0; rRA_IF <= 5'h0; rRD_IF <= 5'h0; // End of automatics end else if (ena_i & iwb_ack_i) begin {rOPC_IF, rRD_IF, rRA_IF, rIMM_IF} <= #1 iwb_dat_i; end always @(posedge clk_i) if (rst_i) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rPC_EX <= 30'h0; rPC_IF <= 30'h0; rPC_MA <= 30'h0; rPC_OF <= 30'h0; // End of automatics end else if (ena_i) begin // TODO: Stuff inside a small LUT FIFO {rPC_MA, rPC_EX, rPC_OF, rPC_IF} <= #1 {rPC_EX, rPC_OF, rPC_IF, rPC}; end /* Branch Control */ wire wRTD = (rOPC_OF == 6'o55); wire wBCC = (rOPC_OF == 6'o47) | (rOPC_OF == 6'o57); wire wBRU = (rOPC_OF == 6'o46) | (rOPC_OF == 6'o56); wire wBEQ = (rOPX_OF == 32'd0); wire wBNE = ~wBEQ; wire wBLT = rOPX_OF[31]; wire wBLE = wBLT | wBEQ; wire wBGE = ~wBLT; wire wBGT = ~wBLE; reg xXCC; always @(/*AUTOSENSE*/rRD_OF or wBEQ or wBGE or wBGT or wBLE or wBLT or wBNE) case (rRD_OF[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_OF[2:0]) always @(posedge clk_i) if (rst_i) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rBRA <= 2'h0; // End of automatics end else if(ena_i) begin rBRA[1] <= #1 wRTD | wBRU | (wBCC & xXCC); rBRA[0] <= #1 (wBRU & rRA_OF[4]) | (wBCC & rRD_OF[4]) | wRTD; 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 /* $Log: not supported by cvs2svn $ */
Go to most recent revision | Compare with Previous | Blame | View Log