rtl: send part of out_axis_fifo
This commit is contained in:
@ -13,6 +13,10 @@ module out_axis_fifo #(
|
|||||||
output logic s_axis_tvalid,
|
output logic s_axis_tvalid,
|
||||||
input logic s_axis_tready,
|
input logic s_axis_tready,
|
||||||
output logic s_axis_tlast,
|
output logic s_axis_tlast,
|
||||||
|
// eth handshake
|
||||||
|
input logic req_ready,
|
||||||
|
output logic send_req,
|
||||||
|
output logic [15:0] udp_data_length,
|
||||||
|
|
||||||
// data from acc
|
// data from acc
|
||||||
input logic [ACCUM_WIDTH-1:0] acc_din,
|
input logic [ACCUM_WIDTH-1:0] acc_din,
|
||||||
@ -25,6 +29,32 @@ module out_axis_fifo #(
|
|||||||
output logic batch_req,
|
output logic batch_req,
|
||||||
output logic finish
|
output logic finish
|
||||||
);
|
);
|
||||||
|
// sync reset
|
||||||
|
reg [1:0] rst_sync_ff;
|
||||||
|
reg rst_eth;
|
||||||
|
|
||||||
|
always @(posedge acc_clk_in or posedge rst) begin
|
||||||
|
if (rst) begin
|
||||||
|
rst_sync_ff <= 2'b11;
|
||||||
|
end else begin
|
||||||
|
rst_sync_ff <= {rst_sync_ff[0], 1'b0};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign rst_eth = rst_sync_ff[1];
|
||||||
|
|
||||||
|
logic [1:0] rst_acc_ff;
|
||||||
|
logic rst_acc;
|
||||||
|
|
||||||
|
always_ff @(posedge acc_clk_in or posedge rst) begin
|
||||||
|
if (rst)
|
||||||
|
rst_acc_ff <= 2'b11;
|
||||||
|
else
|
||||||
|
rst_acc_ff <= {rst_acc_ff[0], 1'b0};
|
||||||
|
end
|
||||||
|
|
||||||
|
assign rst_acc = rst_acc_ff[1];
|
||||||
|
|
||||||
|
|
||||||
// fifo params calc
|
// fifo params calc
|
||||||
// round up to be enough for 2xPACKET_SIZE storage
|
// round up to be enough for 2xPACKET_SIZE storage
|
||||||
@ -37,9 +67,8 @@ module out_axis_fifo #(
|
|||||||
localparam int FIFO_RDEPTH = FIFO_WDEPTH * ACCUM_WIDTH / 8;
|
localparam int FIFO_RDEPTH = FIFO_WDEPTH * ACCUM_WIDTH / 8;
|
||||||
localparam int RDEPTH_BITS = $clog2(FIFO_RDEPTH) + 1;
|
localparam int RDEPTH_BITS = $clog2(FIFO_RDEPTH) + 1;
|
||||||
|
|
||||||
|
|
||||||
wire rd_unavail;
|
|
||||||
wire wr_unavail;
|
wire wr_unavail;
|
||||||
|
wire wr_rst_busy;
|
||||||
reg rd_en;
|
reg rd_en;
|
||||||
|
|
||||||
|
|
||||||
@ -57,14 +86,16 @@ module out_axis_fifo #(
|
|||||||
reg [31:0] wr_batch_tgt; // next 'target' that should be written from batch
|
reg [31:0] wr_batch_tgt; // next 'target' that should be written from batch
|
||||||
reg [31:0] wr_total; // total BITS to be sent!
|
reg [31:0] wr_total; // total BITS to be sent!
|
||||||
|
|
||||||
|
wire [WDEPTH_BITS:0] wr_data_count;
|
||||||
|
|
||||||
// NOTE:
|
// NOTE:
|
||||||
// each written "acc_din" ACCUM_WIDTH word
|
// each written "acc_din" ACCUM_WIDTH word
|
||||||
// is counted as WINDOWS_SIZE samples actually
|
// is counted as WINDOWS_SIZE samples actually
|
||||||
// because hw division for counters is painful
|
// because hw division for counters is painful
|
||||||
// so we just increased the counter sizes
|
// so we just increased the counter sizes
|
||||||
|
|
||||||
always_ff @(posedge acc_clk_in or posedge rst) begin
|
always_ff @(posedge acc_clk_in) begin
|
||||||
if (rst) begin
|
if (rst_acc) begin
|
||||||
wr_state <= WR_IDLE;
|
wr_state <= WR_IDLE;
|
||||||
wr_cnt <= 32'b0;
|
wr_cnt <= 32'b0;
|
||||||
wr_batch_tgt <= 32'b0;
|
wr_batch_tgt <= 32'b0;
|
||||||
@ -82,13 +113,15 @@ module out_axis_fifo #(
|
|||||||
wr_state <= WR_CHECK;
|
wr_state <= WR_CHECK;
|
||||||
wr_total <= smp_num * ACCUM_WIDTH;
|
wr_total <= smp_num * ACCUM_WIDTH;
|
||||||
wr_batch_tgt <= 32'b0;
|
wr_batch_tgt <= 32'b0;
|
||||||
|
batch_req <= 0;
|
||||||
|
finish <= 0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// wait until we can request a word
|
// wait until we can request a word
|
||||||
// depends on prog_full signal
|
// depends on prog_full signal
|
||||||
WR_CHECK: begin
|
WR_CHECK: begin
|
||||||
if (~wr_unavail) begin
|
if (~wr_unavail && ~wr_rst_busy) begin
|
||||||
batch_req <= 1;
|
batch_req <= 1;
|
||||||
// should give us exactly PACKET_SIZE * 8 bits
|
// should give us exactly PACKET_SIZE * 8 bits
|
||||||
// multiplied by WINDOW_SIZE, because we count
|
// multiplied by WINDOW_SIZE, because we count
|
||||||
@ -103,11 +136,7 @@ module out_axis_fifo #(
|
|||||||
// wait until all requested packet is written
|
// wait until all requested packet is written
|
||||||
WR_RUN: begin
|
WR_RUN: begin
|
||||||
batch_req <= 0;
|
batch_req <= 0;
|
||||||
if (din_valid) begin
|
if (wr_cnt == wr_batch_tgt) begin
|
||||||
// data supplied
|
|
||||||
// count as we got WINDOW_SIZE samples
|
|
||||||
wr_cnt <= wr_cnt + ACCUM_WIDTH * WINDOW_SIZE;
|
|
||||||
end else if (wr_cnt == wr_batch_tgt) begin
|
|
||||||
// got enough words
|
// got enough words
|
||||||
wr_state <= WR_END;
|
wr_state <= WR_END;
|
||||||
end else if (wr_cnt > wr_batch_tgt) begin
|
end else if (wr_cnt > wr_batch_tgt) begin
|
||||||
@ -116,6 +145,12 @@ module out_axis_fifo #(
|
|||||||
wr_cnt <= 32'hffffffff; // sort of signal for sim/ila
|
wr_cnt <= 32'hffffffff; // sort of signal for sim/ila
|
||||||
wr_state <= WR_END;
|
wr_state <= WR_END;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (din_valid) begin
|
||||||
|
// data supplied
|
||||||
|
// count as we got WINDOW_SIZE samples
|
||||||
|
wr_cnt <= wr_cnt + ACCUM_WIDTH * WINDOW_SIZE;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// check if this was last data batch
|
// check if this was last data batch
|
||||||
@ -123,8 +158,11 @@ module out_axis_fifo #(
|
|||||||
// here we check that we sent enough data
|
// here we check that we sent enough data
|
||||||
// wr_cnt should be by design PACKET_SIZE-aligned
|
// wr_cnt should be by design PACKET_SIZE-aligned
|
||||||
if (wr_cnt >= wr_total) begin
|
if (wr_cnt >= wr_total) begin
|
||||||
|
// wait until all data is sent
|
||||||
|
if (wr_data_count == 0) begin
|
||||||
finish <= 1;
|
finish <= 1;
|
||||||
wr_state <= WR_IDLE;
|
wr_state <= WR_IDLE;
|
||||||
|
end
|
||||||
end else begin
|
end else begin
|
||||||
// next word
|
// next word
|
||||||
wr_state <= WR_CHECK;
|
wr_state <= WR_CHECK;
|
||||||
@ -134,6 +172,78 @@ module out_axis_fifo #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// Readout FSM with ethernet request
|
||||||
|
|
||||||
|
assign udp_data_length = PACKET_SIZE; // fixed packet size
|
||||||
|
reg [15:0] sent_cnt;
|
||||||
|
|
||||||
|
typedef enum logic [2:0] {
|
||||||
|
RD_IDLE = 3'd0,
|
||||||
|
RD_CHECK = 3'd1,
|
||||||
|
RD_SEND = 3'd2
|
||||||
|
} rd_state_t;
|
||||||
|
|
||||||
|
(* MARK_DEBUG="true" *) rd_state_t rd_state;
|
||||||
|
|
||||||
|
wire rd_valid;
|
||||||
|
wire [RDEPTH_BITS-1:0] rd_data_count;
|
||||||
|
|
||||||
|
always_ff @(posedge eth_clk_in) begin
|
||||||
|
if (rst_eth) begin
|
||||||
|
rd_state <= RD_IDLE;
|
||||||
|
send_req <= 1'b0;
|
||||||
|
sent_cnt <= 16'd0;
|
||||||
|
s_axis_tlast <= 1'b0;
|
||||||
|
s_axis_tvalid <= 1'b0;
|
||||||
|
rd_en <= 1'b0;
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
|
||||||
|
case (rd_state)
|
||||||
|
// wait until fifo has enough data to send
|
||||||
|
RD_IDLE: begin
|
||||||
|
if (rd_data_count == PACKET_SIZE) begin
|
||||||
|
// enough data to send packet, begin
|
||||||
|
rd_state <= RD_CHECK;
|
||||||
|
end
|
||||||
|
send_req <= 1'b0;
|
||||||
|
sent_cnt <= 16'd0;
|
||||||
|
rd_en <= 1'b0;
|
||||||
|
s_axis_tlast <= 1'b0;
|
||||||
|
s_axis_tvalid <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
// await udp ready
|
||||||
|
RD_CHECK: begin
|
||||||
|
if (req_ready) begin
|
||||||
|
send_req <= 1'b1;
|
||||||
|
rd_state <= RD_SEND;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// send data
|
||||||
|
RD_SEND: begin
|
||||||
|
// udp is ready and fifo is ready = sent
|
||||||
|
send_req <= 1'b0;
|
||||||
|
if (s_axis_tready && rd_valid) begin
|
||||||
|
rd_en <= 1'b1;
|
||||||
|
s_axis_tvalid <= 1'b1;
|
||||||
|
sent_cnt <= sent_cnt + 1;
|
||||||
|
// final packet of the batch
|
||||||
|
if (sent_cnt == PACKET_SIZE - 1) begin
|
||||||
|
rd_state <= RD_IDLE;
|
||||||
|
s_axis_tlast <= 1'b1;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
rd_en <= 1'b0;
|
||||||
|
s_axis_tvalid <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
// xpm_fifo_async: Asynchronous FIFO
|
// xpm_fifo_async: Asynchronous FIFO
|
||||||
// Xilinx Parameterized Macro, version 2025.1
|
// Xilinx Parameterized Macro, version 2025.1
|
||||||
|
|
||||||
@ -148,13 +258,13 @@ module out_axis_fifo #(
|
|||||||
.READ_DATA_WIDTH(8), // always 8 bit for eth
|
.READ_DATA_WIDTH(8), // always 8 bit for eth
|
||||||
.READ_MODE("fwft"),
|
.READ_MODE("fwft"),
|
||||||
.SIM_ASSERT_CHK(1), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
|
.SIM_ASSERT_CHK(1), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
|
||||||
.USE_ADV_FEATURES("1606"), // String
|
.USE_ADV_FEATURES("1616"), // String
|
||||||
.WRITE_DATA_WIDTH(ACCUM_WIDTH),
|
.WRITE_DATA_WIDTH(ACCUM_WIDTH),
|
||||||
.WR_DATA_COUNT_WIDTH(WDEPTH_BITS)
|
.WR_DATA_COUNT_WIDTH(WDEPTH_BITS+1)
|
||||||
)
|
)
|
||||||
xpm_fifo_async_inst (
|
xpm_fifo_async_inst (
|
||||||
|
|
||||||
.data_valid(s_axis_tvalid), // 1-bit output: Read Data Valid: When asserted, this signal indicates that valid data is available on the
|
.data_valid(rd_valid), // 1-bit output: Read Data Valid: When asserted, this signal indicates that valid data is available on the
|
||||||
// output bus (dout).
|
// output bus (dout).
|
||||||
|
|
||||||
.dout(s_axis_tdata),
|
.dout(s_axis_tdata),
|
||||||
@ -162,17 +272,13 @@ module out_axis_fifo #(
|
|||||||
|
|
||||||
.full( ),
|
.full( ),
|
||||||
|
|
||||||
.prog_empty(rd_unavail), // 1-bit output: Programmable Empty: This signal is asserted when the number of words in the FIFO is less than
|
|
||||||
// or equal to the programmable empty threshold value. It is de-asserted when the number of words in the FIFO
|
|
||||||
// exceeds the programmable empty threshold value.
|
|
||||||
|
|
||||||
.prog_full(wr_unavail), // 1-bit output: Programmable Full: This signal is asserted when the number of words in the FIFO is greater than
|
.prog_full(wr_unavail), // 1-bit output: Programmable Full: This signal is asserted when the number of words in the FIFO is greater than
|
||||||
// or equal to the programmable full threshold value. It is de-asserted when the number of words in the FIFO is
|
// or equal to the programmable full threshold value. It is de-asserted when the number of words in the FIFO is
|
||||||
// less than the programmable full threshold value.
|
// less than the programmable full threshold value.
|
||||||
|
|
||||||
.rd_data_count( ), // RD_DATA_COUNT_WIDTH-bit output: Read Data Count: This bus indicates the number of words read from the FIFO.
|
.rd_data_count(rd_data_count), // RD_DATA_COUNT_WIDTH-bit output: Read Data Count: This bus indicates the number of words read from the FIFO.
|
||||||
|
|
||||||
.wr_data_count( ), // WR_DATA_COUNT_WIDTH-bit output: Write Data Count: This bus indicates the number of words written into the
|
.wr_data_count(wr_data_count), // WR_DATA_COUNT_WIDTH-bit output: Write Data Count: This bus indicates the number of words written into the
|
||||||
// FIFO.
|
// FIFO.
|
||||||
|
|
||||||
|
|
||||||
@ -186,7 +292,9 @@ module out_axis_fifo #(
|
|||||||
|
|
||||||
.din(acc_din), // WRITE_DATA_WIDTH-bit input: Write Data: The input data bus used when writing the FIFO.
|
.din(acc_din), // WRITE_DATA_WIDTH-bit input: Write Data: The input data bus used when writing the FIFO.
|
||||||
.wr_clk(acc_clk_in), // 1-bit input: Write clock: Used for write operation. wr_clk must be a free running clock.
|
.wr_clk(acc_clk_in), // 1-bit input: Write clock: Used for write operation. wr_clk must be a free running clock.
|
||||||
.wr_en(din_valid)
|
.wr_en(din_valid),
|
||||||
|
|
||||||
|
.wr_rst_busy(wr_rst_busy)
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user