hw/ip/usbdev/rtl/usbdev_iomux.sv Cov: 100%
1: // Copyright lowRISC contributors.
2: // Copyright ETH Zurich.
3: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
4: // SPDX-License-Identifier: Apache-2.0
5: //
6: // USB IO Mux
7: //
8: // Muxes the USB IO signals from: register access, differential signaling,
9: // single-ended signaling. The incomming signals are also muxed and synchronized
10: // to the corresponding clock domain.
11:
12: import usbdev_reg_pkg::*;
13:
14: module usbdev_iomux (
15: input logic clk_i,
16: input logic rst_ni,
17: input logic clk_usb_48mhz_i, // use usb_ prefix for signals in this clk
18: input logic rst_usb_ni,
19:
20: // Configuration (quasi-static)
21: input logic rx_differential_mode_i,
22: input logic tx_differential_mode_i,
23:
24: // Register interface (system clk)
25: input usbdev_reg2hw_phy_config_reg_t sys_reg2hw_config_i,
26: output logic sys_usb_sense_o,
27:
28: // External USB Interface(s) (async)
29: input logic cio_usb_d_i,
30: input logic cio_usb_dp_i,
31: input logic cio_usb_dn_i,
32:
33: output logic cio_usb_d_o,
34: output logic cio_usb_se0_o,
35: output logic cio_usb_dp_o,
36: output logic cio_usb_dn_o,
37: output logic cio_usb_oe_o,
38:
39: output logic cio_usb_tx_mode_se_o,
40: input logic cio_usb_sense_i,
41: output logic cio_usb_pullup_en_o,
42: output logic cio_usb_suspend_o,
43:
44: // Internal USB Interface (usb clk)
45: output logic usb_rx_d_o,
46: output logic usb_rx_se0_o,
47:
48: input logic usb_tx_d_i,
49: input logic usb_tx_se0_i,
50: input logic usb_tx_oe_i,
51:
52: output logic usb_pwr_sense_o,
53: input logic usb_pullup_en_i,
54: input logic usb_suspend_i
55: );
56:
57: logic async_pwr_sense;
58:
59: logic sys_usb_sense;
60:
61: logic usb_rx_d;
62: logic usb_rx_dp;
63: logic usb_rx_dn;
64:
65: //////////
66: // CDCs //
67: //////////
68:
69: // USB pins sense (to sysclk)
70: prim_flop_2sync #(
71: .Width (1)
72: ) cdc_io_to_sys (
73: .clk_i (clk_i),
74: .rst_ni (rst_ni),
75: .d ({cio_usb_sense_i}),
76: .q ({sys_usb_sense})
77: );
78:
79: assign sys_usb_sense_o = sys_usb_sense;
80:
81: // USB input pins (to usbclk)
82: prim_flop_2sync #(
83: .Width (4)
84: ) cdc_io_to_usb (
85: .clk_i (clk_usb_48mhz_i),
86: .rst_ni (rst_usb_ni),
87: .d ({cio_usb_dp_i,
88: cio_usb_dn_i,
89: cio_usb_d_i,
90: async_pwr_sense}),
91: .q ({usb_rx_dp,
92: usb_rx_dn,
93: usb_rx_d,
94: usb_pwr_sense_o})
95: );
96:
97: ///////////////////////////////
98: // USB output pins drive mux //
99: ///////////////////////////////
100: always_comb begin : proc_drive_out
101: // Defaults
102: cio_usb_dn_o = 1'b0;
103: cio_usb_dp_o = 1'b0;
104:
105: // Signals from the peripheral core
106: cio_usb_pullup_en_o = usb_pullup_en_i;
107: cio_usb_suspend_o = usb_suspend_i;
108:
109: if (tx_differential_mode_i) begin
110: // Differential mode
111: cio_usb_tx_mode_se_o = 1'b0;
112:
113: end else begin
114: // Single-ended mode
115: cio_usb_tx_mode_se_o = 1'b1;
116: if (usb_tx_se0_i) begin
117: cio_usb_dp_o = 1'b0;
118: cio_usb_dn_o = 1'b0;
119: end else begin
120: cio_usb_dp_o = usb_tx_d_i;
121: cio_usb_dn_o = !usb_tx_d_i;
122: end
123: end
124: end
125:
126: // It would be possible to insert explicit controllability muxes here.
127: // For now, we just pass the signal through
128: assign cio_usb_d_o = usb_tx_d_i;
129: assign cio_usb_se0_o = usb_tx_se0_i;
130: assign cio_usb_oe_o = usb_tx_oe_i;
131:
132: ///////////////////////
133: // USB input pin mux //
134: ///////////////////////
135: always_comb begin : proc_mux_data_input
136: usb_rx_se0_o = ~usb_rx_dp & ~usb_rx_dn;
137:
138: if (rx_differential_mode_i) begin
139: // Differential RX mode
140: usb_rx_d_o = usb_rx_d;
141:
142: end else begin
143: // Single-ended RX mode
144: usb_rx_d_o = usb_rx_dp; // SE1 is interpreted as differential 1
145: end
146: end
147:
148: // Power sense mux
149: always_comb begin : proc_mux_pwr_input
150: if (sys_reg2hw_config_i.override_pwr_sense_en.q) begin
151: async_pwr_sense = sys_reg2hw_config_i.override_pwr_sense_val.q;
152: end else begin
153: async_pwr_sense = cio_usb_sense_i;
154: end
155: end
156:
157: endmodule
158: