📄 or1200_ctrl.v
字号:
////////////////////////////////////////////////////////////////////////// //////// 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 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 id_freeze, ex_freeze, wb_freeze, flushpipe, if_insn, ex_insn, branch_op, branch_taken, rf_addra, rf_addrb, rf_rda, rf_rdb, alu_op, mac_op, shrot_op, comp_op, rf_addrw, rfwb_op, wb_insn, simm, branch_addrofs, lsu_addrofs, sel_a, sel_b, lsu_op, multicycle, spr_addrimm, wbforw_valid, sig_syscall, sig_trap, force_dslot_fetch, no_more_dslot, ex_void, id_macrc_op, ex_macrc_op, rfe, except_illegal);//// I/O//input clk;input rst;input id_freeze;input ex_freeze;input wb_freeze;input flushpipe;input [31:0] if_insn;output [31:0] ex_insn;output [`OR1200_BRANCHOP_WIDTH-1:0] branch_op;input 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;output [31:0] wb_insn;output [31:0] simm;output [31:2] branch_addrofs;output [31:0] lsu_addrofs;output [`OR1200_SEL_WIDTH-1:0] sel_a;output [`OR1200_SEL_WIDTH-1:0] sel_b;output [`OR1200_LSUOP_WIDTH-1:0] lsu_op;output [`OR1200_COMPOP_WIDTH-1:0] comp_op;output [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;output [15:0] spr_addrimm;input wbforw_valid;output sig_syscall;output sig_trap;output force_dslot_fetch;output no_more_dslot;output ex_void;output id_macrc_op;output ex_macrc_op;output rfe;output except_illegal;//// Internal wires and regs//reg [`OR1200_BRANCHOP_WIDTH-1:0] pre_branch_op;reg [`OR1200_BRANCHOP_WIDTH-1:0] branch_op;reg [`OR1200_ALUOP_WIDTH-1:0] alu_op;`ifdef OR1200_MAC_IMPLEMENTEDreg [`OR1200_MACOP_WIDTH-1:0] mac_op;reg ex_macrc_op;`elsewire [`OR1200_MACOP_WIDTH-1:0] mac_op;wire ex_macrc_op;`endifreg [`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 [31:0] lsu_addrofs;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] lsu_op;reg [`OR1200_COMPOP_WIDTH-1:0] comp_op;reg [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;reg imm_signextend;reg [15:0] spr_addrimm;reg sig_syscall;reg sig_trap;reg except_illegal;wire id_void;//// Register file read addresses//assign rf_addra = if_insn[20:16];assign rf_addrb = if_insn[15:11];assign rf_rda = if_insn[31];assign rf_rdb = if_insn[30];//// Force fetch of delay slot instruction when jump/branch is preceeded by load/store// instructions//// SIMON// assign force_dslot_fetch = ((|pre_branch_op) & (|lsu_op));assign force_dslot_fetch = 1'b0;assign no_more_dslot = |branch_op & !id_void & branch_taken | (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];//// Sign/Zero extension of immediates//assign simm = (imm_signextend == 1'b1) ? {{16{id_insn[15]}}, id_insn[15:0]} : {{16'b0}, id_insn[15:0]};//// Sign extension of branch offset//assign branch_addrofs = {{4{ex_insn[25]}}, ex_insn[25:0]};//// l.macrc in ID stage//`ifdef OR1200_MAC_IMPLEMENTEDassign id_macrc_op = (id_insn[31:26] == `OR1200_OR32_MOVHI) & id_insn[16];`elseassign id_macrc_op = 1'b0;`endif//////assign rfe = (pre_branch_op == `OR1200_BRANCHOP_RFE) | (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;//// l.macrc in EX stage//`ifdef OR1200_MAC_IMPLEMENTEDalways @(posedge clk or posedge rst) begin if (rst) ex_macrc_op <= #1 1'b0; else if (!ex_freeze & id_freeze | flushpipe) ex_macrc_op <= #1 1'b0; else if (!ex_freeze) ex_macrc_op <= #1 id_macrc_op;end`elseassign ex_macrc_op = 1'b0;`endif//// Decode of spr_addrimm//always @(posedge clk or posedge rst) begin if (rst) spr_addrimm <= #1 16'h0000; else if (!ex_freeze & id_freeze | flushpipe) spr_addrimm <= #1 16'h0000; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys parallel_case // l.mfspr `OR1200_OR32_MFSPR: spr_addrimm <= #1 id_insn[15:0]; // l.mtspr default: spr_addrimm <= #1 {id_insn[25:21], id_insn[10:0]}; endcase endend//// 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 // ALU instructions except the one with immediate `OR1200_OR32_ALU: multicycle = id_insn[`OR1200_ALUMCYC_POS]; // Single cycle instructions default: begin multicycle = `OR1200_ONE_CYCLE; end endcase end//// Decode of imm_signextend//always @(id_insn) begin case (id_insn[31:26]) // synopsys parallel_case // l.addi `OR1200_OR32_ADDI: imm_signextend = 1'b1; // l.addic `OR1200_OR32_ADDIC: imm_signextend = 1'b1; // l.xori `OR1200_OR32_XORI: imm_signextend = 1'b1; // l.muli`ifdef OR1200_MULT_IMPLEMENTED `OR1200_OR32_MULI: imm_signextend = 1'b1;`endif // l.maci`ifdef OR1200_MAC_IMPLEMENTED `OR1200_OR32_MACI: imm_signextend = 1'b1;`endif // SFXX insns with immediate `OR1200_OR32_SFXXI: imm_signextend = 1'b1; // Instructions with no or zero extended immediate default: begin imm_signextend = 1'b0; endendcaseend//// LSU addr offset//always @(lsu_op or ex_insn) begin lsu_addrofs[10:0] = ex_insn[10:0]; case(lsu_op) // synopsys parallel_case `OR1200_LSUOP_SW, `OR1200_LSUOP_SH, `OR1200_LSUOP_SB : lsu_addrofs[31:11] = {{16{ex_insn[25]}}, ex_insn[25:21]}; default : lsu_addrofs[31:11] = {{16{ex_insn[15]}}, ex_insn[15:11]}; endcaseend//// 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 (pre_branch_op) // synopsys parallel_case `OR1200_BRANCHOP_JR, `OR1200_BRANCHOP_BAL: rf_addrw <= #1 5'd09; // link register r9 default: rf_addrw <= #1 id_insn[25:21]; endcaseend//// 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 (flushpipe) id_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // 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 endend//// 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 | flushpipe) ex_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // 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 endend//// Instruction latch in wb_insn//always @(posedge clk or posedge rst) begin if (rst) wb_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; else if (flushpipe) wb_insn <= #1 {`OR1200_OR32_NOP, 26'h041_0000}; // wb_insn[16] must be 1 else if (!wb_freeze) begin wb_insn <= #1 ex_insn; endend//// 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -