aboutsummaryrefslogtreecommitdiffstats
path: root/inband_lib/chan_fifo_reader.v
blob: 2b3178da71606fb1a614167d89f55ba7ea453ff2 (plain)
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