../src/lowrisc_ip_usb_fs_nb_pe_0.1/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:     unique case (state_q)
 149:       Idle : begin
 150:         if (tx_osc_test_mode_i) begin
 151:           state_d         = OscTest;
 152:           test_mode_start = 1;
 153:         end else if (pkt_start_i) begin
 154:           state_d = Sync;
 155:         end
 156:       end
 157: 
 158:       Sync : begin
 159:         if (byte_strobe_q) begin
 160:           state_d = Pid;
 161:           data_shift_reg_d = 8'b10000000;
 162:           oe_shift_reg_d = 8'b11111111;
 163:           se0_shift_reg_d = 8'b00000000;
 164:         end
 165:       end
 166: 
 167:       Pid : begin
 168:         if (byte_strobe_q) begin
 169:           if (pid_q[1:0] == 2'b11) begin
 170:             state_d = DataOrCrc160;
 171:           end else begin
 172:             state_d = Eop;
 173:           end
 174: 
 175:           data_shift_reg_d = {~pid_q, pid_q};
 176:           oe_shift_reg_d = 8'b11111111;
 177:           se0_shift_reg_d = 8'b00000000;
 178:         end
 179:       end
 180: 
 181:       DataOrCrc160 : begin
 182:         if (byte_strobe_q) begin
 183:           if (tx_data_avail_i) begin
 184:             state_d = DataOrCrc160;
 185:             data_payload_d = 1;
 186:             tx_data_get_d = 1;
 187:             data_shift_reg_d = tx_data_i;
 188:             oe_shift_reg_d = 8'b11111111;
 189:             se0_shift_reg_d = 8'b00000000;
 190:           end else begin
 191:             state_d = Crc161;
 192:             data_payload_d = 0;
 193:             tx_data_get_d = 0;
 194:             data_shift_reg_d = ~{crc16_q[8],  crc16_q[9],  crc16_q[10], crc16_q[11],
 195:                                  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],
 208:                                crc16_q[4], crc16_q[5], crc16_q[6], crc16_q[7]};
 209:           oe_shift_reg_d = 8'b11111111;
 210:           se0_shift_reg_d = 8'b00000000;
 211:         end
 212:       end
 213: 
 214:       Eop : begin
 215:         if (byte_strobe_q) begin
 216:           state_d = Idle;
 217:           oe_shift_reg_d = 8'b00000111;
 218:           se0_shift_reg_d = 8'b00000111;
 219:         end
 220:       end
 221: 
 222:       OscTest: begin
 223:         // Oscillator test mode: toggle constantly
 224:         if (!tx_osc_test_mode_i && byte_strobe_q) begin
 225:           oe_shift_reg_d   = 8'b00000000;
 226:           state_d = Idle;
 227:         end else if (byte_strobe_q) begin
 228:           data_shift_reg_d = 8'b00000000;
 229:           oe_shift_reg_d   = 8'b11111111;
 230:           se0_shift_reg_d  = 8'b00000000;
 231:         end
 232:       end
 233: 
 234:       default: state_d = Idle;
 235:     endcase
 236: 
 237:     // Logic closely coupled to the FSM
 238:     if (pkt_start_i) begin
 239:       // We need to have a inter-packed delay between
 240:       // 2 and 6.5 bit times (see USB 2.0 spec / 7.1.18.1)
 241:       // The latency in the rest of the system is approximately (measured)
 242:       // 3.68 bit-times, so we only introduce 1 bit-time here
 243:       bit_count_d   = 7; // 8-7 = 1
 244:       bit_history_d = 0;
 245: 
 246:     end else if (bit_strobe_i) begin
 247:       // bitstuff
 248:       if (bitstuff /* && !serial_tx_se0*/) begin
 249:         bit_history_d       = bit_history[5:1];
 250:         data_shift_reg_d[0] = 0;
 251: 
 252:       // normal deserialize
 253:       end else begin
 254:         bit_count_d = bit_count_q + 1;
 255: 
 256:         data_shift_reg_d  = (data_shift_reg_q >> 1);
 257:         oe_shift_reg_d    = (oe_shift_reg_q >> 1);
 258:         se0_shift_reg_d   = (se0_shift_reg_q >> 1);
 259: 
 260:         bit_history_d = bit_history[5:1];
 261:       end
 262:     end
 263:   end
 264: 
 265:   always_comb begin : proc_byte_str
 266:     if (bit_strobe_i && !bitstuff && !pkt_start_i) begin
 267:       byte_strobe_d = (bit_count_q == 3'b000);
 268:     end else begin
 269:       byte_strobe_d = 0;
 270:     end
 271: 
 272:   end
 273: 
 274:   assign tx_data_get_o = tx_data_get_q;
 275: 
 276:   // calculate crc16
 277:   assign crc16_invert = serial_tx_data ^ crc16_q[15];
 278: 
 279:   always_comb begin : proc_crc16
 280:     crc16_d = crc16_q; // default assignment
 281: 
 282:     if (pkt_start_i) begin
 283:       crc16_d = 16'b1111111111111111;
 284:     end
 285: 
 286:     if (bit_strobe_i && data_payload_q && !bitstuff_q4 && !pkt_start_i) begin
 287:       crc16_d = {crc16_q[14:0], 1'b0} ^ ({16{crc16_invert}} & 16'b1000000000000101);
 288:     end
 289:   end
 290: 
 291:   ///////////////////////
 292:   // Regular Registers //
 293:   ///////////////////////
 294: 
 295:   always_ff @(posedge clk_i or negedge rst_ni) begin : proc_reg
 296:     if (!rst_ni) begin
 297:       state_q           <= Idle;
 298:       data_payload_q    <= 0;
 299:       data_shift_reg_q  <= 0;
 300:       oe_shift_reg_q    <= 0;
 301:       se0_shift_reg_q   <= 0;
 302:       tx_data_get_q     <= 0;
 303:       byte_strobe_q     <= 0;
 304:       bit_history_q     <= 0;
 305:       bit_count_q       <= 0;
 306:       crc16_q           <= 0;
 307:     end else begin
 308:       if (link_reset_i) begin
 309:         state_q           <= Idle;
 310:         data_payload_q    <= 0;
 311:         data_shift_reg_q  <= 0;
 312:         oe_shift_reg_q    <= 0;
 313:         se0_shift_reg_q   <= 0;
 314:         tx_data_get_q     <= 0;
 315:         byte_strobe_q     <= 0;
 316:         bit_history_q     <= 0;
 317:         bit_count_q       <= 0;
 318:         crc16_q           <= 0;
 319:       end else begin
 320:         state_q           <= state_d;
 321:         data_payload_q    <= data_payload_d;
 322:         data_shift_reg_q  <= data_shift_reg_d;
 323:         oe_shift_reg_q    <= oe_shift_reg_d;
 324:         se0_shift_reg_q   <= se0_shift_reg_d;
 325:         tx_data_get_q     <= tx_data_get_d;
 326:         byte_strobe_q     <= byte_strobe_d;
 327:         bit_history_q     <= bit_history_d;
 328:         bit_count_q       <= bit_count_d;
 329:         crc16_q           <= crc16_d;
 330:       end
 331:     end
 332:   end
 333: 
 334:   ///////////////////////////////////
 335:   // nrzi and differential driving //
 336:   ///////////////////////////////////
 337: 
 338:   // Output FSM
 339:   always_comb begin : proc_out_fsm
 340:     out_state_d          = out_state_q;
 341:     out_nrzi_en          = 1'b0;
 342: 
 343:     unique case (out_state_q)
 344:       OsIdle: begin
 345:         if (pkt_start_i || test_mode_start) begin
 346:           out_state_d = OsWaitByte;
 347:         end
 348:       end
 349: 
 350:       OsWaitByte: begin
 351:         if (byte_strobe_q) begin
 352:           out_state_d = OsTransmit;
 353:         end
 354:       end
 355: 
 356:       OsTransmit: begin
 357:         out_nrzi_en          = 1'b1;
 358:         if ((bit_strobe_i && !serial_tx_oe)) begin
 359:           out_state_d = OsIdle;
 360:         end
 361:       end
 362: 
 363:       default : out_state_d = OsIdle;
 364:     endcase
 365:   end
 366: 
 367:   always_comb begin : proc_diff
 368:     usb_d_d   = usb_d_q;
 369:     usb_se0_d = usb_se0_q;
 370:     oe_d     = oe_q;
 371:     dp_eop_d = dp_eop_q;
 372: 
 373:     if (pkt_start_i) begin
 374:       usb_d_d = 1; // J -> first bit will be K (start of sync)
 375:       dp_eop_d = 3'b100; // Eop: {SE0, SE0, J}
 376: 
 377:     end else if (bit_strobe_i && out_nrzi_en) begin
 378:       oe_d = serial_tx_oe;
 379: 
 380:       if (serial_tx_se0) begin
 381:         // Eop
 382:         dp_eop_d = dp_eop_q >> 1;
 383: 
 384:         if (dp_eop_q[0]) begin
 385:           // last bit of Eop: J
 386:           usb_d_d   = 1;
 387:           usb_se0_d = 0;
 388:         end else begin
 389:           // first two bits of Eop: SE0
 390:           usb_se0_d = 1;
 391:         end
 392: 
 393:       end else if (serial_tx_data) begin
 394:         // value should stay the same, do nothing
 395: 
 396:       end else begin
 397:         usb_d_d = !usb_d_q;
 398:       end
 399: 
 400:       // Set to J state when OE=0 to avoid
 401:       // glitches
 402:       if (!oe_d) begin
 403:         usb_d_d = 1;
 404:       end
 405:     end
 406: 
 407:   end
 408: 
 409:   always_ff @(posedge clk_i or negedge rst_ni) begin : proc_diff_reg
 410:     if (!rst_ni) begin
 411:       dp_eop_q             <= 0;
 412:       oe_q                 <= 0;
 413:       usb_d_q              <= 1; // J state = idle state
 414:       usb_se0_q            <= 0;
 415:       out_state_q          <= OsIdle;
 416:     end else begin
 417:       if (link_reset_i) begin
 418:         dp_eop_q             <= 0;
 419:         oe_q                 <= 0;
 420:         usb_d_q              <= 1;
 421:         usb_se0_q            <= 0;
 422:         out_state_q          <= OsIdle;
 423:       end else begin
 424:         dp_eop_q             <= dp_eop_d;
 425:         oe_q                 <= oe_d;
 426:         usb_d_q              <= usb_d_d;
 427:         usb_se0_q            <= usb_se0_d;
 428:         out_state_q          <= out_state_d;
 429:       end
 430:     end
 431:   end
 432: 
 433:   assign usb_oe_o  = oe_q;
 434:   assign usb_d_o   = usb_d_q;
 435:   assign usb_se0_o = usb_se0_q;
 436: 
 437: endmodule
 438: