`timescale 1 ns / 1 ps ////////////////////////////////////////////////////////////////////////////////// // Company: BITSILICA PRIVATE LIMITED // Design Name: AXI4_STREAM_MASTER_INTERFACE // Module Name: DOUT_M_AXIS // Project Name: POLAR ENCODER-DECODER // Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) // Tool Versions: VIVADO 2020.1 // Description: AXI4 Stream Master Interface is used to stream out output data from // the polar Encoder. // //////////////////////////////////////////////////////////////////////////////////// module DOUT_M_AXIS # ( // Width of S_AXIS address bus. The slave accepts the read and write addresses of width C_M_AXIS_TDATA_WIDTH. parameter integer C_M_AXIS_TDATA_WIDTH = 32, parameter integer C_S_AXIS_TDATA_WIDTH = 512, parameter integer DEPTH = 16, // Start count is the numeber of clock cycles the master will wait before initiating/issuing any transaction. parameter integer C_M_START_COUNT = 2 ) ( // Global ports input logic M_AXIS_ACLK, // input logic M_AXIS_ARESETN, // Master Stream Ports. TVALID indicates that the master is driving a valid transfer, A transfer takes place when both TVALID and TREADY are asserted. output logic M_AXIS_TVALID, // TDATA is the primary payload that is used to provide the data that is passing across the interface from the master. output logic [C_M_AXIS_TDATA_WIDTH-1 : 0] M_AXIS_TDATA, // TLAST indicates the boundary of a packet. output logic M_AXIS_TLAST, // TREADY indicates that the slave can accept a transfer in the current cycle. input logic M_AXIS_TREADY, // Input from PBCH Encoder Core of Width 864 bits input logic [C_S_AXIS_TDATA_WIDTH-1:0]S_AXIS_TDATA, // Input from PBCH Encoder Core input logic DONE ); //Total number of output data. // Total number of output data localparam NUMBER_OF_OUTPUT_WORDS = 27; // function called clogb2 that returns an integer which has the // value of the ceiling of the log base 2. function integer clogb2 (input integer bit_depth); begin for(clogb2=0; bit_depth>0; clogb2=clogb2+1) bit_depth = bit_depth >> 1; end endfunction // WAIT_COUNT_BITS is the width of the wait counter. localparam integer WAIT_COUNT_BITS = clogb2(C_M_START_COUNT-1); // bit_num gives the minimum number of bits needed to address 'depth' size of FIFO. localparam bit_num = clogb2(NUMBER_OF_OUTPUT_WORDS); // Define the states of state machine // The control state machine oversees the writing of input streaming data to the FIFO, // and outputs the streaming data from the FIFO parameter [1:0] IDLE = 2'b00, // This is the initial/idle state INIT_COUNTER = 2'b01, // This state initializes the counter, ones // the counter reaches C_M_START_COUNT count, // the state machine changes state to INIT_WRITE SEND_STREAM = 2'b10; // In this state the // stream data is output through M_AXIS_TDATA // State variable logic [1:0] mst_exec_state; // FIFO read pointer logic [bit_num-1:0] read_pointer; // AXI Stream internal signals //wait counter. The master waits for the user defined number of clock cycles before initiating a transfer. logic [WAIT_COUNT_BITS-1 : 0] count; //streaming data valid logic axis_tvalid; //streaming data valid delayed by one clock cycle logic axis_tvalid_delay; //Last of the streaming data logic axis_tlast; //Last of the streaming data delayed by one clock cycle logic axis_tlast_delay; //FIFO implementation signals logic [C_M_AXIS_TDATA_WIDTH-1 : 0] stream_data_out; logic tx_en; //The master has issued all the streaming data stored in FIFO logic tx_done; (* ram_style="register" *) logic [C_M_AXIS_TDATA_WIDTH-1:0] slv_reg0 [0:DEPTH-1]; // I/O Connections assignments assign M_AXIS_TVALID = axis_tvalid_delay; assign M_AXIS_TDATA = stream_data_out; assign M_AXIS_TLAST = axis_tlast_delay; integer i; integer byte_index; always_ff @( posedge M_AXIS_ACLK ) begin if (!M_AXIS_ARESETN ) begin stream_data_out <= 0; for(i = 0; i <= DEPTH - 1 ; i = i+1) slv_reg0[i] <= 0; end else begin if (DONE) for ( byte_index = 0; byte_index <= DEPTH - 1; byte_index = byte_index+1 ) slv_reg0[byte_index] <= S_AXIS_TDATA[(byte_index*C_M_AXIS_TDATA_WIDTH) +: C_M_AXIS_TDATA_WIDTH]; else if (tx_en) begin stream_data_out <= slv_reg0[read_pointer]; end end end // Control state machine implementation always_ff @(posedge M_AXIS_ACLK) begin // Synchronous reset (active low) if (!M_AXIS_ARESETN) begin mst_exec_state <= IDLE; count <= 0; end else case (mst_exec_state) IDLE: // The slave starts accepting tdata when // there tvalid is asserted to mark the // presence of valid streaming data mst_exec_state <= INIT_COUNTER; INIT_COUNTER: // The slave starts accepting tdata when // there tvalid is asserted to mark the // presence of valid streaming data if ( count == C_M_START_COUNT - 1 ) begin mst_exec_state <= SEND_STREAM; end else begin count <= count + 1; mst_exec_state <= INIT_COUNTER; end SEND_STREAM: // The example design streaming master functionality starts // when the master drives output tdata from the FIFO and the slave // has finished storing the S_AXIS_TDATA if (tx_done) begin mst_exec_state <= IDLE; end else begin mst_exec_state <= SEND_STREAM; end endcase end //tvalid generation //axis_tvalid is asserted when the control state machine's state is SEND_STREAM and //number of output streaming data is less than the NUMBER_OF_OUTPUT_WORDS. assign axis_tvalid = ((mst_exec_state == SEND_STREAM) && (read_pointer < NUMBER_OF_OUTPUT_WORDS)); // AXI tlast generation // axis_tlast is asserted number of output streaming data is NUMBER_OF_OUTPUT_WORDS-1 // (0 to NUMBER_OF_OUTPUT_WORDS-1) assign axis_tlast = (read_pointer == NUMBER_OF_OUTPUT_WORDS-1); // Delay the axis_tvalid and axis_tlast signal by one clock cycle // to match the latency of M_AXIS_TDATA always_ff @(posedge M_AXIS_ACLK) begin if (!M_AXIS_ARESETN) begin axis_tvalid_delay <= 1'b0; axis_tlast_delay <= 1'b0; end else begin axis_tvalid_delay <= axis_tvalid; axis_tlast_delay <= axis_tlast; end end //read_pointer pointer always_ff@(posedge M_AXIS_ACLK) begin if(!M_AXIS_ARESETN) begin read_pointer <= 0; tx_done <= 1'b0; end else if (read_pointer <= NUMBER_OF_OUTPUT_WORDS-1) begin if (tx_en) // read pointer is incremented after every read from the FIFO // when FIFO read signal is enabled. begin read_pointer <= read_pointer + 1; tx_done <= 1'b0; end end else if (read_pointer == NUMBER_OF_OUTPUT_WORDS) begin // tx_done is asserted when NUMBER_OF_OUTPUT_WORDS numbers of streaming data // has been out. tx_done <= 1'b1; if(DONE)read_pointer <= 0; end end //FIFO read enable generation assign tx_en = M_AXIS_TREADY && axis_tvalid; endmodule