Skip to content

Commit 486a10b

Browse files
committed
Grouped response support for outstanding transactions
1 parent f656897 commit 486a10b

File tree

4 files changed

+90
-168
lines changed

4 files changed

+90
-168
lines changed

Bender.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ sources:
2727
- rtl/variable_latency_interconnect/burst_cutter.sv
2828
- rtl/variable_latency_interconnect/burst_manager.sv
2929
- rtl/variable_latency_interconnect/burst_req_grouper.sv
30-
- rtl/variable_latency_interconnect/burst_rsp_grouper.sv
3130
# Level 2
3231
- rtl/tcdm_interconnect/clos_net.sv
3332
- rtl/tcdm_interconnect/bfly_net.sv

rtl/variable_latency_interconnect/burst_manager.sv

Lines changed: 55 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ module burst_manager
9696
always_comb begin
9797
prearb_data = '0;
9898
prearb_valid = '0;
99-
ready_mask = '0;
10099
valid_mask = req_valid_i;
100+
ready_mask = '0;
101101

102102
for (int unsigned i = 0; i < NumOut; i++) begin
103103
if (req_valid_i[i] && req_burst_i[i].isburst) begin
@@ -108,7 +108,7 @@ module burst_manager
108108
prearb_data[i].ben = req_ben_i[i];
109109
prearb_data[i].burst = req_burst_i[i];
110110
prearb_valid[i] = 1'b1;
111-
valid_mask = 1'b0;
111+
valid_mask[i] = 1'b0;
112112
// Mark retired burst requests
113113
if (prearb_ready[i]) begin
114114
ready_mask[i] = 1'b1;
@@ -190,31 +190,30 @@ module burst_manager
190190
DoBurst // generate parallel requests when ready
191191
} req_gen_fsm_e;
192192

193-
// FSM state
193+
// FSM state & signals
194194
req_gen_fsm_e state_d, state_q;
195-
// FSM stored signals
196-
fifo_data_t breq_d, breq_q;
197-
195+
fifo_data_t req_d, req_q;
196+
// Indicates which req inputs are involved in a burst
198197
logic [NumOut-1:0] burst_mask_d, burst_mask_q;
199-
// group mask used for response grouping
198+
// Indicates which resp inputs are involved in a burst
200199
logic [NumOut-1:0] group_mask_d, group_mask_q;
201-
202-
// indicate if there is pending response to be picked
200+
// indicates if there is pending response to be picked
203201
logic pending_rsp;
204202

