libusrp/fpga/inband_lib/chan_fifo_reader.v

197 lines
6.1 KiB
Verilog
Executable File

module chan_fifo_reader
( input reset,
input tx_clock,
input tx_strobe,
input [31:0]adc_clock,
input [3:0] samples_format,
input [15:0] fifodata,
input pkt_waiting,
output reg rdreq,
output reg skip,
output reg [15:0]tx_q,
output reg [15:0]tx_i,
output reg overrun,
output reg underrun) ;
// Should not be needed if adc clock rate < tx clock rate
`define JITTER 5
//Samples format
// 16 bits interleaved complex samples
`define QI16 4'b0
// States
`define IDLE 4'd0
`define READ 4'd1
`define HEADER1 4'd2
`define HEADER2 4'd3
`define TIMESTAMP1 4'd4
`define TIMESTAMP2 4'd5
`define WAIT 4'd6
`define WAITSTROBE 4'd7
`define SENDWAIT 4'd8
`define SEND 4'd9
`define FEED 4'd10
`define DISCARD 4'd11
// State registers
reg[3:0] reader_state;
reg[3:0] reader_next_state;
//Variables
reg[8:0] payload_len;
reg[8:0] read_len;
reg[31:0] timestamp;
reg burst;
reg qsample;
always @(posedge tx_clock)
begin
if (reset)
begin
reader_state <= `IDLE;
reader_next_state <= `IDLE;
rdreq <= 0;
skip <= 0;
overrun <= 0;
underrun <= 0;
burst <= 0;
qsample <= 1;
end
else
begin
reader_state = reader_next_state;
case (reader_state)
`IDLE:
begin
if (pkt_waiting == 1)
begin
reader_next_state <= `READ;
rdreq <= 1;
underrun <= 0;
end
else if (burst == 1)
underrun <= 1;
end
// Just wait for the fifo data to arrive
`READ:
begin
reader_next_state <= `HEADER1;
end
// First part of the header
`HEADER1:
begin
reader_next_state <= `HEADER2;
//Check Start burst flag
if (fifodata[3] == 1)
burst <= 1;
if (fifodata[4] == 1)
burst <= 0;
end
// Read payload length
`HEADER2:
begin
payload_len <= (fifodata & 16'h1FF);
read_len <= 9'd0;
reader_next_state <= `TIMESTAMP1;
end
`TIMESTAMP1:
begin
timestamp <= {fifodata, 16'b0};
rdreq <= 0;
reader_next_state <= `TIMESTAMP2;
end
`TIMESTAMP2:
begin
timestamp <= timestamp + fifodata;
reader_next_state <= `WAIT;
end
// Decide if we wait, send or discard samples
`WAIT:
begin
// Wait a little bit more
if (timestamp > adc_clock + `JITTER)
reader_next_state <= `WAIT;
// Let's send it
else if ((timestamp < adc_clock + `JITTER
&& timestamp > adc_clock)
|| timestamp == 32'hFFFFFFFF)
begin
reader_next_state <= `WAITSTROBE;
end
// Outdated
else if (timestamp < adc_clock)
begin
reader_next_state <= `DISCARD;
skip <= 1;
end
end
// Wait for the transmit chain to be ready
`WAITSTROBE:
begin
// If end of payload...
if (read_len == payload_len)
begin
reader_next_state <= `DISCARD;
skip <= (payload_len < 508);
end
if (tx_strobe == 1)
reader_next_state <= `SENDWAIT;
end
`SENDWAIT:
begin
rdreq <= 1;
reader_next_state <= `SEND;
end
// Send the samples to the tx_chain
`SEND:
begin
reader_next_state <= `WAITSTROBE;
rdreq <= 0;
read_len <= read_len + 2;
case(samples_format)
`QI16:
begin
tx_q <= qsample ? fifodata : 16'bZ;
tx_i <= ~qsample ? fifodata : 16'bZ;
qsample <= ~ qsample;
end
default:
begin
// Assume 16 bits complex samples by default
$display ("Error unknown samples format");
tx_q <= qsample ? fifodata : 16'bZ;
tx_i <= ~qsample ? fifodata : 16'bZ;
qsample <= ~ qsample;
end
endcase
end
`DISCARD:
begin
skip <= 0;
reader_next_state <= `IDLE;
end
default:
begin
$display ("Error unknown state");
reader_state <= `IDLE;
reader_next_state <= `IDLE;
end
endcase
end
end
endmodule