usbf_sie_tx.v 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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. //`define USB_RANDOM_CORRUPT 6
  35. //-----------------------------------------------------------------
  36. // Generated File
  37. //-----------------------------------------------------------------
  38. module usbf_sie_tx
  39. (
  40. // Inputs
  41. input clk_i
  42. ,input rst_i
  43. ,input enable_i
  44. ,input chirp_i
  45. ,input utmi_txready_i
  46. ,input tx_valid_i
  47. ,input [ 7:0] tx_pid_i
  48. ,input data_valid_i
  49. ,input data_strb_i
  50. ,input [ 7:0] data_i
  51. ,input data_last_i
  52. // Outputs
  53. ,output [ 7:0] utmi_data_o
  54. ,output utmi_txvalid_o
  55. ,output tx_accept_o
  56. ,output data_accept_o
  57. );
  58. //-----------------------------------------------------------------
  59. // Defines:
  60. //-----------------------------------------------------------------
  61. `include "usbf_defs.v"
  62. localparam STATE_W = 3;
  63. localparam STATE_TX_IDLE = 3'd0;
  64. localparam STATE_TX_PID = 3'd1;
  65. localparam STATE_TX_DATA = 3'd2;
  66. localparam STATE_TX_CRC1 = 3'd3;
  67. localparam STATE_TX_CRC2 = 3'd4;
  68. localparam STATE_TX_DONE = 3'd5;
  69. localparam STATE_TX_CHIRP = 3'd6;
  70. reg [STATE_W-1:0] state_q;
  71. reg [STATE_W-1:0] next_state_r;
  72. //-----------------------------------------------------------------
  73. // Request Type
  74. //-----------------------------------------------------------------
  75. reg data_pid_q;
  76. reg data_zlp_q;
  77. always @ (posedge clk_i or posedge rst_i)
  78. if (rst_i)
  79. begin
  80. data_pid_q <= 1'b0;
  81. data_zlp_q <= 1'b0;
  82. end
  83. else if (!enable_i)
  84. begin
  85. data_pid_q <= 1'b0;
  86. data_zlp_q <= 1'b0;
  87. end
  88. else if (tx_valid_i && tx_accept_o)
  89. begin
  90. case (tx_pid_i)
  91. `PID_MDATA, `PID_DATA2, `PID_DATA0, `PID_DATA1:
  92. begin
  93. data_pid_q <= 1'b1;
  94. data_zlp_q <= data_valid_i && (data_strb_i == 1'b0) && data_last_i;
  95. end
  96. default :
  97. begin
  98. data_pid_q <= 1'b0;
  99. data_zlp_q <= 1'b0;
  100. end
  101. endcase
  102. end
  103. else if (next_state_r == STATE_TX_CRC1)
  104. begin
  105. data_pid_q <= 1'b0;
  106. data_zlp_q <= 1'b0;
  107. end
  108. assign tx_accept_o = (state_q == STATE_TX_IDLE);
  109. //-----------------------------------------------------------------
  110. // Next state
  111. //-----------------------------------------------------------------
  112. always @ *
  113. begin
  114. next_state_r = state_q;
  115. //-----------------------------------------
  116. // State Machine
  117. //-----------------------------------------
  118. case (state_q)
  119. //-----------------------------------------
  120. // IDLE
  121. //-----------------------------------------
  122. STATE_TX_IDLE :
  123. begin
  124. if (chirp_i)
  125. next_state_r = STATE_TX_CHIRP;
  126. else if (tx_valid_i)
  127. next_state_r = STATE_TX_PID;
  128. end
  129. //-----------------------------------------
  130. // TX_PID
  131. //-----------------------------------------
  132. STATE_TX_PID :
  133. begin
  134. // Data accepted
  135. if (utmi_txready_i)
  136. begin
  137. if (data_zlp_q)
  138. next_state_r = STATE_TX_CRC1;
  139. else if (data_pid_q)
  140. next_state_r = STATE_TX_DATA;
  141. else
  142. next_state_r = STATE_TX_DONE;
  143. end
  144. end
  145. //-----------------------------------------
  146. // TX_DATA
  147. //-----------------------------------------
  148. STATE_TX_DATA :
  149. begin
  150. // Data accepted
  151. if (utmi_txready_i)
  152. begin
  153. // Generate CRC16 at end of packet
  154. if (data_last_i)
  155. next_state_r = STATE_TX_CRC1;
  156. end
  157. end
  158. //-----------------------------------------
  159. // TX_CRC1 (first byte)
  160. //-----------------------------------------
  161. STATE_TX_CRC1 :
  162. begin
  163. // Data sent?
  164. if (utmi_txready_i)
  165. next_state_r = STATE_TX_CRC2;
  166. end
  167. //-----------------------------------------
  168. // TX_CRC (second byte)
  169. //-----------------------------------------
  170. STATE_TX_CRC2 :
  171. begin
  172. // Data sent?
  173. if (utmi_txready_i)
  174. next_state_r = STATE_TX_DONE;
  175. end
  176. //-----------------------------------------
  177. // TX_DONE
  178. //-----------------------------------------
  179. STATE_TX_DONE :
  180. begin
  181. // Data sent?
  182. if (!utmi_txvalid_o || utmi_txready_i)
  183. next_state_r = STATE_TX_IDLE;
  184. end
  185. //-----------------------------------------
  186. // TX_CHIRP
  187. //-----------------------------------------
  188. STATE_TX_CHIRP :
  189. begin
  190. if (!chirp_i)
  191. next_state_r = STATE_TX_IDLE;
  192. end
  193. default :
  194. ;
  195. endcase
  196. // USB reset but not chirping...
  197. if (!enable_i && !chirp_i)
  198. next_state_r = STATE_TX_IDLE;
  199. end
  200. // Update state
  201. always @ (posedge clk_i or posedge rst_i)
  202. if (rst_i)
  203. state_q <= STATE_TX_IDLE;
  204. else
  205. state_q <= next_state_r;
  206. //-----------------------------------------------------------------
  207. // Data Input
  208. //-----------------------------------------------------------------
  209. reg input_valid_r;
  210. reg [7:0] input_byte_r;
  211. reg input_last_r;
  212. always @ *
  213. begin
  214. input_valid_r = data_strb_i & data_pid_q;
  215. input_byte_r = data_i;
  216. input_last_r = data_last_i;
  217. end
  218. reg data_accept_r;
  219. always @ *
  220. begin
  221. if (state_q == STATE_TX_DATA)
  222. data_accept_r = utmi_txready_i;
  223. else if (state_q == STATE_TX_PID && data_zlp_q)
  224. data_accept_r = utmi_txready_i;
  225. else
  226. data_accept_r = 1'b0;
  227. end
  228. assign data_accept_o = data_accept_r;
  229. //-----------------------------------------------------------------
  230. // CRC16: Generate CRC16 on outgoing data
  231. //-----------------------------------------------------------------
  232. reg [15:0] crc_sum_q;
  233. wire [15:0] crc_out_w;
  234. reg crc_err_q;
  235. `ifdef USB_RANDOM_CORRUPT
  236. reg [`USB_RANDOM_CORRUPT-1:0] corrupt_ctr_q;
  237. always @(posedge clk_i)
  238. corrupt_ctr_q <= corrupt_ctr_q + 1'b1;
  239. wire corrupt_tx = !corrupt_ctr_q;
  240. `else
  241. wire corrupt_tx = 1'b0;
  242. `endif
  243. usbf_crc16
  244. u_crc16
  245. (
  246. .crc_in_i(crc_sum_q),
  247. .din_i(utmi_data_o),
  248. .crc_out_o(crc_out_w)
  249. );
  250. always @ (posedge clk_i or posedge rst_i)
  251. if (rst_i)
  252. crc_sum_q <= 16'hFFFF;
  253. else if (state_q == STATE_TX_IDLE)
  254. crc_sum_q <= 16'hFFFF ^ corrupt_tx;
  255. else if (state_q == STATE_TX_DATA && utmi_txvalid_o && utmi_txready_i)
  256. crc_sum_q <= crc_out_w;
  257. //-----------------------------------------------------------------
  258. // Output
  259. //-----------------------------------------------------------------
  260. reg valid_q;
  261. reg [7:0] data_q;
  262. always @ (posedge clk_i or posedge rst_i)
  263. if (rst_i)
  264. begin
  265. valid_q <= 1'b0;
  266. data_q <= 8'b0;
  267. end
  268. else if (!enable_i)
  269. begin
  270. valid_q <= 1'b0;
  271. data_q <= 8'b0;
  272. end
  273. else if (tx_valid_i && tx_accept_o)
  274. begin
  275. valid_q <= 1'b1;
  276. data_q <= tx_pid_i;
  277. end
  278. else if (utmi_txready_i)
  279. begin
  280. valid_q <= 1'b0;
  281. data_q <= 8'b0;
  282. end
  283. reg utmi_txvalid_r;
  284. reg [7:0] utmi_data_r;
  285. always @ *
  286. begin
  287. if (state_q == STATE_TX_CHIRP)
  288. begin
  289. utmi_txvalid_r = 1'b1;
  290. utmi_data_r = 8'b0;
  291. end
  292. else if (state_q == STATE_TX_CRC1)
  293. begin
  294. utmi_txvalid_r = 1'b1;
  295. utmi_data_r = crc_sum_q[7:0] ^ 8'hFF;
  296. end
  297. else if (state_q == STATE_TX_CRC2)
  298. begin
  299. utmi_txvalid_r = 1'b1;
  300. utmi_data_r = crc_sum_q[15:8] ^ 8'hFF;
  301. end
  302. else if (state_q == STATE_TX_DATA)
  303. begin
  304. utmi_txvalid_r = data_valid_i;
  305. utmi_data_r = data_i;
  306. end
  307. else
  308. begin
  309. utmi_txvalid_r = valid_q;
  310. utmi_data_r = data_q;
  311. end
  312. end
  313. assign utmi_txvalid_o = utmi_txvalid_r;
  314. assign utmi_data_o = utmi_data_r;
  315. endmodule