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

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Hardware/] [MIPS32_Standalone/] [CPZero.v] - Blame information for rev 9

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

Line No. Rev Author Line
1 2 ayersg
`timescale 1ns / 1ps
2
/*
3
 * File         : CPZero.v
4
 * Project      : University of Utah, XUM Project MIPS32 core
5
 * Creator(s)   : Grant Ayers (ayers@cs.utah.edu)
6
 *
7
 * Modification History:
8
 *   Rev   Date         Initials  Description of Change
9
 *   1.0   16-Sep-2011  GEA       Initial design.
10
 *   2.0   14-May-2012  GEA       Complete rework.
11
 *
12
 * Standards/Formatting:
13
 *   Verilog 2001, 4 soft tab, wide column.
14
 *
15
 * Description:
16
 *   The MIPS-32 Coprocessor 0 (CP0). This is the processor management unit that allows
17
 *   interrupts, traps, system calls, and other exceptions. It distinguishes
18
 *   user and kernel modes, provides status information, and can override program
19
 *   flow. This processor is designed for "bare metal" memory access and thus does
20
 *   not have virtual memory hardware as a part of it. However, the subset of CP0
21
 *   is MIPS-32-compliant.
22
 */
23
module CPZero(
24 3 ayersg
    input  clock,
25
    //-- CP0 Functionality --//
26 2 ayersg
    input  Mfc0,                    // CPU instruction is Mfc0
27 3 ayersg
    input  Mtc0,                    // CPU instruction is Mtc0
28 2 ayersg
    input  IF_Stall,
29
    input  ID_Stall,                // Commits are not made during stalls
30 3 ayersg
    input  COP1,                    // Instruction for Coprocessor 1
31
    input  COP2,                    // Instruction for Coprocessor 2
32
    input  COP3,                    // Instruction for Coprocessor 3
33 2 ayersg
    input  ERET,                    // Instruction is ERET (Exception Return)
34 3 ayersg
    input  [4:0] Rd,                // Specifies Cp0 register
35
    input  [2:0] Sel,               // Specifies Cp0 'select'
36
    input  [31:0] Reg_In,           // Data from GP register to replace CP0 register
37 2 ayersg
    output reg [31:0] Reg_Out,      // Data from CP0 register for GP register
38
    output KernelMode,              // Kernel mode indicator for pipeline transit
39
    output ReverseEndian,           // Reverse Endian memory indicator for User Mode
40 3 ayersg
    //-- Hw Interrupts --//
41
    input  [4:0] Int,               // Five hardware interrupts external to the processor
42
    //-- Exceptions --//
43
    input  reset,                   // Cold Reset (EXC_Reset)
44 2 ayersg
//  input  EXC_SReset,              // Soft Reset (not implemented)
45 3 ayersg
    input  EXC_NMI,                 // Non-Maskable Interrupt
46 2 ayersg
    input  EXC_AdIF,                // Address Error Exception from i-fetch (mapped to AdEL)
47 3 ayersg
    input  EXC_AdEL,                // Address Error Exception from data memory load
48
    input  EXC_AdES,                // Address Error Exception from data memory store
49
    input  EXC_Ov,                  // Integer Overflow Exception
50
    input  EXC_Tr,                  // Trap Exception
51
    input  EXC_Sys,                 // System Call Exception
52
    input  EXC_Bp,                  // Breakpoint Exception
53
    input  EXC_RI,                  // Reserved Instruction Exception
54
    //-- Exception Data --//
55 2 ayersg
    input  [31:0] ID_RestartPC,     // PC for exception, whether PC of instruction or of branch (PC-4) if BDS
56
    input  [31:0] EX_RestartPC,     // Same as 'ID_RestartPC' but in EX stage
57
    input  [31:0] M_RestartPC,      // Same as 'ID_RestartPC' but in MEM stage
58
    input  ID_IsFlushed,
59
    input  IF_IsBD,                 // Indicator of IF exception being a branch delay slot instruction
60
    input  ID_IsBD,                 // Indicator of ID exception being a branch delay slot instruction
61
    input  EX_IsBD,                 // Indicator of EX exception being a branch delay slot instruction
62
    input  M_IsBD,                  // Indicator of M  exception being a branch delay slot instruction
63 3 ayersg
    input  [31:0] BadAddr_M,        // Bad 'Virtual' Address for exceptions AdEL, AdES in MEM stage
64 2 ayersg
    input  [31:0] BadAddr_IF,       // Bad 'Virtual' Address for AdIF (i.e. AdEL) in IF stage
65
    input  ID_CanErr,               // Cumulative signal, i.e. (ID_ID_CanErr | ID_EX_CanErr | ID_M_CanErr)
66
    input  EX_CanErr,               // Cumulative signal, i.e. (EX_EX_CanErr | EX_M_CanErr)
67
    input  M_CanErr,                // Memory stage can error (i.e. cause exception)
68
    //-- Exception Control Flow --/
69
    output IF_Exception_Stall,
70
    output ID_Exception_Stall,
71
    output EX_Exception_Stall,
72
    output M_Exception_Stall,
73
    output IF_Exception_Flush,
74
    output ID_Exception_Flush,
75
    output EX_Exception_Flush,
76
    output M_Exception_Flush,
77
    output Exc_PC_Sel,              // Mux selector for exception PC override
78
    output reg [31:0] Exc_PC_Out,   // Address for PC at the beginning of an exception
79
    output [7:0] IP                 // Pending Interrupts from Cause register (for diagnostic purposes)
80 3 ayersg
    );
81 2 ayersg
 
82 3 ayersg
    `include "MIPS_Parameters.v"
