3 Commits

Author SHA1 Message Date
Josh Blum
7b1348ee97 fpga: bump compat minor, work on late flag 2015-07-22 20:05:19 -07:00
Josh Blum
63e2ee1967 fpga: implement fifo control tracking info
* detect loss host to device, and device to host
* warn on near fifo capacity
* added time wait flag (replaces tsf for waiting)
* added skip late flag (implementation TODO)
2015-07-22 18:14:04 -07:00
Josh Blum
89394c9a58 fpga: larger long fifo with 64 entries 2015-07-22 13:01:10 -07:00
4 changed files with 106 additions and 22 deletions

View File

@@ -22,7 +22,8 @@ module settings_fifo_ctrl
parameter XPORT_HDR = 1, //extra transport hdr line
parameter PROT_DEST = 0, //protocol framer destination
parameter PROT_HDR = 1, //needs a protocol header?
parameter ACK_SID = 0 //stream ID for packet ACK
parameter ACK_SID = 0, //stream ID for packet ACK
parameter DEPTH = 6 //size of fifo in addr bit width
)
(
//clock and synchronous reset for all interfaces
@@ -75,16 +76,17 @@ module settings_fifo_ctrl
wire [63:0] in_command_ticks, out_command_ticks;
wire [31:0] in_command_hdr, out_command_hdr;
wire [31:0] in_command_data, out_command_data;
wire in_command_has_time, out_command_has_time;
wire command_fifo_full, command_fifo_empty;
wire command_fifo_read, command_fifo_write;
wire [15:0] command_fifo_occupied;
shortfifo #(.WIDTH(129)) command_fifo (
longfifo #(.WIDTH(128), .SIZE(DEPTH)) command_fifo (
.clk(clock), .rst(reset), .clear(clear),
.datain({in_command_ticks, in_command_hdr, in_command_data, in_command_has_time}),
.dataout({out_command_ticks, out_command_hdr, out_command_data, out_command_has_time}),
.datain({in_command_ticks, in_command_hdr, in_command_data}),
.dataout({out_command_ticks, out_command_hdr, out_command_data}),
.write(command_fifo_write), .full(command_fifo_full), //input interface
.empty(command_fifo_empty), .read(command_fifo_read) //output interface
.empty(command_fifo_empty), .read(command_fifo_read), //output interface
.occupied(command_fifo_occupied)
);
//------------------------------------------------------------------
@@ -95,13 +97,15 @@ module settings_fifo_ctrl
wire [31:0] in_result_data, out_result_data;
wire result_fifo_full, result_fifo_empty;
wire result_fifo_read, result_fifo_write;
wire [15:0] result_fifo_occupied;
shortfifo #(.WIDTH(64)) result_fifo (
longfifo #(.WIDTH(64), .SIZE(DEPTH)) result_fifo (
.clk(clock), .rst(reset), .clear(clear),
.datain({in_result_hdr, in_result_data}),
.dataout({out_result_hdr, out_result_data}),
.write(result_fifo_write), .full(result_fifo_full), //input interface
.empty(result_fifo_empty), .read(result_fifo_read) //output interface
.empty(result_fifo_empty), .read(result_fifo_read), //output interface
.occupied(result_fifo_occupied)
);
//------------------------------------------------------------------
@@ -139,7 +143,6 @@ module settings_fifo_ctrl
assign in_command_ticks = in_ticks_reg;
assign in_command_data = in_data_reg;
assign in_command_hdr = in_hdr_reg;
assign in_command_has_time = has_tsf_reg;
always @(posedge clock) begin
if (reset) begin
@@ -244,18 +247,24 @@ module settings_fifo_ctrl
always @(posedge clock)
vita_time_reg <= vita_time;
wire late;
wire late, now;
`ifndef FIFO_CTRL_NO_TIME
time_compare time_compare(
.time_now(vita_time_reg), .trigger_time(command_ticks_reg), .late(late));
.time_now(vita_time_reg), .trigger_time(command_ticks_reg), .late(late), .now(now));
`else
assign late = 1;
assign now = 1;
`endif
//these config flags are available only in the LOAD_CMD state (where we wait)
wire time_wait = out_command_hdr[9];
wire skip_late = out_command_hdr[10]; //TODO (implement)
reg cmd_was_late;
//action occurs in the event state and when there is fifo space (should always be true)
//the third condition is that all peripherals in the perfs signal are ready/active high
//the fourth condition is that is an event time has been set, action is delayed until that time
wire time_ready = (out_command_has_time)? late : 1;
wire time_ready = (time_wait)? (late || now) : 1;
wire action = (cmd_state == EVENT_CMD) && ~result_fifo_full && perfs_ready && time_ready;
assign command_fifo_read = action;
@@ -275,6 +284,7 @@ module settings_fifo_ctrl
command_ticks_reg <= out_command_ticks;
command_hdr_reg <= out_command_hdr;
command_data_reg <= out_command_data;
cmd_was_late <= late; //TODO do something with
end
EVENT_CMD: begin // poking and peeking happens here!
@@ -332,11 +342,14 @@ module settings_fifo_ctrl
localparam WRITE_VRT_SID = 2;
localparam WRITE_RB_HDR = 3;
localparam WRITE_RB_DATA = 4;
localparam WRITE_RB_DATA2 = 5;
localparam WRITE_RB_DATA3 = 6;
//the state for the start of packet condition
localparam WRITE_PKT_HDR = (PROT_HDR)? WRITE_PROT_HDR : WRITE_VRT_HDR;
reg [2:0] out_state;
reg [31:0] last_result_hdr;
assign out_valid = ~result_fifo_empty;
assign result_fifo_read = out_data[33] && writing;
@@ -344,9 +357,11 @@ module settings_fifo_ctrl
always @(posedge clock) begin
if (reset) begin
out_state <= WRITE_PKT_HDR;
last_result_hdr <= 32'b0;
end
else if (writing && out_data[33]) begin
out_state <= WRITE_PKT_HDR;
last_result_hdr <= out_result_hdr;
end
else if (writing) begin
out_state <= out_state + 1;
@@ -357,7 +372,7 @@ module settings_fifo_ctrl
//-- assign to output fifo interface
//------------------------------------------------------------------
wire [31:0] prot_hdr;
assign prot_hdr[15:0] = 16; //bytes in proceeding vita packet
assign prot_hdr[15:0] = 24; //bytes in proceeding vita packet
assign prot_hdr[16] = 1; //yes frame
assign prot_hdr[18:17] = PROT_DEST;
assign prot_hdr[31:19] = 0; //nothing
@@ -370,12 +385,14 @@ module settings_fifo_ctrl
WRITE_VRT_SID: out_data_int <= ACK_SID;
WRITE_RB_HDR: out_data_int <= out_result_hdr;
WRITE_RB_DATA: out_data_int <= out_result_data;
WRITE_RB_DATA2: out_data_int <= last_result_hdr;
WRITE_RB_DATA3: out_data_int <= {result_fifo_occupied, command_fifo_occupied};
default: out_data_int <= 0;
endcase //state
end
assign out_data[35:34] = 2'b0;
assign out_data[33] = (out_state == WRITE_RB_DATA);
assign out_data[33] = (out_state == WRITE_RB_DATA3);
assign out_data[32] = (out_state == WRITE_PKT_HDR);
assign out_data[31:0] = out_data_int;
@@ -389,7 +406,7 @@ module settings_fifo_ctrl
command_fifo_empty, command_fifo_full, //2
command_fifo_read, command_fifo_write, //2
addr, //8
strobe_reg, strobe, poke, out_command_has_time //4
strobe_reg, strobe, poke, time_wait //4
};
endmodule //settings_fifo_ctrl

View File

@@ -448,7 +448,7 @@ module umtrx_core
// Buffer Pool Status -- Slave #5
//compatibility number -> increment when the fpga has been sufficiently altered
localparam compat_num = {16'd9, 16'd1}; //major, minor
localparam compat_num = {16'd9, 16'd2}; //major, minor
wire [31:0] irq_readback = {16'b0, aux_ld2, aux_ld1, button, spi_ready, 12'b0};

View File

@@ -29,11 +29,16 @@
using namespace uhd;
using namespace uhd::transport;
//command policy flags
static const size_t POKE32_CMD = (1 << 8);
static const size_t PEEK32_CMD = 0;
static const size_t PEEK32_CMD = 0; //no flag set
static const size_t TIME_WAIT_CMD = (1 << 9);
static const size_t SKIP_LATE_CMD = (1 << 10);
static const double ACK_TIMEOUT = 0.5;
static const double MASSIVE_TIMEOUT = 10.0; //for when we wait on a timed command
static const boost::uint32_t MAX_SEQS_OUT = 15;
static const boost::uint32_t FIFO_DEPTH = 64;
static const boost::uint32_t MAX_SEQS_OUT = FIFO_DEPTH-1;
#define SPI_DIV SR_SPI_CORE + 0
#define SPI_CTRL SR_SPI_CORE + 1
@@ -50,6 +55,12 @@ public:
_window_size(std::min(window_size, MAX_SEQS_OUT)),
_seq_out(0),
_seq_ack(0),
_prev_recv_seq(0),
_total_recv_packets(0),
_start_of_burst(false),
_skip_late(false),
_use_time(false),
_tick_rate(1.0),
_timeout(ACK_TIMEOUT)
{
UHD_MSG(status) << "fifo_ctrl.window_size = " << _window_size << std::endl;
@@ -155,6 +166,7 @@ public:
_time = time;
_use_time = _time != uhd::time_spec_t(0.0);
if (_use_time) _timeout = MASSIVE_TIMEOUT; //permanently sets larger timeout
_start_of_burst = true;
}
void set_tick_rate(const double rate){
@@ -162,6 +174,11 @@ public:
_tick_rate = rate;
}
void set_late_policy(const bool skip_late)
{
_skip_late = skip_late;
}
private:
/*******************************************************************
@@ -184,7 +201,8 @@ private:
packet_info.packet_count = _seq_out;
packet_info.sid = _sid;
packet_info.tsf = _time.to_ticks(_tick_rate);
packet_info.sob = false;
packet_info.sob = _start_of_burst;
_start_of_burst = false; //only set once by set time, then cleared
packet_info.eob = false;
packet_info.has_sid = true;
packet_info.has_cid = false;
@@ -195,6 +213,10 @@ private:
//load header
vrt::if_hdr_pack_be(pkt, packet_info);
//time command flags
if (_skip_late) cmd |= SKIP_LATE_CMD;
if (_use_time) cmd |= TIME_WAIT_CMD;
//load payload
const boost::uint32_t ctrl_word = (addr & 0xff) | cmd | (_seq_out << 16);
pkt[packet_info.num_header_words32+0] = htonl(ctrl_word);
@@ -221,10 +243,50 @@ private:
vrt::if_packet_info_t packet_info;
packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t);
vrt::if_hdr_unpack_be(pkt, packet_info);
_seq_ack = ntohl(pkt[packet_info.num_header_words32+0]) >> 16;
if (_seq_ack == seq_to_ack){
return ntohl(pkt[packet_info.num_header_words32+1]);
//extract the payloads
const boost::int32_t header = ntohl(pkt[packet_info.num_header_words32+0]);
const boost::int32_t rb_data = ntohl(pkt[packet_info.num_header_words32+1]);
const boost::int32_t last_header = ntohl(pkt[packet_info.num_header_words32+2]);
const boost::int32_t fifo_occupied = ntohl(pkt[packet_info.num_header_words32+3]);
const boost::uint16_t this_seq = header >> 16;
const boost::uint16_t last_seq = last_header >> 16;
const boost::uint16_t result_fifo_occupied = fifo_occupied >> 16;
const boost::uint16_t command_fifo_occupied = fifo_occupied & 0xffff;
//check if we lost packets from device -> host
const boost::uint16_t next_recv_seq = _prev_recv_seq+1;
if (next_recv_seq != this_seq)
{
UHD_MSG(error) << boost::format(
"Detected packet loss from device to host:\n"
"Host expected sequence 0x%x, but got 0x%x"
) % next_recv_seq % this_seq << std::endl;
}
//check if we lost packets from host -> device
if (_total_recv_packets != 0 and _prev_recv_seq != last_seq)
{
UHD_MSG(error) << boost::format(
"Detected packet loss from host to device:\n"
"Device expected last sequence 0x%x, but saw 0x%x"
) % _prev_recv_seq % last_seq << std::endl;
}
if (result_fifo_occupied > FIFO_DEPTH/2 or command_fifo_occupied > FIFO_DEPTH/2)
{
UHD_MSG(warning) << boost::format(
"FIFOs are past half capacity!\n"
"Command FIFO occupancy: %d/%d\n"
"Result FIFO occupancy: %d/%d"
) % command_fifo_occupied % FIFO_DEPTH % result_fifo_occupied % FIFO_DEPTH << std::endl;
}
//store state for next recv iteration
_total_recv_packets++;
_prev_recv_seq = this_seq;
_seq_ack = this_seq;
if (_seq_ack == seq_to_ack) return rb_data;
}
return 0;
@@ -236,7 +298,12 @@ private:
boost::mutex _mutex;
boost::uint16_t _seq_out;
boost::uint16_t _seq_ack;
boost::uint16_t _prev_recv_seq;
boost::uint16_t _next_recv_seq;
boost::uint64_t _total_recv_packets;
uhd::time_spec_t _time;
bool _start_of_burst;
bool _skip_late;
bool _use_time;
double _tick_rate;
double _timeout;

Binary file not shown.