URL
https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk
Subversion Repositories openrisc_me
[/] [openrisc/] [trunk/] [or1200/] [rtl/] [verilog/] [or1200_ctrl.v] - Rev 146
Go to most recent revision | Compare with Previous | Blame | View Log
////////////////////////////////////////////////////////////////////// //// //// //// OR1200's Instruction decode //// //// //// //// This file is part of the OpenRISC 1200 project //// //// http://www.opencores.org/cores/or1k/ //// //// //// //// Description //// //// Majority of instruction decoding is performed here. //// //// //// //// 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: or1200_ctrl.v,v $ // Revision 2.0 2010/06/30 11:00:00 ORSoC // Major update: // Structure reordered and bugs fixed. // // Revision 1.13 2005/01/13 11:03:43 phoenix // revert to the old l.sfxxi behavior // // Revision 1.12 2005/01/07 09:31:07 andreje // sign/zero extension for l.sfxxi instructions corrected // // Revision 1.11 2004/06/08 18:17:36 lampret // Non-functional changes. Coding style fixes. // // Revision 1.10 2004/05/09 19:49:04 lampret // Added some l.cust5 custom instructions as example // // Revision 1.9 2004/04/05 08:29:57 lampret // Merged branch_qmem into main tree. // // Revision 1.8.4.1 2004/02/11 01:40:11 lampret // preliminary HW breakpoints support in debug unit (by default disabled). To enable define OR1200_DU_HWBKPTS. // // Revision 1.8 2003/04/24 00:16:07 lampret // No functional changes. Added defines to disable implementation of multiplier/MAC // // Revision 1.7 2002/09/07 05:42:02 lampret // Added optional SR[CY]. Added define to enable additional (compare) flag modifiers. Defines are OR1200_IMPL_ADDC and OR1200_ADDITIONAL_FLAG_MODIFIERS. // // Revision 1.6 2002/03/29 15:16:54 lampret // Some of the warnings fixed. // // Revision 1.5 2002/02/01 19:56:54 lampret // Fixed combinational loops. // // Revision 1.4 2002/01/28 01:15:59 lampret // Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways. // // Revision 1.3 2002/01/18 14:21:43 lampret // Fixed 'the NPC single-step fix'. // // Revision 1.2 2002/01/14 06:18:22 lampret // Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if. // // Revision 1.1 2002/01/03 08:16:15 lampret // New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs. // // Revision 1.14 2001/11/30 18:59:17 simons // force_dslot_fetch does not work - allways zero. // // Revision 1.13 2001/11/20 18:46:15 simons // Break point bug fixed // // Revision 1.12 2001/11/18 08:36:28 lampret // For GDB changed single stepping and disabled trap exception. // // Revision 1.11 2001/11/13 10:02:21 lampret // Added 'setpc'. Renamed some signals (except_flushpipe into flushpipe etc) // // Revision 1.10 2001/11/12 01:45:40 lampret // Moved flag bit into SR. Changed RF enable from constant enable to dynamic enable for read ports. // // Revision 1.9 2001/11/10 03:43:57 lampret // Fixed exceptions. // // Revision 1.8 2001/10/21 17:57:16 lampret // Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF. // // Revision 1.7 2001/10/14 13:12:09 lampret // MP3 version. // // Revision 1.1.1.1 2001/10/06 10:18:36 igorm // no message // // Revision 1.2 2001/08/13 03:36:20 lampret // Added cfg regs. Moved all defines into one defines.v file. More cleanup. // // Revision 1.1 2001/08/09 13:39:33 lampret // Major clean-up. // // // synopsys translate_off `include "timescale.v" // synopsys translate_on `include "or1200_defines.v" module or1200_ctrl( // Clock and reset clk, rst, // Internal i/f except_flushpipe, extend_flush, if_flushpipe, id_flushpipe, ex_flushpipe, wb_flushpipe, id_freeze, ex_freeze, wb_freeze, if_insn, id_insn, ex_insn, abort_mvspr, id_branch_op, ex_branch_op, ex_branch_taken, pc_we, rf_addra, rf_addrb, rf_rda, rf_rdb, alu_op, mac_op, shrot_op, comp_op, rf_addrw, rfwb_op, wb_insn, id_simm, ex_simm, id_branch_addrtarget, ex_branch_addrtarget, sel_a, sel_b, id_lsu_op, cust5_op, cust5_limm, id_pc, ex_pc, du_hwbkpt, multicycle, wbforw_valid, sig_syscall, sig_trap, force_dslot_fetch, no_more_dslot, id_void, ex_void, ex_spr_read, ex_spr_write, id_mac_op, id_macrc_op, ex_macrc_op, rfe, except_illegal ); // // I/O // input clk; input rst; input id_freeze; input ex_freeze; input wb_freeze; output if_flushpipe; output id_flushpipe; output ex_flushpipe; output wb_flushpipe; input extend_flush; input except_flushpipe; input abort_mvspr ; input [31:0] if_insn; output [31:0] id_insn; output [31:0] ex_insn; output [`OR1200_BRANCHOP_WIDTH-1:0] ex_branch_op; output [`OR1200_BRANCHOP_WIDTH-1:0] id_branch_op; input ex_branch_taken; output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw; output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addra; output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrb; output rf_rda; output rf_rdb; output [`OR1200_ALUOP_WIDTH-1:0] alu_op; output [`OR1200_MACOP_WIDTH-1:0] mac_op; output [`OR1200_SHROTOP_WIDTH-1:0] shrot_op; output [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op; input pc_we; output [31:0] wb_insn; output [31:2] id_branch_addrtarget; output [31:2] ex_branch_addrtarget; output [`OR1200_SEL_WIDTH-1:0] sel_a; output [`OR1200_SEL_WIDTH-1:0] sel_b; output [`OR1200_LSUOP_WIDTH-1:0] id_lsu_op; output [`OR1200_COMPOP_WIDTH-1:0] comp_op; output [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle; output [4:0] cust5_op; output [5:0] cust5_limm; input [31:0] id_pc; input [31:0] ex_pc; output [31:0] id_simm; output [31:0] ex_simm; input wbforw_valid; input du_hwbkpt; output sig_syscall; output sig_trap; output force_dslot_fetch; output no_more_dslot; output id_void; output ex_void; output ex_spr_read; output ex_spr_write; output [`OR1200_MACOP_WIDTH-1:0] id_mac_op; output id_macrc_op; output ex_macrc_op; output rfe; output except_illegal; // // Internal wires and regs // reg [`OR1200_BRANCHOP_WIDTH-1:0] id_branch_op; reg [`OR1200_BRANCHOP_WIDTH-1:0] ex_branch_op; reg [`OR1200_ALUOP_WIDTH-1:0] alu_op; wire if_maci_op; `ifdef OR1200_MAC_IMPLEMENTED reg [`OR1200_MACOP_WIDTH-1:0] ex_mac_op; reg [`OR1200_MACOP_WIDTH-1:0] id_mac_op; wire [`OR1200_MACOP_WIDTH-1:0] mac_op; reg ex_macrc_op; `else wire [`OR1200_MACOP_WIDTH-1:0] mac_op; wire ex_macrc_op; `endif reg [`OR1200_SHROTOP_WIDTH-1:0] shrot_op; reg [31:0] id_insn; reg [31:0] ex_insn; reg [31:0] wb_insn; reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw; reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] wb_rfaddrw; reg [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op; reg [`OR1200_SEL_WIDTH-1:0] sel_a; reg [`OR1200_SEL_WIDTH-1:0] sel_b; reg sel_imm; reg [`OR1200_LSUOP_WIDTH-1:0] id_lsu_op; reg [`OR1200_COMPOP_WIDTH-1:0] comp_op; reg [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle; reg [31:0] id_simm; reg [31:0] ex_simm; reg sig_syscall; reg sig_trap; reg except_illegal; wire id_void; wire ex_void; wire wb_void; reg ex_delayslot_dsi; reg ex_delayslot_nop; reg spr_read; reg spr_write; reg [31:2] ex_branch_addrtarget; // // Register file read addresses // assign rf_addra = if_insn[20:16]; assign rf_addrb = if_insn[15:11]; assign rf_rda = if_insn[31] || if_maci_op; assign rf_rdb = if_insn[30]; // // Force fetch of delay slot instruction when jump/branch is preceeded by load/store // instructions // assign force_dslot_fetch = 1'b0; assign no_more_dslot = (|ex_branch_op & !id_void & ex_branch_taken) | (ex_branch_op == `OR1200_BRANCHOP_RFE); assign id_void = (id_insn[31:26] == `OR1200_OR32_NOP) & id_insn[16]; assign ex_void = (ex_insn[31:26] == `OR1200_OR32_NOP) & ex_insn[16]; assign wb_void = (wb_insn[31:26] == `OR1200_OR32_NOP) & wb_insn[16]; assign ex_spr_write = spr_write && !abort_mvspr; assign ex_spr_read = spr_read && !abort_mvspr; // // ex_delayslot_dsi: delay slot insn is in EX stage // ex_delayslot_nop: (filler) nop insn is in EX stage (before nops jump/branch was executed) // // ex_delayslot_dsi & !ex_delayslot_nop - DS insn in EX stage // !ex_delayslot_dsi & ex_delayslot_nop - NOP insn in EX stage, // next different is DS insn, previous different was Jump/Branch // !ex_delayslot_dsi & !ex_delayslot_nop - normal insn in EX stage // always @(posedge clk or posedge rst) begin if (rst) begin ex_delayslot_nop <= #1 1'b0; ex_delayslot_dsi <= #1 1'b0; end else if (!ex_freeze & !ex_delayslot_dsi & ex_delayslot_nop) begin ex_delayslot_nop <= #1 id_void; ex_delayslot_dsi <= #1 !id_void; end else if (!ex_freeze & ex_delayslot_dsi & !ex_delayslot_nop) begin ex_delayslot_nop <= #1 1'b0; ex_delayslot_dsi <= #1 1'b0; end else if (!ex_freeze) begin ex_delayslot_nop <= #1 id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) && (ex_branch_op != `OR1200_BRANCHOP_RFE); ex_delayslot_dsi <= #1 !id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) && (ex_branch_op != `OR1200_BRANCHOP_RFE); end end // // Flush pipeline // assign if_flushpipe = except_flushpipe | pc_we | extend_flush; assign id_flushpipe = except_flushpipe | pc_we | extend_flush; assign ex_flushpipe = except_flushpipe | pc_we | extend_flush; assign wb_flushpipe = except_flushpipe | pc_we | extend_flush; // // EX Sign/Zero extension of immediates // always @(posedge clk or posedge rst) begin if (rst) ex_simm <= #1 32'h0000_0000; else if (!ex_freeze) begin ex_simm <= #1 id_simm; end end // // ID Sign/Zero extension of immediate // always @(id_insn) begin case (id_insn[31:26]) // synopsys parallel_case // l.addi `OR1200_OR32_ADDI: id_simm = {{16{id_insn[15]}}, id_insn[15:0]}; // l.addic `OR1200_OR32_ADDIC: id_simm = {{16{id_insn[15]}}, id_insn[15:0]}; // l.lxx (load instructions) `OR1200_OR32_LWZ, `OR1200_OR32_LBZ, `OR1200_OR32_LBS, `OR1200_OR32_LHZ, `OR1200_OR32_LHS: id_simm = {{16{id_insn[15]}}, id_insn[15:0]}; // l.muli `ifdef OR1200_MULT_IMPLEMENTED `OR1200_OR32_MULI: id_simm = {{16{id_insn[15]}}, id_insn[15:0]}; `endif // l.maci `ifdef OR1200_MAC_IMPLEMENTED `OR1200_OR32_MACI: id_simm = {{16{id_insn[25]}}, id_insn[25:21], id_insn[10:0]}; `endif // l.mtspr `OR1200_OR32_MTSPR: id_simm = {16'b0, id_insn[25:21], id_insn[10:0]}; // l.sxx (store instructions) `OR1200_OR32_SW, `OR1200_OR32_SH, `OR1200_OR32_SB: id_simm = {{16{id_insn[25]}}, id_insn[25:21], id_insn[10:0]}; // l.xori `OR1200_OR32_XORI: id_simm = {{16{id_insn[15]}}, id_insn[15:0]}; // l.sfxxi (SFXX with immediate) `OR1200_OR32_SFXXI: id_simm = {{16{id_insn[15]}}, id_insn[15:0]}; // Instructions with no or zero extended immediate default: id_simm = {{16'b0}, id_insn[15:0]}; endcase end // // ID Sign extension of branch offset // assign id_branch_addrtarget = {{4{id_insn[25]}}, id_insn[25:0]} + id_pc[31:2]; // // EX Sign extension of branch offset // // pipeline ID and EX branch target address always @(posedge clk or posedge rst) begin if (rst) ex_branch_addrtarget <= #1 32'h00000000; else if (!ex_freeze) ex_branch_addrtarget <= #1 id_branch_addrtarget; end // not pipelined //assign ex_branch_addrtarget = {{4{ex_insn[25]}}, ex_insn[25:0]} + ex_pc[31:2]; // // l.maci in IF stage // `ifdef OR1200_MAC_IMPLEMENTED assign if_maci_op = (if_insn[31:26] == `OR1200_OR32_MACI); `else assign if_maci_op = 1'b0; `endif // // l.macrc in ID stage // `ifdef OR1200_MAC_IMPLEMENTED assign id_macrc_op = (id_insn[31:26] == `OR1200_OR32_MOVHI) & id_insn[16]; `else assign id_macrc_op = 1'b0; `endif // // l.macrc in EX stage // `ifdef OR1200_MAC_IMPLEMENTED always @(posedge clk or posedge rst) begin if (rst) ex_macrc_op <= #1 1'b0; else if (!ex_freeze & id_freeze | ex_flushpipe) ex_macrc_op <= #1 1'b0; else if (!ex_freeze) ex_macrc_op <= #1 id_macrc_op; end `else assign ex_macrc_op = 1'b0; `endif // // cust5_op, cust5_limm (L immediate) // assign cust5_op = ex_insn[4:0]; assign cust5_limm = ex_insn[10:5]; // // // assign rfe = (id_branch_op == `OR1200_BRANCHOP_RFE) | (ex_branch_op == `OR1200_BRANCHOP_RFE); // // Generation of sel_a // always @(rf_addrw or id_insn or rfwb_op or wbforw_valid or wb_rfaddrw) if ((id_insn[20:16] == rf_addrw) && rfwb_op[0]) sel_a = `OR1200_SEL_EX_FORW; else if ((id_insn[20:16] == wb_rfaddrw) && wbforw_valid) sel_a = `OR1200_SEL_WB_FORW; else sel_a = `OR1200_SEL_RF; // // Generation of sel_b // always @(rf_addrw or sel_imm or id_insn or rfwb_op or wbforw_valid or wb_rfaddrw) if (sel_imm) sel_b = `OR1200_SEL_IMM; else if ((id_insn[15:11] == rf_addrw) && rfwb_op[0]) sel_b = `OR1200_SEL_EX_FORW; else if ((id_insn[15:11] == wb_rfaddrw) && wbforw_valid) sel_b = `OR1200_SEL_WB_FORW; else sel_b = `OR1200_SEL_RF; // // Decode of multicycle // always @(id_insn) begin case (id_insn[31:26]) // synopsys parallel_case `ifdef UNUSED // l.lwz `OR1200_OR32_LWZ: multicycle = `OR1200_TWO_CYCLES; // l.lbz `OR1200_OR32_LBZ: multicycle = `OR1200_TWO_CYCLES; // l.lbs `OR1200_OR32_LBS: multicycle = `OR1200_TWO_CYCLES; // l.lhz `OR1200_OR32_LHZ: multicycle = `OR1200_TWO_CYCLES; // l.lhs `OR1200_OR32_LHS: multicycle = `OR1200_TWO_CYCLES; // l.sw `OR1200_OR32_SW: multicycle = `OR1200_TWO_CYCLES; // l.sb `OR1200_OR32_SB: multicycle = `OR1200_TWO_CYCLES; // l.sh `OR1200_OR32_SH: multicycle = `OR1200_TWO_CYCLES; `endif // l.mfspr `OR1200_OR32_MFSPR: multicycle = `OR1200_TWO_CYCLES; // to read from ITLB/DTLB (sync RAMs) // ALU instructions except the one with immediate `OR1200_OR32_ALU: case (id_insn[3:0]) // synopsys parallel_case 4'h6: multicycle = 2'b11; // l.mul 4'h9: multicycle = 2'b10; // l.div 4'hA: multicycle = 2'b10; // l.divu 4'hB: multicycle = 2'b11; // l.mulu default: multicycle = 2'b00; endcase `OR1200_OR32_MULI: multicycle = 2'h3; // Single cycle instructions default: begin multicycle = `OR1200_ONE_CYCLE; end endcase end // // Register file write address // always @(posedge clk or posedge rst) begin if (rst) rf_addrw <= #1 5'd0; else if (!ex_freeze & id_freeze) rf_addrw <= #1 5'd00; else if (!ex_freeze) case (id_insn[31:26]) // synopsys parallel_case `OR1200_OR32_JAL, `OR1200_OR32_JALR: rf_addrw <= #1 5'd09; // link register r9 default: rf_addrw <= #1 id_insn[25:21]; endcase end // // rf_addrw in wb stage (used in forwarding logic) // always @(posedge clk or posedge rst) begin if (rst) wb_rfaddrw <= #1 5'd0; else if (!wb_freeze) wb_rfaddrw <= #1 rf_addrw; end // // Instruction latch in id_insn // always @(posedge clk or posedge rst) begin if (rst) id_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; else if (id_flushpipe) id_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> id_insn[16] must be 1 else if (!id_freeze) begin id_insn <= #1 if_insn; `ifdef OR1200_VERBOSE // synopsys translate_off $display("%t: id_insn <= %h", $time, if_insn); // synopsys translate_on `endif end end // // Instruction latch in ex_insn // always @(posedge clk or posedge rst) begin if (rst) ex_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; else if (!ex_freeze & id_freeze | ex_flushpipe) ex_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> ex_insn[16] must be 1 else if (!ex_freeze) begin ex_insn <= #1 id_insn; `ifdef OR1200_VERBOSE // synopsys translate_off $display("%t: ex_insn <= %h", $time, id_insn); // synopsys translate_on `endif end end // // Instruction latch in wb_insn // always @(posedge clk or posedge rst) begin if (rst) wb_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // wb_insn should not be changed by exceptions due to correct // recording of display_arch_state in the or1200_monitor! // wb_insn changed by exception is not used elsewhere! else if (!wb_freeze) begin wb_insn <= #1 ex_insn; end end // // Decode of sel_imm // always @(posedge clk or posedge rst) begin if (rst) sel_imm <= #1 1'b0; else if (!id_freeze) begin case (if_insn[31:26]) // synopsys parallel_case // j.jalr `OR1200_OR32_JALR: sel_imm <= #1 1'b0; // l.jr `OR1200_OR32_JR: sel_imm <= #1 1'b0; // l.rfe `OR1200_OR32_RFE: sel_imm <= #1 1'b0; // l.mfspr `OR1200_OR32_MFSPR: sel_imm <= #1 1'b0; // l.mtspr `OR1200_OR32_MTSPR: sel_imm <= #1 1'b0; // l.sys, l.brk and all three sync insns `OR1200_OR32_XSYNC: sel_imm <= #1 1'b0; // l.mac/l.msb `ifdef OR1200_MAC_IMPLEMENTED `OR1200_OR32_MACMSB: sel_imm <= #1 1'b0; `endif // l.sw `OR1200_OR32_SW: sel_imm <= #1 1'b0; // l.sb `OR1200_OR32_SB: sel_imm <= #1 1'b0; // l.sh `OR1200_OR32_SH: sel_imm <= #1 1'b0; // ALU instructions except the one with immediate `OR1200_OR32_ALU: sel_imm <= #1 1'b0; // SFXX instructions `OR1200_OR32_SFXX: sel_imm <= #1 1'b0; `ifdef OR1200_OR32_CUST5 // l.cust5 instructions `OR1200_OR32_CUST5: sel_imm <= #1 1'b0; `endif // l.nop `OR1200_OR32_NOP: sel_imm <= #1 1'b0; // All instructions with immediates default: begin sel_imm <= #1 1'b1; end endcase end end // // Decode of except_illegal // always @(posedge clk or posedge rst) begin if (rst) except_illegal <= #1 1'b0; else if (!ex_freeze & id_freeze | ex_flushpipe) except_illegal <= #1 1'b0; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys parallel_case `OR1200_OR32_J, `OR1200_OR32_JAL, `OR1200_OR32_JALR, `OR1200_OR32_JR, `OR1200_OR32_BNF, `OR1200_OR32_BF, `OR1200_OR32_RFE, `OR1200_OR32_MOVHI, `OR1200_OR32_MFSPR, `OR1200_OR32_XSYNC, `ifdef OR1200_MAC_IMPLEMENTED `OR1200_OR32_MACI, `endif `OR1200_OR32_LWZ, `OR1200_OR32_LBZ, `OR1200_OR32_LBS, `OR1200_OR32_LHZ, `OR1200_OR32_LHS, `OR1200_OR32_ADDI, `OR1200_OR32_ADDIC, `OR1200_OR32_ANDI, `OR1200_OR32_ORI, `OR1200_OR32_XORI, `ifdef OR1200_MULT_IMPLEMENTED `OR1200_OR32_MULI, `endif `OR1200_OR32_SH_ROTI, `OR1200_OR32_SFXXI, `OR1200_OR32_MTSPR, `ifdef OR1200_MAC_IMPLEMENTED `OR1200_OR32_MACMSB, `endif `OR1200_OR32_SW, `OR1200_OR32_SB, `OR1200_OR32_SH, `OR1200_OR32_SFXX, `ifdef OR1200_OR32_CUST5 `OR1200_OR32_CUST5, `endif `OR1200_OR32_NOP: except_illegal <= #1 1'b0; `OR1200_OR32_ALU: except_illegal <= #1 1'b0 `ifdef OR1200_MULT_IMPLEMENTED `ifdef OR1200_IMPL_DIV `else | ({1'b0, id_insn[3:0]} == `OR1200_ALUOP_DIV) | ({1'b0, id_insn[3:0]} == `OR1200_ALUOP_DIVU) `endif `else | ({1'b0, id_insn[3:0]} == `OR1200_ALUOP_DIV) | ({1'b0, id_insn[3:0]} == `OR1200_ALUOP_DIVU) | ({1'b0, id_insn[3:0]} == `OR1200_ALUOP_MUL) `endif `ifdef OR1200_IMPL_ADDC `else | ({1'b0, id_insn[3:0]} == `OR1200_ALUOP_ADDC) `endif `ifdef OR1200_IMPL_ALU_ROTATE `else | (({1'b0, id_insn[3:0]} == `OR1200_ALUOP_SHROT) && (id_insn[7:6] == `OR1200_SHROTOP_ROR)) `endif `ifdef OR1200_IMPL_SUB `else | ({1'b0, id_insn[3:0]} == `OR1200_ALUOP_SUB) `endif ; // Illegal and OR1200 unsupported instructions default: except_illegal <= #1 1'b1; endcase end end // // Decode of alu_op // always @(posedge clk or posedge rst) begin if (rst) alu_op <= #1 `OR1200_ALUOP_NOP; else if (!ex_freeze & id_freeze | ex_flushpipe) alu_op <= #1 `OR1200_ALUOP_NOP; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys parallel_case // l.movhi `OR1200_OR32_MOVHI: alu_op <= #1 `OR1200_ALUOP_MOVHI; // l.addi `OR1200_OR32_ADDI: alu_op <= #1 `OR1200_ALUOP_ADD; // l.addic `OR1200_OR32_ADDIC: alu_op <= #1 `OR1200_ALUOP_ADDC; // l.andi `OR1200_OR32_ANDI: alu_op <= #1 `OR1200_ALUOP_AND; // l.ori `OR1200_OR32_ORI: alu_op <= #1 `OR1200_ALUOP_OR; // l.xori `OR1200_OR32_XORI: alu_op <= #1 `OR1200_ALUOP_XOR; // l.muli `ifdef OR1200_MULT_IMPLEMENTED `OR1200_OR32_MULI: alu_op <= #1 `OR1200_ALUOP_MUL; `endif // Shift and rotate insns with immediate `OR1200_OR32_SH_ROTI: alu_op <= #1 `OR1200_ALUOP_SHROT; // SFXX insns with immediate `OR1200_OR32_SFXXI: alu_op <= #1 `OR1200_ALUOP_COMP; // ALU instructions except the one with immediate `OR1200_OR32_ALU: alu_op <= #1 id_insn[3:0]; // SFXX instructions `OR1200_OR32_SFXX: alu_op <= #1 `OR1200_ALUOP_COMP; `ifdef OR1200_OR32_CUST5 // l.cust5 instructions `OR1200_OR32_CUST5: alu_op <= #1 `OR1200_ALUOP_CUST5; `endif // Default default: begin alu_op <= #1 `OR1200_ALUOP_NOP; end endcase end end // // Decode of spr_read, spr_write // always @(posedge clk or posedge rst) begin if (rst) begin spr_read <= #1 1'b0; spr_write <= #1 1'b0; end else if (!ex_freeze & id_freeze | ex_flushpipe) begin spr_read <= #1 1'b0; spr_write <= #1 1'b0; end else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys parallel_case // l.mfspr `OR1200_OR32_MFSPR: begin spr_read <= #1 1'b1; spr_write <= #1 1'b0; end // l.mtspr `OR1200_OR32_MTSPR: begin spr_read <= #1 1'b0; spr_write <= #1 1'b1; end // Default default: begin spr_read <= #1 1'b0; spr_write <= #1 1'b0; end endcase end end // // Decode of mac_op // `ifdef OR1200_MAC_IMPLEMENTED always @(id_insn) begin case (id_insn[31:26]) // synopsys parallel_case // l.maci `OR1200_OR32_MACI: id_mac_op <= #1 `OR1200_MACOP_MAC; // l.mac, l.msb `OR1200_OR32_MACMSB: id_mac_op <= #1 id_insn[2:0]; // Illegal and OR1200 unsupported instructions default: id_mac_op <= #1 `OR1200_MACOP_NOP; endcase end always @(posedge clk or posedge rst) begin if (rst) ex_mac_op <= #1 `OR1200_MACOP_NOP; else if (!ex_freeze & id_freeze | ex_flushpipe) ex_mac_op <= #1 `OR1200_MACOP_NOP; else if (!ex_freeze) ex_mac_op <= #1 id_mac_op; end assign mac_op = abort_mvspr ? `OR1200_MACOP_NOP : ex_mac_op; `else assign id_mac_op = `OR1200_MACOP_NOP; assign mac_op = `OR1200_MACOP_NOP; `endif // // Decode of shrot_op // always @(posedge clk or posedge rst) begin if (rst) shrot_op <= #1 `OR1200_SHROTOP_NOP; else if (!ex_freeze & id_freeze | ex_flushpipe) shrot_op <= #1 `OR1200_SHROTOP_NOP; else if (!ex_freeze) begin shrot_op <= #1 id_insn[`OR1200_SHROTOP_POS]; end end // // Decode of rfwb_op // always @(posedge clk or posedge rst) begin if (rst) rfwb_op <= #1 `OR1200_RFWBOP_NOP; else if (!ex_freeze & id_freeze | ex_flushpipe) rfwb_op <= #1 `OR1200_RFWBOP_NOP; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys parallel_case // j.jal `OR1200_OR32_JAL: rfwb_op <= #1 `OR1200_RFWBOP_LR; // j.jalr `OR1200_OR32_JALR: rfwb_op <= #1 `OR1200_RFWBOP_LR; // l.movhi `OR1200_OR32_MOVHI: rfwb_op <= #1 `OR1200_RFWBOP_ALU; // l.mfspr `OR1200_OR32_MFSPR: rfwb_op <= #1 `OR1200_RFWBOP_SPRS; // l.lwz `OR1200_OR32_LWZ: rfwb_op <= #1 `OR1200_RFWBOP_LSU; // l.lbz `OR1200_OR32_LBZ: rfwb_op <= #1 `OR1200_RFWBOP_LSU; // l.lbs `OR1200_OR32_LBS: rfwb_op <= #1 `OR1200_RFWBOP_LSU; // l.lhz `OR1200_OR32_LHZ: rfwb_op <= #1 `OR1200_RFWBOP_LSU; // l.lhs `OR1200_OR32_LHS: rfwb_op <= #1 `OR1200_RFWBOP_LSU; // l.addi `OR1200_OR32_ADDI: rfwb_op <= #1 `OR1200_RFWBOP_ALU; // l.addic `OR1200_OR32_ADDIC: rfwb_op <= #1 `OR1200_RFWBOP_ALU; // l.andi `OR1200_OR32_ANDI: rfwb_op <= #1 `OR1200_RFWBOP_ALU; // l.ori `OR1200_OR32_ORI: rfwb_op <= #1 `OR1200_RFWBOP_ALU; // l.xori `OR1200_OR32_XORI: rfwb_op <= #1 `OR1200_RFWBOP_ALU; // l.muli `ifdef OR1200_MULT_IMPLEMENTED `OR1200_OR32_MULI: rfwb_op <= #1 `OR1200_RFWBOP_ALU; `endif // Shift and rotate insns with immediate `OR1200_OR32_SH_ROTI: rfwb_op <= #1 `OR1200_RFWBOP_ALU; // ALU instructions except the one with immediate `OR1200_OR32_ALU: rfwb_op <= #1 `OR1200_RFWBOP_ALU; `ifdef OR1200_OR32_CUST5 // l.cust5 instructions `OR1200_OR32_CUST5: rfwb_op <= #1 `OR1200_RFWBOP_ALU; `endif // Instructions w/o register-file write-back default: rfwb_op <= #1 `OR1200_RFWBOP_NOP; endcase end end // // Decode of id_branch_op // always @(posedge clk or posedge rst) begin if (rst) id_branch_op <= #1 `OR1200_BRANCHOP_NOP; else if (id_flushpipe) id_branch_op <= #1 `OR1200_BRANCHOP_NOP; else if (!id_freeze) begin case (if_insn[31:26]) // synopsys parallel_case // l.j `OR1200_OR32_J: id_branch_op <= #1 `OR1200_BRANCHOP_J; // j.jal `OR1200_OR32_JAL: id_branch_op <= #1 `OR1200_BRANCHOP_J; // j.jalr `OR1200_OR32_JALR: id_branch_op <= #1 `OR1200_BRANCHOP_JR; // l.jr `OR1200_OR32_JR: id_branch_op <= #1 `OR1200_BRANCHOP_JR; // l.bnf `OR1200_OR32_BNF: id_branch_op <= #1 `OR1200_BRANCHOP_BNF; // l.bf `OR1200_OR32_BF: id_branch_op <= #1 `OR1200_BRANCHOP_BF; // l.rfe `OR1200_OR32_RFE: id_branch_op <= #1 `OR1200_BRANCHOP_RFE; // Non branch instructions default: id_branch_op <= #1 `OR1200_BRANCHOP_NOP; endcase end end // // Generation of ex_branch_op // always @(posedge clk or posedge rst) if (rst) ex_branch_op <= #1 `OR1200_BRANCHOP_NOP; else if (!ex_freeze & id_freeze | ex_flushpipe) ex_branch_op <= #1 `OR1200_BRANCHOP_NOP; else if (!ex_freeze) ex_branch_op <= #1 id_branch_op; // // Decode of id_lsu_op // always @(id_insn) begin case (id_insn[31:26]) // synopsys parallel_case // l.lwz `OR1200_OR32_LWZ: id_lsu_op <= #1 `OR1200_LSUOP_LWZ; // l.lbz `OR1200_OR32_LBZ: id_lsu_op <= #1 `OR1200_LSUOP_LBZ; // l.lbs `OR1200_OR32_LBS: id_lsu_op <= #1 `OR1200_LSUOP_LBS; // l.lhz `OR1200_OR32_LHZ: id_lsu_op <= #1 `OR1200_LSUOP_LHZ; // l.lhs `OR1200_OR32_LHS: id_lsu_op <= #1 `OR1200_LSUOP_LHS; // l.sw `OR1200_OR32_SW: id_lsu_op <= #1 `OR1200_LSUOP_SW; // l.sb `OR1200_OR32_SB: id_lsu_op <= #1 `OR1200_LSUOP_SB; // l.sh `OR1200_OR32_SH: id_lsu_op <= #1 `OR1200_LSUOP_SH; // Non load/store instructions default: id_lsu_op <= #1 `OR1200_LSUOP_NOP; endcase end // // Decode of comp_op // always @(posedge clk or posedge rst) begin if (rst) begin comp_op <= #1 4'd0; end else if (!ex_freeze & id_freeze | ex_flushpipe) comp_op <= #1 4'd0; else if (!ex_freeze) comp_op <= #1 id_insn[24:21]; end // // Decode of l.sys // always @(posedge clk or posedge rst) begin if (rst) sig_syscall <= #1 1'b0; else if (!ex_freeze & id_freeze | ex_flushpipe) sig_syscall <= #1 1'b0; else if (!ex_freeze) begin `ifdef OR1200_VERBOSE // synopsys translate_off if (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b000}) $display("Generating sig_syscall"); // synopsys translate_on `endif sig_syscall <= #1 (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b000}); end end // // Decode of l.trap // always @(posedge clk or posedge rst) begin if (rst) sig_trap <= #1 1'b0; else if (!ex_freeze & id_freeze | ex_flushpipe) sig_trap <= #1 1'b0; else if (!ex_freeze) begin `ifdef OR1200_VERBOSE // synopsys translate_off if (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b010}) $display("Generating sig_trap"); // synopsys translate_on `endif sig_trap <= #1 (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b010}) | du_hwbkpt; end end endmodule
Go to most recent revision | Compare with Previous | Blame | View Log