vt52-fpga  1.0.0 Initial
vt52-fpga is a serial terminal implemented on a FPGA
usb_fs_rx.v
Go to the documentation of this file.
1 module usb_fs_rx (
2  // A 48MHz clock is required to recover the clock from the incoming data.
3  input clk_48mhz,
4  input reset,
5 
6  // USB data+ and data- lines.
7  input dp,
8  input dn,
9 
10  // pulse on every bit transition.
11  output bit_strobe,
12 
13  // Pulse on beginning of new packet.
14  output pkt_start,
15 
16  // Pulse on end of current packet.
17  output pkt_end,
18 
19  // Most recent packet decoded.
20  output [3:0] pid,
21  output reg [6:0] addr = 0,
22  output reg [3:0] endp = 0,
23  output reg [10:0] frame_num = 0,
24 
25  // Pulse on valid data on rx_data.
26  output rx_data_put,
27  output [7:0] rx_data,
28 
29  // Most recent packet passes PID and CRC checks
30  output valid_packet
31 );
32  wire clk = clk_48mhz;
33 
34  ////////////////////////////////////////////////////////////////////////////////
35  ////////////////////////////////////////////////////////////////////////////////
36  ////////
37  //////// usb receive path
38  ////////
39  ////////////////////////////////////////////////////////////////////////////////
40  ////////////////////////////////////////////////////////////////////////////////
41 
42 
43  ////////////////////////////////////////////////////////////////////////////////
44  // double flop for metastability
45  /*
46  all asynchronous inputs into the RTL need to be double-flopped to protect
47  against metastable scenarios. if the RTL clock samples an asynchronous signal
48  at the same time the signal is transitioning the result is undefined. flopping
49  the signal twice ensures it will be either 1 or 0 and nothing in between.
50  */
51 
52  reg [3:0] dpair_q = 0;
53 
54  always @(posedge clk) begin
55  dpair_q[3:0] <= {dpair_q[1:0], dp, dn};
56  end
57 
58 
59  ////////////////////////////////////////////////////////////////////////////////
60  // line state recovery state machine
61  /*
62  the recieve path doesn't currently use a differential reciever. because of
63  this there is a chance that one of the differential pairs will appear to have
64  changed to the new state while the other is still in the old state. the
65  following state machine detects transitions and waits an extra sampling clock
66  before decoding the state on the differential pair. this transition period
67  will only ever last for one clock as long as there is no noise on the line.
68  if there is enough noise on the line then the data may be corrupted and the
69  packet will fail the data integrity checks.
70  */
71 
72  reg [2:0] line_state = 0;
73  localparam DT = 3'b100;
74  localparam DJ = 3'b010;
75  localparam DK = 3'b001;
76  localparam SE0 = 3'b000;
77  localparam SE1 = 3'b011;
78 
79  wire [1:0] dpair = dpair_q[3:2];
80 
81  always @(posedge clk) begin
82  case (line_state)
83  // if we are in a transition state, then we can sample the pair and
84  // move to the next corresponding line state
85  DT : begin
86  case (dpair)
87  2'b10 : line_state <= DJ;
88  2'b01 : line_state <= DK;
89  2'b00 : line_state <= SE0;
90  2'b11 : line_state <= SE1;
91  endcase
92  end
93 
94  // if we are in a valid line state and the value of the pair changes,
95  // then we need to move to the transition state
96  DJ : if (dpair != 2'b10) line_state <= DT;
97  DK : if (dpair != 2'b01) line_state <= DT;
98  SE0 : if (dpair != 2'b00) line_state <= DT;
99  SE1 : if (dpair != 2'b11) line_state <= DT;
100 
101  // if we are in an invalid state we should move to the transition state
102  default : line_state <= DT;
103  endcase
104  end
105 
106 
107  ////////////////////////////////////////////////////////////////////////////////
108  // clock recovery
109  /*
110  the DT state from the line state recovery state machine is used to align to
111  transmit clock. the line state is sampled in the middle of the bit time.
112 
113  example of signal relationships
114  -------------------------------
115  line_state DT DJ DJ DJ DT DK DK DK DK DK DK DT DJ DJ DJ
116  line_state_valid ________----____________----____________----________----____
117  bit_phase 0 0 1 2 3 0 1 2 3 0 1 2 0 1 2
118  */
119 
120  reg [1:0] bit_phase = 0;
121 
122  wire line_state_valid = (bit_phase == 1);
123  assign bit_strobe = (bit_phase == 2);
124 
125  always @(posedge clk) begin
126  // keep track of phase within each bit
127  if (line_state == DT) begin
128  bit_phase <= 0;
129 
130  end else begin
131  bit_phase <= bit_phase + 1;
132  end
133  end
134 
135 
136  ////////////////////////////////////////////////////////////////////////////////
137  // packet detection
138  /*
139  usb uses a sync to denote the beginning of a packet and two single-ended-0 to
140  denote the end of a packet. this state machine recognizes the beginning and
141  end of packets for subsequent layers to process.
142  */
143  reg [5:0] line_history = 0;
144  reg packet_valid = 0;
145  reg next_packet_valid;
146  wire packet_start = next_packet_valid && !packet_valid;
147  wire packet_end = !next_packet_valid && packet_valid;
148 
149  always @* begin
150  if (line_state_valid) begin
151  // check for packet start: KJKJKK
152  if (!packet_valid && line_history[5:0] == 6'b100101) begin
153  next_packet_valid <= 1;
154  end
155 
156  // check for packet end: SE0 SE0
157  else if (packet_valid && line_history[3:0] == 4'b0000) begin
158  next_packet_valid <= 0;
159 
160  end else begin
161  next_packet_valid <= packet_valid;
162  end
163  end else begin
164  next_packet_valid <= packet_valid;
165  end
166  end
167 
168  always @(posedge clk) begin
169  if (reset) begin
170  line_history <= 6'b101010;
171  packet_valid <= 0;
172  end else begin
173  // keep a history of the last two states on the line
174  if (line_state_valid) begin
175  line_history[5:0] <= {line_history[3:0], line_state[1:0]};
176  end
177  end
178  packet_valid <= next_packet_valid;
179  end
180 
181 
182  ////////////////////////////////////////////////////////////////////////////////
183  // NRZI decode
184  /*
185  in order to ensure there are enough bit transitions for a receiver to recover
186  the clock usb uses NRZI encoding.
187 
188  https://en.wikipedia.org/wiki/Non-return-to-zero
189  */
190  reg dvalid_raw;
191  reg din;
192 
193  always @* begin
194  case (line_history[3:0])
195  4'b0101 : din <= 1;
196  4'b0110 : din <= 0;
197  4'b1001 : din <= 0;
198  4'b1010 : din <= 1;
199  default : din <= 0;
200  endcase
201 
202  if (packet_valid && line_state_valid) begin
203  case (line_history[3:0])
204  4'b0101 : dvalid_raw <= 1;
205  4'b0110 : dvalid_raw <= 1;
206  4'b1001 : dvalid_raw <= 1;
207  4'b1010 : dvalid_raw <= 1;
208  default : dvalid_raw <= 0;
209  endcase
210  end else begin
211  dvalid_raw <= 0;
212  end
213  end
214 
215  reg [5:0] bitstuff_history = 0;
216 
217  always @(posedge clk) begin
218  if (reset || packet_end) begin
219  bitstuff_history <= 6'b000000;
220  end else begin
221  if (dvalid_raw) begin
222  bitstuff_history <= {bitstuff_history[4:0], din};
223  end
224  end
225  end
226 
227  wire dvalid = dvalid_raw && !(bitstuff_history == 6'b111111);
228 
229 
230  ////////////////////////////////////////////////////////////////////////////////
231  // save and check pid
232  /*
233  shift in the entire 8-bit pid with an additional 9th bit used as a sentinal.
234  */
235 
236  reg [8:0] full_pid = 0;
237  wire pid_valid = full_pid[4:1] == ~full_pid[8:5];
238  wire pid_complete = full_pid[0];
239 
240  always @(posedge clk) begin
241  if (packet_start) begin
242  full_pid <= 9'b100000000;
243  end
244 
245  if (dvalid && !pid_complete) begin
246  full_pid <= {din, full_pid[8:1]};
247  end
248  end
249 
250 
251  ////////////////////////////////////////////////////////////////////////////////
252  // check crc5
253  reg [4:0] crc5 = 0;
254  wire crc5_valid = crc5 == 5'b01100;
255  wire crc5_invert = din ^ crc5[4];
256  always @(posedge clk) begin
257  if (packet_start) begin
258  crc5 <= 5'b11111;
259  end
260 
261  if (dvalid && pid_complete) begin
262  crc5[4] <= crc5[3];
263  crc5[3] <= crc5[2];
264  crc5[2] <= crc5[1] ^ crc5_invert;
265  crc5[1] <= crc5[0];
266  crc5[0] <= crc5_invert;
267  end
268  end
269 
270 
271  ////////////////////////////////////////////////////////////////////////////////
272  // check crc16
273  reg [15:0] crc16 = 0;
274  wire crc16_valid = crc16 == 16'b1000000000001101;
275  wire crc16_invert = din ^ crc16[15];
276 
277  always @(posedge clk) begin
278  if (packet_start) begin
279  crc16 <= 16'b1111111111111111;
280  end
281 
282  if (dvalid && pid_complete) begin
283  crc16[15] <= crc16[14] ^ crc16_invert;
284  crc16[14] <= crc16[13];
285  crc16[13] <= crc16[12];
286  crc16[12] <= crc16[11];
287  crc16[11] <= crc16[10];
288  crc16[10] <= crc16[9];
289  crc16[9] <= crc16[8];
290  crc16[8] <= crc16[7];
291  crc16[7] <= crc16[6];
292  crc16[6] <= crc16[5];
293  crc16[5] <= crc16[4];
294  crc16[4] <= crc16[3];
295  crc16[3] <= crc16[2];
296  crc16[2] <= crc16[1] ^ crc16_invert;
297  crc16[1] <= crc16[0];
298  crc16[0] <= crc16_invert;
299  end
300  end
301 
302 
303  ////////////////////////////////////////////////////////////////////////////////
304  // output control signals
305  wire pkt_is_token = full_pid[2:1] == 2'b01;
306  wire pkt_is_data = full_pid[2:1] == 2'b11;
307  wire pkt_is_handshake = full_pid[2:1] == 2'b10;
308 
309 
310  // TODO: need to check for data packet babble
311  // TODO: do i need to check for bitstuff error?
312  assign valid_packet = pid_valid && (
313  (pkt_is_handshake) ||
314  (pkt_is_data && crc16_valid) ||
315  (pkt_is_token && crc5_valid)
316  );
317 
318 
319  reg [11:0] token_payload = 0;
320  wire token_payload_done = token_payload[0];
321 
322  always @(posedge clk) begin
323  if (packet_start) begin
324  token_payload <= 12'b100000000000;
325  end
326 
327  if (dvalid && pid_complete && pkt_is_token && !token_payload_done) begin
328  token_payload <= {din, token_payload[11:1]};
329  end
330  end
331 
332  always @(posedge clk) begin
333  if (token_payload_done && pkt_is_token) begin
334  addr <= token_payload[7:1];
335  endp <= token_payload[11:8];
336  frame_num <= token_payload[11:1];
337  end
338  end
339 
340  assign pkt_start = packet_start;
341  assign pkt_end = packet_end;
342  assign pid = full_pid[4:1];
343  //assign addr = token_payload[7:1];
344  //assign endp = token_payload[11:8];
345  //assign frame_num = token_payload[11:1];
346 
347 
348  ////////////////////////////////////////////////////////////////////////////////
349  // deserialize and output data
350  //assign rx_data_put = dvalid && pid_complete && pkt_is_data;
351  reg [8:0] rx_data_buffer = 0;
352  wire rx_data_buffer_full = rx_data_buffer[0];
353  assign rx_data_put = rx_data_buffer_full;
354  assign rx_data = rx_data_buffer[8:1];
355 
356  always @(posedge clk) begin
357  if (packet_start || rx_data_buffer_full) begin
358  rx_data_buffer <= 9'b100000000;
359  end
360 
361  if (dvalid && pid_complete && pkt_is_data) begin
362  rx_data_buffer <= {din, rx_data_buffer[8:1]};
363  end
364  end
365 
366 endmodule // usb_fs_rx
module usb_fs_rx(input clk_48mhz, input reset, input dp, input dn, output bit_strobe, output pkt_start, output pkt_end, output[4] pid, output reg< 6:0 > addr=0, output reg< 3:0 > endp=0, output reg< 10:0 > frame_num=0, output rx_data_put, output[8] rx_data, output valid_packet)
Definition: usb_fs_rx.v:1
always(posedge clk)
Definition: uart_rx.v:86