Line 1... |
Line 1... |
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// AltOR32
|
// AltOR32
|
// Alternative Lightweight OpenRisc
|
// Alternative Lightweight OpenRisc
|
// V2.0
|
// V2.1
|
// Ultra-Embedded.com
|
// Ultra-Embedded.com
|
// Copyright 2011 - 2013
|
// Copyright 2011 - 2014
|
//
|
//
|
// Email: admin@ultra-embedded.com
|
// Email: admin@ultra-embedded.com
|
//
|
//
|
// License: LGPL
|
// License: LGPL
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
Line 37... |
Line 37... |
|
|
//`define CONF_CORE_DEBUG
|
//`define CONF_CORE_DEBUG
|
//`define CONF_CORE_TRACE
|
//`define CONF_CORE_TRACE
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Includes
|
|
//-----------------------------------------------------------------
|
|
`include "altor32_defs.v"
|
|
|
|
//-----------------------------------------------------------------
|
|
// Module - Instruction Execute
|
// Module - Instruction Execute
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
module altor32_exec
|
module altor32_exec
|
(
|
(
|
// General
|
// General
|
Line 111... |
Line 106... |
input dmem_stall_i /*verilator public*/,
|
input dmem_stall_i /*verilator public*/,
|
input dmem_ack_i /*verilator public*/
|
input dmem_ack_i /*verilator public*/
|
);
|
);
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
// Includes
|
|
//-----------------------------------------------------------------
|
|
`include "altor32_defs.v"
|
|
`include "altor32_funcs.v"
|
|
|
|
//-----------------------------------------------------------------
|
// Params
|
// Params
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
parameter BOOT_VECTOR = 32'h00000000;
|
parameter BOOT_VECTOR = 32'h00000000;
|
parameter ISR_VECTOR = 32'h00000000;
|
parameter ISR_VECTOR = 32'h00000000;
|
|
|
Line 123... |
Line 124... |
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
// Branch PC
|
// Branch PC
|
reg [31:0] r_pc_branch;
|
reg [31:0] r_pc_branch;
|
reg r_pc_fetch;
|
reg r_pc_fetch;
|
reg r_stall;
|
|
|
|
// Exception saved program counter
|
// Exception saved program counter
|
reg [31:0] r_epc;
|
reg [31:0] r_epc;
|
|
|
// Supervisor register
|
// Supervisor register
|
Line 153... |
Line 153... |
wire [31:0] r_e_result;
|
wire [31:0] r_e_result;
|
|
|
// Resolved RA/RB register contents
|
// Resolved RA/RB register contents
|
wire [31:0] ra_value_resolved;
|
wire [31:0] ra_value_resolved;
|
wire [31:0] rb_value_resolved;
|
wire [31:0] rb_value_resolved;
|
|
wire operand_resolved;
|
wire resolve_failed;
|
wire resolve_failed;
|
|
|
// ALU Carry
|
// ALU Carry
|
wire alu_carry_out;
|
wire alu_carry_out;
|
wire alu_carry_update;
|
wire alu_carry_update;
|
|
wire alu_flag_update;
|
|
|
|
// ALU Comparisons
|
|
wire compare_equal_w;
|
|
wire compare_gts_w;
|
|
wire compare_gt_w;
|
|
wire compare_lts_w;
|
|
wire compare_lt_w;
|
|
|
// ALU operation selection
|
// ALU operation selection
|
reg [3:0] r_e_alu_func;
|
reg [3:0] r_e_alu_func;
|
|
|
// Load instruction details
|
// Load instruction details
|
Line 211... |
Line 220... |
// Result
|
// Result
|
.p_o(r_e_result),
|
.p_o(r_e_result),
|
|
|
// Carry
|
// Carry
|
.c_o(alu_carry_out),
|
.c_o(alu_carry_out),
|
.c_update_o(alu_carry_update)
|
.c_update_o(alu_carry_update),
|
|
|
|
// Comparisons
|
|
.equal_o(compare_equal_w),
|
|
.greater_than_signed_o(compare_gts_w),
|
|
.greater_than_o(compare_gt_w),
|
|
.less_than_signed_o(compare_lts_w),
|
|
.less_than_o(compare_lt_w),
|
|
.flag_update_o(alu_flag_update)
|
);
|
);
|
|
|
// Load result forwarding
|
// Load result forwarding
|
altor32_lfu
|
altor32_lfu
|
u_lfu
|
u_lfu
|
Line 304... |
Line 321... |
|
|
// Resolved register values
|
// Resolved register values
|
.result_ra_o(ra_value_resolved),
|
.result_ra_o(ra_value_resolved),
|
.result_rb_o(rb_value_resolved),
|
.result_rb_o(rb_value_resolved),
|
|
|
|
// Operands required forwarding
|
|
.resolved_o(operand_resolved),
|
|
|
// Stall due to failed resolve
|
// Stall due to failed resolve
|
.stall_o(resolve_failed)
|
.stall_o(resolve_failed)
|
);
|
);
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
Line 333... |
Line 353... |
// Instruction
|
// Instruction
|
inst_r = {2'b00,opcode_i[31:26]};
|
inst_r = {2'b00,opcode_i[31:26]};
|
|
|
// Sub instructions
|
// Sub instructions
|
alu_op_r = {opcode_i[9:6],opcode_i[3:0]};
|
alu_op_r = {opcode_i[9:6],opcode_i[3:0]};
|
sfxx_op_r = {5'b00,opcode_i[31:21]};
|
sfxx_op_r = {5'b00,opcode_i[31:21]} & `INST_OR32_SFMASK;
|
shift_op_r = opcode_i[7:6];
|
shift_op_r = opcode_i[7:6];
|
|
|
// Branch target
|
// Branch target
|
target_int26_r = sign_extend_imm26(opcode_i[25:0]);
|
target_int26_r = sign_extend_imm26(opcode_i[25:0]);
|
|
|
Line 358... |
Line 378... |
|
|
// Shift ammount (from immediate)
|
// Shift ammount (from immediate)
|
shift_imm_r = {26'b00,opcode_i[5:0]};
|
shift_imm_r = {26'b00,opcode_i[5:0]};
|
|
|
// MTSPR/MFSPR operand
|
// MTSPR/MFSPR operand
|
mxspr_uint16_r = (ra_value_resolved[15:0] | {5'b00000,opcode_i[10:0]});
|
// NOTE: Use unresolved register value and stall pipeline if required.
|
|
// This is to improve timing.
|
|
mxspr_uint16_r = (reg_ra_value_i[15:0] | {5'b00000,opcode_i[10:0]});
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Instruction Decode
|
// Instruction Decode
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
Line 373... |
Line 395... |
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_sra_w = (inst_r == `INST_OR32_ALU) & (alu_op_r == `INST_OR32_SRA); // l.sra
|
wire inst_sra_w = (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_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
|
Line 408... |
Line 432... |
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_r == `INST_OR32_SFXX) & (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_r == `INST_OR32_SFXX) & (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_r == `INST_OR32_SFXX) & (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_r == `INST_OR32_SFXX) & (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_r == `INST_OR32_SFXX) & (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_r == `INST_OR32_SFXX) & (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_r == `INST_OR32_SFXX) & (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_r == `INST_OR32_SFXX) & (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_r == `INST_OR32_SFXX) & (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_r == `INST_OR32_SFXX) & (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_sfeqi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFEQI); // l.sfeqi
|
|
wire inst_sfgesi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGESI); // l.sfgesi
|
|
wire inst_sfgeui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGEUI); // l.sfgeui
|
|
wire inst_sfgtsi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTSI); // l.sfgtsi
|
|
wire inst_sfgtui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFGTUI); // l.sfgtui
|
|
wire inst_sflesi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLESI); // l.sflesi
|
|
|
|
wire inst_sfleui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLEUI); // l.sfleui
|
|
wire inst_sfltsi_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTSI); // l.sfltsi
|
|
wire inst_sfltui_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFLTUI); // l.sfltui
|
|
wire inst_sfnei_w = (inst_r == `INST_OR32_SFXXI) & (sfxx_op_r == `INST_OR32_SFNEI); // l.sfnei
|
|
|
|
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_SYS); // l.sys
|
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_SYS); // l.sys
|
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_TRAP); // l.trap
|
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (opcode_i[31:24] == `INST_OR32_TRAP); // l.trap
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
Line 450... |
Line 462... |
|
|
// No opcode ready or branch delay slot
|
// No opcode ready or branch delay slot
|
if (~opcode_valid_i | r_pc_fetch)
|
if (~opcode_valid_i | r_pc_fetch)
|
execute_inst_r = 1'b0;
|
execute_inst_r = 1'b0;
|
// Valid instruction, but load result / operand not ready
|
// Valid instruction, but load result / operand not ready
|
else if (resolve_failed | load_stall)
|
else if (resolve_failed | load_stall |
|
|
(operand_resolved & (inst_mfspr_w | inst_mtspr_w)))
|
stall_inst_r = 1'b1;
|
stall_inst_r = 1'b1;
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Next PC
|
// Next PC
|
Line 474... |
Line 487... |
reg compare_result_r;
|
reg compare_result_r;
|
always @ *
|
always @ *
|
begin
|
begin
|
next_sr_r = r_sr;
|
next_sr_r = r_sr;
|
|
|
|
// Update SR.F
|
|
if (alu_flag_update)
|
|
next_sr_r[`OR32_SR_F] = compare_result_r;
|
|
|
// Latch carry if updated
|
// Latch carry if updated
|
if (alu_carry_update)
|
if (alu_carry_update)
|
next_sr_r[`OR32_SR_CY] = alu_carry_out;
|
next_sr_r[`OR32_SR_CY] = alu_carry_out;
|
|
|
// If valid instruction, check if SR needs updating
|
// If valid instruction, check if SR needs updating
|
Line 500... |
Line 517... |
;
|
;
|
endcase
|
endcase
|
end
|
end
|
inst_rfe_w:
|
inst_rfe_w:
|
next_sr_r = r_esr;
|
next_sr_r = r_esr;
|
inst_sfxx_w,
|
|
inst_sfxxi_w:
|
|
next_sr_r[`OR32_SR_F] = compare_result_r;
|
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
Line 629... |
Line 643... |
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_mulu_w: // l.mulu
|
|
begin
|
|
write_rd_r = 1'b1;
|
|
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;
|
Line 732... |
Line 752... |
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;
|
|
|
|
// l.sf*i
|
|
inst_sfxxi_w:
|
|
begin
|
|
alu_func_r = `ALU_COMPARE;
|
|
alu_input_a_r = reg_ra_r;
|
|
alu_input_b_r = int32_r;
|
|
end
|
|
|
|
// l.sf*
|
|
inst_sfxx_w:
|
|
begin
|
|
alu_func_r = `ALU_COMPARE;
|
|
alu_input_a_r = reg_ra_r;
|
|
alu_input_b_r = reg_rb_r;
|
|
end
|
|
|
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;
|
Line 745... |
Line 781... |
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Comparisons
|
// Comparisons (from ALU outputs)
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
reg [31:0] compare_a_r;
|
reg inst_sfges_r;
|
reg [31:0] compare_b_r;
|
reg inst_sfgeu_r;
|
|
reg inst_sfgts_r;
|
|
reg inst_sfgtu_r;
|
|
reg inst_sfles_r;
|
|
reg inst_sfleu_r;
|
|
reg inst_sflts_r;
|
|
reg inst_sfltu_r;
|
|
reg inst_sfne_r;
|
|
reg inst_sfges_q;
|
|
reg inst_sfgeu_q;
|
|
reg inst_sfgts_q;
|
|
reg inst_sfgtu_q;
|
|
reg inst_sfles_q;
|
|
reg inst_sfleu_q;
|
|
reg inst_sflts_q;
|
|
reg inst_sfltu_q;
|
|
reg inst_sfne_q;
|
|
|
always @ *
|
always @ *
|
begin
|
begin
|
compare_a_r = reg_ra_r;
|
inst_sfges_r = 1'b0;
|
compare_b_r = reg_rb_r;
|
inst_sfgeu_r = 1'b0;
|
|
inst_sfgts_r = 1'b0;
|
|
inst_sfgtu_r = 1'b0;
|
|
inst_sfles_r = 1'b0;
|
|
inst_sfleu_r = 1'b0;
|
|
inst_sflts_r = 1'b0;
|
|
inst_sfltu_r = 1'b0;
|
|
inst_sfne_r = 1'b0;
|
|
|
|
// Valid instruction
|
|
if (execute_inst_r && ~stall_inst_r)
|
|
begin
|
|
|
case (1'b1)
|
case (1'b1)
|
inst_sfeqi_w, // l.sfeqi
|
inst_sfges_w: // l.sfges
|
inst_sfgesi_w, // l.sfgesi
|
inst_sfges_r = 1'b1;
|
inst_sfgeui_w, // l.sfgeui
|
|
inst_sfgtsi_w, // l.sfgtsi
|
inst_sfgeu_w: // l.sfgeu
|
inst_sfgtui_w, // l.sfgtui
|
inst_sfgeu_r = 1'b1;
|
inst_sflesi_w, // l.sflesi
|
|
inst_sfleui_w, // l.sfleui
|
inst_sfgts_w: // l.sfgts
|
inst_sfltsi_w, // l.sfltsi
|
inst_sfgts_r = 1'b1;
|
inst_sfltui_w, // l.sfltui
|
|
inst_sfnei_w: // l.sfnei
|
inst_sfgtu_w: // l.sfgtu
|
compare_b_r = int32_r;
|
inst_sfgtu_r = 1'b1;
|
|
|
|
inst_sfles_w: // l.sfles
|
|
inst_sfles_r = 1'b1;
|
|
|
|
inst_sfleu_w: // l.sfleu
|
|
inst_sfleu_r = 1'b1;
|
|
|
|
inst_sflts_w: // l.sflts
|
|
inst_sflts_r = 1'b1;
|
|
|
|
inst_sfltu_w: // l.sfltu
|
|
inst_sfltu_r = 1'b1;
|
|
|
|
inst_sfne_w: // l.sfne
|
|
inst_sfne_r = 1'b1;
|
|
|
default:
|
default:
|
;
|
;
|
endcase
|
endcase
|
end
|
end
|
|
end
|
|
|
reg compare_equal_r;
|
always @ (posedge clk_i or posedge rst_i)
|
reg compare_gts_r;
|
|
reg compare_gt_r;
|
|
reg compare_lts_r;
|
|
reg compare_lt_r;
|
|
always @ *
|
|
begin
|
begin
|
if (compare_a_r == compare_b_r)
|
if (rst_i == 1'b1)
|
compare_equal_r = 1'b1;
|
begin
|
else
|
inst_sfges_q <= 1'b0;
|
compare_equal_r = 1'b0;
|
inst_sfgeu_q <= 1'b0;
|
|
inst_sfgts_q <= 1'b0;
|
compare_lts_r = less_than_signed(compare_a_r, compare_b_r);
|
inst_sfgtu_q <= 1'b0;
|
|
inst_sfles_q <= 1'b0;
|
if (compare_a_r < compare_b_r)
|
inst_sfleu_q <= 1'b0;
|
compare_lt_r = 1'b1;
|
inst_sflts_q <= 1'b0;
|
else
|
inst_sfltu_q <= 1'b0;
|
compare_lt_r = 1'b0;
|
inst_sfne_q <= 1'b0;
|
|
end
|
// Greater than (signed)
|
|
compare_gts_r = ~(compare_lts_r | compare_equal_r);
|
|
|
|
if (compare_a_r > compare_b_r)
|
|
compare_gt_r = 1'b1;
|
|
else
|
else
|
compare_gt_r = 1'b0;
|
begin
|
|
inst_sfges_q <= inst_sfges_r;
|
|
inst_sfgeu_q <= inst_sfgeu_r;
|
|
inst_sfgts_q <= inst_sfgts_r;
|
|
inst_sfgtu_q <= inst_sfgtu_r;
|
|
inst_sfles_q <= inst_sfles_r;
|
|
inst_sfleu_q <= inst_sfleu_r;
|
|
inst_sflts_q <= inst_sflts_r;
|
|
inst_sfltu_q <= inst_sfltu_r;
|
|
inst_sfne_q <= inst_sfne_r;
|
|
end
|
end
|
end
|
|
|
always @ *
|
always @ *
|
begin
|
begin
|
compare_result_r = 1'b0;
|
|
|
|
case (1'b1)
|
case (1'b1)
|
inst_sfeq_w, // l.sfeq
|
inst_sfges_q: // l.sfges
|
inst_sfeqi_w: // l.sfeqi
|
compare_result_r = compare_gts_w | compare_equal_w;
|
compare_result_r = compare_equal_r;
|
|
|
|
inst_sfges_w, // l.sfges
|
|
inst_sfgesi_w: // l.sfgesi
|
|
compare_result_r = compare_gts_r | compare_equal_r;
|
|
|
|
inst_sfgeu_w, // l.sfgeu
|
|
inst_sfgeui_w: // l.sfgeui
|
|
compare_result_r = compare_gt_r | compare_equal_r;
|
|
|
|
inst_sfgts_w, // l.sfgts
|
inst_sfgeu_q: // l.sfgeu
|
inst_sfgtsi_w: // l.sfgtsi
|
compare_result_r = compare_gt_w | compare_equal_w;
|
compare_result_r = compare_gts_r;
|
|
|
|
inst_sfgtu_w, // l.sfgtu
|
inst_sfgts_q: // l.sfgts
|
inst_sfgtui_w: // l.sfgtui
|
compare_result_r = compare_gts_w;
|
compare_result_r = compare_gt_r;
|
|
|
|
inst_sfles_w, // l.sfles
|
inst_sfgtu_q: // l.sfgtu
|
inst_sflesi_w: // l.sflesi
|
compare_result_r = compare_gt_w;
|
compare_result_r = compare_lts_r | compare_equal_r;
|
|
|
|
inst_sfleu_w, // l.sfleu
|
inst_sfles_q: // l.sfles
|
|
compare_result_r = compare_lts_w | compare_equal_w;
|
|
|
inst_sfleui_w: // l.sfleui
|
inst_sfleu_q: // l.sfleu
|
compare_result_r = compare_lt_r | compare_equal_r;
|
compare_result_r = compare_lt_w | compare_equal_w;
|
|
|
inst_sflts_w, // l.sflts
|
inst_sflts_q: // l.sflts
|
|
compare_result_r = compare_lts_w;
|
|
|
inst_sfltsi_w: // l.sfltsi
|
inst_sfltu_q: // l.sfltu
|
compare_result_r = compare_lts_r;
|
compare_result_r = compare_lt_w;
|
|
|
inst_sfltu_w, // l.sfltu
|
inst_sfne_q: // l.sfne
|
|
compare_result_r = ~compare_equal_w;
|
|
|
inst_sfltui_w: // l.sfltui
|
default: // l.sfeq
|
compare_result_r = compare_lt_r;
|
compare_result_r = compare_equal_w;
|
|
|
inst_sfne_w, // l.sfne
|
|
|
|
inst_sfnei_w: // l.sfnei
|
|
compare_result_r = ~compare_equal_r;
|
|
default:
|
|
;
|
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Load/Store operation?
|
// Load/Store operation?
|
Line 888... |
Line 951... |
// Default branch target is relative to current PC
|
// Default branch target is relative to current PC
|
branch_target_r = (opcode_pc_i + {target_int26_r[29:0],2'b00});
|
branch_target_r = (opcode_pc_i + {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 = r_sr[`OR32_SR_F];
|
branch_r = next_sr_r[`OR32_SR_F];
|
|
|
inst_bnf_w: // l.bnf
|
inst_bnf_w: // l.bnf
|
branch_r = ~r_sr[`OR32_SR_F];
|
branch_r = ~next_sr_r[`OR32_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
|
Line 987... |
Line 1050... |
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_sfeqi_w,
|
|
inst_sfges_w,
|
inst_sfges_w,
|
inst_sfgesi_w,
|
|
inst_sfgeu_w,
|
inst_sfgeu_w,
|
inst_sfgeui_w,
|
|
inst_sfgts_w,
|
inst_sfgts_w,
|
inst_sfgtsi_w,
|
|
inst_sfgtu_w,
|
inst_sfgtu_w,
|
inst_sfgtui_w,
|
|
inst_sfles_w,
|
inst_sfles_w,
|
inst_sflesi_w,
|
|
inst_sfleu_w,
|
inst_sfleu_w,
|
inst_sfleui_w,
|
|
inst_sflts_w,
|
inst_sflts_w,
|
inst_sfltsi_w,
|
|
inst_sfltu_w,
|
inst_sfltu_w,
|
inst_sfltui_w,
|
|
inst_sfne_w,
|
inst_sfne_w,
|
inst_sfnei_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;
|
Line 1054... |
Line 1107... |
end
|
end
|
end
|
end
|
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
// Valid instruction
|
// Valid instruction
|
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
else if (~invalid_inst_r)
|
else
|
begin
|
begin
|
// Update ALU input flops
|
// Update ALU input flops
|
r_e_alu_func <= alu_func_r;
|
r_e_alu_func <= alu_func_r;
|
r_e_alu_a <= alu_input_a_r;
|
r_e_alu_a <= alu_input_a_r;
|
r_e_alu_b <= alu_input_b_r;
|
r_e_alu_b <= alu_input_b_r;
|
Line 1082... |
Line 1135... |
begin
|
begin
|
if (rst_i == 1'b1)
|
if (rst_i == 1'b1)
|
begin
|
begin
|
r_e_opcode <= 32'h00000000;
|
r_e_opcode <= 32'h00000000;
|
r_e_opcode_pc <= 32'h00000000;
|
r_e_opcode_pc <= 32'h00000000;
|
|
|
r_stall <= 1'b0;
|
|
end
|
end
|
else
|
else
|
begin
|
begin
|
r_stall <= stall_inst_r;
|
|
|
|
// Instruction not ready
|
// Instruction not ready
|
if (~execute_inst_r | stall_inst_r)
|
if (~execute_inst_r | stall_inst_r)
|
begin
|
begin
|
// Store bubble opcode
|
// Store bubble opcode
|
r_e_opcode <= `OPCODE_INST_BUBBLE;
|
r_e_opcode <= `OPCODE_INST_BUBBLE;
|
r_e_opcode_pc <= opcode_pc_i;
|
r_e_opcode_pc <= opcode_pc_i;
|
end
|
end
|
// Valid instruction
|
// Valid instruction
|
else if (~invalid_inst_r)
|
else
|
begin
|
begin
|
// Store opcode
|
// Store opcode
|
r_e_opcode <= opcode_i;
|
r_e_opcode <= opcode_i;
|
r_e_opcode_pc <= opcode_pc_i;
|
r_e_opcode_pc <= opcode_pc_i;
|
|
|
Line 1288... |
Line 1337... |
if (~dmem_stall_i)
|
if (~dmem_stall_i)
|
dmem_stb_o <= 1'b0;
|
dmem_stb_o <= 1'b0;
|
|
|
if (dmem_ack_i)
|
if (dmem_ack_i)
|
dmem_cyc_o <= 1'b0;
|
dmem_cyc_o <= 1'b0;
|
|
|
r_mem_access <= 1'b0;
|
r_mem_access <= 1'b0;
|
d_mem_load <= r_mem_access & r_mem_load;
|
d_mem_load <= r_mem_access & r_mem_load;
|
|
|
// Pending accesses
|
// Pending accesses
|
r_mem_load <= load_pending;
|
r_mem_load <= load_pending;
|
r_mem_store <= store_pending;
|
r_mem_store <= store_pending;
|
|
|
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
// Valid instruction
|
// Valid instruction
|
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
|
if (execute_inst_r & ~stall_inst_r)
|
begin
|
begin
|
// Branch and link (Rd = LR/R9)
|
// Branch and link (Rd = LR/R9)
|
if (branch_link_r)
|
if (branch_link_r)
|
begin
|
begin
|
// Load outstanding, check if result target is being
|
// Load outstanding, check if result target is being
|
Line 1461... |
Line 1511... |
dcache_flush_o <= 1'b0;
|
dcache_flush_o <= 1'b0;
|
|
|
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
// Valid instruction
|
// Valid instruction
|
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
|
if (execute_inst_r & ~stall_inst_r)
|
begin
|
begin
|
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)
|
Line 1506... |
Line 1556... |
r_putc <= 8'b0;
|
r_putc <= 8'b0;
|
`endif
|
`endif
|
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
// Valid instruction
|
// Valid instruction
|
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
if (execute_inst_r & ~stall_inst_r & ~invalid_inst_r)
|
if (execute_inst_r & ~stall_inst_r)
|
begin
|
begin
|
|
|
case (1'b1)
|
case (1'b1)
|
inst_nop_w: // l.nop
|
inst_nop_w: // l.nop
|
begin
|
begin
|
Line 1540... |
Line 1590... |
// Assignments
|
// Assignments
|
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
|
|
assign branch_pc_o = r_pc_branch;
|
assign branch_pc_o = r_pc_branch;
|
assign branch_o = r_pc_fetch;
|
assign branch_o = r_pc_fetch;
|
assign stall_o = r_stall;
|
assign stall_o = stall_inst_r;
|
|
|
assign opcode_o = r_e_opcode;
|
assign opcode_o = r_e_opcode;
|
|
|
assign reg_rd_o = r_e_rd;
|
assign reg_rd_o = r_e_rd;
|
assign reg_rd_value_o = r_e_result;
|
assign reg_rd_value_o = r_e_result;
|
|
|
assign mult_o = 1'b0;
|
assign mult_o = 1'b0;
|
assign mult_res_o = 32'b0;
|
assign mult_res_o = 32'b0;
|
|
|
`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;
|
Line 1574... |
Line 1622... |
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 = ~(resolve_failed | load_stall);
|
get_reg_valid = ~(resolve_failed | load_stall | ~opcode_valid_i);
|
endfunction
|
endfunction
|
function [4:0] get_reg_ra;
|
function [4:0] get_reg_ra;
|
// verilator public
|
// verilator public
|
get_reg_ra = reg_ra_i;
|
get_reg_ra = reg_ra_i;
|
endfunction
|
endfunction
|