83 2 ayersg
 
84
 
85
    /***
86
     Exception Control Flow Notes
87
 
88
     - Exceptions can occur in every pipeline stage. This implies that more than one exception
89
       can be raised in a single cycle. When this occurs, only the forward-most exception
90
       (i.e. MEM over EX) is handled. This and the following note guarantee program order.
91
 
92
     - An exception in any pipeline stage must stall that stage until all following stages are
93
       exception-free. This is because it only makes sense for exceptions to occur in program order.
94
 
95
     - A pipeline stage which causes an exception must flush, i.e. prevent any commits it would
96
       have normally made and convert itself to a NOP for the next pipeline stage. Furthermore,
97
       it must flush all previous pipeline stages as well in order to retain program order.
98
 
99
     - Instructions reading CP0 (mtc0) read in ID without further action. Writes to CP0 (mtc0,
100
       eret) also write in ID, but only after forward pipeline stages have been cleared
101
       of possible exceptions. This prevents many insidious bugs, such as switching to User Mode
102
       in ID when a legitimate memory access in kernel mode is processing in MEM, or conversely
103
       a switch to Kernel Mode in ID when an instruction in User Mode is attempting a kernel region
104
       memory access (when a kernel mode signal does not propagate through the pipeline).
105
 
106
     - Commits occur in ID (CP0), EX (HILO), MEM, and WB (registers).
107
 
108
     - Hardware interrupts are detected and inserted in the ID stage, but only when there are no
109
       other possible exceptions in the pipeline. Because they appear 'asynchronous' to the
110
       processor, the remaining instructions in forward stages (EX, MEM, WB) can either be
111
       flushed or completed. It is simplest to have them complete to avoid restarts, but the
112
       interrupt latency is higher if e.g. the MEM stage stalls on a memory access (this would
113
       be unavoidable on single-cycle processors). This implementation allows all forward instructions
114
       to complete, for a greater instruction throughput but higher interrupt latency.
115
 
116
     - Software interrupts should appear synchronous in the program order, meaning that all
117
       instructions previous to them should complete and no instructions after them should start
118
       until the interrupts has been processed.
119
 
120
     Exception Name             Short Name          Pipeline Stage
121 3 ayersg
       Address Error Ex         (AdEL, AdES)        MEM, IF
122
       Integer Overflow Ex      (Ov)                EX
123
       Trap Ex                  (Tr)                MEM
124
       Syscall                  (Sys)               ID
125
       Breakpoint               (Bp)                ID
126
       Reserved Instruction     (RI)                ID
127
       Coprocessor Unusable     (CpU)               ID
128
       Interrupt                (Int)               ID
129
       Reset, SReset, NMI                           ID
130 2 ayersg
    ***/
131 3 ayersg
 
132
 
133 2 ayersg
    // Exceptions Generated Internally
134
    wire EXC_CpU;
135
 
136
    // Hardware Interrupt #5, caused by Timer/Perf counter
137
    wire Int5;
138
 
139
    // Top-level Authoritative Interrupt Signal
140
    wire EXC_Int;
141
 
142
    // General Exception detection (all but Interrupts, Reset, Soft Reset, and NMI)
143
    wire EXC_General = EXC_AdIF | EXC_AdEL | EXC_AdES | EXC_Ov | EXC_Tr | EXC_Sys | EXC_Bp | EXC_RI | EXC_CpU;
144
 
145
    // Misc
146
    wire CP0_WriteCond;
147
    reg  [3:0] Cause_ExcCode_bits;
148
 
149
    reg reset_r;
150
    always @(posedge clock) begin
151
        reset_r <= reset;
152
    end
153
 
154
    /***
155
     MIPS-32 COPROCESSOR 0 (Cp0) REGISTERS
156
 
157
     These are defined in "MIPS32 Architecture for Programmers Volume III:
158
     The MIPS32 Privileged Resource Architecture" from MIPS Technologies, Inc.
159
 
160
     Optional registers are omitted. Changes to the processor (such as adding
161
     an MMU/TLB, etc. must be reflected in these registers.
162
    */
163
 
164
    // BadVAddr Register (Register 8, Select 0)
165
    reg [31:0] BadVAddr;
166
 
167
    // Count Register (Register 9, Select 0)
168
    reg [31:0] Count;
169
 
170
    // Compare Register (Register 11, Select 0)
171
    reg [31:0] Compare;
172
 
173
    // Status Register (Register 12, Select 0)
174
    wire [2:0] Status_CU_321 = 3'b000;
175
    reg  Status_CU_0;       // Access Control to CPs, [2]->Cp3, ... [0]->Cp0
176
    wire Status_RP = 0;
177
    wire Status_FR = 0;
178
    reg  Status_RE;         // Reverse Endian Memory for User Mode
179
    wire Status_MX = 0;
180
    wire Status_PX = 0;
181 3 ayersg
    reg  Status_BEV;        // Exception vector locations (0->Norm, 1->Bootstrap)
182 2 ayersg
    wire Status_TS = 0;
183 3 ayersg
    wire Status_SR = 0;     // Soft reset not implemented
184 2 ayersg
    reg  Status_NMI;        // Non-Maskable Interrupt
185
    wire Status_RES = 0;
186
    wire [1:0] Status_Custom = 2'b00;
187
    reg [7:0] Status_IM;    // Interrupt mask
188
    wire Status_KX = 0;
189
    wire Status_SX = 0;
190
    wire Status_UX = 0;
191 3 ayersg
    reg  Status_UM;         // Base operating mode (0->Kernel, 1->User)
192 2 ayersg
    wire Status_R0 = 0;
193 3 ayersg
    reg  Status_ERL;        // Error Level     (0->Normal, 1->Error (reset, NMI))
194 2 ayersg
    reg  Status_EXL;        // Exception level (0->Normal, 1->Exception)
195
    reg  Status_IE;         // Interrupt Enable
196
    wire [31:0] Status = {Status_CU_321, Status_CU_0, Status_RP, Status_FR, Status_RE, Status_MX,
197
                                 Status_PX, Status_BEV, Status_TS, Status_SR, Status_NMI, Status_RES,
198
                                 Status_Custom, Status_IM, Status_KX, Status_SX, Status_UX,
199
                                 Status_UM, Status_R0, Status_ERL, Status_EXL, Status_IE};
200
 
201
    // Cause Register (Register 13, Select 0)
202 3 ayersg
    reg  Cause_BD;                  // Exception occured in Branch Delay
203
    reg  [1:0] Cause_CE;            // CP number for CP Unusable exception
204
    reg  Cause_IV;                  // Indicator of general IV (0->0x180) or special IV (1->0x200)
205 2 ayersg
    wire Cause_WP = 0;
206 3 ayersg
    reg  [7:0] Cause_IP;            // Pending HW Interrupt indicator.
207 2 ayersg
    wire Cause_ExcCode4 = 0;        // Can be made into a register when this bit is needed.
208
    reg  [3:0] Cause_ExcCode30;     // Description of Exception (only lower 4 bits currently used; see above)
209
    wire [31:0] Cause  = {Cause_BD, 1'b0, Cause_CE, 4'b0000, Cause_IV, Cause_WP,
210
                                 6'b000000, Cause_IP, 1'b0, Cause_ExcCode4, Cause_ExcCode30, 2'b00};
211
 
212
    // Exception Program Counter (Register 14, Select 0)
213
    reg [31:0] EPC;
214
 
215
    // Processor Identification (Register 15, Select 0)
216
    wire [7:0] ID_Options = 8'b0000_0000;
217
    wire [7:0] ID_CID = 8'b0000_0000;
218
    wire [7:0] ID_PID = 8'b0000_0000;
219
    wire [7:0] ID_Rev = 8'b0000_0001;
220
    wire [31:0] PRId = {ID_Options, ID_CID, ID_PID, ID_Rev};
221
 
222
    // Configuration Register (Register 16, Select 0)
223
    wire Config_M = 1;
224
    wire [14:0] Config_Impl = 15'b000_0000_0000_0000;
225 3 ayersg
    wire Config_BE = Big_Endian;    // From parameters file
226 2 ayersg
    wire [1:0] Config_AT = 2'b00;
227
    wire [2:0] Config_AR = 3'b000;
228
    wire [2:0] Config_MT = 3'b000;
229
    wire [2:0] Config_K0 = 3'b000;
230
    wire [31:0] Config = {Config_M, Config_Impl, Config_BE, Config_AT, Config_AR, Config_MT,
231
                                 4'b0000, Config_K0};
232
 
233
    // Configuration Register 1 (Register 16, Select 1)
234
    wire Config1_M = 0;
235
    wire [5:0] Config1_MMU = 6'b000000;
236
    wire [2:0] Config1_IS = 3'b000;
237
    wire [2:0] Config1_IL = 3'b000;
238
    wire [2:0] Config1_IA = 3'b000;
239
    wire [2:0] Config1_DS = 3'b000;
240
    wire [2:0] Config1_DL = 3'b000;
241
    wire [2:0] Config1_DA = 3'b000;
242
    wire Config1_C2 = 0;
243
    wire Config1_MD = 0;
244 3 ayersg
    wire Config1_PC = 0;    // XXX Performance Counters
245
    wire Config1_WR = 0;    // XXX Watch Registers
246 2 ayersg
    wire Config1_CA = 0;
247
    wire Config1_EP = 0;
248
    wire Config1_FP = 0;
249
    wire [31:0] Config1 = {Config1_M, Config1_MMU, Config1_IS, Config1_IL, Config1_IA,
250
                                  Config1_DS, Config1_DL, Config1_DA, Config1_C2,
251
                                  Config1_MD, Config1_PC, Config1_WR, Config1_CA,
252
                                  Config1_EP, Config1_FP};
253
 
254
    // Performance Counter Register (Register 25) XXX TODO
255
 
256
    // ErrorEPC Register (Register 30, Select 0)
257
    reg [31:0] ErrorEPC;
258
 
259
    // Exception Detection and Processing
260
    wire M_Exception_Detect, EX_Exception_Detect, ID_Exception_Detect, IF_Exception_Detect;
261
    wire M_Exception_Mask, EX_Exception_Mask, ID_Exception_Mask, IF_Exception_Mask;
262
    wire M_Exception_Ready, EX_Exception_Ready, ID_Exception_Ready, IF_Exception_Ready;
263
 
264
    assign IP = Cause_IP;
265
 
266
    /*** Coprocessor Unusable Exception ***/
267
    assign EXC_CpU = COP1 | COP2 | COP3 | ((Mtc0 | Mfc0 | ERET) & ~(Status_CU_0 | KernelMode));
268
 
269
    /*** Kernel Mode Signal ***/
270
    assign KernelMode = ~Status_UM | Status_EXL | Status_ERL;
271
 
272
    /*** Reverse Endian for User Mode ***/
273
    assign ReverseEndian = Status_RE;
274
 
275
    /*** Interrupts ***/
276
    assign Int5 = (Count == Compare);
277
    //assign EXC_Int = ((Cause_IP[7:0] & Status_IM[7:0]) != 8'h00) & Status_IE & ~Status_EXL & ~Status_ERL & ~ID_IsFlushed;
278
    wire   Enabled_Interrupt = EXC_NMI | (Status_IE & ((Cause_IP[7:0] & Status_IM[7:0]) != 8'h00));
279
    assign EXC_Int = Enabled_Interrupt & ~Status_EXL & ~Status_ERL & ~ID_IsFlushed;
280
 
281
    assign CP0_WriteCond = (Status_CU_0 | KernelMode) & Mtc0 & ~ID_Stall;
282
 
283
 
284
    /***
285
     Exception Hazard Flow Control Explanation:
286
        - An exception at any time in any stage causes its own and any previous stages to
287
          flush (clear own commits, NOPS to fwd stages).
288
        - An exception in a stage can also stall that stage (and inherently all previous stages) if and only if:
289
            1. A forward stage is capable of causing an exception AND
290
            2. A forward stage is not currently causing an exception.
291
        - An exception is ready to process when it is detected and not stalled in a stage.
292
 
293
        Flush specifics per pipeline stage:
294
            MEM: Mask 'MemWrite' and 'MemRead' (for performance) after EX/M and before data memory. NOPs to M/WB.
295
            EX : Mask writes to HI/LO. NOPs to EX/M.
296
            ID : Mask writes (reads?) to CP0. NOPs to ID/EX.
297
            IF : NOP to IF/ID.
298
    ***/
299
 
300
    /*** Exceptions grouped by pipeline stage ***/
301
    assign   M_Exception_Detect = EXC_AdEL | EXC_AdES | EXC_Tr;
302
    assign  EX_Exception_Detect = EXC_Ov;
303
    assign  ID_Exception_Detect = EXC_Sys | EXC_Bp | EXC_RI | EXC_CpU | EXC_Int;
304
    assign  IF_Exception_Detect = EXC_AdIF;
305
 
306
    /*** Exception mask conditions ***/
307
 
308
    // A potential bug would occur if e.g. EX stalls, MEM has data, but MEM is not stalled and finishes
309
    // going through the pipeline so forwarding would fail. This is not a problem however because 
310
    // EX would not need data since it would flush on an exception.
311
    assign   M_Exception_Mask = IF_Stall;
312
    assign  EX_Exception_Mask = IF_Stall | M_CanErr;
313
    assign  ID_Exception_Mask = IF_Stall | M_CanErr | EX_CanErr;
314
    assign  IF_Exception_Mask = M_CanErr | EX_CanErr | ID_CanErr | EXC_Int;
315
 
316
    /***
317
     Exceptions which must wait for forward stages. A stage will not stall if a forward stage has an exception.
318
     These stalls must be inserted as stall conditions in the hazard unit so that it will take care of chaining.
319
     All writes to CP0 must also wait for forward hazard conditions to clear.
320
    */
321
    assign  M_Exception_Stall  =  M_Exception_Detect  & M_Exception_Mask;
322
    assign  EX_Exception_Stall =  EX_Exception_Detect & EX_Exception_Mask & ~M_Exception_Detect;
323
    assign  ID_Exception_Stall = (ID_Exception_Detect | ERET | Mtc0) & ID_Exception_Mask & ~(EX_Exception_Detect | M_Exception_Detect);
324
    assign  IF_Exception_Stall =  IF_Exception_Detect & IF_Exception_Mask & ~(ID_Exception_Detect | EX_Exception_Detect | M_Exception_Detect);
325
 
326
 
327
    /*** Exceptions which are ready to process (mutually exclusive) ***/
328
    // XXX can remove ~ID_Stall since in mask now (?)
329
    assign   M_Exception_Ready =  ~ID_Stall & M_Exception_Detect  & ~M_Exception_Mask;
330
    assign  EX_Exception_Ready =  ~ID_Stall & EX_Exception_Detect & ~EX_Exception_Mask;
331
    assign  ID_Exception_Ready =  ~ID_Stall & ID_Exception_Detect & ~ID_Exception_Mask;
332
    assign  IF_Exception_Ready =  ~ID_Stall & IF_Exception_Detect & ~IF_Exception_Mask;
333
 
334
    /***
335
     Flushes. A flush clears a pipeline stage's control signals and prevents the stage from committing any changes.
336
     Data such as 'RestartPC' and the detected exception must remain.
337
    */
338
    assign   M_Exception_Flush = M_Exception_Detect;
339
    assign  EX_Exception_Flush = M_Exception_Detect | EX_Exception_Detect;
340
    assign  ID_Exception_Flush = M_Exception_Detect | EX_Exception_Detect | ID_Exception_Detect;
341
    assign  IF_Exception_Flush = M_Exception_Detect | EX_Exception_Detect | ID_Exception_Detect | IF_Exception_Detect | (ERET & ~ID_Stall) | reset_r;
342
 
343
 
344
    /*** Software reads of CP0 Registers ***/
345
    always @(*) begin
346
        if (Mfc0 & (Status_CU_0 | KernelMode)) begin
347
            case (Rd)
348
                5'd8  : Reg_Out <= BadVAddr;
349
                5'd9  : Reg_Out <= Count;
350
                5'd11 : Reg_Out <= Compare;
351
                5'd12 : Reg_Out <= Status;
352
                5'd13 : Reg_Out <= Cause;
353
                5'd14 : Reg_Out <= EPC;
354
                5'd15 : Reg_Out <= PRId;
355
                5'd16 : Reg_Out <= (Sel == 3'b000) ? Config : Config1;
356
                5'd30 : Reg_Out <= ErrorEPC;
357
                default : Reg_Out <= 32'h0000_0000;
358
            endcase
359
        end
360
        else begin
361
            Reg_Out <= 32'h0000_0000;
362
        end
363
    end
364
 
365
    /*** Cp0 Register Assignments: Non-general exceptions (Reset, Soft Reset, NMI...) ***/
366
    always @(posedge clock) begin
367
        if (reset) begin
368
            Status_BEV <= 1;
369
            Status_NMI <= 0;
370
            Status_ERL <= 1;
371
            ErrorEPC   <= 32'b0;
372
        end
373
        else if (ID_Exception_Ready & EXC_NMI) begin
374
            Status_BEV <= 1;
375
            Status_NMI <= 1;
376
            Status_ERL <= 1;
377
            ErrorEPC   <= ID_RestartPC;
378
        end
379
        else begin
380
            Status_BEV    <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[22]   : Status_BEV;
381
            Status_NMI    <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[19]   : Status_NMI;
382
            Status_ERL    <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[2]    : ((Status_ERL & ERET & ~ID_Stall) ? 0 : Status_ERL);
383
            ErrorEPC      <= (CP0_WriteCond & (Rd == 5'd30) & (Sel == 3'b000)) ? Reg_In       : ErrorEPC;
384
        end
385
    end
386
 
387
    /*** Cp0 Register Assignments: All other registers ***/
388
    always @(posedge clock) begin
389
        if (reset) begin
390
            Count         <= 32'b0;
391
            Compare       <= 32'b0;
392
            Status_CU_0   <= 0;
393
            Status_RE     <= 0;
394
            Status_IM     <= 8'b0;
395
            Status_UM     <= 0;
396
            Status_IE     <= 0;
397
            Cause_IV      <= 0;
398
            Cause_IP      <= 8'b0;
399
        end
400
        else begin
401
            Count         <= (CP0_WriteCond & (Rd == 5'd9 ) & (Sel == 3'b000)) ? Reg_In       : ((Count == Compare) ? 32'b0 : Count + 1);
402
            Compare       <= (CP0_WriteCond & (Rd == 5'd11) & (Sel == 3'b000)) ? Reg_In       : Compare;
403
            Status_CU_0   <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[28]   : Status_CU_0;
404
            Status_RE     <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[25]   : Status_RE;
405
            Status_IM     <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[15:8] : Status_IM;
406
            Status_UM     <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[4]    : Status_UM;
407
            Status_IE     <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[0]    : Status_IE;
408
            Cause_IV      <= (CP0_WriteCond & (Rd == 5'd13) & (Sel == 3'b000)) ? Reg_In[23]   : Cause_IV;
409
            /* Cause_IP indicates 8 interrupts:
410
               [7]   is set by the timer comparison, and cleared by reading 'Count'.
411
               [6:2] are set and cleared by external hardware.
412
               [1:0] are set and cleared by software.
413
             */
414
            // If reading -> 0, Otherwise if 0 -> Int5.
415
            Cause_IP[7]   <= ((Status_CU_0 | KernelMode) & Mfc0 & (Rd == 5'd9) & (Sel == 3'b000)) ? 0 : ((Cause_IP[7] == 0) ? Int5 : Cause_IP[7]);
416
            Cause_IP[6:2] <= Int[4:0];
417
            Cause_IP[1:0] <= (CP0_WriteCond & (Rd == 5'd13) & (Sel == 3'b000)) ? Reg_In[9:8]  : Cause_IP[1:0];
418
        end
419
    end
420
 
421
    /*** Cp0 Register Assignments: General Exception and Interrupt Processing ***/
422
    always @(posedge clock) begin
423
        if (reset) begin
424
            Cause_BD <= 0;
425
            Cause_CE <= 2'b00;
426
            Cause_ExcCode30 <= 4'b0000;
427
            Status_EXL <= 0;
428
            EPC <= 32'h0;
429
            BadVAddr <= 32'h0;
430
        end
431
        else begin
432
            // MEM stage
433
            if (M_Exception_Ready) begin
434
                Cause_BD <= (Status_EXL) ? Cause_BD : M_IsBD;
435
                Cause_CE <= (COP3) ? 2'b11 : ((COP2) ? 2'b10 : ((COP1) ? 2'b01 : 2'b00));
436
                Cause_ExcCode30 <= Cause_ExcCode_bits;
437
                Status_EXL <= 1;
438
                EPC <= (Status_EXL) ? EPC : M_RestartPC;
439
                BadVAddr <= BadAddr_M;
440
            end
441
            // EX stage
442
            else if (EX_Exception_Ready) begin
443
                Cause_BD <= (Status_EXL) ? Cause_BD : EX_IsBD;
444
                Cause_CE <= (COP3) ? 2'b11 : ((COP2) ? 2'b10 : ((COP1) ? 2'b01 : 2'b00));
445
                Cause_ExcCode30 <= Cause_ExcCode_bits;
446
                Status_EXL <= 1;
447
                EPC <= (Status_EXL) ? EPC : EX_RestartPC;
448
                BadVAddr <= BadVAddr;
449
            end
450
            // ID stage
451
            else if (ID_Exception_Ready) begin
452
                Cause_BD <= (Status_EXL) ? Cause_BD : ID_IsBD;
453
                Cause_CE <= (COP3) ? 2'b11 : ((COP2) ? 2'b10 : ((COP1) ? 2'b01 : 2'b00));
454
                Cause_ExcCode30 <= Cause_ExcCode_bits;
455
                Status_EXL <= 1;
456
                EPC <= (Status_EXL) ? EPC : ID_RestartPC;
457
                BadVAddr <= BadVAddr;
458
            end
459
            // IF stage
460
            else if (IF_Exception_Ready) begin
461
                Cause_BD <= (Status_EXL) ? Cause_BD : IF_IsBD;
462
                Cause_CE <= (COP3) ? 2'b11 : ((COP2) ? 2'b10 : ((COP1) ? 2'b01 : 2'b00));
