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 118... |
Line 118... |
|
|
// ALU Carry
|
// ALU Carry
|
wire alu_carry_out;
|
wire alu_carry_out;
|
wire alu_carry_update;
|
wire alu_carry_update;
|
|
|
|
// ALU Comparisons
|
|
wire compare_equal_w;
|
|
wire compare_gts_w;
|
|
wire compare_gt_w;
|
|
wire compare_lts_w;
|
|
wire compare_lt_w;
|
|
wire alu_flag_update;
|
|
|
// ALU operation selection
|
// ALU operation selection
|
reg [3:0] r_e_alu_func;
|
reg [3:0] r_e_alu_func;
|
|
|
// Delayed NMI
|
// Delayed NMI
|
reg r_nmi;
|
reg r_nmi;
|
Line 172... |
Line 180... |
// 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)
|
);
|
);
|
|
|
// Writeback result
|
// Writeback result
|
wire [31:0] w_write_res = (state == STATE_MEM) ? r_load_result : r_e_result;
|
wire [31:0] w_write_res = (state == STATE_MEM) ? r_load_result : r_e_result;
|
|
|
Line 276... |
Line 292... |
// Instruction
|
// Instruction
|
inst_r = {2'b00,r_opcode[31:26]};
|
inst_r = {2'b00,r_opcode[31:26]};
|
|
|
// Sub instructions
|
// Sub instructions
|
alu_op_r = {r_opcode[9:6],r_opcode[3:0]};
|
alu_op_r = {r_opcode[9:6],r_opcode[3:0]};
|
sfxx_op_r = {5'b00,r_opcode[31:21]};
|
sfxx_op_r = {5'b00,r_opcode[31:21]} & `INST_OR32_SFMASK;
|
shift_op_r = r_opcode[7:6];
|
shift_op_r = r_opcode[7:6];
|
|
|
// Branch target
|
// Branch target
|
target_int26_r = sign_extend_imm26(r_opcode[25:0]);
|
target_int26_r = sign_extend_imm26(r_opcode[25:0]);
|
|
|
Line 353... |
Line 369... |
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) & (r_opcode[31:24] == `INST_OR32_SYS); // l.sys
|
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_SYS); // l.sys
|
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_TRAP); // l.trap
|
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_TRAP); // l.trap
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
Line 683... |
Line 687... |
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;
|
|
|
case (1'b1)
|
case (1'b1)
|
Line 942... |
Line 950... |
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
|
|
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
|
|
|
// 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,
|
Line 966... |
Line 990... |
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Comparisons
|
// Comparisons
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
|
|
reg [31:0] compare_a_r;
|
|
reg [31:0] compare_b_r;
|
|
always @ *
|
always @ *
|
begin
|
begin
|
compare_a_r = reg_ra_r;
|
|
compare_b_r = reg_rb_r;
|
|
|
|
case (1'b1)
|
case (1'b1)
|
inst_sfeqi_w, // l.sfeqi
|
inst_sfges_w: // l.sfges
|
inst_sfgesi_w, // l.sfgesi
|
compare_result_r = compare_gts_w | compare_equal_w;
|
inst_sfgeui_w, // l.sfgeui
|
|
inst_sfgtsi_w, // l.sfgtsi
|
|
inst_sfgtui_w, // l.sfgtui
|
|
inst_sflesi_w, // l.sflesi
|
|
inst_sfleui_w, // l.sfleui
|
|
inst_sfltsi_w, // l.sfltsi
|
|
inst_sfltui_w, // l.sfltui
|
|
inst_sfnei_w: // l.sfnei
|
|
compare_b_r = int32_r;
|
|
default:
|
|
;
|
|
endcase
|
|
end
|
|
|
|
reg compare_equal_r;
|
inst_sfgeu_w: // l.sfgeu
|
reg compare_gts_r;
|
compare_result_r = compare_gt_w | compare_equal_w;
|
reg compare_gt_r;
|
|
reg compare_lts_r;
|
|
reg compare_lt_r;
|
|
always @ *
|
|
begin
|
|
if (compare_a_r == compare_b_r)
|
|
compare_equal_r = 1'b1;
|
|
else
|
|
compare_equal_r = 1'b0;
|
|
|
|
compare_lts_r = less_than_signed(compare_a_r, compare_b_r);
|
inst_sfgts_w: // l.sfgts
|
|
compare_result_r = compare_gts_w;
|
|
|
if (compare_a_r < compare_b_r)
|
inst_sfgtu_w: // l.sfgtu
|
compare_lt_r = 1'b1;
|
compare_result_r = compare_gt_w;
|
else
|
|
compare_lt_r = 1'b0;
|
|
|
|
// Greater than (signed)
|
inst_sfles_w: // l.sfles
|
compare_gts_r = ~(compare_lts_r | compare_equal_r);
|
compare_result_r = compare_lts_w | compare_equal_w;
|
|
|
if (compare_a_r > compare_b_r)
|
inst_sfleu_w: // l.sfleu
|
compare_gt_r = 1'b1;
|
compare_result_r = compare_lt_w | compare_equal_w;
|
else
|
|
compare_gt_r = 1'b0;
|
|
end
|
|
|
|
always @ *
|
inst_sflts_w: // l.sflts
|
begin
|
compare_result_r = compare_lts_w;
|
compare_result_r = 1'b0;
|
|
|
|
case (1'b1)
|
inst_sfltu_w: // l.sfltu
|
inst_sfeq_w, // l.sfeq
|
compare_result_r = compare_lt_w;
|
inst_sfeqi_w: // l.sfeqi
|
|
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_sfgtsi_w: // l.sfgtsi
|
|
compare_result_r = compare_gts_r;
|
|
|
|
inst_sfgtu_w, // l.sfgtu
|
|
inst_sfgtui_w: // l.sfgtui
|
|
compare_result_r = compare_gt_r;
|
|
|
|
inst_sfles_w, // l.sfles
|
|
inst_sflesi_w: // l.sflesi
|
|
compare_result_r = compare_lts_r | compare_equal_r;
|
|
|
|
inst_sfleu_w, // l.sfleu
|
|
inst_sfleui_w: // l.sfleui
|
|
compare_result_r = compare_lt_r | compare_equal_r;
|
|
|
|
inst_sflts_w, // l.sflts
|
|
inst_sfltsi_w: // l.sfltsi
|
|
compare_result_r = compare_lts_r;
|
|
|
|
inst_sfltu_w, // l.sfltu
|
|
inst_sfltui_w: // l.sfltui
|
|
compare_result_r = compare_lt_r;
|
|
|
|
inst_sfne_w, // l.sfne
|
|
inst_sfnei_w: // l.sfnei
|
|
compare_result_r = ~compare_equal_r;
|
|
|
|
default:
|
inst_sfne_w: // l.sfne
|
;
|
compare_result_r = ~compare_equal_w;
|
|
|
|
default: // l.sfeq
|
|
compare_result_r = compare_equal_w;
|
endcase
|
endcase
|
end
|
end
|
|
|
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
// Branches
|
// Branches
|
Line 1188... |
Line 1144... |
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;
|