soc_usb.v 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * soc_usb.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
  7. * SPDX-License-Identifier: CERN-OHL-P-2.0
  8. */
  9. `default_nettype none
  10. module soc_usb #(
  11. parameter integer DW = 32
  12. )(
  13. // USB
  14. inout wire usb_dp,
  15. inout wire usb_dn,
  16. output wire usb_pu,
  17. // Wishbone slave
  18. input wire [ 11:0] wb_addr,
  19. output wire [DW-1:0] wb_rdata,
  20. input wire [DW-1:0] wb_wdata,
  21. input wire wb_we,
  22. input wire [1:0] wb_cyc,
  23. output wire [1:0] wb_ack,
  24. // Misc
  25. output wire usb_sof,
  26. // Clock / Reset
  27. input wire clk_sys,
  28. input wire clk_48m,
  29. input wire rst
  30. );
  31. // Signals
  32. // -------
  33. // Bus OR
  34. wire [DW-1:0] wb_rdata_i[0:1];
  35. // Wishbone in 48 MHz domain
  36. wire [11:0] ub_addr;
  37. wire [15:0] ub_wdata;
  38. wire [15:0] ub_rdata;
  39. wire ub_cyc;
  40. wire ub_we;
  41. wire ub_ack;
  42. // SoF in 48 MHz domain
  43. wire usb_sof_48m;
  44. // EP Buffer
  45. wire [ 8:0] ep_tx_addr_0;
  46. wire [31:0] ep_tx_data_0;
  47. wire ep_tx_we_0;
  48. wire [ 8:0] ep_rx_addr_0;
  49. wire [31:0] ep_rx_data_1;
  50. wire ep_rx_re_0;
  51. reg ack_ep;
  52. // Cross-clock
  53. // -----------
  54. // Bring control reg wishbone to 48 MHz domain
  55. xclk_wb #(
  56. .DW(16),
  57. .AW(12)
  58. ) wb_48m_xclk_I (
  59. .s_addr (wb_addr[11:0]),
  60. .s_wdata (wb_wdata[15:0]),
  61. .s_rdata (wb_rdata_i[0][15:0]),
  62. .s_cyc (wb_cyc[0]),
  63. .s_ack (wb_ack[0]),
  64. .s_we (wb_we),
  65. .s_clk (clk_sys),
  66. .m_addr (ub_addr),
  67. .m_wdata (ub_wdata),
  68. .m_rdata (ub_rdata),
  69. .m_cyc (ub_cyc),
  70. .m_ack (ub_ack),
  71. .m_we (ub_we),
  72. .m_clk (clk_48m),
  73. .rst (rst)
  74. );
  75. if (DW != 16)
  76. assign wb_rdata_i[0][DW-1:16] = 0;
  77. xclk_strobe sof_xclk_I (
  78. .in_stb (usb_sof_48m),
  79. .in_clk (clk_48m),
  80. .out_stb (usb_sof),
  81. .out_clk (clk_sys),
  82. .rst (rst)
  83. );
  84. // Core
  85. // ----
  86. usb #(
  87. .EPDW(32)
  88. ) usb_I (
  89. .pad_dp (usb_dp),
  90. .pad_dn (usb_dn),
  91. .pad_pu (usb_pu),
  92. .ep_tx_addr_0 (ep_tx_addr_0),
  93. .ep_tx_data_0 (ep_tx_data_0),
  94. .ep_tx_we_0 (ep_tx_we_0),
  95. .ep_rx_addr_0 (ep_rx_addr_0),
  96. .ep_rx_data_1 (ep_rx_data_1),
  97. .ep_rx_re_0 (ep_rx_re_0),
  98. .ep_clk (clk_sys),
  99. .wb_addr (ub_addr),
  100. .wb_rdata (ub_rdata),
  101. .wb_wdata (ub_wdata),
  102. .wb_we (ub_we),
  103. .wb_cyc (ub_cyc),
  104. .wb_ack (ub_ack),
  105. .sof (usb_sof_48m),
  106. .clk (clk_48m),
  107. .rst (rst)
  108. );
  109. // EP data
  110. // -------
  111. assign ep_tx_addr_0 = wb_addr[8:0];
  112. assign ep_rx_addr_0 = wb_addr[8:0];
  113. assign ep_tx_data_0 = wb_wdata;
  114. assign wb_rdata_i[1] = ack_ep ? ep_rx_data_1 : 32'h00000000;
  115. assign ep_tx_we_0 = wb_cyc[1] & wb_we & ~ack_ep;
  116. assign ep_rx_re_0 = 1'b1;
  117. assign wb_ack[1] = ack_ep;
  118. always @(posedge clk_sys or posedge rst)
  119. if (rst)
  120. ack_ep <= 1'b0;
  121. else
  122. ack_ep <= wb_cyc[1] & ~ack_ep;
  123. // Bus read data
  124. // -------------
  125. assign wb_rdata = wb_rdata_i[0] | wb_rdata_i[1];
  126. endmodule // soc_usb