// Copyright 2024 Intel Corporation. // // This software and the related documents are Intel copyrighted materials, // and your use of them is governed by the express license under which they // were provided to you ("License"). Unless the License provides otherwise, // you may not use, modify, copy, publish, distribute, disclose or transmit // this software or the related documents without Intel's prior written // permission. // // This software and the related documents are provided as is, with no express // or implied warranties, other than those that are expressly stated in the // License. /* * dla_streamer_fsm.sv * * This module implements a state machine to produce the correct AXI-s o_tready signal for CoreDLA * input streaming. The goal is to make sure that the o_ready signal goes low as soon as the last * input transmission for the current frame is received, and does not go high again until the next * move instruction is configured in the input feeder. * * To accomplish this, this module implements the FSM as shown below: * * ~i_dla_ready | ~i_stream_en * ┌────┐ * │ │ * │ │ ┌───────┐ ~i_tvalid * ┌─┴────▼┌─────┐ │ ├────┐ ┌─────────────────────────────────────────────────────────────┐ * │ │ └──────────►│ S1 │ │ │ │ * │ S0 | i_dla_ready │ │◄───┘ │ S0: IDLE ("Wait for input feeder to become ready") │ * │ │ & i_stream_en ├──┬────┘ │ o_stream_ready = 0 │ * └───────┘ │ │ │ │ * ▲ │ │ │ S1: STREAM_FIRST ("Accept first input") │ * │ i_lt_done_frame │ │i_tvalid │ o_stream_ready = 1 │ * │ ┌──────┘ │ │ │ * │ │ │ │ S1: STREAMING ("Accept AXI-s inputs") │ * │ │ ┌───▼───┐ │ o_stream_ready = 1 │ * │~i_dla_ready │ │ ├────┐ │ │ * │ │ │ S2 │ │ │ S2: WAIT_FOR_NEXT_FRAME ("Downstream is digesting inputs") │ * │ ┌──────────┘ │ │◄───┘ │ o_stream_ready = 0 │ * │ ▼ └───┬───┘ └─────────────────────────────────────────────────────────────┘ * ┌─┴─────┐ │ * │ │ │i_lt_done_frame * │ S3 ├──────────────────┘ * │ │ * └─────┬─┘ * ▲ │ * │ │ * └───┘ * i_dla_ready * * * Note: This FSM assumes that the i_dla_ready signal from the input feeder goes low between every input frame. */ `resetall `undefineall `default_nettype none module dla_streamer_fsm ( input wire clk_dla, input wire clk_axi, input wire i_resetn_axi, input wire i_resetn_async, input wire i_dla_ready, input wire i_lt_ready, input wire i_streaming_enable, input wire i_lt_done_frame, input wire i_tvalid, output logic o_stream_ready, output logic o_reading_first_word // Used to start the 'active jobs' CSR counter ); enum { // 2-state ints IDLE_BIT, STREAM_FIRST_BIT, STREAMING_BIT, WAIT_FOR_NEXT_FRAME_BIT } index; enum logic [index.num()-1:0] { // 1-hot encodings IDLE = 1 << IDLE_BIT, STREAM_FIRST = 1 << STREAM_FIRST_BIT, STREAMING = 1 << STREAMING_BIT, WAIT_FOR_NEXT_FRAME = 1 << WAIT_FOR_NEXT_FRAME_BIT, XXX = 'x } state, next; logic axi_dla_ready; // move the ready signal from input feeder into AXI domain. dla_clock_cross_full_sync cc_dla_ready ( .clk_src(clk_dla), .i_src_async_resetn(1'b1), .i_src_data(i_dla_ready), .o_src_data(), // in streamer, sort out resets and pass in the appropriate resets. .clk_dst(clk_axi), .i_dst_async_resetn(1'b1), .o_dst_data(axi_dla_ready) ); always_comb begin : fsm_combinational next = XXX; unique case (1'b1) state[IDLE_BIT]: if (i_lt_ready & i_streaming_enable) next = STREAM_FIRST; else next = IDLE; state[STREAM_FIRST_BIT]: if (i_tvalid & i_streaming_enable) next = STREAMING; else next = STREAM_FIRST; state[STREAMING_BIT]: if (i_lt_done_frame) next = WAIT_FOR_NEXT_FRAME; else next = STREAMING; state[WAIT_FOR_NEXT_FRAME_BIT]: next = IDLE; default: next = XXX; endcase end always_ff @( posedge clk_axi ) begin : fsm_state_logic state <= next; o_reading_first_word <= 0; if (state[STREAM_FIRST_BIT] & next != STREAM_FIRST) begin o_reading_first_word <= 1; end if (~i_resetn_axi) begin state <= IDLE; end end assign o_stream_ready = state[STREAMING_BIT] | (state[STREAM_FIRST_BIT] & i_streaming_enable); endmodule