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

Subversion Repositories aemb

[/] [aemb/] [branches/] [DEV_SYBREON/] [rtl/] [verilog/] [aeMB2_bpcu.v] - Blame information for rev 194

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 94 sybreon
/* $Id: aeMB2_bpcu.v,v 1.5 2007-12-21 22:39:38 sybreon Exp $
2 78 sybreon
**
3
** AEMB2 BRANCH/PROGRAMME COUNTER
4
**
5
** Copyright (C) 2004-2007 Shawn Tan Ser Ngiap <shawn.tan@aeste.net>
6
**
7
** This file is part of AEMB.
8
**
9
** AEMB is free software: you can redistribute it and/or modify it
10
** under the terms of the GNU Lesser General Public License as
11
** published by the Free Software Foundation, either version 3 of the
12
** License, or (at your option) any later version.
13
**
14
** AEMB is distributed in the hope that it will be useful, but WITHOUT
15
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
** or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
17
** Public License for more details.
18
**
19
** You should have received a copy of the GNU Lesser General Public
20
** License along with AEMB. If not, see <http://www.gnu.org/licenses/>.
21
*/
22
 
23
module aeMB2_bpcu (/*AUTOARG*/
24
   // Outputs
25 80 sybreon
   iwb_adr_o, rPC_MA, rPC_IF, rIMM_IF, rALT_IF, rOPC_IF, rRD_IF,
26
   rRA_IF, rRB_IF, rBRA,
27 78 sybreon
   // Inputs
28
   iwb_dat_i, iwb_ack_i, rOPX_OF, rOPC_OF, rRA_OF, rRD_OF, rRES_EX,
29 81 sybreon
   rRD_EX, rOPD_EX, clk_i, rst_i, ena_i, pha_i
30 78 sybreon
   );
31
   parameter IWB = 32;
32
   parameter TXE = 1;
33
 
34
   // IWB
35
   output [IWB-1:2] iwb_adr_o;
36
   input [31:0]     iwb_dat_i;
37
   input            iwb_ack_i;
38
 
39
   // PIPELINE
40 80 sybreon
   output [31:2]    //rPC_OF,
41 78 sybreon
                    rPC_MA,
42
                    rPC_IF;
43
   output [15:0]    rIMM_IF;
44
   output [10:0]    rALT_IF;
45
   output [5:0]     rOPC_IF;
46
   output [4:0]     rRD_IF,
47
                    rRA_IF,
48
                    rRB_IF;
49
 
50
   // BRANCH DETECTION
51 80 sybreon
   output [1:0]     rBRA; // {branch, delay}
52 78 sybreon
   input [31:0]     rOPX_OF; // BCC op test   
53
   input [5:0]       rOPC_OF;
54
   input [4:0]       rRA_OF,
55
                    rRD_OF;
56
   input [31:0]     rRES_EX;
57
 
58
   // MEMORY HAZARD DETECTION
59
   input [4:0]       rRD_EX; ///< RD
60
   input [2:0]       rOPD_EX; ///< data register source (ALU, MEM/FSL, PC)
61
 
62
   // SYSTEM
63
   input            clk_i,
64
                    rst_i,
65
                    ena_i,
66
                    pha_i;
67
 
68
   /*AUTOREG*/
69
   // Beginning of automatic regs (for this module's undeclared outputs)
70
   reg [1:0]             rBRA;
71
   reg [15:0]            rIMM_IF;
72
   reg [5:0]             rOPC_IF;
73
   reg [31:2]           rPC_IF;
74
   reg [31:2]           rPC_MA;
75
   reg [4:0]             rRA_IF;
76
   reg [4:0]             rRD_IF;
77
   // End of automatics
78
 
79
   /* Partial decoding */
80
   wire [5:0]            rOPC = rOPC_IF;
81
   wire [4:0]            rRA = rRA_IF;
82
   wire [4:0]            rRB = rRB_IF;
