1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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
|