`timescale 1ns / 1ps module sampler #( parameter DATA_WIDTH = 12, parameter PACK_FACTOR = 1, parameter PROCESS_MODE = 0 ) ( input clk_in, input rst, input [DATA_WIDTH-1:0] data_in, input out_of_range, input [31:0] smp_num, input request, output logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata, output logic m_axis_tvalid, output logic done ); // WARNING: number of samples smp_num must be multiple of PACK_FACTOR // Last (smp_num % PACK_FACTOR) will be lost and not transmitted logic [DATA_WIDTH-1:0] data_converted; logic [31:0] smp_num_reg, cnt_smp_num; logic synced; logic [$clog2(PACK_FACTOR):0] pack_cnt; always_comb begin if (PROCESS_MODE) begin if (out_of_range) begin data_converted = {~data_in[DATA_WIDTH-1], {(DATA_WIDTH-1){data_in[DATA_WIDTH-1]}}}; end else begin data_converted = {~data_in[DATA_WIDTH-1], data_in[DATA_WIDTH-2:0]}; end end else begin if (out_of_range) begin data_converted = {DATA_WIDTH{data_in[DATA_WIDTH-1]}}; end else begin data_converted = data_in; end end end initial begin synced = 0; m_axis_tdata = '0; m_axis_tvalid = 0; end always_ff @(posedge clk_in) begin if (rst) begin m_axis_tdata <= '0; m_axis_tvalid <= 0; cnt_smp_num <= '0; smp_num_reg <= '0; pack_cnt <= '0; synced <= 0; done <= 0; end else begin if (!synced) begin if (done && request) begin synced <= 1; done <= 0; cnt_smp_num <= 0; smp_num_reg <= smp_num; end else begin done <= 1; end end else begin if (cnt_smp_num != smp_num_reg) begin cnt_smp_num++; m_axis_tdata[pack_cnt*DATA_WIDTH +: DATA_WIDTH] <= data_converted; if (pack_cnt == PACK_FACTOR-1) begin pack_cnt <= 0; m_axis_tvalid <= 1; end else begin pack_cnt++; m_axis_tvalid <= 0; end end else begin pack_cnt <= '0; synced <= 0; m_axis_tvalid <= 0; end end end end endmodule