hw/ip/usb_fs_nb_pe/rtl/usb_fs_tx.sv Cov: 100%

   1: // Copyright lowRISC contributors.
   2: // Copyright ETH Zurich.
   3: // Copyright Luke Valenty (TinyFPGA project, https://github.com/tinyfpga/TinyFPGA-Bootloader).
   4: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
   5: // SPDX-License-Identifier: Apache-2.0
   6: 
   7: module usb_fs_tx (
   8:   // A 48MHz clock is required to receive USB data at 12MHz
   9:   // it's simpler to juse use 48MHz everywhere
  10:   input  logic clk_i,
  11:   input  logic rst_ni,  // asyc reset
  12:   input  logic link_reset_i, // USB reset, sync to 48 MHz, active high
  13: 
  14:   // Oscillator test mode (constantly output JK)
  15:   input  logic tx_osc_test_mode_i,
  16: 
  17:   // bit strobe from rx to align with senders clock
  18:   input  logic bit_strobe_i,
  19: 
  20:   // output enable to take ownership of bus and data out
  21:   output logic usb_oe_o,
  22:   output logic usb_d_o,
  23:   output logic usb_se0_o,
  24: 
  25:   // pulse to initiate new packet transmission
  26:   input  logic pkt_start_i,
  27:   output logic pkt_end_o,
  28: 
  29:   // pid_i to send
  30:   input  logic [3:0] pid_i,
  31: 
  32:   // tx logic pulls data until there is nothing available
  33:   input  logic tx_data_avail_i,
  34:   output logic tx_data_get_o,
  35:   input  logic [7:0] tx_data_i
  36: );
  37: 
  38: 
  39:   typedef enum logic [2:0] {Idle, Sync, Pid, DataOrCrc160, Crc161, Eop, OscTest} state_e;
  40:   typedef enum logic [1:0] {OsIdle, OsWaitByte, OsTransmit} out_state_e;
  41: 
  42: 
  43:   /////////////////////////
  44:   // Signal Declarations //
  45:   /////////////////////////
  46:   logic [3:0] pid_q, pid_d;
  47:   logic bitstuff;
  48:   logic bitstuff_q;
  49:   logic bitstuff_q2;
  50:   logic bitstuff_q3;
  51:   logic bitstuff_q4;
  52: 
  53:   logic [5:0] bit_history;
  54: 
  55:   state_e      state_d, state_q;
  56:   out_state_e  out_state_d, out_state_q;
  57: 
  58: 
  59:   logic [7:0] data_shift_reg_q, data_shift_reg_d;
  60:   logic [7:0] oe_shift_reg_q, oe_shift_reg_d;
  61:   logic [7:0] se0_shift_reg_q, se0_shift_reg_d;
  62:   logic data_payload_q, data_payload_d;
  63:   logic tx_data_get_q, tx_data_get_d;
  64:   logic byte_strobe_q, byte_strobe_d;
  65:   logic [4:0] bit_history_d, bit_history_q;
  66:   logic [2:0] bit_count_d, bit_count_q;
  67: 
  68:   logic [15:0] crc16_d, crc16_q;
  69: 
  70:   logic oe_q, oe_d;
  71:   logic usb_d_q, usb_d_d;
  72:   logic usb_se0_q, usb_se0_d;
  73:   logic [2:0] dp_eop_q, dp_eop_d;
  74: 
  75:   logic test_mode_start;
  76:   logic serial_tx_data;
  77:   logic serial_tx_oe;
  78:   logic serial_tx_se0;
  79:   logic crc16_invert;
  80:   logic pkt_end;
  81:   logic out_nrzi_en;
  82: 
  83:   // save packet parameters at pkt_start_i
  84:   always_ff @(posedge clk_i or negedge rst_ni) begin : proc_pid
  85:     if (!rst_ni) begin
  86:       pid_q <= 0;
  87:     end else begin
  88:       if (link_reset_i) begin
  89:         pid_q <= 0;
  90:       end else begin
  91:         pid_q <= pid_d;
  92:       end
  93:     end
  94:   end
  95: 
  96:   assign pid_d = pkt_start_i ? pid_i : pid_q;
  97: 
  98: 
  99:   assign serial_tx_data = data_shift_reg_q[0];
 100:   assign serial_tx_oe = oe_shift_reg_q[0];
 101:   assign serial_tx_se0 = se0_shift_reg_q[0];
 102: 
 103: 
 104:   // serialize sync, pid_i, data payload, and crc16
 105:   assign bit_history = {serial_tx_data, bit_history_q};
 106:   assign bitstuff    = bit_history == 6'b111111;
 107: 
 108:   always_ff @(posedge clk_i or negedge rst_ni) begin : proc_bitstuff
 109:     if (!rst_ni) begin
 110:       bitstuff_q  <= 0;
 111:       bitstuff_q2 <= 0;
 112:       bitstuff_q3 <= 0;
 113:       bitstuff_q4 <= 0;
 114:     end else begin
 115:       if (link_reset_i) begin
 116:         bitstuff_q  <= 0;
 117:         bitstuff_q2 <= 0;
 118:         bitstuff_q3 <= 0;
 119:         bitstuff_q4 <= 0;
 120:       end else begin
 121:         bitstuff_q  <= bitstuff;
 122:         bitstuff_q2 <= bitstuff_q;
 123:         bitstuff_q3 <= bitstuff_q2;
 124:         bitstuff_q4 <= bitstuff_q3;
 125:       end
 126:     end
 127:   end
 128: 
 129:   assign pkt_end   = bit_strobe_i && se0_shift_reg_q[1:0] == 2'b01;
 130:   assign pkt_end_o = pkt_end;
 131: 
 132: 
 133:   /////////
 134:   // FSM //
 135:   /////////
 136:   always_comb begin : proc_fsm
 137:     // Default assignments
 138:     state_d          = state_q;
 139:     data_shift_reg_d = data_shift_reg_q;
 140:     oe_shift_reg_d   = oe_shift_reg_q;
 141:     se0_shift_reg_d  = se0_shift_reg_q;
 142:     data_payload_d   = data_payload_q;
 143:     tx_data_get_d    = tx_data_get_q;
 144:     bit_history_d    = bit_history_q;
 145:     bit_count_d      = bit_count_q;
 146:     test_mode_start  = 0;
 147: 
 148: 
 149:     unique case (state_q)
 150:       Idle : begin
 151:         if (tx_osc_test_mode_i) begin
 152:           state_d         = OscTest;
 153:           test_mode_start = 1;
 154:         end else if (pkt_start_i) begin
 155:           state_d = Sync;
 156:         end
 157:       end
 158: 
 159:       Sync : begin
 160:         if (byte_strobe_q) begin
 161:           state_d = Pid;
 162:           data_shift_reg_d = 8'b10000000;
 163:           oe_shift_reg_d = 8'b11111111;
 164:           se0_shift_reg_d = 8'b00000000;
 165:         end
 166:       end
 167: 
 168:       Pid : begin
 169:         if (byte_strobe_q) begin
 170:           if (pid_q[1:0] == 2'b11) begin
 171:             state_d = DataOrCrc160;
 172:           end else begin
 173:             state_d = Eop;
 174:           end
 175: 
 176:           data_shift_reg_d = {~pid_q, pid_q};
 177:           oe_shift_reg_d = 8'b11111111;
 178:           se0_shift_reg_d = 8'b00000000;
 179:         end
 180:       end
 181: 
 182:       DataOrCrc160 : begin
 183:         if (byte_strobe_q) begin
 184:           if (tx_data_avail_i) begin
 185:             state_d = DataOrCrc160;
 186:             data_payload_d = 1;
 187:             tx_data_get_d = 1;
 188:             data_shift_reg_d = tx_data_i;
 189:             oe_shift_reg_d = 8'b11111111;
 190:             se0_shift_reg_d = 8'b00000000;
 191:           end else begin
 192:             state_d = Crc161;
 193:             data_payload_d = 0;
 194:             tx_data_get_d = 0;
 195:             data_shift_reg_d = ~{crc16_q[8], crc16_q[9], crc16_q[10], crc16_q[11], crc16_q[12], crc16_q[13], crc16_q[14], crc16_q[15]};
 196:             oe_shift_reg_d = 8'b11111111;
 197:             se0_shift_reg_d = 8'b00000000;
 198:           end
 199:         end else begin
 200:           tx_data_get_d = 0;
 201:         end
 202:       end
 203: 
 204:       Crc161 : begin
 205:         if (byte_strobe_q) begin
 206:           state_d = Eop;
 207:           data_shift_reg_d = ~{crc16_q[0], crc16_q[1], crc16_q[2], crc16_q[3], crc16_q[4], crc16_q[5], crc16_q[6], crc16_q[7]};
 208:           oe_shift_reg_d = 8'b11111111;
 209:           se0_shift_reg_d = 8'b00000000;
 210:         end
 211:       end
 212: 
 213:       Eop : begin
 214:         if (byte_strobe_q) begin
 215:           state_d = Idle;
 216:           oe_shift_reg_d = 8'b00000111;
 217:           se0_shift_reg_d = 8'b00000111;
 218:         end
 219:       end
 220: 
 221:       OscTest: begin
 222:         // Oscillator test mode: toggle constantly
 223:         if (!tx_osc_test_mode_i && byte_strobe_q) begin
 224:           oe_shift_reg_d   = 8'b00000000;
 225:           state_d = Idle;
 226:         end else if (byte_strobe_q) begin
 227:           data_shift_reg_d = 8'b00000000;
 228:           oe_shift_reg_d   = 8'b11111111;
 229:           se0_shift_reg_d  = 8'b00000000;
 230:         end
 231:       end
 232:     endcase
 233: 
 234:     // Logic closely coupled to the FSM
 235:     if (pkt_start_i) begin
 236:       // We need to have a inter-packed delay between
 237:       // 2 and 6.5 bit times (see USB 2.0 spec / 7.1.18.1)
 238:       // The latency in the rest of the system is approximately (measured)
 239:       // 3.68 bit-times, so we only introduce 1 bit-time here
 240:       bit_count_d   = 7; // 8-7 = 1
 241:       bit_history_d = 0;
 242: 
 243:     end else if (bit_strobe_i) begin
 244:       // bitstuff
 245:       if (bitstuff /* && !serial_tx_se0*/) begin
 246:         bit_history_d       = bit_history[5:1];
 247:         data_shift_reg_d[0] = 0;
 248: 
 249:       // normal deserialize
 250:       end else begin
 251:         bit_count_d = bit_count_q + 1;
 252: 
 253:         data_shift_reg_d  = (data_shift_reg_q >> 1);
 254:         oe_shift_reg_d    = (oe_shift_reg_q >> 1);
 255:         se0_shift_reg_d   = (se0_shift_reg_q >> 1);
 256: 
 257:         bit_history_d = bit_history[5:1];
 258:       end
 259:     end
 260:   end
 261: 
 262:   always_comb begin : proc_byte_str
 263:     if (bit_strobe_i && !bitstuff && !pkt_start_i) begin
 264:       byte_strobe_d = (bit_count_q == 3'b000);
 265:     end else begin
 266:       byte_strobe_d = 0;
 267:     end
 268: 
 269:   end
 270: 
 271:   assign tx_data_get_o = tx_data_get_q;
 272: 
 273:   // calculate crc16
 274:   assign crc16_invert = serial_tx_data ^ crc16_q[15];
 275: 
 276:   always_comb begin : proc_crc16
 277:     crc16_d = crc16_q; // default assignment
 278: 
 279:     if (pkt_start_i) begin
 280:       crc16_d = 16'b1111111111111111;
 281:     end
 282: 
 283:     if (bit_strobe_i && data_payload_q && !bitstuff_q4 && !pkt_start_i) begin
 284:       crc16_d = {crc16_q[14:0], 1'b0} ^ ({16{crc16_invert}} & 16'b1000000000000101);
 285:     end
 286:   end
 287: 
 288:   ///////////////////////
 289:   // Regular Registers //
 290:   ///////////////////////
 291: 
 292:   always_ff @(posedge clk_i or negedge rst_ni) begin : proc_reg
 293:     if (!rst_ni) begin
 294:       state_q           <= Idle;
 295:       data_payload_q    <= 0;
 296:       data_shift_reg_q  <= 0;
 297:       oe_shift_reg_q    <= 0;
 298:       se0_shift_reg_q   <= 0;
 299:       tx_data_get_q     <= 0;
 300:       byte_strobe_q     <= 0;
 301:       bit_history_q     <= 0;
 302:       bit_count_q       <= 0;
 303:       crc16_q           <= 0;
 304:     end else begin
 305:       if (link_reset_i) begin
 306:         state_q           <= Idle;
 307:         data_payload_q    <= 0;
 308:         data_shift_reg_q  <= 0;
 309:         oe_shift_reg_q    <= 0;
 310:         se0_shift_reg_q   <= 0;
 311:         tx_data_get_q     <= 0;
 312:         byte_strobe_q     <= 0;
 313:         bit_history_q     <= 0;
 314:         bit_count_q       <= 0;
 315:         crc16_q           <= 0;
 316:       end else begin
 317:         state_q           <= state_d;
 318:         data_payload_q    <= data_payload_d;
 319:         data_shift_reg_q  <= data_shift_reg_d;
 320:         oe_shift_reg_q    <= oe_shift_reg_d;
 321:         se0_shift_reg_q   <= se0_shift_reg_d;
 322:         tx_data_get_q     <= tx_data_get_d;
 323:         byte_strobe_q     <= byte_strobe_d;
 324:         bit_history_q     <= bit_history_d;
 325:         bit_count_q       <= bit_count_d;
 326:         crc16_q           <= crc16_d;
 327:       end
 328:     end
 329:   end
 330: 
 331:   ///////////////////////////////////
 332:   // nrzi and differential driving //
 333:   ///////////////////////////////////
 334: 
 335:   // Output FSM
 336:   always_comb begin : proc_out_fsm
 337:     out_state_d          = out_state_q;
 338:     out_nrzi_en          = 1'b0;
 339: 
 340:     unique case (out_state_q)
 341:       OsIdle: begin
 342:         if (pkt_start_i || test_mode_start) begin
 343:           out_state_d = OsWaitByte;
 344:         end
 345:       end
 346: 
 347:       OsWaitByte: begin
 348:         if (byte_strobe_q) begin
 349:           out_state_d = OsTransmit;
 350:         end
 351:       end
 352: 
 353:       OsTransmit: begin
 354:         out_nrzi_en          = 1'b1;
 355:         if ((bit_strobe_i && !serial_tx_oe)) begin
 356:           out_state_d = OsIdle;
 357:         end
 358:       end
 359: 
 360:       default : out_state_d = OsIdle;
 361:     endcase
 362:   end
 363: 
 364:   always_comb begin : proc_diff
 365:     usb_d_d   = usb_d_q;
 366:     usb_se0_d = usb_se0_q;
 367:     oe_d     = oe_q;
 368:     dp_eop_d = dp_eop_q;
 369: 
 370:     if (pkt_start_i) begin
 371:       usb_d_d = 1; // J -> first bit will be K (start of sync)
 372:       dp_eop_d = 3'b100; // Eop: {SE0, SE0, J}
 373: 
 374:     end else if (bit_strobe_i && out_nrzi_en) begin
 375:       oe_d = serial_tx_oe;
 376: 
 377:       if (serial_tx_se0) begin
 378:         // Eop
 379:         dp_eop_d = dp_eop_q >> 1;
 380: 
 381:         if (dp_eop_q[0]) begin
 382:           // last bit of Eop: J
 383:           usb_d_d   = 1;
 384:           usb_se0_d = 0;
 385:         end else begin
 386:           // first two bits of Eop: SE0
 387:           usb_se0_d = 1;
 388:         end
 389: 
 390:       end else if (serial_tx_data) begin
 391:         // value should stay the same, do nothing
 392: 
 393:       end else begin
 394:         usb_d_d = !usb_d_q;
 395:       end
 396: 
 397:       // Set to J state when OE=0 to avoid
 398:       // glitches
 399:       if (!oe_d) begin
 400:         usb_d_d = 1;
 401:       end
 402:     end
 403: 
 404:   end
 405: 
 406:   always_ff @(posedge clk_i or negedge rst_ni) begin : proc_diff_reg
 407:     if (!rst_ni) begin
 408:       dp_eop_q             <= 0;
 409:       oe_q                 <= 0;
 410:       usb_d_q              <= 1; // J state = idle state
 411:       usb_se0_q            <= 0;
 412:       out_state_q          <= OsIdle;
 413:     end else begin
 414:       if (link_reset_i) begin
 415:         dp_eop_q             <= 0;
 416:         oe_q                 <= 0;
 417:         usb_d_q              <= 1;
 418:         usb_se0_q            <= 0;
 419:         out_state_q          <= OsIdle;
 420:       end else begin
 421:         dp_eop_q             <= dp_eop_d;
 422:         oe_q                 <= oe_d;
 423:         usb_d_q              <= usb_d_d;
 424:         usb_se0_q            <= usb_se0_d;
 425:         out_state_q          <= out_state_d;
 426:       end
 427:     end
 428:   end
 429: 
 430:   assign usb_oe_o  = oe_q;
 431:   assign usb_d_o   = usb_d_q;
 432:   assign usb_se0_o = usb_se0_q;
 433: 
 434: endmodule
 435: