URL
https://opencores.org/ocsvn/mips32r1/mips32r1/trunk
Subversion Repositories mips32r1
[/] [mips32r1/] [trunk/] [Hardware/] [MIPS32_Standalone/] [CPZero.v] - Rev 12
Go to most recent revision | Compare with Previous | Blame | View Log
`timescale 1ns / 1ps /* * File : CPZero.v * Project : University of Utah, XUM Project MIPS32 core * Creator(s) : Grant Ayers (ayers@cs.utah.edu) * * Modification History: * Rev Date Initials Description of Change * 1.0 16-Sep-2011 GEA Initial design. * 2.0 14-May-2012 GEA Complete rework. * * Standards/Formatting: * Verilog 2001, 4 soft tab, wide column. * * Description: * The MIPS-32 Coprocessor 0 (CP0). This is the processor management unit that allows * interrupts, traps, system calls, and other exceptions. It distinguishes * user and kernel modes, provides status information, and can override program * flow. This processor is designed for "bare metal" memory access and thus does * not have virtual memory hardware as a part of it. However, the subset of CP0 * is MIPS-32-compliant. */ module CPZero( input clock, //-- CP0 Functionality --// input Mfc0, // CPU instruction is Mfc0 input Mtc0, // CPU instruction is Mtc0 input IF_Stall, input ID_Stall, // Commits are not made during stalls input COP1, // Instruction for Coprocessor 1 input COP2, // Instruction for Coprocessor 2 input COP3, // Instruction for Coprocessor 3 input ERET, // Instruction is ERET (Exception Return) input [4:0] Rd, // Specifies Cp0 register input [2:0] Sel, // Specifies Cp0 'select' input [31:0] Reg_In, // Data from GP register to replace CP0 register output reg [31:0] Reg_Out, // Data from CP0 register for GP register output KernelMode, // Kernel mode indicator for pipeline transit output ReverseEndian, // Reverse Endian memory indicator for User Mode //-- Hw Interrupts --// input [4:0] Int, // Five hardware interrupts external to the processor //-- Exceptions --// input reset, // Cold Reset (EXC_Reset) // input EXC_SReset, // Soft Reset (not implemented) input EXC_NMI, // Non-Maskable Interrupt input EXC_AdIF, // Address Error Exception from i-fetch (mapped to AdEL) input EXC_AdEL, // Address Error Exception from data memory load input EXC_AdES, // Address Error Exception from data memory store input EXC_Ov, // Integer Overflow Exception input EXC_Tr, // Trap Exception input EXC_Sys, // System Call Exception input EXC_Bp, // Breakpoint Exception input EXC_RI, // Reserved Instruction Exception //-- Exception Data --// input [31:0] ID_RestartPC, // PC for exception, whether PC of instruction or of branch (PC-4) if BDS input [31:0] EX_RestartPC, // Same as 'ID_RestartPC' but in EX stage input [31:0] M_RestartPC, // Same as 'ID_RestartPC' but in MEM stage input ID_IsFlushed, input IF_IsBD, // Indicator of IF exception being a branch delay slot instruction input ID_IsBD, // Indicator of ID exception being a branch delay slot instruction input EX_IsBD, // Indicator of EX exception being a branch delay slot instruction input M_IsBD, // Indicator of M exception being a branch delay slot instruction input [31:0] BadAddr_M, // Bad 'Virtual' Address for exceptions AdEL, AdES in MEM stage input [31:0] BadAddr_IF, // Bad 'Virtual' Address for AdIF (i.e. AdEL) in IF stage input ID_CanErr, // Cumulative signal, i.e. (ID_ID_CanErr | ID_EX_CanErr | ID_M_CanErr) input EX_CanErr, // Cumulative signal, i.e. (EX_EX_CanErr | EX_M_CanErr) input M_CanErr, // Memory stage can error (i.e. cause exception) //-- Exception Control Flow --/ output IF_Exception_Stall, output ID_Exception_Stall, output EX_Exception_Stall, output M_Exception_Stall, output IF_Exception_Flush, output ID_Exception_Flush, output EX_Exception_Flush, output M_Exception_Flush, output Exc_PC_Sel, // Mux selector for exception PC override output reg [31:0] Exc_PC_Out, // Address for PC at the beginning of an exception output [7:0] IP // Pending Interrupts from Cause register (for diagnostic purposes) ); `include "MIPS_Parameters.v" /*** Exception Control Flow Notes - Exceptions can occur in every pipeline stage. This implies that more than one exception can be raised in a single cycle. When this occurs, only the forward-most exception (i.e. MEM over EX) is handled. This and the following note guarantee program order. - An exception in any pipeline stage must stall that stage until all following stages are exception-free. This is because it only makes sense for exceptions to occur in program order. - A pipeline stage which causes an exception must flush, i.e. prevent any commits it would have normally made and convert itself to a NOP for the next pipeline stage. Furthermore, it must flush all previous pipeline stages as well in order to retain program order. - Instructions reading CP0 (mtc0) read in ID without further action. Writes to CP0 (mtc0, eret) also write in ID, but only after forward pipeline stages have been cleared of possible exceptions. This prevents many insidious bugs, such as switching to User Mode in ID when a legitimate memory access in kernel mode is processing in MEM, or conversely a switch to Kernel Mode in ID when an instruction in User Mode is attempting a kernel region memory access (when a kernel mode signal does not propagate through the pipeline). - Commits occur in ID (CP0), EX (HILO), MEM, and WB (registers). - Hardware interrupts are detected and inserted in the ID stage, but only when there are no other possible exceptions in the pipeline. Because they appear 'asynchronous' to the processor, the remaining instructions in forward stages (EX, MEM, WB) can either be flushed or completed. It is simplest to have them complete to avoid restarts, but the interrupt latency is higher if e.g. the MEM stage stalls on a memory access (this would be unavoidable on single-cycle processors). This implementation allows all forward instructions to complete, for a greater instruction throughput but higher interrupt latency. - Software interrupts should appear synchronous in the program order, meaning that all instructions previous to them should complete and no instructions after them should start until the interrupts has been processed. Exception Name Short Name Pipeline Stage Address Error Ex (AdEL, AdES) MEM, IF Integer Overflow Ex (Ov) EX Trap Ex (Tr) MEM Syscall (Sys) ID Breakpoint (Bp) ID Reserved Instruction (RI) ID Coprocessor Unusable (CpU) ID Interrupt (Int) ID Reset, SReset, NMI ID ***/ // Exceptions Generated Internally wire EXC_CpU; // Hardware Interrupt #5, caused by Timer/Perf counter wire Int5; // Top-level Authoritative Interrupt Signal wire EXC_Int; // General Exception detection (all but Interrupts, Reset, Soft Reset, and NMI) wire EXC_General = EXC_AdIF | EXC_AdEL | EXC_AdES | EXC_Ov | EXC_Tr | EXC_Sys | EXC_Bp | EXC_RI | EXC_CpU; // Misc wire CP0_WriteCond; reg [3:0] Cause_ExcCode_bits; reg reset_r; always @(posedge clock) begin reset_r <= reset; end /*** MIPS-32 COPROCESSOR 0 (Cp0) REGISTERS These are defined in "MIPS32 Architecture for Programmers Volume III: The MIPS32 Privileged Resource Architecture" from MIPS Technologies, Inc. Optional registers are omitted. Changes to the processor (such as adding an MMU/TLB, etc. must be reflected in these registers. */ // BadVAddr Register (Register 8, Select 0) reg [31:0] BadVAddr; // Count Register (Register 9, Select 0) reg [31:0] Count; // Compare Register (Register 11, Select 0) reg [31:0] Compare; // Status Register (Register 12, Select 0) wire [2:0] Status_CU_321 = 3'b000; reg Status_CU_0; // Access Control to CPs, [2]->Cp3, ... [0]->Cp0 wire Status_RP = 0; wire Status_FR = 0; reg Status_RE; // Reverse Endian Memory for User Mode wire Status_MX = 0; wire Status_PX = 0; reg Status_BEV; // Exception vector locations (0->Norm, 1->Bootstrap) wire Status_TS = 0; wire Status_SR = 0; // Soft reset not implemented reg Status_NMI; // Non-Maskable Interrupt wire Status_RES = 0; wire [1:0] Status_Custom = 2'b00; reg [7:0] Status_IM; // Interrupt mask wire Status_KX = 0; wire Status_SX = 0; wire Status_UX = 0; reg Status_UM; // Base operating mode (0->Kernel, 1->User) wire Status_R0 = 0; reg Status_ERL; // Error Level (0->Normal, 1->Error (reset, NMI)) reg Status_EXL; // Exception level (0->Normal, 1->Exception) reg Status_IE; // Interrupt Enable wire [31:0] Status = {Status_CU_321, Status_CU_0, Status_RP, Status_FR, Status_RE, Status_MX, Status_PX, Status_BEV, Status_TS, Status_SR, Status_NMI, Status_RES, Status_Custom, Status_IM, Status_KX, Status_SX, Status_UX, Status_UM, Status_R0, Status_ERL, Status_EXL, Status_IE}; // Cause Register (Register 13, Select 0) reg Cause_BD; // Exception occured in Branch Delay reg [1:0] Cause_CE; // CP number for CP Unusable exception reg Cause_IV; // Indicator of general IV (0->0x180) or special IV (1->0x200) wire Cause_WP = 0; reg [7:0] Cause_IP; // Pending HW Interrupt indicator. wire Cause_ExcCode4 = 0; // Can be made into a register when this bit is needed. reg [3:0] Cause_ExcCode30; // Description of Exception (only lower 4 bits currently used; see above) wire [31:0] Cause = {Cause_BD, 1'b0, Cause_CE, 4'b0000, Cause_IV, Cause_WP, 6'b000000, Cause_IP, 1'b0, Cause_ExcCode4, Cause_ExcCode30, 2'b00}; // Exception Program Counter (Register 14, Select 0) reg [31:0] EPC; // Processor Identification (Register 15, Select 0) wire [7:0] ID_Options = 8'b0000_0000; wire [7:0] ID_CID = 8'b0000_0000; wire [7:0] ID_PID = 8'b0000_0000; wire [7:0] ID_Rev = 8'b0000_0001; wire [31:0] PRId = {ID_Options, ID_CID, ID_PID, ID_Rev}; // Configuration Register (Register 16, Select 0) wire Config_M = 1; wire [14:0] Config_Impl = 15'b000_0000_0000_0000; wire Config_BE = Big_Endian; // From parameters file wire [1:0] Config_AT = 2'b00; wire [2:0] Config_AR = 3'b000; wire [2:0] Config_MT = 3'b000; wire [2:0] Config_K0 = 3'b000; wire [31:0] Config = {Config_M, Config_Impl, Config_BE, Config_AT, Config_AR, Config_MT, 4'b0000, Config_K0}; // Configuration Register 1 (Register 16, Select 1) wire Config1_M = 0; wire [5:0] Config1_MMU = 6'b000000; wire [2:0] Config1_IS = 3'b000; wire [2:0] Config1_IL = 3'b000; wire [2:0] Config1_IA = 3'b000; wire [2:0] Config1_DS = 3'b000; wire [2:0] Config1_DL = 3'b000; wire [2:0] Config1_DA = 3'b000; wire Config1_C2 = 0; wire Config1_MD = 0; wire Config1_PC = 0; // XXX Performance Counters wire Config1_WR = 0; // XXX Watch Registers wire Config1_CA = 0; wire Config1_EP = 0; wire Config1_FP = 0; wire [31:0] Config1 = {Config1_M, Config1_MMU, Config1_IS, Config1_IL, Config1_IA, Config1_DS, Config1_DL, Config1_DA, Config1_C2, Config1_MD, Config1_PC, Config1_WR, Config1_CA, Config1_EP, Config1_FP}; // Performance Counter Register (Register 25) XXX TODO // ErrorEPC Register (Register 30, Select 0) reg [31:0] ErrorEPC; // Exception Detection and Processing wire M_Exception_Detect, EX_Exception_Detect, ID_Exception_Detect, IF_Exception_Detect; wire M_Exception_Mask, EX_Exception_Mask, ID_Exception_Mask, IF_Exception_Mask; wire M_Exception_Ready, EX_Exception_Ready, ID_Exception_Ready, IF_Exception_Ready; assign IP = Cause_IP; /*** Coprocessor Unusable Exception ***/ assign EXC_CpU = COP1 | COP2 | COP3 | ((Mtc0 | Mfc0 | ERET) & ~(Status_CU_0 | KernelMode)); /*** Kernel Mode Signal ***/ assign KernelMode = ~Status_UM | Status_EXL | Status_ERL; /*** Reverse Endian for User Mode ***/ assign ReverseEndian = Status_RE; /*** Interrupts ***/ assign Int5 = (Count == Compare); //assign EXC_Int = ((Cause_IP[7:0] & Status_IM[7:0]) != 8'h00) & Status_IE & ~Status_EXL & ~Status_ERL & ~ID_IsFlushed; wire Enabled_Interrupt = EXC_NMI | (Status_IE & ((Cause_IP[7:0] & Status_IM[7:0]) != 8'h00)); assign EXC_Int = Enabled_Interrupt & ~Status_EXL & ~Status_ERL & ~ID_IsFlushed; assign CP0_WriteCond = (Status_CU_0 | KernelMode) & Mtc0 & ~ID_Stall; /*** Exception Hazard Flow Control Explanation: - An exception at any time in any stage causes its own and any previous stages to flush (clear own commits, NOPS to fwd stages). - An exception in a stage can also stall that stage (and inherently all previous stages) if and only if: 1. A forward stage is capable of causing an exception AND 2. A forward stage is not currently causing an exception. - An exception is ready to process when it is detected and not stalled in a stage. Flush specifics per pipeline stage: MEM: Mask 'MemWrite' and 'MemRead' (for performance) after EX/M and before data memory. NOPs to M/WB. EX : Mask writes to HI/LO. NOPs to EX/M. ID : Mask writes (reads?) to CP0. NOPs to ID/EX. IF : NOP to IF/ID. ***/ /*** Exceptions grouped by pipeline stage ***/ assign M_Exception_Detect = EXC_AdEL | EXC_AdES | EXC_Tr; assign EX_Exception_Detect = EXC_Ov; assign ID_Exception_Detect = EXC_Sys | EXC_Bp | EXC_RI | EXC_CpU | EXC_Int; assign IF_Exception_Detect = EXC_AdIF; /*** Exception mask conditions ***/ // A potential bug would occur if e.g. EX stalls, MEM has data, but MEM is not stalled and finishes // going through the pipeline so forwarding would fail. This is not a problem however because // EX would not need data since it would flush on an exception. assign M_Exception_Mask = IF_Stall; assign EX_Exception_Mask = IF_Stall | M_CanErr; assign ID_Exception_Mask = IF_Stall | M_CanErr | EX_CanErr; assign IF_Exception_Mask = M_CanErr | EX_CanErr | ID_CanErr | EXC_Int; /*** Exceptions which must wait for forward stages. A stage will not stall if a forward stage has an exception. These stalls must be inserted as stall conditions in the hazard unit so that it will take care of chaining. All writes to CP0 must also wait for forward hazard conditions to clear. */ assign M_Exception_Stall = M_Exception_Detect & M_Exception_Mask; assign EX_Exception_Stall = EX_Exception_Detect & EX_Exception_Mask & ~M_Exception_Detect; assign ID_Exception_Stall = (ID_Exception_Detect | ERET | Mtc0) & ID_Exception_Mask & ~(EX_Exception_Detect | M_Exception_Detect); assign IF_Exception_Stall = IF_Exception_Detect & IF_Exception_Mask & ~(ID_Exception_Detect | EX_Exception_Detect | M_Exception_Detect); /*** Exceptions which are ready to process (mutually exclusive) ***/ // XXX can remove ~ID_Stall since in mask now (?) assign M_Exception_Ready = ~ID_Stall & M_Exception_Detect & ~M_Exception_Mask; assign EX_Exception_Ready = ~ID_Stall & EX_Exception_Detect & ~EX_Exception_Mask; assign ID_Exception_Ready = ~ID_Stall & ID_Exception_Detect & ~ID_Exception_Mask; assign IF_Exception_Ready = ~ID_Stall & IF_Exception_Detect & ~IF_Exception_Mask; /*** Flushes. A flush clears a pipeline stage's control signals and prevents the stage from committing any changes. Data such as 'RestartPC' and the detected exception must remain. */ assign M_Exception_Flush = M_Exception_Detect; assign EX_Exception_Flush = M_Exception_Detect | EX_Exception_Detect; assign ID_Exception_Flush = M_Exception_Detect | EX_Exception_Detect | ID_Exception_Detect; assign IF_Exception_Flush = M_Exception_Detect | EX_Exception_Detect | ID_Exception_Detect | IF_Exception_Detect | (ERET & ~ID_Stall) | reset_r; /*** Software reads of CP0 Registers ***/ always @(*) begin if (Mfc0 & (Status_CU_0 | KernelMode)) begin case (Rd) 5'd8 : Reg_Out <= BadVAddr; 5'd9 : Reg_Out <= Count; 5'd11 : Reg_Out <= Compare; 5'd12 : Reg_Out <= Status; 5'd13 : Reg_Out <= Cause; 5'd14 : Reg_Out <= EPC; 5'd15 : Reg_Out <= PRId; 5'd16 : Reg_Out <= (Sel == 3'b000) ? Config : Config1; 5'd30 : Reg_Out <= ErrorEPC; default : Reg_Out <= 32'h0000_0000; endcase end else begin Reg_Out <= 32'h0000_0000; end end /*** Cp0 Register Assignments: Non-general exceptions (Reset, Soft Reset, NMI...) ***/ always @(posedge clock) begin if (reset) begin Status_BEV <= 1; Status_NMI <= 0; Status_ERL <= 1; ErrorEPC <= 32'b0; end else if (ID_Exception_Ready & EXC_NMI) begin Status_BEV <= 1; Status_NMI <= 1; Status_ERL <= 1; ErrorEPC <= ID_RestartPC; end else begin Status_BEV <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[22] : Status_BEV; Status_NMI <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[19] : Status_NMI; Status_ERL <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[2] : ((Status_ERL & ERET & ~ID_Stall) ? 0 : Status_ERL); ErrorEPC <= (CP0_WriteCond & (Rd == 5'd30) & (Sel == 3'b000)) ? Reg_In : ErrorEPC; end end /*** Cp0 Register Assignments: All other registers ***/ always @(posedge clock) begin if (reset) begin Count <= 32'b0; Compare <= 32'b0; Status_CU_0 <= 0; Status_RE <= 0; Status_IM <= 8'b0; Status_UM <= 0; Status_IE <= 0; Cause_IV <= 0; Cause_IP <= 8'b0; end else begin Count <= (CP0_WriteCond & (Rd == 5'd9 ) & (Sel == 3'b000)) ? Reg_In : ((Count == Compare) ? 32'b0 : Count + 1); Compare <= (CP0_WriteCond & (Rd == 5'd11) & (Sel == 3'b000)) ? Reg_In : Compare; Status_CU_0 <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[28] : Status_CU_0; Status_RE <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[25] : Status_RE; Status_IM <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[15:8] : Status_IM; Status_UM <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[4] : Status_UM; Status_IE <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[0] : Status_IE; Cause_IV <= (CP0_WriteCond & (Rd == 5'd13) & (Sel == 3'b000)) ? Reg_In[23] : Cause_IV; /* Cause_IP indicates 8 interrupts: [7] is set by the timer comparison, and cleared by reading 'Count'. [6:2] are set and cleared by external hardware. [1:0] are set and cleared by software. */ // If reading -> 0, Otherwise if 0 -> Int5. Cause_IP[7] <= ((Status_CU_0 | KernelMode) & Mfc0 & (Rd == 5'd9) & (Sel == 3'b000)) ? 0 : ((Cause_IP[7] == 0) ? Int5 : Cause_IP[7]); Cause_IP[6:2] <= Int[4:0]; Cause_IP[1:0] <= (CP0_WriteCond & (Rd == 5'd13) & (Sel == 3'b000)) ? Reg_In[9:8] : Cause_IP[1:0]; end end /*** Cp0 Register Assignments: General Exception and Interrupt Processing ***/ always @(posedge clock) begin if (reset) begin Cause_BD <= 0; Cause_CE <= 2'b00; Cause_ExcCode30 <= 4'b0000; Status_EXL <= 0; EPC <= 32'h0; BadVAddr <= 32'h0; end else begin // MEM stage if (M_Exception_Ready) begin Cause_BD <= (Status_EXL) ? Cause_BD : M_IsBD; Cause_CE <= (COP3) ? 2'b11 : ((COP2) ? 2'b10 : ((COP1) ? 2'b01 : 2'b00)); Cause_ExcCode30 <= Cause_ExcCode_bits; Status_EXL <= 1; EPC <= (Status_EXL) ? EPC : M_RestartPC; BadVAddr <= BadAddr_M; end // EX stage else if (EX_Exception_Ready) begin Cause_BD <= (Status_EXL) ? Cause_BD : EX_IsBD; Cause_CE <= (COP3) ? 2'b11 : ((COP2) ? 2'b10 : ((COP1) ? 2'b01 : 2'b00)); Cause_ExcCode30 <= Cause_ExcCode_bits; Status_EXL <= 1; EPC <= (Status_EXL) ? EPC : EX_RestartPC; BadVAddr <= BadVAddr; end // ID stage else if (ID_Exception_Ready) begin Cause_BD <= (Status_EXL) ? Cause_BD : ID_IsBD; Cause_CE <= (COP3) ? 2'b11 : ((COP2) ? 2'b10 : ((COP1) ? 2'b01 : 2'b00)); Cause_ExcCode30 <= Cause_ExcCode_bits; Status_EXL <= 1; EPC <= (Status_EXL) ? EPC : ID_RestartPC; BadVAddr <= BadVAddr; end // IF stage else if (IF_Exception_Ready) begin Cause_BD <= (Status_EXL) ? Cause_BD : IF_IsBD; Cause_CE <= (COP3) ? 2'b11 : ((COP2) ? 2'b10 : ((COP1) ? 2'b01 : 2'b00)); Cause_ExcCode30 <= Cause_ExcCode_bits; Status_EXL <= 1; EPC <= (Status_EXL) ? EPC : BadAddr_IF; BadVAddr <= BadAddr_IF; end // No exceptions this cycle else begin Cause_BD <= 1'b0; Cause_CE <= Cause_CE; Cause_ExcCode30 <= Cause_ExcCode30; // Without new exceptions, 'Status_EXL' is set by software or cleared by ERET. Status_EXL <= (CP0_WriteCond & (Rd == 5'd12) & (Sel == 3'b000)) ? Reg_In[1] : ((Status_EXL & ERET & ~ID_Stall) ? 0 : Status_EXL); // The EPC is also writable by software EPC <= (CP0_WriteCond & (Rd == 5'd14) & (Sel == 3'b000)) ? Reg_In : EPC; BadVAddr <= BadVAddr; end end end /*** Program Counter for all Exceptions/Interrupts ***/ always @(*) begin // Following is redundant since PC has initial value now. if (reset) begin Exc_PC_Out <= EXC_Vector_Base_Reset; end else if (ERET & ~ID_Stall) begin Exc_PC_Out <= (Status_ERL) ? ErrorEPC : EPC; end else if (EXC_General) begin Exc_PC_Out <= (Status_BEV) ? (EXC_Vector_Base_Other_Boot + EXC_Vector_Offset_General) : (EXC_Vector_Base_Other_NoBoot + EXC_Vector_Offset_General); end else if (EXC_NMI) begin Exc_PC_Out <= EXC_Vector_Base_Reset; end else if (EXC_Int & Cause_IV) begin Exc_PC_Out <= (Status_BEV) ? (EXC_Vector_Base_Other_Boot + EXC_Vector_Offset_Special) : (EXC_Vector_Base_Other_NoBoot + EXC_Vector_Offset_Special); end else begin Exc_PC_Out <= (Status_BEV) ? (EXC_Vector_Base_Other_Boot + EXC_Vector_Offset_General) : (EXC_Vector_Base_Other_NoBoot + EXC_Vector_Offset_General); end end //assign Exc_PC_Sel = (reset | (ERET & ~ID_Stall) | EXC_General | EXC_Int); assign Exc_PC_Sel = reset | (ERET & ~ID_Stall) | IF_Exception_Ready | ID_Exception_Ready | EX_Exception_Ready | M_Exception_Ready; /*** Cause Register ExcCode Field ***/ always @(*) begin // Ordered by Pipeline Stage with Interrupts last if (EXC_AdEL) Cause_ExcCode_bits <= 4'h4; // 00100 else if (EXC_AdES) Cause_ExcCode_bits <= 4'h5; // 00101 else if (EXC_Tr) Cause_ExcCode_bits <= 4'hd; // 01101 else if (EXC_Ov) Cause_ExcCode_bits <= 4'hc; // 01100 else if (EXC_Sys) Cause_ExcCode_bits <= 4'h8; // 01000 else if (EXC_Bp) Cause_ExcCode_bits <= 4'h9; // 01001 else if (EXC_RI) Cause_ExcCode_bits <= 4'ha; // 01010 else if (EXC_CpU) Cause_ExcCode_bits <= 4'hb; // 01011 else if (EXC_AdIF) Cause_ExcCode_bits <= 4'h4; // 00100 else if (EXC_Int) Cause_ExcCode_bits <= 4'h0; // 00000 // OK that NMI writes this. else Cause_ExcCode_bits <= 4'bxxxx; end endmodule
Go to most recent revision | Compare with Previous | Blame | View Log