LSU cleanup, abort misaligned ops if first part fails

This commit cleans up the LSU and fixes two bugs:

1. If a misalgned transaction creates an error during the first
   part of the transaction, the second part is not pushed out and
   the transaction is aborted. Previously, the LSU tried to output
   also the second part but did not adhere to the defined
   protocol.

2. Misaligned operations are again working correctly. Previously,
   the generation of the byte enable and the alignment of read
   data was broken as these operations rely on the updated
   address from the AGU to have the same alignment as the
   original address.

This partially resolves #121.
This commit is contained in:
Pirmin Vogel 2019-07-04 14:43:14 +01:00
parent c84ca25755
commit 8613e880fc
4 changed files with 230 additions and 246 deletions

View file

@ -130,7 +130,8 @@ module ibex_core #(
// ID performance counter signals
logic is_decoding;
logic data_misaligned;
// LSU signals
logic lsu_addr_incr_req;
logic [31:0] lsu_addr_last;
// Jump and branch target and decision (EX->IF)
@ -187,7 +188,7 @@ module ibex_core #(
logic if_valid;
logic id_valid;
logic data_valid_lsu;
logic lsu_data_valid;
// Signals between instruction core interface and pipe (if and id stages)
logic instr_req_int; // Id stage asserts a req to instruction core interface
@ -391,7 +392,7 @@ module ibex_core #(
.id_ready_o ( id_ready ),
.ex_valid_i ( ex_valid ),
.lsu_valid_i ( data_valid_lsu ),
.lsu_valid_i ( lsu_data_valid ),
.id_valid_o ( id_valid ),
@ -425,7 +426,7 @@ module ibex_core #(
.data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit
.data_wdata_ex_o ( data_wdata_ex ), // to load store unit
.data_misaligned_i ( data_misaligned ),
.lsu_addr_incr_req_i ( lsu_addr_incr_req ),
.lsu_addr_last_i ( lsu_addr_last ),
.lsu_load_err_i ( lsu_load_err ),
@ -501,44 +502,42 @@ module ibex_core #(
/////////////////////
ibex_load_store_unit load_store_unit_i (
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.clk_i ( clk ),
.rst_ni ( rst_ni ),
//output to data memory
.data_req_o ( data_req_o ),
.data_gnt_i ( data_gnt_i ),
.data_rvalid_i ( data_rvalid_i ),
.data_err_i ( data_err_i ),
// data interface
.data_req_o ( data_req_o ),
.data_gnt_i ( data_gnt_i ),
.data_rvalid_i ( data_rvalid_i ),
.data_err_i ( data_err_i ),
.data_addr_o ( data_addr_o ),
.data_we_o ( data_we_o ),
.data_be_o ( data_be_o ),
.data_wdata_o ( data_wdata_o ),
.data_rdata_i ( data_rdata_i ),
.data_addr_o ( data_addr_o ),
.data_we_o ( data_we_o ),
.data_be_o ( data_be_o ),
.data_wdata_o ( data_wdata_o ),
.data_rdata_i ( data_rdata_i ),
// signal from ex stage
.data_we_ex_i ( data_we_ex ),
.data_type_ex_i ( data_type_ex ),
.data_wdata_ex_i ( data_wdata_ex ),
.data_reg_offset_ex_i ( data_reg_offset_ex ),
.data_sign_ext_ex_i ( data_sign_ext_ex ),
// signals to/from ID/EX stage
.data_we_ex_i ( data_we_ex ),
.data_type_ex_i ( data_type_ex ),
.data_wdata_ex_i ( data_wdata_ex ),
.data_reg_offset_ex_i ( data_reg_offset_ex ),
.data_sign_ext_ex_i ( data_sign_ext_ex ),
.data_rdata_ex_o ( regfile_wdata_lsu ),
.data_req_ex_i ( data_req_ex ),
.data_rdata_ex_o ( regfile_wdata_lsu ),
.data_req_ex_i ( data_req_ex ),
.adder_result_ex_i ( alu_adder_result_ex),
.adder_result_ex_i ( alu_adder_result_ex ),
.data_misaligned_o ( data_misaligned ),
.addr_last_o ( lsu_addr_last ),
.addr_incr_req_o ( lsu_addr_incr_req ),
.addr_last_o ( lsu_addr_last ),
.data_valid_o ( lsu_data_valid ),
// exception signals
.load_err_o ( lsu_load_err ),
.store_err_o ( lsu_store_err ),
.load_err_o ( lsu_load_err ),
.store_err_o ( lsu_store_err ),
// control signals
.data_valid_o ( data_valid_lsu ),
.lsu_update_addr_o ( ),
.busy_o ( lsu_busy )
.busy_o ( lsu_busy )
);
@ -780,7 +779,7 @@ module ibex_core #(
.ex_reg_addr_i ( id_stage_i.regfile_waddr ),
.ex_reg_we_i ( id_stage_i.regfile_we ),
.ex_reg_wdata_i ( id_stage_i.regfile_wdata ),
.data_valid_lsu_i ( data_valid_lsu ),
.lsu_data_valid_i ( lsu_data_valid ),
.ex_data_addr_i ( data_addr_o ),
.ex_data_req_i ( data_req_o ),
.ex_data_gnt_i ( data_gnt_i ),

View file

@ -106,7 +106,7 @@ module ibex_id_stage #(
output logic [1:0] data_reg_offset_ex_o,
output logic [31:0] data_wdata_ex_o,
input logic data_misaligned_i,
input logic lsu_addr_incr_req_i,
input logic [31:0] lsu_addr_last_i,
// Interrupt signals
@ -240,12 +240,12 @@ module ibex_id_stage #(
/////////////
// Misaligned loads/stores result in two aligned loads/stores, compute second address
assign alu_op_a_mux_sel = data_misaligned_i ? OP_A_FWD : alu_op_a_mux_sel_dec;
assign alu_op_b_mux_sel = data_misaligned_i ? OP_B_IMM : alu_op_b_mux_sel_dec;
assign imm_b_mux_sel = data_misaligned_i ? IMM_B_INCR_ADDR : imm_b_mux_sel_dec;
assign alu_op_a_mux_sel = lsu_addr_incr_req_i ? OP_A_FWD : alu_op_a_mux_sel_dec;
assign alu_op_b_mux_sel = lsu_addr_incr_req_i ? OP_B_IMM : alu_op_b_mux_sel_dec;
assign imm_b_mux_sel = lsu_addr_incr_req_i ? IMM_B_INCR_ADDR : imm_b_mux_sel_dec;
// do not write back the second address since the first calculated address was the correct one
assign regfile_we_id = data_misaligned_i ? 1'b0 : regfile_we_dec & ~deassert_we;
assign regfile_we_id = lsu_addr_incr_req_i ? 1'b0 : regfile_we_dec & ~deassert_we;
///////////////////
// Operand A MUX //
@ -287,7 +287,7 @@ module ibex_id_stage #(
assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : regfile_rdata_b;
// Signals used by tracer
assign operand_a_fw_id = data_misaligned_i ? lsu_addr_last_i : regfile_rdata_a;
assign operand_a_fw_id = lsu_addr_incr_req_i ? lsu_addr_last_i : regfile_rdata_a;
assign operand_b_fw_id = regfile_rdata_b;
assign unused_operand_a_fw_id = operand_a_fw_id;
@ -676,7 +676,7 @@ module ibex_id_stage #(
`ifdef CHECK_MISALIGNED
assert property (
@(posedge clk_i) (~data_misaligned_i) ) else
@(posedge clk_i) (~lsu_addr_incr_req_i) ) else
$display("Misaligned memory access at %x",pc_id_i);
`endif

View file

@ -30,7 +30,7 @@ module ibex_load_store_unit (
input logic clk_i,
input logic rst_ni,
// output to data memory
// data interface
output logic data_req_o,
input logic data_gnt_i,
input logic data_rvalid_i,
@ -42,52 +42,56 @@ module ibex_load_store_unit (
output logic [31:0] data_wdata_o,
input logic [31:0] data_rdata_i,
// signals from ex stage
input logic data_we_ex_i, // write enable -> from EX
input logic [1:0] data_type_ex_i, // data type: word, half word, byte -> from EX
input logic [31:0] data_wdata_ex_i, // data to write to memory -> from EX
input logic [1:0] data_reg_offset_ex_i, // register byte offset for stores -> from EX
input logic data_sign_ext_ex_i, // sign extension -> from EX
// signals to/from ID/EX stage
input logic data_we_ex_i, // write enable -> from ID/EX
input logic [1:0] data_type_ex_i, // data type: word, half word, byte -> from ID/EX
input logic [31:0] data_wdata_ex_i, // data to write to memory -> from ID/EX
input logic [1:0] data_reg_offset_ex_i, // register byte offset for stores -> from ID/EX
input logic data_sign_ext_ex_i, // sign extension -> from ID/EX
output logic [31:0] data_rdata_ex_o, // requested data -> to EX
input logic data_req_ex_i, // data request -> from EX
output logic [31:0] data_rdata_ex_o, // requested data -> to ID/EX
input logic data_req_ex_i, // data request -> from ID/EX
input logic [31:0] adder_result_ex_i, // address computed in ALU -> from EX
input logic [31:0] adder_result_ex_i, // address computed in ALU -> from ID/EX
output logic data_misaligned_o, // misaligned access detected -> to controller
output logic addr_incr_req_o, // request address increment for
// misaligned accesses -> to ID/EX
output logic [31:0] addr_last_o, // address of last transaction -> to controller
// -> mtval
// -> AGU for misaligned accesses
output logic data_valid_o, // LSU has completed transaction -> to
// exception signals
output logic load_err_o,
output logic store_err_o,
// stall signal
output logic lsu_update_addr_o, // LSU ready for new data in EX stage
output logic data_valid_o,
output logic busy_o
);
logic [31:0] data_addr;
logic [31:0] data_addr_w_aligned;
logic [31:0] addr_last_q, addr_last_n;
logic [31:0] addr_last_q, addr_last_d;
// registers for data_rdata alignment and sign extension
logic [1:0] data_type_q;
logic [1:0] rdata_offset_q;
logic data_sign_ext_q;
logic data_we_q;
logic [31:0] rdata_q, rdata_d;
logic [1:0] rdata_offset_q, rdata_offset_d;
logic [1:0] data_type_q, data_type_d;
logic data_sign_ext_q, data_sign_ext_d;
logic data_we_q, data_we_d;
logic [1:0] wdata_offset; // mux control for data to be written to memory
logic [3:0] data_be;
logic [31:0] data_wdata;
logic misaligned_st; // high if we are currently performing the second part
// of a misaligned store
logic data_misaligned, data_misaligned_q;
logic [31:0] data_rdata_ext;
logic [31:0] rdata_w_ext; // word realignment for misaligned loads
logic [31:0] rdata_h_ext; // sign extension for half words
logic [31:0] rdata_b_ext; // sign extension for bytes
logic split_misaligned_access;
logic handle_misaligned_q, handle_misaligned_d; // high after receiving grant for first
// part of a misaligned access
typedef enum logic [2:0] {
IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT, WAIT_RVALID
@ -95,15 +99,16 @@ module ibex_load_store_unit (
ls_fsm_e ls_fsm_cs, ls_fsm_ns;
logic [31:0] rdata_q;
assign data_addr = adder_result_ex_i;
///////////////////
// BE generation //
///////////////////
always_comb begin
unique case (data_type_ex_i) // Data type 00 Word, 01 Half word, 11,10 byte
2'b00: begin // Writing a word
if (!misaligned_st) begin // non-misaligned case
if (!handle_misaligned_q) begin // first part of potentially misaligned transaction
unique case (data_addr[1:0])
2'b00: data_be = 4'b1111;
2'b01: data_be = 4'b1110;
@ -111,7 +116,7 @@ module ibex_load_store_unit (
2'b11: data_be = 4'b1000;
default: data_be = 'X;
endcase // case (data_addr[1:0])
end else begin // misaligned case
end else begin // second part of misaligned transaction
unique case (data_addr[1:0])
2'b00: data_be = 4'b0000; // this is not used, but included for completeness
2'b01: data_be = 4'b0001;
@ -123,7 +128,7 @@ module ibex_load_store_unit (
end
2'b01: begin // Writing a half word
if (!misaligned_st) begin // non-misaligned case
if (!handle_misaligned_q) begin // first part of potentially misaligned transaction
unique case (data_addr[1:0])
2'b00: data_be = 4'b0011;
2'b01: data_be = 4'b0110;
@ -131,7 +136,7 @@ module ibex_load_store_unit (
2'b11: data_be = 4'b1000;
default: data_be = 'X;
endcase // case (data_addr[1:0])
end else begin // misaligned case
end else begin // second part of misaligned transaction
data_be = 4'b0001;
end
end
@ -151,6 +156,10 @@ module ibex_load_store_unit (
endcase // case (data_type_ex_i)
end
/////////////////////
// WData alignment //
/////////////////////
// prepare data to be written to the memory
// we handle misaligned accesses, half word and byte accesses and
// register offsets here
@ -165,32 +174,40 @@ module ibex_load_store_unit (
endcase // case (wdata_offset)
end
/////////////////////
// RData alignment //
/////////////////////
// FF for rdata alignment and sign-extension
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
data_type_q <= 2'h0;
rdata_offset_q <= 2'h0;
data_sign_ext_q <= 1'b0;
data_we_q <= 1'b0;
end else if (data_gnt_i) begin
// request was granted, we wait for rvalid and can continue to WB
data_type_q <= data_type_ex_i;
rdata_offset_q <= data_addr[1:0];
data_sign_ext_q <= data_sign_ext_ex_i;
data_we_q <= data_we_ex_i;
// rdata_q holds data returned from memory for first part of misaligned loads
always_comb begin
rdata_d = rdata_q;
if (data_rvalid_i & ~data_we_q & handle_misaligned_q) begin
rdata_d = data_rdata_i;
end
end
////////////////////
// Sign extension //
////////////////////
// update control signals for next read data upon receiving grant
assign rdata_offset_d = data_gnt_i ? data_addr[1:0] : rdata_offset_q;
assign data_type_d = data_gnt_i ? data_type_ex_i : data_type_q;
assign data_sign_ext_d = data_gnt_i ? data_sign_ext_ex_i : data_sign_ext_q;
assign data_we_d = data_gnt_i ? data_we_ex_i : data_we_q;
logic [31:0] data_rdata_ext;
logic [31:0] rdata_w_ext; // sign extension for words, actually only misaligned assembly
logic [31:0] rdata_h_ext; // sign extension for half words
logic [31:0] rdata_b_ext; // sign extension for bytes
// registers for rdata alignment and sign-extension
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rdata_q <= '0;
rdata_offset_q <= 2'h0;
data_type_q <= 2'h0;
data_sign_ext_q <= 1'b0;
data_we_q <= 1'b0;
end else begin
rdata_q <= rdata_d;
rdata_offset_q <= rdata_offset_d;
data_type_q <= data_type_d;
data_sign_ext_q <= data_sign_ext_d;
data_we_q <= data_we_d;
end
end
// take care of misaligned words
always_comb begin
@ -203,6 +220,10 @@ module ibex_load_store_unit (
endcase
end
////////////////////
// Sign extension //
////////////////////
// sign extension for half words
always_comb begin
unique case (rdata_offset_q)
@ -291,47 +312,130 @@ module ibex_load_store_unit (
endcase //~case(rdata_type_q)
end
// store last output address for mtval + AGU for misaligned transactions
// do not update in case of errors, mtval needs the failing address
/////////////
// LSU FSM //
/////////////
// check for misaligned accesses that need to be split into two word-aligned accesses
assign split_misaligned_access =
((data_type_ex_i == 2'b00) && (data_addr[1:0] != 2'b00)) || // misaligned word access
((data_type_ex_i == 2'b01) && (data_addr[1:0] == 2'b11)); // misaligned half-word access
// FSM
always_comb begin
addr_last_n = addr_last_q;
if (data_req_o & data_gnt_i & ~(load_err_o | store_err_o)) begin
addr_last_n = data_addr_o;
end
end
ls_fsm_ns = ls_fsm_cs;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ls_fsm_cs <= IDLE;
addr_last_q <= '0;
rdata_q <= '0;
data_misaligned_q <= '0;
end else begin
ls_fsm_cs <= ls_fsm_ns;
addr_last_q <= addr_last_n;
if (lsu_update_addr_o) begin
data_misaligned_q <= data_misaligned;
end
if (data_rvalid_i && !data_we_q) begin
// if we have detected a misaligned access, and we are
// currently doing the first part of this access, then
// store the data coming from memory in rdata_q.
// In all other cases, rdata_q gets the value that we are
// writing to the register file
data_req_o = 1'b0;
data_valid_o = 1'b0;
addr_incr_req_o = 1'b0;
handle_misaligned_d = handle_misaligned_q;
if (data_misaligned_q || data_misaligned) begin
rdata_q <= data_rdata_i;
end else begin
rdata_q <= data_rdata_ext;
unique case (ls_fsm_cs)
IDLE: begin
if (data_req_ex_i) begin
data_req_o = 1'b1;
if (data_gnt_i) begin
handle_misaligned_d = split_misaligned_access;
ls_fsm_ns = split_misaligned_access ? WAIT_RVALID_MIS : WAIT_RVALID;
end else begin
ls_fsm_ns = split_misaligned_access ? WAIT_GNT_MIS : WAIT_GNT;
end
end
end
WAIT_GNT_MIS: begin
data_req_o = 1'b1;
if (data_gnt_i) begin
handle_misaligned_d = 1'b1;
ls_fsm_ns = WAIT_RVALID_MIS;
end
end
WAIT_RVALID_MIS: begin
// tell ID/EX stage to update the address
addr_incr_req_o = 1'b1;
if (data_rvalid_i) begin
// first part rvalid is received
if (data_err_i) begin
// first part created an error, abort transaction
data_valid_o = 1'b1;
handle_misaligned_d = 1'b0;
ls_fsm_ns = IDLE;
end else begin
// push out second request
data_req_o = 1'b1;
if (data_gnt_i) begin
// second grant is received
ls_fsm_ns = WAIT_RVALID;
end else begin
// second grant is NOT received, but first rvalid
ls_fsm_ns = WAIT_GNT;
end
end
end else begin
// first part rvalid is NOT received
ls_fsm_ns = WAIT_RVALID_MIS;
end
end
WAIT_GNT: begin
// tell ID/EX stage to update the address
addr_incr_req_o = handle_misaligned_q;
data_req_o = 1'b1;
if (data_gnt_i) begin
ls_fsm_ns = WAIT_RVALID;
end
end
WAIT_RVALID: begin
data_req_o = 1'b0;
if (data_rvalid_i) begin
data_valid_o = 1'b1;
handle_misaligned_d = 1'b0;
ls_fsm_ns = IDLE;
end else begin
ls_fsm_ns = WAIT_RVALID;
end
end
default: begin
ls_fsm_ns = ls_fsm_e'(1'bX);
end
endcase
end
// store last address for mtval + AGU for misaligned transactions:
// - misaligned address needed for correct generation of data_be and data_rdata_ext
// - do not update in case of errors, mtval needs the failing address
always_comb begin
addr_last_d = addr_last_q;
if (data_req_o & data_gnt_i & ~(load_err_o | store_err_o)) begin
addr_last_d = data_addr;
end
end
// output to register file
assign data_rdata_ex_o = data_rvalid_i ? data_rdata_ext : rdata_q;
// registers for FSM
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ls_fsm_cs <= IDLE;
addr_last_q <= '0;
handle_misaligned_q <= '0;
end else begin
ls_fsm_cs <= ls_fsm_ns;
addr_last_q <= addr_last_d;
handle_misaligned_q <= handle_misaligned_d;
end
end
// output data address must be aligned to word
/////////////
// Outputs //
/////////////
// output to register file
assign data_rdata_ex_o = data_rdata_ext;
// output data address must be word aligned
assign data_addr_w_aligned = {data_addr[31:2], 2'b00};
// output to data interface
@ -340,8 +444,7 @@ module ibex_load_store_unit (
assign data_we_o = data_we_ex_i;
assign data_be_o = data_be;
assign misaligned_st = data_misaligned_q;
// output to ID stage: mtval + AGU for misaligned transactions
assign addr_last_o = addr_last_q;
// to know what kind of error to signal, we need to know the type of the transaction to which
@ -349,130 +452,12 @@ module ibex_load_store_unit (
assign load_err_o = data_err_i & data_rvalid_i & ~data_we_q;
assign store_err_o = data_err_i & data_rvalid_i & data_we_q;
// FSM
always_comb begin
ls_fsm_ns = ls_fsm_cs;
data_req_o = 1'b0;
lsu_update_addr_o = 1'b0;
data_valid_o = 1'b0;
data_misaligned_o = 1'b0;
unique case(ls_fsm_cs)
// starts from not active and stays in IDLE until request was granted
IDLE: begin
if (data_req_ex_i) begin
data_req_o = data_req_ex_i;
if (data_gnt_i) begin
lsu_update_addr_o = 1'b1;
ls_fsm_ns = data_misaligned ? WAIT_RVALID_MIS : WAIT_RVALID;
end else begin
ls_fsm_ns = data_misaligned ? WAIT_GNT_MIS : WAIT_GNT;
end
end
end // IDLE
WAIT_GNT_MIS: begin
data_req_o = 1'b1;
if (data_gnt_i) begin
lsu_update_addr_o = 1'b1;
ls_fsm_ns = WAIT_RVALID_MIS;
end
end // WAIT_GNT_MIS
// wait for rvalid in WB stage and send a new request if there is any
WAIT_RVALID_MIS: begin
//tell the controller to update the address
data_misaligned_o = 1'b1;
data_req_o = 1'b0;
lsu_update_addr_o = data_gnt_i;
if (data_rvalid_i) begin
//if first part rvalid is received
data_req_o = 1'b1;
if (data_gnt_i) begin
//second grant is received
ls_fsm_ns = WAIT_RVALID;
//in this stage we already received the first valid but no the second one
//it differes from WAIT_RVALID_MIS because we do not send other requests
end else begin
//second grant is NOT received, but first rvalid yes
//lsu_update_addr_o is 0 so data_misaligned_q stays high in WAIT_GNT
//increase address stays the same as well
ls_fsm_ns = WAIT_GNT; // [1]
end
end else begin
//if first part rvalid is NOT received
//the second grand is not received either by protocol.
//stay here
ls_fsm_ns = WAIT_RVALID_MIS;
end
end
WAIT_GNT: begin
data_misaligned_o = data_misaligned_q;
//useful in case [1]
data_req_o = 1'b1;
if (data_gnt_i) begin
lsu_update_addr_o = 1'b1;
ls_fsm_ns = WAIT_RVALID;
end
end //~ WAIT_GNT
WAIT_RVALID: begin
data_req_o = 1'b0;
if (data_rvalid_i) begin
data_valid_o = 1'b1;
ls_fsm_ns = IDLE;
end else begin
ls_fsm_ns = WAIT_RVALID;
end
end //~ WAIT_RVALID
default: begin
ls_fsm_ns = ls_fsm_e'(1'bX);
end
endcase
end
// check for misaligned accesses that need a second memory access
// If one is detected, this is signaled with data_misaligned_o to
// the controller which selectively stalls the pipeline
always_comb begin
data_misaligned = 1'b0;
if (data_req_ex_i && !data_misaligned_q) begin
unique case (data_type_ex_i)
2'b00: begin // word
if (data_addr[1:0] != 2'b00) begin
data_misaligned = 1'b1;
end
end
2'b01: begin // half word
if (data_addr[1:0] == 2'b11) begin
data_misaligned = 1'b1;
end
end
2'b10,
2'b11:;
default: data_misaligned = 1'bX;
endcase // case (data_type_ex_i)
end
end
assign data_addr = adder_result_ex_i;
assign busy_o = (ls_fsm_cs == WAIT_RVALID) | (data_req_o == 1'b1);
////////////////
// Assertions //
////////////////
`ifndef VERILATOR
// make sure there is no new request when the old one is not yet completely done
// i.e. it should not be possible to get a grant without an rvalid for the

View file

@ -62,7 +62,7 @@ module ibex_tracer #(
input logic [(RegAddrWidth-1):0] ex_reg_addr_i,
input logic ex_reg_we_i,
input logic [31:0] ex_reg_wdata_i,
input logic data_valid_lsu_i,
input logic lsu_data_valid_i,
input logic ex_data_req_i,
input logic ex_data_gnt_i,
input logic ex_data_we_i,
@ -433,7 +433,7 @@ module ibex_tracer #(
end
//we wait until the the data instruction ends
do @(negedge clk_i);
while (!data_valid_lsu_i);
while (!lsu_data_valid_i);
if (!mem_acc.we) begin
//load operations