usbf_sie_tx.v 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. //-----------------------------------------------------------------
  2. // USB Serial Port
  3. // V0.1
  4. // Ultra-Embedded.com
  5. // Copyright 2020
  6. //
  7. // Email: admin@ultra-embedded.com
  8. //
  9. // License: LGPL
  10. //-----------------------------------------------------------------
  11. //
  12. // This source file may be used and distributed without
  13. // restriction provided that this copyright statement is not
  14. // removed from the file and that any derivative work contains
  15. // the original copyright notice and the associated disclaimer.
  16. //
  17. // This source file is free software; you can redistribute it
  18. // and/or modify it under the terms of the GNU Lesser General
  19. // Public License as published by the Free Software Foundation;
  20. // either version 2.1 of the License, or (at your option) any
  21. // later version.
  22. //
  23. // This source is distributed in the hope that it will be
  24. // useful, but WITHOUT ANY WARRANTY; without even the implied
  25. // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  26. // PURPOSE. See the GNU Lesser General Public License for more
  27. // details.
  28. //
  29. // You should have received a copy of the GNU Lesser General
  30. // Public License along with this source; if not, write to the
  31. // Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  32. // Boston, MA 02111-1307 USA
  33. //-----------------------------------------------------------------
  34. //-----------------------------------------------------------------
  35. // Generated File
  36. //-----------------------------------------------------------------
  37. module usbf_sie_tx
  38. (
  39. // Inputs
  40. input clk_i
  41. ,input rst_i
  42. ,input enable_i
  43. ,input chirp_i
  44. ,input utmi_txready_i
  45. ,input tx_valid_i
  46. ,input [ 7:0] tx_pid_i
  47. ,input data_valid_i
  48. ,input data_strb_i
  49. ,input [ 7:0] data_i
  50. ,input data_last_i
  51. // Outputs
  52. ,output [ 7:0] utmi_data_o
  53. ,output utmi_txvalid_o
  54. ,output tx_accept_o
  55. ,output data_accept_o
  56. );
  57. //-----------------------------------------------------------------
  58. // Defines:
  59. //-----------------------------------------------------------------
  60. `include "usbf_defs.v"
  61. localparam STATE_W = 3;
  62. localparam STATE_TX_IDLE = 3'd0;
  63. localparam STATE_TX_PID = 3'd1;
  64. localparam STATE_TX_DATA = 3'd2;
  65. localparam STATE_TX_CRC1 = 3'd3;
  66. localparam STATE_TX_CRC2 = 3'd4;
  67. localparam STATE_TX_DONE = 3'd5;
  68. localparam STATE_TX_CHIRP = 3'd6;
  69. reg [STATE_W-1:0] state_q;
  70. reg [STATE_W-1:0] next_state_r;
  71. //-----------------------------------------------------------------
  72. // Request Type
  73. //-----------------------------------------------------------------
  74. reg data_pid_q;
  75. reg data_zlp_q;
  76. always @ (posedge clk_i or posedge rst_i)
  77. if (rst_i)
  78. begin
  79. data_pid_q <= 1'b0;
  80. data_zlp_q <= 1'b0;
  81. end
  82. else if (!enable_i)
  83. begin
  84. data_pid_q <= 1'b0;
  85. data_zlp_q <= 1'b0;
  86. end
  87. else if (tx_valid_i && tx_accept_o)
  88. begin
  89. case (tx_pid_i)
  90. `PID_MDATA, `PID_DATA2, `PID_DATA0, `PID_DATA1:
  91. begin
  92. data_pid_q <= 1'b1;
  93. data_zlp_q <= data_valid_i && (data_strb_i == 1'b0) && data_last_i;
  94. end
  95. default :
  96. begin
  97. data_pid_q <= 1'b0;
  98. data_zlp_q <= 1'b0;
  99. end
  100. endcase
  101. end
  102. else if (next_state_r == STATE_TX_CRC1)
  103. begin
  104. data_pid_q <= 1'b0;
  105. data_zlp_q <= 1'b0;
  106. end
  107. assign tx_accept_o = (state_q == STATE_TX_IDLE);
  108. //-----------------------------------------------------------------
  109. // Next state
  110. //-----------------------------------------------------------------
  111. always @ *
  112. begin
  113. next_state_r = state_q;
  114. //-----------------------------------------
  115. // State Machine
  116. //-----------------------------------------
  117. case (state_q)
  118. //-----------------------------------------
  119. // IDLE
  120. //-----------------------------------------
  121. STATE_TX_IDLE :
  122. begin
  123. if (chirp_i)
  124. next_state_r = STATE_TX_CHIRP;
  125. else if (tx_valid_i)
  126. next_state_r = STATE_TX_PID;
  127. end
  128. //-----------------------------------------
  129. // TX_PID
  130. //-----------------------------------------
  131. STATE_TX_PID :
  132. begin
  133. // Data accepted
  134. if (utmi_txready_i)
  135. begin
  136. if (data_zlp_q)
  137. next_state_r = STATE_TX_CRC1;
  138. else if (data_pid_q)
  139. next_state_r = STATE_TX_DATA;
  140. else
  141. next_state_r = STATE_TX_DONE;
  142. end
  143. end
  144. //-----------------------------------------
  145. // TX_DATA
  146. //-----------------------------------------
  147. STATE_TX_DATA :
  148. begin
  149. // Data accepted
  150. if (utmi_txready_i)
  151. begin
  152. // Generate CRC16 at end of packet
  153. if (data_last_i)
  154. next_state_r = STATE_TX_CRC1;
  155. end
  156. end
  157. //-----------------------------------------
  158. // TX_CRC1 (first byte)
  159. //-----------------------------------------
  160. STATE_TX_CRC1 :
  161. begin
  162. // Data sent?
  163. if (utmi_txready_i)
  164. next_state_r = STATE_TX_CRC2;
  165. end
  166. //-----------------------------------------
  167. // TX_CRC (second byte)
  168. //-----------------------------------------
  169. STATE_TX_CRC2 :
  170. begin
  171. // Data sent?
  172. if (utmi_txready_i)
  173. next_state_r = STATE_TX_DONE;
  174. end
  175. //-----------------------------------------
  176. // TX_DONE
  177. //-----------------------------------------
  178. STATE_TX_DONE :
  179. begin
  180. // Data sent?
  181. if (!utmi_txvalid_o || utmi_txready_i)
  182. next_state_r = STATE_TX_IDLE;
  183. end
  184. //-----------------------------------------
  185. // TX_CHIRP
  186. //-----------------------------------------
  187. STATE_TX_CHIRP :
  188. begin
  189. if (!chirp_i)
  190. next_state_r = STATE_TX_IDLE;
  191. end
  192. default :
  193. ;
  194. endcase
  195. // USB reset but not chirping...
  196. if (!enable_i && !chirp_i)
  197. next_state_r = STATE_TX_IDLE;
  198. end
  199. // Update state
  200. always @ (posedge clk_i or posedge rst_i)
  201. if (rst_i)
  202. state_q <= STATE_TX_IDLE;
  203. else
  204. state_q <= next_state_r;
  205. //-----------------------------------------------------------------
  206. // Data Input
  207. //-----------------------------------------------------------------
  208. reg input_valid_r;
  209. reg [7:0] input_byte_r;
  210. reg input_last_r;
  211. always @ *
  212. begin
  213. input_valid_r = data_strb_i & data_pid_q;
  214. input_byte_r = data_i;
  215. input_last_r = data_last_i;
  216. end
  217. reg data_accept_r;
  218. always @ *
  219. begin
  220. if (state_q == STATE_TX_DATA)
  221. data_accept_r = utmi_txready_i;
  222. else if (state_q == STATE_TX_PID && data_zlp_q)
  223. data_accept_r = utmi_txready_i;
  224. else
  225. data_accept_r = 1'b0;
  226. end
  227. assign data_accept_o = data_accept_r;
  228. //-----------------------------------------------------------------
  229. // CRC16: Generate CRC16 on outgoing data
  230. //-----------------------------------------------------------------
  231. reg [15:0] crc_sum_q;
  232. wire [15:0] crc_out_w;
  233. reg crc_err_q;
  234. usbf_crc16
  235. u_crc16
  236. (
  237. .crc_in_i(crc_sum_q),
  238. .din_i(utmi_data_o),
  239. .crc_out_o(crc_out_w)
  240. );
  241. always @ (posedge clk_i or posedge rst_i)
  242. if (rst_i)
  243. crc_sum_q <= 16'hFFFF;
  244. else if (state_q == STATE_TX_IDLE)
  245. crc_sum_q <= 16'hFFFF;
  246. else if (state_q == STATE_TX_DATA && utmi_txvalid_o && utmi_txready_i)
  247. crc_sum_q <= crc_out_w;
  248. //-----------------------------------------------------------------
  249. // Output
  250. //-----------------------------------------------------------------
  251. reg valid_q;
  252. reg [7:0] data_q;
  253. always @ (posedge clk_i or posedge rst_i)
  254. if (rst_i)
  255. begin
  256. valid_q <= 1'b0;
  257. data_q <= 8'b0;
  258. end
  259. else if (!enable_i)
  260. begin
  261. valid_q <= 1'b0;
  262. data_q <= 8'b0;
  263. end
  264. else if (tx_valid_i && tx_accept_o)
  265. begin
  266. valid_q <= 1'b1;
  267. data_q <= tx_pid_i;
  268. end
  269. else if (utmi_txready_i)
  270. begin
  271. valid_q <= 1'b0;
  272. data_q <= 8'b0;
  273. end
  274. reg utmi_txvalid_r;
  275. reg [7:0] utmi_data_r;
  276. always @ *
  277. begin
  278. if (state_q == STATE_TX_CHIRP)
  279. begin
  280. utmi_txvalid_r = 1'b1;
  281. utmi_data_r = 8'b0;
  282. end
  283. else if (state_q == STATE_TX_CRC1)
  284. begin
  285. utmi_txvalid_r = 1'b1;
  286. utmi_data_r = crc_sum_q[7:0] ^ 8'hFF;
  287. end
  288. else if (state_q == STATE_TX_CRC2)
  289. begin
  290. utmi_txvalid_r = 1'b1;
  291. utmi_data_r = crc_sum_q[15:8] ^ 8'hFF;
  292. end
  293. else if (state_q == STATE_TX_DATA)
  294. begin
  295. utmi_txvalid_r = data_valid_i;
  296. utmi_data_r = data_i;
  297. end
  298. else
  299. begin
  300. utmi_txvalid_r = valid_q;
  301. utmi_data_r = data_q;
  302. end
  303. end
  304. assign utmi_txvalid_o = utmi_txvalid_r;
  305. assign utmi_data_o = utmi_data_r;
  306. endmodule