URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [mp3/] [rtl/] [verilog/] [or1200.xcv/] [id.v] - Rev 1765
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: not supported by cvs2svn $ // 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. // // `include "timescale.v" `include "defines.v" module id( // Clock and reset clk, rst, // Internal i/f id_freeze, ex_freeze, wb_freeze, except_flushpipe, if_insn, branch_op, rf_addra, rf_addrb, alu_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, id_macrc_op, ex_macrc_op ); // // I/O // input clk; input rst; input id_freeze; input ex_freeze; input wb_freeze; input except_flushpipe; input [31:0] if_insn; output [`BRANCHOP_WIDTH-1:0] branch_op; output [`REGFILE_ADDR_WIDTH-1:0] rf_addrw; output [`REGFILE_ADDR_WIDTH-1:0] rf_addra; output [`REGFILE_ADDR_WIDTH-1:0] rf_addrb; output [`ALUOP_WIDTH-1:0] alu_op; output [`SHROTOP_WIDTH-1:0] shrot_op; output [`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 [`SEL_WIDTH-1:0] sel_a; output [`SEL_WIDTH-1:0] sel_b; output [`LSUOP_WIDTH-1:0] lsu_op; output [`COMPOP_WIDTH-1:0] comp_op; output [`MULTICYCLE_WIDTH-1:0] multicycle; output [15:0] spr_addrimm; input wbforw_valid; output sig_syscall; output sig_trap; output force_dslot_fetch; output id_macrc_op; output ex_macrc_op; // // Internal wires and regs // reg [`BRANCHOP_WIDTH-1:0] pre_branch_op; reg [`BRANCHOP_WIDTH-1:0] branch_op; reg [`ALUOP_WIDTH-1:0] alu_op; reg [`SHROTOP_WIDTH-1:0] shrot_op; reg [31:0] id_insn; reg [31:0] ex_insn; reg [31:0] wb_insn; reg [`REGFILE_ADDR_WIDTH-1:0] rf_addrw; reg [`REGFILE_ADDR_WIDTH-1:0] wb_rfaddrw; reg [`RFWBOP_WIDTH-1:0] rfwb_op; reg [31:0] lsu_addrofs; reg [`SEL_WIDTH-1:0] sel_a; reg [`SEL_WIDTH-1:0] sel_b; reg sel_imm; reg [`LSUOP_WIDTH-1:0] lsu_op; reg [`COMPOP_WIDTH-1:0] comp_op; reg [`MULTICYCLE_WIDTH-1:0] multicycle; reg imm_signextend; reg [15:0] spr_addrimm; reg sig_syscall; reg sig_trap; wire rst_or_except_flushpipe; reg ex_macrc_op; // // Register file read addresses // assign rf_addra = if_insn[20:16]; assign rf_addrb = if_insn[15:11]; // // Force fetch of delay slot instruction when jump/branch is preceeded by load/store // instructions // assign force_dslot_fetch = ((|pre_branch_op) & (|lsu_op)); // // Sign/Zero extension of immediates // assign simm = (imm_signextend == `on) ? {{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]}; // // Async reset for most of pipeline flops // assign rst_or_except_flushpipe = rst | except_flushpipe; // // l.macrc in ID stage // assign id_macrc_op = (id_insn[31:26] == 6'b00_0110) & id_insn[16]; // // 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 = `SEL_EX_FORW; else if ((id_insn[20:16] == wb_rfaddrw) && wbforw_valid) sel_a = `SEL_WB_FORW; else sel_a = `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 = `SEL_IMM; else if ((id_insn[15:11] == rf_addrw) && rfwb_op[0]) sel_b = `SEL_EX_FORW; else if ((id_insn[15:11] == wb_rfaddrw) && wbforw_valid) sel_b = `SEL_WB_FORW; else sel_b = `SEL_RF; // // l.macrc in EX stage // always @(posedge clk or posedge rst_or_except_flushpipe) begin if (rst_or_except_flushpipe) ex_macrc_op <= #1 1'b0; else if (!ex_freeze & id_freeze) ex_macrc_op <= #1 1'b0; else if (!ex_freeze) ex_macrc_op <= #1 id_macrc_op; end // // Decode of spr_addrimm // always @(posedge clk or posedge rst_or_except_flushpipe) begin if (rst_or_except_flushpipe) spr_addrimm <= #1 16'h0000; else if (!ex_freeze & id_freeze) spr_addrimm <= #1 16'h0000; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys full_case parallel_case // l.mfspr `OR32_MFSPR: spr_addrimm <= #1 id_insn[15:0]; // l.mtspr default: spr_addrimm <= #1 {id_insn[25:21], id_insn[10:0]}; endcase end end // // Decode of multicycle // always @(id_insn) begin case (id_insn[31:26]) // synopsys full_case parallel_case // l.lwz `OR32_LWZ: multicycle = `TWO_CYCLES; // l.lbz `OR32_LBZ: multicycle = `TWO_CYCLES; // l.lbs `OR32_LBS: multicycle = `TWO_CYCLES; // l.lhz `OR32_LHZ: multicycle = `TWO_CYCLES; // l.lhs `OR32_LHS: multicycle = `TWO_CYCLES; // l.sw `OR32_SW: multicycle = `TWO_CYCLES; // l.sb `OR32_SB: multicycle = `TWO_CYCLES; // l.sh `OR32_SH: multicycle = `TWO_CYCLES; // ALU instructions except the one with immediate `OR32_ALU: multicycle = id_insn[`ALUMCYC_POS]; // Single cycle instructions default: begin multicycle = `ONE_CYCLE; end endcase end // // Decode of imm_signextend // always @(id_insn) begin case (id_insn[31:26]) // synopsys full_case parallel_case // l.addi `OR32_ADDI: imm_signextend = `on; // l.addic `OR32_ADDIC: imm_signextend = `on; // l.xori `OR32_XORI: imm_signextend = `on; // l.muli `OR32_MULI: imm_signextend = `on; // l.maci `OR32_MACI: imm_signextend = `on; // SFXX insns with immediate `OR32_SFXXI: imm_signextend = `on; // Instructions with no or zero extended immediate default: begin imm_signextend = `off; end endcase end // // LSU addr offset // always @(lsu_op or ex_insn) begin lsu_addrofs[10:0] = ex_insn[10:0]; case(lsu_op) // synopsys parallel_case full_case `LSUOP_SW, `LSUOP_SH, `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]}; 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 (pre_branch_op) // synopsys parallel_case full_case `BRANCHOP_JR, `BRANCHOP_BAL: 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) begin id_insn[31:26] <= #1 `OR32_NOP; id_insn[25:0] <= #1 26'd0; end 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) begin ex_insn[31:26] <= #1 `OR32_NOP; ex_insn[25:0] <= #1 26'd0; end else if (!ex_freeze & id_freeze) ex_insn <= #1 {`OR32_NOP, 26'h000_4444}; 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) begin wb_insn[31:26] <= #1 `OR32_NOP; wb_insn[25:0] <= #1 26'd0; end 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 full_case parallel_case // j.jalr `OR32_JALR: sel_imm <= #1 `off; // l.jr `OR32_JR: sel_imm <= #1 `off; // l.rfe `OR32_RFE: sel_imm <= #1 `off; // l.mfspr `OR32_MFSPR: sel_imm <= #1 `off; // l.mtspr `OR32_MTSPR: sel_imm <= #1 `off; // l.sys, l.brk and all three sync insns `OR32_XSYNC: sel_imm <= #1 `off; // l.sw `OR32_SW: sel_imm <= #1 `off; // l.sb `OR32_SB: sel_imm <= #1 `off; // l.sh `OR32_SH: sel_imm <= #1 `off; // ALU instructions except the one with immediate `OR32_ALU: sel_imm <= #1 `off; // SFXX instructions `OR32_SFXX: sel_imm <= #1 `off; // l.nop `OR32_NOP: sel_imm <= #1 `off; // All instructions with immediates default: begin sel_imm <= #1 `on; end endcase end end // // Decode of alu_op // always @(posedge clk or posedge rst_or_except_flushpipe) begin if (rst_or_except_flushpipe) alu_op <= #1 `ALUOP_NOP; else if (!ex_freeze & id_freeze) alu_op <= #1 `ALUOP_NOP; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys full_case parallel_case // l.j `OR32_J: alu_op <= #1 `ALUOP_IMM; // j.jal `OR32_JAL: alu_op <= #1 `ALUOP_IMM; // j.jalr `OR32_JALR: alu_op <= #1 `ALUOP_OR; // l.jr `OR32_JR: alu_op <= #1 `ALUOP_ADD; // l.bnf `OR32_BNF: alu_op <= #1 `ALUOP_ADD; // l.bf `OR32_BF: alu_op <= #1 `ALUOP_ADD; // l.rfe `OR32_RFE: alu_op <= #1 `ALUOP_NOP; // l.movhi `OR32_MOVHI: alu_op <= #1 `ALUOP_MOVHI; // l.mfspr `OR32_MFSPR: alu_op <= #1 `ALUOP_MFSR; // l.mtspr `OR32_MTSPR: alu_op <= #1 `ALUOP_MTSR; // l.sys, l.brk and all three sync insns `OR32_XSYNC: alu_op <= #1 `ALUOP_NOP; // l.lwz `OR32_LWZ: alu_op <= #1 `ALUOP_ADD; // l.lbz `OR32_LBZ: alu_op <= #1 `ALUOP_ADD; // l.lbs `OR32_LBS: alu_op <= #1 `ALUOP_ADD; // l.lhz `OR32_LHZ: alu_op <= #1 `ALUOP_ADD; // l.lhs `OR32_LHS: alu_op <= #1 `ALUOP_ADD; // l.addi `OR32_ADDI: alu_op <= #1 `ALUOP_ADD; // l.addic `OR32_ADDIC: alu_op <= #1 `ALUOP_ADD; // l.andi `OR32_ANDI: alu_op <= #1 `ALUOP_AND; // l.ori `OR32_ORI: alu_op <= #1 `ALUOP_OR; // l.xori `OR32_XORI: alu_op <= #1 `ALUOP_XOR; // l.muli `OR32_MULI: alu_op <= #1 `ALUOP_MUL; // l.maci `OR32_MACI: alu_op <= #1 `ALUOP_MAC; // Shift and rotate insns with immediate `OR32_SH_ROTI: alu_op <= #1 `ALUOP_SHROT; // SFXX insns with immediate `OR32_SFXXI: alu_op <= #1 `ALUOP_COMP; // l.sw `OR32_SW: alu_op <= #1 `ALUOP_ADD; // l.sb `OR32_SB: alu_op <= #1 `ALUOP_ADD; // l.sh `OR32_SH: alu_op <= #1 `ALUOP_ADD; // ALU instructions except the one with immediate `OR32_ALU: alu_op <= #1 id_insn[3:0]; // SFXX instructions `OR32_SFXX: alu_op <= #1 `ALUOP_COMP; // l.nop `OR32_NOP: alu_op <= #1 `ALUOP_NOP; // Illegal and OR1200 unsupported instructions default: begin alu_op <= #1 `ALUOP_NOP; `ifdef OR1200_VERBOSE // synopsys translate_off $display("%t: Illegal insn.... insn %h", $time, id_insn); // synopsys translate_on `endif end endcase end end // // Decode of shrot_op // always @(posedge clk or posedge rst_or_except_flushpipe) begin if (rst_or_except_flushpipe) shrot_op <= #1 `SHROTOP_NOP; else if (!ex_freeze & id_freeze) shrot_op <= #1 `SHROTOP_NOP; else if (!ex_freeze) begin shrot_op <= #1 id_insn[`SHROTOP_POS]; end end // // Decode of rfwb_op // always @(posedge clk or posedge rst_or_except_flushpipe) begin if (rst_or_except_flushpipe) rfwb_op <= #1 `RFWBOP_NOP; else if (!ex_freeze & id_freeze) rfwb_op <= #1 `RFWBOP_NOP; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys full_case parallel_case // j.jal `OR32_JAL: rfwb_op <= #1 `RFWBOP_LR; // j.jalr `OR32_JALR: rfwb_op <= #1 `RFWBOP_LR; // l.movhi `OR32_MOVHI: rfwb_op <= #1 `RFWBOP_ALU; // l.mfspr `OR32_MFSPR: rfwb_op <= #1 `RFWBOP_SPRS; // l.lwz `OR32_LWZ: rfwb_op <= #1 `RFWBOP_LSU; // l.lbz `OR32_LBZ: rfwb_op <= #1 `RFWBOP_LSU; // l.lbs `OR32_LBS: rfwb_op <= #1 `RFWBOP_LSU; // l.lhz `OR32_LHZ: rfwb_op <= #1 `RFWBOP_LSU; // l.lhs `OR32_LHS: rfwb_op <= #1 `RFWBOP_LSU; // l.addi `OR32_ADDI: rfwb_op <= #1 `RFWBOP_ALU; // l.addic `OR32_ADDIC: rfwb_op <= #1 `RFWBOP_ALU; // l.andi `OR32_ANDI: rfwb_op <= #1 `RFWBOP_ALU; // l.ori `OR32_ORI: rfwb_op <= #1 `RFWBOP_ALU; // l.xori `OR32_XORI: rfwb_op <= #1 `RFWBOP_ALU; // l.muli `OR32_MULI: rfwb_op <= #1 `RFWBOP_ALU; // l.maci `OR32_MACI: rfwb_op <= #1 `RFWBOP_ALU; // Shift and rotate insns with immediate `OR32_SH_ROTI: rfwb_op <= #1 `RFWBOP_ALU; // ALU instructions except the one with immediate `OR32_ALU: rfwb_op <= #1 `RFWBOP_ALU; // Instructions w/o register-file write-back default: begin rfwb_op <= #1 `RFWBOP_NOP; end endcase end end // // Decode of pre_branch_op // always @(posedge clk or posedge rst_or_except_flushpipe) begin if (rst_or_except_flushpipe) pre_branch_op <= #1 `BRANCHOP_NOP; else if (!id_freeze) begin case (if_insn[31:26]) // synopsys full_case parallel_case // l.j `OR32_J: pre_branch_op <= #1 `BRANCHOP_BAL; // j.jal `OR32_JAL: pre_branch_op <= #1 `BRANCHOP_BAL; // j.jalr `OR32_JALR: pre_branch_op <= #1 `BRANCHOP_JR; // l.jr `OR32_JR: pre_branch_op <= #1 `BRANCHOP_JR; // l.bnf `OR32_BNF: pre_branch_op <= #1 `BRANCHOP_BNF; // l.bf `OR32_BF: pre_branch_op <= #1 `BRANCHOP_BF; // l.rfe `OR32_RFE: pre_branch_op <= #1 `BRANCHOP_RFE; // Non branch instructions default: begin pre_branch_op <= #1 `BRANCHOP_NOP; end endcase end end // // Generation of branch_op // always @(posedge clk or posedge rst_or_except_flushpipe) begin if (rst_or_except_flushpipe) branch_op <= #1 `BRANCHOP_NOP; else if (!ex_freeze & id_freeze) branch_op <= #1 `BRANCHOP_NOP; else if (!ex_freeze) begin branch_op <= #1 pre_branch_op; end end // // Decode of lsu_op // always @(posedge clk or posedge rst_or_except_flushpipe) begin if (rst_or_except_flushpipe) lsu_op <= #1 `LSUOP_NOP; else if (!ex_freeze & id_freeze) lsu_op <= #1 `LSUOP_NOP; else if (!ex_freeze) begin case (id_insn[31:26]) // synopsys full_case parallel_case // l.lwz `OR32_LWZ: lsu_op <= #1 `LSUOP_LWZ; // l.lbz `OR32_LBZ: lsu_op <= #1 `LSUOP_LBZ; // l.lbs `OR32_LBS: lsu_op <= #1 `LSUOP_LBS; // l.lhz `OR32_LHZ: lsu_op <= #1 `LSUOP_LHZ; // l.lhs `OR32_LHS: lsu_op <= #1 `LSUOP_LHS; // l.sw `OR32_SW: lsu_op <= #1 `LSUOP_SW; // l.sb `OR32_SB: lsu_op <= #1 `LSUOP_SB; // l.sh `OR32_SH: lsu_op <= #1 `LSUOP_SH; // Non load/store instructions default: begin lsu_op <= #1 `LSUOP_NOP; end endcase end end // // Decode of comp_op // always @(posedge clk or posedge rst_or_except_flushpipe) begin if (rst_or_except_flushpipe) comp_op <= #1 4'd0; else if (!ex_freeze & id_freeze) comp_op <= #1 4'd0; else if (!ex_freeze) begin comp_op <= #1 id_insn[24:21]; end 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) sig_syscall <= #1 1'b0; else if (!ex_freeze) begin `ifdef OR1200_VERBOSE // synopsys translate_off if (id_insn[31:23] == {`OR32_XSYNC, 3'b000}) $display("Generating sig_syscall"); // synopsys translate_on `endif sig_syscall <= #1 (id_insn[31:23] == {`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) sig_trap <= #1 1'b0; else if (!ex_freeze) begin `ifdef OR1200_VERBOSE // synopsys translate_off if (id_insn[31:23] == {`OR32_XSYNC, 3'b010}) $display("Generating sig_trap"); // synopsys translate_on `endif sig_trap <= #1 (id_insn[31:23] == {`OR32_XSYNC, 3'b010}); end end endmodule