vt52-fpga  1.0.0 Initial
vt52-fpga is a serial terminal implemented on a FPGA
usb_serial_ctrl_ep.v
Go to the documentation of this file.
1 module usb_serial_ctrl_ep #(
2  parameter MAX_IN_PACKET_SIZE = 32,
3  parameter MAX_OUT_PACKET_SIZE = 32
4 ) (
5  input clk,
6  input reset,
7  output [6:0] dev_addr,
8 
9  ////////////////////
10  // out endpoint interface
11  ////////////////////
12  output out_ep_req,
13  input out_ep_grant,
14  input out_ep_data_avail,
15  input out_ep_setup,
16  output out_ep_data_get,
17  input [7:0] out_ep_data,
18  output out_ep_stall,
19  input out_ep_acked,
20 
21 
22  ////////////////////
23  // in endpoint interface
24  ////////////////////
25  output in_ep_req,
26  input in_ep_grant,
27  input in_ep_data_free,
28  output in_ep_data_put,
29  output reg [7:0] in_ep_data = 0,
30  output in_ep_data_done,
31  output reg in_ep_stall,
32  input in_ep_acked
33 );
34 
35 
36  localparam IDLE = 0;
37  localparam SETUP = 1;
38  localparam DATA_IN = 2;
39  localparam DATA_OUT = 3;
40  localparam STATUS_IN = 4;
41  localparam STATUS_OUT = 5;
42 
43  reg [5:0] ctrl_xfr_state = IDLE;
44  reg [5:0] ctrl_xfr_state_next;
45 
46 
47 
48  reg setup_stage_end = 0;
49  reg data_stage_end = 0;
50  reg status_stage_end = 0;
51  reg send_zero_length_data_pkt = 0;
52 
53 
54 
55  // the default control endpoint gets assigned the device address
56  reg [6:0] dev_addr_i = 0;
57  assign dev_addr = dev_addr_i;
58 
59  assign out_ep_req = out_ep_data_avail;
60  assign out_ep_data_get = out_ep_data_avail;
61  reg out_ep_data_valid = 0;
62  always @(posedge clk) out_ep_data_valid <= out_ep_data_avail && out_ep_grant;
63 
64  // need to record the setup data
65  reg [3:0] setup_data_addr = 0;
66  reg [9:0] raw_setup_data [7:0];
67 
68  wire [7:0] bmRequestType = raw_setup_data[0];
69  wire [7:0] bRequest = raw_setup_data[1];
70  wire [15:0] wValue = {raw_setup_data[3][7:0], raw_setup_data[2][7:0]};
71  wire [15:0] wIndex = {raw_setup_data[5][7:0], raw_setup_data[4][7:0]};
72  wire [15:0] wLength = {raw_setup_data[7][7:0], raw_setup_data[6][7:0]};
73 
74  // keep track of new out data start and end
75  wire pkt_start;
76  wire pkt_end;
77 
78  rising_edge_detector detect_pkt_start (
79  .clk(clk),
80  .in(out_ep_data_avail),
81  .out(pkt_start)
82  );
83 
84  falling_edge_detector detect_pkt_end (
85  .clk(clk),
86  .in(out_ep_data_avail),
87  .out(pkt_end)
88  );
89 
90  assign out_ep_stall = 1'b0;
91 
92  wire setup_pkt_start = pkt_start && out_ep_setup;
93 
94  // wire has_data_stage = wLength != 16'b0000000000000000; // this version for some reason causes a 16b carry which is slow
95  wire has_data_stage = |wLength;
96 
97  wire out_data_stage;
98  assign out_data_stage = has_data_stage && !bmRequestType[7];
99 
100  wire in_data_stage;
101  assign in_data_stage = has_data_stage && bmRequestType[7];
102 
103  reg [7:0] bytes_sent = 0;
104  reg [6:0] rom_length = 0;
105 
106  wire wLength_is_large = |wLength[15:7]; // 15-7 bits because rom_length is only 7 bits wide
107 
108  wire all_data_sent =
109  (bytes_sent >= rom_length) ||
110  (!wLength_is_large && bytes_sent >= wLength[7:0]); // if the requested wLength is large, we only send rom_length bytes
111 
112  wire more_data_to_send =
113  !all_data_sent;
114 
115  wire in_data_transfer_done;
116 
117  rising_edge_detector detect_in_data_transfer_done (
118  .clk(clk),
119  .in(all_data_sent),
120  .out(in_data_transfer_done)
121  );
122 
123  assign in_ep_data_done = (in_data_transfer_done && ctrl_xfr_state == DATA_IN) || send_zero_length_data_pkt;
124 
125  assign in_ep_req = ctrl_xfr_state == DATA_IN && more_data_to_send;
126  assign in_ep_data_put = ctrl_xfr_state == DATA_IN && more_data_to_send && in_ep_data_free;
127 
128 
129  reg [6:0] rom_addr = 0;
130 
131  reg save_dev_addr = 0;
132  reg [6:0] new_dev_addr = 0;
133 
134  ////////////////////////////////////////////////////////////////////////////////
135  // control transfer state machine
136  ////////////////////////////////////////////////////////////////////////////////
137 
138 
139  always @* begin
140  setup_stage_end <= 0;
141  data_stage_end <= 0;
142  status_stage_end <= 0;
143  send_zero_length_data_pkt <= 0;
144 
145  case (ctrl_xfr_state)
146  IDLE : begin
147  if (setup_pkt_start) begin
148  ctrl_xfr_state_next <= SETUP;
149  end else begin
150  ctrl_xfr_state_next <= IDLE;
151  end
152  end
153 
154  SETUP : begin
155  if (pkt_end) begin
156  setup_stage_end <= 1;
157 
158  if (in_data_stage) begin
159  ctrl_xfr_state_next <= DATA_IN;
160 
161  end else if (out_data_stage) begin
162  ctrl_xfr_state_next <= DATA_OUT;
163 
164  end else begin
165  ctrl_xfr_state_next <= STATUS_IN;
166  send_zero_length_data_pkt <= 1;
167  end
168 
169  end else begin
170  ctrl_xfr_state_next <= SETUP;
171  end
172  end
173 
174  DATA_IN : begin
175  if (in_ep_stall) begin
176  ctrl_xfr_state_next <= IDLE;
177  data_stage_end <= 1;
178  status_stage_end <= 1;
179 
180  end else if (in_ep_acked && all_data_sent) begin
181  ctrl_xfr_state_next <= STATUS_OUT;
182  data_stage_end <= 1;
183 
184  end else begin
185  ctrl_xfr_state_next <= DATA_IN;
186  end
187  end
188 
189  DATA_OUT : begin
190  if (out_ep_acked) begin
191  ctrl_xfr_state_next <= STATUS_IN;
192  send_zero_length_data_pkt <= 1;
193  data_stage_end <= 1;
194 
195  end else begin
196  ctrl_xfr_state_next <= DATA_OUT;
197  end
198  end
199 
200  STATUS_IN : begin
201  if (in_ep_acked) begin
202  ctrl_xfr_state_next <= IDLE;
203  status_stage_end <= 1;
204 
205  end else begin
206  ctrl_xfr_state_next <= STATUS_IN;
207  end
208  end
209 
210  STATUS_OUT: begin
211  if (out_ep_acked) begin
212  ctrl_xfr_state_next <= IDLE;
213  status_stage_end <= 1;
214 
215  end else begin
216  ctrl_xfr_state_next <= STATUS_OUT;
217  end
218  end
219 
220  default begin
221  ctrl_xfr_state_next <= IDLE;
222  end
223  endcase
224  end
225 
226  always @(posedge clk) begin
227  if (reset) begin
228  ctrl_xfr_state <= IDLE;
229  end else begin
230  ctrl_xfr_state <= ctrl_xfr_state_next;
231  end
232  end
233 
234  always @(posedge clk) begin
235  in_ep_stall <= 0;
236 
237  if (out_ep_setup && out_ep_data_valid) begin
238  raw_setup_data[setup_data_addr] <= out_ep_data;
239  setup_data_addr <= setup_data_addr + 1;
240  end
241 
242  if (setup_stage_end) begin
243  case (bRequest)
244  'h06 : begin
245  // GET_DESCRIPTOR
246  case (wValue[15:8])
247  1 : begin
248  // DEVICE
249  rom_addr <= 'h00;
250  rom_length <= 'h12;
251  end
252 
253  2 : begin
254  // CONFIGURATION
255  rom_addr <= 'h12;
256  rom_length <= 'h43;
257  end
258 
259  3 : begin
260  // STRING
261  in_ep_stall <= 1;
262  rom_addr <= 'h00;
263  rom_length <= 'h00;
264  end
265 
266  6 : begin
267  // DEVICE_QUALIFIER
268  in_ep_stall <= 1;
269  rom_addr <= 'h00;
270  rom_length <= 'h00;
271  end
272 
273  default : begin
274  // DEVICE_QUALIFIER
275  in_ep_stall <= 1;
276  rom_addr <= 'h00;
277  rom_length <= 'h00;
278  end
279 
280  endcase
281  end
282 
283  'h05 : begin
284  // SET_ADDRESS
285  rom_addr <= 'h00;
286  rom_length <= 'h00;
287 
288  // we need to save the address after the status stage ends
289  // this is because the status stage token will still be using
290  // the old device address
291  save_dev_addr <= 1;
292  new_dev_addr <= wValue[6:0];
293  end
294 
295  'h09 : begin
296  // SET_CONFIGURATION
297  rom_addr <= 'h00;
298  rom_length <= 'h00;
299  end
300 
301  'h20 : begin
302  // SET_LINE_CODING
303  rom_addr <= 'h00;
304  rom_length <= 'h00;
305  end
306 
307  'h21 : begin
308  // GET_LINE_CODING
309  rom_addr <= 'h55;
310  rom_length <= 'h07;
311  end
312 
313  'h22 : begin
314  // SET_CONTROL_LINE_STATE
315  rom_addr <= 'h00;
316  rom_length <= 'h00;
317  end
318 
319  'h23 : begin
320  // SEND_BREAK
321  rom_addr <= 'h00;
322  rom_length <= 'h00;
323  end
324 
325  default begin
326  rom_addr <= 'h00;
327  rom_length <= 'h00;
328  end
329  endcase
330  end
331 
332  if (ctrl_xfr_state == DATA_IN && more_data_to_send && in_ep_grant && in_ep_data_free) begin
333  rom_addr <= rom_addr + 1;
334  bytes_sent <= bytes_sent + 1;
335  end
336 
337  if (status_stage_end) begin
338  setup_data_addr <= 0;
339  bytes_sent <= 0;
340  rom_addr <= 0;
341  rom_length <= 0;
342 
343  if (save_dev_addr) begin
344  save_dev_addr <= 0;
345  dev_addr_i <= new_dev_addr;
346  end
347  end
348 
349  if (reset) begin
350  dev_addr_i <= 0;
351  setup_data_addr <= 0;
352  save_dev_addr <= 0;
353  end
354  end
355 
356 
357  `define CDC_ACM_ENDPOINT 2
358  `define CDC_RX_ENDPOINT 1
359  `define CDC_TX_ENDPOINT 1
360 
361 
362  always @* begin
363  case (rom_addr)
364  // device descriptor
365  'h000 : in_ep_data <= 18; // bLength
366  'h001 : in_ep_data <= 1; // bDescriptorType
367  'h002 : in_ep_data <= 'h00; // bcdUSB[0]
368  'h003 : in_ep_data <= 'h02; // bcdUSB[1]
369  'h004 : in_ep_data <= 'h02; // bDeviceClass (Communications Device Class)
370  'h005 : in_ep_data <= 'h00; // bDeviceSubClass (Abstract Control Model)
371  'h006 : in_ep_data <= 'h00; // bDeviceProtocol (No class specific protocol required)
372  'h007 : in_ep_data <= MAX_IN_PACKET_SIZE; // bMaxPacketSize0
373 
374  'h008 : in_ep_data <= 'h50; // idVendor[0] http://wiki.openmoko.org/wiki/USB_Product_IDs
375  'h009 : in_ep_data <= 'h1d; // idVendor[1]
376  'h00A : in_ep_data <= 'h30; // idProduct[0]
377  'h00B : in_ep_data <= 'h61; // idProduct[1]
378 
379  'h00C : in_ep_data <= 0; // bcdDevice[0]
380  'h00D : in_ep_data <= 0; // bcdDevice[1]
381  'h00E : in_ep_data <= 0; // iManufacturer
382  'h00F : in_ep_data <= 0; // iProduct
383  'h010 : in_ep_data <= 0; // iSerialNumber
384  'h011 : in_ep_data <= 1; // bNumConfigurations
385 
386  // configuration descriptor
387  'h012 : in_ep_data <= 9; // bLength
388  'h013 : in_ep_data <= 2; // bDescriptorType
389  'h014 : in_ep_data <= (9+9+5+5+4+5+7+9+7+7); // wTotalLength[0]
390  'h015 : in_ep_data <= 0; // wTotalLength[1]
391  'h016 : in_ep_data <= 2; // bNumInterfaces
392  'h017 : in_ep_data <= 1; // bConfigurationValue
393  'h018 : in_ep_data <= 0; // iConfiguration
394  'h019 : in_ep_data <= 'hC0; // bmAttributes
395  'h01A : in_ep_data <= 50; // bMaxPower
396 
397  // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
398  'h01B : in_ep_data <= 9; // bLength
399  'h01C : in_ep_data <= 4; // bDescriptorType
400  'h01D : in_ep_data <= 0; // bInterfaceNumber
401  'h01E : in_ep_data <= 0; // bAlternateSetting
402  'h01F : in_ep_data <= 1; // bNumEndpoints
403  'h020 : in_ep_data <= 2; // bInterfaceClass (Communications Device Class)
404  'h021 : in_ep_data <= 2; // bInterfaceSubClass (Abstract Control Model)
405  'h022 : in_ep_data <= 0; // bInterfaceProtocol (0 = ?, 1 = AT Commands: V.250 etc)
406  'h023 : in_ep_data <= 0; // iInterface
407 
408  // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26
409  'h024 : in_ep_data <= 5; // bFunctionLength
410  'h025 : in_ep_data <= 'h24; // bDescriptorType
411  'h026 : in_ep_data <= 'h00; // bDescriptorSubtype
412  'h027 : in_ep_data <= 'h10;
413  'h028 : in_ep_data <= 'h01; // bcdCDC
414 
415  // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27
416  'h029 : in_ep_data <= 5; // bFunctionLength
417  'h02A : in_ep_data <= 'h24; // bDescriptorType
418  'h02B : in_ep_data <= 'h01; // bDescriptorSubtype
419  'h02C : in_ep_data <= 'h00; // bmCapabilities
420  'h02D : in_ep_data <= 1; // bDataInterface
421 
422  // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28
423  'h02E : in_ep_data <= 4; // bFunctionLength
424  'h02F : in_ep_data <= 'h24; // bDescriptorType
425  'h030 : in_ep_data <= 'h02; // bDescriptorSubtype
426  'h031 : in_ep_data <= 'h06; // bmCapabilities
427 
428  // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33
429  'h032 : in_ep_data <= 5; // bFunctionLength
430  'h033 : in_ep_data <= 'h24; // bDescriptorType
431  'h034 : in_ep_data <= 'h06; // bDescriptorSubtype
432  'h035 : in_ep_data <= 0; // bMasterInterface
433  'h036 : in_ep_data <= 1; // bSlaveInterface0
434 
435  // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
436  'h037 : in_ep_data <= 7; // bLength
437  'h038 : in_ep_data <= 5; // bDescriptorType
438  'h039 : in_ep_data <= `CDC_ACM_ENDPOINT | 'h80; // bEndpointAddress
439  'h03A : in_ep_data <= 'h03; // bmAttributes (0x03=intr)
440  'h03B : in_ep_data <= 8; // wMaxPacketSize[0]
441  'h03C : in_ep_data <= 0; // wMaxPacketSize[1]
442  'h03D : in_ep_data <= 64; // bInterval
443 
444  // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
445  'h03E : in_ep_data <= 9; // bLength
446  'h03F : in_ep_data <= 4; // bDescriptorType
447  'h040 : in_ep_data <= 1; // bInterfaceNumber
448  'h041 : in_ep_data <= 0; // bAlternateSetting
449  'h042 : in_ep_data <= 2; // bNumEndpoints
450  'h043 : in_ep_data <= 'h0A; // bInterfaceClass
451  'h044 : in_ep_data <= 'h00; // bInterfaceSubClass
452  'h045 : in_ep_data <= 'h00; // bInterfaceProtocol
453  'h046 : in_ep_data <= 0; // iInterface
454 
455  // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
456  'h047 : in_ep_data <= 7; // bLength
457  'h048 : in_ep_data <= 5; // bDescriptorType
458  'h049 : in_ep_data <= `CDC_RX_ENDPOINT; // bEndpointAddress
459  'h04A : in_ep_data <= 'h02; // bmAttributes (0x02=bulk)
460  'h04B : in_ep_data <= MAX_IN_PACKET_SIZE; // wMaxPacketSize[0]
461  'h04C : in_ep_data <= 0; // wMaxPacketSize[1]
462  'h04D : in_ep_data <= 0; // bInterval
463 
464  // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
465  'h04E : in_ep_data <= 7; // bLength
466  'h04F : in_ep_data <= 5; // bDescriptorType
467  'h050 : in_ep_data <= `CDC_TX_ENDPOINT | 'h80; // bEndpointAddress
468  'h051 : in_ep_data <= 'h02; // bmAttributes (0x02=bulk)
469 
470  'h052 : in_ep_data <= MAX_OUT_PACKET_SIZE; // wMaxPacketSize[0]
471  'h053 : in_ep_data <= 0; // wMaxPacketSize[1]
472  'h054 : in_ep_data <= 0; // bInterval
473 
474  // LINE_CODING
475  'h055 : in_ep_data <= 'h80; // dwDTERate[0]
476  'h056 : in_ep_data <= 'h25; // dwDTERate[1]
477  'h057 : in_ep_data <= 'h00; // dwDTERate[2]
478  'h058 : in_ep_data <= 'h00; // dwDTERate[3]
479  'h059 : in_ep_data <= 1; // bCharFormat (1 stop bit)
480  'h05A : in_ep_data <= 0; // bParityType (None)
481  'h05B : in_ep_data <= 8; // bDataBits (8 bits)
482 
483  default begin
484  in_ep_data <= 0;
485  end
486  endcase
487  end
488 
489 endmodule
module falling_edge_detector(input clk, input in, output out)
Definition: edge_detect.v:15
module usb_serial_ctrl_ep(input clk, input reset, output[7] dev_addr, output out_ep_req, input out_ep_grant, input out_ep_data_avail, input out_ep_setup, output out_ep_data_get, input[8] out_ep_data, output out_ep_stall, input out_ep_acked, output in_ep_req, input in_ep_grant, input in_ep_data_free, output in_ep_data_put, output reg< 7:0 > in_ep_data=0, output in_ep_data_done, output reg in_ep_stall, input in_ep_acked)
module rising_edge_detector(input clk, input in, output out)
Definition: edge_detect.v:1
always(posedge clk)
Definition: uart_rx.v:86
#define CDC_RX_ENDPOINT
#define CDC_TX_ENDPOINT