4 // LS-Byte is sent first, MS-Byte is second
6 // K0.0 000-00000 Error detected
7 // K31.7 111-11111 Loss of input signal
11 // K28.1 001-11100 Alternate COMMA?
15 // K28.5 101-11100 Standard COMMA?
17 // K28.7 111-11100 Bad COMMA?
24 #(parameter FIFOSIZE = 9)
34 output [31:0] wr_dat_o,
35 output [3:0] wr_flags_o,
39 output [15:0] fifo_space,
40 output xon_rcvd, output xoff_rcvd,
42 output [15:0] fifo_occupied, output fifo_full, output fifo_empty,
43 output reg serdes_link_up,
47 localparam K_COMMA = 8'b101_11100; // 0xBC K28.5
48 localparam K_IDLE = 8'b001_11100; // 0x3C K28.1
49 localparam K_PKT_START = 8'b110_11100; // 0xDC K28.6
50 localparam K_PKT_END = 8'b100_11100; // 0x9C K28.4
51 localparam K_XON = 8'b010_11100; // 0x5C K28.2
52 localparam K_XOFF = 8'b011_11100; // 0x7C K28.3
53 localparam K_LOS = 8'b111_11111; // 0xFF K31.7
54 localparam K_ERROR = 8'b000_00000; // 0x00 K00.0
55 localparam D_56 = 8'b110_00101; // 0xC5 D05.6
57 localparam IDLE = 3'd0;
58 localparam FIRSTLINE1 = 3'd1;
59 localparam FIRSTLINE2 = 3'd2;
60 localparam PKT1 = 3'd3;
61 localparam PKT2 = 3'd4;
62 localparam CRC_CHECK = 3'd5;
63 localparam ERROR = 3'd6;
64 localparam DONE = 3'd7;
66 wire [17:0] even_data;
68 wire [17:0] chosen_data;
72 reg sop_i, eop_i, error_i;
73 wire error_o, sop_o, eop_o, write, read, empty, full;
85 oneshot_2clk rst_1s(.clk_in(clk),.in(rst),.clk_out(ser_rx_clk),.out(rst_rxclk));
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),
93 assign even_data = {ser_rkmsb,ser_rklsb,ser_r};
95 always @(posedge ser_rx_clk)
99 holder <= {even_data[17],even_data[15:8]};
101 always @(posedge ser_rx_clk)
105 odd_data <= {even_data[16],holder[8],even_data[7:0],holder[7:0]};
107 assign chosen_data = odd ? odd_data : even_data;
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]} );
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));
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}) );
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;
130 always @(posedge ser_rx_clk)
147 if(even_data == {2'b11,K_PKT_START,K_PKT_START})
152 else if(odd_data == {2'b11,K_PKT_START,K_PKT_START})
160 if(chosen_data[17:16] == 0)
162 halfline <= chosen_data[15:0];
166 ; // Flow Controlled, so wait here and do nothing
171 if(chosen_data[17:16] == 0)
173 line_i <= {chosen_data[15:0],halfline};
174 if(full) // No space to write to! Should have been avoided by flow control
181 end // if (chosen_data[17:16] == 0)
183 ; // Flow Controlled, so wait here and do nothing
190 if(chosen_data[17:16] == 0)
192 halfline <= chosen_data[15:0];
197 else if(chosen_data == {2'b11,K_PKT_END,K_PKT_END})
204 if(chosen_data[17:16] == 0)
206 line_i <= {1'b0,1'b0,1'b0,chosen_data[15:0],halfline};
207 if(full) // No space to write to!
214 end // if (chosen_data[17:16] == 0)
221 if(chosen_data[17:0] == {2'b00,CRC})
248 endcase // case(state)
251 always @(posedge ser_rx_clk)
254 else if(state == IDLE)
256 else if(chosen_data[17:16] == 2'b00)
259 CRC16_D16 crc_blk(chosen_data[15:0],CRC,nextCRC);
261 always @(posedge ser_rx_clk)
262 if(rst_rxclk) write_d <= 0;
263 else write_d <= write_pre;
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));
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;
284 wire [FIFOSIZE-1:0] level;
285 fifo_2clock_casc #(.DWIDTH(35),.AWIDTH(FIFOSIZE)) serdes_rx_fifo
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;
298 wire [FIFOSIZE-1:0] level;
299 fifo_generator_v4_1 ser_rx_fifo
300 (.din({error_i,sop_i,eop_i,line_i}),
306 .dout({error_o,sop_o,eop_o,line_o}),
309 .rd_data_count(level),
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
319 // Internal FIFO to Buffer interface
320 assign read = wr_ready_i & wr_ready_o;
321 assign wr_ready_o = ~empty;
322 assign wr_dat_o = line_o;
323 assign wr_flags_o = { 2'b00, eop_o | error_o, sop_o | error_o };
325 wire slu = ~(({2'b11,K_ERROR,K_ERROR}=={ser_rkmsb,ser_rklsb,ser_r}) ||
326 ({2'b11,K_LOS,K_LOS}=={ser_rkmsb,ser_rklsb,ser_r}));
330 always @(posedge clk)
331 if(rst) slu_reg <= 0;
332 else slu_reg <= {slu_reg[2:0],slu};
334 always @(posedge clk)
335 serdes_link_up <= &slu_reg[3:1];
337 assign debug = { full, empty, odd, sop_i, eop_i, error_i, state[2:0] };
339 endmodule // serdes_rx