463
                Cause_ExcCode30 <= Cause_ExcCode_bits;
464
                Status_EXL <= 1;
465
                EPC <= (Status_EXL) ? EPC : BadAddr_IF;
466
                BadVAddr <= BadAddr_IF;
467
            end
468
            // No exceptions this cycle
469
            else begin
470
                Cause_BD <= 1'b0;
471
                Cause_CE <= Cause_CE;
472
                Cause_ExcCode30 <= Cause_ExcCode30;
473
                // Without new exceptions, 'Status_EXL' is set by software or cleared by ERET.
474
                Status_EXL <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[1] : ((Status_EXL & ERET & ~ID_Stall) ? 0 : Status_EXL);
475
                // The EPC is also writable by software
476
                EPC <= (CP0_WriteCond & (Rd == 5'd14) & (Sel == 3'b000)) ? Reg_In : EPC;
477
                BadVAddr <= BadVAddr;
478
            end
479
        end
480
    end
481
 
482
 
483
    /*** Program Counter for all Exceptions/Interrupts ***/
484
    always @(*) begin
485
        // Following is redundant since PC has initial value now.
486
        if (reset) begin
487
            Exc_PC_Out <= EXC_Vector_Base_Reset;
488
        end
489
        else if (ERET & ~ID_Stall) begin
