summaryrefslogtreecommitdiff
path: root/usrp/fpga/inband_lib/chan_fifo_reader.v
blob: a6edf2c60b6220f09622caa8345ba854e6e291c0 (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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
module chan_fifo_reader 
  ( reset, tx_clock, tx_strobe, adc_time, samples_format,
    fifodata, pkt_waiting, rdreq, skip, tx_q, tx_i,
    underrun, tx_empty, debug, rssi, threshhold, rssi_wait) ;

    input   wire                     reset ;
    input   wire                     tx_clock ;
    input   wire                     tx_strobe ; //signal to output tx_i and tx_q
    input   wire              [31:0] adc_time ; //current time
    input   wire               [3:0] samples_format ;// not useful at this point
    input   wire              [31:0] fifodata ; //the data input
    input   wire                     pkt_waiting ; //signal the next packet is ready
    output  reg                      rdreq ; //actually an ack to the current fifodata
    output  reg                      skip ; //finish reading current packet
    output  reg               [15:0] tx_q ; //top 16 bit output of fifodata
    output  reg               [15:0] tx_i ; //bottom 16 bit output of fifodata
    output  reg                      underrun ; 
    output  reg                      tx_empty ; //cause 0 to be the output
    input 	wire			  [31:0] rssi;
    input	wire			  [31:0] threshhold;
	input	wire			  [31:0] rssi_wait;

	output wire [14:0] debug;
	assign debug = {reader_state, trash, skip, timestamp[4:0], adc_time[4:0]};
    // Should not be needed if adc clock rate < tx clock rate
    // Used only to debug
    `define JITTER                   5
    
    //Samples format
    // 16 bits interleaved complex samples
    `define QI16                     4'b0
    
    // States
    parameter IDLE           =     3'd0;    
	parameter HEADER         =     3'd1;
    parameter TIMESTAMP      =     3'd2;
    parameter WAIT           =     3'd3;
    parameter WAITSTROBE     =     3'd4;
    parameter SEND           =     3'd5;

    // Header format
    `define PAYLOAD                  8:2
    `define ENDOFBURST               27
    `define STARTOFBURST            28
    `define RSSI_FLAG				 26
	

    /* State registers */
    reg                        [2:0] reader_state;
	/* Local registers */  
    reg                        [6:0] payload_len;
    reg                        [6:0] read_len;
    reg                       [31:0] timestamp;
    reg                              burst;
	reg								 trash;
	reg								 rssi_flag;
	reg						  [31:0] time_wait;
   
    always @(posedge tx_clock)
    begin
        if (reset) 
          begin
            reader_state <= IDLE;
            rdreq <= 0;
            skip <= 0;
            underrun <= 0;
            burst <= 0;
            tx_empty <= 1;
            tx_q <= 0;
            tx_i <= 0;
			trash <= 0;
			rssi_flag <= 0;
			time_wait <= 0;
         end
       else 
		   begin
           case (reader_state)
               IDLE:
               begin
				/*
				 * reset all the variables and wait for a tx_strobe
				 * it is assumed that the ram connected to this fifo_reader 
				 * is a short hand fifo meaning that the header to the next packet
				 * is already available to this fifo_reader when pkt_waiting is on
				 */
                   skip <=0;
				   time_wait <= 0;
                   if (pkt_waiting == 1)
                     begin
                        reader_state <= HEADER;
                        rdreq <= 1;
                        underrun <= 0;
                     end
                   if (burst == 1 && pkt_waiting == 0)
                        underrun <= 1;
                        
                   if (tx_strobe == 1)
                       tx_empty <= 1 ;
               end

				   /* Process header */
               HEADER:
               begin
                   if (tx_strobe == 1)
                       tx_empty <= 1 ;
                   
                   rssi_flag <= fifodata[`RSSI_FLAG]&fifodata[`STARTOFBURST];
                   //Check Start/End burst flag
                   if  (fifodata[`STARTOFBURST] == 1 
                       && fifodata[`ENDOFBURST] == 1)
                       burst <= 0;
                   else if (fifodata[`STARTOFBURST] == 1)
                       burst <= 1;
                   else if (fifodata[`ENDOFBURST] == 1)
                       burst <= 0;

					if (trash == 1 && fifodata[`STARTOFBURST] == 0)
					begin
						skip <= 1;
						reader_state <= IDLE;
						rdreq <= 0;
					end 
                    else
					begin   
                   		payload_len <= fifodata[`PAYLOAD] ;
                   		read_len <= 0;
                        rdreq <= 1;
						reader_state <= TIMESTAMP;
					end
               end

               TIMESTAMP: 
               begin
                   timestamp <= fifodata;
                   reader_state <= WAIT;
                   if (tx_strobe == 1)
                       tx_empty <= 1 ;
                   rdreq <= 0;
               end
				
				   // Decide if we wait, send or discard samples
               WAIT: 
               begin
                   if (tx_strobe == 1)
                       tx_empty <= 1 ;
                    
                   time_wait <= time_wait + 32'd1;
				   // Outdated
                   if ((timestamp < adc_time) ||
							(time_wait >= rssi_wait && rssi_wait != 0 && rssi_flag))
                     begin
						trash <= 1;
                        reader_state <= IDLE;
                        skip <= 1;
                     end  
                   // Let's send it					
                   else if ((timestamp <= adc_time + `JITTER 
                             && timestamp > adc_time)
                             || timestamp == 32'hFFFFFFFF)
					begin
						if (rssi <= threshhold || rssi_flag == 0)
						  begin
						    trash <= 0;
                            reader_state <= WAITSTROBE; 
                          end
						else
						    reader_state <= WAIT;
					end
				   else
						reader_state <= WAIT;
                   // Wait a little bit more
                   //else if (timestamp > adc_time + `JITTER)
                   //    reader_state <= WAIT;
               end
                 
               // Wait for the transmit chain to be ready
               WAITSTROBE:
               begin
                   // If end of payload...
                   if (read_len == payload_len)
                     begin
                       reader_state <= IDLE;
                       skip <= 1;
                       if (tx_strobe == 1)
                           tx_empty <= 1 ;
                     end  
                   else if (tx_strobe == 1)
                     begin
                       reader_state <= SEND;
                       rdreq <= 1;
                     end
               end
               
			   // Send the samples to the tx_chain
               SEND:
               begin
                   reader_state <= WAITSTROBE; 
                   read_len <= read_len + 7'd1;
                   tx_empty <= 0;
                   rdreq <= 0;
                   
                   case(samples_format)
                       `QI16:
                        begin
                            tx_i <= fifodata[15:0];
                            tx_q <= fifodata[31:16];
                        end
                        
                        // Assume 16 bits complex samples by default
                        default:
                        begin
                            tx_i <= fifodata[15:0];
                            tx_q <= fifodata[31:16];
                        end 
                   endcase
               end
               
               default:
               begin
					//error handling
                   reader_state <= IDLE;
               end
           endcase
       end
   end
 
endmodule