usb_tx_ll.v 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * usb_tx_ll.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2019 Sylvain Munaut
  7. * All rights reserved.
  8. *
  9. * LGPL v3+, see LICENSE.lgpl3
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation; either
  14. * version 3 of the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public License
  22. * along with this program; if not, write to the Free Software Foundation,
  23. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  24. */
  25. `default_nettype none
  26. module usb_tx_ll (
  27. // PHY
  28. output wire phy_tx_dp,
  29. output wire phy_tx_dn,
  30. output wire phy_tx_en,
  31. // Low-Level
  32. input wire ll_start,
  33. input wire ll_bit,
  34. input wire ll_last,
  35. output reg ll_ack,
  36. // Common
  37. input wire clk,
  38. input wire rst
  39. );
  40. `include "usb_defs.vh"
  41. // Signals
  42. // -------
  43. // State
  44. reg [2:0] state;
  45. wire active;
  46. reg [2:0] br_cnt;
  47. wire br_now;
  48. // Bit stuffing
  49. reg [2:0] bs_cnt;
  50. reg bs_now;
  51. wire bs_bit;
  52. // NRZI
  53. reg lvl_prev;
  54. // Output
  55. reg out_active;
  56. reg [1:0] out_sym;
  57. // State
  58. // -----
  59. always @(posedge clk or posedge rst)
  60. if (rst)
  61. state <= 3'b000;
  62. else begin
  63. if (ll_start)
  64. state <= 3'b100;
  65. else if (br_now) begin
  66. if (ll_last)
  67. state <= 3'b101;
  68. else
  69. case (state[1:0])
  70. 2'b00: state <= state;
  71. 2'b01: state <= 3'b110;
  72. 2'b10: state <= 3'b111;
  73. default: state <= 3'b000;
  74. endcase
  75. end
  76. end
  77. assign active = state[2];
  78. always @(posedge clk)
  79. br_cnt <= { 1'b0, active ? br_cnt[1:0] : 2'b10 } + 1;
  80. assign br_now = br_cnt[2];
  81. // Bit Stuffing
  82. // ------------
  83. // Track number of 1s
  84. always @(posedge clk or posedge ll_start)
  85. if (ll_start) begin
  86. bs_cnt <= 3'b000;
  87. bs_now <= 1'b0;
  88. end else if (br_now) begin
  89. bs_cnt <= (ll_bit & ~bs_now) ? (bs_cnt + 1) : 3'b000;
  90. bs_now <= ll_bit & (bs_cnt == 3'b101);
  91. end
  92. // Effective bit
  93. assign bs_bit = ~bs_now & ll_bit;
  94. // Track previous level
  95. always @(posedge clk)
  96. lvl_prev <= active ? (lvl_prev ^ (~bs_bit & br_now)) : 1'b1;
  97. // Output stage
  98. // ------------
  99. // Ack input
  100. always @(posedge clk)
  101. ll_ack <= br_now & ~bs_now & (state[1:0] == 2'b00);
  102. // Output symbol. Must be forced to 'J' outside of active area to
  103. // be ready for the next packet start
  104. always @(posedge clk or posedge rst)
  105. begin
  106. if (rst)
  107. out_sym <= SYM_J;
  108. else if (br_now) begin
  109. case (state[1:0])
  110. 2'b00: out_sym <= (bs_bit ^ lvl_prev) ? SYM_K : SYM_J;
  111. 2'b01: out_sym <= SYM_SE0;
  112. 2'b10: out_sym <= SYM_SE0;
  113. 2'b11: out_sym <= SYM_J;
  114. default: out_sym <= 2'bxx;
  115. endcase
  116. end
  117. end
  118. // The OE is a bit in advance (not aligned with br_now) on purpose
  119. // so that we output a bit of 'J' at the packet beginning
  120. always @(posedge clk)
  121. out_active <= active;
  122. // PHY control
  123. assign phy_tx_dp = out_sym[1];
  124. assign phy_tx_dn = out_sym[0];
  125. assign phy_tx_en = out_active;
  126. endmodule // usb_tx_ll