URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [mp3_stable/] [or1200/] [rtl/] [verilog/] [id.v] - Rev 168
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: not supported by cvs2svn $ // `include "timescale.v" `include "defines.v" module id( // Clock and reset clk, rst, // Internal i/f pipeline_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, branch_stall, spr_addrimm, wbforw_valid, sig_syscall ); // // I/O // input clk; input rst; input pipeline_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 branch_stall; output [15:0] spr_addrimm; input wbforw_valid; output sig_syscall; // // 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; wire rst_or_except_flushpipe; // // Register file read addresses // assign rf_addra = if_insn[20:16]; assign rf_addrb = if_insn[15:11]; // // 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]}; // // Assert branch_stall if pre_branch_op is a branch operation // assign branch_stall = pre_branch_op ? 1'b1 : 1'b0; // // Async reset for most of pipeline flops // assign rst_or_except_flushpipe = rst | except_flushpipe; // // Generation of sel_a // always @(rf_addrw or wb_insn or id_insn or rfwb_op or wbforw_valid or wb_rfaddrw) if ((id_insn[20:16] == rf_addrw) && rfwb_op[0]) sel_a <= #1 `SEL_EX_FORW; else if ((id_insn[20:16] == wb_rfaddrw) && wbforw_valid) sel_a <= #1 `SEL_WB_FORW; else sel_a <= #1 `SEL_RF; // // Generation of sel_b // always @(rf_addrw or wb_insn or sel_imm or id_insn or rfwb_op or wbforw_valid or wb_rfaddrw) if (sel_imm) sel_b <= #1 `SEL_IMM; else if ((id_insn[15:11] == rf_addrw) && rfwb_op[0]) sel_b <= #1 `SEL_EX_FORW; else if ((id_insn[15:11] == wb_rfaddrw) && wbforw_valid) sel_b <= #1 `SEL_WB_FORW; else sel_b <= #1 `SEL_RF; // // 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 (!pipeline_freeze) begin case (id_insn[31:26]) // synopsys full_case parallel_case // l.mtspr `OR32_MTSPR: spr_addrimm <= #1 id_insn[15:0]; // l.mfspr 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 <= #1 `TWO_CYCLES; // l.lbz `OR32_LBZ: multicycle <= #1 `TWO_CYCLES; // l.lbs `OR32_LBS: multicycle <= #1 `TWO_CYCLES; // l.lhz `OR32_LHZ: multicycle <= #1 `TWO_CYCLES; // l.lhs `OR32_LHS: multicycle <= #1 `TWO_CYCLES; // l.sw `OR32_SW: multicycle <= #1 `TWO_CYCLES; // l.sb `OR32_SB: multicycle <= #1 `TWO_CYCLES; // l.sh `OR32_SH: multicycle <= #1 `TWO_CYCLES; // ALU instructions except the one with immediate `OR32_ALU: multicycle <= #1 id_insn[`ALUMCYC_POS]; // Single cycle instructions default: begin multicycle <= #1 `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 <= #1 `on; // l.addic `OR32_ADDIC: imm_signextend <= #1 `on; // l.xori `OR32_XORI: imm_signextend <= #1 `on; // l.muli `OR32_MULI: imm_signextend <= #1 `on; // l.maci `OR32_MACI: imm_signextend <= #1 `on; // SFXX insns with immediate `OR32_SFXXI: imm_signextend <= #1 `on; // Instructions with no or zero extended immediate default: begin imm_signextend <= #1 `off; end endcase end // // LSU addr offset // always @(lsu_op or ex_insn) begin lsu_addrofs[10:0] <= #1 ex_insn[10:0]; case(lsu_op) // synopsys parallel_case full_case `LSUOP_SW, `LSUOP_SH, `LSUOP_SB : lsu_addrofs[31:11] <= #1 {{16{ex_insn[25]}}, ex_insn[25:21]}; default : lsu_addrofs[31:11] <= #1 {{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 (!pipeline_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 (!pipeline_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 (!pipeline_freeze) begin id_insn <= #1 if_insn; $display("%t: id_insn <= %h", $time, if_insn); 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 (!pipeline_freeze) begin ex_insn <= #1 id_insn; $display("%t: ex_insn <= %h", $time, id_insn); 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 (!pipeline_freeze) begin wb_insn <= #1 ex_insn; // synopsys translate_off #3; if ((wb_insn != 32'h1500ffff) && (wb_insn != 32'h14000000)) display_arch_state; if (ex_insn == 32'h200000cb) // small hack to stop simulation (l.sys 203) caught_sys203; // synopsys translate_on end end // // Decode of sel_imm // always @(posedge clk or posedge rst) begin if (rst) sel_imm <= #1 1'b0; else if (!pipeline_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 (!pipeline_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; $display("%t: Illegal insn.... insn %h", $time, id_insn); 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 (!pipeline_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 (!pipeline_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 (!pipeline_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 (!pipeline_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 (!pipeline_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 (!pipeline_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 (!pipeline_freeze) begin // synopsys translate_off if (wb_insn[31:24] == {`OR32_XSYNC, 2'b00}) $display("Generating sig_syscall"); // synopsys translate_on sig_syscall <= #1 (wb_insn[31:24] == {`OR32_XSYNC, 2'b00}); end end endmodule
Go to most recent revision | Compare with Previous | Blame | View Log