Refactored how the usrp2/firmware connects into the top-level built.
[debian/gnuradio] / usrp2 / fpga / serdes / serdes_rx.v
1
2 // SERDES Interface
3
4 // LS-Byte is sent first, MS-Byte is second
5 // Invalid K Codes
6 //  K0.0  000-00000  Error detected
7 //  K31.7 111-11111  Loss of input signal
8
9 // Valid K Codes
10 //  K28.0 000-11100
11 //  K28.1 001-11100  Alternate COMMA?
12 //  K28.2 010-11100
13 //  K28.3 011-11100
14 //  K28.4 100-11100
15 //  K28.5 101-11100  Standard COMMA?
16 //  K28.6 110-11100
17 //  K28.7 111-11100  Bad COMMA?
18 //  K23.7 111-10111
19 //  K27.7 111-11011
20 //  K29.7 111-11101
21 //  K30.7 111-11110
22
23 module serdes_rx
24   #(parameter FIFOSIZE = 9)
25     (input clk,
26      input rst,
27      
28      // RX HW Interface
29      input ser_rx_clk,
30      input [15:0] ser_r,
31      input ser_rklsb,
32      input ser_rkmsb,
33      
34      output [31:0] wr_dat_o,
35      output wr_write_o,
36      output wr_done_o,
37      output wr_error_o,
38      input wr_ready_i,
39      input wr_full_i,
40
41      output [15:0] fifo_space,
42      output xon_rcvd, output xoff_rcvd,
43
44      output [15:0] fifo_occupied, output fifo_full, output fifo_empty,
45      output [31:0] debug
46      );
47
48    localparam K_COMMA = 8'b101_11100;     // 0xBC K28.5
49    localparam K_IDLE = 8'b001_11100;      // 0x3C K28.1
50    localparam K_PKT_START = 8'b110_11100; // 0xDC K28.6
51    localparam K_PKT_END = 8'b100_11100;   // 0x9C K28.4
52    localparam K_XON = 8'b010_11100;       // 0x5C K28.2
53    localparam K_XOFF = 8'b011_11100;      // 0x7C K28.3
54    localparam K_LOS = 8'b111_11111;       // 0xFF K31.7
55    localparam K_ERROR = 8'b000_00000;     // 0x00 K00.0
56    localparam D_56 = 8'b110_00101;        // 0xC5 D05.6
57    
58    localparam IDLE = 3'd0;
59    localparam FIRSTLINE1 = 3'd1;
60    localparam FIRSTLINE2 = 3'd2;
61    localparam PKT1 = 3'd3;
62    localparam PKT2 = 3'd4;
63    localparam CRC_CHECK = 3'd5;
64    localparam ERROR = 3'd6;
65    localparam DONE = 3'd7;
66    
67    wire [17:0] even_data;
68    reg [17:0]  odd_data;
69    wire [17:0] chosen_data;
70    reg         odd;
71    
72    reg [31:0]  line_i;
73    reg         sop_i, eop_i, error_i;
74    wire        error_o, sop_o, eop_o, write, read, empty, full;
75    reg [15:0]  halfline;
76    reg [8:0]   holder;
77    wire [31:0] line_o;
78    
79    reg [2:0]   state;
80
81    reg [15:0]  CRC;
82    wire [15:0] nextCRC;
83    reg         write_d;
84
85    oneshot_2clk rst_1s(.clk_in(clk),.in(rst),.clk_out(ser_rx_clk),.out(rst_rxclk));
86
87    /*
88    ss_rcvr #(.WIDTH(18)) ss_rcvr
89      (.rxclk(ser_rx_clk),.sysclk(clk),.rst(rst),
90       .data_in({ser_rkmsb,ser_rklsb,ser_r}),.data_out(even_data),
91       .clock_present());
92    */
93    assign      even_data = {ser_rkmsb,ser_rklsb,ser_r};
94    
95    always @(posedge ser_rx_clk)
96      if(rst_rxclk)
97        holder <= 9'd0;
98      else
99        holder <= {even_data[17],even_data[15:8]};
100    
101    always @(posedge ser_rx_clk)
102      if(rst_rxclk)
103        odd_data <= 18'd0;
104      else
105        odd_data <= {even_data[16],holder[8],even_data[7:0],holder[7:0]};
106    
107    assign      chosen_data = odd ? odd_data : even_data;
108
109    // Transfer xon and xoff info to the main system clock for flow control purposes
110    reg         xon_rcvd_rxclk, xoff_rcvd_rxclk;
111    always @(posedge ser_rx_clk)
112      xon_rcvd_rxclk = ({1'b1,K_XON} == {ser_rkmsb,ser_r[15:8]}) | ({1'b1,K_XON} == {ser_rklsb,ser_r[7:0]} );
113    always @(posedge ser_rx_clk)
114      xoff_rcvd_rxclk = ({1'b1,K_XOFF} == {ser_rkmsb,ser_r[15:8]}) | ({1'b1,K_XOFF} == {ser_rklsb,ser_r[7:0]} );
115    
116    oneshot_2clk xon_1s(.clk_in(ser_rx_clk),.in(xon_rcvd_rxclk),.clk_out(clk),.out(xon_rcvd));
117    oneshot_2clk xoff_1s(.clk_in(ser_rx_clk),.in(xoff_rcvd_rxclk),.clk_out(clk),.out(xoff_rcvd));
118
119    // If the other side is sending xon or xoff, or is flow controlled (b/c we told them to be), don't fill the fifos
120    wire        wait_here = ((chosen_data == {2'b10,K_COMMA,D_56})||
121                             (chosen_data == {2'b11,K_XON,K_XON})||
122                             (chosen_data == {2'b11,K_XOFF,K_XOFF}) );
123
124    always @(posedge ser_rx_clk)
125      if(rst_rxclk) sop_i <= 0;
126      else if(state == FIRSTLINE1) sop_i <= 1;
127      else if(write_d) sop_i <= 0;
128    
129    reg         write_pre;
130    always @(posedge ser_rx_clk)
131      if(rst_rxclk)
132        begin
133           state <= IDLE;
134           odd <= 0;
135           halfline <= 0;
136           line_i <= 0;
137           eop_i <= 0;
138           error_i <= 0;
139           write_pre <= 0;
140        end
141      else
142        case(state)
143          IDLE :
144            begin
145               error_i <= 0;
146               write_pre <= 0;
147               if(even_data == {2'b11,K_PKT_START,K_PKT_START})
148                 begin
149                    state <= FIRSTLINE1;
150                    odd <= 0;
151                 end
152               else if(odd_data == {2'b11,K_PKT_START,K_PKT_START})
153                 begin
154                    state <= FIRSTLINE1;
155                    odd <= 1;
156                 end
157            end
158
159          FIRSTLINE1 :
160            if(chosen_data[17:16] == 0)
161              begin
162                 halfline <= chosen_data[15:0];
163                 state <= FIRSTLINE2;
164              end
165            else if(wait_here)
166              ;  // Flow Controlled, so wait here and do nothing
167            else
168              state <= ERROR;
169
170          FIRSTLINE2 :
171            if(chosen_data[17:16] == 0)
172              begin
173                 line_i <= {chosen_data[15:0],halfline};
174                 if(full)  // No space to write to!  Should have been avoided by flow control
175                   state <= ERROR;
176                 else
177                   begin
178                      state <= PKT1;
179                      write_pre <= 1;
180                   end
181              end // if (chosen_data[17:16] == 0)
182            else if(wait_here)
183              ;  // Flow Controlled, so wait here and do nothing
184            else
185              state <= ERROR;
186          
187          PKT1 :
188            begin
189               write_pre <= 0;
190               if(chosen_data[17:16] == 0)
191                 begin
192                    halfline <= chosen_data[15:0];
193                    state <= PKT2;
194                 end
195               else if(wait_here)
196                 ;  // Flow Controlled
197               else if(chosen_data == {2'b11,K_PKT_END,K_PKT_END})
198                 state <= CRC_CHECK;
199               else
200                 state <= ERROR;
201            end // case: PKT1
202          
203          PKT2 :
204            if(chosen_data[17:16] == 0)
205              begin
206                 line_i <= {1'b0,1'b0,1'b0,chosen_data[15:0],halfline};
207                 if(full)  // No space to write to!
208                   state <= ERROR;
209                 else
210                   begin
211                      state <= PKT1;
212                      write_pre <= 1;
213                   end
214              end // if (chosen_data[17:16] == 0)
215            else if(wait_here)
216              ;  // Flow Controlled
217            else
218              state <= ERROR;
219            
220          CRC_CHECK :
221            if(chosen_data[17:0] == {2'b00,CRC})
222              begin
223                 if(full)
224                   state <= ERROR;
225                 else
226                   begin
227                      eop_i <= 1;
228                      state <= DONE;
229                   end
230              end
231            else if(wait_here)
232              ;
233            else
234              state <= ERROR;
235          
236          ERROR :
237            begin
238               error_i <= 1;
239               if(~full)
240                 state <= IDLE;
241            end
242          DONE :
243            begin
244               state <= IDLE;
245               eop_i <= 0;
246            end
247               
248        endcase // case(state)
249    
250    
251    always @(posedge ser_rx_clk)
252      if(rst_rxclk)
253        CRC <= 16'hFFFF;
254      else if(state == IDLE)
255        CRC <= 16'hFFFF;
256      else if(chosen_data[17:16] == 2'b00)
257        CRC <= nextCRC;
258
259    CRC16_D16 crc_blk(chosen_data[15:0],CRC,nextCRC);
260
261    always @(posedge ser_rx_clk)
262      if(rst_rxclk) write_d <= 0;
263      else write_d <= write_pre;
264
265    // Internal FIFO, size 9 is 2K, size 10 is 4K Bytes
266    assign write = eop_i | (error_i & ~full) | (write_d & (state != CRC_CHECK));
267
268
269 //`define CASC 1
270 `define MYFIFO 1   
271 //`define XILFIFO 1
272
273 `ifdef CASC   
274    cascadefifo2 #(.WIDTH(35),.SIZE(FIFOSIZE)) serdes_rx_fifo
275      (.clk(clk),.rst(rst),.clear(0),
276       .datain({error_i,sop_i,eop_i,line_i}), .write(write), .full(full),
277       .dataout({error_o,sop_o,eop_o,line_o}), .read(read), .empty(empty),
278       .space(fifo_space),.occupied(fifo_occupied) );
279    assign fifo_full = full;
280    assign fifo_empty = empty;
281 `endif
282
283 `ifdef MYFIFO
284    wire [FIFOSIZE-1:0] level;
285     fifo_2clock_casc #(.DWIDTH(35),.AWIDTH(FIFOSIZE)) serdes_rx_fifo
286      (.arst(rst),
287       .wclk(ser_rx_clk),.datain({error_i,sop_i,eop_i,line_i}), .write(write), .full(full),
288       .rclk(clk),.dataout({error_o,sop_o,eop_o,line_o}), .read(read), .empty(empty),
289       .level_rclk(level) );
290    assign              fifo_space = {{(16-FIFOSIZE){1'b0}},{FIFOSIZE{1'b1}}} - 
291                        {{(16-FIFOSIZE){1'b0}},level};
292    assign              fifo_occupied = { {(16-FIFOSIZE){1'b0}} ,level};
293    assign              fifo_full = full;   // Note -- fifo_full is in the wrong clock domain
294    assign              fifo_empty = empty;
295 `endif
296
297 `ifdef XILFIFO
298    wire [FIFOSIZE-1:0] level;
299    fifo_generator_v4_1 ser_rx_fifo
300      (.din({error_i,sop_i,eop_i,line_i}),
301       .rd_clk(clk),
302       .rd_en(read),
303       .rst(rst),
304       .wr_clk(ser_rx_clk),
305       .wr_en(write),
306       .dout({error_o,sop_o,eop_o,line_o}),
307       .empty(empty),
308       .full(full),
309       .rd_data_count(level),
310       .wr_data_count() );
311    assign              fifo_space = {{(16-FIFOSIZE){1'b0}},{FIFOSIZE{1'b1}}} - 
312                        {{(16-FIFOSIZE){1'b0}},level};
313    assign              fifo_occupied = { {(16-FIFOSIZE){1'b0}}, level };
314    assign              fifo_full = full;   // Note -- fifo_full is in the wrong clock domain
315    assign              fifo_empty = empty;
316 `endif //  `ifdef XILFIFO
317    
318    
319    // Internal FIFO to Buffer interface
320    reg         xfer_active;
321
322    always @(posedge clk)
323      if(rst)
324        xfer_active <= 0;
325      else if(xfer_active & ~empty & (eop_o | wr_full_i | error_o))
326        xfer_active <= 0;
327      else if(wr_ready_i & sop_o)
328        xfer_active <= 1;
329
330    assign      read = (xfer_active | ~sop_o) & ~empty;
331
332    assign      wr_write_o = xfer_active & ~empty;
333    assign      wr_done_o = eop_o & ~empty & xfer_active;
334    //assign      wr_error_o = xfer_active & ((wr_full_i & ~eop_o & ~empty)|error_o);
335    assign      wr_error_o = xfer_active & ~empty & error_o;
336
337    assign      wr_dat_o = line_o;
338
339    /*
340    assign debug = { { fifo_space[15:8] },
341                     { fifo_space[7:0] },
342                     { 2'd0, error_i, sop_i, eop_i, error_o, sop_o, eop_o },
343                     { full, empty, write, read, xfer_active, state[2:0] } };
344
345    assign      debug = { { xoff_rcvd,xon_rcvd,sop_i,eop_i,error_i,state[2:0] },
346                          { odd, wait_here, write_pre, write_d, write, full, chosen_data[17:16]},
347                          { chosen_data[15:8] },
348                          { chosen_data[7:0] } };
349    */
350
351    assign      debug = { full, empty, odd, xfer_active, sop_i, eop_i, error_i, state[2:0] };
352    
353 endmodule // serdes_rx