OpenCores
URL https://opencores.org/ocsvn/aemb/aemb/trunk

Subversion Repositories aemb

[/] [aemb/] [branches/] [DEV_SYBREON/] [rtl/] [verilog/] [aeMB2_bpcu.v] - Diff between revs 115 and 191

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 115 Rev 191
/* $Id: aeMB2_bpcu.v,v 1.5 2007-12-21 22:39:38 sybreon Exp $
/* $Id: aeMB2_bpcu.v,v 1.5 2007-12-21 22:39:38 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>
**
**
** 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/>.
*/
*/
 
 
module aeMB2_bpcu (/*AUTOARG*/
module aeMB2_bpcu (/*AUTOARG*/
   // Outputs
   // Outputs
   iwb_adr_o, rPC_MA, rPC_IF, rIMM_IF, rALT_IF, rOPC_IF, rRD_IF,
   iwb_adr_o, rPC_MA, rPC_IF, rIMM_IF, rALT_IF, rOPC_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, clk_i, rst_i, ena_i, pha_i
   );
   );
   parameter IWB = 32;
   parameter IWB = 32;
   parameter TXE = 1;
   parameter TXE = 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;
 
 
   // 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            clk_i,
   input            clk_i,
                    rst_i,
                    rst_i,
                    ena_i,
                    ena_i,
                    pha_i;
                    pha_i;
 
 
   /*AUTOREG*/
   /*AUTOREG*/
   // Beginning of automatic regs (for this module's undeclared outputs)
   // Beginning of automatic regs (for this module's undeclared outputs)
   reg [1:0]             rBRA;
   reg [1:0]             rBRA;
   reg [15:0]            rIMM_IF;
   reg [15:0]            rIMM_IF;
   reg [5:0]             rOPC_IF;
   reg [5:0]             rOPC_IF;
   reg [31:2]           rPC_IF;
   reg [31:2]           rPC_IF;
   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);
   wire                 fLOG = ({rOPC[5:4],rOPC[2]} == 3'o4);
   wire                 fLOG = ({rOPC[5:4],rOPC[2]} == 3'o4);
   wire                 fMUL = (rOPC == 6'o20) | (rOPC == 6'o30);
   wire                 fMUL = (rOPC == 6'o20) | (rOPC == 6'o30);
   wire                 fBSF = (rOPC == 6'o21) | (rOPC == 6'o31);
   wire                 fBSF = (rOPC == 6'o21) | (rOPC == 6'o31);
   wire                 fDIV = (rOPC == 6'o22);
   wire                 fDIV = (rOPC == 6'o22);
   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                 fBRA = fBRU & rRA[3];
   wire                 fBRA = fBRU & rRA[3];
   wire                 fIMM = (rOPC == 6'o54);
   wire                 fIMM = (rOPC == 6'o54);
   wire                 fMOV = (rOPC == 6'o45);
   wire                 fMOV = (rOPC == 6'o45);
   wire                 fLOD = ({rOPC[5:4],rOPC[2]} == 3'o6);
   wire                 fLOD = ({rOPC[5:4],rOPC[2]} == 3'o6);
   wire                 fSTR = ({rOPC[5:4],rOPC[2]} == 3'o7);
   wire                 fSTR = ({rOPC[5:4],rOPC[2]} == 3'o7);
   wire                 fLDST = (rOPC[5:4] == 2'o3);
   wire                 fLDST = (rOPC[5:4] == 2'o3);
   wire                 fPUT = (rOPC == 6'o33) & rRB[4];
   wire                 fPUT = (rOPC == 6'o33) & rRB[4];
   wire                 fGET = (rOPC == 6'o33) & !rRB[4];
   wire                 fGET = (rOPC == 6'o33) & !rRB[4];
 
 
   /* 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:1]; // LUT based
                        rPCL[0:1]; // LUT based
 
 
   wire [31:2]          wPCNXT = (pha_i | !TXE) ? rPC0 : rPC1;
   wire [31:2]          wPCNXT = (pha_i | !TXE) ? rPC0 : rPC1;
   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
 
 
   wire                 fLOAD = (rOPD_EX == 3'o2);
   wire                 fLOAD = (rOPD_EX == 3'o2);
   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                 fHZD = (fOPBHZD | fOPAHZD | fOPDHZD) & !rBRA[1];
   wire                 fHZD = (fOPBHZD | fOPAHZD | fOPDHZD) & !rBRA[1];
 
 
   /*
   /*
    IWB PC OUTPUT
    IWB PC OUTPUT
 
 
    This is part of the address generation stage. It pre-selects the
    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
    next PC to fetch depending on whether it's a branch, retry or
    normal. A retry happens during a special hazard */
    normal. A retry happens during a special hazard */
 
 
   wire [1:0]            wIPCMX = {fHZD, 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}};
        /*AUTORESET*/
        /*AUTORESET*/
     end else if (ena_i) begin
     end else if (ena_i) begin
        case (wIPCMX)
        case (wIPCMX)
          2'o0 : rPC <= #1 wPCNXT[IWB-1:2]; // normal
          2'o0 : rPC <= #1 wPCNXT[IWB-1:2]; // normal
          2'o1 : rPC <= #1 rRES_EX[IWB-1:2]; // branch/return/break
          2'o1 : rPC <= #1 rRES_EX[IWB-1:2]; // branch/return/break
          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
 
 
   /*
   /*
    PC INCREMENT
    PC INCREMENT
 
 
    This will store the next PC in a holding register until it is
    This will store the next PC in a holding register until it is
    needed during the next AG stage. */
    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 if (ena_i) begin
        if (pha_i)
        if (pha_i)
          rPC1 <= #1 wPCINC;
          rPC1 <= #1 wPCINC;
        else
        else
          rPC0 <= #1 wPCINC;
          rPC0 <= #1 wPCINC;
     end
     end
 
 
   /*
   /*
    INSTRUCTION LATCH
    INSTRUCTION LATCH
 
 
    This latches onto the instruction. It may not work correctly if
    This latches onto the instruction. It may not work correctly if
    there is a pipeline stall. */
    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)
     if (rst_i) begin
     if (rst_i) begin
        /*AUTORESET*/
        /*AUTORESET*/
        // Beginning of autoreset for uninitialized flops
        // Beginning of autoreset for uninitialized flops
        rIMM_IF <= 16'h0;
        rIMM_IF <= 16'h0;
        rOPC_IF <= 6'h0;
        rOPC_IF <= 6'h0;
        rRA_IF <= 5'h0;
        rRA_IF <= 5'h0;
        rRD_IF <= 5'h0;
        rRD_IF <= 5'h0;
        // 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
 
 
   /*
   /*
    PC PIPELINE
    PC PIPELINE
 
 
    This merely passes the PC down so that it is available during
    This merely passes the PC down so that it is available during
    branch instructions. This may be modified to use a shift register.
    branch instructions. This may be modified to use a shift register.
    */
    */
 
 
   always @(posedge clk_i) if (rst_i) begin
   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;
        rPC_OF <= 30'h0;
        rPC_OF <= 30'h0;
        // End of automatics
        // End of automatics
   end else if (ena_i) begin
   end else if (ena_i) begin
        // 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);
   wire                 wBNE = ~wBEQ;
   wire                 wBNE = ~wBEQ;
   wire                 wBLT = rOPX_OF[31];
   wire                 wBLT = rOPX_OF[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_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;
       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_OF[2:0])
     endcase // case (rRD_OF[2:0])
 
 
   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
        rBRA <= 2'h0;
        rBRA <= 2'h0;
        // End of automatics
        // End of automatics
     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
 
 
endmodule // aeMB2_bpcu
endmodule // aeMB2_bpcu
 
 
/* $Log: not supported by cvs2svn $
/* $Log: not supported by cvs2svn $
/* Revision 1.4  2007/12/17 12:53:43  sybreon
/* Revision 1.4  2007/12/17 12:53:43  sybreon
/* Made idle thread PC track main PC.
/* Made idle thread PC track main PC.
/*
/*
/* Revision 1.3  2007/12/13 20:12:11  sybreon
/* Revision 1.3  2007/12/13 20:12:11  sybreon
/* Code cleanup + minor speed regression.
/* Code cleanup + minor speed regression.
/*
/*
/* Revision 1.2  2007/12/12 19:16:59  sybreon
/* Revision 1.2  2007/12/12 19:16:59  sybreon
/* Minor optimisations (~10% faster)
/* Minor optimisations (~10% faster)
/*
/*
/* Revision 1.1  2007/12/11 00:43:17  sybreon
/* Revision 1.1  2007/12/11 00:43:17  sybreon
/* initial import
/* initial import
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.