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:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user