rtl: wip accum output module, currently only with write part
This commit is contained in:
193
rtl/accum/src/out_axis_fifo.sv
Normal file
193
rtl/accum/src/out_axis_fifo.sv
Normal file
@ -0,0 +1,193 @@
|
||||
module out_axis_fifo #(
|
||||
parameter ACCUM_WIDTH = 32,
|
||||
parameter WINDOW_SIZE = 65,
|
||||
parameter PACKET_SIZE = 1024
|
||||
) (
|
||||
input logic eth_clk_in,
|
||||
input logic acc_clk_in,
|
||||
input logic rst,
|
||||
input logic [31:0] smp_num,
|
||||
|
||||
// AXI stream master for output, eth_clk_in domain
|
||||
output logic [7:0] s_axis_tdata,
|
||||
output logic s_axis_tvalid,
|
||||
input logic s_axis_tready,
|
||||
output logic s_axis_tlast,
|
||||
|
||||
// data from acc
|
||||
input logic [ACCUM_WIDTH-1:0] acc_din,
|
||||
input logic din_valid,
|
||||
|
||||
// input pulse
|
||||
input logic readout_begin,
|
||||
|
||||
// output pulses
|
||||
output logic batch_req,
|
||||
output logic finish
|
||||
);
|
||||
|
||||
// fifo params calc
|
||||
// round up to be enough for 2xPACKET_SIZE storage
|
||||
localparam int MIN_BYTES = 2 * PACKET_SIZE;
|
||||
localparam int MIN_BITS = MIN_BYTES * 8;
|
||||
localparam int MIN_WR_WORDS = (MIN_BITS + ACCUM_WIDTH - 1) / ACCUM_WIDTH; // ceil div
|
||||
localparam int WDEPTH_BITS = $clog2(MIN_WR_WORDS);
|
||||
localparam int FIFO_WDEPTH = 1 << WDEPTH_BITS;
|
||||
|
||||
localparam int FIFO_RDEPTH = FIFO_WDEPTH * ACCUM_WIDTH / 8;
|
||||
localparam int RDEPTH_BITS = $clog2(FIFO_RDEPTH) + 1;
|
||||
|
||||
|
||||
wire rd_unavail;
|
||||
wire wr_unavail;
|
||||
reg rd_en;
|
||||
|
||||
|
||||
typedef enum logic [2:0] {
|
||||
WR_IDLE = 3'd0,
|
||||
WR_CHECK = 3'd1,
|
||||
WR_RUN = 3'd2,
|
||||
WR_END = 3'd3
|
||||
} wr_state_t;
|
||||
|
||||
(* MARK_DEBUG="true" *) wr_state_t wr_state;
|
||||
|
||||
// Write FSM
|
||||
reg [31:0] wr_cnt; // current BIT mem ptr
|
||||
reg [31:0] wr_batch_tgt; // next 'target' that should be written from batch
|
||||
reg [31:0] wr_total; // total BITS to be sent!
|
||||
|
||||
// NOTE:
|
||||
// each written "acc_din" ACCUM_WIDTH word
|
||||
// is counted as WINDOWS_SIZE samples actually
|
||||
// because hw division for counters is painful
|
||||
// so we just increased the counter sizes
|
||||
|
||||
always_ff @(posedge acc_clk_in or posedge rst) begin
|
||||
if (rst) begin
|
||||
wr_state <= WR_IDLE;
|
||||
wr_cnt <= 32'b0;
|
||||
wr_batch_tgt <= 32'b0;
|
||||
wr_total <= 32'b0;
|
||||
batch_req <= 0;
|
||||
finish <= 0;
|
||||
|
||||
end else begin
|
||||
|
||||
case (wr_state)
|
||||
// wait until readout is requested
|
||||
WR_IDLE: begin
|
||||
if (readout_begin) begin
|
||||
wr_cnt <= 32'b0;
|
||||
wr_state <= WR_CHECK;
|
||||
wr_total <= smp_num * ACCUM_WIDTH;
|
||||
wr_batch_tgt <= 32'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// wait until we can request a word
|
||||
// depends on prog_full signal
|
||||
WR_CHECK: begin
|
||||
if (~wr_unavail) begin
|
||||
batch_req <= 1;
|
||||
// should give us exactly PACKET_SIZE * 8 bits
|
||||
// multiplied by WINDOW_SIZE, because we count
|
||||
// each given ACCUM_WIDTH word as WINDOWS_SIZE samples !!!
|
||||
wr_batch_tgt <= wr_batch_tgt + (8 * WINDOW_SIZE * PACKET_SIZE);
|
||||
wr_state <= WR_RUN;
|
||||
end else begin
|
||||
batch_req <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
// wait until all requested packet is written
|
||||
WR_RUN: begin
|
||||
batch_req <= 0;
|
||||
if (din_valid) 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
|
||||
wr_state <= WR_END;
|
||||
end else if (wr_cnt > wr_batch_tgt) begin
|
||||
// weird case when accum gave us too much words
|
||||
// block resets
|
||||
wr_cnt <= 32'hffffffff; // sort of signal for sim/ila
|
||||
wr_state <= WR_END;
|
||||
end
|
||||
end
|
||||
|
||||
// check if this was last data batch
|
||||
WR_END: begin
|
||||
// here we check that we sent enough data
|
||||
// wr_cnt should be by design PACKET_SIZE-aligned
|
||||
if (wr_cnt >= wr_total) begin
|
||||
finish <= 1;
|
||||
wr_state <= WR_IDLE;
|
||||
end else begin
|
||||
// next word
|
||||
wr_state <= WR_CHECK;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// xpm_fifo_async: Asynchronous FIFO
|
||||
// Xilinx Parameterized Macro, version 2025.1
|
||||
|
||||
xpm_fifo_async #(
|
||||
.DOUT_RESET_VALUE("0"), // String
|
||||
.FIFO_READ_LATENCY(1), // DECIMAL
|
||||
.FIFO_WRITE_DEPTH(FIFO_WDEPTH),
|
||||
.FULL_RESET_VALUE(0),
|
||||
.PROG_EMPTY_THRESH(PACKET_SIZE),
|
||||
.PROG_FULL_THRESH(PACKET_SIZE),
|
||||
.RD_DATA_COUNT_WIDTH(RDEPTH_BITS),
|
||||
.READ_DATA_WIDTH(8), // always 8 bit for eth
|
||||
.READ_MODE("fwft"),
|
||||
.SIM_ASSERT_CHK(1), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
|
||||
.USE_ADV_FEATURES("1606"), // String
|
||||
.WRITE_DATA_WIDTH(ACCUM_WIDTH),
|
||||
.WR_DATA_COUNT_WIDTH(WDEPTH_BITS)
|
||||
)
|
||||
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
|
||||
// output bus (dout).
|
||||
|
||||
.dout(s_axis_tdata),
|
||||
.empty( ),
|
||||
|
||||
.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
|
||||
// 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.
|
||||
|
||||
.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
|
||||
// FIFO.
|
||||
|
||||
|
||||
|
||||
|
||||
.rd_clk(eth_clk_in), // 1-bit input: Read clock: Used for read operation. rd_clk must be a free running clock.
|
||||
.rd_en(rd_en), // 1-bit input: Read Enable: If the FIFO is not empty, asserting this signal causes data (on dout) to be read
|
||||
// from the FIFO. Must be held active-low when rd_rst_busy is active high.
|
||||
|
||||
.rst(rst),
|
||||
|
||||
.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_en(din_valid)
|
||||
|
||||
);
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user