Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions hardware/src/vlsu/align_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ assign axi_resp_i_cut[0].r_valid = axi_resp_i.r_valid;
// Handle Vector Loads //
/////////////////////////

logic is_load_aligned, is_load_resp_valid;

always_comb begin

// Initialize state
Expand Down Expand Up @@ -239,14 +241,11 @@ always_comb begin

///// Handling unaligned data using byte enable /////

// If a stage receives a valid packet, shift the byte enable
for (int s=0; s < NumStages; s++) begin
if (axi_resp_o_cut[s].r_valid) begin
be_d[s+1] = tracker_q[rd_resp_pnt_q[s]].shift_en[s] ? be_q[s] >> (1 << s) : be_q[s];
end
end
be_final_d = be_q[NumStages];

is_load_aligned = be_final_d[AxiDataBytes-1];
is_load_resp_valid = axi_resp_i_cut[NumStages].r_valid;

///// Handle incoming AXI responses /////

// Track the previous data packet and along with the byte enable
Expand All @@ -259,7 +258,7 @@ always_comb begin
axi_req_cut_ready[NumStages] = axi_req_i.r_ready;

// For a valid handshake assign to buffer to be used later
if (axi_resp_i_cut[NumStages].r_valid && axi_req_i.r_ready) begin
if (is_load_resp_valid && axi_req_i.r_ready) begin
// Buffer data in this cycle
data_d = axi_resp_i_cut[NumStages].r.data;
data_valid_d = 1'b1;
Expand All @@ -277,7 +276,7 @@ always_comb begin
// If misaligned, make sure you have a valid beat in the current cycle
// or if the transaction is short that is check if previous beat was the last beat
// Otherwise, we have a valid data if the request is aligned
automatic logic valid_data = (~be_final_d[AxiDataBytes-1] & (axi_resp_i_cut[NumStages].r_valid | last_q)) | be_final_d[AxiDataBytes-1];
automatic logic valid_data = (~is_load_aligned & (is_load_resp_valid | last_q)) | is_load_aligned;
for (int b=0; b<AxiDataBytes; b++) begin
axi_resp_o.r.data[b*8 +: 8] = be_final_d[b] ? data_q[b*8 +: 8] : axi_resp_i_cut[NumStages].r.data[b*8 +: 8];
end
Expand All @@ -290,7 +289,7 @@ always_comb begin
tracker_d[rd_resp_pnt_q_del[NumStages-1]].len -= axi_valid_el;

// If aligned request, set data valid only if available valid beat
data_valid_d = be_final_d[AxiDataBytes-1] ? axi_resp_i_cut[NumStages].r_valid : 1'b1;
data_valid_d = is_load_aligned ? is_load_resp_valid : 1'b1;

// Use vl from tracker to check if this is the last data packet or not
// Since using delayed data, using delayed pointer to the tracker
Expand All @@ -300,14 +299,12 @@ always_comb begin

// If the current data is not misaligned and we have a valid data
// Set valid data for the next subsequent load to avoid bubble
data_valid_d = be_final_d[AxiDataBytes-1] & axi_resp_i_cut[NumStages].r_valid;
data_valid_d = is_load_aligned & is_load_resp_valid;

// If misaligned but we already have a response for the next request,
// stall it for 1 cycle
if (!be_final_d[AxiDataBytes-1] & !axi_resp_i_cut[NumStages].r.last) begin
// If misaligned stall it for 1 cycle
if (!is_load_aligned & last_q) begin
axi_req_cut_ready[NumStages] = 1'b0;
end

last_d = 1'b0;
end
end
Expand All @@ -324,6 +321,13 @@ always_comb begin
data_valid_d = 1'b0;
end

// If a stage receives a valid packet, shift the byte enable
for (int s=0; s < NumStages; s++) begin
if (axi_resp_o_cut[s].r_valid & axi_req_cut_ready[NumStages]) begin
be_d[s+1] = tracker_q[rd_resp_pnt_q[s]].shift_en[s] ? be_q[s] >> (1 << s) : be_q[s];
end
end

///// Pointer updates to align stages /////

// Update read pointer of each stage
Expand Down
18 changes: 11 additions & 7 deletions hardware/src/vlsu/global_ldst.sv
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ vew_e vew_d, vew_q;
vlen_cluster_t vl_ldst_rd_d, vl_ldst_rd_q, vl_ldst_wr_d, vl_ldst_wr_q;

logic fifo_push_d, fifo_push_q;
logic w_fifo_push_d, w_fifo_push_q;

// These are updated only when a new aw/ar is accepted
assign cluster_metadata_o.vew = vew_d;
Expand All @@ -103,6 +104,7 @@ always_ff @(posedge clk_i or negedge rst_ni) begin
r_resp_lane_q <= '0;
r_resp_rem_q <= '0;
fifo_push_q <= 1'b0;
w_fifo_push_q <= 1'b0;
axi_resp_q <= '0;
end else begin
r_req_valid_q <= r_req_valid_d;
Expand All @@ -119,6 +121,7 @@ always_ff @(posedge clk_i or negedge rst_ni) begin
r_resp_lane_q <= r_resp_lane_d;
r_resp_rem_q <= r_resp_rem_d;
fifo_push_q <= fifo_push_d;
w_fifo_push_q <= w_fifo_push_d;
axi_resp_q <= axi_resp_d;
end
end
Expand Down Expand Up @@ -247,6 +250,7 @@ always_comb begin : p_global_ldst
fifo_push_i = 1'b0;
b_fifo_push_i = 1'b0;
fifo_push_d = fifo_push_q;
w_fifo_push_d = w_fifo_push_q;

// Initialize cluster pointers and request counters
cluster_aw_d = cluster_aw_q;
Expand Down Expand Up @@ -328,24 +332,24 @@ always_comb begin : p_global_ldst
vl_ldst_wr_d -= vl_w_done;
req_d.aw.addr = wr_aligned_next_start_addr_d; // Update request state
w_req_valid_d = 1'b1;
b_fifo_push_i = fifo_push_q ? 1'b0 : 1'b1;
fifo_push_d = 1'b1;
b_fifo_push_i = w_fifo_push_q ? 1'b0 : 1'b1;
w_fifo_push_d = 1'b1;
end else begin
vl_ldst_wr_d = '0;
w_req_valid_d = 1'b0;
b_fifo_push_i = fifo_push_q ? 1'b0 : 1'b1;
fifo_push_d = 1'b0;
b_fifo_push_i = w_fifo_push_q ? 1'b0 : 1'b1;
w_fifo_push_d = 1'b0;
end
end else begin
vl_ldst_wr_d -= 1;
// If request already pushed to fifo don't push again
b_fifo_push_i = fifo_push_q ? 1'b0 : 1'b1;
fifo_push_d = 1'b1;
b_fifo_push_i = w_fifo_push_q ? 1'b0 : 1'b1;
w_fifo_push_d = 1'b1;
if (vl_ldst_wr_d == 0) begin
// If we have sent all the requests for this indexed vector store, we can move the AW pointer back to cluster 0.
cluster_aw_d = '0;
lane_aw_d = '0;
fifo_push_d = 1'b0;
w_fifo_push_d = 1'b0;
end
w_req_valid_d = 1'b0;
end
Expand Down
Loading
Loading