203+
// Store FSM state and signals
205204
`FF(state_q, state_d, Idle, clk_i, rst_ni);
206-
`FF(breq_q, breq_d, '0, clk_i, rst_ni);
205+
`FF(req_q, req_d, '0, clk_i, rst_ni);
207206
`FF(burst_mask_q, burst_mask_d, '0, clk_i, rst_ni);
208207
`FF(group_mask_q, group_mask_d, '0, clk_i, rst_ni);
209208

210-
// Each element of a burst request must be retired to start request
209+
// Block burstlen ports after the port receiving a burst
211210
assign req_ready_o = ready_mask | (req_ready_i & ~burst_mask_q);
212211

213212
always_comb begin : request_generator
214213

215214
// FSM defaults
216215
state_d = state_q;
217-
breq_d = breq_q;
216+
req_d = req_q;
218217
burst_mask_d = burst_mask_q;
219218

220219
// comb logic defaults
@@ -228,7 +227,6 @@ module burst_manager
228227
req_ini_addr_o = req_ini_addr_i;
229228
req_wen_o = req_wen_i;
230229
req_ben_o = req_ben_i;
231-
232230
// Let valid requests not in burst pass
233231
req_valid_o = valid_mask;
234232

@@ -245,30 +243,30 @@ module burst_manager
245243
// pop next element
246244
fifo_pop = 1'b1;
247245
// store request
248-
breq_d = fifo_data;
246+
req_d = fifo_data;
249247
// a mask with burst length ones
250-
burst_mask_d = (1'b1 << breq_d.burst.blen) - 1'b1;
248+
burst_mask_d = (1'b1 << req_d.burst.blen) - 1'b1;
251249
// shift the mask to the first bank index addressed by the burst
252-
burst_mask_d = burst_mask_d << breq_d.idx;
250+
burst_mask_d = burst_mask_d << req_d.idx;
253251
state_d = DoBurst;
254252
end
255253

256254
end
257255

258256
DoBurst: begin
259257

260-
// If there is pending responses among the affected banks we wait
258+
// Check if there is pending responses among the affected banks
261259
pending_rsp = |((resp_valid_o & ~resp_ready_i) & burst_mask_q);
262-
// Send out requests when 1. required banks are all ready 2. no pending responses
263-
if (&(req_ready_i | (~burst_mask_q)) & !pending_rsp) begin
260+
// If no pending response and all the affected banks are ready send a new request
261+
if (&(req_ready_i | (~burst_mask_q)) && !pending_rsp) begin
264262
for (int unsigned i = 0; i < NumOut; i++) begin
263+
// Overwrite the request on affected banks
265264
if (burst_mask_q[i]) begin
266-
req_wdata_o[i] = breq_q.wdata;
267-
req_wen_o[i] = breq_q.wen;
268-
req_ben_o[i] = breq_q.ben;
269-
// overwrite tgt_addr
270-
req_tgt_addr_o[i] = i + breq_q.tgt_addr - breq_q.idx;
271-
req_ini_addr_o[i] = i + breq_q.ini_addr - breq_q.idx;
265+
req_wdata_o[i] = req_q.wdata;
266+
req_tgt_addr_o[i] = i + req_q.tgt_addr - req_q.idx;
267+
req_ini_addr_o[i] = i + req_q.ini_addr - req_q.idx;
268+
req_wen_o[i] = req_q.wen;
269+
req_ben_o[i] = req_q.ben;
272270
// Set the valid for burst requests
273271
req_valid_o[i] = 1'b1;
274272
end
@@ -306,49 +304,46 @@ module burst_manager
306304
logic [NumOut-1:0] grouped_resp_valid;
307305
logic [NumOut-1:0] grouped_resp_ready;
308306

309-
for (genvar i = 0; i < NumGroup; i ++) begin : gen_data_grouper
310-
burst_rsp_grouper #(
311-
.NumIn ( NumIn ),
312-
.NumOut ( NumOut ),
313-
.DataWidth ( DataWidth ),
314-
.RspGF ( RspGF ),
315-
.burst_resp_t ( burst_resp_t )
316-
) i_burst_rsp_grouper (
317-
.clk_i (clk_i ),
318-
.rst_ni (rst_ni ),
319-
/// Bank side
320-
.resp_ini_addr_i (resp_ini_addr_i[i*RspGF+:RspGF] ),
321-
.resp_rdata_i (resp_rdata_i[i*RspGF+:RspGF] ),
322-
.resp_valid_i (resp_valid_i[i*RspGF+:RspGF] ),
323-
.resp_ready_o (grouped_resp_ready[i*RspGF+:RspGF] ),
324-
/// Xbar side
325-
.resp_ini_addr_o (grouped_resp_ini_addr[i*RspGF+:RspGF] ),
326-
.resp_rdata_o (grouped_resp_rdata[i*RspGF+:RspGF] ),
327-
.resp_burst_o (grouped_resp_burst[i*RspGF+:RspGF] ),
328-
.resp_valid_o (grouped_resp_valid[i*RspGF+:RspGF] ),
329-
.resp_ready_i (resp_ready_i[i*RspGF+:RspGF] )
330-
);
331-
end
332-
333307
always_comb begin
308+
// Latch the new ports requested in burst
309+
group_mask_d = group_mask_q;
334310
for (int i = 0; i < NumGroup; i ++) begin
335-
if (state_q == DoBurst) begin
336-
group_mask_d[i*RspGF+:RspGF] = {RspGF{&burst_mask_q[i*RspGF+:RspGF]}};
337-
end else if (resp_ready_i[i*RspGF]) begin
311+
if ((state_q == DoBurst) && !pending_rsp) begin
312+
group_mask_d[i*RspGF+:RspGF] = group_mask_q[i*RspGF+:RspGF] | burst_mask_q[i*RspGF+:RspGF];
313+
end else if (resp_valid_o[i*RspGF] && resp_ready_i[i*RspGF]) begin
338314
group_mask_d[i*RspGF+:RspGF] = '0;
339-
end else begin
340-
group_mask_d[i*RspGF+:RspGF] = group_mask_q[i*RspGF+:RspGF];
341315
end
342316
end
343317
end
344318

319+
// Assign data to grouped response field
320+
always_comb begin
321+
for (int i = 0; i < NumGroup; i++) begin
322+
grouped_resp_burst[i*RspGF].isburst = &resp_valid_i[i*RspGF+:RspGF];
323+
grouped_resp_valid[i*RspGF] = &resp_valid_i[i*RspGF+:RspGF];
324+
for (int j = 1; j < RspGF; j++) begin
325+
grouped_resp_burst[i*RspGF].gdata[j-1] = resp_rdata_i[i*RspGF+j];
326+
grouped_resp_burst[i*RspGF+j].isburst = '0;
327+
grouped_resp_valid[i*RspGF+j] = 1'b0;
328+
end
329+
end
330+
end
331+
332+
// Assign grouped outputs
333+
// TODO: the code runs through, but there is a violation because the valid_o is sent before all the grouped factors are collected
334+
// This gives an assertion error on the local_response_interconnect, because the response_data changes (we add the gdata), before
335+
// the handshake happens.
345336
for (genvar i = 0; i < NumOut; i++) begin
346-
assign resp_ini_addr_o[i] = group_mask_q[i] ? (i % RspGF == 0 ? grouped_resp_ini_addr[i] : '0) : resp_ini_addr_i[i];
347-
assign resp_rdata_o[i] = group_mask_q[i] ? (i % RspGF == 0 ? grouped_resp_rdata[i] : '0) : resp_rdata_i[i];
348-
assign resp_burst_o[i].gdata = group_mask_q[i] ? (i % RspGF == 0 ? grouped_resp_burst[i].gdata : '0) : '0;
349-
assign resp_burst_o[i].isburst = group_mask_q[i] ? (i % RspGF == 0 ? grouped_resp_burst[i].isburst : 1'b0) : 1'b0;
350-
assign resp_valid_o[i] = group_mask_q[i] ? (i % RspGF == 0 ? grouped_resp_valid[i] : '0) : resp_valid_i[i];
351-
assign resp_ready_o[i] = group_mask_q[i] ? grouped_resp_ready[RspGF*(i/RspGF)] : resp_ready_i[i];
337+
assign grouped_resp_ini_addr[i] = (i % RspGF == 0) ? resp_ini_addr_i[i] : '0;
338+
assign grouped_resp_rdata[i] = (i % RspGF == 0) ? resp_rdata_i[i] : '0;
339+
340+
assign grouped_resp_ready[i] = (resp_valid_o[RspGF*(i/RspGF)] && resp_ready_i[RspGF*(i/RspGF)]);
341+
assign resp_ini_addr_o[i] = group_mask_q[i] ? grouped_resp_ini_addr[i] : resp_ini_addr_i[i];
342+
assign resp_rdata_o[i] = group_mask_q[i] ? grouped_resp_rdata[i] : resp_rdata_i[i];
343+
assign resp_burst_o[i].gdata = group_mask_q[i] ? grouped_resp_burst[i].gdata : '0;
344+
assign resp_burst_o[i].isburst = group_mask_q[i] ? grouped_resp_burst[i].isburst : 1'b0;
345+
assign resp_valid_o[i] = group_mask_q[i] ? grouped_resp_valid[i] : resp_valid_i[i];
346+
assign resp_ready_o[i] = group_mask_q[i] ? grouped_resp_ready[i] : (resp_valid_o[i] && resp_ready_i[i]);
352347
end
353348
end
354349

rtl/variable_latency_interconnect/burst_req_grouper.sv

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -180,32 +180,42 @@ module burst_req_grouper
180180
localparam int unsigned NumGroup = RspGF > 0 ? NumIn >> $clog2(RspGF) : NumIn;
181181

182182
always_comb begin
183-
for (int i = 0; i < NumIn; i++) begin
184-
automatic int grp_idx = i >> $clog2(RspGF);
185-
automatic int grp_off = i % RspGF;
186-
187-
if (i < NumGroup*RspGF) begin
188-
189-
if (resp_valid_i[grp_idx*RspGF] && resp_burst_i[grp_idx*RspGF].isburst && !resp_valid_i[i]) begin
190-
// Assign valid and data from grouped responses
191-
resp_ini_addr_o[i] = grp_off == 0 ? resp_ini_addr_i[i] : resp_ini_addr_i[i] + grp_off;
192-
resp_rdata_o[i] = grp_off == 0 ? resp_rdata_i[i] : resp_burst_i[grp_idx*RspGF].gdata[grp_off-1];
193-
resp_valid_o[i] = resp_valid_i[grp_idx*RspGF];
194-
// Assign ready when all grouped responses are retired
195-
resp_ready_o[i] = grp_off == 0 ? &resp_ready_i[i+:RspGF] : 1'b0;
196-
end else begin
197-
resp_ini_addr_o[i] = resp_ini_addr_i[i];
198-
resp_rdata_o[i] = resp_rdata_i[i];
199-
resp_valid_o[i] = resp_valid_i[i];
200-
resp_ready_o[i] = resp_ready_i[i];
201-
end
202183

203-
end else begin
204-
resp_ini_addr_o[i] = resp_ini_addr_i[i];
205-
resp_rdata_o[i] = resp_rdata_i[i];
206-
resp_valid_o[i] = resp_valid_i[i];
207-
resp_ready_o[i] = resp_ready_i[i];
208-
end
184+
// Default assignment
185+
resp_ini_addr_o = resp_ini_addr_i;
186+
resp_rdata_o = resp_rdata_i;
187+
resp_valid_o = resp_valid_i;
188+
resp_ready_o = resp_ready_i;
189+
190+
for (int ii = 0; ii < NumGroup; ii++) begin
191+
192+
if (resp_valid_i[ii*RspGF] && resp_burst_i[ii*RspGF].isburst) begin
193+
194+
// If any of the other inputs is valid give them priority
195+
if (|resp_valid_o[(ii*RspGF+1)+:(RspGF-1)]) begin
196+
resp_ini_addr_o[ii*RspGF] = '0;
197+
resp_rdata_o[ii*RspGF] = '0;
198+
resp_valid_o[ii*RspGF] = 1'b0;
199+
resp_ready_o[ii*RspGF] = 1'b0;
200+
201+
end else begin
202+
// Assign values from port ii*RspGF
203+
resp_ini_addr_o[ii*RspGF] = resp_ini_addr_i[ii*RspGF];
204+
resp_rdata_o[ii*RspGF] = resp_rdata_i[ii*RspGF];
205+
resp_rdata_o[ii*RspGF][DataWidth-1:DataWidth-6] = resp_rdata_i[ii*RspGF][DataWidth-1:DataWidth-6];
206+
resp_valid_o[ii*RspGF] = resp_valid_i[ii*RspGF];
207+
// Send ready back only when all the ports are ready
208+
resp_ready_o[ii*RspGF] = &resp_ready_i[ii*RspGF+:RspGF];
209+
for (int jj = 1; jj < RspGF; jj++) begin
210+
resp_ini_addr_o[ii*RspGF+jj] = resp_ini_addr_i[ii*RspGF] + jj;
211+
resp_rdata_o[ii*RspGF+jj] = resp_burst_i[ii*RspGF].gdata[jj-1];
212+
resp_rdata_o[ii*RspGF+jj][DataWidth-1:DataWidth-6] = resp_rdata_i[ii*RspGF][DataWidth-1:DataWidth-6];
213+
resp_valid_o[ii*RspGF+jj] = resp_valid_i[ii*RspGF];
214+
resp_ready_o[ii*RspGF+jj] = 1'b0;
215+
end
216+
end
217+
218+
end
209219

210220
end
211221
end

rtl/variable_latency_interconnect/burst_rsp_grouper.sv

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)