//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// AltOR32
|
// AltOR32
|
// Alternative Lightweight OpenRisc
|
// Alternative Lightweight OpenRisc
|
// V2.1
|
// V2.1
|
// Ultra-Embedded.com
|
// Ultra-Embedded.com
|
// Copyright 2011 - 2014
|
// Copyright 2011 - 2014
|
//
|
//
|
// Email: admin@ultra-embedded.com
|
// Email: admin@ultra-embedded.com
|
//
|
//
|
// License: LGPL
|
// License: LGPL
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
//
|
//
|
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
|
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
|
//
|
//
|
// 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, write to the
|
// Public License along with this source; if not, write to the
|
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
// Boston, MA 02111-1307 USA
|
// Boston, MA 02111-1307 USA
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
//`define CONF_CORE_DEBUG
|
//`define CONF_CORE_DEBUG
|
//`define CONF_CORE_TRACE
|
//`define CONF_CORE_TRACE
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Includes
|
// Includes
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`include "altor32_defs.v"
|
`include "altor32_defs.v"
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Module - Simple AltOR32 (non-pipelined, small, single WB interface)
|
// Module - Simple AltOR32 (non-pipelined, small, single WB interface)
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
module altor32_lite
|
module altor32_lite
|
(
|
(
|
// General
|
// General
|
input clk_i /*verilator public*/,
|
input clk_i /*verilator public*/,
|
input rst_i /*verilator public*/,
|
input rst_i /*verilator public*/,
|
|
|
// Maskable interrupt
|
// Maskable interrupt
|
input intr_i /*verilator public*/,
|
input intr_i /*verilator public*/,
|
|
|
// Unmaskable interrupt
|
// Unmaskable interrupt
|
input nmi_i /*verilator public*/,
|
input nmi_i /*verilator public*/,
|
|
|
// Enable core
|
// Enable core
|
input enable_i /*verilator public*/,
|
input enable_i /*verilator public*/,
|
|
|
// Fault
|
// Fault
|
output reg fault_o /*verilator public*/,
|
output reg fault_o /*verilator public*/,
|
|
|
// Breakpoint / Trap
|
// Breakpoint / Trap
|
output reg break_o /*verilator public*/,
|
output reg break_o /*verilator public*/,
|
|
|
// Memory interface
|
// Memory interface
|
output reg [31:0] mem_addr_o /*verilator public*/,
|
output reg [31:0] mem_addr_o /*verilator public*/,
|
input [31:0] mem_dat_i /*verilator public*/,
|
input [31:0] mem_dat_i /*verilator public*/,
|
output reg [31:0] mem_dat_o /*verilator public*/,
|
output reg [31:0] mem_dat_o /*verilator public*/,
|
output [2:0] mem_cti_o /*verilator public*/,
|
output [2:0] mem_cti_o /*verilator public*/,
|
output reg mem_cyc_o /*verilator public*/,
|
output reg mem_cyc_o /*verilator public*/,
|
output reg mem_stb_o /*verilator public*/,
|
output reg mem_stb_o /*verilator public*/,
|
output reg mem_we_o /*verilator public*/,
|
output reg mem_we_o /*verilator public*/,
|
output reg [3:0] mem_sel_o /*verilator public*/,
|
output reg [3:0] mem_sel_o /*verilator public*/,
|
input mem_stall_i/*verilator public*/,
|
input mem_stall_i/*verilator public*/,
|
input mem_ack_i/*verilator public*/
|
input mem_ack_i/*verilator public*/
|
);
|
);
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Params
|
// Params
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
parameter BOOT_VECTOR = 32'h00000000;
|
parameter BOOT_VECTOR = 32'h00000000;
|
parameter ISR_VECTOR = 32'h00000000;
|
parameter ISR_VECTOR = 32'h00000000;
|
parameter REGISTER_FILE_TYPE = "SIMULATION";
|
parameter REGISTER_FILE_TYPE = "SIMULATION";
|
parameter SUPPORT_32REGS = "ENABLED";
|
parameter SUPPORT_32REGS = "ENABLED";
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Registers
|
// Registers
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
// PC
|
// PC
|
reg [31:0] pc_q;
|
reg [31:0] pc_q;
|
|
|
// Exception saved program counter
|
// Exception saved program counter
|
reg [31:0] epc_q;
|
reg [31:0] epc_q;
|
|
|
// Supervisor register
|
// Supervisor register
|
reg [31:0] sr_q;
|
reg [31:0] sr_q;
|
|
|
// Exception saved supervisor register
|
// Exception saved supervisor register
|
reg [31:0] esr_q;
|
reg [31:0] esr_q;
|
|
|
// Destination register number (post execute stage)
|
// Destination register number (post execute stage)
|
reg [4:0] ex_rd_q;
|
reg [4:0] ex_rd_q;
|
|
|
// ALU input A
|
// ALU input A
|
reg [31:0] ex_alu_a_q;
|
reg [31:0] ex_alu_a_q;
|
|
|
// ALU input B
|
// ALU input B
|
reg [31:0] ex_alu_b_q;
|
reg [31:0] ex_alu_b_q;
|
|
|
// ALU output
|
// ALU output
|
wire [31:0] ex_result_w;
|
wire [31:0] ex_result_w;
|
|
|
// ALU Carry
|
// ALU Carry
|
wire alu_carry_out_w;
|
wire alu_carry_out_w;
|
wire alu_carry_update_w;
|
wire alu_carry_update_w;
|
|
|
// ALU Comparisons
|
// ALU Comparisons
|
wire compare_equal_w;
|
wire compare_equal_w;
|
wire compare_gts_w;
|
wire compare_gts_w;
|
wire compare_gt_w;
|
wire compare_gt_w;
|
wire compare_lts_w;
|
wire compare_lts_w;
|
wire compare_lt_w;
|
wire compare_lt_w;
|
wire alu_flag_update;
|
wire alu_flag_update_w;
|
|
|
// ALU operation selection
|
// ALU operation selection
|
reg [3:0] ex_alu_func_q;
|
reg [3:0] ex_alu_func_q;
|
|
|
// Delayed NMI
|
// Delayed NMI
|
reg nmi_q;
|
reg nmi_q;
|
|
|
// SIM PUTC
|
// SIM PUTC
|
`ifdef SIM_EXT_PUTC
|
`ifdef SIM_EXT_PUTC
|
reg [7:0] putc_q;
|
reg [7:0] putc_q;
|
`endif
|
`endif
|
|
|
wire [4:0] ra_w;
|
wire [4:0] ra_w;
|
wire [4:0] rb_w;
|
wire [4:0] rb_w;
|
wire [4:0] rd_w;
|
wire [4:0] rd_w;
|
|
|
wire [31:0] reg_ra_w;
|
wire [31:0] reg_ra_w;
|
wire [31:0] reg_rb_w;
|
wire [31:0] reg_rb_w;
|
|
|
reg [31:0] opcode_q;
|
reg [31:0] opcode_q;
|
|
|
reg [31:0] load_result_r;
|
reg [31:0] load_result_r;
|
|
|
reg [1:0] mem_offset_q;
|
reg [1:0] mem_offset_q;
|
|
|
// Current state
|
// Current state
|
parameter STATE_IDLE = 0;
|
parameter STATE_IDLE = 0;
|
parameter STATE_FETCH = 1;
|
parameter STATE_FETCH = 1;
|
parameter STATE_FETCH_WAIT = 2;
|
parameter STATE_FETCH_WAIT = 2;
|
parameter STATE_EXEC = 3;
|
parameter STATE_EXEC = 3;
|
parameter STATE_MEM = 4;
|
parameter STATE_MEM = 4;
|
parameter STATE_WRITE_BACK = 5;
|
parameter STATE_WRITE_BACK = 5;
|
|
|
reg [3:0] state_q;
|
reg [3:0] state_q;
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Instantiation
|
// Instantiation
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
// ALU
|
// ALU
|
altor32_alu alu
|
altor32_alu alu
|
(
|
(
|
// ALU operation select
|
// ALU operation select
|
.op_i(ex_alu_func_q),
|
.op_i(ex_alu_func_q),
|
|
|
// Operands
|
// Operands
|
.a_i(ex_alu_a_q),
|
.a_i(ex_alu_a_q),
|
.b_i(ex_alu_b_q),
|
.b_i(ex_alu_b_q),
|
.c_i(sr_q[`OR32_SR_CY]),
|
.c_i(sr_q[`SR_CY]),
|
|
|
// Result
|
// Result
|
.p_o(ex_result_w),
|
.p_o(ex_result_w),
|
|
|
// Carry
|
// Carry
|
.c_o(alu_carry_out_w),
|
.c_o(alu_carry_out_w),
|
.c_update_o(alu_carry_update_w),
|
.c_update_o(alu_carry_update_w),
|
|
|
// Comparisons
|
// Comparisons
|
.equal_o(compare_equal_w),
|
.equal_o(compare_equal_w),
|
.greater_than_signed_o(compare_gts_w),
|
.greater_than_signed_o(compare_gts_w),
|
.greater_than_o(compare_gt_w),
|
.greater_than_o(compare_gt_w),
|
.less_than_signed_o(compare_lts_w),
|
.less_than_signed_o(compare_lts_w),
|
.less_than_o(compare_lt_w),
|
.less_than_o(compare_lt_w),
|
.flag_update_o(alu_flag_update)
|
.flag_update_o(alu_flag_update_w)
|
);
|
);
|
|
|
// Writeback result
|
// Writeback result
|
wire [31:0] w_write_res = (state_q == STATE_MEM) ? load_result_r : ex_result_w;
|
wire [31:0] w_write_res = (state_q == STATE_MEM) ? load_result_r : ex_result_w;
|
|
|
// Writeback enable
|
// Writeback enable
|
wire w_write_en = (state_q == STATE_MEM & mem_ack_i) | (state_q == STATE_WRITE_BACK);
|
wire w_write_en = (state_q == STATE_MEM & mem_ack_i) | (state_q == STATE_WRITE_BACK);
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// [Xilinx] Register file
|
// [Xilinx] Register file
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
generate
|
generate
|
if (REGISTER_FILE_TYPE == "XILINX")
|
if (REGISTER_FILE_TYPE == "XILINX")
|
begin : REGFILE_XIL
|
begin : REGFILE_XIL
|
altor32_regfile_xil
|
altor32_regfile_xil
|
#(
|
#(
|
.SUPPORT_32REGS(SUPPORT_32REGS)
|
.SUPPORT_32REGS(SUPPORT_32REGS)
|
)
|
)
|
reg_bank
|
reg_bank
|
(
|
(
|
// Clocking
|
// Clocking
|
.clk_i(clk_i),
|
.clk_i(clk_i),
|
.rst_i(rst_i),
|
.rst_i(rst_i),
|
.wr_i(w_write_en),
|
.wr_i(w_write_en),
|
|
|
// Tri-port
|
// Tri-port
|
.ra_i(ra_w),
|
.ra_i(ra_w),
|
.rb_i(rb_w),
|
.rb_i(rb_w),
|
.rd_i(ex_rd_q),
|
.rd_i(ex_rd_q),
|
.reg_ra_o(reg_ra_w),
|
.reg_ra_o(reg_ra_w),
|
.reg_rb_o(reg_rb_w),
|
.reg_rb_o(reg_rb_w),
|
.reg_rd_i(w_write_res)
|
.reg_rd_i(w_write_res)
|
);
|
);
|
end
|
end
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// [Altera] Register file
|
// [Altera] Register file
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
else if (REGISTER_FILE_TYPE == "ALTERA")
|
else if (REGISTER_FILE_TYPE == "ALTERA")
|
begin : REGFILE_ALT
|
begin : REGFILE_ALT
|
altor32_regfile_alt
|
altor32_regfile_alt
|
#(
|
#(
|
.SUPPORT_32REGS(SUPPORT_32REGS)
|
.SUPPORT_32REGS(SUPPORT_32REGS)
|
)
|
)
|
reg_bank
|
reg_bank
|
(
|
(
|
// Clocking
|
// Clocking
|
.clk_i(clk_i),
|
.clk_i(clk_i),
|
.rst_i(rst_i),
|
.rst_i(rst_i),
|
.wr_i(w_write_en),
|
.wr_i(w_write_en),
|
|
|
// Tri-port
|
// Tri-port
|
.ra_i(ra_w),
|
.ra_i(ra_w),
|
.rb_i(rb_w),
|
.rb_i(rb_w),
|
.rd_i(ex_rd_q),
|
.rd_i(ex_rd_q),
|
.reg_ra_o(reg_ra_w),
|
.reg_ra_o(reg_ra_w),
|
.reg_rb_o(reg_rb_w),
|
.reg_rb_o(reg_rb_w),
|
.reg_rd_i(w_write_res)
|
.reg_rd_i(w_write_res)
|
);
|
);
|
end
|
end
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// [Simulation] Register file
|
// [Simulation] Register file
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
else
|
else
|
begin : REGFILE_SIM
|
begin : REGFILE_SIM
|
altor32_regfile_sim
|
altor32_regfile_sim
|
#(
|
#(
|
.SUPPORT_32REGS(SUPPORT_32REGS)
|
.SUPPORT_32REGS(SUPPORT_32REGS)
|
)
|
)
|
reg_bank
|
reg_bank
|
(
|
(
|
// Clocking
|
// Clocking
|
.clk_i(clk_i),
|
.clk_i(clk_i),
|
.rst_i(rst_i),
|
.rst_i(rst_i),
|
.wr_i(w_write_en),
|
.wr_i(w_write_en),
|
|
|
// Tri-port
|
// Tri-port
|
.ra_i(ra_w),
|
.ra_i(ra_w),
|
.rb_i(rb_w),
|
.rb_i(rb_w),
|
.rd_i(ex_rd_q),
|
.rd_i(ex_rd_q),
|
.reg_ra_o(reg_ra_w),
|
.reg_ra_o(reg_ra_w),
|
.reg_rb_o(reg_rb_w),
|
.reg_rb_o(reg_rb_w),
|
.reg_rd_i(w_write_res)
|
.reg_rd_i(w_write_res)
|
);
|
);
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Opcode decode
|
// Opcode decode
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg [7:0] inst_r;
|
reg [7:0] inst_r;
|
reg [7:0] alu_op_r;
|
reg [7:0] alu_op_r;
|
reg [1:0] shift_op_r;
|
reg [1:0] shift_op_r;
|
reg [15:0] sfxx_op_r;
|
reg [15:0] sfxx_op_r;
|
reg [15:0] uint16_r;
|
reg [15:0] uint16_r;
|
reg [31:0] uint32_r;
|
reg [31:0] uint32_r;
|
reg [31:0] int32_r;
|
reg [31:0] int32_r;
|
reg [31:0] store_int32_r;
|
reg [31:0] store_int32_r;
|
reg [15:0] mxspr_uint16_r;
|
reg [15:0] mxspr_uint16_r;
|
reg [31:0] target_int26_r;
|
reg [31:0] target_int26_r;
|
reg [31:0] reg_ra_r;
|
reg [31:0] reg_ra_r;
|
reg [31:0] reg_rb_r;
|
reg [31:0] reg_rb_r;
|
reg [31:0] shift_rb_r;
|
reg [31:0] shift_rb_r;
|
reg [31:0] shift_imm_r;
|
reg [31:0] shift_imm_r;
|
|
|
always @ *
|
always @ *
|
begin
|
begin
|
// Instruction
|
// Instruction
|
inst_r = {2'b00,opcode_q[31:26]};
|
inst_r = {2'b00,opcode_q[31:26]};
|
|
|
// Sub instructions
|
// Sub instructions
|
alu_op_r = {opcode_q[9:6],opcode_q[3:0]};
|
alu_op_r = {opcode_q[9:6],opcode_q[3:0]};
|
sfxx_op_r = {5'b00,opcode_q[31:21]} & `INST_OR32_SFMASK;
|
sfxx_op_r = {5'b00,opcode_q[31:21]} & `INST_OR32_SFMASK;
|
shift_op_r = opcode_q[7:6];
|
shift_op_r = opcode_q[7:6];
|
|
|
// Branch target
|
// Branch target
|
target_int26_r = sign_extend_imm26(opcode_q[25:0]);
|
target_int26_r = sign_extend_imm26(opcode_q[25:0]);
|
|
|
// Store immediate
|
// Store immediate
|
store_int32_r = sign_extend_imm16({opcode_q[25:21],opcode_q[10:0]});
|
store_int32_r = sign_extend_imm16({opcode_q[25:21],opcode_q[10:0]});
|
|
|
// Signed & unsigned imm -> 32-bits
|
// Signed & unsigned imm -> 32-bits
|
uint16_r = opcode_q[15:0];
|
uint16_r = opcode_q[15:0];
|
int32_r = sign_extend_imm16(opcode_q[15:0]);
|
int32_r = sign_extend_imm16(opcode_q[15:0]);
|
uint32_r = extend_imm16(opcode_q[15:0]);
|
uint32_r = extend_imm16(opcode_q[15:0]);
|
|
|
// Register values [ra/rb]
|
// Register values [ra/rb]
|
reg_ra_r = reg_ra_w;
|
reg_ra_r = reg_ra_w;
|
reg_rb_r = reg_rb_w;
|
reg_rb_r = reg_rb_w;
|
|
|
// Shift ammount (from register[rb])
|
// Shift ammount (from register[rb])
|
shift_rb_r = {26'b00,reg_rb_w[5:0]};
|
shift_rb_r = {26'b00,reg_rb_w[5:0]};
|
|
|
// Shift ammount (from immediate)
|
// Shift ammount (from immediate)
|
shift_imm_r = {26'b00,opcode_q[5:0]};
|
shift_imm_r = {26'b00,opcode_q[5:0]};
|
|
|
// MTSPR/MFSPR operand
|
// MTSPR/MFSPR operand
|
mxspr_uint16_r = (reg_ra_w[15:0] | {5'b00000,opcode_q[10:0]});
|
mxspr_uint16_r = (reg_ra_w[15:0] | {5'b00000,opcode_q[10:0]});
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Instruction Decode
|
// Instruction Decode
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
wire inst_add_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_ADD); // l.add
|
wire inst_add_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_ADD); // l.add
|
wire inst_addc_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_ADDC); // l.addc
|
wire inst_addc_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_ADDC); // l.addc
|
wire inst_and_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_AND); // l.and
|
wire inst_and_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_AND); // l.and
|
wire inst_or_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_OR); // l.or
|
wire inst_or_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_OR); // l.or
|
wire inst_sll_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SLL); // l.sll
|
wire inst_sll_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SLL); // l.sll
|
wire inst_sw_ra = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRA); // l.sra
|
wire inst_sw_ra = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRA); // l.sra
|
wire inst_srl_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRL); // l.srl
|
wire inst_srl_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRL); // l.srl
|
wire inst_sub_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SUB); // l.sub
|
wire inst_sub_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SUB); // l.sub
|
wire inst_xor_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_XOR); // l.xor
|
wire inst_xor_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_XOR); // l.xor
|
wire inst_mul_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_MUL); // l.mul
|
wire inst_mul_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_MUL); // l.mul
|
wire inst_mulu_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_MULU); // l.mulu
|
wire inst_mulu_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_MULU); // l.mulu
|
|
|
wire inst_addi_w = (inst_r == `INST_OR32_ADDI); // l.addi
|
wire inst_addi_w = (inst_r == `INST_OR32_ADDI); // l.addi
|
wire inst_andi_w = (inst_r == `INST_OR32_ANDI); // l.andi
|
wire inst_andi_w = (inst_r == `INST_OR32_ANDI); // l.andi
|
wire inst_bf_w = (inst_r == `INST_OR32_BF); // l.bf
|
wire inst_bf_w = (inst_r == `INST_OR32_BF); // l.bf
|
wire inst_bnf_w = (inst_r == `INST_OR32_BNF); // l.bnf
|
wire inst_bnf_w = (inst_r == `INST_OR32_BNF); // l.bnf
|
wire inst_j_w = (inst_r == `INST_OR32_J); // l.j
|
wire inst_j_w = (inst_r == `INST_OR32_J); // l.j
|
wire inst_jal_w = (inst_r == `INST_OR32_JAL); // l.jal
|
wire inst_jal_w = (inst_r == `INST_OR32_JAL); // l.jal
|
wire inst_jalr_w = (inst_r == `INST_OR32_JALR); // l.jalr
|
wire inst_jalr_w = (inst_r == `INST_OR32_JALR); // l.jalr
|
wire inst_jr_w = (inst_r == `INST_OR32_JR); // l.jr
|
wire inst_jr_w = (inst_r == `INST_OR32_JR); // l.jr
|
wire inst_lbs_w = (inst_r == `INST_OR32_LBS); // l.lbs
|
wire inst_lbs_w = (inst_r == `INST_OR32_LBS); // l.lbs
|
wire inst_lhs_w = (inst_r == `INST_OR32_LHS); // l.lhs
|
wire inst_lhs_w = (inst_r == `INST_OR32_LHS); // l.lhs
|
wire inst_lws_w = (inst_r == `INST_OR32_LWS); // l.lws
|
wire inst_lws_w = (inst_r == `INST_OR32_LWS); // l.lws
|
wire inst_lbz_w = (inst_r == `INST_OR32_LBZ); // l.lbz
|
wire inst_lbz_w = (inst_r == `INST_OR32_LBZ); // l.lbz
|
wire inst_lhz_w = (inst_r == `INST_OR32_LHZ); // l.lhz
|
wire inst_lhz_w = (inst_r == `INST_OR32_LHZ); // l.lhz
|
wire inst_lwz_w = (inst_r == `INST_OR32_LWZ); // l.lwz
|
wire inst_lwz_w = (inst_r == `INST_OR32_LWZ); // l.lwz
|
wire inst_mfspr_w = (inst_r == `INST_OR32_MFSPR); // l.mfspr
|
wire inst_mfspr_w = (inst_r == `INST_OR32_MFSPR); // l.mfspr
|
wire inst_mtspr_w = (inst_r == `INST_OR32_MTSPR); // l.mtspr
|
wire inst_mtspr_w = (inst_r == `INST_OR32_MTSPR); // l.mtspr
|
wire inst_movhi_w = (inst_r == `INST_OR32_MOVHI); // l.movhi
|
wire inst_movhi_w = (inst_r == `INST_OR32_MOVHI); // l.movhi
|
wire inst_nop_w = (inst_r == `INST_OR32_NOP); // l.nop
|
wire inst_nop_w = (inst_r == `INST_OR32_NOP); // l.nop
|
wire inst_ori_w = (inst_r == `INST_OR32_ORI); // l.ori
|
wire inst_ori_w = (inst_r == `INST_OR32_ORI); // l.ori
|
wire inst_rfe_w = (inst_r == `INST_OR32_RFE); // l.rfe
|
wire inst_rfe_w = (inst_r == `INST_OR32_RFE); // l.rfe
|
|
|
wire inst_sb_w = (inst_r == `INST_OR32_SB); // l.sb
|
wire inst_sb_w = (inst_r == `INST_OR32_SB); // l.sb
|
wire inst_sh_w = (inst_r == `INST_OR32_SH); // l.sh
|
wire inst_sh_w = (inst_r == `INST_OR32_SH); // l.sh
|
wire inst_sw_w = (inst_r == `INST_OR32_SW); // l.sw
|
wire inst_sw_w = (inst_r == `INST_OR32_SW); // l.sw
|
|
|
wire inst_slli_w = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SLLI); // l.slli
|
wire inst_slli_w = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SLLI); // l.slli
|
wire inst_srai_w = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SRAI); // l.srai
|
wire inst_srai_w = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SRAI); // l.srai
|
wire inst_srli_w = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SRLI); // l.srli
|
wire inst_srli_w = (inst_r == `INST_OR32_SHIFTI) & (shift_op_r == `INST_OR32_SRLI); // l.srli
|
|
|
wire inst_xori_w = (inst_r == `INST_OR32_XORI); // l.xori
|
wire inst_xori_w = (inst_r == `INST_OR32_XORI); // l.xori
|
|
|
wire inst_sfxx_w = (inst_r == `INST_OR32_SFXX);
|
wire inst_sfxx_w = (inst_r == `INST_OR32_SFXX);
|
wire inst_sfxxi_w = (inst_r == `INST_OR32_SFXXI);
|
wire inst_sfxxi_w = (inst_r == `INST_OR32_SFXXI);
|
|
|
wire inst_sfeq_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFEQ); // l.sfeq
|
wire inst_sfeq_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFEQ); // l.sfeq
|
wire inst_sfges_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGES); // l.sfges
|
wire inst_sfges_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGES); // l.sfges
|
|
|
wire inst_sfgeu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGEU); // l.sfgeu
|
wire inst_sfgeu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGEU); // l.sfgeu
|
wire inst_sfgts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTS); // l.sfgts
|
wire inst_sfgts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTS); // l.sfgts
|
wire inst_sfgtu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTU); // l.sfgtu
|
wire inst_sfgtu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFGTU); // l.sfgtu
|
wire inst_sfles_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLES); // l.sfles
|
wire inst_sfles_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLES); // l.sfles
|
wire inst_sfleu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLEU); // l.sfleu
|
wire inst_sfleu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLEU); // l.sfleu
|
wire inst_sflts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTS); // l.sflts
|
wire inst_sflts_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTS); // l.sflts
|
wire inst_sfltu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu
|
wire inst_sfltu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu
|
wire inst_sfne_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne
|
wire inst_sfne_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne
|
|
|
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (opcode_q[31:24] == `INST_OR32_SYS); // l.sys
|
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (opcode_q[31:24] == `INST_OR32_SYS); // l.sys
|
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (opcode_q[31:24] == `INST_OR32_TRAP); // l.trap
|
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (opcode_q[31:24] == `INST_OR32_TRAP); // l.trap
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Load/Store operation?
|
// Load/Store operation?
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg load_inst_r;
|
reg load_inst_r;
|
reg store_inst_r;
|
reg store_inst_r;
|
reg [31:0] mem_addr_r;
|
reg [31:0] mem_addr_r;
|
always @ *
|
always @ *
|
begin
|
begin
|
load_inst_r = inst_lbs_w | inst_lhs_w | inst_lws_w |
|
load_inst_r = inst_lbs_w | inst_lhs_w | inst_lws_w |
|
inst_lbz_w | inst_lhz_w | inst_lwz_w;
|
inst_lbz_w | inst_lhz_w | inst_lwz_w;
|
store_inst_r = inst_sb_w | inst_sh_w | inst_sw_w;
|
store_inst_r = inst_sb_w | inst_sh_w | inst_sw_w;
|
|
|
// Memory address is relative to RA
|
// Memory address is relative to RA
|
mem_addr_r = reg_ra_r + (store_inst_r ? store_int32_r : int32_r);
|
mem_addr_r = reg_ra_r + (store_inst_r ? store_int32_r : int32_r);
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Next State Logic
|
// Next State Logic
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg [3:0] next_state_r;
|
reg [3:0] next_state_r;
|
always @ *
|
always @ *
|
begin
|
begin
|
next_state_r = state_q;
|
next_state_r = state_q;
|
|
|
case (state_q)
|
case (state_q)
|
//-----------------------------------------
|
//-----------------------------------------
|
// IDLE -
|
// IDLE -
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_IDLE :
|
STATE_IDLE :
|
begin
|
begin
|
if (enable_i)
|
if (enable_i)
|
next_state_r = STATE_FETCH;
|
next_state_r = STATE_FETCH;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH - Fetch line from memory
|
// FETCH - Fetch line from memory
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH :
|
STATE_FETCH :
|
begin
|
begin
|
next_state_r = STATE_FETCH_WAIT;
|
next_state_r = STATE_FETCH_WAIT;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH_WAIT - Wait for read responses
|
// FETCH_WAIT - Wait for read responses
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH_WAIT:
|
STATE_FETCH_WAIT:
|
begin
|
begin
|
// Read from memory complete
|
// Read from memory complete
|
if (mem_ack_i)
|
if (mem_ack_i)
|
next_state_r = STATE_EXEC;
|
next_state_r = STATE_EXEC;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// EXEC
|
// EXEC
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_EXEC :
|
STATE_EXEC :
|
begin
|
begin
|
if (load_inst_r || store_inst_r)
|
if (load_inst_r || store_inst_r)
|
next_state_r = STATE_MEM;
|
next_state_r = STATE_MEM;
|
else
|
else
|
next_state_r = STATE_WRITE_BACK;
|
next_state_r = STATE_WRITE_BACK;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// MEM
|
// MEM
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_MEM :
|
STATE_MEM :
|
begin
|
begin
|
// Read from memory complete
|
// Read from memory complete
|
if (mem_ack_i)
|
if (mem_ack_i)
|
next_state_r = STATE_FETCH;
|
next_state_r = STATE_FETCH;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// WRITE_BACK
|
// WRITE_BACK
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_WRITE_BACK :
|
STATE_WRITE_BACK :
|
begin
|
begin
|
if (enable_i)
|
if (enable_i)
|
next_state_r = STATE_FETCH;
|
next_state_r = STATE_FETCH;
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
// Update state
|
// Update state
|
always @ (posedge rst_i or posedge clk_i )
|
always @ (posedge rst_i or posedge clk_i )
|
begin
|
begin
|
if (rst_i == 1'b1)
|
if (rst_i == 1'b1)
|
state_q <= STATE_IDLE;
|
state_q <= STATE_IDLE;
|
else
|
else
|
state_q <= next_state_r;
|
state_q <= next_state_r;
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Memory Access / Instruction Fetch
|
// Memory Access / Instruction Fetch
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
always @ (posedge rst_i or posedge clk_i )
|
always @ (posedge rst_i or posedge clk_i )
|
begin
|
begin
|
if (rst_i == 1'b1)
|
if (rst_i == 1'b1)
|
begin
|
begin
|
mem_addr_o <= 32'h00000000;
|
mem_addr_o <= 32'h00000000;
|
mem_dat_o <= 32'h00000000;
|
mem_dat_o <= 32'h00000000;
|
mem_sel_o <= 4'b0;
|
mem_sel_o <= 4'b0;
|
mem_we_o <= 1'b0;
|
mem_we_o <= 1'b0;
|
mem_stb_o <= 1'b0;
|
mem_stb_o <= 1'b0;
|
mem_cyc_o <= 1'b0;
|
mem_cyc_o <= 1'b0;
|
|
|
opcode_q <= 32'h00000000;
|
opcode_q <= 32'h00000000;
|
mem_offset_q <= 2'b0;
|
mem_offset_q <= 2'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
|
|
if (~mem_stall_i)
|
if (~mem_stall_i)
|
mem_stb_o <= 1'b0;
|
mem_stb_o <= 1'b0;
|
|
|
case (state_q)
|
case (state_q)
|
|
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH - Issue instruction fetch
|
// FETCH - Issue instruction fetch
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH :
|
STATE_FETCH :
|
begin
|
begin
|
// Start fetch from memory
|
// Start fetch from memory
|
mem_addr_o <= pc_q;
|
mem_addr_o <= pc_q;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_we_o <= 1'b0;
|
mem_we_o <= 1'b0;
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// FETCH_WAIT - Wait for response
|
// FETCH_WAIT - Wait for response
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_FETCH_WAIT :
|
STATE_FETCH_WAIT :
|
begin
|
begin
|
// Data ready from memory?
|
// Data ready from memory?
|
if (mem_ack_i)
|
if (mem_ack_i)
|
begin
|
begin
|
opcode_q <= mem_dat_i;
|
opcode_q <= mem_dat_i;
|
mem_cyc_o <= 1'b0;
|
mem_cyc_o <= 1'b0;
|
end
|
end
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// EXEC - Issue read / write
|
// EXEC - Issue read / write
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_EXEC :
|
STATE_EXEC :
|
begin
|
begin
|
`ifdef CONF_CORE_TRACE
|
`ifdef CONF_CORE_TRACE
|
$display("%08x: Execute 0x%08x", pc_q, opcode_q);
|
$display("%08x: Execute 0x%08x", pc_q, opcode_q);
|
$display(" rA[%d] = 0x%08x", ra_w, reg_ra_r);
|
$display(" rA[%d] = 0x%08x", ra_w, reg_ra_r);
|
$display(" rB[%d] = 0x%08x", rb_w, reg_rb_r);
|
$display(" rB[%d] = 0x%08x", rb_w, reg_rb_r);
|
`endif
|
`endif
|
|
|
case (1'b1)
|
case (1'b1)
|
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
|
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
|
load_inst_r:
|
load_inst_r:
|
begin
|
begin
|
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
|
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
|
mem_offset_q <= mem_addr_r[1:0];
|
mem_offset_q <= mem_addr_r[1:0];
|
mem_dat_o <= 32'h00000000;
|
mem_dat_o <= 32'h00000000;
|
mem_sel_o <= 4'b1111;
|
mem_sel_o <= 4'b1111;
|
mem_we_o <= 1'b0;
|
mem_we_o <= 1'b0;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
|
|
`ifdef CONF_CORE_DEBUG
|
`ifdef CONF_CORE_DEBUG
|
$display(" Load from 0x%08x to R%d", mem_addr_r, rd_w);
|
$display(" Load from 0x%08x to R%d", mem_addr_r, rd_w);
|
`endif
|
`endif
|
end
|
end
|
|
|
inst_sb_w: // l.sb
|
inst_sb_w: // l.sb
|
begin
|
begin
|
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
|
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
|
mem_offset_q <= mem_addr_r[1:0];
|
mem_offset_q <= mem_addr_r[1:0];
|
case (mem_addr_r[1:0])
|
case (mem_addr_r[1:0])
|
2'b00 :
|
2'b00 :
|
begin
|
begin
|
mem_dat_o <= {reg_rb_r[7:0],24'h000000};
|
mem_dat_o <= {reg_rb_r[7:0],24'h000000};
|
mem_sel_o <= 4'b1000;
|
mem_sel_o <= 4'b1000;
|
mem_we_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
end
|
end
|
2'b01 :
|
2'b01 :
|
begin
|
begin
|
mem_dat_o <= {{8'h00,reg_rb_r[7:0]},16'h0000};
|
mem_dat_o <= {{8'h00,reg_rb_r[7:0]},16'h0000};
|
mem_sel_o <= 4'b0100;
|
mem_sel_o <= 4'b0100;
|
mem_we_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
end
|
end
|
2'b10 :
|
2'b10 :
|
begin
|
begin
|
mem_dat_o <= {{16'h0000,reg_rb_r[7:0]},8'h00};
|
mem_dat_o <= {{16'h0000,reg_rb_r[7:0]},8'h00};
|
mem_sel_o <= 4'b0010;
|
mem_sel_o <= 4'b0010;
|
mem_we_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
end
|
end
|
2'b11 :
|
2'b11 :
|
begin
|
begin
|
mem_dat_o <= {24'h000000,reg_rb_r[7:0]};
|
mem_dat_o <= {24'h000000,reg_rb_r[7:0]};
|
mem_sel_o <= 4'b0001;
|
mem_sel_o <= 4'b0001;
|
mem_we_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
end
|
end
|
default :
|
default :
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
inst_sh_w: // l.sh
|
inst_sh_w: // l.sh
|
begin
|
begin
|
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
|
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
|
mem_offset_q <= mem_addr_r[1:0];
|
mem_offset_q <= mem_addr_r[1:0];
|
case (mem_addr_r[1:0])
|
case (mem_addr_r[1:0])
|
2'b00 :
|
2'b00 :
|
begin
|
begin
|
mem_dat_o <= {reg_rb_r[15:0],16'h0000};
|
mem_dat_o <= {reg_rb_r[15:0],16'h0000};
|
mem_sel_o <= 4'b1100;
|
mem_sel_o <= 4'b1100;
|
mem_we_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
end
|
end
|
2'b10 :
|
2'b10 :
|
begin
|
begin
|
mem_dat_o <= {16'h0000,reg_rb_r[15:0]};
|
mem_dat_o <= {16'h0000,reg_rb_r[15:0]};
|
mem_sel_o <= 4'b0011;
|
mem_sel_o <= 4'b0011;
|
mem_we_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
end
|
end
|
default :
|
default :
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
inst_sw_w: // l.sw
|
inst_sw_w: // l.sw
|
begin
|
begin
|
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
|
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
|
mem_offset_q <= mem_addr_r[1:0];
|
mem_offset_q <= mem_addr_r[1:0];
|
mem_dat_o <= reg_rb_r;
|
mem_dat_o <= reg_rb_r;
|
mem_sel_o <= 4'b1111;
|
mem_sel_o <= 4'b1111;
|
mem_we_o <= 1'b1;
|
mem_we_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_stb_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
mem_cyc_o <= 1'b1;
|
|
|
`ifdef CONF_CORE_DEBUG
|
`ifdef CONF_CORE_DEBUG
|
$display(" Store R%d to 0x%08x = 0x%08x", rb_w, {mem_addr_r[31:2],2'b00}, reg_rb_r);
|
$display(" Store R%d to 0x%08x = 0x%08x", rb_w, {mem_addr_r[31:2],2'b00}, reg_rb_r);
|
`endif
|
`endif
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
//-----------------------------------------
|
//-----------------------------------------
|
// MEM - Wait for response
|
// MEM - Wait for response
|
//-----------------------------------------
|
//-----------------------------------------
|
STATE_MEM :
|
STATE_MEM :
|
begin
|
begin
|
// Data ready from memory?
|
// Data ready from memory?
|
if (mem_ack_i)
|
if (mem_ack_i)
|
begin
|
begin
|
mem_cyc_o <= 1'b0;
|
mem_cyc_o <= 1'b0;
|
end
|
end
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
assign mem_cti_o = 3'b111;
|
assign mem_cti_o = 3'b111;
|
|
|
// If simulation, RA = 03 if NOP instruction
|
// If simulation, RA = 03 if NOP instruction
|
`ifdef SIMULATION
|
`ifdef SIMULATION
|
wire [7:0] v_fetch_inst = {2'b00, opcode_q[31:26]};
|
wire [7:0] v_fetch_inst = {2'b00, opcode_q[31:26]};
|
wire v_is_nop = (v_fetch_inst == `INST_OR32_NOP);
|
wire v_is_nop = (v_fetch_inst == `INST_OR32_NOP);
|
assign ra_w = v_is_nop ? 5'd3 : opcode_q[20:16];
|
assign ra_w = v_is_nop ? 5'd3 : opcode_q[20:16];
|
`else
|
`else
|
assign ra_w = opcode_q[20:16];
|
assign ra_w = opcode_q[20:16];
|
`endif
|
`endif
|
|
|
assign rb_w = opcode_q[15:11];
|
assign rb_w = opcode_q[15:11];
|
assign rd_w = opcode_q[25:21];
|
assign rd_w = opcode_q[25:21];
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Next PC
|
// Next PC
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg [31:0] next_pc_r;
|
reg [31:0] next_pc_r;
|
|
|
always @ *
|
always @ *
|
begin
|
begin
|
// Next expected PC (current PC + 4)
|
// Next expected PC (current PC + 4)
|
next_pc_r = (pc_q + 4);
|
next_pc_r = (pc_q + 4);
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Next SR
|
// Next SR
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg [31:0] next_sr_r;
|
reg [31:0] next_sr_r;
|
reg compare_result_r;
|
reg compare_result_r;
|
always @ *
|
always @ *
|
begin
|
begin
|
next_sr_r = sr_q;
|
next_sr_r = sr_q;
|
|
|
// Update SR.F
|
// Update SR.F
|
if (alu_flag_update)
|
if (alu_flag_update_w)
|
next_sr_r[`OR32_SR_F] = compare_result_r;
|
next_sr_r[`SR_F] = compare_result_r;
|
|
|
// Latch carry if updated
|
// Latch carry if updated
|
if (alu_carry_update_w)
|
if (alu_carry_update_w)
|
next_sr_r[`OR32_SR_CY] = alu_carry_out_w;
|
next_sr_r[`SR_CY] = alu_carry_out_w;
|
|
|
case (1'b1)
|
case (1'b1)
|
inst_mtspr_w:
|
inst_mtspr_w:
|
begin
|
begin
|
case (mxspr_uint16_r)
|
case (mxspr_uint16_r)
|
// SR - Supervision register
|
// SR - Supervision register
|
`SPR_REG_SR:
|
`SPR_REG_SR:
|
begin
|
begin
|
next_sr_r[`OR32_SR_F] = reg_rb_r[`OR32_SR_F];
|
next_sr_r[`SR_F] = reg_rb_r[`SR_F];
|
next_sr_r[`OR32_SR_CY] = reg_rb_r[`OR32_SR_CY];
|
next_sr_r[`SR_CY] = reg_rb_r[`SR_CY];
|
next_sr_r[`OR32_SR_IEE] = reg_rb_r[`OR32_SR_IEE];
|
next_sr_r[`SR_IEE] = reg_rb_r[`SR_IEE];
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
inst_rfe_w:
|
inst_rfe_w:
|
begin
|
begin
|
next_sr_r[`OR32_SR_F] = esr_q[`OR32_SR_F];
|
next_sr_r[`SR_F] = esr_q[`SR_F];
|
next_sr_r[`OR32_SR_CY] = esr_q[`OR32_SR_CY];
|
next_sr_r[`SR_CY] = esr_q[`SR_CY];
|
next_sr_r[`OR32_SR_IEE] = esr_q[`OR32_SR_IEE];
|
next_sr_r[`SR_IEE] = esr_q[`SR_IEE];
|
end
|
end
|
inst_sfxx_w,
|
inst_sfxx_w,
|
inst_sfxxi_w:
|
inst_sfxxi_w:
|
next_sr_r[`OR32_SR_F] = compare_result_r;
|
next_sr_r[`SR_F] = compare_result_r;
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Next EPC/ESR
|
// Next EPC/ESR
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg [31:0] next_epc_r;
|
reg [31:0] next_epc_r;
|
reg [31:0] next_esr_r;
|
reg [31:0] next_esr_r;
|
|
|
always @ *
|
always @ *
|
begin
|
begin
|
next_epc_r = epc_q;
|
next_epc_r = epc_q;
|
next_esr_r = esr_q;
|
next_esr_r = esr_q;
|
|
|
case (1'b1)
|
case (1'b1)
|
inst_mtspr_w: // l.mtspr
|
inst_mtspr_w: // l.mtspr
|
begin
|
begin
|
case (mxspr_uint16_r)
|
case (mxspr_uint16_r)
|
// EPCR - EPC Exception saved PC
|
// EPCR - EPC Exception saved PC
|
`SPR_REG_EPCR: next_epc_r = reg_rb_r;
|
`SPR_REG_EPCR: next_epc_r = reg_rb_r;
|
|
|
// ESR - Exception saved SR
|
// ESR - Exception saved SR
|
`SPR_REG_ESR: next_esr_r = reg_rb_r;
|
`SPR_REG_ESR: next_esr_r = reg_rb_r;
|
endcase
|
endcase
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// ALU inputs
|
// ALU inputs
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
// ALU operation selection
|
// ALU operation selection
|
reg [3:0] alu_func_r;
|
reg [3:0] alu_func_r;
|
|
|
// ALU operands
|
// ALU operands
|
reg [31:0] alu_input_a_r;
|
reg [31:0] alu_input_a_r;
|
reg [31:0] alu_input_b_r;
|
reg [31:0] alu_input_b_r;
|
reg write_rd_r;
|
reg write_rd_r;
|
|
|
always @ *
|
always @ *
|
begin
|
begin
|
alu_func_r = `ALU_NONE;
|
alu_func_r = `ALU_NONE;
|
alu_input_a_r = 32'b0;
|
alu_input_a_r = 32'b0;
|
alu_input_b_r = 32'b0;
|
alu_input_b_r = 32'b0;
|
write_rd_r = 1'b0;
|
write_rd_r = 1'b0;
|
|
|
case (1'b1)
|
case (1'b1)
|
|
|
inst_add_w: // l.add
|
inst_add_w: // l.add
|
begin
|
begin
|
alu_func_r = `ALU_ADD;
|
alu_func_r = `ALU_ADD;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = reg_rb_r;
|
alu_input_b_r = reg_rb_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_addc_w: // l.addc
|
inst_addc_w: // l.addc
|
begin
|
begin
|
alu_func_r = `ALU_ADDC;
|
alu_func_r = `ALU_ADDC;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = reg_rb_r;
|
alu_input_b_r = reg_rb_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_and_w: // l.and
|
inst_and_w: // l.and
|
begin
|
begin
|
alu_func_r = `ALU_AND;
|
alu_func_r = `ALU_AND;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = reg_rb_r;
|
alu_input_b_r = reg_rb_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_or_w: // l.or
|
inst_or_w: // l.or
|
begin
|
begin
|
alu_func_r = `ALU_OR;
|
alu_func_r = `ALU_OR;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = reg_rb_r;
|
alu_input_b_r = reg_rb_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_sll_w: // l.sll
|
inst_sll_w: // l.sll
|
begin
|
begin
|
alu_func_r = `ALU_SHIFTL;
|
alu_func_r = `ALU_SHIFTL;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = shift_rb_r;
|
alu_input_b_r = shift_rb_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_sw_ra: // l.sra
|
inst_sw_ra: // l.sra
|
begin
|
begin
|
alu_func_r = `ALU_SHIRTR_ARITH;
|
alu_func_r = `ALU_SHIRTR_ARITH;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = shift_rb_r;
|
alu_input_b_r = shift_rb_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_srl_w: // l.srl
|
inst_srl_w: // l.srl
|
begin
|
begin
|
alu_func_r = `ALU_SHIFTR;
|
alu_func_r = `ALU_SHIFTR;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = shift_rb_r;
|
alu_input_b_r = shift_rb_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_sub_w: // l.sub
|
inst_sub_w: // l.sub
|
begin
|
begin
|
alu_func_r = `ALU_SUB;
|
alu_func_r = `ALU_SUB;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = reg_rb_r;
|
alu_input_b_r = reg_rb_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_xor_w: // l.xor
|
inst_xor_w: // l.xor
|
begin
|
begin
|
alu_func_r = `ALU_XOR;
|
alu_func_r = `ALU_XOR;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = reg_rb_r;
|
alu_input_b_r = reg_rb_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_mul_w, // l.mul
|
inst_mul_w, // l.mul
|
inst_mulu_w: // l.mulu
|
inst_mulu_w: // l.mulu
|
begin
|
begin
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_addi_w: // l.addi
|
inst_addi_w: // l.addi
|
begin
|
begin
|
alu_func_r = `ALU_ADD;
|
alu_func_r = `ALU_ADD;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = int32_r;
|
alu_input_b_r = int32_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_andi_w: // l.andi
|
inst_andi_w: // l.andi
|
begin
|
begin
|
alu_func_r = `ALU_AND;
|
alu_func_r = `ALU_AND;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = uint32_r;
|
alu_input_b_r = uint32_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_jal_w: // l.jal
|
inst_jal_w: // l.jal
|
begin
|
begin
|
alu_input_a_r = next_pc_r;
|
alu_input_a_r = next_pc_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_jalr_w: // l.jalr
|
inst_jalr_w: // l.jalr
|
begin
|
begin
|
alu_input_a_r = next_pc_r;
|
alu_input_a_r = next_pc_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_mfspr_w: // l.mfspr
|
inst_mfspr_w: // l.mfspr
|
begin
|
begin
|
case (mxspr_uint16_r)
|
case (mxspr_uint16_r)
|
// SR - Supervision register
|
// SR - Supervision register
|
`SPR_REG_SR:
|
`SPR_REG_SR:
|
begin
|
begin
|
alu_input_a_r = 32'b0;
|
alu_input_a_r = 32'b0;
|
alu_input_a_r[`OR32_SR_F] = next_sr_r[`OR32_SR_F];
|
alu_input_a_r[`SR_F] = next_sr_r[`SR_F];
|
alu_input_a_r[`OR32_SR_CY] = next_sr_r[`OR32_SR_CY];
|
alu_input_a_r[`SR_CY] = next_sr_r[`SR_CY];
|
alu_input_a_r[`OR32_SR_IEE] = next_sr_r[`OR32_SR_IEE];
|
alu_input_a_r[`SR_IEE] = next_sr_r[`SR_IEE];
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
// EPCR - EPC Exception saved PC
|
// EPCR - EPC Exception saved PC
|
`SPR_REG_EPCR:
|
`SPR_REG_EPCR:
|
begin
|
begin
|
alu_input_a_r = epc_q;
|
alu_input_a_r = epc_q;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
// ESR - Exception saved SR
|
// ESR - Exception saved SR
|
`SPR_REG_ESR:
|
`SPR_REG_ESR:
|
begin
|
begin
|
alu_input_a_r = 32'b0;
|
alu_input_a_r = 32'b0;
|
alu_input_a_r[`OR32_SR_F] = esr_q[`OR32_SR_F];
|
alu_input_a_r[`SR_F] = esr_q[`SR_F];
|
alu_input_a_r[`OR32_SR_CY] = esr_q[`OR32_SR_CY];
|
alu_input_a_r[`SR_CY] = esr_q[`SR_CY];
|
alu_input_a_r[`OR32_SR_IEE] = esr_q[`OR32_SR_IEE];
|
alu_input_a_r[`SR_IEE] = esr_q[`SR_IEE];
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
inst_movhi_w: // l.movhi
|
inst_movhi_w: // l.movhi
|
begin
|
begin
|
alu_input_a_r = {uint16_r,16'h0000};
|
alu_input_a_r = {uint16_r,16'h0000};
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_ori_w: // l.ori
|
inst_ori_w: // l.ori
|
begin
|
begin
|
alu_func_r = `ALU_OR;
|
alu_func_r = `ALU_OR;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = uint32_r;
|
alu_input_b_r = uint32_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_slli_w: // l.slli
|
inst_slli_w: // l.slli
|
begin
|
begin
|
alu_func_r = `ALU_SHIFTL;
|
alu_func_r = `ALU_SHIFTL;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = shift_imm_r;
|
alu_input_b_r = shift_imm_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_srai_w: // l.srai
|
inst_srai_w: // l.srai
|
begin
|
begin
|
alu_func_r = `ALU_SHIRTR_ARITH;
|
alu_func_r = `ALU_SHIRTR_ARITH;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = shift_imm_r;
|
alu_input_b_r = shift_imm_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
inst_srli_w: // l.srli
|
inst_srli_w: // l.srli
|
begin
|
begin
|
alu_func_r = `ALU_SHIFTR;
|
alu_func_r = `ALU_SHIFTR;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = shift_imm_r;
|
alu_input_b_r = shift_imm_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
|
|
// l.sf*i
|
// l.sf*i
|
inst_sfxxi_w:
|
inst_sfxxi_w:
|
begin
|
begin
|
alu_func_r = `ALU_COMPARE;
|
alu_func_r = `ALU_COMPARE;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = int32_r;
|
alu_input_b_r = int32_r;
|
end
|
end
|
|
|
// l.sf*
|
// l.sf*
|
inst_sfxx_w:
|
inst_sfxx_w:
|
begin
|
begin
|
alu_func_r = `ALU_COMPARE;
|
alu_func_r = `ALU_COMPARE;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = reg_rb_r;
|
alu_input_b_r = reg_rb_r;
|
end
|
end
|
|
|
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
|
// l.lbs l.lhs l.lws l.lbz l.lhz l.lwz
|
inst_lbs_w,
|
inst_lbs_w,
|
inst_lhs_w,
|
inst_lhs_w,
|
inst_lws_w,
|
inst_lws_w,
|
inst_lbz_w,
|
inst_lbz_w,
|
inst_lhz_w,
|
inst_lhz_w,
|
inst_lwz_w:
|
inst_lwz_w:
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
|
|
inst_xori_w: // l.xori
|
inst_xori_w: // l.xori
|
begin
|
begin
|
alu_func_r = `ALU_XOR;
|
alu_func_r = `ALU_XOR;
|
alu_input_a_r = reg_ra_r;
|
alu_input_a_r = reg_ra_r;
|
alu_input_b_r = int32_r;
|
alu_input_b_r = int32_r;
|
write_rd_r = 1'b1;
|
write_rd_r = 1'b1;
|
end
|
end
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Comparisons
|
// Comparisons
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
always @ *
|
always @ *
|
begin
|
begin
|
case (1'b1)
|
case (1'b1)
|
inst_sfges_w: // l.sfges
|
inst_sfges_w: // l.sfges
|
compare_result_r = compare_gts_w | compare_equal_w;
|
compare_result_r = compare_gts_w | compare_equal_w;
|
|
|
inst_sfgeu_w: // l.sfgeu
|
inst_sfgeu_w: // l.sfgeu
|
compare_result_r = compare_gt_w | compare_equal_w;
|
compare_result_r = compare_gt_w | compare_equal_w;
|
|
|
inst_sfgts_w: // l.sfgts
|
inst_sfgts_w: // l.sfgts
|
compare_result_r = compare_gts_w;
|
compare_result_r = compare_gts_w;
|
|
|
inst_sfgtu_w: // l.sfgtu
|
inst_sfgtu_w: // l.sfgtu
|
compare_result_r = compare_gt_w;
|
compare_result_r = compare_gt_w;
|
|
|
inst_sfles_w: // l.sfles
|
inst_sfles_w: // l.sfles
|
compare_result_r = compare_lts_w | compare_equal_w;
|
compare_result_r = compare_lts_w | compare_equal_w;
|
|
|
inst_sfleu_w: // l.sfleu
|
inst_sfleu_w: // l.sfleu
|
compare_result_r = compare_lt_w | compare_equal_w;
|
compare_result_r = compare_lt_w | compare_equal_w;
|
|
|
inst_sflts_w: // l.sflts
|
inst_sflts_w: // l.sflts
|
compare_result_r = compare_lts_w;
|
compare_result_r = compare_lts_w;
|
|
|
inst_sfltu_w: // l.sfltu
|
inst_sfltu_w: // l.sfltu
|
compare_result_r = compare_lt_w;
|
compare_result_r = compare_lt_w;
|
|
|
inst_sfne_w: // l.sfne
|
inst_sfne_w: // l.sfne
|
compare_result_r = ~compare_equal_w;
|
compare_result_r = ~compare_equal_w;
|
|
|
default: // l.sfeq
|
default: // l.sfeq
|
compare_result_r = compare_equal_w;
|
compare_result_r = compare_equal_w;
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Branches
|
// Branches
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg branch_r;
|
reg branch_r;
|
reg branch_link_r;
|
reg branch_link_r;
|
reg [31:0] branch_target_r;
|
reg [31:0] branch_target_r;
|
reg branch_except_r;
|
reg branch_except_r;
|
|
|
always @ *
|
always @ *
|
begin
|
begin
|
|
|
branch_r = 1'b0;
|
branch_r = 1'b0;
|
branch_link_r = 1'b0;
|
branch_link_r = 1'b0;
|
branch_except_r = 1'b0;
|
branch_except_r = 1'b0;
|
|
|
// Default branch target is relative to current PC
|
// Default branch target is relative to current PC
|
branch_target_r = (pc_q + {target_int26_r[29:0],2'b00});
|
branch_target_r = (pc_q + {target_int26_r[29:0],2'b00});
|
|
|
case (1'b1)
|
case (1'b1)
|
inst_bf_w: // l.bf
|
inst_bf_w: // l.bf
|
branch_r = sr_q[`OR32_SR_F];
|
branch_r = sr_q[`SR_F];
|
|
|
inst_bnf_w: // l.bnf
|
inst_bnf_w: // l.bnf
|
branch_r = ~sr_q[`OR32_SR_F];
|
branch_r = ~sr_q[`SR_F];
|
|
|
inst_j_w: // l.j
|
inst_j_w: // l.j
|
branch_r = 1'b1;
|
branch_r = 1'b1;
|
|
|
inst_jal_w: // l.jal
|
inst_jal_w: // l.jal
|
begin
|
begin
|
// Write to REG_9_LR
|
// Write to REG_9_LR
|
branch_link_r = 1'b1;
|
branch_link_r = 1'b1;
|
branch_r = 1'b1;
|
branch_r = 1'b1;
|
end
|
end
|
|
|
inst_jalr_w: // l.jalr
|
inst_jalr_w: // l.jalr
|
begin
|
begin
|
// Write to REG_9_LR
|
// Write to REG_9_LR
|
branch_link_r = 1'b1;
|
branch_link_r = 1'b1;
|
branch_r = 1'b1;
|
branch_r = 1'b1;
|
branch_target_r = reg_rb_r;
|
branch_target_r = reg_rb_r;
|
end
|
end
|
|
|
inst_jr_w: // l.jr
|
inst_jr_w: // l.jr
|
begin
|
begin
|
branch_r = 1'b1;
|
branch_r = 1'b1;
|
branch_target_r = reg_rb_r;
|
branch_target_r = reg_rb_r;
|
end
|
end
|
|
|
inst_rfe_w: // l.rfe
|
inst_rfe_w: // l.rfe
|
begin
|
begin
|
branch_r = 1'b1;
|
branch_r = 1'b1;
|
branch_target_r = epc_q;
|
branch_target_r = epc_q;
|
end
|
end
|
|
|
inst_sys_w: // l.sys
|
inst_sys_w: // l.sys
|
begin
|
begin
|
branch_r = 1'b1;
|
branch_r = 1'b1;
|
branch_except_r = 1'b1;
|
branch_except_r = 1'b1;
|
branch_target_r = ISR_VECTOR + `VECTOR_SYSCALL;
|
branch_target_r = ISR_VECTOR + `VECTOR_SYSCALL;
|
end
|
end
|
|
|
inst_trap_w: // l.trap
|
inst_trap_w: // l.trap
|
begin
|
begin
|
branch_r = 1'b1;
|
branch_r = 1'b1;
|
branch_except_r = 1'b1;
|
branch_except_r = 1'b1;
|
branch_target_r = ISR_VECTOR + `VECTOR_TRAP;
|
branch_target_r = ISR_VECTOR + `VECTOR_TRAP;
|
end
|
end
|
|
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Invalid instruction
|
// Invalid instruction
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg invalid_inst_r;
|
reg invalid_inst_r;
|
|
|
always @ *
|
always @ *
|
begin
|
begin
|
case (1'b1)
|
case (1'b1)
|
inst_add_w,
|
inst_add_w,
|
inst_addc_w,
|
inst_addc_w,
|
inst_and_w,
|
inst_and_w,
|
inst_or_w,
|
inst_or_w,
|
inst_sll_w,
|
inst_sll_w,
|
inst_sw_ra,
|
inst_sw_ra,
|
inst_srl_w,
|
inst_srl_w,
|
inst_sub_w,
|
inst_sub_w,
|
inst_xor_w,
|
inst_xor_w,
|
inst_addi_w,
|
inst_addi_w,
|
inst_andi_w,
|
inst_andi_w,
|
inst_bf_w,
|
inst_bf_w,
|
inst_bnf_w,
|
inst_bnf_w,
|
inst_j_w,
|
inst_j_w,
|
inst_jal_w,
|
inst_jal_w,
|
inst_jalr_w,
|
inst_jalr_w,
|
inst_jr_w,
|
inst_jr_w,
|
inst_lbs_w,
|
inst_lbs_w,
|
inst_lhs_w,
|
inst_lhs_w,
|
inst_lws_w,
|
inst_lws_w,
|
inst_lbz_w,
|
inst_lbz_w,
|
inst_lhz_w,
|
inst_lhz_w,
|
inst_lwz_w,
|
inst_lwz_w,
|
inst_mfspr_w,
|
inst_mfspr_w,
|
inst_mtspr_w,
|
inst_mtspr_w,
|
inst_movhi_w,
|
inst_movhi_w,
|
inst_nop_w,
|
inst_nop_w,
|
inst_ori_w,
|
inst_ori_w,
|
inst_rfe_w,
|
inst_rfe_w,
|
inst_sb_w,
|
inst_sb_w,
|
inst_sh_w,
|
inst_sh_w,
|
inst_sw_w,
|
inst_sw_w,
|
inst_xori_w,
|
inst_xori_w,
|
inst_slli_w,
|
inst_slli_w,
|
inst_srai_w,
|
inst_srai_w,
|
inst_srli_w,
|
inst_srli_w,
|
inst_sfeq_w,
|
inst_sfeq_w,
|
inst_sfges_w,
|
inst_sfges_w,
|
inst_sfgeu_w,
|
inst_sfgeu_w,
|
inst_sfgts_w,
|
inst_sfgts_w,
|
inst_sfgtu_w,
|
inst_sfgtu_w,
|
inst_sfles_w,
|
inst_sfles_w,
|
inst_sfleu_w,
|
inst_sfleu_w,
|
inst_sflts_w,
|
inst_sflts_w,
|
inst_sfltu_w,
|
inst_sfltu_w,
|
inst_sfne_w,
|
inst_sfne_w,
|
inst_sys_w,
|
inst_sys_w,
|
inst_trap_w:
|
inst_trap_w:
|
invalid_inst_r = 1'b0;
|
invalid_inst_r = 1'b0;
|
default:
|
default:
|
invalid_inst_r = 1'b1;
|
invalid_inst_r = 1'b1;
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Execute: ALU control
|
// Execute: ALU control
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
always @ (posedge clk_i or posedge rst_i)
|
always @ (posedge clk_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i == 1'b1)
|
if (rst_i == 1'b1)
|
begin
|
begin
|
ex_alu_func_q <= `ALU_NONE;
|
ex_alu_func_q <= `ALU_NONE;
|
ex_alu_a_q <= 32'h00000000;
|
ex_alu_a_q <= 32'h00000000;
|
ex_alu_b_q <= 32'h00000000;
|
ex_alu_b_q <= 32'h00000000;
|
ex_rd_q <= 5'b00000;
|
ex_rd_q <= 5'b00000;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
// Update ALU input flops
|
// Update ALU input flops
|
ex_alu_func_q <= alu_func_r;
|
ex_alu_func_q <= alu_func_r;
|
ex_alu_a_q <= alu_input_a_r;
|
ex_alu_a_q <= alu_input_a_r;
|
ex_alu_b_q <= alu_input_b_r;
|
ex_alu_b_q <= alu_input_b_r;
|
|
|
// Branch and link (Rd = LR/R9)
|
// Branch and link (Rd = LR/R9)
|
if (branch_link_r)
|
if (branch_link_r)
|
ex_rd_q <= 5'd9;
|
ex_rd_q <= 5'd9;
|
// Instruction with register writeback
|
// Instruction with register writeback
|
else if (write_rd_r)
|
else if (write_rd_r)
|
ex_rd_q <= rd_w;
|
ex_rd_q <= rd_w;
|
else
|
else
|
ex_rd_q <= 5'b0;
|
ex_rd_q <= 5'b0;
|
end
|
end
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Execute: Branch / exceptions
|
// Execute: Branch / exceptions
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
always @ (posedge clk_i or posedge rst_i)
|
always @ (posedge clk_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i == 1'b1)
|
if (rst_i == 1'b1)
|
begin
|
begin
|
pc_q <= BOOT_VECTOR + `VECTOR_RESET;
|
pc_q <= BOOT_VECTOR + `VECTOR_RESET;
|
|
|
// Status registers
|
// Status registers
|
epc_q <= 32'h00000000;
|
epc_q <= 32'h00000000;
|
sr_q <= 32'h00000000;
|
sr_q <= 32'h00000000;
|
esr_q <= 32'h00000000;
|
esr_q <= 32'h00000000;
|
|
|
fault_o <= 1'b0;
|
fault_o <= 1'b0;
|
|
|
nmi_q <= 1'b0;
|
nmi_q <= 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
// Record NMI in-case it can't be processed this cycle
|
// Record NMI in-case it can't be processed this cycle
|
if (nmi_i)
|
if (nmi_i)
|
nmi_q <= 1'b1;
|
nmi_q <= 1'b1;
|
|
|
// Core disabled?
|
// Core disabled?
|
if (~enable_i)
|
if (~enable_i)
|
begin
|
begin
|
// Reset
|
// Reset
|
pc_q <= BOOT_VECTOR + `VECTOR_RESET;
|
pc_q <= BOOT_VECTOR + `VECTOR_RESET;
|
|
|
// Status registers
|
// Status registers
|
epc_q <= 32'h00000000;
|
epc_q <= 32'h00000000;
|
sr_q <= 32'h00000000;
|
sr_q <= 32'h00000000;
|
esr_q <= 32'h00000000;
|
esr_q <= 32'h00000000;
|
|
|
fault_o <= 1'b0;
|
fault_o <= 1'b0;
|
|
|
nmi_q <= 1'b0;
|
nmi_q <= 1'b0;
|
end
|
end
|
// Write-back?
|
// Write-back?
|
else if (w_write_en)
|
else if (w_write_en)
|
begin
|
begin
|
// Update SR
|
// Update SR
|
sr_q <= next_sr_r;
|
sr_q <= next_sr_r;
|
|
|
// Exception: Instruction opcode not valid / supported, invalid PC
|
// Exception: Instruction opcode not valid / supported, invalid PC
|
if (invalid_inst_r || (pc_q[1:0] != 2'b00))
|
if (invalid_inst_r || (pc_q[1:0] != 2'b00))
|
begin
|
begin
|
// Save PC of next instruction
|
// Save PC of next instruction
|
epc_q <= next_pc_r;
|
epc_q <= next_pc_r;
|
esr_q <= next_sr_r;
|
esr_q <= next_sr_r;
|
|
|
// Disable further interrupts
|
// Disable further interrupts
|
sr_q <= 32'b0;
|
sr_q <= 32'b0;
|
|
|
// Set PC to exception vector
|
// Set PC to exception vector
|
if (invalid_inst_r)
|
if (invalid_inst_r)
|
pc_q <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
|
pc_q <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
|
else
|
else
|
pc_q <= ISR_VECTOR + `VECTOR_BUS_ERROR;
|
pc_q <= ISR_VECTOR + `VECTOR_BUS_ERROR;
|
|
|
fault_o <= 1'b1;
|
fault_o <= 1'b1;
|
end
|
end
|
// Exception: Syscall / Break
|
// Exception: Syscall / Break
|
else if (branch_except_r)
|
else if (branch_except_r)
|
begin
|
begin
|
// Save PC of next instruction
|
// Save PC of next instruction
|
epc_q <= next_pc_r;
|
epc_q <= next_pc_r;
|
esr_q <= next_sr_r;
|
esr_q <= next_sr_r;
|
|
|
// Disable further interrupts
|
// Disable further interrupts
|
sr_q <= 32'b0;
|
sr_q <= 32'b0;
|
|
|
// Set PC to exception vector
|
// Set PC to exception vector
|
pc_q <= branch_target_r;
|
pc_q <= branch_target_r;
|
|
|
`ifdef CONF_CORE_DEBUG
|
`ifdef CONF_CORE_DEBUG
|
$display(" Exception 0x%08x", branch_target_r);
|
$display(" Exception 0x%08x", branch_target_r);
|
`endif
|
`endif
|
end
|
end
|
// Non-maskable interrupt
|
// Non-maskable interrupt
|
else if (nmi_i | nmi_q)
|
else if (nmi_i | nmi_q)
|
begin
|
begin
|
nmi_q <= 1'b0;
|
nmi_q <= 1'b0;
|
|
|
// Save PC of next instruction
|
// Save PC of next instruction
|
if (branch_r)
|
if (branch_r)
|
epc_q <= branch_target_r;
|
epc_q <= branch_target_r;
|
// Next expected PC (current PC + 4)
|
// Next expected PC (current PC + 4)
|
else
|
else
|
epc_q <= next_pc_r;
|
epc_q <= next_pc_r;
|
|
|
esr_q <= next_sr_r;
|
esr_q <= next_sr_r;
|
|
|
// Disable further interrupts
|
// Disable further interrupts
|
sr_q <= 32'b0;
|
sr_q <= 32'b0;
|
|
|
// Set PC to exception vector
|
// Set PC to exception vector
|
pc_q <= ISR_VECTOR + `VECTOR_NMI;
|
pc_q <= ISR_VECTOR + `VECTOR_NMI;
|
|
|
`ifdef CONF_CORE_DEBUG
|
`ifdef CONF_CORE_DEBUG
|
$display(" NMI 0x%08x", ISR_VECTOR + `VECTOR_NMI);
|
$display(" NMI 0x%08x", ISR_VECTOR + `VECTOR_NMI);
|
`endif
|
`endif
|
end
|
end
|
// External interrupt
|
// External interrupt
|
else if (intr_i && next_sr_r[`OR32_SR_IEE])
|
else if (intr_i && next_sr_r[`SR_IEE])
|
begin
|
begin
|
// Save PC of next instruction & SR
|
// Save PC of next instruction & SR
|
if (branch_r)
|
if (branch_r)
|
epc_q <= branch_target_r;
|
epc_q <= branch_target_r;
|
// Next expected PC (current PC + 4)
|
// Next expected PC (current PC + 4)
|
else
|
else
|
epc_q <= next_pc_r;
|
epc_q <= next_pc_r;
|
|
|
esr_q <= next_sr_r;
|
esr_q <= next_sr_r;
|
|
|
// Disable further interrupts
|
// Disable further interrupts
|
sr_q <= 32'b0;
|
sr_q <= 32'b0;
|
|
|
// Set PC to external interrupt vector
|
// Set PC to external interrupt vector
|
pc_q <= ISR_VECTOR + `VECTOR_EXTINT;
|
pc_q <= ISR_VECTOR + `VECTOR_EXTINT;
|
|
|
`ifdef CONF_CORE_DEBUG
|
`ifdef CONF_CORE_DEBUG
|
$display(" External Interrupt 0x%08x", ISR_VECTOR + `VECTOR_EXTINT);
|
$display(" External Interrupt 0x%08x", ISR_VECTOR + `VECTOR_EXTINT);
|
`endif
|
`endif
|
end
|
end
|
// Branch (l.bf, l.bnf, l.j, l.jal, l.jr, l.jalr, l.rfe)
|
// Branch (l.bf, l.bnf, l.j, l.jal, l.jr, l.jalr, l.rfe)
|
else if (branch_r)
|
else if (branch_r)
|
begin
|
begin
|
// Perform branch
|
// Perform branch
|
pc_q <= branch_target_r;
|
pc_q <= branch_target_r;
|
|
|
`ifdef CONF_CORE_DEBUG
|
`ifdef CONF_CORE_DEBUG
|
$display(" Branch to 0x%08x", branch_target_r);
|
$display(" Branch to 0x%08x", branch_target_r);
|
`endif
|
`endif
|
end
|
end
|
// Non branch
|
// Non branch
|
else
|
else
|
begin
|
begin
|
// Update EPC / ESR which may have been updated
|
// Update EPC / ESR which may have been updated
|
// by an MTSPR write
|
// by an MTSPR write
|
pc_q <= next_pc_r;
|
pc_q <= next_pc_r;
|
epc_q <= next_epc_r;
|
epc_q <= next_epc_r;
|
esr_q <= next_esr_r;
|
esr_q <= next_esr_r;
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
// Load result
|
// Load result
|
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
always @ *
|
always @ *
|
begin
|
begin
|
load_result_r = 32'h00000000;
|
load_result_r = 32'h00000000;
|
|
|
case (1'b1)
|
case (1'b1)
|
|
|
inst_lbs_w, // l.lbs
|
inst_lbs_w, // l.lbs
|
inst_lbz_w: // l.lbz
|
inst_lbz_w: // l.lbz
|
begin
|
begin
|
case (mem_offset_q)
|
case (mem_offset_q)
|
2'b00 : load_result_r[7:0] = mem_dat_i[31:24];
|
2'b00 : load_result_r[7:0] = mem_dat_i[31:24];
|
2'b01 : load_result_r[7:0] = mem_dat_i[23:16];
|
2'b01 : load_result_r[7:0] = mem_dat_i[23:16];
|
2'b10 : load_result_r[7:0] = mem_dat_i[15:8];
|
2'b10 : load_result_r[7:0] = mem_dat_i[15:8];
|
2'b11 : load_result_r[7:0] = mem_dat_i[7:0];
|
2'b11 : load_result_r[7:0] = mem_dat_i[7:0];
|
default : ;
|
default : ;
|
endcase
|
endcase
|
|
|
// Sign extend LB
|
// Sign extend LB
|
if (inst_lbs_w && load_result_r[7])
|
if (inst_lbs_w && load_result_r[7])
|
load_result_r[31:8] = 24'hFFFFFF;
|
load_result_r[31:8] = 24'hFFFFFF;
|
end
|
end
|
|
|
inst_lhs_w, // l.lhs
|
inst_lhs_w, // l.lhs
|
inst_lhz_w: // l.lhz
|
inst_lhz_w: // l.lhz
|
begin
|
begin
|
case (mem_offset_q)
|
case (mem_offset_q)
|
2'b00 : load_result_r[15:0] = mem_dat_i[31:16];
|
2'b00 : load_result_r[15:0] = mem_dat_i[31:16];
|
2'b10 : load_result_r[15:0] = mem_dat_i[15:0];
|
2'b10 : load_result_r[15:0] = mem_dat_i[15:0];
|
default : ;
|
default : ;
|
endcase
|
endcase
|
|
|
// Sign extend LH
|
// Sign extend LH
|
if (inst_lhs_w && load_result_r[15])
|
if (inst_lhs_w && load_result_r[15])
|
load_result_r[31:16] = 16'hFFFF;
|
load_result_r[31:16] = 16'hFFFF;
|
end
|
end
|
|
|
// l.lwz l.lws
|
// l.lwz l.lws
|
default :
|
default :
|
load_result_r = mem_dat_i;
|
load_result_r = mem_dat_i;
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Execute: Misc operations
|
// Execute: Misc operations
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
always @ (posedge clk_i or posedge rst_i)
|
always @ (posedge clk_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i == 1'b1)
|
if (rst_i == 1'b1)
|
begin
|
begin
|
break_o <= 1'b0;
|
break_o <= 1'b0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
break_o <= 1'b0;
|
break_o <= 1'b0;
|
|
|
case (1'b1)
|
case (1'b1)
|
inst_trap_w: // l.trap
|
inst_trap_w: // l.trap
|
break_o <= 1'b1;
|
break_o <= 1'b1;
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Execute: NOP (simulation) operations
|
// Execute: NOP (simulation) operations
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
`ifdef SIMULATION
|
`ifdef SIMULATION
|
always @ (posedge clk_i or posedge rst_i)
|
always @ (posedge clk_i or posedge rst_i)
|
begin
|
begin
|
if (rst_i == 1'b1)
|
if (rst_i == 1'b1)
|
begin
|
begin
|
`ifdef SIM_EXT_PUTC
|
`ifdef SIM_EXT_PUTC
|
putc_q <= 8'b0;
|
putc_q <= 8'b0;
|
`endif
|
`endif
|
end
|
end
|
else
|
else
|
begin
|
begin
|
`ifdef SIM_EXT_PUTC
|
`ifdef SIM_EXT_PUTC
|
putc_q <= 8'b0;
|
putc_q <= 8'b0;
|
`endif
|
`endif
|
if (inst_nop_w && state_q == STATE_EXEC)
|
if (inst_nop_w && state_q == STATE_EXEC)
|
begin
|
begin
|
case (uint16_r)
|
case (uint16_r)
|
// NOP_PUTC
|
// NOP_PUTC
|
16'h0004:
|
16'h0004:
|
begin
|
begin
|
`ifdef SIM_EXT_PUTC
|
`ifdef SIM_EXT_PUTC
|
putc_q <= reg_ra_r[7:0];
|
putc_q <= reg_ra_r[7:0];
|
`else
|
`else
|
$write("%c", reg_ra_r[7:0]);
|
$write("%c", reg_ra_r[7:0]);
|
`endif
|
`endif
|
end
|
end
|
// NOP
|
// NOP
|
16'h0000: ;
|
16'h0000: ;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
end
|
end
|
`endif
|
`endif
|
|
|
`include "altor32_funcs.v"
|
`include "altor32_funcs.v"
|
|
|
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
// Hooks for debug
|
// Hooks for debug
|
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
`ifdef verilator
|
`ifdef verilator
|
function [31:0] get_opcode_ex;
|
function [31:0] get_opcode_ex;
|
// verilator public
|
// verilator public
|
get_opcode_ex = (state_q == STATE_EXEC) ? opcode_q : `OPCODE_INST_BUBBLE;
|
get_opcode_ex = (state_q == STATE_EXEC) ? opcode_q : `OPCODE_INST_BUBBLE;
|
endfunction
|
endfunction
|
function [31:0] get_pc_ex;
|
function [31:0] get_pc_ex;
|
// verilator public
|
// verilator public
|
get_pc_ex = pc_q;
|
get_pc_ex = pc_q;
|
endfunction
|
endfunction
|
function [7:0] get_putc;
|
function [7:0] get_putc;
|
// verilator public
|
// verilator public
|
`ifdef SIM_EXT_PUTC
|
`ifdef SIM_EXT_PUTC
|
get_putc = putc_q;
|
get_putc = putc_q;
|
`else
|
`else
|
get_putc = 8'b0;
|
get_putc = 8'b0;
|
`endif
|
`endif
|
endfunction
|
endfunction
|
function [0:0] get_reg_valid;
|
function [0:0] get_reg_valid;
|
// verilator public
|
// verilator public
|
get_reg_valid = (state_q == STATE_EXEC) ? 1'b1 : 1'b0;
|
get_reg_valid = (state_q == STATE_EXEC) ? 1'b1 : 1'b0;
|
endfunction
|
endfunction
|
function [4:0] get_reg_ra;
|
function [4:0] get_reg_ra;
|
// verilator public
|
// verilator public
|
get_reg_ra = ra_w;
|
get_reg_ra = ra_w;
|
endfunction
|
endfunction
|
function [31:0] get_reg_ra_value;
|
function [31:0] get_reg_ra_value;
|
// verilator public
|
// verilator public
|
get_reg_ra_value = reg_ra_w;
|
get_reg_ra_value = reg_ra_w;
|
endfunction
|
endfunction
|
function [4:0] get_reg_rb;
|
function [4:0] get_reg_rb;
|
// verilator public
|
// verilator public
|
get_reg_rb = rb_w;
|
get_reg_rb = rb_w;
|
endfunction
|
endfunction
|
function [31:0] get_reg_rb_value;
|
function [31:0] get_reg_rb_value;
|
// verilator public
|
// verilator public
|
get_reg_rb_value = reg_rb_w;
|
get_reg_rb_value = reg_rb_w;
|
endfunction
|
endfunction
|
`endif
|
`endif
|
|
|
endmodule
|
endmodule
|
|
|