146 lines
4.7 KiB
C++
146 lines
4.7 KiB
C++
// Copyright (2019-2023) Paul Scherrer Institute
|
|
|
|
|
|
#include "hls_jfjoch.h"
|
|
|
|
void data_collection_fsm(AXI_STREAM ð_in,
|
|
STREAM_512 &data_out,
|
|
hls::stream<axis_addr> &addr_in,
|
|
hls::stream<axis_addr> &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> one_over_energy,
|
|
ap_uint<32> nframes,
|
|
ap_uint<8> nmodules,
|
|
ap_uint<4> nstorage_cells,
|
|
ap_uint<32> hbm_size_bytes) {
|
|
#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=one_over_energy
|
|
#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=hbm_size_bytes
|
|
|
|
#pragma HLS PIPELINE II=1 style=flp
|
|
|
|
packet_512_t packet_in;
|
|
packet_512_t packet_out;
|
|
axis_addr addr;
|
|
|
|
enum rcv_state_t {RCV_WAIT_FOR_START = 0, RCV_WAIT_FOR_START_LOW = 1, RCV_START = 2, RCV_INIT = 3, RCV_GOOD = 4,
|
|
RCV_FLUSH = 5, RCV_LAST = 6, RCV_FLUSH_IDLE = 7, RCV_IGNORE = 8};
|
|
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_ONE_OVER_ENERGY(packet_out.data) = one_over_energy;
|
|
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_HBM_SIZE_256b(packet_out.data) = hbm_size_bytes / 32;
|
|
|
|
packet_out.user = 0;
|
|
packet_out.last = 0;
|
|
packet_out.dest = 0;
|
|
packet_out.id = 1;
|
|
data_out << packet_out;
|
|
|
|
addr.last = 0;
|
|
addr_out << addr;
|
|
|
|
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 + 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;
|
|
}
|
|
}
|
|
|