83
   wire                 fSFT = (rOPC == 6'o44);
84
   wire                 fLOG = ({rOPC[5:4],rOPC[2]} == 3'o4);
85
   wire                 fMUL = (rOPC == 6'o20) | (rOPC == 6'o30);
86
   wire                 fBSF = (rOPC == 6'o21) | (rOPC == 6'o31);
87
   wire                 fDIV = (rOPC == 6'o22);
88
   wire                 fRTD = (rOPC == 6'o55);
89
   wire                 fBCC = (rOPC == 6'o47) | (rOPC == 6'o57);
90
   wire                 fBRU = (rOPC == 6'o46) | (rOPC == 6'o56);
91
   wire                 fBRA = fBRU & rRA[3];
92
   wire                 fIMM = (rOPC == 6'o54);
93
   wire                 fMOV = (rOPC == 6'o45);
94
   wire                 fLOD = ({rOPC[5:4],rOPC[2]} == 3'o6);
95
   wire                 fSTR = ({rOPC[5:4],rOPC[2]} == 3'o7);
96
   wire                 fLDST = (rOPC[5:4] == 2'o3);
97
   wire                 fPUT = (rOPC == 6'o33) & rRB[4];
98
   wire                 fGET = (rOPC == 6'o33) & !rRB[4];
99
 
100
   /* Select the PC. */
101
 
102
   reg [31:2]           rPC, // PC
103 80 sybreon
                        rPC0, rPC1,// register based 
104
                        rPCL[0:1]; // LUT based
105 78 sybreon
 
106 91 sybreon
   wire [31:2]          wPCNXT = (pha_i | !TXE) ? rPC0 : rPC1;
107 78 sybreon
   wire [31:2]          wPCINC = (rPC + 1);
108
 
109
   /* Check for RW data hazard */
110
   // TODO: Optimise
111
 
112
   wire                 fLOAD = (rOPD_EX == 3'o2);
113
   wire                 fMULT = (rOPD_EX == 3'o3);
114
   wire                 fWRE = |rRD_EX;
115
   wire                 fOPBHZD = (rRB_IF == rRD_EX) & (fLOAD | fMULT) & !fMOV & !rOPC_IF[3] & fWRE;
116
   wire                 fOPAHZD = (rRA_IF == rRD_EX) & (fLOAD | fMULT) & !fBRU & fWRE;
117
   wire                 fOPDHZD = (rRD_IF == rRD_EX) & (fLOAD | fMULT) & fSTR & fWRE;
118 94 sybreon
   wire                 fHZD = (fOPBHZD | fOPAHZD | fOPDHZD) & !rBRA[1];
119 78 sybreon
 
120 80 sybreon
   /*
121
    IWB PC OUTPUT
122
 
123
    This is part of the address generation stage. It pre-selects the
124
    next PC to fetch depending on whether it's a branch, retry or
125
    normal. A retry happens during a special hazard */
126 78 sybreon
 
127 80 sybreon
   wire [1:0]            wIPCMX = {fHZD, rBRA[1]};
128 78 sybreon
   assign               iwb_adr_o = rPC[IWB-1:2];
129
 
130
   always @ (posedge clk_i)
131
     if (rst_i) begin
132
        rPC <= {(30){1'b1}};
133
        /*AUTORESET*/
134
     end else if (ena_i) begin
135
        case (wIPCMX)
136
          2'o0 : rPC <= #1 wPCNXT[IWB-1:2]; // normal
137
          2'o1 : rPC <= #1 rRES_EX[IWB-1:2]; // branch/return/break
138
          2'o2 : rPC <= #1 rPC_IF[IWB-1:2]; // retry/stall
139
          default: rPC <= {(IWB-2){1'bX}}; // undefined
140
        endcase // case (wIPCMX)
141
     end
142
 
143 80 sybreon
   /*
144
    PC INCREMENT
145
 
146
    This will store the next PC in a holding register until it is
147
    needed during the next AG stage. */
148
 
149 78 sybreon
   always @(posedge clk_i)
150
     if (rst_i) begin
151
        /*AUTORESET*/
152
        // Beginning of autoreset for uninitialized flops
153
        rPC0 <= 30'h0;
154
        rPC1 <= 30'h0;
155
        // End of automatics
156 81 sybreon
     end else if (ena_i) begin
157
        if (pha_i)
158
          rPC1 <= #1 wPCINC;
159
        else
160
          rPC0 <= #1 wPCINC;
161 78 sybreon
     end
162
 
163 80 sybreon
   /*
164
    INSTRUCTION LATCH
165
 
166
    This latches onto the instruction. It may not work correctly if
167
    there is a pipeline stall. */
168 78 sybreon
 
169
   reg [31:2]           rPC_OF, rPC_EX;
170
   assign               {rRB_IF, rALT_IF} = rIMM_IF;
171
 
172
   always @(posedge clk_i)
173
     if (rst_i) begin
174
        /*AUTORESET*/
175
        // Beginning of autoreset for uninitialized flops
176
        rIMM_IF <= 16'h0;
177
        rOPC_IF <= 6'h0;
178
        rRA_IF <= 5'h0;
179
        rRD_IF <= 5'h0;
180
        // End of automatics
181
     end else if (ena_i & iwb_ack_i) begin
182
        {rOPC_IF, rRD_IF, rRA_IF, rIMM_IF} <= #1 iwb_dat_i;
183
     end
184
 
185 80 sybreon
   /*
186
    PC PIPELINE
187
 
188
    This merely passes the PC down so that it is available during
189
    branch instructions. This may be modified to use a shift register.
190
    */
191
 
192
   always @(posedge clk_i) if (rst_i) begin
193 78 sybreon
        /*AUTORESET*/
194
        // Beginning of autoreset for uninitialized flops
195
        rPC_EX <= 30'h0;
196
        rPC_IF <= 30'h0;
197
        rPC_MA <= 30'h0;
198
        rPC_OF <= 30'h0;
199
        // End of automatics
200 80 sybreon
   end else if (ena_i) begin
201 78 sybreon
        // TODO: Stuff inside a small LUT FIFO
202
        {rPC_MA, rPC_EX, rPC_OF, rPC_IF} <= #1 {rPC_EX, rPC_OF, rPC_IF, rPC};
203 80 sybreon
   end
204 78 sybreon
 
205
   /* Branch Control */
206 80 sybreon
 
207 78 sybreon
   wire                 wRTD = (rOPC_OF == 6'o55);
208
   wire                 wBCC = (rOPC_OF == 6'o47) | (rOPC_OF == 6'o57);
209
   wire                 wBRU = (rOPC_OF == 6'o46) | (rOPC_OF == 6'o56);
210
 
211
   wire                 wBEQ = (rOPX_OF == 32'd0);
212
   wire                 wBNE = ~wBEQ;
213
   wire                 wBLT = rOPX_OF[31];
214
   wire                 wBLE = wBLT | wBEQ;
215
   wire                 wBGE = ~wBLT;
216
   wire                 wBGT = ~wBLE;
217
 
218 80 sybreon
   reg                  xXCC;
219
 
220 78 sybreon
   always @(/*AUTOSENSE*/rRD_OF or wBEQ or wBGE or wBGT or wBLE
221
            or wBLT or wBNE)
222
     case (rRD_OF[2:0])
223
       3'o0: xXCC <= wBEQ;
224
       3'o1: xXCC <= wBNE;
225
       3'o2: xXCC <= wBLT;
226
       3'o3: xXCC <= wBLE;
227
       3'o4: xXCC <= wBGT;
228
       3'o5: xXCC <= wBGE;
229
       default: xXCC <= 1'bX;
230
     endcase // case (rRD_OF[2:0])
231
 
232
   always @(posedge clk_i)
233
     if (rst_i) begin
234
        /*AUTORESET*/
235
        // Beginning of autoreset for uninitialized flops
236
        rBRA <= 2'h0;
237
        // End of automatics
238
     end else if(ena_i) begin
239
        rBRA[1] <= #1 wRTD | wBRU | (wBCC & xXCC);
240
        rBRA[0] <= #1 (wBRU & rRA_OF[4]) | (wBCC & rRD_OF[4]) | wRTD;
241
     end
242
 
243
endmodule // aeMB2_bpcu
244
 
245 80 sybreon
/* $Log: not supported by cvs2svn $
246 94 sybreon
/* Revision 1.4  2007/12/17 12:53:43  sybreon
247
/* Made idle thread PC track main PC.
248
/*
249 91 sybreon
/* Revision 1.3  2007/12/13 20:12:11  sybreon
250
/* Code cleanup + minor speed regression.
251
/*
252 81 sybreon
/* Revision 1.2  2007/12/12 19:16:59  sybreon
253
/* Minor optimisations (~10% faster)
254
/*
255 80 sybreon
/* Revision 1.1  2007/12/11 00:43:17  sybreon
256
/* initial import
257
/* */

powered by: WebSVN 2.1.0

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