hw/ip/usbdev/rtl/usbdev.sv Cov: 100%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // USB Full-Speed Device Interface (usbdev).
6: //
7: //
8:
9:
10: module usbdev (
11: input logic clk_i,
12: input logic rst_ni,
13: input logic clk_usb_48mhz_i, // use usb_ prefix for signals in this clk
14: input logic rst_usb_ni, // async reset, with relase sync to clk_usb_48_mhz_i
15:
16: // Register interface
17: input tlul_pkg::tl_h2d_t tl_i,
18: output tlul_pkg::tl_d2h_t tl_o,
19:
20: // USB Interface
21: input logic cio_usb_d_i,
22: input logic cio_usb_dp_i,
23: input logic cio_usb_dn_i,
24:
25: output logic cio_usb_d_o,
26: output logic cio_usb_se0_o,
27: output logic cio_usb_dp_o,
28: output logic cio_usb_dn_o,
29: output logic cio_usb_oe_o,
30:
31: output logic cio_usb_tx_mode_se_o,
32: input logic cio_usb_sense_i,
33: output logic cio_usb_pullup_en_o,
34: output logic cio_usb_suspend_o,
35:
36: // Interrupts
37: output logic intr_pkt_received_o, // Packet received
38: output logic intr_pkt_sent_o, // Packet sent
39: output logic intr_connected_o,
40: output logic intr_disconnected_o,
41: output logic intr_host_lost_o,
42: output logic intr_link_reset_o,
43: output logic intr_link_suspend_o,
44: output logic intr_link_resume_o,
45: output logic intr_av_empty_o,
46: output logic intr_rx_full_o,
47: output logic intr_av_overflow_o,
48: output logic intr_link_in_err_o,
49: output logic intr_rx_crc_err_o,
50: output logic intr_rx_pid_err_o,
51: output logic intr_rx_bitstuff_err_o,
52: output logic intr_frame_o
53: );
54:
55: import usbdev_reg_pkg::*;
56:
57: // Could make SramDepth, MaxPktSizeByte, AVFifoDepth and RXFifoDepth
58: // module parameters but may need to fix register def for the first two
59: localparam int SramDw = 32; // Places packing bytes to SRAM assume this
60: localparam int SramDepth = 512; // 2kB, SRAM Width is DW
61: localparam int MaxPktSizeByte = 64;
62:
63: localparam int SramAw = $clog2(SramDepth);
64: localparam int SizeWidth = $clog2(MaxPktSizeByte);
65: localparam int NBuf = (SramDepth * SramDw) / (MaxPktSizeByte * 8);
66: localparam int NBufWidth = $clog2(NBuf);
67:
68: // AV fifo just stores buffer numbers
69: localparam int AVFifoWidth = NBufWidth;
70: localparam int AVFifoDepth = 4;
71:
72: // RX fifo stores buf# + size(0-MaxPktSizeByte) + EP# + Type
73: localparam int RXFifoWidth = NBufWidth + (1+SizeWidth) + 4 + 1;
74: localparam int RXFifoDepth = 4;
75:
76: // Number of endpoints
77: localparam int NEndpoints = usbdev_reg_pkg::NEndpoints;
78:
79: usbdev_reg2hw_t reg2hw;
80: usbdev_hw2reg_t hw2reg;
81:
82: tlul_pkg::tl_h2d_t tl_sram_h2d [1];
83: tlul_pkg::tl_d2h_t tl_sram_d2h [1];
84:
85: // Dual-port SRAM Interface: Refer prim_ram_2p_wrapper.sv
86: logic mem_a_req;
87: logic mem_a_write;
88: logic [SramAw-1:0] mem_a_addr;
89: logic [SramDw-1:0] mem_a_wdata;
90: logic mem_a_rvalid;
91: logic [SramDw-1:0] mem_a_rdata;
92: logic [1:0] mem_a_rerror;
93:
94: logic usb_mem_b_req;
95: logic usb_mem_b_write;
96: logic [SramAw-1:0] usb_mem_b_addr;
97: logic [SramDw-1:0] usb_mem_b_wdata;
98: logic [SramDw-1:0] usb_mem_b_rdata;
99:
100: logic usb_clr_devaddr;
101: logic usb_event_av_empty, event_av_overflow, usb_event_rx_full;
102: logic event_av_empty, event_rx_full;
103: logic usb_event_link_reset, usb_event_link_suspend, usb_event_link_resume;
104: logic usb_event_host_lost, usb_event_disconnect, usb_event_connect;
105: logic usb_event_rx_crc_err, usb_event_rx_pid_err;
106: logic usb_event_rx_bitstuff_err;
107: logic usb_event_in_err;
108: logic usb_event_frame;
109:
110: logic event_link_reset, event_link_suspend, event_link_resume;
111: logic event_host_lost, event_disconnect, event_connect;
112: logic event_rx_crc_err, event_rx_pid_err;
113: logic event_rx_bitstuff_err;
114: logic event_in_err;
115: logic event_frame;
116:
117: // CDC signals
118: logic [10:0] usb_frame;
119: logic [2:0] usb_link_state;
120: logic usb_enable;
121: logic [6:0] usb_device_addr;
122:
123: logic usb_data_toggle_clear_en;
124: logic [NEndpoints-1:0] usb_data_toggle_clear;
125:
126:
127: /////////////////////////////////
128: // USB IO after CDC & muxing //
129: /////////////////////////////////
130: logic usb_rx_d;
131: logic usb_rx_se0;
132: logic usb_tx_d;
133: logic usb_tx_se0;
134: logic usb_tx_oe;
135: logic usb_pwr_sense;
136: logic usb_pullup_en;
137:
138: /////////////////////////////
139: // Receive interface fifos //
140: /////////////////////////////
141:
142: logic av_fifo_wready;
143: logic event_pkt_received;
144: logic usb_av_rvalid, usb_av_rready;
145: logic usb_rx_wvalid, usb_rx_wready;
146: logic rx_fifo_rvalid;
147:
148: logic [AVFifoWidth - 1:0] usb_av_rdata;
149: logic [RXFifoWidth - 1:0] usb_rx_wdata, rx_rdata_raw, rx_rdata;
150:
151: assign event_av_overflow = reg2hw.avbuffer.qe & (~av_fifo_wready);
152: assign hw2reg.usbstat.av_full.d = ~av_fifo_wready;
153: assign hw2reg.usbstat.rx_empty.d = ~rx_fifo_rvalid;
154:
155: prim_fifo_async #(
156: .Width(AVFifoWidth),
157: .Depth(AVFifoDepth)
158: ) usbdev_avfifo (
159: .clk_wr_i (clk_i),
160: .rst_wr_ni (rst_ni),
161:
162: .wvalid (reg2hw.avbuffer.qe),
163: .wready (av_fifo_wready),
164: .wdata (reg2hw.avbuffer.q),
165: .wdepth (hw2reg.usbstat.av_depth.d),
166:
167: .clk_rd_i (clk_usb_48mhz_i),
168: .rst_rd_ni (rst_usb_ni),
169: .rvalid (usb_av_rvalid),
170: .rready (usb_av_rready),
171: .rdata (usb_av_rdata),
172: .rdepth () // only using empty
173: );
174:
175: prim_fifo_async #(
176: .Width(RXFifoWidth),
177: .Depth(RXFifoDepth)
178: ) usbdev_rxfifo (
179: .clk_wr_i (clk_usb_48mhz_i),
180: .rst_wr_ni (rst_usb_ni),
181:
182: .wvalid (usb_rx_wvalid),
183: .wready (usb_rx_wready),
184: .wdata (usb_rx_wdata),
185: .wdepth (),
186:
187: .clk_rd_i (clk_i),
188: .rst_rd_ni (rst_ni),
189: .rvalid (rx_fifo_rvalid),
190: .rready (reg2hw.rxfifo.buffer.re),
191: .rdata (rx_rdata_raw),
192: .rdepth (hw2reg.usbstat.rx_depth.d)
193: );
194:
195: // Return all zero if the FIFO is empty (instead of X)
196: assign rx_rdata = rx_fifo_rvalid ? rx_rdata_raw : '0;
197: assign hw2reg.rxfifo.ep.d = rx_rdata[16:13];
198: assign hw2reg.rxfifo.setup.d = rx_rdata[12];
199: assign hw2reg.rxfifo.size.d = rx_rdata[11:5];
200: assign hw2reg.rxfifo.buffer.d = rx_rdata[4:0];
201: assign event_pkt_received = rx_fifo_rvalid;
202: logic [2:0] unused_re;
203: assign unused_re = {reg2hw.rxfifo.ep.re, reg2hw.rxfifo.setup.re, reg2hw.rxfifo.size.re};
204:
205: ////////////////////////////////////
206: // IN (Transmit) interface config //
207: ////////////////////////////////////
208: logic [NBufWidth-1:0] usb_in_buf [NEndpoints];
209: logic [SizeWidth:0] usb_in_size [NEndpoints];
210: logic [3:0] usb_in_endpoint;
211: logic [NEndpoints-1:0] usb_in_rdy;
212: logic [NEndpoints-1:0] clear_rdybit, set_sentbit, update_pend;
213: logic usb_setup_received, setup_received, usb_set_sent, set_sent;
214: logic [NEndpoints-1:0] ep_iso;
215: logic [NEndpoints-1:0] enable_setup, enable_out, ep_stall;
216: logic [NEndpoints-1:0] usb_enable_setup, usb_enable_out, usb_ep_stall;
217: logic [NEndpoints-1:0] in_rdy_async;
218: logic [3:0] usb_out_endpoint;
219:
220: // RX enables
221: always_comb begin : proc_map_rxenable
222: for (int i = 0; i < NEndpoints; i++) begin
223: enable_setup[i] = reg2hw.rxenable_setup[i].q;
224: enable_out[i] = reg2hw.rxenable_out[i].q;
225: end
226: end
227:
228: // STALL for both directions
229: always_comb begin : proc_map_stall
230: for (int i = 0; i < NEndpoints; i++) begin
231: ep_stall[i] = reg2hw.stall[i];
232: end
233: end
234:
235: prim_flop_2sync #(
236: .Width(3*NEndpoints)
237: ) usbdev_sync_ep_cfg (
238: .clk_i (clk_usb_48mhz_i),
239: .rst_ni (rst_usb_ni),
240: .d ({enable_setup, enable_out, ep_stall}),
241: .q ({usb_enable_setup, usb_enable_out, usb_ep_stall})
242: );
243:
244: // CDC: ok, quasi-static
245: always_comb begin : proc_map_iso
246: for (int i = 0; i < NEndpoints; i++) begin
247: ep_iso[i] = reg2hw.iso[i].q;
248: end
249: end
250:
251: // CDC: flop_2sync for ready bit covers others so assigns are ok
252: always_comb begin : proc_map_buf_size
253: for (int i = 0; i < NEndpoints; i++) begin
254: usb_in_buf[i] = reg2hw.configin[i].buffer.q;
255: usb_in_size[i] = reg2hw.configin[i].size.q;
256: end
257: end
258:
259: always_comb begin : proc_map_rdy_reg2hw
260: for (int i = 0; i < NEndpoints; i++) begin
261: in_rdy_async[i] = reg2hw.configin[i].rdy.q;
262: end
263: end
264:
265: prim_flop_2sync #(
266: .Width (NEndpoints)
267: ) usbdev_rdysync (
268: .clk_i (clk_usb_48mhz_i),
269: .rst_ni (rst_usb_ni),
270: .d (in_rdy_async),
271: .q (usb_in_rdy)
272: );
273:
274: // CDC: We synchronize the qe (write pulse) and assume that the
275: // rest of the register remains stable
276: prim_pulse_sync usbdev_data_toggle_clear (
277: .clk_src_i (clk_i),
278: .clk_dst_i (clk_usb_48mhz_i),
279: .rst_src_ni (rst_ni),
280: .rst_dst_ni (rst_usb_ni),
281: .src_pulse_i (reg2hw.data_toggle_clear[0].qe),
282: .dst_pulse_o (usb_data_toggle_clear_en)
283: );
284:
285: always_comb begin : proc_usb_data_toggle_clear
286: usb_data_toggle_clear = '0;
287: for (int i = 0; i < NEndpoints; i++) begin
288: if (usb_data_toggle_clear_en) begin
289: usb_data_toggle_clear[i] = reg2hw.data_toggle_clear[i].q;
290: end
291: end
292: end
293:
294: // Clear of ready and set of sent is a pulse in USB clock domain
295: // but needs to ensure register bit is cleared/set in TLUL domain
296: // usbdev_pulsesync takes pulse in clk_src to pulse in clk_dst
297: prim_pulse_sync usbdev_setsent (
298: .clk_src_i (clk_usb_48mhz_i),
299: .clk_dst_i (clk_i),
300: .rst_src_ni (rst_usb_ni),
301: .rst_dst_ni (rst_ni),
302: .src_pulse_i (usb_set_sent),
303: .dst_pulse_o (set_sent)
304: );
305:
306: always_comb begin
307: set_sentbit = '0;
308: if (set_sent) begin
309: // synchronization of set_sent ensures usb_endpoint is stable
310: set_sentbit[usb_in_endpoint] = 1; // lint: usb_in_endpoint range was checked
311: end
312: end
313:
314: always_comb begin : proc_map_sent
315: for (int i = 0; i < NEndpoints; i++) begin
316: hw2reg.in_sent[i].de = set_sentbit[i];
317: hw2reg.in_sent[i].d = 1'b1;
318: end
319: end
320:
321: // Event (pulse) synchronization
322: prim_pulse_sync usbdev_sync_in_err (
323: .clk_src_i (clk_usb_48mhz_i),
324: .clk_dst_i (clk_i),
325: .rst_src_ni (rst_usb_ni),
326: .rst_dst_ni (rst_ni),
327: .src_pulse_i (usb_event_in_err),
328: .dst_pulse_o (event_in_err)
329: );
330:
331: prim_pulse_sync usbdev_outrdyclr (
332: .clk_src_i (clk_usb_48mhz_i),
333: .clk_dst_i (clk_i),
334: .rst_src_ni (rst_usb_ni),
335: .rst_dst_ni (rst_ni),
336: .src_pulse_i (usb_setup_received),
337: .dst_pulse_o (setup_received)
338: );
339:
340: prim_pulse_sync sync_usb_event_rx_crc_err (
341: .clk_src_i (clk_usb_48mhz_i),
342: .clk_dst_i (clk_i),
343: .rst_src_ni (rst_usb_ni),
344: .rst_dst_ni (rst_ni),
345: .src_pulse_i (usb_event_rx_crc_err),
346: .dst_pulse_o (event_rx_crc_err)
347: );
348:
349: prim_pulse_sync sync_usb_event_rx_pid_err (
350: .clk_src_i (clk_usb_48mhz_i),
351: .clk_dst_i (clk_i),
352: .rst_src_ni (rst_usb_ni),
353: .rst_dst_ni (rst_ni),
354: .src_pulse_i (usb_event_rx_pid_err),
355: .dst_pulse_o (event_rx_pid_err)
356: );
357:
358: prim_pulse_sync sync_usb_event_rx_bitstuff_err (
359: .clk_src_i (clk_usb_48mhz_i),
360: .clk_dst_i (clk_i),
361: .rst_src_ni (rst_usb_ni),
362: .rst_dst_ni (rst_ni),
363: .src_pulse_i (usb_event_rx_bitstuff_err),
364: .dst_pulse_o (event_rx_bitstuff_err)
365: );
366:
367: prim_pulse_sync sync_usb_event_frame (
368: .clk_src_i (clk_usb_48mhz_i),
369: .clk_dst_i (clk_i),
370: .rst_src_ni (rst_usb_ni),
371: .rst_dst_ni (rst_ni),
372: .src_pulse_i (usb_event_frame),
373: .dst_pulse_o (event_frame)
374: );
375:
376: logic event_link_reset_q;
377:
378: always_ff @(posedge clk_usb_48mhz_i or negedge rst_usb_ni) begin
379: if (!rst_usb_ni) begin
380: event_link_reset_q <= 0;
381: end else begin
382: event_link_reset_q <= event_link_reset;
383: end
384: end
385:
386: always_comb begin
387: clear_rdybit = '0;
388: update_pend = '0;
389: if (event_link_reset && !event_link_reset_q) begin
390: clear_rdybit = {NEndpoints{1'b1}};
391: update_pend = {NEndpoints{1'b1}};
392: end else begin
393: // Clear pending when a SETUP is received
394: // CDC: usb_out_endpoint is synchronized implicitly by
395: // setup_received, as it is stable
396: clear_rdybit[usb_out_endpoint] = setup_received;
397: update_pend[usb_out_endpoint] = setup_received;
398:
399: // Clear when a IN transmission was sucessful
400: // CDC: usb_in_endpoint is synchronzied implicitly by
401: // set_sent
402: clear_rdybit[usb_in_endpoint] = set_sent;
403: end
404: end
405:
406: always_comb begin : proc_map_rdy_hw2reg
407: for (int i = 0; i < NEndpoints; i++) begin
408: hw2reg.configin[i].rdy.de = clear_rdybit[i];
409: hw2reg.configin[i].rdy.d = 1'b0;
410: end
411: end
412:
413: // Update the pending bit by copying the ready bit that is about to clear
414: always_comb begin : proc_map_pend
415: for (int i = 0; i < NEndpoints; i++) begin
416: hw2reg.configin[i].pend.de = update_pend[i];
417: hw2reg.configin[i].pend.d = reg2hw.configin[i].rdy.q | reg2hw.configin[i].pend.q;
418: end
419: end
420:
421: ////////////////////////////////////////////////////////
422: // USB interface -- everything is in USB clock domain //
423: ////////////////////////////////////////////////////////
424:
425: usbdev_usbif #(
426: .NEndpoints (NEndpoints),
427: .AVFifoWidth (AVFifoWidth),
428: .RXFifoWidth (RXFifoWidth),
429: .MaxPktSizeByte (MaxPktSizeByte),
430: .NBuf (NBuf),
431: .SramAw (SramAw)
432: ) usbdev_impl (
433: .clk_48mhz_i (clk_usb_48mhz_i),
434: .rst_ni (rst_usb_ni),
435:
436: // Pins
437: .usb_d_i (usb_rx_d),
438: .usb_se0_i (usb_rx_se0),
439: .usb_oe_o (usb_tx_oe),
440: .usb_d_o (usb_tx_d),
441: .usb_se0_o (usb_tx_se0),
442: .usb_sense_i (usb_pwr_sense),
443: .usb_pullup_en_o (usb_pullup_en),
444:
445: // receive side
446: .rx_setup_i (usb_enable_setup),
447: .rx_out_i (usb_enable_out),
448: .rx_stall_i (usb_ep_stall),
449: .av_rvalid_i (usb_av_rvalid),
450: .av_rready_o (usb_av_rready),
451: .av_rdata_i (usb_av_rdata),
452: .event_av_empty_o (usb_event_av_empty),
453:
454: .rx_wvalid_o (usb_rx_wvalid),
455: .rx_wready_i (usb_rx_wready),
456: .rx_wdata_o (usb_rx_wdata),
457: .event_rx_full_o (usb_event_rx_full),
458: .setup_received_o (usb_setup_received),
459: .out_endpoint_o (usb_out_endpoint), // will be stable for several cycles
460:
461: // transmit side
462: .in_buf_i (usb_in_buf[usb_in_endpoint]), // lint: usb_in_endpoint range was checked
463: .in_size_i (usb_in_size[usb_in_endpoint]), // lint: usb_in_endpoint range was checked
464: .in_stall_i (usb_ep_stall),
465: .in_rdy_i (usb_in_rdy),
466: .set_sent_o (usb_set_sent),
467: .in_endpoint_o (usb_in_endpoint),
468:
469: // memory
470: .mem_req_o (usb_mem_b_req),
471: .mem_write_o (usb_mem_b_write),
472: .mem_addr_o (usb_mem_b_addr),
473: .mem_wdata_o (usb_mem_b_wdata),
474: .mem_rdata_i (usb_mem_b_rdata),
475:
476: // control
477: .enable_i (usb_enable),
478: .devaddr_i (usb_device_addr),
479: .clr_devaddr_o (usb_clr_devaddr),
480: .ep_iso_i (ep_iso), // cdc ok, quasi-static
481: .cfg_eop_single_bit_i (reg2hw.phy_config.eop_single_bit.q), // cdc ok: quasi-static
482: .tx_osc_test_mode_i (1'b0), // cdc ok: quasi-static & testmode only
483: .data_toggle_clear_i (usb_data_toggle_clear),
484:
485: // status
486: .frame_o (usb_frame),
487: .frame_start_o (usb_event_frame),
488: .link_state_o (usb_link_state),
489: .link_disconnect_o (usb_event_disconnect),
490: .link_connect_o (usb_event_connect),
491: .link_reset_o (usb_event_link_reset),
492: .link_suspend_o (usb_event_link_suspend),
493: .link_resume_o (usb_event_link_resume),
494: .host_lost_o (usb_event_host_lost),
495: .link_in_err_o (usb_event_in_err),
496: .rx_crc_err_o (usb_event_rx_crc_err),
497: .rx_pid_err_o (usb_event_rx_pid_err),
498: .rx_bitstuff_err_o (usb_event_rx_bitstuff_err)
499: );
500:
501: /////////////////////////////////
502: // Control signal / status CDC //
503: /////////////////////////////////
504:
505: // USB clk -> sys clk
506: prim_flop_2sync #(
507: .Width (3+11)
508: ) cdc_usb_to_sys (
509: .clk_i (clk_i),
510: .rst_ni (rst_ni),
511: .d ({usb_link_state, usb_frame}),
512: .q ({hw2reg.usbstat.link_state.d, hw2reg.usbstat.frame.d})
513: );
514:
515: // sys clk -> USB clk
516: prim_flop_2sync #(
517: .Width (1+7)
518: ) cdc_sys_to_usb (
519: .clk_i (clk_usb_48mhz_i),
520: .rst_ni (rst_usb_ni),
521: .d ({reg2hw.usbctrl.enable.q, reg2hw.usbctrl.device_address.q}),
522: .q ({usb_enable, usb_device_addr})
523: );
524:
525: // CDC for event signals (arguably they are there for a long time so would be ok)
526: // Just want a pulse to ensure only one interrupt for an event
527: usbdev_flop_2syncpulse #(.Width(5)) syncevent (
528: .clk_i (clk_i),
529: .rst_ni (rst_ni),
530: .d ({usb_event_disconnect, usb_event_link_reset, usb_event_link_suspend,
531: usb_event_host_lost, usb_event_connect}),
532: .q ({event_disconnect, event_link_reset, event_link_suspend,
533: event_host_lost, event_connect})
534: );
535:
536: // Resume is a single pulse so needs pulsesync
537: prim_pulse_sync usbdev_resume (
538: .clk_src_i (clk_usb_48mhz_i),
539: .clk_dst_i (clk_i),
540: .rst_src_ni (rst_usb_ni),
541: .rst_dst_ni (rst_ni),
542: .src_pulse_i (usb_event_link_resume),
543: .dst_pulse_o (event_link_resume)
544: );
545:
546: assign hw2reg.usbstat.host_lost.d = event_host_lost;
547:
548: // resets etc cause the device address to clear
549: prim_pulse_sync usbdev_devclr (
550: .clk_src_i (clk_usb_48mhz_i),
551: .clk_dst_i (clk_i),
552: .rst_src_ni (rst_usb_ni),
553: .rst_dst_ni (rst_ni),
554: .src_pulse_i (usb_clr_devaddr),
555: .dst_pulse_o (hw2reg.usbctrl.device_address.de)
556: );
557: assign hw2reg.usbctrl.device_address.d = '0;
558:
559: // AV empty is a single pulse so needs pulsesync
560: prim_pulse_sync sync_usb_event_av_empty (
561: .clk_src_i (clk_usb_48mhz_i),
562: .clk_dst_i (clk_i),
563: .rst_src_ni (rst_usb_ni),
564: .rst_dst_ni (rst_ni),
565: .src_pulse_i (usb_event_av_empty),
566: .dst_pulse_o (event_av_empty)
567: );
568:
569: // RX full is a single pulse so needs pulsesync
570: prim_pulse_sync sync_usb_event_rx_full (
571: .clk_src_i (clk_usb_48mhz_i),
572: .clk_dst_i (clk_i),
573: .rst_src_ni (rst_usb_ni),
574: .rst_dst_ni (rst_ni),
575: .src_pulse_i (usb_event_rx_full),
576: .dst_pulse_o (event_rx_full)
577: );
578:
579: // Clear the stall flag when a SETUP is received
580:
581: // CDC: usb_out_endpoint is synchronized implicitly by
582: // setup_received, as it is stable
583: always_comb begin : proc_stall_tieoff
584: for (int i = 0; i < NEndpoints; i++) begin
585: hw2reg.stall[i].d = 1'b0;
586: if (setup_received && usb_out_endpoint == 4'(i)) begin
587: hw2reg.stall[i].de = 1'b1;
588: end else begin
589: hw2reg.stall[i].de = 1'b0;
590: end
591: end
592: end
593:
594: logic unused_mem_a_rerror_d;
595:
596: // TL-UL to SRAM adapter
597: tlul_adapter_sram #(
598: .SramAw(SramAw),
599: .ByteAccess(0)
600: ) u_tlul2sram (
601: .clk_i (clk_i),
602: .rst_ni (rst_ni),
603:
604: .tl_i (tl_sram_h2d [0]),
605: .tl_o (tl_sram_d2h [0]),
606:
607: .req_o (mem_a_req),
608: .gnt_i (mem_a_req), //Always grant when request
609: .we_o (mem_a_write),
610: .addr_o (mem_a_addr),
611: .wdata_o (mem_a_wdata),
612: .wmask_o (), // Not used
613: .rdata_i (mem_a_rdata),
614: .rvalid_i (mem_a_rvalid),
615: .rerror_i (mem_a_rerror)
616: );
617:
618: assign unused_mem_a_rerror_d = mem_a_rerror[1] ; // Only uncorrectable error
619:
620: // SRAM Wrapper
621: prim_ram_2p_async_adv #(
622: .Depth (SramDepth),
623: .Width (SramDw), // 32 x 512 --> 2kB
624: .CfgW (8),
625:
626: .EnableECC (0), // No Protection
627: .EnableParity (0),
628: .EnableInputPipeline (0),
629: .EnableOutputPipeline(0),
630:
631: // large memory, implement with SRAMs
632: .MemT ("SRAM")
633: ) u_memory_2p (
634: .clk_a_i (clk_i),
635: .clk_b_i (clk_usb_48mhz_i),
636: .rst_a_ni (rst_ni),
637: .rst_b_ni (rst_usb_ni),
638: .a_req_i (mem_a_req),
639: .a_write_i (mem_a_write),
640: .a_addr_i (mem_a_addr),
641: .a_wdata_i (mem_a_wdata),
642: .a_rvalid_o (mem_a_rvalid),
643: .a_rdata_o (mem_a_rdata),
644: .a_rerror_o (mem_a_rerror),
645:
646: .b_req_i (usb_mem_b_req),
647: .b_write_i (usb_mem_b_write),
648: .b_addr_i (usb_mem_b_addr),
649: .b_wdata_i (usb_mem_b_wdata),
650: .b_rvalid_o (),
651: .b_rdata_o (usb_mem_b_rdata),
652: .b_rerror_o (),
653:
654: .cfg_i (8'h0)
655: );
656:
657: // Register module
658: usbdev_reg_top u_reg (
659: .clk_i,
660: .rst_ni,
661:
662: .tl_i (tl_i),
663: .tl_o (tl_o),
664:
665: .tl_win_o (tl_sram_h2d),
666: .tl_win_i (tl_sram_d2h),
667:
668: .reg2hw,
669: .hw2reg,
670: .devmode_i (1'b1)
671: );
672:
673: prim_intr_hw #(.Width(1)) intr_hw_pkt_received (
674: .event_intr_i (event_pkt_received),
675: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.pkt_received.q),
676: .reg2hw_intr_test_q_i (reg2hw.intr_test.pkt_received.q),
677: .reg2hw_intr_test_qe_i (reg2hw.intr_test.pkt_received.qe),
678: .reg2hw_intr_state_q_i (reg2hw.intr_state.pkt_received.q),
679: .hw2reg_intr_state_de_o (hw2reg.intr_state.pkt_received.de),
680: .hw2reg_intr_state_d_o (hw2reg.intr_state.pkt_received.d),
681: .intr_o (intr_pkt_received_o)
682: );
683:
684: prim_intr_hw #(.Width(1)) intr_hw_pkt_sent (
685: .event_intr_i (set_sent),
686: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.pkt_sent.q),
687: .reg2hw_intr_test_q_i (reg2hw.intr_test.pkt_sent.q),
688: .reg2hw_intr_test_qe_i (reg2hw.intr_test.pkt_sent.qe),
689: .reg2hw_intr_state_q_i (reg2hw.intr_state.pkt_sent.q),
690: .hw2reg_intr_state_de_o (hw2reg.intr_state.pkt_sent.de),
691: .hw2reg_intr_state_d_o (hw2reg.intr_state.pkt_sent.d),
692: .intr_o (intr_pkt_sent_o)
693: );
694:
695: prim_intr_hw #(.Width(1)) intr_disconnected (
696: .event_intr_i (event_disconnect),
697: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.disconnected.q),
698: .reg2hw_intr_test_q_i (reg2hw.intr_test.disconnected.q),
699: .reg2hw_intr_test_qe_i (reg2hw.intr_test.disconnected.qe),
700: .reg2hw_intr_state_q_i (reg2hw.intr_state.disconnected.q),
701: .hw2reg_intr_state_de_o (hw2reg.intr_state.disconnected.de),
702: .hw2reg_intr_state_d_o (hw2reg.intr_state.disconnected.d),
703: .intr_o (intr_disconnected_o)
704: );
705:
706: prim_intr_hw #(.Width(1)) intr_connected (
707: .event_intr_i (event_connect),
708: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.connected.q),
709: .reg2hw_intr_test_q_i (reg2hw.intr_test.connected.q),
710: .reg2hw_intr_test_qe_i (reg2hw.intr_test.connected.qe),
711: .reg2hw_intr_state_q_i (reg2hw.intr_state.connected.q),
712: .hw2reg_intr_state_de_o (hw2reg.intr_state.connected.de),
713: .hw2reg_intr_state_d_o (hw2reg.intr_state.connected.d),
714: .intr_o (intr_connected_o)
715: );
716:
717: prim_intr_hw #(.Width(1)) intr_host_lost (
718: .event_intr_i (event_host_lost),
719: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.host_lost.q),
720: .reg2hw_intr_test_q_i (reg2hw.intr_test.host_lost.q),
721: .reg2hw_intr_test_qe_i (reg2hw.intr_test.host_lost.qe),
722: .reg2hw_intr_state_q_i (reg2hw.intr_state.host_lost.q),
723: .hw2reg_intr_state_de_o (hw2reg.intr_state.host_lost.de),
724: .hw2reg_intr_state_d_o (hw2reg.intr_state.host_lost.d),
725: .intr_o (intr_host_lost_o)
726: );
727:
728: prim_intr_hw #(.Width(1)) intr_link_reset (
729: .event_intr_i (event_link_reset),
730: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.link_reset.q),
731: .reg2hw_intr_test_q_i (reg2hw.intr_test.link_reset.q),
732: .reg2hw_intr_test_qe_i (reg2hw.intr_test.link_reset.qe),
733: .reg2hw_intr_state_q_i (reg2hw.intr_state.link_reset.q),
734: .hw2reg_intr_state_de_o (hw2reg.intr_state.link_reset.de),
735: .hw2reg_intr_state_d_o (hw2reg.intr_state.link_reset.d),
736: .intr_o (intr_link_reset_o)
737: );
738:
739: prim_intr_hw #(.Width(1)) intr_link_suspend (
740: .event_intr_i (event_link_suspend),
741: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.link_suspend.q),
742: .reg2hw_intr_test_q_i (reg2hw.intr_test.link_suspend.q),
743: .reg2hw_intr_test_qe_i (reg2hw.intr_test.link_suspend.qe),
744: .reg2hw_intr_state_q_i (reg2hw.intr_state.link_suspend.q),
745: .hw2reg_intr_state_de_o (hw2reg.intr_state.link_suspend.de),
746: .hw2reg_intr_state_d_o (hw2reg.intr_state.link_suspend.d),
747: .intr_o (intr_link_suspend_o)
748: );
749:
750: prim_intr_hw #(.Width(1)) intr_link_resume (
751: .event_intr_i (event_link_resume),
752: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.link_resume.q),
753: .reg2hw_intr_test_q_i (reg2hw.intr_test.link_resume.q),
754: .reg2hw_intr_test_qe_i (reg2hw.intr_test.link_resume.qe),
755: .reg2hw_intr_state_q_i (reg2hw.intr_state.link_resume.q),
756: .hw2reg_intr_state_de_o (hw2reg.intr_state.link_resume.de),
757: .hw2reg_intr_state_d_o (hw2reg.intr_state.link_resume.d),
758: .intr_o (intr_link_resume_o)
759: );
760:
761: prim_intr_hw #(.Width(1)) intr_av_empty (
762: .event_intr_i (event_av_empty),
763: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.av_empty.q),
764: .reg2hw_intr_test_q_i (reg2hw.intr_test.av_empty.q),
765: .reg2hw_intr_test_qe_i (reg2hw.intr_test.av_empty.qe),
766: .reg2hw_intr_state_q_i (reg2hw.intr_state.av_empty.q),
767: .hw2reg_intr_state_de_o (hw2reg.intr_state.av_empty.de),
768: .hw2reg_intr_state_d_o (hw2reg.intr_state.av_empty.d),
769: .intr_o (intr_av_empty_o)
770: );
771:
772: prim_intr_hw #(.Width(1)) intr_rx_full (
773: .event_intr_i (event_rx_full),
774: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_full.q),
775: .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_full.q),
776: .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_full.qe),
777: .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_full.q),
778: .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_full.de),
779: .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_full.d),
780: .intr_o (intr_rx_full_o)
781: );
782:
783: prim_intr_hw #(.Width(1)) intr_av_overflow (
784: .event_intr_i (event_av_overflow),
785: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.av_overflow.q),
786: .reg2hw_intr_test_q_i (reg2hw.intr_test.av_overflow.q),
787: .reg2hw_intr_test_qe_i (reg2hw.intr_test.av_overflow.qe),
788: .reg2hw_intr_state_q_i (reg2hw.intr_state.av_overflow.q),
789: .hw2reg_intr_state_de_o (hw2reg.intr_state.av_overflow.de),
790: .hw2reg_intr_state_d_o (hw2reg.intr_state.av_overflow.d),
791: .intr_o (intr_av_overflow_o)
792: );
793:
794: prim_intr_hw #(.Width(1)) intr_link_in_err (
795: .event_intr_i (event_in_err),
796: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.link_in_err.q),
797: .reg2hw_intr_test_q_i (reg2hw.intr_test.link_in_err.q),
798: .reg2hw_intr_test_qe_i (reg2hw.intr_test.link_in_err.qe),
799: .reg2hw_intr_state_q_i (reg2hw.intr_state.link_in_err.q),
800: .hw2reg_intr_state_de_o (hw2reg.intr_state.link_in_err.de),
801: .hw2reg_intr_state_d_o (hw2reg.intr_state.link_in_err.d),
802: .intr_o (intr_link_in_err_o)
803: );
804:
805: prim_intr_hw #(.Width(1)) intr_rx_crc_err (
806: .event_intr_i (event_rx_crc_err),
807: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_crc_err.q),
808: .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_crc_err.q),
809: .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_crc_err.qe),
810: .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_crc_err.q),
811: .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_crc_err.de),
812: .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_crc_err.d),
813: .intr_o (intr_rx_crc_err_o)
814: );
815:
816: prim_intr_hw #(.Width(1)) intr_rx_pid_err (
817: .event_intr_i (event_rx_pid_err),
818: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_pid_err.q),
819: .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_pid_err.q),
820: .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_pid_err.qe),
821: .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_pid_err.q),
822: .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_pid_err.de),
823: .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_pid_err.d),
824: .intr_o (intr_rx_pid_err_o)
825: );
826:
827: prim_intr_hw #(.Width(1)) intr_rx_bitstuff_err (
828: .event_intr_i (event_rx_bitstuff_err),
829: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.rx_bitstuff_err.q),
830: .reg2hw_intr_test_q_i (reg2hw.intr_test.rx_bitstuff_err.q),
831: .reg2hw_intr_test_qe_i (reg2hw.intr_test.rx_bitstuff_err.qe),
832: .reg2hw_intr_state_q_i (reg2hw.intr_state.rx_bitstuff_err.q),
833: .hw2reg_intr_state_de_o (hw2reg.intr_state.rx_bitstuff_err.de),
834: .hw2reg_intr_state_d_o (hw2reg.intr_state.rx_bitstuff_err.d),
835: .intr_o (intr_rx_bitstuff_err_o)
836: );
837:
838: prim_intr_hw #(.Width(1)) intr_frame (
839: .event_intr_i (event_frame),
840: .reg2hw_intr_enable_q_i (reg2hw.intr_enable.frame.q),
841: .reg2hw_intr_test_q_i (reg2hw.intr_test.frame.q),
842: .reg2hw_intr_test_qe_i (reg2hw.intr_test.frame.qe),
843: .reg2hw_intr_state_q_i (reg2hw.intr_state.frame.q),
844: .hw2reg_intr_state_de_o (hw2reg.intr_state.frame.de),
845: .hw2reg_intr_state_d_o (hw2reg.intr_state.frame.d),
846: .intr_o (intr_frame_o)
847: );
848:
849: /////////////////////////////////
850: // USB IO Muxing //
851: /////////////////////////////////
852:
853: usbdev_iomux i_usbdev_iomux (
854: .clk_i (clk_i),
855: .rst_ni (rst_ni),
856: .clk_usb_48mhz_i (clk_usb_48mhz_i),
857: .rst_usb_ni (rst_usb_ni),
858: .rx_differential_mode_i (reg2hw.phy_config.rx_differential_mode),
859: .tx_differential_mode_i (reg2hw.phy_config.tx_differential_mode),
860: .sys_reg2hw_config_i (reg2hw.phy_config),
861: .sys_usb_sense_o (hw2reg.usbstat.usb_sense.d),
862:
863: // Chip IO
864: .cio_usb_d_i (cio_usb_d_i),
865: .cio_usb_dp_i (cio_usb_dp_i),
866: .cio_usb_dn_i (cio_usb_dn_i),
867: .cio_usb_d_o (cio_usb_d_o),
868: .cio_usb_se0_o (cio_usb_se0_o),
869: .cio_usb_dp_o (cio_usb_dp_o),
870: .cio_usb_dn_o (cio_usb_dn_o),
871: .cio_usb_oe_o (cio_usb_oe_o),
872: .cio_usb_tx_mode_se_o (cio_usb_tx_mode_se_o),
873: .cio_usb_sense_i (cio_usb_sense_i),
874: .cio_usb_pullup_en_o (cio_usb_pullup_en_o),
875: .cio_usb_suspend_o (cio_usb_suspend_o),
876:
877: // Internal interface
878: .usb_rx_d_o (usb_rx_d),
879: .usb_rx_se0_o (usb_rx_se0),
880: .usb_tx_d_i (usb_tx_d),
881: .usb_tx_se0_i (usb_tx_se0),
882: .usb_tx_oe_i (usb_tx_oe),
883: .usb_pwr_sense_o (usb_pwr_sense),
884: .usb_pullup_en_i (usb_pullup_en),
885: .usb_suspend_i (usb_event_link_suspend)
886: );
887:
888: endmodule
889: