mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Fix jump/branch problem in IF
This commit is contained in:
parent
4d02dc1490
commit
0042daa8c9
1 changed files with 48 additions and 46 deletions
94
if_stage.sv
94
if_stage.sv
|
@ -226,42 +226,46 @@ module if_stage
|
|||
begin
|
||||
if (fetch_fsm_cs == WAIT_ACK) begin
|
||||
fetch_fsm_ns = WAIT_ACK;
|
||||
sample_addr = 1'b0;
|
||||
sample_addr = 1'b0;
|
||||
req_int = 1'b1; // keep req_int asserted or start request (for branches)
|
||||
if (ack_int) begin
|
||||
req_int = 1'b0;
|
||||
ack_o = 1'b1;
|
||||
fetch_fsm_ns = WAIT_REQ;
|
||||
end
|
||||
end
|
||||
|
||||
// handle requests
|
||||
if (req_i) begin
|
||||
fetch_fsm_ns = WAIT_ACK;
|
||||
req_int = 1'b1;
|
||||
if (fetch_fsm_cs == WAIT_REQ || ack_int) begin
|
||||
if (req_i) begin
|
||||
fetch_fsm_ns = WAIT_ACK;
|
||||
req_int = 1'b1;
|
||||
|
||||
if (pc_if_offset) begin
|
||||
if (is_compressed[1]) begin
|
||||
// serve second part of fetched instruction and request next
|
||||
pc_if_offset_n = 1'b0;
|
||||
ack_o = 1'b1;
|
||||
sample_addr = 1'b1;
|
||||
fetch_fsm_ns = WAIT_ACK;
|
||||
if (pc_if_offset) begin
|
||||
if (is_compressed[1]) begin
|
||||
// serve second part of fetched instruction and request next
|
||||
pc_if_offset_n = 1'b0;
|
||||
ack_o = 1'b1;
|
||||
sample_addr = 1'b1;
|
||||
fetch_fsm_ns = WAIT_ACK;
|
||||
end else begin
|
||||
// cross line access
|
||||
// .. need to fetch next word here and delay everything till then
|
||||
sample_addr = 1'b1;
|
||||
fetch_fsm_ns = FETCH_NEXT;
|
||||
end
|
||||
end else begin
|
||||
// cross line access
|
||||
// .. need to fetch next word here and delay everything till then
|
||||
sample_addr = 1'b1;
|
||||
fetch_fsm_ns = FETCH_NEXT;
|
||||
end
|
||||
end else begin
|
||||
if (is_compressed[0]) begin
|
||||
// compressed instruction, only increase PC by two bytes
|
||||
sample_addr = 1'b0;
|
||||
req_int = 1'b0;
|
||||
ack_o = 1'b1;
|
||||
pc_if_offset_n = 1'b1;
|
||||
fetch_fsm_ns = WAIT_REQ;
|
||||
end else begin
|
||||
// regular fetch
|
||||
sample_addr = 1'b1;
|
||||
if (is_compressed[0]) begin
|
||||
// compressed instruction, only increase PC by two bytes
|
||||
sample_addr = 1'b0;
|
||||
req_int = 1'b0;
|
||||
ack_o = 1'b1;
|
||||
pc_if_offset_n = 1'b1;
|
||||
fetch_fsm_ns = WAIT_REQ;
|
||||
end else begin
|
||||
// regular fetch
|
||||
sample_addr = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -292,19 +296,20 @@ module if_stage
|
|||
if (jump_in_ex_i == `BRANCH_COND && branch_decision_i == 1'b0) begin
|
||||
// branch not taken, continue as before
|
||||
// TODO: Already serve request here?
|
||||
fetch_fsm_ns = WAIT_REQ;
|
||||
fetch_fsm_ns = WAIT_REQ;
|
||||
end else begin
|
||||
// set new PC
|
||||
fetch_addr_n = {jump_target_i[31:2], 2'b0};
|
||||
sample_addr = 1'b1;
|
||||
// set PC
|
||||
// next_pc already contains correct jump target, but need to
|
||||
// handle special cases with compressed instructions here
|
||||
sample_addr = 1'b1;
|
||||
if (jump_target_i[1:0] == 2'b0) begin
|
||||
// regular fetch
|
||||
pc_if_offset_n = 1'b0;
|
||||
fetch_fsm_ns = WAIT_REQ;
|
||||
fetch_fsm_ns = WAIT_ACK;
|
||||
end else begin
|
||||
// unaligned access
|
||||
pc_if_offset_n = 1'b1;
|
||||
fetch_fsm_ns = FETCH;
|
||||
fetch_fsm_ns = FETCH;
|
||||
end
|
||||
// TODO: Already send request here?
|
||||
end
|
||||
|
@ -368,16 +373,16 @@ module if_stage
|
|||
end
|
||||
endcase
|
||||
|
||||
//if (jump_in_ex_i == 2'b01) begin
|
||||
// // jump handling
|
||||
// next_pc = jump_target_i;
|
||||
//end else if (jump_in_ex_i == 2'b10) begin
|
||||
// // branch handling
|
||||
// if (branch_decision_i == 1'b1)
|
||||
// next_pc = jump_target_i;
|
||||
// else
|
||||
// next_pc = incr_pc;
|
||||
//end
|
||||
// jump handling
|
||||
if (jump_in_ex_i == `BRANCH_JAL || jump_in_ex_i == `BRANCH_JALR) begin
|
||||
next_pc = jump_target_i;
|
||||
end else if (jump_in_ex_i == `BRANCH_COND) begin
|
||||
// branch handling
|
||||
if (branch_decision_i == 1'b1)
|
||||
next_pc = jump_target_i;
|
||||
else
|
||||
next_pc = current_pc_if_o;
|
||||
end
|
||||
|
||||
if (pc_mux_boot_i)
|
||||
next_pc = {boot_addr_i[31:5], `EXC_OFF_RST};
|
||||
|
@ -427,7 +432,6 @@ module if_stage
|
|||
// get PC from debug unit
|
||||
fetch_addr <= {dbg_pc_from_npc[31:2], 2'b0};
|
||||
pc_if_offset <= (dbg_pc_from_npc[1:0] != 2'b0);
|
||||
//end else if (stall_if_i == 1'b0) begin
|
||||
end else begin
|
||||
// update PC
|
||||
pc_if_offset <= pc_if_offset_n;
|
||||
|
@ -454,8 +458,6 @@ module if_stage
|
|||
current_pc_id_o <= last_fetch_addr + (bypass_data_reg? 32'd2 : -2); // TODO: Cleanup
|
||||
else
|
||||
current_pc_id_o <= last_fetch_addr;
|
||||
//current_pc_id_o <= last_fetch_addr + (pc_if_offset? 32'd2 : '0);
|
||||
//current_pc_id_o <= current_pc_if_o;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue