soc_usb.v 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. // Clock / Reset
  25. input wire clk_sys,
  26. input wire clk_48m,
  27. input wire rst
  28. );
  29. // Signals
  30. // -------
  31. // Bus OR
  32. wire [DW-1:0] wb_rdata_i[0:1];
  33. // Wishbone in 48 MHz domain
  34. wire [11:0] ub_addr;
  35. wire [15:0] ub_wdata;
  36. wire [15:0] ub_rdata;
  37. wire ub_cyc;
  38. wire ub_we;
  39. wire ub_ack;
  40. // EP Buffer
  41. wire [ 8:0] ep_tx_addr_0;
  42. wire [31:0] ep_tx_data_0;
  43. wire ep_tx_we_0;
  44. wire [ 8:0] ep_rx_addr_0;
  45. wire [31:0] ep_rx_data_1;
  46. wire ep_rx_re_0;
  47. reg ack_ep;
  48. // Cross-clock
  49. // -----------
  50. // Bring control reg wishbone to 48 MHz domain
  51. xclk_wb #(
  52. .DW(16),
  53. .AW(12)
  54. ) wb_48m_xclk_I (
  55. .s_addr (wb_addr[11:0]),
  56. .s_wdata (wb_wdata[15:0]),
  57. .s_rdata (wb_rdata_i[0][15:0]),
  58. .s_cyc (wb_cyc[0]),
  59. .s_ack (wb_ack[0]),
  60. .s_we (wb_we),
  61. .s_clk (clk_sys),
  62. .m_addr (ub_addr),
  63. .m_wdata (ub_wdata),
  64. .m_rdata (ub_rdata),
  65. .m_cyc (ub_cyc),
  66. .m_ack (ub_ack),
  67. .m_we (ub_we),
  68. .m_clk (clk_48m),
  69. .rst (rst)
  70. );
  71. if (DW != 16)
  72. assign wb_rdata_i[0][DW-1:16] = 0;
  73. // Core
  74. // ----
  75. usb #(
  76. .EPDW(32)
  77. ) usb_I (
  78. .pad_dp (usb_dp),
  79. .pad_dn (usb_dn),
  80. .pad_pu (usb_pu),
  81. .ep_tx_addr_0 (ep_tx_addr_0),
  82. .ep_tx_data_0 (ep_tx_data_0),
  83. .ep_tx_we_0 (ep_tx_we_0),
  84. .ep_rx_addr_0 (ep_rx_addr_0),
  85. .ep_rx_data_1 (ep_rx_data_1),
  86. .ep_rx_re_0 (ep_rx_re_0),
  87. .ep_clk (clk_sys),
  88. .wb_addr (ub_addr),
  89. .wb_rdata (ub_rdata),
  90. .wb_wdata (ub_wdata),
  91. .wb_we (ub_we),
  92. .wb_cyc (ub_cyc),
  93. .wb_ack (ub_ack),
  94. .clk (clk_48m),
  95. .rst (rst)
  96. );
  97. // EP data
  98. // -------
  99. assign ep_tx_addr_0 = wb_addr[8:0];
  100. assign ep_rx_addr_0 = wb_addr[8:0];
  101. assign ep_tx_data_0 = wb_wdata;
  102. assign wb_rdata_i[1] = ack_ep ? ep_rx_data_1 : 32'h00000000;
  103. assign ep_tx_we_0 = wb_cyc[1] & wb_we & ~ack_ep;
  104. assign ep_rx_re_0 = 1'b1;
  105. assign wb_ack[1] = ack_ep;
  106. always @(posedge clk_sys or posedge rst)
  107. if (rst)
  108. ack_ep <= 1'b0;
  109. else
  110. ack_ep <= wb_cyc[1] & ~ack_ep;
  111. // Bus read data
  112. // -------------
  113. assign wb_rdata = wb_rdata_i[0] | wb_rdata_i[1];
  114. endmodule // soc_usb