// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: CERN-OHL-S-2.0 #include "hls_jfjoch.h" void data_collection_fsm(AXI_STREAM ð_in, STREAM_512 &data_out, hls::stream &addr_in, hls::stream &addr_out, volatile ap_uint<1> &in_run, volatile ap_uint<1> &in_cancel, volatile ap_uint<1> &out_idle, ap_uint<32> mode, ap_uint<32> energy_kev, ap_uint<32> nframes, ap_uint<5> nmodules, ap_uint<4> nstorage_cells, ap_uint<8> nsummation, ap_uint<8> sqrtmult, ap_uint<32> pxlthreshold_min, ap_uint<32> pxlthreshold_max, volatile rcv_state_t &data_collection_state) { #pragma HLS INTERFACE ap_ctrl_none port=return #pragma HLS INTERFACE axis register both port=eth_in #pragma HLS INTERFACE axis register both port=data_out #pragma HLS INTERFACE axis register both port=addr_in #pragma HLS INTERFACE axis register both port=addr_out #pragma HLS INTERFACE ap_none register port=in_run #pragma HLS INTERFACE ap_none register port=in_cancel #pragma HLS INTERFACE ap_none register port=out_idle #pragma HLS INTERFACE ap_none register port=mode #pragma HLS INTERFACE ap_none register port=energy_kev #pragma HLS INTERFACE ap_none register port=nframes #pragma HLS INTERFACE ap_none register port=nmodules #pragma HLS INTERFACE ap_none register port=nstorage_cells #pragma HLS INTERFACE ap_none register port=nsummation #pragma HLS INTERFACE ap_none register port=sqrtmult #pragma HLS INTERFACE ap_none register port=pxlthreshold_min #pragma HLS INTERFACE ap_none register port=pxlthreshold_max #pragma HLS INTERFACE ap_none register port=data_collection_state #pragma HLS PIPELINE II=1 style=flp packet_512_t packet_in; packet_512_t packet_out; axis_addr addr; static rcv_state_t rcv_state = RCV_WAIT_FOR_START; #pragma HLS RESET variable=rcv_state switch (rcv_state) { case RCV_WAIT_FOR_START: if (in_run.read() == 1) { rcv_state = RCV_WAIT_FOR_START_LOW; out_idle = 0; } else if (!addr_in.empty()) { addr_in.read(); rcv_state = RCV_FLUSH_IDLE; out_idle = 1; } else out_idle = 1; break; case RCV_FLUSH_IDLE: eth_in >> packet_in; if (packet_in.last) { out_idle = 1; rcv_state = RCV_WAIT_FOR_START; } break; case RCV_WAIT_FOR_START_LOW: out_idle = 0; if (in_run.read() == 0) rcv_state = RCV_START; break; case RCV_START: out_idle = 0; packet_out.data = 0; ACT_REG_MODE(packet_out.data) = mode; ACT_REG_ENERGY_KEV_FLOAT(packet_out.data) = energy_kev; ACT_REG_NFRAMES(packet_out.data) = nframes; ACT_REG_NMODULES(packet_out.data) = nmodules; ACT_REG_NSTORAGE_CELLS(packet_out.data) = nstorage_cells + 1; ACT_REG_NSUMMATION(packet_out.data) = nsummation; ACT_REG_SQRTMULT(packet_out.data) = sqrtmult; ACT_REG_THRESHOLD_MIN(packet_out.data) = pxlthreshold_min; ACT_REG_THRESHOLD_MAX(packet_out.data) = pxlthreshold_max; packet_out.user = 0; packet_out.last = 1; packet_out.dest = 0; packet_out.id = 1; data_out << packet_out; rcv_state = RCV_INIT; break; case RCV_INIT: out_idle = 0; if (in_cancel.read() == 1) rcv_state = RCV_LAST; else if (!addr_in.empty()) { addr_in >> addr; if (addr.frame_number >= nframes - 1 + DELAY_FRAMES_STOP_AND_QUIT) rcv_state = RCV_FLUSH; else { addr_out << addr; rcv_state = RCV_GOOD; } } break; case RCV_GOOD: out_idle = 0; eth_in >> packet_in; packet_in.user = 0; packet_in.id = 0; data_out << packet_in; if (packet_in.last) rcv_state = RCV_INIT; break; case RCV_IGNORE: out_idle = 0; eth_in >> packet_in; if (packet_in.last) rcv_state = RCV_INIT; break; case RCV_FLUSH: out_idle = 0; eth_in >> packet_in; if (packet_in.last) rcv_state = RCV_LAST; break; case RCV_LAST: out_idle = 0; addr.last = 1; addr_out << addr; // Finish data collection packet_out.data = 0; packet_out.dest = 0; packet_out.id = 1; // Special packet packet_out.last = 1; packet_out.user = 1; data_out << packet_out; rcv_state = RCV_WAIT_FOR_START; break; } data_collection_state = rcv_state; }