URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [mp3_stable/] [mp3/] [rtl/] [verilog/] [or1200.xcv/] [except.v] - Rev 1765
Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////// //// //// //// OR1200's Exception logic //// //// //// //// This file is part of the OpenRISC 1200 project //// //// http://www.opencores.org/cores/or1k/ //// //// //// //// Description //// //// Handles all OR1K exceptions inside CPU block. //// //// //// //// To Do: //// //// - make it smaller and faster //// //// //// //// Author(s): //// //// - Damjan Lampret, lampret@opencores.org //// //// //// ////////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2000 Authors and OPENCORES.ORG //// //// //// //// This source file may be used and distributed without //// //// restriction provided that this copyright statement is not //// //// removed from the file and that any derivative work contains //// //// the original copyright notice and the associated disclaimer. //// //// //// //// This source file 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 2.1 of the License, or (at your option) any //// //// later version. //// //// //// //// This source 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 this source; if not, download it //// //// from http://www.opencores.org/lgpl.shtml //// //// //// ////////////////////////////////////////////////////////////////////// // // CVS Revision History // // $Log: not supported by cvs2svn $ // Revision 1.1.1.1 2001/10/06 10:18:36 igorm // no message // // Revision 1.2 2001/08/09 13:39:33 lampret // Major clean-up. // // Revision 1.1 2001/07/20 00:46:03 lampret // Development version of RTL. Libraries are missing. // // // synopsys translate_off `include "timescale.v" // synopsys translate_on `include "defines.v" `define EXCEPTFSM_WIDTH 2 `define EXCEPTFSM_IDLE `EXCEPTFSM_WIDTH'd0 `define EXCEPTFSM_FLU1 `EXCEPTFSM_WIDTH'd1 `define EXCEPTFSM_FLU2 `EXCEPTFSM_WIDTH'd2 `define EXCEPTFSM_FLU3 `EXCEPTFSM_WIDTH'd3 // // Exception recognition and sequencing // module except( // Clock and reset clk, rst, // Internal i/f sig_buserr, sig_illegal, sig_align, sig_range, sig_dtlbmiss, sig_dmmufault, sig_inthigh, sig_syscall, sig_trap, sig_itlbmiss, sig_immufault, sig_intlow, branch_taken, id_freeze, ex_freeze, wb_freeze, if_stall, if_pc, lr_sav, except_flushpipe, except_type, except_start, except_started, wb_pc, ex_pc, datain, epcr_we, eear_we, esr_we, epcr, eear, esr, sr, lsu_addr ); // // I/O // input clk; input rst; input sig_buserr; input sig_illegal; input sig_align; input sig_range; input sig_dtlbmiss; input sig_dmmufault; input sig_inthigh; input sig_syscall; input sig_trap; input sig_itlbmiss; input sig_immufault; input sig_intlow; input branch_taken; input id_freeze; input ex_freeze; input wb_freeze; input if_stall; input [31:0] if_pc; output [31:2] lr_sav; input [31:0] datain; input epcr_we; input eear_we; input esr_we; output [31:0] epcr; output [31:0] eear; output [`SR_WIDTH-1:0] esr; input [`SR_WIDTH-1:0] sr; input [31:0] lsu_addr; output except_flushpipe; output [`EXCEPT_WIDTH-1:0] except_type; output except_start; output except_started; output [31:0] wb_pc; output [31:0] ex_pc; // // Internal regs and wires // reg [`EXCEPT_WIDTH-1:0] except_type; reg [31:0] id_pc; reg [31:0] ex_pc; reg [31:0] wb_pc; reg [31:0] epcr; reg [31:0] eear; reg [`SR_WIDTH-1:0] esr; reg [2:0] id_exceptflags; reg [2:0] ex_exceptflags; reg [`EXCEPTFSM_WIDTH-1:0] state; reg extend_flush; reg ex_dslot; reg delayed1_ex_dslot; reg delayed2_ex_dslot; wire except_started; wire [12:0] except_trig; // // Simple combinatorial logic // assign except_started = ~except_start & extend_flush; assign lr_sav = ex_pc[31:2]; assign except_start = (except_type != `EXCEPT_NONE); assign except_trig = { sig_buserr, sig_illegal, sig_align, sig_range, sig_dtlbmiss, sig_dmmufault, sig_inthigh, sig_trap, sig_syscall, ex_exceptflags[2:0]}; // // PC and Exception flags pipelines // always @(posedge clk or posedge rst) begin if (rst) begin id_pc <= #1 32'd0; id_exceptflags <= #1 3'b0; end else if (!id_freeze) begin `ifdef OR1200_VERBOSE // synopsys translate_off $display("%t: id_pc <= %h", $time, if_pc); // synopsys translate_on `endif id_pc <= #1 if_pc; id_exceptflags <= #1 { sig_itlbmiss, sig_immufault, sig_intlow & sr[`SR_EXR]}; end end // // PC and Exception flags pipelines // always @(posedge clk or posedge rst) begin if (rst) begin ex_dslot <= #1 1'b0; ex_pc <= #1 32'd0; ex_exceptflags <= #1 3'b0; delayed1_ex_dslot <= #1 1'b0; delayed2_ex_dslot <= #1 1'b0; end else if (!ex_freeze & id_freeze) begin ex_dslot <= #1 1'b0; ex_pc <= #1 id_pc; ex_exceptflags <= #1 3'b000; delayed1_ex_dslot <= #1 ex_dslot; delayed2_ex_dslot <= #1 delayed1_ex_dslot; end else if (!ex_freeze) begin `ifdef OR1200_VERBOSE // synopsys translate_off $display("%t: ex_pc <= %h", $time, id_pc); // synopsys translate_on `endif ex_dslot <= #1 branch_taken; ex_pc <= #1 id_pc; ex_exceptflags <= #1 id_exceptflags; delayed1_ex_dslot <= #1 ex_dslot; delayed2_ex_dslot <= #1 delayed1_ex_dslot; end end // // PC and Exception flags pipelines // always @(posedge clk or posedge rst) begin if (rst) begin wb_pc <= #1 32'd0; end else if (!wb_freeze) begin wb_pc <= #1 ex_pc; end end // // We have started execution of exception handler: // 1. Asserted for 3 clock cycles // 2. Don't execute any instruction that is still in pipeline and is not part of exception handler // assign except_flushpipe = (sr[`SR_EXR] & (sig_dtlbmiss | sig_dmmufault | sig_inthigh | sig_syscall |sig_trap | (|ex_exceptflags)) | extend_flush); // // Exception FSM that sequences execution of exception handler // // except_type signals which exception handler we start fetching in: // 1. Asserted in next clock cycle after exception is recognized // always @(posedge clk or posedge rst) begin if (rst) begin state <= #1 `EXCEPTFSM_IDLE; except_type <= #1 `EXCEPT_NONE; extend_flush <= #1 1'b0; epcr <= #1 32'b0; eear <= #1 32'b0; esr <= #1 `SR_WIDTH'b0; end else begin case (state) // synopsys full_case parallel_case `EXCEPTFSM_IDLE: if (except_flushpipe) begin state <= #1 `EXCEPTFSM_FLU1; extend_flush <= #1 1'b1; if (ex_dslot) begin `ifdef OR1200_VERBOSE // synopsys translate_off $display(" INFO: Exception during first delay slot instruction."); // synopsys translate_on `endif epcr <= #1 wb_pc; end else if (delayed1_ex_dslot) begin `ifdef OR1200_VERBOSE // synopsys translate_off $display(" INFO: Exception during second (NOP) delay slot instruction."); // synopsys translate_on `endif epcr <= #1 id_pc; end else if (delayed2_ex_dslot) begin `ifdef OR1200_VERBOSE // synopsys translate_off $display(" INFO: Exception during third delay slot (SHOULD NOT HAPPEN)."); // synopsys translate_on `endif epcr <= #1 id_pc; end else begin `ifdef OR1200_VERBOSE // synopsys translate_off $display(" INFO: Exception during normal (no delay slot) instruction."); // synopsys translate_on `endif epcr <= #1 ex_pc; end esr <= #1 sr; eear <= #1 lsu_addr; casex (except_trig) 13'b1_xxxx_xxxx_xxxx: except_type <= #1 `EXCEPT_BUSERR; 13'b0_1xxx_xxxx_xxxx: except_type <= #1 `EXCEPT_ILLEGAL; 13'b0_01xx_xxxx_xxxx: except_type <= #1 `EXCEPT_ALIGN; 13'b0_0001_xxxx_xxxx: except_type <= #1 `EXCEPT_RANGE; 13'b0_0000_1xxx_xxxx: except_type <= #1 `EXCEPT_DTLBMISS; 13'b0_0000_01xx_xxxx: except_type <= #1 `EXCEPT_DPF; 13'b0_0000_001x_xxxx: except_type <= #1 `EXCEPT_HPINT; 13'b0_0000_0001_xxxx: except_type <= #1 `EXCEPT_TRAP; 13'b0_0000_0000_1xxx: except_type <= #1 `EXCEPT_SYSCALL; 13'b0_0000_0000_01xx: except_type <= #1 `EXCEPT_ITLBMISS; 13'b0_0000_0000_001x: except_type <= #1 `EXCEPT_IPF; 13'b0_0000_0000_0001: except_type <= #1 `EXCEPT_LPINT; default: except_type <= #1 `EXCEPT_NONE; endcase end else begin if (epcr_we) epcr <= #1 datain; if (eear_we) eear <= #1 datain; if (esr_we) esr <= #1 datain[`SR_WIDTH-1:0]; end `EXCEPTFSM_FLU1: if (!if_stall && !id_freeze) begin `ifdef OR1200_VERBOSE // synopsys translate_off $display(" INFO: EPCR0 %h EEAR %h ESR %h", epcr, eear, esr); // synopsys translate_on `endif state <= #1 `EXCEPTFSM_FLU2; except_type <= #1 `EXCEPT_NONE; end `EXCEPTFSM_FLU2: state <= #1 `EXCEPTFSM_FLU3; `EXCEPTFSM_FLU3: begin `ifdef OR1200_VERBOSE // synopsys translate_off $display(" INFO: Exception just finished flushing pipeline."); // synopsys translate_on `endif state <= #1 `EXCEPTFSM_IDLE; extend_flush <= #1 1'b0; end endcase end end endmodule