mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Works, but bug in compressed decoder for sll
This commit is contained in:
parent
d324cfc01f
commit
5b3ba2d1d6
2 changed files with 141 additions and 158 deletions
|
@ -1126,11 +1126,13 @@ module controller
|
|||
if (jump_in_ex_i == `BRANCH_COND && ~branch_decision_i) begin
|
||||
// not taken
|
||||
pc_mux_sel_o = `PC_INCR;
|
||||
ctrl_fsm_ns = DECODE;
|
||||
if (~stall_id_o)
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end else begin
|
||||
// branch taken or jump
|
||||
pc_mux_sel_o = `PC_JUMP;
|
||||
ctrl_fsm_ns = BRANCH_DELAY;
|
||||
if (~stall_id_o)
|
||||
ctrl_fsm_ns = BRANCH_DELAY;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1247,7 +1249,7 @@ module controller
|
|||
// we unstall the if_stage if the debug unit wants to set a new
|
||||
// pc, so that the new value gets written into current_pc_if and is
|
||||
// used by the instr_core_interface
|
||||
stall_if_o = instr_ack_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_halt | dbg_stall_i | (~pc_valid_i);
|
||||
stall_if_o = instr_ack_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_halt | dbg_stall_i | (~pc_valid_i) | (jump_in_id_o != `BRANCH_NONE);
|
||||
stall_id_o = instr_ack_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_halt | dbg_stall_i;
|
||||
stall_ex_o = instr_ack_stall | lsu_stall | dbg_stall_i;
|
||||
stall_wb_o = lsu_stall | dbg_stall_i;
|
||||
|
|
291
if_stage.sv
291
if_stage.sv
|
@ -81,17 +81,18 @@ module if_stage
|
|||
);
|
||||
|
||||
// offset FSM
|
||||
enum logic[3:0] {IDLE, WAIT_ALIGNED, WAIT_UNALIGNED, VALID_ALIGNED, VALID_UNALIGNED,
|
||||
HANDLE_BRANCH, FETCH_UNALIGNED} offset_fsm_cs, offset_fsm_ns, offset_fsm_stored;
|
||||
enum logic[3:0] {WAIT_ALIGNED, VALID_ALIGNED,
|
||||
UNALIGNED_16,
|
||||
WAIT_UNALIGNED_32, VALID_UNALIGNED_32,
|
||||
WAIT_JUMPED_ALIGNED, VALID_JUMPED_ALIGNED,
|
||||
WAIT_JUMPED_UNALIGNED, VALID_JUMPED_UNALIGNED,
|
||||
IDLE } offset_fsm_cs, offset_fsm_ns, offset_fsm_stored;
|
||||
|
||||
logic [1:0] is_compressed;
|
||||
logic crossword_n, crossword_Q;
|
||||
logic unaligned, unaligned_Q;
|
||||
logic crossword;
|
||||
logic unaligned;
|
||||
logic unaligned_jump;
|
||||
|
||||
logic handle_branch;
|
||||
logic force_nop_int;
|
||||
|
||||
// instr_core_interface
|
||||
logic fetch_req;
|
||||
logic [31:0] fetch_rdata;
|
||||
|
@ -115,7 +116,7 @@ module if_stage
|
|||
current_pc_if_o = {fetch_addr[31:2], 2'b00};
|
||||
|
||||
if (unaligned) begin
|
||||
if (crossword_Q) begin
|
||||
if (crossword) begin
|
||||
// cross-word access, regular instruction
|
||||
instr_rdata_int = {fetch_rdata[15:0], data_arr};
|
||||
current_pc_if_o = {fetch_addr_Q[31:2], 2'b10};
|
||||
|
@ -127,10 +128,6 @@ module if_stage
|
|||
current_pc_if_o = {fetch_addr[31:2], 2'b10};
|
||||
end
|
||||
end
|
||||
|
||||
// insert NOPs for branches
|
||||
if (force_nop_int)
|
||||
instr_rdata_int = {25'b0, `OPCODE_OPIMM};
|
||||
end
|
||||
|
||||
|
||||
|
@ -199,14 +196,8 @@ module if_stage
|
|||
begin
|
||||
if (rst_n == 1'b0) begin
|
||||
offset_fsm_cs <= IDLE;
|
||||
offset_fsm_stored <= IDLE;
|
||||
end else begin
|
||||
if (handle_branch) begin
|
||||
offset_fsm_cs <= HANDLE_BRANCH;
|
||||
offset_fsm_stored <= offset_fsm_ns;
|
||||
end
|
||||
else
|
||||
offset_fsm_cs <= offset_fsm_ns;
|
||||
offset_fsm_cs <= offset_fsm_ns;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -215,171 +206,151 @@ module if_stage
|
|||
begin
|
||||
offset_fsm_ns = offset_fsm_cs;
|
||||
|
||||
handle_branch = 1'b0;
|
||||
|
||||
fetch_req = 1'b0;
|
||||
valid_o = 1'b0;
|
||||
|
||||
unaligned = unaligned_Q;
|
||||
crossword_n = crossword_Q;
|
||||
force_nop_int = 1'b0;
|
||||
unaligned = 1'b0;
|
||||
crossword = 1'b0;
|
||||
|
||||
unique case (offset_fsm_cs)
|
||||
// no valid instruction data for ID stage
|
||||
// assume aligned
|
||||
IDLE: begin
|
||||
if (req_i) begin
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_JUMPED_ALIGNED;
|
||||
end
|
||||
end
|
||||
|
||||
// aligned 32 bit or 16 bit instruction, we don't know yet
|
||||
WAIT_ALIGNED,
|
||||
VALID_ALIGNED: begin
|
||||
|
||||
if (fetch_valid || offset_fsm_cs == VALID_ALIGNED) begin
|
||||
valid_o = 1'b1; // an instruction is ready for ID stage
|
||||
offset_fsm_ns = VALID_ALIGNED;
|
||||
|
||||
if (req_i && ~stall_if_i) begin
|
||||
|
||||
if (~is_compressed[0]) begin
|
||||
// 32 bit aligned instruction found
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_ALIGNED;
|
||||
end else begin
|
||||
// 16 bit aligned instruction found
|
||||
if (is_compressed[1]) begin
|
||||
// next is 16 bit unaligned instruction
|
||||
// we already have that data, no need to fetch anything
|
||||
offset_fsm_ns = UNALIGNED_16;
|
||||
end else begin
|
||||
// next is 32 bit unaligned instruction
|
||||
// the upper half of this instruction is missing, start
|
||||
// fetching it
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_UNALIGNED_32;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// unaligned 16 bit instruction
|
||||
UNALIGNED_16: begin
|
||||
unaligned = 1'b1;
|
||||
|
||||
// we don't need to wait for a fetch_valid as we already have the data
|
||||
valid_o = 1'b1;
|
||||
|
||||
if (req_i && ~stall_if_i) begin
|
||||
// next instruction will be aligned
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_ALIGNED;
|
||||
end
|
||||
end
|
||||
|
||||
// We are currently in an ALIGNED state, serving PC[1] == 1'b0
|
||||
VALID_ALIGNED,
|
||||
WAIT_ALIGNED: begin
|
||||
unaligned = 1'b0;
|
||||
// unaligned 32 bit instruction
|
||||
WAIT_UNALIGNED_32,
|
||||
VALID_UNALIGNED_32: begin
|
||||
unaligned = 1'b1;
|
||||
crossword = 1'b1;
|
||||
|
||||
if (fetch_valid || offset_fsm_cs == VALID_ALIGNED) begin
|
||||
if (fetch_valid || offset_fsm_cs == VALID_UNALIGNED_32) begin
|
||||
valid_o = 1'b1;
|
||||
offset_fsm_ns = VALID_ALIGNED;
|
||||
offset_fsm_ns = VALID_UNALIGNED_32;
|
||||
|
||||
if (req_i && ~stall_if_i) begin
|
||||
crossword_n = 1'b0;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// no branch in ID, do regular fetch
|
||||
// ----------------------------------------------------------------------
|
||||
if (is_compressed[0]) begin
|
||||
// compressed instruction
|
||||
if (is_compressed[1]) begin
|
||||
// upper half contains compressed instruction and is available
|
||||
// from register, don't start fetch now
|
||||
offset_fsm_ns = VALID_UNALIGNED;
|
||||
end else begin
|
||||
// cross-word access, upper half is beginning of 32 bit instruction
|
||||
crossword_n = 1'b1;
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_UNALIGNED;
|
||||
end
|
||||
if (is_compressed[1]) begin
|
||||
// next is 16 bit unaligned instruction
|
||||
// we already have that data, no need to fetch anything
|
||||
offset_fsm_ns = UNALIGNED_16;
|
||||
end else begin
|
||||
// regular instruction
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_ALIGNED;
|
||||
end
|
||||
|
||||
if (jump_in_id_i != `BRANCH_NONE) begin
|
||||
// ----------------------------------------------------------------------
|
||||
// need to handle branch
|
||||
// ----------------------------------------------------------------------
|
||||
handle_branch = 1'b1;
|
||||
// next is 32 bit unaligned instruction
|
||||
// the upper half of this instruction is missing, start
|
||||
// fetching it
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_UNALIGNED_32;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// We are currently in an unaligned state, serving PC[1] == 1'b1
|
||||
WAIT_UNALIGNED,
|
||||
VALID_UNALIGNED: begin
|
||||
unaligned = 1'b1;
|
||||
// we did an aligned jump
|
||||
WAIT_JUMPED_ALIGNED,
|
||||
VALID_JUMPED_ALIGNED: begin
|
||||
|
||||
if (fetch_valid || offset_fsm_cs == VALID_UNALIGNED) begin
|
||||
if (fetch_valid || offset_fsm_cs == VALID_JUMPED_ALIGNED) begin
|
||||
valid_o = 1'b1;
|
||||
offset_fsm_ns = VALID_UNALIGNED;
|
||||
offset_fsm_ns = VALID_JUMPED_ALIGNED;
|
||||
|
||||
if (req_i && ~stall_if_i) begin
|
||||
crossword_n = 1'b0;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// no branch in ID, do regular fetch
|
||||
// ----------------------------------------------------------------------
|
||||
if (crossword_Q) begin
|
||||
// last instruction was 32 bit crossword, unaligned
|
||||
if (is_compressed[0]) begin
|
||||
// this instruction is 16 bit
|
||||
|
||||
if (is_compressed[1]) begin
|
||||
// compressed instruction, next instruction will be
|
||||
// unaligned
|
||||
offset_fsm_ns = VALID_UNALIGNED;
|
||||
// next instruction is also 16 bit
|
||||
offset_fsm_ns = UNALIGNED_16;
|
||||
end else begin
|
||||
// regular instruction, fetch following instruction
|
||||
fetch_req = 1'b1;
|
||||
crossword_n = 1'b1;
|
||||
offset_fsm_ns = WAIT_UNALIGNED;
|
||||
// next is 32 bit unaligned instruction
|
||||
// the upper half of this instruction is missing, start
|
||||
// fetching it
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_UNALIGNED_32;
|
||||
end
|
||||
end else begin
|
||||
// compressed instruction because no cross-word access done,
|
||||
// next instruction will be aligned
|
||||
// this instruction is 32 bit, so next one will be aligned
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_ALIGNED;
|
||||
|
||||
assert(is_compressed[1]) else $error("Not compressed, but compressed expected");
|
||||
end
|
||||
|
||||
if (jump_in_id_i != `BRANCH_NONE) begin
|
||||
handle_branch = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
HANDLE_BRANCH: begin
|
||||
// assume jump/branch instruction is in EX stage
|
||||
if (jump_in_ex_i == `BRANCH_COND && ~branch_decision_i) begin
|
||||
// branch not taken
|
||||
|
||||
// let's go to one instruction after the one we already put into the
|
||||
// pipeline
|
||||
if (unaligned_Q) begin
|
||||
// last state was unaligned, go back
|
||||
if (crossword_Q) begin
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_UNALIGNED;
|
||||
end else begin
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_ALIGNED;
|
||||
end
|
||||
end else begin
|
||||
crossword_n = 1'b0;
|
||||
|
||||
if (is_compressed[0]) begin
|
||||
offset_fsm_ns = VALID_UNALIGNED;
|
||||
end else begin
|
||||
offset_fsm_ns = VALID_ALIGNED;
|
||||
end
|
||||
end
|
||||
|
||||
end else begin
|
||||
// branch taken or jump
|
||||
fetch_req = 1'b1;
|
||||
crossword_n = 1'b0;
|
||||
if (unaligned_jump) begin
|
||||
// if the target address is unaligned, we need to fetch the lower
|
||||
// word first
|
||||
offset_fsm_ns = FETCH_UNALIGNED;
|
||||
end else begin
|
||||
offset_fsm_ns = WAIT_ALIGNED;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// can be cross-word or compressed
|
||||
FETCH_UNALIGNED: begin
|
||||
// we did an unaligned jump
|
||||
WAIT_JUMPED_UNALIGNED,
|
||||
VALID_JUMPED_UNALIGNED: begin
|
||||
unaligned = 1'b1;
|
||||
|
||||
if (fetch_valid) begin
|
||||
if (fetch_valid || offset_fsm_cs == VALID_JUMPED_UNALIGNED) begin
|
||||
// here we might not yet have the data, if the instruction is 32 bit
|
||||
// unaligned
|
||||
offset_fsm_ns = VALID_JUMPED_UNALIGNED;
|
||||
|
||||
if (is_compressed[1]) begin
|
||||
// no cross-word access
|
||||
crossword_n = 1'b0;
|
||||
valid_o = 1'b1;
|
||||
if (req_i && ~stall_if_i) begin
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_ALIGNED;
|
||||
end else begin
|
||||
offset_fsm_ns = VALID_UNALIGNED;
|
||||
end
|
||||
// Puh, lucky, we got a 16 bit instruction
|
||||
valid_o = 1'b1;
|
||||
|
||||
// next instruction will be aligned
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_ALIGNED;
|
||||
|
||||
end else begin
|
||||
// cross-word access, fetch next word
|
||||
fetch_req = 1'b1;
|
||||
crossword_n = 1'b1;
|
||||
offset_fsm_ns = WAIT_UNALIGNED;
|
||||
// a 32 bit unaligned instruction, let's fetch the upper half
|
||||
// we don't wait for stalls here as we still need data to get
|
||||
// unstalled
|
||||
fetch_req = 1'b1;
|
||||
offset_fsm_ns = WAIT_UNALIGNED_32;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -388,6 +359,31 @@ module if_stage
|
|||
offset_fsm_ns = IDLE;
|
||||
end
|
||||
endcase
|
||||
|
||||
|
||||
// take care of jumps and branches
|
||||
if(~stall_id_i) begin
|
||||
if (jump_in_ex_i != `BRANCH_NONE) begin
|
||||
if ((jump_in_ex_i == `BRANCH_COND && branch_decision_i) ||
|
||||
jump_in_ex_i == `BRANCH_JAL || jump_in_ex_i == `BRANCH_JALR) begin
|
||||
// branch taken
|
||||
|
||||
fetch_req = 1'b1;
|
||||
if (unaligned_jump)
|
||||
offset_fsm_ns = WAIT_JUMPED_UNALIGNED;
|
||||
else
|
||||
offset_fsm_ns = WAIT_JUMPED_ALIGNED;
|
||||
|
||||
end else begin
|
||||
// branch not taken
|
||||
// we don't need to do anything?
|
||||
end
|
||||
end else if (jump_in_id_i != `BRANCH_NONE) begin
|
||||
// new branch in ID, just wait
|
||||
//fetch_req = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -410,7 +406,7 @@ module if_stage
|
|||
data_arr <= 16'b0;
|
||||
fetch_addr_Q <= 32'b0;
|
||||
end else begin
|
||||
if (~stall_if_i) begin
|
||||
if (fetch_req) begin
|
||||
data_arr <= fetch_rdata[31:16];
|
||||
fetch_addr_Q <= fetch_addr;
|
||||
end
|
||||
|
@ -418,21 +414,6 @@ module if_stage
|
|||
end
|
||||
|
||||
|
||||
// IF PC register
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin : IF_PIPELINE
|
||||
if (rst_n == 1'b0)
|
||||
begin
|
||||
crossword_Q <= 1'b0;
|
||||
unaligned_Q <= 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
crossword_Q <= crossword_n;
|
||||
unaligned_Q <= unaligned;
|
||||
end
|
||||
end
|
||||
|
||||
// IF-ID pipeline registers, frozen when the ID stage is stalled
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin : IF_ID_PIPE_REGISTERS
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue