//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// OR1200's Instruction decode ////
|
//// OR1200's Instruction decode ////
|
//// ////
|
//// ////
|
//// This file is part of the OpenRISC 1200 project ////
|
//// This file is part of the OpenRISC 1200 project ////
|
//// http://www.opencores.org/project,or1k ////
|
//// http://www.opencores.org/project,or1k ////
|
//// ////
|
//// ////
|
//// Description ////
|
//// Description ////
|
//// Majority of instruction decoding is performed here. ////
|
//// Majority of instruction decoding is performed here. ////
|
//// ////
|
//// ////
|
//// To Do: ////
|
//// To Do: ////
|
//// - make it smaller and faster ////
|
//// - make it smaller and faster ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// - Damjan Lampret, lampret@opencores.org ////
|
//// - Damjan Lampret, lampret@opencores.org ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
|
//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//
|
//
|
//
|
//
|
// $Log: or1200_ctrl.v,v $
|
// $Log: or1200_ctrl.v,v $
|
// Revision 2.0 2010/06/30 11:00:00 ORSoC
|
// Revision 2.0 2010/06/30 11:00:00 ORSoC
|
// Major update:
|
// Major update:
|
// Structure reordered and bugs fixed.
|
// Structure reordered and bugs fixed.
|
|
|
// synopsys translate_off
|
// synopsys translate_off
|
`include "timescale.v"
|
`include "timescale.v"
|
// synopsys translate_on
|
// synopsys translate_on
|
`include "or1200_defines.v"
|
`include "or1200_defines.v"
|
|
|
module or1200_ctrl
|
module or1200_ctrl
|
(
|
(
|
// Clock and reset
|
// Clock and reset
|
clk, rst,
|
clk, rst,
|
|
|
// Internal i/f
|
// Internal i/f
|
except_flushpipe, extend_flush, if_flushpipe, id_flushpipe, ex_flushpipe,
|
except_flushpipe, extend_flush, if_flushpipe, id_flushpipe, ex_flushpipe,
|
wb_flushpipe,
|
wb_flushpipe,
|
id_freeze, ex_freeze, wb_freeze, if_insn, id_insn, ex_insn, abort_mvspr,
|
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,
|
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_addra, rf_addrb, rf_rda, rf_rdb, alu_op, alu_op2, mac_op, shrot_op,
|
rf_addrw, rfwb_op, fpu_op,
|
comp_op, rf_addrw, rfwb_op, fpu_op,
|
wb_insn, id_simm, ex_simm, id_branch_addrtarget, ex_branch_addrtarget, sel_a,
|
wb_insn, id_simm, ex_simm, id_branch_addrtarget, ex_branch_addrtarget, sel_a,
|
sel_b, id_lsu_op,
|
sel_b, id_lsu_op,
|
cust5_op, cust5_limm, id_pc, ex_pc, du_hwbkpt,
|
cust5_op, cust5_limm, id_pc, ex_pc, du_hwbkpt,
|
multicycle, wait_on, wbforw_valid, sig_syscall, sig_trap,
|
multicycle, wait_on, wbforw_valid, sig_syscall, sig_trap,
|
force_dslot_fetch, no_more_dslot, id_void, ex_void, ex_spr_read,
|
force_dslot_fetch, no_more_dslot, id_void, ex_void, ex_spr_read,
|
ex_spr_write,
|
ex_spr_write,
|
id_mac_op, id_macrc_op, ex_macrc_op, rfe, except_illegal, dc_no_writethrough
|
id_mac_op, id_macrc_op, ex_macrc_op, rfe, except_illegal, dc_no_writethrough
|
);
|
);
|
|
|
//
|
//
|
// I/O
|
// I/O
|
//
|
//
|
input clk;
|
input clk;
|
input rst;
|
input rst;
|
input id_freeze;
|
input id_freeze;
|
input ex_freeze /* verilator public */;
|
input ex_freeze /* verilator public */;
|
input wb_freeze /* verilator public */;
|
input wb_freeze /* verilator public */;
|
output if_flushpipe;
|
output if_flushpipe;
|
output id_flushpipe;
|
output id_flushpipe;
|
output ex_flushpipe;
|
output ex_flushpipe;
|
output wb_flushpipe;
|
output wb_flushpipe;
|
input extend_flush;
|
input extend_flush;
|
input except_flushpipe;
|
input except_flushpipe;
|
input abort_mvspr ;
|
input abort_mvspr ;
|
input [31:0] if_insn;
|
input [31:0] if_insn;
|
output [31:0] id_insn;
|
output [31:0] id_insn;
|
output [31:0] ex_insn /* verilator public */;
|
output [31:0] ex_insn /* verilator public */;
|
output [`OR1200_BRANCHOP_WIDTH-1:0] ex_branch_op;
|
output [`OR1200_BRANCHOP_WIDTH-1:0] ex_branch_op;
|
output [`OR1200_BRANCHOP_WIDTH-1:0] id_branch_op;
|
output [`OR1200_BRANCHOP_WIDTH-1:0] id_branch_op;
|
input ex_branch_taken;
|
input ex_branch_taken;
|
output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw;
|
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_addra;
|
output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrb;
|
output [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrb;
|
output rf_rda;
|
output rf_rda;
|
output rf_rdb;
|
output rf_rdb;
|
output [`OR1200_ALUOP_WIDTH-1:0] alu_op;
|
output [`OR1200_ALUOP_WIDTH-1:0] alu_op;
|
|
output [`OR1200_ALUOP2_WIDTH-1:0] alu_op2;
|
output [`OR1200_MACOP_WIDTH-1:0] mac_op;
|
output [`OR1200_MACOP_WIDTH-1:0] mac_op;
|
output [`OR1200_SHROTOP_WIDTH-1:0] shrot_op;
|
output [`OR1200_SHROTOP_WIDTH-1:0] shrot_op;
|
output [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op;
|
output [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op;
|
output [`OR1200_FPUOP_WIDTH-1:0] fpu_op;
|
output [`OR1200_FPUOP_WIDTH-1:0] fpu_op;
|
input pc_we;
|
input pc_we;
|
output [31:0] wb_insn;
|
output [31:0] wb_insn;
|
output [31:2] id_branch_addrtarget;
|
output [31:2] id_branch_addrtarget;
|
output [31:2] ex_branch_addrtarget;
|
output [31:2] ex_branch_addrtarget;
|
output [`OR1200_SEL_WIDTH-1:0] sel_a;
|
output [`OR1200_SEL_WIDTH-1:0] sel_a;
|
output [`OR1200_SEL_WIDTH-1:0] sel_b;
|
output [`OR1200_SEL_WIDTH-1:0] sel_b;
|
output [`OR1200_LSUOP_WIDTH-1:0] id_lsu_op;
|
output [`OR1200_LSUOP_WIDTH-1:0] id_lsu_op;
|
output [`OR1200_COMPOP_WIDTH-1:0] comp_op;
|
output [`OR1200_COMPOP_WIDTH-1:0] comp_op;
|
output [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
|
output [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
|
output [`OR1200_WAIT_ON_WIDTH-1:0] wait_on;
|
output [`OR1200_WAIT_ON_WIDTH-1:0] wait_on;
|
output [4:0] cust5_op;
|
output [4:0] cust5_op;
|
output [5:0] cust5_limm;
|
output [5:0] cust5_limm;
|
input [31:0] id_pc;
|
input [31:0] id_pc;
|
input [31:0] ex_pc;
|
input [31:0] ex_pc;
|
output [31:0] id_simm;
|
output [31:0] id_simm;
|
output [31:0] ex_simm;
|
output [31:0] ex_simm;
|
input wbforw_valid;
|
input wbforw_valid;
|
input du_hwbkpt;
|
input du_hwbkpt;
|
output sig_syscall;
|
output sig_syscall;
|
output sig_trap;
|
output sig_trap;
|
output force_dslot_fetch;
|
output force_dslot_fetch;
|
output no_more_dslot;
|
output no_more_dslot;
|
output id_void;
|
output id_void;
|
output ex_void;
|
output ex_void;
|
output ex_spr_read;
|
output ex_spr_read;
|
output ex_spr_write;
|
output ex_spr_write;
|
output [`OR1200_MACOP_WIDTH-1:0] id_mac_op;
|
output [`OR1200_MACOP_WIDTH-1:0] id_mac_op;
|
output id_macrc_op;
|
output id_macrc_op;
|
output ex_macrc_op;
|
output ex_macrc_op;
|
output rfe;
|
output rfe;
|
output except_illegal;
|
output except_illegal;
|
output dc_no_writethrough;
|
output dc_no_writethrough;
|
|
|
|
|
//
|
//
|
// Internal wires and regs
|
// Internal wires and regs
|
//
|
//
|
reg [`OR1200_BRANCHOP_WIDTH-1:0] id_branch_op;
|
reg [`OR1200_BRANCHOP_WIDTH-1:0] id_branch_op;
|
reg [`OR1200_BRANCHOP_WIDTH-1:0] ex_branch_op;
|
reg [`OR1200_BRANCHOP_WIDTH-1:0] ex_branch_op;
|
reg [`OR1200_ALUOP_WIDTH-1:0] alu_op;
|
reg [`OR1200_ALUOP_WIDTH-1:0] alu_op;
|
|
reg [`OR1200_ALUOP2_WIDTH-1:0] alu_op2;
|
wire if_maci_op;
|
wire if_maci_op;
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`ifdef OR1200_MAC_IMPLEMENTED
|
reg [`OR1200_MACOP_WIDTH-1:0] ex_mac_op;
|
reg [`OR1200_MACOP_WIDTH-1:0] ex_mac_op;
|
reg [`OR1200_MACOP_WIDTH-1:0] id_mac_op;
|
reg [`OR1200_MACOP_WIDTH-1:0] id_mac_op;
|
wire [`OR1200_MACOP_WIDTH-1:0] mac_op;
|
wire [`OR1200_MACOP_WIDTH-1:0] mac_op;
|
reg ex_macrc_op;
|
reg ex_macrc_op;
|
`else
|
`else
|
wire [`OR1200_MACOP_WIDTH-1:0] mac_op;
|
wire [`OR1200_MACOP_WIDTH-1:0] mac_op;
|
wire ex_macrc_op;
|
wire ex_macrc_op;
|
`endif
|
`endif
|
reg [`OR1200_SHROTOP_WIDTH-1:0] shrot_op;
|
reg [`OR1200_SHROTOP_WIDTH-1:0] shrot_op;
|
reg [31:0] id_insn /* verilator public */;
|
reg [31:0] id_insn /* verilator public */;
|
reg [31:0] ex_insn /* verilator public */;
|
reg [31:0] ex_insn /* verilator public */;
|
reg [31:0] wb_insn /* verilator public */;
|
reg [31:0] wb_insn /* verilator public */;
|
reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw;
|
reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] rf_addrw;
|
reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] wb_rfaddrw;
|
reg [`OR1200_REGFILE_ADDR_WIDTH-1:0] wb_rfaddrw;
|
reg [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op;
|
reg [`OR1200_RFWBOP_WIDTH-1:0] rfwb_op;
|
reg [`OR1200_SEL_WIDTH-1:0] sel_a;
|
reg [`OR1200_SEL_WIDTH-1:0] sel_a;
|
reg [`OR1200_SEL_WIDTH-1:0] sel_b;
|
reg [`OR1200_SEL_WIDTH-1:0] sel_b;
|
reg sel_imm;
|
reg sel_imm;
|
reg [`OR1200_LSUOP_WIDTH-1:0] id_lsu_op;
|
reg [`OR1200_LSUOP_WIDTH-1:0] id_lsu_op;
|
reg [`OR1200_COMPOP_WIDTH-1:0] comp_op;
|
reg [`OR1200_COMPOP_WIDTH-1:0] comp_op;
|
reg [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
|
reg [`OR1200_MULTICYCLE_WIDTH-1:0] multicycle;
|
reg [`OR1200_WAIT_ON_WIDTH-1:0] wait_on;
|
reg [`OR1200_WAIT_ON_WIDTH-1:0] wait_on;
|
reg [31:0] id_simm;
|
reg [31:0] id_simm;
|
reg [31:0] ex_simm;
|
reg [31:0] ex_simm;
|
reg sig_syscall;
|
reg sig_syscall;
|
reg sig_trap;
|
reg sig_trap;
|
reg except_illegal;
|
reg except_illegal;
|
wire id_void;
|
wire id_void;
|
wire ex_void;
|
wire ex_void;
|
wire wb_void;
|
wire wb_void;
|
reg ex_delayslot_dsi;
|
reg ex_delayslot_dsi;
|
reg ex_delayslot_nop;
|
reg ex_delayslot_nop;
|
reg spr_read;
|
reg spr_read;
|
reg spr_write;
|
reg spr_write;
|
reg [31:2] ex_branch_addrtarget;
|
reg [31:2] ex_branch_addrtarget;
|
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
|
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
|
reg dc_no_writethrough;
|
reg dc_no_writethrough;
|
`endif
|
`endif
|
|
|
//
|
//
|
// Register file read addresses
|
// Register file read addresses
|
//
|
//
|
assign rf_addra = if_insn[20:16];
|
assign rf_addra = if_insn[20:16];
|
assign rf_addrb = if_insn[15:11];
|
assign rf_addrb = if_insn[15:11];
|
assign rf_rda = if_insn[31] || if_maci_op;
|
assign rf_rda = if_insn[31] || if_maci_op;
|
assign rf_rdb = if_insn[30];
|
assign rf_rdb = if_insn[30];
|
|
|
//
|
//
|
// Force fetch of delay slot instruction when jump/branch is preceeded by load/store
|
// Force fetch of delay slot instruction when jump/branch is preceeded by load/store
|
// instructions
|
// instructions
|
//
|
//
|
assign force_dslot_fetch = 1'b0;
|
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 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 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 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 wb_void = (wb_insn[31:26] == `OR1200_OR32_NOP) & wb_insn[16];
|
|
|
assign ex_spr_write = spr_write && !abort_mvspr;
|
assign ex_spr_write = spr_write && !abort_mvspr;
|
assign ex_spr_read = spr_read && !abort_mvspr;
|
assign ex_spr_read = spr_read && !abort_mvspr;
|
|
|
//
|
//
|
// ex_delayslot_dsi: delay slot insn is in EX stage
|
// 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_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 - DS insn in EX stage
|
// !ex_delayslot_dsi & ex_delayslot_nop - NOP 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
|
// next different is DS insn, previous different was Jump/Branch
|
// !ex_delayslot_dsi & !ex_delayslot_nop - normal insn in EX stage
|
// !ex_delayslot_dsi & !ex_delayslot_nop - normal insn in EX stage
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
ex_delayslot_nop <= 1'b0;
|
ex_delayslot_nop <= 1'b0;
|
ex_delayslot_dsi <= 1'b0;
|
ex_delayslot_dsi <= 1'b0;
|
end
|
end
|
else if (!ex_freeze & !ex_delayslot_dsi & ex_delayslot_nop) begin
|
else if (!ex_freeze & !ex_delayslot_dsi & ex_delayslot_nop) begin
|
ex_delayslot_nop <= id_void;
|
ex_delayslot_nop <= id_void;
|
ex_delayslot_dsi <= !id_void;
|
ex_delayslot_dsi <= !id_void;
|
end
|
end
|
else if (!ex_freeze & ex_delayslot_dsi & !ex_delayslot_nop) begin
|
else if (!ex_freeze & ex_delayslot_dsi & !ex_delayslot_nop) begin
|
ex_delayslot_nop <= 1'b0;
|
ex_delayslot_nop <= 1'b0;
|
ex_delayslot_dsi <= 1'b0;
|
ex_delayslot_dsi <= 1'b0;
|
end
|
end
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
ex_delayslot_nop <= id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) &&
|
ex_delayslot_nop <= id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) &&
|
(ex_branch_op != `OR1200_BRANCHOP_RFE);
|
(ex_branch_op != `OR1200_BRANCHOP_RFE);
|
ex_delayslot_dsi <= !id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) &&
|
ex_delayslot_dsi <= !id_void && ex_branch_taken && (ex_branch_op != `OR1200_BRANCHOP_NOP) &&
|
(ex_branch_op != `OR1200_BRANCHOP_RFE);
|
(ex_branch_op != `OR1200_BRANCHOP_RFE);
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Flush pipeline
|
// Flush pipeline
|
//
|
//
|
assign if_flushpipe = except_flushpipe | pc_we | extend_flush;
|
assign if_flushpipe = except_flushpipe | pc_we | extend_flush;
|
assign id_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 ex_flushpipe = except_flushpipe | pc_we | extend_flush;
|
assign wb_flushpipe = except_flushpipe | pc_we | extend_flush;
|
assign wb_flushpipe = except_flushpipe | pc_we | extend_flush;
|
|
|
//
|
//
|
// EX Sign/Zero extension of immediates
|
// EX Sign/Zero extension of immediates
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
ex_simm <= 32'h0000_0000;
|
ex_simm <= 32'h0000_0000;
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
ex_simm <= id_simm;
|
ex_simm <= id_simm;
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// ID Sign/Zero extension of immediate
|
// ID Sign/Zero extension of immediate
|
//
|
//
|
always @(id_insn) begin
|
always @(id_insn) begin
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
|
|
// l.addi
|
// l.addi
|
`OR1200_OR32_ADDI:
|
`OR1200_OR32_ADDI:
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
|
|
// l.addic
|
// l.addic
|
`OR1200_OR32_ADDIC:
|
`OR1200_OR32_ADDIC:
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
|
|
// l.lxx (load instructions)
|
// l.lxx (load instructions)
|
`OR1200_OR32_LWZ, `OR1200_OR32_LBZ, `OR1200_OR32_LBS, `OR1200_OR32_LHZ, `OR1200_OR32_LHS:
|
`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]};
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
|
|
// l.muli
|
// l.muli
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`OR1200_OR32_MULI:
|
`OR1200_OR32_MULI:
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
`endif
|
`endif
|
|
|
// l.maci
|
// l.maci
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`OR1200_OR32_MACI:
|
`OR1200_OR32_MACI:
|
id_simm = {{16{id_insn[25]}}, id_insn[25:21], id_insn[10:0]};
|
id_simm = {{16{id_insn[25]}}, id_insn[25:21], id_insn[10:0]};
|
`endif
|
`endif
|
|
|
// l.mtspr
|
// l.mtspr
|
`OR1200_OR32_MTSPR:
|
`OR1200_OR32_MTSPR:
|
id_simm = {16'b0, id_insn[25:21], id_insn[10:0]};
|
id_simm = {16'b0, id_insn[25:21], id_insn[10:0]};
|
|
|
// l.sxx (store instructions)
|
// l.sxx (store instructions)
|
`OR1200_OR32_SW, `OR1200_OR32_SH, `OR1200_OR32_SB:
|
`OR1200_OR32_SW, `OR1200_OR32_SH, `OR1200_OR32_SB:
|
id_simm = {{16{id_insn[25]}}, id_insn[25:21], id_insn[10:0]};
|
id_simm = {{16{id_insn[25]}}, id_insn[25:21], id_insn[10:0]};
|
|
|
// l.xori
|
// l.xori
|
`OR1200_OR32_XORI:
|
`OR1200_OR32_XORI:
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
|
|
// l.sfxxi (SFXX with immediate)
|
// l.sfxxi (SFXX with immediate)
|
`OR1200_OR32_SFXXI:
|
`OR1200_OR32_SFXXI:
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
id_simm = {{16{id_insn[15]}}, id_insn[15:0]};
|
|
|
// Instructions with no or zero extended immediate
|
// Instructions with no or zero extended immediate
|
default:
|
default:
|
id_simm = {{16'b0}, id_insn[15:0]};
|
id_simm = {{16'b0}, id_insn[15:0]};
|
|
|
endcase
|
endcase
|
end
|
end
|
|
|
//
|
//
|
// ID Sign extension of branch offset
|
// ID Sign extension of branch offset
|
//
|
//
|
assign id_branch_addrtarget = {{4{id_insn[25]}}, id_insn[25:0]} + id_pc[31:2];
|
assign id_branch_addrtarget = {{4{id_insn[25]}}, id_insn[25:0]} + id_pc[31:2];
|
|
|
//
|
//
|
// EX Sign extension of branch offset
|
// EX Sign extension of branch offset
|
//
|
//
|
|
|
// pipeline ID and EX branch target address
|
// pipeline ID and EX branch target address
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
ex_branch_addrtarget <= 0;
|
ex_branch_addrtarget <= 0;
|
else if (!ex_freeze)
|
else if (!ex_freeze)
|
ex_branch_addrtarget <= id_branch_addrtarget;
|
ex_branch_addrtarget <= id_branch_addrtarget;
|
end
|
end
|
// not pipelined
|
// not pipelined
|
//assign ex_branch_addrtarget = {{4{ex_insn[25]}}, ex_insn[25:0]} + ex_pc[31:2];
|
//assign ex_branch_addrtarget = {{4{ex_insn[25]}}, ex_insn[25:0]} + ex_pc[31:2];
|
|
|
//
|
//
|
// l.maci in IF stage
|
// l.maci in IF stage
|
//
|
//
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`ifdef OR1200_MAC_IMPLEMENTED
|
assign if_maci_op = (if_insn[31:26] == `OR1200_OR32_MACI);
|
assign if_maci_op = (if_insn[31:26] == `OR1200_OR32_MACI);
|
`else
|
`else
|
assign if_maci_op = 1'b0;
|
assign if_maci_op = 1'b0;
|
`endif
|
`endif
|
|
|
//
|
//
|
// l.macrc in ID stage
|
// l.macrc in ID stage
|
//
|
//
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`ifdef OR1200_MAC_IMPLEMENTED
|
assign id_macrc_op = (id_insn[31:26] == `OR1200_OR32_MOVHI) & id_insn[16];
|
assign id_macrc_op = (id_insn[31:26] == `OR1200_OR32_MOVHI) & id_insn[16];
|
`else
|
`else
|
assign id_macrc_op = 1'b0;
|
assign id_macrc_op = 1'b0;
|
`endif
|
`endif
|
|
|
//
|
//
|
// l.macrc in EX stage
|
// l.macrc in EX stage
|
//
|
//
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`ifdef OR1200_MAC_IMPLEMENTED
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
ex_macrc_op <= 1'b0;
|
ex_macrc_op <= 1'b0;
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
ex_macrc_op <= 1'b0;
|
ex_macrc_op <= 1'b0;
|
else if (!ex_freeze)
|
else if (!ex_freeze)
|
ex_macrc_op <= id_macrc_op;
|
ex_macrc_op <= id_macrc_op;
|
end
|
end
|
`else
|
`else
|
assign ex_macrc_op = 1'b0;
|
assign ex_macrc_op = 1'b0;
|
`endif
|
`endif
|
|
|
//
|
//
|
// cust5_op, cust5_limm (L immediate)
|
// cust5_op, cust5_limm (L immediate)
|
//
|
//
|
assign cust5_op = ex_insn[4:0];
|
assign cust5_op = ex_insn[4:0];
|
assign cust5_limm = ex_insn[10:5];
|
assign cust5_limm = ex_insn[10:5];
|
|
|
//
|
//
|
//
|
//
|
//
|
//
|
assign rfe = (id_branch_op == `OR1200_BRANCHOP_RFE) | (ex_branch_op == `OR1200_BRANCHOP_RFE);
|
assign rfe = (id_branch_op == `OR1200_BRANCHOP_RFE) | (ex_branch_op == `OR1200_BRANCHOP_RFE);
|
|
|
|
|
`ifdef verilator
|
`ifdef verilator
|
// Function to access wb_insn (for Verilator). Have to hide this from
|
// Function to access wb_insn (for Verilator). Have to hide this from
|
// simulator, since functions with no inputs are not allowed in IEEE
|
// simulator, since functions with no inputs are not allowed in IEEE
|
// 1364-2001.
|
// 1364-2001.
|
function [31:0] get_wb_insn;
|
function [31:0] get_wb_insn;
|
// verilator public
|
// verilator public
|
get_wb_insn = wb_insn;
|
get_wb_insn = wb_insn;
|
endfunction // get_wb_insn
|
endfunction // get_wb_insn
|
|
|
// Function to access id_insn (for Verilator). Have to hide this from
|
// Function to access id_insn (for Verilator). Have to hide this from
|
// simulator, since functions with no inputs are not allowed in IEEE
|
// simulator, since functions with no inputs are not allowed in IEEE
|
// 1364-2001.
|
// 1364-2001.
|
function [31:0] get_id_insn;
|
function [31:0] get_id_insn;
|
// verilator public
|
// verilator public
|
get_id_insn = id_insn;
|
get_id_insn = id_insn;
|
endfunction // get_id_insn
|
endfunction // get_id_insn
|
|
|
// Function to access ex_insn (for Verilator). Have to hide this from
|
// Function to access ex_insn (for Verilator). Have to hide this from
|
// simulator, since functions with no inputs are not allowed in IEEE
|
// simulator, since functions with no inputs are not allowed in IEEE
|
// 1364-2001.
|
// 1364-2001.
|
function [31:0] get_ex_insn;
|
function [31:0] get_ex_insn;
|
// verilator public
|
// verilator public
|
get_ex_insn = ex_insn;
|
get_ex_insn = ex_insn;
|
endfunction // get_ex_insn
|
endfunction // get_ex_insn
|
|
|
`endif
|
`endif
|
|
|
|
|
//
|
//
|
// Generation of sel_a
|
// Generation of sel_a
|
//
|
//
|
always @(rf_addrw or id_insn or rfwb_op or wbforw_valid or wb_rfaddrw)
|
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])
|
if ((id_insn[20:16] == rf_addrw) && rfwb_op[0])
|
sel_a = `OR1200_SEL_EX_FORW;
|
sel_a = `OR1200_SEL_EX_FORW;
|
else if ((id_insn[20:16] == wb_rfaddrw) && wbforw_valid)
|
else if ((id_insn[20:16] == wb_rfaddrw) && wbforw_valid)
|
sel_a = `OR1200_SEL_WB_FORW;
|
sel_a = `OR1200_SEL_WB_FORW;
|
else
|
else
|
sel_a = `OR1200_SEL_RF;
|
sel_a = `OR1200_SEL_RF;
|
|
|
//
|
//
|
// Generation of sel_b
|
// Generation of sel_b
|
//
|
//
|
always @(rf_addrw or sel_imm or id_insn or rfwb_op or wbforw_valid or wb_rfaddrw)
|
always @(rf_addrw or sel_imm or id_insn or rfwb_op or wbforw_valid or wb_rfaddrw)
|
if (sel_imm)
|
if (sel_imm)
|
sel_b = `OR1200_SEL_IMM;
|
sel_b = `OR1200_SEL_IMM;
|
else if ((id_insn[15:11] == rf_addrw) && rfwb_op[0])
|
else if ((id_insn[15:11] == rf_addrw) && rfwb_op[0])
|
sel_b = `OR1200_SEL_EX_FORW;
|
sel_b = `OR1200_SEL_EX_FORW;
|
else if ((id_insn[15:11] == wb_rfaddrw) && wbforw_valid)
|
else if ((id_insn[15:11] == wb_rfaddrw) && wbforw_valid)
|
sel_b = `OR1200_SEL_WB_FORW;
|
sel_b = `OR1200_SEL_WB_FORW;
|
else
|
else
|
sel_b = `OR1200_SEL_RF;
|
sel_b = `OR1200_SEL_RF;
|
|
|
//
|
//
|
// Decode of multicycle
|
// Decode of multicycle
|
//
|
//
|
always @(id_insn) begin
|
always @(id_insn) begin
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
`ifdef UNUSED
|
`ifdef UNUSED
|
// l.lwz
|
// l.lwz
|
`OR1200_OR32_LWZ:
|
`OR1200_OR32_LWZ:
|
multicycle = `OR1200_TWO_CYCLES;
|
multicycle = `OR1200_TWO_CYCLES;
|
|
|
// l.lbz
|
// l.lbz
|
`OR1200_OR32_LBZ:
|
`OR1200_OR32_LBZ:
|
multicycle = `OR1200_TWO_CYCLES;
|
multicycle = `OR1200_TWO_CYCLES;
|
|
|
// l.lbs
|
// l.lbs
|
`OR1200_OR32_LBS:
|
`OR1200_OR32_LBS:
|
multicycle = `OR1200_TWO_CYCLES;
|
multicycle = `OR1200_TWO_CYCLES;
|
|
|
// l.lhz
|
// l.lhz
|
`OR1200_OR32_LHZ:
|
`OR1200_OR32_LHZ:
|
multicycle = `OR1200_TWO_CYCLES;
|
multicycle = `OR1200_TWO_CYCLES;
|
|
|
// l.lhs
|
// l.lhs
|
`OR1200_OR32_LHS:
|
`OR1200_OR32_LHS:
|
multicycle = `OR1200_TWO_CYCLES;
|
multicycle = `OR1200_TWO_CYCLES;
|
|
|
// l.sw
|
// l.sw
|
`OR1200_OR32_SW:
|
`OR1200_OR32_SW:
|
multicycle = `OR1200_TWO_CYCLES;
|
multicycle = `OR1200_TWO_CYCLES;
|
|
|
// l.sb
|
// l.sb
|
`OR1200_OR32_SB:
|
`OR1200_OR32_SB:
|
multicycle = `OR1200_TWO_CYCLES;
|
multicycle = `OR1200_TWO_CYCLES;
|
|
|
// l.sh
|
// l.sh
|
`OR1200_OR32_SH:
|
`OR1200_OR32_SH:
|
multicycle = `OR1200_TWO_CYCLES;
|
multicycle = `OR1200_TWO_CYCLES;
|
`endif
|
`endif
|
// l.mfspr
|
// l.mfspr
|
`OR1200_OR32_MFSPR:
|
`OR1200_OR32_MFSPR:
|
multicycle = `OR1200_TWO_CYCLES; // to read from ITLB/DTLB (sync RAMs)
|
multicycle = `OR1200_TWO_CYCLES; // to read from ITLB/DTLB (sync RAMs)
|
|
|
// ALU instructions except the one with immediate
|
// ALU instructions except the one with immediate
|
`OR1200_OR32_ALU:
|
`OR1200_OR32_ALU:
|
case (id_insn[3:0]) // synopsys parallel_case
|
case (id_insn[3:0]) // synopsys parallel_case
|
4'h6: multicycle = `OR1200_MULTICYCLE_WIDTH'd3; // l.mul
|
4'h6: multicycle = `OR1200_MULTICYCLE_WIDTH'd3; // l.mul
|
4'h9: multicycle = `OR1200_MULTICYCLE_WIDTH'd2; // l.div
|
4'h9: multicycle = `OR1200_MULTICYCLE_WIDTH'd2; // l.div
|
4'hA: multicycle = `OR1200_MULTICYCLE_WIDTH'd2; // l.divu
|
4'hA: multicycle = `OR1200_MULTICYCLE_WIDTH'd2; // l.divu
|
4'hB: multicycle = `OR1200_MULTICYCLE_WIDTH'd3; // l.mulu
|
4'hB: multicycle = `OR1200_MULTICYCLE_WIDTH'd3; // l.mulu
|
default: multicycle = `OR1200_MULTICYCLE_WIDTH'd0;
|
default: multicycle = `OR1200_MULTICYCLE_WIDTH'd0;
|
endcase
|
endcase
|
`OR1200_OR32_MULI:
|
`OR1200_OR32_MULI:
|
multicycle = `OR1200_MULTICYCLE_WIDTH'd3;
|
multicycle = `OR1200_MULTICYCLE_WIDTH'd3;
|
|
|
// Single cycle instructions
|
// Single cycle instructions
|
default: begin
|
default: begin
|
multicycle = `OR1200_ONE_CYCLE;
|
multicycle = `OR1200_ONE_CYCLE;
|
end
|
end
|
endcase
|
endcase
|
end // always @ (id_insn)
|
end // always @ (id_insn)
|
|
|
//
|
//
|
// Encode wait_on signal
|
// Encode wait_on signal
|
//
|
//
|
always @(id_insn) begin
|
always @(id_insn) begin
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
`ifdef OR1200_FPU_IMPLEMENTED
|
`ifdef OR1200_FPU_IMPLEMENTED
|
`OR1200_OR32_FLOAT: begin
|
`OR1200_OR32_FLOAT: begin
|
wait_on = id_insn[`OR1200_FPUOP_DOUBLE_BIT] ? 0 : `OR1200_WAIT_ON_FPU;
|
wait_on = id_insn[`OR1200_FPUOP_DOUBLE_BIT] ? 0 : `OR1200_WAIT_ON_FPU;
|
end
|
end
|
`endif
|
`endif
|
`ifndef OR1200_DC_WRITHROUGH
|
`ifndef OR1200_DC_WRITHROUGH
|
// l.mtspr
|
// l.mtspr
|
`OR1200_OR32_MTSPR: begin
|
`OR1200_OR32_MTSPR: begin
|
wait_on = `OR1200_WAIT_ON_MTSPR;
|
wait_on = `OR1200_WAIT_ON_MTSPR;
|
end
|
end
|
`endif
|
`endif
|
default: begin
|
default: begin
|
wait_on = 0;
|
wait_on = 0;
|
end
|
end
|
endcase // case (id_insn[31:26])
|
endcase // case (id_insn[31:26])
|
end // always @ (id_insn)
|
end // always @ (id_insn)
|
|
|
|
|
|
|
|
|
//
|
//
|
// Register file write address
|
// Register file write address
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
rf_addrw <= 5'd0;
|
rf_addrw <= 5'd0;
|
else if (!ex_freeze & id_freeze)
|
else if (!ex_freeze & id_freeze)
|
rf_addrw <= 5'd00;
|
rf_addrw <= 5'd00;
|
else if (!ex_freeze)
|
else if (!ex_freeze)
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
`OR1200_OR32_JAL, `OR1200_OR32_JALR:
|
`OR1200_OR32_JAL, `OR1200_OR32_JALR:
|
rf_addrw <= 5'd09; // link register r9
|
rf_addrw <= 5'd09; // link register r9
|
default:
|
default:
|
rf_addrw <= id_insn[25:21];
|
rf_addrw <= id_insn[25:21];
|
endcase
|
endcase
|
end
|
end
|
|
|
//
|
//
|
// rf_addrw in wb stage (used in forwarding logic)
|
// rf_addrw in wb stage (used in forwarding logic)
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
wb_rfaddrw <= 5'd0;
|
wb_rfaddrw <= 5'd0;
|
else if (!wb_freeze)
|
else if (!wb_freeze)
|
wb_rfaddrw <= rf_addrw;
|
wb_rfaddrw <= rf_addrw;
|
end
|
end
|
|
|
//
|
//
|
// Instruction latch in id_insn
|
// Instruction latch in id_insn
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
id_insn <= {`OR1200_OR32_NOP, 26'h041_0000};
|
id_insn <= {`OR1200_OR32_NOP, 26'h041_0000};
|
else if (id_flushpipe)
|
else if (id_flushpipe)
|
id_insn <= {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> id_insn[16] must be 1
|
id_insn <= {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> id_insn[16] must be 1
|
else if (!id_freeze) begin
|
else if (!id_freeze) begin
|
id_insn <= if_insn;
|
id_insn <= if_insn;
|
`ifdef OR1200_VERBOSE
|
`ifdef OR1200_VERBOSE
|
// synopsys translate_off
|
// synopsys translate_off
|
$display("%t: id_insn <= %h", $time, if_insn);
|
$display("%t: id_insn <= %h", $time, if_insn);
|
// synopsys translate_on
|
// synopsys translate_on
|
`endif
|
`endif
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Instruction latch in ex_insn
|
// Instruction latch in ex_insn
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
ex_insn <= {`OR1200_OR32_NOP, 26'h041_0000};
|
ex_insn <= {`OR1200_OR32_NOP, 26'h041_0000};
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
ex_insn <= {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> ex_insn[16] must be 1
|
ex_insn <= {`OR1200_OR32_NOP, 26'h041_0000}; // NOP -> ex_insn[16] must be 1
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
ex_insn <= id_insn;
|
ex_insn <= id_insn;
|
`ifdef OR1200_VERBOSE
|
`ifdef OR1200_VERBOSE
|
// synopsys translate_off
|
// synopsys translate_off
|
$display("%t: ex_insn <= %h", $time, id_insn);
|
$display("%t: ex_insn <= %h", $time, id_insn);
|
// synopsys translate_on
|
// synopsys translate_on
|
`endif
|
`endif
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Instruction latch in wb_insn
|
// Instruction latch in wb_insn
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
wb_insn <= {`OR1200_OR32_NOP, 26'h041_0000};
|
wb_insn <= {`OR1200_OR32_NOP, 26'h041_0000};
|
// wb_insn should not be changed by exceptions due to correct
|
// wb_insn should not be changed by exceptions due to correct
|
// recording of display_arch_state in the or1200_monitor!
|
// recording of display_arch_state in the or1200_monitor!
|
// wb_insn changed by exception is not used elsewhere!
|
// wb_insn changed by exception is not used elsewhere!
|
else if (!wb_freeze) begin
|
else if (!wb_freeze) begin
|
wb_insn <= ex_insn;
|
wb_insn <= ex_insn;
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Decode of sel_imm
|
// Decode of sel_imm
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
else if (!id_freeze) begin
|
else if (!id_freeze) begin
|
case (if_insn[31:26]) // synopsys parallel_case
|
case (if_insn[31:26]) // synopsys parallel_case
|
|
|
// j.jalr
|
// j.jalr
|
`OR1200_OR32_JALR:
|
`OR1200_OR32_JALR:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// l.jr
|
// l.jr
|
`OR1200_OR32_JR:
|
`OR1200_OR32_JR:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// l.rfe
|
// l.rfe
|
`OR1200_OR32_RFE:
|
`OR1200_OR32_RFE:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// l.mfspr
|
// l.mfspr
|
`OR1200_OR32_MFSPR:
|
`OR1200_OR32_MFSPR:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// l.mtspr
|
// l.mtspr
|
`OR1200_OR32_MTSPR:
|
`OR1200_OR32_MTSPR:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// l.sys, l.brk and all three sync insns
|
// l.sys, l.brk and all three sync insns
|
`OR1200_OR32_XSYNC:
|
`OR1200_OR32_XSYNC:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// l.mac/l.msb
|
// l.mac/l.msb
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`OR1200_OR32_MACMSB:
|
`OR1200_OR32_MACMSB:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
`endif
|
`endif
|
|
|
// l.sw
|
// l.sw
|
`OR1200_OR32_SW:
|
`OR1200_OR32_SW:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// l.sb
|
// l.sb
|
`OR1200_OR32_SB:
|
`OR1200_OR32_SB:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// l.sh
|
// l.sh
|
`OR1200_OR32_SH:
|
`OR1200_OR32_SH:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// ALU instructions except the one with immediate
|
// ALU instructions except the one with immediate
|
`OR1200_OR32_ALU:
|
`OR1200_OR32_ALU:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// SFXX instructions
|
// SFXX instructions
|
`OR1200_OR32_SFXX:
|
`OR1200_OR32_SFXX:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
`ifdef OR1200_OR32_CUST5
|
`ifdef OR1200_OR32_CUST5
|
// l.cust5 instructions
|
// l.cust5 instructions
|
`OR1200_OR32_CUST5:
|
`OR1200_OR32_CUST5:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
`endif
|
`endif
|
`ifdef OR1200_FPU_IMPLEMENTED
|
`ifdef OR1200_FPU_IMPLEMENTED
|
// FPU instructions
|
// FPU instructions
|
`OR1200_OR32_FLOAT:
|
`OR1200_OR32_FLOAT:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
`endif
|
`endif
|
// l.nop
|
// l.nop
|
`OR1200_OR32_NOP:
|
`OR1200_OR32_NOP:
|
sel_imm <= 1'b0;
|
sel_imm <= 1'b0;
|
|
|
// All instructions with immediates
|
// All instructions with immediates
|
default: begin
|
default: begin
|
sel_imm <= 1'b1;
|
sel_imm <= 1'b1;
|
end
|
end
|
|
|
endcase
|
endcase
|
|
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Decode of except_illegal
|
// Decode of except_illegal
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
except_illegal <= 1'b0;
|
except_illegal <= 1'b0;
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
except_illegal <= 1'b0;
|
except_illegal <= 1'b0;
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
|
|
`OR1200_OR32_J,
|
`OR1200_OR32_J,
|
`OR1200_OR32_JAL,
|
`OR1200_OR32_JAL,
|
`OR1200_OR32_JALR,
|
`OR1200_OR32_JALR,
|
`OR1200_OR32_JR,
|
`OR1200_OR32_JR,
|
`OR1200_OR32_BNF,
|
`OR1200_OR32_BNF,
|
`OR1200_OR32_BF,
|
`OR1200_OR32_BF,
|
`OR1200_OR32_RFE,
|
`OR1200_OR32_RFE,
|
`OR1200_OR32_MOVHI,
|
`OR1200_OR32_MOVHI,
|
`OR1200_OR32_MFSPR,
|
`OR1200_OR32_MFSPR,
|
`OR1200_OR32_XSYNC,
|
`OR1200_OR32_XSYNC,
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`OR1200_OR32_MACI,
|
`OR1200_OR32_MACI,
|
`endif
|
`endif
|
`OR1200_OR32_LWZ,
|
`OR1200_OR32_LWZ,
|
`OR1200_OR32_LBZ,
|
`OR1200_OR32_LBZ,
|
`OR1200_OR32_LBS,
|
`OR1200_OR32_LBS,
|
`OR1200_OR32_LHZ,
|
`OR1200_OR32_LHZ,
|
`OR1200_OR32_LHS,
|
`OR1200_OR32_LHS,
|
`OR1200_OR32_ADDI,
|
`OR1200_OR32_ADDI,
|
`OR1200_OR32_ADDIC,
|
`OR1200_OR32_ADDIC,
|
`OR1200_OR32_ANDI,
|
`OR1200_OR32_ANDI,
|
`OR1200_OR32_ORI,
|
`OR1200_OR32_ORI,
|
`OR1200_OR32_XORI,
|
`OR1200_OR32_XORI,
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`OR1200_OR32_MULI,
|
`OR1200_OR32_MULI,
|
`endif
|
`endif
|
`OR1200_OR32_SH_ROTI,
|
`OR1200_OR32_SH_ROTI,
|
`OR1200_OR32_SFXXI,
|
`OR1200_OR32_SFXXI,
|
`OR1200_OR32_MTSPR,
|
`OR1200_OR32_MTSPR,
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`OR1200_OR32_MACMSB,
|
`OR1200_OR32_MACMSB,
|
`endif
|
`endif
|
`OR1200_OR32_SW,
|
`OR1200_OR32_SW,
|
`OR1200_OR32_SB,
|
`OR1200_OR32_SB,
|
`OR1200_OR32_SH,
|
`OR1200_OR32_SH,
|
`OR1200_OR32_SFXX,
|
`OR1200_OR32_SFXX,
|
`ifdef OR1200_OR32_CUST5
|
`ifdef OR1200_OR32_CUST5
|
`OR1200_OR32_CUST5,
|
`OR1200_OR32_CUST5,
|
`endif
|
`endif
|
`OR1200_OR32_NOP:
|
`OR1200_OR32_NOP:
|
except_illegal <= 1'b0;
|
except_illegal <= 1'b0;
|
`ifdef OR1200_FPU_IMPLEMENTED
|
`ifdef OR1200_FPU_IMPLEMENTED
|
`OR1200_OR32_FLOAT:
|
`OR1200_OR32_FLOAT:
|
// Check it's not a double precision instruction
|
// Check it's not a double precision instruction
|
except_illegal <= id_insn[`OR1200_FPUOP_DOUBLE_BIT];
|
except_illegal <= id_insn[`OR1200_FPUOP_DOUBLE_BIT];
|
`endif
|
`endif
|
|
|
`OR1200_OR32_ALU:
|
`OR1200_OR32_ALU:
|
except_illegal <= 1'b0
|
except_illegal <= 1'b0
|
|
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`ifdef OR1200_DIV_IMPLEMENTED
|
`ifdef OR1200_DIV_IMPLEMENTED
|
`else
|
`else
|
| (id_insn[3:0] == `OR1200_ALUOP_DIV)
|
| (id_insn[3:0] == `OR1200_ALUOP_DIV)
|
| (id_insn[3:0] == `OR1200_ALUOP_DIVU)
|
| (id_insn[3:0] == `OR1200_ALUOP_DIVU)
|
`endif
|
`endif
|
`else
|
`else
|
| (id_insn[3:0] == `OR1200_ALUOP_DIV)
|
| (id_insn[3:0] == `OR1200_ALUOP_DIV)
|
| (id_insn[3:0] == `OR1200_ALUOP_DIVU)
|
| (id_insn[3:0] == `OR1200_ALUOP_DIVU)
|
| (id_insn[3:0] == `OR1200_ALUOP_MUL)
|
| (id_insn[3:0] == `OR1200_ALUOP_MUL)
|
`endif
|
`endif
|
|
|
`ifdef OR1200_IMPL_ADDC
|
`ifdef OR1200_IMPL_ADDC
|
`else
|
`else
|
| (id_insn[3:0] == `OR1200_ALUOP_ADDC)
|
| (id_insn[3:0] == `OR1200_ALUOP_ADDC)
|
`endif
|
`endif
|
|
|
|
`ifdef OR1200_IMPL_ALU_FFL1
|
|
`else
|
|
| (id_insn[3:0] == `OR1200_ALUOP_FFL1)
|
|
`endif
|
|
|
`ifdef OR1200_IMPL_ALU_ROTATE
|
`ifdef OR1200_IMPL_ALU_ROTATE
|
`else
|
`else
|
| ((id_insn[3:0] == `OR1200_ALUOP_SHROT) &
|
| ((id_insn[3:0] == `OR1200_ALUOP_SHROT) &
|
(id_insn[7:6] == `OR1200_SHROTOP_ROR))
|
(id_insn[7:6] == `OR1200_SHROTOP_ROR))
|
`endif
|
`endif
|
|
|
`ifdef OR1200_IMPL_SUB
|
`ifdef OR1200_IMPL_SUB
|
`else
|
`else
|
| (id_insn[3:0] == `OR1200_ALUOP_SUB)
|
| (id_insn[3:0] == `OR1200_ALUOP_SUB)
|
`endif
|
`endif
|
;
|
;
|
|
|
// Illegal and OR1200 unsupported instructions
|
// Illegal and OR1200 unsupported instructions
|
default:
|
default:
|
except_illegal <= 1'b1;
|
except_illegal <= 1'b1;
|
|
|
endcase
|
endcase
|
end // if (!ex_freeze)
|
end // if (!ex_freeze)
|
end
|
end
|
|
|
|
|
//
|
//
|
// Decode of alu_op
|
// Decode of alu_op
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
alu_op <= `OR1200_ALUOP_NOP;
|
alu_op <= `OR1200_ALUOP_NOP;
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
alu_op <= `OR1200_ALUOP_NOP;
|
alu_op <= `OR1200_ALUOP_NOP;
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
|
|
// l.movhi
|
// l.movhi
|
`OR1200_OR32_MOVHI:
|
`OR1200_OR32_MOVHI:
|
alu_op <= `OR1200_ALUOP_MOVHI;
|
alu_op <= `OR1200_ALUOP_MOVHI;
|
|
|
// l.addi
|
// l.addi
|
`OR1200_OR32_ADDI:
|
`OR1200_OR32_ADDI:
|
alu_op <= `OR1200_ALUOP_ADD;
|
alu_op <= `OR1200_ALUOP_ADD;
|
|
|
// l.addic
|
// l.addic
|
`OR1200_OR32_ADDIC:
|
`OR1200_OR32_ADDIC:
|
alu_op <= `OR1200_ALUOP_ADDC;
|
alu_op <= `OR1200_ALUOP_ADDC;
|
|
|
// l.andi
|
// l.andi
|
`OR1200_OR32_ANDI:
|
`OR1200_OR32_ANDI:
|
alu_op <= `OR1200_ALUOP_AND;
|
alu_op <= `OR1200_ALUOP_AND;
|
|
|
// l.ori
|
// l.ori
|
`OR1200_OR32_ORI:
|
`OR1200_OR32_ORI:
|
alu_op <= `OR1200_ALUOP_OR;
|
alu_op <= `OR1200_ALUOP_OR;
|
|
|
// l.xori
|
// l.xori
|
`OR1200_OR32_XORI:
|
`OR1200_OR32_XORI:
|
alu_op <= `OR1200_ALUOP_XOR;
|
alu_op <= `OR1200_ALUOP_XOR;
|
|
|
// l.muli
|
// l.muli
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`OR1200_OR32_MULI:
|
`OR1200_OR32_MULI:
|
alu_op <= `OR1200_ALUOP_MUL;
|
alu_op <= `OR1200_ALUOP_MUL;
|
`endif
|
`endif
|
|
|
// Shift and rotate insns with immediate
|
// Shift and rotate insns with immediate
|
`OR1200_OR32_SH_ROTI:
|
`OR1200_OR32_SH_ROTI:
|
alu_op <= `OR1200_ALUOP_SHROT;
|
alu_op <= `OR1200_ALUOP_SHROT;
|
|
|
// SFXX insns with immediate
|
// SFXX insns with immediate
|
`OR1200_OR32_SFXXI:
|
`OR1200_OR32_SFXXI:
|
alu_op <= `OR1200_ALUOP_COMP;
|
alu_op <= `OR1200_ALUOP_COMP;
|
|
|
// ALU instructions except the one with immediate
|
// ALU instructions except the one with immediate
|
`OR1200_OR32_ALU:
|
`OR1200_OR32_ALU:
|
alu_op <= id_insn[3:0];
|
alu_op <= id_insn[3:0];
|
|
|
// SFXX instructions
|
// SFXX instructions
|
`OR1200_OR32_SFXX:
|
`OR1200_OR32_SFXX:
|
alu_op <= `OR1200_ALUOP_COMP;
|
alu_op <= `OR1200_ALUOP_COMP;
|
|
|
`ifdef OR1200_OR32_CUST5
|
`ifdef OR1200_OR32_CUST5
|
// l.cust5 instructions
|
// l.cust5 instructions
|
`OR1200_OR32_CUST5:
|
`OR1200_OR32_CUST5:
|
alu_op <= `OR1200_ALUOP_CUST5;
|
alu_op <= `OR1200_ALUOP_CUST5;
|
`endif
|
`endif
|
|
|
// Default
|
// Default
|
default: begin
|
default: begin
|
alu_op <= `OR1200_ALUOP_NOP;
|
alu_op <= `OR1200_ALUOP_NOP;
|
end
|
end
|
|
|
endcase
|
endcase
|
|
|
end
|
end
|
end
|
end
|
|
|
|
|
|
//
|
|
// Decode of alu_op2 (field of bits 9:8)
|
|
//
|
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
|
if (rst == `OR1200_RST_VALUE)
|
|
alu_op2 <= 0;
|
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
|
alu_op2 <= 0;
|
|
else if (!ex_freeze) begin
|
|
alu_op2 <= id_insn[`OR1200_ALUOP2_POS];
|
|
end
|
|
end
|
|
|
|
|
//
|
//
|
// Decode of spr_read, spr_write
|
// Decode of spr_read, spr_write
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
spr_read <= 1'b0;
|
spr_read <= 1'b0;
|
spr_write <= 1'b0;
|
spr_write <= 1'b0;
|
end
|
end
|
else if (!ex_freeze & id_freeze | ex_flushpipe) begin
|
else if (!ex_freeze & id_freeze | ex_flushpipe) begin
|
spr_read <= 1'b0;
|
spr_read <= 1'b0;
|
spr_write <= 1'b0;
|
spr_write <= 1'b0;
|
end
|
end
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
|
|
// l.mfspr
|
// l.mfspr
|
`OR1200_OR32_MFSPR: begin
|
`OR1200_OR32_MFSPR: begin
|
spr_read <= 1'b1;
|
spr_read <= 1'b1;
|
spr_write <= 1'b0;
|
spr_write <= 1'b0;
|
end
|
end
|
|
|
// l.mtspr
|
// l.mtspr
|
`OR1200_OR32_MTSPR: begin
|
`OR1200_OR32_MTSPR: begin
|
spr_read <= 1'b0;
|
spr_read <= 1'b0;
|
spr_write <= 1'b1;
|
spr_write <= 1'b1;
|
end
|
end
|
|
|
// Default
|
// Default
|
default: begin
|
default: begin
|
spr_read <= 1'b0;
|
spr_read <= 1'b0;
|
spr_write <= 1'b0;
|
spr_write <= 1'b0;
|
end
|
end
|
|
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Decode of mac_op
|
// Decode of mac_op
|
//
|
//
|
`ifdef OR1200_MAC_IMPLEMENTED
|
`ifdef OR1200_MAC_IMPLEMENTED
|
always @(id_insn) begin
|
always @(id_insn) begin
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
|
|
// l.maci
|
// l.maci
|
`OR1200_OR32_MACI:
|
`OR1200_OR32_MACI:
|
id_mac_op = `OR1200_MACOP_MAC;
|
id_mac_op = `OR1200_MACOP_MAC;
|
|
|
// l.mac, l.msb
|
// l.mac, l.msb
|
`OR1200_OR32_MACMSB:
|
`OR1200_OR32_MACMSB:
|
id_mac_op = id_insn[2:0];
|
id_mac_op = id_insn[2:0];
|
|
|
// Illegal and OR1200 unsupported instructions
|
// Illegal and OR1200 unsupported instructions
|
default:
|
default:
|
id_mac_op = `OR1200_MACOP_NOP;
|
id_mac_op = `OR1200_MACOP_NOP;
|
|
|
endcase
|
endcase
|
end
|
end
|
|
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
ex_mac_op <= `OR1200_MACOP_NOP;
|
ex_mac_op <= `OR1200_MACOP_NOP;
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
ex_mac_op <= `OR1200_MACOP_NOP;
|
ex_mac_op <= `OR1200_MACOP_NOP;
|
else if (!ex_freeze)
|
else if (!ex_freeze)
|
ex_mac_op <= id_mac_op;
|
ex_mac_op <= id_mac_op;
|
end
|
end
|
|
|
assign mac_op = abort_mvspr ? `OR1200_MACOP_NOP : ex_mac_op;
|
assign mac_op = abort_mvspr ? `OR1200_MACOP_NOP : ex_mac_op;
|
`else
|
`else
|
assign id_mac_op = `OR1200_MACOP_NOP;
|
assign id_mac_op = `OR1200_MACOP_NOP;
|
assign mac_op = `OR1200_MACOP_NOP;
|
assign mac_op = `OR1200_MACOP_NOP;
|
`endif
|
`endif
|
|
|
//
|
//
|
// Decode of shrot_op
|
// Decode of shrot_op
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
shrot_op <= `OR1200_SHROTOP_NOP;
|
shrot_op <= `OR1200_SHROTOP_NOP;
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
shrot_op <= `OR1200_SHROTOP_NOP;
|
shrot_op <= `OR1200_SHROTOP_NOP;
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
shrot_op <= id_insn[`OR1200_SHROTOP_POS];
|
shrot_op <= id_insn[`OR1200_SHROTOP_POS];
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Decode of rfwb_op
|
// Decode of rfwb_op
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
rfwb_op <= `OR1200_RFWBOP_NOP;
|
rfwb_op <= `OR1200_RFWBOP_NOP;
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
rfwb_op <= `OR1200_RFWBOP_NOP;
|
rfwb_op <= `OR1200_RFWBOP_NOP;
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
|
|
// j.jal
|
// j.jal
|
`OR1200_OR32_JAL:
|
`OR1200_OR32_JAL:
|
rfwb_op <= {`OR1200_RFWBOP_LR, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_LR, 1'b1};
|
|
|
// j.jalr
|
// j.jalr
|
`OR1200_OR32_JALR:
|
`OR1200_OR32_JALR:
|
rfwb_op <= {`OR1200_RFWBOP_LR, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_LR, 1'b1};
|
|
|
// l.movhi
|
// l.movhi
|
`OR1200_OR32_MOVHI:
|
`OR1200_OR32_MOVHI:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
|
|
// l.mfspr
|
// l.mfspr
|
`OR1200_OR32_MFSPR:
|
`OR1200_OR32_MFSPR:
|
rfwb_op <= {`OR1200_RFWBOP_SPRS, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_SPRS, 1'b1};
|
|
|
// l.lwz
|
// l.lwz
|
`OR1200_OR32_LWZ:
|
`OR1200_OR32_LWZ:
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
|
|
// l.lbz
|
// l.lbz
|
`OR1200_OR32_LBZ:
|
`OR1200_OR32_LBZ:
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
|
|
// l.lbs
|
// l.lbs
|
`OR1200_OR32_LBS:
|
`OR1200_OR32_LBS:
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
|
|
// l.lhz
|
// l.lhz
|
`OR1200_OR32_LHZ:
|
`OR1200_OR32_LHZ:
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
|
|
// l.lhs
|
// l.lhs
|
`OR1200_OR32_LHS:
|
`OR1200_OR32_LHS:
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_LSU, 1'b1};
|
|
|
// l.addi
|
// l.addi
|
`OR1200_OR32_ADDI:
|
`OR1200_OR32_ADDI:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
|
|
// l.addic
|
// l.addic
|
`OR1200_OR32_ADDIC:
|
`OR1200_OR32_ADDIC:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
|
|
// l.andi
|
// l.andi
|
`OR1200_OR32_ANDI:
|
`OR1200_OR32_ANDI:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
|
|
// l.ori
|
// l.ori
|
`OR1200_OR32_ORI:
|
`OR1200_OR32_ORI:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
|
|
// l.xori
|
// l.xori
|
`OR1200_OR32_XORI:
|
`OR1200_OR32_XORI:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
|
|
// l.muli
|
// l.muli
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`ifdef OR1200_MULT_IMPLEMENTED
|
`OR1200_OR32_MULI:
|
`OR1200_OR32_MULI:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
`endif
|
`endif
|
|
|
// Shift and rotate insns with immediate
|
// Shift and rotate insns with immediate
|
`OR1200_OR32_SH_ROTI:
|
`OR1200_OR32_SH_ROTI:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
|
|
// ALU instructions except the one with immediate
|
// ALU instructions except the one with immediate
|
`OR1200_OR32_ALU:
|
`OR1200_OR32_ALU:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
|
|
`ifdef OR1200_OR32_CUST5
|
`ifdef OR1200_OR32_CUST5
|
// l.cust5 instructions
|
// l.cust5 instructions
|
`OR1200_OR32_CUST5:
|
`OR1200_OR32_CUST5:
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
rfwb_op <= {`OR1200_RFWBOP_ALU, 1'b1};
|
`endif
|
`endif
|
`ifdef OR1200_FPU_IMPLEMENTED
|
`ifdef OR1200_FPU_IMPLEMENTED
|
// FPU instructions, lf.XXX.s, except sfxx
|
// FPU instructions, lf.XXX.s, except sfxx
|
`OR1200_OR32_FLOAT:
|
`OR1200_OR32_FLOAT:
|
rfwb_op <= {`OR1200_RFWBOP_FPU,!id_insn[3]};
|
rfwb_op <= {`OR1200_RFWBOP_FPU,!id_insn[3]};
|
`endif
|
`endif
|
// Instructions w/o register-file write-back
|
// Instructions w/o register-file write-back
|
default:
|
default:
|
rfwb_op <= `OR1200_RFWBOP_NOP;
|
rfwb_op <= `OR1200_RFWBOP_NOP;
|
|
|
|
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Decode of id_branch_op
|
// Decode of id_branch_op
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
id_branch_op <= `OR1200_BRANCHOP_NOP;
|
id_branch_op <= `OR1200_BRANCHOP_NOP;
|
else if (id_flushpipe)
|
else if (id_flushpipe)
|
id_branch_op <= `OR1200_BRANCHOP_NOP;
|
id_branch_op <= `OR1200_BRANCHOP_NOP;
|
else if (!id_freeze) begin
|
else if (!id_freeze) begin
|
case (if_insn[31:26]) // synopsys parallel_case
|
case (if_insn[31:26]) // synopsys parallel_case
|
|
|
// l.j
|
// l.j
|
`OR1200_OR32_J:
|
`OR1200_OR32_J:
|
id_branch_op <= `OR1200_BRANCHOP_J;
|
id_branch_op <= `OR1200_BRANCHOP_J;
|
|
|
// j.jal
|
// j.jal
|
`OR1200_OR32_JAL:
|
`OR1200_OR32_JAL:
|
id_branch_op <= `OR1200_BRANCHOP_J;
|
id_branch_op <= `OR1200_BRANCHOP_J;
|
|
|
// j.jalr
|
// j.jalr
|
`OR1200_OR32_JALR:
|
`OR1200_OR32_JALR:
|
id_branch_op <= `OR1200_BRANCHOP_JR;
|
id_branch_op <= `OR1200_BRANCHOP_JR;
|
|
|
// l.jr
|
// l.jr
|
`OR1200_OR32_JR:
|
`OR1200_OR32_JR:
|
id_branch_op <= `OR1200_BRANCHOP_JR;
|
id_branch_op <= `OR1200_BRANCHOP_JR;
|
|
|
// l.bnf
|
// l.bnf
|
`OR1200_OR32_BNF:
|
`OR1200_OR32_BNF:
|
id_branch_op <= `OR1200_BRANCHOP_BNF;
|
id_branch_op <= `OR1200_BRANCHOP_BNF;
|
|
|
// l.bf
|
// l.bf
|
`OR1200_OR32_BF:
|
`OR1200_OR32_BF:
|
id_branch_op <= `OR1200_BRANCHOP_BF;
|
id_branch_op <= `OR1200_BRANCHOP_BF;
|
|
|
// l.rfe
|
// l.rfe
|
`OR1200_OR32_RFE:
|
`OR1200_OR32_RFE:
|
id_branch_op <= `OR1200_BRANCHOP_RFE;
|
id_branch_op <= `OR1200_BRANCHOP_RFE;
|
|
|
// Non branch instructions
|
// Non branch instructions
|
default:
|
default:
|
id_branch_op <= `OR1200_BRANCHOP_NOP;
|
id_branch_op <= `OR1200_BRANCHOP_NOP;
|
|
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Generation of ex_branch_op
|
// Generation of ex_branch_op
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst)
|
always @(posedge clk or `OR1200_RST_EVENT rst)
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
ex_branch_op <= `OR1200_BRANCHOP_NOP;
|
ex_branch_op <= `OR1200_BRANCHOP_NOP;
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
ex_branch_op <= `OR1200_BRANCHOP_NOP;
|
ex_branch_op <= `OR1200_BRANCHOP_NOP;
|
else if (!ex_freeze)
|
else if (!ex_freeze)
|
ex_branch_op <= id_branch_op;
|
ex_branch_op <= id_branch_op;
|
|
|
//
|
//
|
// Decode of id_lsu_op
|
// Decode of id_lsu_op
|
//
|
//
|
always @(id_insn) begin
|
always @(id_insn) begin
|
case (id_insn[31:26]) // synopsys parallel_case
|
case (id_insn[31:26]) // synopsys parallel_case
|
|
|
// l.lwz
|
// l.lwz
|
`OR1200_OR32_LWZ:
|
`OR1200_OR32_LWZ:
|
id_lsu_op = `OR1200_LSUOP_LWZ;
|
id_lsu_op = `OR1200_LSUOP_LWZ;
|
|
|
// l.lbz
|
// l.lbz
|
`OR1200_OR32_LBZ:
|
`OR1200_OR32_LBZ:
|
id_lsu_op = `OR1200_LSUOP_LBZ;
|
id_lsu_op = `OR1200_LSUOP_LBZ;
|
|
|
// l.lbs
|
// l.lbs
|
`OR1200_OR32_LBS:
|
`OR1200_OR32_LBS:
|
id_lsu_op = `OR1200_LSUOP_LBS;
|
id_lsu_op = `OR1200_LSUOP_LBS;
|
|
|
// l.lhz
|
// l.lhz
|
`OR1200_OR32_LHZ:
|
`OR1200_OR32_LHZ:
|
id_lsu_op = `OR1200_LSUOP_LHZ;
|
id_lsu_op = `OR1200_LSUOP_LHZ;
|
|
|
// l.lhs
|
// l.lhs
|
`OR1200_OR32_LHS:
|
`OR1200_OR32_LHS:
|
id_lsu_op = `OR1200_LSUOP_LHS;
|
id_lsu_op = `OR1200_LSUOP_LHS;
|
|
|
// l.sw
|
// l.sw
|
`OR1200_OR32_SW:
|
`OR1200_OR32_SW:
|
id_lsu_op = `OR1200_LSUOP_SW;
|
id_lsu_op = `OR1200_LSUOP_SW;
|
|
|
// l.sb
|
// l.sb
|
`OR1200_OR32_SB:
|
`OR1200_OR32_SB:
|
id_lsu_op = `OR1200_LSUOP_SB;
|
id_lsu_op = `OR1200_LSUOP_SB;
|
|
|
// l.sh
|
// l.sh
|
`OR1200_OR32_SH:
|
`OR1200_OR32_SH:
|
id_lsu_op = `OR1200_LSUOP_SH;
|
id_lsu_op = `OR1200_LSUOP_SH;
|
|
|
// Non load/store instructions
|
// Non load/store instructions
|
default:
|
default:
|
id_lsu_op = `OR1200_LSUOP_NOP;
|
id_lsu_op = `OR1200_LSUOP_NOP;
|
|
|
endcase
|
endcase
|
end
|
end
|
|
|
//
|
//
|
// Decode of comp_op
|
// Decode of comp_op
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
if (rst == `OR1200_RST_VALUE) begin
|
comp_op <= 4'd0;
|
comp_op <= 4'd0;
|
end else if (!ex_freeze & id_freeze | ex_flushpipe)
|
end else if (!ex_freeze & id_freeze | ex_flushpipe)
|
comp_op <= 4'd0;
|
comp_op <= 4'd0;
|
else if (!ex_freeze)
|
else if (!ex_freeze)
|
comp_op <= id_insn[24:21];
|
comp_op <= id_insn[24:21];
|
end
|
end
|
|
|
`ifdef OR1200_FPU_IMPLEMENTED
|
`ifdef OR1200_FPU_IMPLEMENTED
|
//
|
//
|
// Decode of FPU ops
|
// Decode of FPU ops
|
//
|
//
|
assign fpu_op = {(id_insn[31:26] == `OR1200_OR32_FLOAT),
|
assign fpu_op = {(id_insn[31:26] == `OR1200_OR32_FLOAT),
|
id_insn[`OR1200_FPUOP_WIDTH-2:0]};
|
id_insn[`OR1200_FPUOP_WIDTH-2:0]};
|
`else
|
`else
|
assign fpu_op = {`OR1200_FPUOP_WIDTH{1'b0}};
|
assign fpu_op = {`OR1200_FPUOP_WIDTH{1'b0}};
|
`endif
|
`endif
|
|
|
|
|
//
|
//
|
// Decode of l.sys
|
// Decode of l.sys
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
sig_syscall <= 1'b0;
|
sig_syscall <= 1'b0;
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
sig_syscall <= 1'b0;
|
sig_syscall <= 1'b0;
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
`ifdef OR1200_VERBOSE
|
`ifdef OR1200_VERBOSE
|
// synopsys translate_off
|
// synopsys translate_off
|
if (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b000})
|
if (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b000})
|
$display("Generating sig_syscall");
|
$display("Generating sig_syscall");
|
// synopsys translate_on
|
// synopsys translate_on
|
`endif
|
`endif
|
sig_syscall <= (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b000});
|
sig_syscall <= (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b000});
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
// Decode of l.trap
|
// Decode of l.trap
|
//
|
//
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
sig_trap <= 1'b0;
|
sig_trap <= 1'b0;
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
else if (!ex_freeze & id_freeze | ex_flushpipe)
|
sig_trap <= 1'b0;
|
sig_trap <= 1'b0;
|
else if (!ex_freeze) begin
|
else if (!ex_freeze) begin
|
`ifdef OR1200_VERBOSE
|
`ifdef OR1200_VERBOSE
|
// synopsys translate_off
|
// synopsys translate_off
|
if (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b010})
|
if (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b010})
|
$display("Generating sig_trap");
|
$display("Generating sig_trap");
|
// synopsys translate_on
|
// synopsys translate_on
|
`endif
|
`endif
|
sig_trap <= (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b010})
|
sig_trap <= (id_insn[31:23] == {`OR1200_OR32_XSYNC, 3'b010})
|
| du_hwbkpt;
|
| du_hwbkpt;
|
end
|
end
|
end
|
end
|
|
|
// Decode destination register address for data cache to check if store ops
|
// Decode destination register address for data cache to check if store ops
|
// are being done from the stack register (r1) or frame pointer register (r2)
|
// are being done from the stack register (r1) or frame pointer register (r2)
|
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
|
`ifdef OR1200_DC_NOSTACKWRITETHROUGH
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
always @(posedge clk or `OR1200_RST_EVENT rst) begin
|
if (rst == `OR1200_RST_VALUE)
|
if (rst == `OR1200_RST_VALUE)
|
dc_no_writethrough <= 0;
|
dc_no_writethrough <= 0;
|
else if (!ex_freeze)
|
else if (!ex_freeze)
|
dc_no_writethrough <= (id_insn[20:16] == 5'd1) | (id_insn[20:16] == 5'd2);
|
dc_no_writethrough <= (id_insn[20:16] == 5'd1) | (id_insn[20:16] == 5'd2);
|
end
|
end
|
`else
|
`else
|
|
|
assign dc_no_writethrough = 0;
|
assign dc_no_writethrough = 0;
|
|
|
`endif
|
`endif
|
|
|
endmodule
|
endmodule
|
|
|