490
            Exc_PC_Out <= (Status_ERL) ? ErrorEPC : EPC;
491
        end
492
        else if (EXC_General) begin
493
            Exc_PC_Out <= (Status_BEV) ? (EXC_Vector_Base_Other_Boot   + EXC_Vector_Offset_General) :
494
                                         (EXC_Vector_Base_Other_NoBoot + EXC_Vector_Offset_General);
495
        end
496
        else if (EXC_NMI) begin
497
            Exc_PC_Out <= EXC_Vector_Base_Reset;
498
        end
499
        else if (EXC_Int & Cause_IV) begin
500
            Exc_PC_Out <= (Status_BEV) ? (EXC_Vector_Base_Other_Boot   + EXC_Vector_Offset_Special) :
501
                                         (EXC_Vector_Base_Other_NoBoot + EXC_Vector_Offset_Special);
502
        end
503
        else begin
504
            Exc_PC_Out <= (Status_BEV) ? (EXC_Vector_Base_Other_Boot   + EXC_Vector_Offset_General) :
505
                                         (EXC_Vector_Base_Other_NoBoot + EXC_Vector_Offset_General);
506
        end
507
    end
508
 
509
    //assign Exc_PC_Sel = (reset | (ERET & ~ID_Stall) | EXC_General | EXC_Int);
