diff options
Diffstat (limited to 'usrp/fpga/inband_lib/chan_fifo_reader.v')
-rwxr-xr-x | usrp/fpga/inband_lib/chan_fifo_reader.v | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/usrp/fpga/inband_lib/chan_fifo_reader.v b/usrp/fpga/inband_lib/chan_fifo_reader.v new file mode 100755 index 000000000..2b3178da7 --- /dev/null +++ b/usrp/fpga/inband_lib/chan_fifo_reader.v @@ -0,0 +1,197 @@ +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
\ No newline at end of file |