fpga: rfnoc: Make Replay packet length independent of burst size

Before this change, the packet size output by the Replay block during
playback was limited to length of a full memory burst transaction.
This led to relatively small packets during playback (typically
2 KiB) and had other side effects, such as simultaneous playback from
two different memory locations using different packet sizes because of
differences in memory alignment.

With this change, the configured packet size, as set by the register
REG_PLAY_WORDS_PER_PKT, is used for all packets except the last
packet of playback, which can of course be smaller.


Original-commit: 082a733c326d6332d581d5b7bf9ee86a503ba502
This commit is contained in:
Wade Fife
2022-03-09 07:57:21 -06:00
parent df7fd28589
commit 56e53d271e
2 changed files with 160 additions and 108 deletions
@@ -281,7 +281,7 @@ module axis_replay #(
reg_play_cmd_time <= 0;
reg_play_words_per_pkt <= REG_PLAY_WORDS_PER_PKT_INIT;
reg_item_size <= DEFAULT_ITEM_SIZE;
items_per_word <= 'bX;
items_per_word <= 'bX;
rec_restart <= 0;
play_cmd_stop <= 0;
clear_cmd_fifo <= 0;
@@ -576,7 +576,7 @@ module axis_replay #(
rec_restart_clear <= 1'b0;
// Update wait timer
if (i_tvalid || !rec_fifo_occupied) begin
if ((i_tvalid && i_tready) || !rec_fifo_occupied) begin
// If a new word is presented to the input FIFO, or the FIFO is empty,
// then reset the timer.
rec_wait_timer <= 0;
@@ -943,78 +943,91 @@ module axis_replay #(
//
// This section monitors the signals to/from the memory interface and
// generates the TLAST and sideband signals. We assert TLAST at the end of
// every read transaction and after every reg_play_words_per_pkt words, so
// every reg_play_words_per_pkt words and at the end of the last packet, so
// that no packets are longer than the length indicated by the
// REG_PLAY_WORDS_PER_PKT register.
//
// The sideband signals consist of the timestamp, has_time flag, and eob
// flag. These are generated by the playback logic for each memory
// transaction.
// The sideband signals consist of the timestamp, has-time flag, and EOB (end
// of burst) flag. Timestamp and has_time are set for the first packet of
// each playback. EOB applies to each packet but is only set to 1 for the
// last packet of a playback.
//
// The timing of this block relies on the fact that read_ctrl_ready is not
// reasserted by the memory interface until after TLAST gets asserted.
// The timing of this section relies on the fact axi_dma_master doesn't allow
// overlapping read transactions. This means that the next read_ctrl_ready
// won't be asserted until after previous memory transaction finishes being
// read out.
//
//---------------------------------------------------------------------------
reg [MEM_COUNT_W-1:0] read_counter;
reg [ WPP_W-1:0] length_counter;
reg [ TIME_W-1:0] time_counter;
reg play_fifo_i_tlast;
reg has_time;
reg eob;
reg [MEM_COUNT_W-1:0] read_counter; // Track outstanding words to read
reg [ WPP_W-1:0] length_counter; // Track packet length
reg [ TIME_W-1:0] timestamp; // Timestamp for the current burst
reg has_time; // Is current burst timed?
reg eob; // End of burst
reg play_fifo_i_tlast; // End of packet
always @(posedge clk)
begin
if (rst) begin
play_fifo_i_tlast <= 1'b0;
// Don't care:
read_counter <= {MEM_COUNT_W{1'bX}};
length_counter <= {MEM_COUNT_W+1{1'bX}};
time_counter <= {TIME_W{1'bX}};
has_time <= 1'bX;
eob <= 1'bX;
end else begin
// Check if we're requesting a read transaction
if (read_ctrl_valid && read_ctrl_ready) begin
// Initialize read_counter for new transaction
read_counter <= read_count;
// synthesis translate_off
//
// Check our assumption about non-overlapping read transactions.
if (read_ctrl_ready && play_fifo_i_tvalid) begin
$fatal(1, "New read transaction started before the previous one completed!");
end
// synthesis translate_on
if (read_ctrl_valid && read_ctrl_ready) begin
read_counter <= read_count;
// If read_count is 0, then the next word is also the last word
if (read_count == 0) begin
play_fifo_i_tlast <= 1'b1;
eob <= last_trans;
end
end
if (play_fifo_i_tvalid && play_fifo_i_tready) begin
read_counter <= read_counter - 1;
length_counter <= length_counter - 1;
// Check if the current word is the last of the packet
if (play_fifo_i_tlast) begin
length_counter <= reg_play_words_per_pkt;
time_counter <= cmd_time;
has_time <= cmd_timed;
eob <= last_trans && (read_count < reg_play_words_per_pkt);
// If read_count is 0, then the first word is also the last word
if (read_count == 0) begin
play_fifo_i_tlast <= 1'b1;
// Clear tlast, unless the first word of the next packet is also the
// last word of the next packet.
if (!(last_trans && read_counter == 1)) begin
play_fifo_i_tlast <= 1'b0;
end
// Track the number of words read out by memory interface
end else if (read_data_valid && read_data_ready) begin
read_counter <= read_counter - 1;
length_counter <= length_counter - 1;
time_counter <= time_counter + items_per_word;
// Check if the word currently being output is the last word of a
// packet, which means we need to clear tlast.
if (play_fifo_i_tlast) begin
// But make sure that the next word isn't also the last of a memory
// burst, for which we will need to keep tlast asserted.
if (read_counter != 1) begin
play_fifo_i_tlast <= 1'b0;
end
// Restart length counter
length_counter <= reg_play_words_per_pkt;
// Check if next packet is the end of the burst (EOB)
eob <= last_trans && (read_counter <= reg_play_words_per_pkt);
// Check if the next word to be output should be the last of a packet.
end else if (read_counter == 1 || length_counter == 2) begin
play_fifo_i_tlast <= 1'b1;
end
// The timestamp only applies to the first packet, so disable for
// subsequent packets.
has_time <= 1'b0;
end
// Check if the next word will be the last of the packet.
//
// First, check if the next word is the last word of playback, in which
// case it's both the last word of the packet and the end of the burst.
if (last_trans && read_counter == 1) begin
play_fifo_i_tlast <= 1'b1;
eob <= 1;
// Next, check if this is the last word of the packet according to packet
// length. But note that the next word won't be the last if we're already
// outputting the last word of a burst on the current cycle.
end else if (length_counter == 2 && !(eob && play_fifo_i_tlast)) begin
play_fifo_i_tlast <= 1'b1;
end
end
if (play_state == PLAY_IDLE) begin
// Reset signals for the next playback
length_counter <= reg_play_words_per_pkt;
timestamp <= cmd_time_cf;
has_time <= cmd_timed_cf;
eob <= 0;
play_fifo_i_tlast <= 1'b0;
end
end
@@ -1053,20 +1066,6 @@ module axis_replay #(
.occupied ()
);
reg play_fifo_i_sop = 1'b1;
// Make play_fifo_i_sop true whenever the next play_fifo_i word is the start
// of a packet.
always @(posedge clk) begin
if (rst) begin
play_fifo_i_sop <= 1'b1;
end else begin
if (play_fifo_i_tvalid & play_fifo_i_tready) begin
play_fifo_i_sop <= play_fifo_i_tlast;
end
end
end
//---------------------------------------------------------------------------
// Header Info FIFO
@@ -1080,6 +1079,7 @@ module axis_replay #(
wire [(TIME_W+2)-1:0] hdr_fifo_i_tdata;
wire hdr_fifo_i_tvalid;
wire [(TIME_W+2)-1:0] hdr_fifo_o_tdata;
wire hdr_fifo_o_tvalid;
wire hdr_fifo_o_tready;
wire [15:0] hdr_fifo_space;
@@ -1097,20 +1097,31 @@ module axis_replay #(
.i_tready (),
//
.o_tdata (hdr_fifo_o_tdata),
.o_tvalid (),
.o_tvalid (hdr_fifo_o_tvalid),
.o_tready (hdr_fifo_o_tready),
//
.space (hdr_fifo_space),
.occupied ()
);
assign hdr_fifo_i_tdata = {has_time, eob, time_counter};
// synthesis translate_off
//
// The FIFO code above assumes the header info will always be available when
// the last word of the payload FIFO is read out. Check that assumption here.
always @(posedge clk) begin
if (hdr_fifo_o_tready && !hdr_fifo_o_tvalid) begin
$fatal(1, "Header FIFO read without valid data!");
end
end
// synthesis translate_on
assign hdr_fifo_i_tdata = {has_time, eob, timestamp };
// Pop the timestamp whenever we finish reading out a data packet
assign hdr_fifo_o_tready = o_tvalid & o_tready & o_tlast;
// Write the timestamp at the start of each packet
assign hdr_fifo_i_tvalid = play_fifo_i_tvalid & play_fifo_i_tready & play_fifo_i_sop;
assign hdr_fifo_i_tvalid = play_fifo_i_tvalid & play_fifo_i_tready & play_fifo_i_tlast;
assign { o_thas_time, o_teob, o_ttimestamp } = hdr_fifo_o_tdata;