510
    assign Exc_PC_Sel = reset | (ERET & ~ID_Stall) | IF_Exception_Ready | ID_Exception_Ready | EX_Exception_Ready | M_Exception_Ready;
511
 
512
    /*** Cause Register ExcCode Field ***/
513
    always @(*) begin
514
        // Ordered by Pipeline Stage with Interrupts last
515
        if      (EXC_AdEL) Cause_ExcCode_bits <= 4'h4;     // 00100
516
        else if (EXC_AdES) Cause_ExcCode_bits <= 4'h5;     // 00101
517
        else if (EXC_Tr)   Cause_ExcCode_bits <= 4'hd;     // 01101
518
        else if (EXC_Ov)   Cause_ExcCode_bits <= 4'hc;     // 01100
519
        else if (EXC_Sys)  Cause_ExcCode_bits <= 4'h8;     // 01000
520
        else if (EXC_Bp)   Cause_ExcCode_bits <= 4'h9;     // 01001
521
        else if (EXC_RI)   Cause_ExcCode_bits <= 4'ha;     // 01010
522
        else if (EXC_CpU)  Cause_ExcCode_bits <= 4'hb;     // 01011
523
        else if (EXC_AdIF) Cause_ExcCode_bits <= 4'h4;     // 00100
524
        else if (EXC_Int)  Cause_ExcCode_bits <= 4'h0;     // 00000     // OK that NMI writes this.
525
        else               Cause_ExcCode_bits <= 4'bxxxx;
526
    end
527 3 ayersg
 
528
endmodule
529 2 ayersg
 

powered by: WebSVN 2.1.0

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