├── TODO ├── load.py ├── core ├── usb3 │ ├── usb3_descrip_rom.v │ ├── usb3_ep0in_ram.v │ ├── usb3_ep_ram.v │ ├── usb_descrip.vh │ ├── usb3_lfsr.v │ ├── usb3_scramble.v │ ├── usb3_ep.v │ ├── usb3_descramble.v │ ├── usb3_const.vh │ ├── usb3_ep0.v │ ├── usb3_protocol.v │ ├── usb3_top.v │ └── usb3_ltssm.v ├── usb2 │ ├── usb2_descrip_rom.v │ ├── usb2_ep0in_ram.v │ ├── usb2_ep_ram.v │ ├── usb_descrip.vh │ ├── usb2_crc.v │ ├── usb2_ep.v │ ├── usb2_top.v │ ├── usb2_protocol.v │ ├── usb2_ep0.v │ ├── usb2_ulpi.v │ └── usb2_packet.v ├── README ├── license.txt ├── readme.txt └── usb_descrip_gen.c ├── test ├── test_usb2.py └── test_usb3.py └── README.md /TODO: -------------------------------------------------------------------------------- 1 | - add IN/OUT endpoints loopback 2 | - add host software and test loopback -------------------------------------------------------------------------------- /load.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from litex.build.xilinx import VivadoProgrammer 3 | 4 | prog = VivadoProgrammer() 5 | prog.load_bitstream("build/gateware/top.bit") 6 | -------------------------------------------------------------------------------- /core/usb3/usb3_descrip_rom.v: -------------------------------------------------------------------------------- 1 | // 128x32b rom 2 | // read latency: 2 clocks 3 | 4 | module usb3_descrip_rom( 5 | input clk, 6 | input [6:0] adr, 7 | output reg [31:0] dat_r 8 | ); 9 | 10 | reg [31:0] mem[0:127]; 11 | reg [6:0] memadr; 12 | always @(posedge clk) begin 13 | memadr <= adr; 14 | dat_r = mem[memadr]; 15 | end 16 | 17 | initial begin 18 | $readmemh("usb3_descrip_rom.init", mem); 19 | end 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /core/usb2/usb2_descrip_rom.v: -------------------------------------------------------------------------------- 1 | // 256x8b rom 2 | // read latency: 1 clock 3 | 4 | module usb2_descrip_rom( 5 | input clk, 6 | input [7:0] adr, 7 | output [7:0] dat_r 8 | ); 9 | 10 | reg [7:0] mem[0:255]; 11 | reg [7:0] memadr; 12 | always @(posedge clk) begin 13 | memadr <= adr; 14 | end 15 | 16 | assign dat_r = mem[memadr]; 17 | 18 | initial begin 19 | $readmemh("usb2_descrip_rom.init", mem); 20 | end 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /test/test_usb2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import time 3 | 4 | from litex.soc.tools.remote.comm_udp import CommUDP 5 | 6 | wb = CommUDP("192.168.1.50", 1234, debug=False) 7 | wb.open() 8 | 9 | # # # 10 | 11 | # disable usb2 phy & core 12 | wb.regs.usb2_control_phy_enable.write(0) 13 | wb.regs.usb2_control_core_enable.write(0) 14 | 15 | # enable usb2 phy 16 | wb.regs.usb2_control_phy_enable.write(1) 17 | 18 | # enable usb2 core 19 | wb.regs.usb2_control_core_enable.write(1) 20 | 21 | # # # 22 | 23 | wb.close() 24 | -------------------------------------------------------------------------------- /core/usb2/usb2_ep0in_ram.v: -------------------------------------------------------------------------------- 1 | // 64x8b ram (1 write / 1 read / 1 clock) 2 | // read latency: 2 clocks 3 | 4 | module usb2_ep0in_ram( 5 | input clk, 6 | input wr_we, 7 | input [5:0] wr_adr, 8 | input [7:0] wr_dat_w, 9 | input [5:0] rd_adr, 10 | output reg [7:0] rd_dat_r 11 | 12 | ); 13 | 14 | reg [7:0] mem[0:63]; 15 | reg [5:0] rd_adr_i; 16 | always @(posedge clk) begin 17 | if (wr_we) 18 | mem[wr_adr] <= wr_dat_w; 19 | end 20 | 21 | always @(posedge clk) begin 22 | rd_adr_i <= rd_adr; 23 | rd_dat_r = mem[rd_adr_i]; 24 | end 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /core/usb3/usb3_ep0in_ram.v: -------------------------------------------------------------------------------- 1 | // 16x32b ram (1 write / 1 read / 1 clock) 2 | // read latency: 2 clocks 3 | 4 | module usb3_ep0in_ram( 5 | input clk, 6 | input wr_we, 7 | input [3:0] wr_adr, 8 | input [31:0] wr_dat_w, 9 | input [3:0] rd_adr, 10 | output reg [31:0] rd_dat_r 11 | 12 | ); 13 | 14 | reg [31:0] mem[0:15]; 15 | reg [3:0] rd_adr_i; 16 | always @(posedge clk) begin 17 | if (wr_we) 18 | mem[wr_adr] <= wr_dat_w; 19 | end 20 | 21 | always @(posedge clk) begin 22 | rd_adr_i <= rd_adr; 23 | rd_dat_r = mem[rd_adr_i]; 24 | end 25 | 26 | endmodule 27 | -------------------------------------------------------------------------------- /core/README: -------------------------------------------------------------------------------- 1 | Daisho USB Core 2 | 3 | This is an open source USB 3.0 core. It can be used to implement a USB device 4 | on an FPGA with a USB 3.0 transceiver such as the TUSB1310A. It can also 5 | operate in USB 2.0 mode with a ULPI transceiver. 6 | 7 | This core is being developed for the Altera Cyclone IV. Operation on other 8 | FPGA platforms may be possible with some work. 9 | 10 | Planned functionality includes device (not host) operation in USB 2.0 and 3.0 11 | (including SuperSpeed) modes. 12 | 13 | The core is part of Project Daisho but may be used on other platforms. 14 | -------------------------------------------------------------------------------- /core/usb2/usb2_ep_ram.v: -------------------------------------------------------------------------------- 1 | // 1024x8b ram (1 write / 1 read / 2 clocks) 2 | // read latency: 1 clock 3 | 4 | module usb2_ep_ram( 5 | input wr_clk, 6 | input wr_we, 7 | input [9:0] wr_adr, 8 | input [7:0] wr_dat_w, 9 | 10 | input rd_clk, 11 | input [9:0] rd_adr, 12 | output [7:0] rd_dat_r 13 | ); 14 | 15 | reg [7:0] mem[0:1023]; 16 | reg [9:0] rd_adr_i; 17 | always @(posedge wr_clk) begin 18 | if (wr_we) 19 | mem[wr_adr] <= wr_dat_w; 20 | end 21 | 22 | always @(posedge rd_clk) begin 23 | rd_adr_i <= rd_adr; 24 | end 25 | 26 | assign rd_dat_r = mem[rd_adr_i]; 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /core/usb3/usb3_ep_ram.v: -------------------------------------------------------------------------------- 1 | // 1024x32b ram (1 write / 1 read / 2 clocks) 2 | // read latency: 2 clocks 3 | 4 | module usb3_ep_ram( 5 | input wr_clk, 6 | input wr_rst, 7 | input wr_we, 8 | input [9:0] wr_adr, 9 | input [31:0] wr_dat_w, 10 | 11 | input rd_clk, 12 | input rd_rst, 13 | input [9:0] rd_adr, 14 | output reg [31:0] rd_dat_r 15 | ); 16 | 17 | reg [31:0] mem[0:1023]; 18 | reg [9:0] rd_adr_i; 19 | always @(posedge wr_clk) begin 20 | if (wr_we) 21 | mem[wr_adr] <= wr_dat_w; 22 | end 23 | 24 | always @(posedge rd_clk) begin 25 | rd_adr_i <= rd_adr; 26 | rd_dat_r = mem[rd_adr_i]; 27 | end 28 | 29 | endmodule 30 | -------------------------------------------------------------------------------- /test/test_usb3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import time 3 | 4 | from litex.soc.tools.remote.comm_udp import CommUDP 5 | 6 | wb = CommUDP("192.168.1.50", 1234, debug=False) 7 | wb.open() 8 | 9 | # # # 10 | 11 | # disable usb2 phy & core 12 | wb.regs.usb2_control_phy_enable.write(0) 13 | wb.regs.usb2_control_core_enable.write(0) 14 | 15 | # disable usb3 phy & core 16 | wb.regs.usb3_control_phy_enable.write(0) 17 | wb.regs.usb3_control_core_enable.write(0) 18 | 19 | # enable usb2 & usb3 phy 20 | wb.regs.usb2_control_phy_enable.write(1) 21 | wb.regs.usb3_control_phy_enable.write(1) 22 | 23 | # enable usb2 & usb3 core 24 | wb.regs.usb2_control_core_enable.write(1) 25 | wb.regs.usb3_control_core_enable.write(1) 26 | 27 | # # # 28 | 29 | wb.close() 30 | -------------------------------------------------------------------------------- /core/usb2/usb_descrip.vh: -------------------------------------------------------------------------------- 1 | parameter [7:0] DESCR_USB2_DEVICE = 'd0; 2 | parameter [6:0] DESCR_USB3_DEVICE = 'd0; 3 | parameter [7:0] DESCR_USB2_DEVICE_QUAL = 'd18; 4 | parameter [7:0] DESCR_USB2_CONFIG = 'd28; 5 | parameter [6:0] DESCR_USB3_CONFIG = 'd5; 6 | parameter [7:0] DESCR_USB2_CONFIG_LEN = 'd41; 7 | parameter [6:0] DESCR_USB3_CONFIG_LEN = 'd53; 8 | parameter [6:0] DESCR_USB3_BOS = 'd19; 9 | parameter [6:0] DESCR_USB3_BOS_LEN = 'd22; 10 | parameter [7:0] DESCR_USB2_STRING0 = 'd69; 11 | parameter [6:0] DESCR_USB3_STRING0 = 'd25; 12 | parameter [7:0] DESCR_USB2_STRING1 = 'd73; 13 | parameter [6:0] DESCR_USB3_STRING1 = 'd26; 14 | parameter [7:0] DESCR_USB2_STRING2 = 'd113; 15 | parameter [6:0] DESCR_USB3_STRING2 = 'd36; 16 | parameter [7:0] DESCR_USB2_STRING3 = 'd145; 17 | parameter [6:0] DESCR_USB3_STRING3 = 'd44; 18 | parameter [7:0] DESCR_USB2_CONFUNSET = 'd171; 19 | parameter [6:0] DESCR_USB3_CONFUNSET = 'd51; 20 | parameter [7:0] DESCR_USB2_CONFSET = 'd172; 21 | parameter [6:0] DESCR_USB3_CONFSET = 'd52; 22 | parameter [7:0] DESCR_USB2_EOF = 'd173; 23 | parameter [6:0] DESCR_USB3_EOF = 'd53; 24 | -------------------------------------------------------------------------------- /core/usb3/usb_descrip.vh: -------------------------------------------------------------------------------- 1 | parameter [7:0] DESCR_USB2_DEVICE = 'd0; 2 | parameter [6:0] DESCR_USB3_DEVICE = 'd0; 3 | parameter [7:0] DESCR_USB2_DEVICE_QUAL = 'd18; 4 | parameter [7:0] DESCR_USB2_CONFIG = 'd28; 5 | parameter [6:0] DESCR_USB3_CONFIG = 'd5; 6 | parameter [7:0] DESCR_USB2_CONFIG_LEN = 'd41; 7 | parameter [6:0] DESCR_USB3_CONFIG_LEN = 'd53; 8 | parameter [6:0] DESCR_USB3_BOS = 'd19; 9 | parameter [6:0] DESCR_USB3_BOS_LEN = 'd22; 10 | parameter [7:0] DESCR_USB2_STRING0 = 'd69; 11 | parameter [6:0] DESCR_USB3_STRING0 = 'd25; 12 | parameter [7:0] DESCR_USB2_STRING1 = 'd73; 13 | parameter [6:0] DESCR_USB3_STRING1 = 'd26; 14 | parameter [7:0] DESCR_USB2_STRING2 = 'd113; 15 | parameter [6:0] DESCR_USB3_STRING2 = 'd36; 16 | parameter [7:0] DESCR_USB2_STRING3 = 'd145; 17 | parameter [6:0] DESCR_USB3_STRING3 = 'd44; 18 | parameter [7:0] DESCR_USB2_CONFUNSET = 'd171; 19 | parameter [6:0] DESCR_USB3_CONFUNSET = 'd51; 20 | parameter [7:0] DESCR_USB2_CONFSET = 'd172; 21 | parameter [6:0] DESCR_USB3_CONFSET = 'd52; 22 | parameter [7:0] DESCR_USB2_EOF = 'd173; 23 | parameter [6:0] DESCR_USB3_EOF = 'd53; 24 | -------------------------------------------------------------------------------- /core/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2013, Marshall H. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Test of the USB3 IP Core from Daisho on a Xilinx device 2 | 3 | In this repository we are testing the USB3 IP Core from Daisho on a Xilinx device. 4 | 5 | * USB2 / ULPI working :) (vendor agnostic) 6 | * USB3 / PIPE working :) (IDDR/ODDR and PLL specific to Xilinx) 7 | 8 | This work was supported by [TimVideos.us](https://code.timvideos.us) and with a generous loan of a USB3.0 protocol analyzer from the Daisho project. 9 | 10 | The design currently uses a TUSB1310A for interfacing with the USB3.0 connector. Future plans include replacing this part using the high speed transceivers (GTPs/GTXs) found in Artix-7/Kintex-7 FPGAs. 11 | 12 | The current work is being done with; 13 | 14 | * Kintex 7 work[1] - [kc705 - Xilinx Kintex-7 FPGA KC705 Evaluation Kit](https://www.xilinx.com/products/boards-and-kits/ek-k7-kc705-g.html) 15 | * Artix 7 work[2] - [Nexys Video - Nexys Video Artix-7 FPGA: Trainer Board for Multimedia Applications](http://store.digilentinc.com/nexys-video-artix-7-fpga-trainer-board-for-multimedia-applications/) 16 | 17 | * USB3.0 work - [HiTech Global - 3-Port USB 3 FMC Module](https://hitechglobal.us/index.php?route=product/product&path=18&product_id=233). 18 | 19 | The FMC module has 3 x USB3.0 ports. Two are connected via TUSB1310A ICs and the third is connected directly to the high speed transceivers. 20 | 21 | [1]: As HA/HB pins from HPC FMC are not connected on Xilinx on devboards, second TUSB1310A is not usable with the KC705. 22 | 23 | [2]: As the Nexys Video has only a [LPC FMC connector](https://en.wikipedia.org/wiki/FPGA_Mezzanine_Card#LPC_vs._HPC), only a limited amount set of the functionality is avalible, but it is enough to prove the design also works on the Artix-7 FPGA. 24 | -------------------------------------------------------------------------------- /core/usb2/usb2_crc.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 2.0 crc5, crc16 4 | // 5 | // Copyright (c) 2012-2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb2_crc5 ( 12 | 13 | input wire [4:0] c, 14 | input wire [10:0] data, 15 | output wire [4:0] next_crc 16 | 17 | ); 18 | 19 | // reverse input 20 | wire [10:0] d = { data[0], data[1], data[2], data[3], data[4], 21 | data[5], data[6], data[7], data[8], data[9], 22 | data[10] }; 23 | 24 | wire [4:0] q = { 25 | ^d[10:9] ^ ^d[6:5] ^ d[3] ^ d[0] ^ c[0] ^ ^c[4:3], 26 | d[10] ^ ^d[7:6] ^ d[4] ^ d[1] ^ ^c[1:0] ^ c[4], 27 | ^d[10:7] ^ d[6] ^ ^d[3:2] ^ d[0] ^ ^c[4:0], 28 | ^d[10:7] ^^ d[4:3] ^ d[1] ^ ^c[4:1], 29 | ^d[10:8] ^ ^d[5:4] ^ d[2] ^ ^c[4:2] 30 | }; 31 | 32 | assign next_crc = ~q; 33 | 34 | endmodule 35 | 36 | 37 | // 38 | // usb 2.0 crc16 39 | // 40 | // Copyright (c) 2012-2013 Marshall H. 41 | // All rights reserved. 42 | // This code is released under the terms of the simplified BSD license. 43 | // See LICENSE.TXT for details. 44 | // 45 | 46 | module usb2_crc16 ( 47 | 48 | input wire [15:0] c, 49 | input wire [7:0] data, 50 | output wire [15:0] next_crc 51 | 52 | ); 53 | 54 | wire [7:0] d = {data[0], data[1], data[2], data[3], 55 | data[4], data[5], data[6], data[7]}; 56 | 57 | assign next_crc = { 58 | ^d[7:0] ^ ^c[15:7], 59 | c[6], 60 | c[5], 61 | c[4], 62 | c[3], 63 | c[2], 64 | d[7] ^ c[1] ^ c[15], 65 | ^d[7:6] ^ ^c[0] ^ ^c[15:14], 66 | ^d[6:5] ^ ^c[14:13], 67 | ^d[5:4] ^ ^c[13:12], 68 | ^d[4:3] ^ ^c[12:11], 69 | ^d[3:2] ^ ^c[11:10], 70 | ^d[2:1] ^ ^c[10:9], 71 | ^d[1:0] ^ ^c[9:8], 72 | ^d[7:1] ^ ^c[15:9], 73 | ^d[7:0] ^ ^c[15:8] 74 | }; 75 | 76 | endmodule 77 | -------------------------------------------------------------------------------- /core/usb3/usb3_lfsr.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 3.0 data scrambling lfsr 4 | // 5 | // Copyright (C) 2009 OutputLogic.com 6 | // This source file may be used and distributed without restriction 7 | // provided that this copyright statement is not removed from the file 8 | // and that any derivative work contains the original copyright notice 9 | // and the associated disclaimer. 10 | // 11 | // THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS 12 | // OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 13 | // WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 14 | // 15 | 16 | module usb3_lfsr ( 17 | 18 | input wire clock, 19 | input wire reset_n, 20 | 21 | input wire [31:0] data_in, 22 | input wire scram_en, 23 | input wire scram_rst, 24 | input wire [15:0] scram_init, 25 | output reg [31:0] data_out, 26 | output reg [31:0] data_out_reg 27 | 28 | ); 29 | 30 | reg [15:0] lfsr_q, lfsr_c; 31 | reg [31:0] data_c; 32 | 33 | always @(*) begin 34 | lfsr_c[0] = lfsr_q[0] ^ lfsr_q[6] ^ lfsr_q[8] ^ lfsr_q[10]; 35 | lfsr_c[1] = lfsr_q[1] ^ lfsr_q[7] ^ lfsr_q[9] ^ lfsr_q[11]; 36 | lfsr_c[2] = lfsr_q[2] ^ lfsr_q[8] ^ lfsr_q[10] ^ lfsr_q[12]; 37 | lfsr_c[3] = lfsr_q[3] ^ lfsr_q[6] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[13]; 38 | lfsr_c[4] = lfsr_q[4] ^ lfsr_q[6] ^ lfsr_q[7] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[14]; 39 | lfsr_c[5] = lfsr_q[5] ^ lfsr_q[6] ^ lfsr_q[7] ^ lfsr_q[9] ^ lfsr_q[12] ^ lfsr_q[13] ^ lfsr_q[15]; 40 | lfsr_c[6] = lfsr_q[0] ^ lfsr_q[6] ^ lfsr_q[7] ^ lfsr_q[8] ^ lfsr_q[10] ^ lfsr_q[13] ^ lfsr_q[14]; 41 | lfsr_c[7] = lfsr_q[1] ^ lfsr_q[7] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[11] ^ lfsr_q[14] ^ lfsr_q[15]; 42 | lfsr_c[8] = lfsr_q[0] ^ lfsr_q[2] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[12] ^ lfsr_q[15]; 43 | lfsr_c[9] = lfsr_q[1] ^ lfsr_q[3] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[13]; 44 | lfsr_c[10] = lfsr_q[0] ^ lfsr_q[2] ^ lfsr_q[4] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[14]; 45 | lfsr_c[11] = lfsr_q[1] ^ lfsr_q[3] ^ lfsr_q[5] ^ lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[13] ^ lfsr_q[15]; 46 | lfsr_c[12] = lfsr_q[2] ^ lfsr_q[4] ^ lfsr_q[6] ^ lfsr_q[12] ^ lfsr_q[13] ^ lfsr_q[14]; 47 | lfsr_c[13] = lfsr_q[3] ^ lfsr_q[5] ^ lfsr_q[7] ^ lfsr_q[13] ^ lfsr_q[14] ^ lfsr_q[15]; 48 | lfsr_c[14] = lfsr_q[4] ^ lfsr_q[6] ^ lfsr_q[8] ^ lfsr_q[14] ^ lfsr_q[15]; 49 | lfsr_c[15] = lfsr_q[5] ^ lfsr_q[7] ^ lfsr_q[9] ^ lfsr_q[15]; 50 | 51 | data_c[0] = data_in[0] ^ lfsr_q[15]; 52 | data_c[1] = data_in[1] ^ lfsr_q[14]; 53 | data_c[2] = data_in[2] ^ lfsr_q[13]; 54 | data_c[3] = data_in[3] ^ lfsr_q[12]; 55 | data_c[4] = data_in[4] ^ lfsr_q[11]; 56 | data_c[5] = data_in[5] ^ lfsr_q[10]; 57 | data_c[6] = data_in[6] ^ lfsr_q[9]; 58 | data_c[7] = data_in[7] ^ lfsr_q[8]; 59 | data_c[8] = data_in[8] ^ lfsr_q[7]; 60 | data_c[9] = data_in[9] ^ lfsr_q[6]; 61 | data_c[10] = data_in[10] ^ lfsr_q[5]; 62 | data_c[11] = data_in[11] ^ lfsr_q[4] ^ lfsr_q[15]; 63 | data_c[12] = data_in[12] ^ lfsr_q[3] ^ lfsr_q[14] ^ lfsr_q[15]; 64 | data_c[13] = data_in[13] ^ lfsr_q[2] ^ lfsr_q[13] ^ lfsr_q[14] ^ lfsr_q[15]; 65 | data_c[14] = data_in[14] ^ lfsr_q[1] ^ lfsr_q[12] ^ lfsr_q[13] ^ lfsr_q[14]; 66 | data_c[15] = data_in[15] ^ lfsr_q[0] ^ lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[13]; 67 | data_c[16] = data_in[16] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[12] ^ lfsr_q[15]; 68 | data_c[17] = data_in[17] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[11] ^ lfsr_q[14]; 69 | data_c[18] = data_in[18] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[10] ^ lfsr_q[13]; 70 | data_c[19] = data_in[19] ^ lfsr_q[7] ^ lfsr_q[8] ^ lfsr_q[9] ^ lfsr_q[12]; 71 | data_c[20] = data_in[20] ^ lfsr_q[6] ^ lfsr_q[7] ^ lfsr_q[8] ^ lfsr_q[11]; 72 | data_c[21] = data_in[21] ^ lfsr_q[5] ^ lfsr_q[6] ^ lfsr_q[7] ^ lfsr_q[10]; 73 | data_c[22] = data_in[22] ^ lfsr_q[4] ^ lfsr_q[5] ^ lfsr_q[6] ^ lfsr_q[9] ^ lfsr_q[15]; 74 | data_c[23] = data_in[23] ^ lfsr_q[3] ^ lfsr_q[4] ^ lfsr_q[5] ^ lfsr_q[8] ^ lfsr_q[14]; 75 | data_c[24] = data_in[24] ^ lfsr_q[2] ^ lfsr_q[3] ^ lfsr_q[4] ^ lfsr_q[7] ^ lfsr_q[13] ^ lfsr_q[15]; 76 | data_c[25] = data_in[25] ^ lfsr_q[1] ^ lfsr_q[2] ^ lfsr_q[3] ^ lfsr_q[6] ^ lfsr_q[12] ^ lfsr_q[14]; 77 | data_c[26] = data_in[26] ^ lfsr_q[0] ^ lfsr_q[1] ^ lfsr_q[2] ^ lfsr_q[5] ^ lfsr_q[11] ^ lfsr_q[13] ^ lfsr_q[15]; 78 | data_c[27] = data_in[27] ^ lfsr_q[0] ^ lfsr_q[1] ^ lfsr_q[4] ^ lfsr_q[10] ^ lfsr_q[12] ^ lfsr_q[14]; 79 | data_c[28] = data_in[28] ^ lfsr_q[0] ^ lfsr_q[3] ^ lfsr_q[9] ^ lfsr_q[11] ^ lfsr_q[13]; 80 | data_c[29] = data_in[29] ^ lfsr_q[2] ^ lfsr_q[8] ^ lfsr_q[10] ^ lfsr_q[12]; 81 | data_c[30] = data_in[30] ^ lfsr_q[1] ^ lfsr_q[7] ^ lfsr_q[9] ^ lfsr_q[11]; 82 | data_c[31] = data_in[31] ^ lfsr_q[0] ^ lfsr_q[6] ^ lfsr_q[8] ^ lfsr_q[10]; 83 | 84 | //data_out = scram_en ? data_c : data_out; 85 | data_out = data_c; 86 | end 87 | 88 | always @(posedge clock, negedge reset_n) begin 89 | if(~reset_n) begin 90 | lfsr_q <= scram_init; 91 | data_out_reg <= 32'h0; 92 | end else begin 93 | lfsr_q <= scram_rst ? scram_init : scram_en ? lfsr_c : lfsr_q; 94 | data_out_reg <= scram_en ? data_c : data_out_reg; 95 | end 96 | end 97 | 98 | endmodule 99 | 100 | -------------------------------------------------------------------------------- /core/usb3/usb3_scramble.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 3.0 tx scrambling and elastic buffer padding 4 | // 5 | // Copyright (c) 2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb3_scramble ( 12 | 13 | input wire clock, 14 | input wire local_clk, 15 | input wire reset_n, 16 | 17 | input wire enable, 18 | 19 | input wire skp_inhibit, 20 | input wire skp_defer, 21 | 22 | input wire [3:0] raw_datak, 23 | input wire [31:0] raw_data, 24 | input wire raw_active, 25 | output reg raw_stall, 26 | 27 | output reg [3:0] proc_datak, 28 | output reg [31:0] proc_data, 29 | 30 | output reg err_empty_accum 31 | ); 32 | 33 | `include "usb3_const.vh" 34 | 35 | reg reset_n_1; 36 | reg enable_1; 37 | 38 | // indicates presence of COM at last symbol position (K28.5) 39 | wire comma = { (pl_data[7:0] == 8'hBC) & pl_datak[0] }; 40 | reg comma_1; 41 | 42 | reg [31:0] pl_data; 43 | reg [3:0] pl_datak; 44 | reg pl_active; 45 | 46 | // step 1. 47 | // accept incoming data, but inject SKP sets to allow remote elastic buffer 48 | // to catch up and compensate for spread spectrum clocking. 49 | 50 | wire insert_skp = enable && symbols_since_skp > 78; 51 | // nominal SKP insertion rate is every 354 symbols. 52 | // however due to SSC profiles varying across the industry (i.e. +/- 2500ppm vs. -5000 to 0 ppm) 53 | // err on the safe side and send more SKP. 54 | 55 | reg [15:0] symbols_since_skp; 56 | reg [2:0] num_queued_skp; 57 | 58 | reg [31:0] ac_data; 59 | reg [3:0] ac_datak; 60 | 61 | always @(posedge local_clk) begin 62 | 63 | pl_data <= raw_data; 64 | pl_datak <= raw_datak; 65 | pl_active <= raw_active; 66 | 67 | reset_n_1 <= reset_n; 68 | comma_1 <= comma; 69 | enable_1 <= enable; 70 | 71 | raw_stall <= 0; 72 | 73 | // increment symbol sent counter 74 | if(enable_1) `INC(symbols_since_skp); 75 | if(insert_skp) begin 76 | symbols_since_skp <= 0; 77 | // increment number of queued sets up to 4 78 | if(num_queued_skp < 4) 79 | `INC(num_queued_skp); 80 | end 81 | 82 | if(enable_1) begin 83 | if(num_queued_skp == 0 || pl_active) begin 84 | // don't inject SKP 85 | ac_data[31:24] <= pl_datak[3] ? pl_data[31:24] : pl_data[31:24] ^ sp_pick32[31:24]; 86 | ac_data[23:16] <= pl_datak[2] ? pl_data[23:16] : pl_data[23:16] ^ sp_pick32[23:16]; 87 | ac_data[15:8 ] <= pl_datak[1] ? pl_data[15:8 ] : pl_data[15:8 ] ^ sp_pick32[15:8 ]; 88 | ac_data[ 7:0 ] <= pl_datak[0] ? pl_data[ 7:0 ] : pl_data[ 7:0 ] ^ sp_pick32[ 7:0 ]; 89 | ac_datak <= pl_datak; 90 | end else if(num_queued_skp == 1) begin 91 | // only 1 ordered set needed 92 | ac_data <= {16'h3C3C, pl_data[15:0] ^ sp_pick16[15:0]}; 93 | ac_datak <= {2'b11, pl_datak[1:0]}; 94 | raw_stall <= 1; 95 | `DEC(num_queued_skp); 96 | end else begin 97 | // 2 or more sets needed 98 | ac_data <= {32'h3C3C3C3C}; 99 | ac_datak <= {4'b1111}; 100 | raw_stall <= 1; 101 | num_queued_skp <= num_queued_skp - 2'h2; 102 | end 103 | end else begin 104 | ac_data <= pl_data; 105 | ac_datak <= pl_datak; 106 | end 107 | 108 | proc_data <= ac_data; 109 | proc_datak <= ac_datak; 110 | 111 | err_empty_accum <= 0; 112 | 113 | if(~enable_1) begin 114 | symbols_since_skp <= 0; 115 | num_queued_skp <= 0; 116 | end 117 | 118 | if(~reset_n) begin 119 | symbols_since_skp <= 0; 120 | end 121 | end 122 | 123 | always @(*) begin 124 | // 125 | // combinational to give us 1 cycle foresight so that 126 | // the lfsr pool can have next word prepared in time 127 | // 128 | if(enable_1) begin 129 | if(num_queued_skp == 0 || pl_active) begin 130 | // don't inject SKP 131 | sp_read_num = 4; 132 | end else if(num_queued_skp == 1) begin 133 | // only 1 ordered set needed 134 | sp_read_num = 2; 135 | end else begin 136 | // 2 or more sets needed 137 | sp_read_num = 0; 138 | end 139 | end else begin 140 | sp_read_num = 0; 141 | end 142 | end 143 | 144 | // 145 | // scrambling LFSR pool 146 | // 147 | 148 | reg [63:0] sp_data; 149 | reg [3:0] sp_depth; 150 | reg [3:0] sp_read_num; 151 | 152 | wire sp_dofill = ((sp_depth+8 - sp_read_num) <= 12); 153 | 154 | wire [15:0] sp_pick16 = sp_pick32[31:16]; 155 | wire [31:0] sp_pick32 = (sp_depth == 4) ? sp_data[31:0] : 156 | (sp_depth == 6) ? sp_data[47:16] : 157 | (sp_depth == 8) ? sp_data[63:32] : 32'hFFFFFFFF; 158 | 159 | always @(posedge local_clk) begin 160 | 161 | sp_depth <= sp_depth - sp_read_num + (sp_dofill ? 4'h4 : 4'h0); 162 | 163 | if(sp_dofill) sp_data <= {sp_data[31:0], ds_out}; 164 | 165 | if(~reset_n_1 | comma_1) begin 166 | sp_depth <= 0; 167 | //sp_data <= 32'hEEEEEEEE; 168 | end 169 | end 170 | 171 | 172 | // 173 | // data scrambling for TX 174 | // 175 | wire [31:0] ds_out = {ds_out_swap[7:0], ds_out_swap[15:8], 176 | ds_out_swap[23:16], ds_out_swap[31:24]}; 177 | wire [31:0] ds_out_swap; 178 | 179 | usb3_lfsr iu3srx( 180 | 181 | .clock ( local_clk ), 182 | .reset_n ( reset_n ), 183 | 184 | .data_in ( 32'h0 ), 185 | .scram_en ( comma | sp_dofill), 186 | .scram_rst ( comma | ~reset_n), 187 | .scram_init ( 16'h7DBD ), 188 | .data_out ( ds_out_swap ) 189 | 190 | ); 191 | 192 | endmodule 193 | -------------------------------------------------------------------------------- /core/usb3/usb3_ep.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 3.0 endpoint abstract 4 | // 5 | // Copyright (c) 2014 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb3_ep ( 12 | 13 | input wire slow_clk, 14 | input wire local_clk, 15 | input wire rd_clk, 16 | input wire wr_clk, 17 | input wire reset_n, 18 | 19 | input wire [8:0] buf_in_addr, 20 | input wire [31:0] buf_in_data, 21 | input wire buf_in_wren, 22 | output wire buf_in_request, 23 | output wire buf_in_ready, 24 | input wire buf_in_commit, 25 | input wire [10:0] buf_in_commit_len, 26 | output wire buf_in_commit_ack, 27 | 28 | input wire [8:0] buf_out_addr, 29 | output wire [31:0] buf_out_q, 30 | output wire [10:0] buf_out_len, 31 | output wire buf_out_hasdata, 32 | input wire buf_out_arm, 33 | output wire buf_out_arm_ack, 34 | 35 | input wire [1:0] mode 36 | 37 | ); 38 | 39 | `include "usb3_const.vh" 40 | 41 | // synchronizers 42 | reg reset_1, reset_2; 43 | reg buf_in_commit_1, buf_in_commit_2, buf_in_commit_3; 44 | reg buf_out_arm_1, buf_out_arm_2, buf_out_arm_3; 45 | 46 | // for keeping track of the endpoint double buffering 47 | reg ptr_in;//, ptr_in_; 48 | reg ptr_out;//, ptr_out_; 49 | 50 | reg [10:0] len_in; 51 | reg ready_in_a; 52 | reg ready_in_b; 53 | assign buf_in_ready = ptr_in ? ready_in_b : ready_in_a; 54 | assign buf_in_commit_ack = (state_in == ST_IN_COMMIT || state_in == ST_IN_SWAP); 55 | 56 | reg [10:0] len_out_a; 57 | reg [10:0] len_out_b; 58 | reg hasdata_out_a; 59 | reg hasdata_out_b; 60 | assign buf_out_len = ptr_out ? len_out_b : len_out_a; 61 | assign buf_out_hasdata = ptr_out ? hasdata_out_b : hasdata_out_a; 62 | assign buf_out_arm_ack = (state_out == ST_OUT_ARM || state_out == ST_OUT_SWAP); 63 | 64 | parameter [1:0] EP_MODE_CONTROL = 2'd0, 65 | EP_MODE_ISOCH = 2'd1, 66 | EP_MODE_BULK = 2'd2, 67 | EP_MODE_INTERRUPT = 2'd3; 68 | 69 | reg [3:0] dc; 70 | 71 | reg [5:0] state_in; 72 | parameter [5:0] ST_RST_0 = 6'd0, 73 | ST_RST_1 = 6'd1, 74 | ST_IDLE = 6'd10, 75 | ST_IN_COMMIT = 6'd11, 76 | ST_IN_SWAP = 6'd12; 77 | 78 | reg [5:0] state_out; 79 | parameter [5:0] ST_OUT_ARM = 6'd11, 80 | ST_OUT_SWAP = 6'd12; 81 | 82 | always @(posedge local_clk) begin 83 | 84 | // synchronizers 85 | {reset_2, reset_1} <= {reset_1, reset_n}; 86 | {buf_in_commit_3, buf_in_commit_2, buf_in_commit_1} <= 87 | {buf_in_commit_2, buf_in_commit_1, buf_in_commit}; 88 | {buf_out_arm_3, buf_out_arm_2, buf_out_arm_1} <= 89 | {buf_out_arm_2, buf_out_arm_1, buf_out_arm}; 90 | 91 | dc <= dc + 1'b1; 92 | 93 | //ptr_in_ <= ptr_in; 94 | //ptr_out_ <= ptr_out; 95 | 96 | // input FSM 97 | // 98 | case(state_in) 99 | ST_RST_0: begin 100 | // reset buffer index 101 | ptr_in <= 0; 102 | 103 | ready_in_a <= 1; 104 | ready_in_b <= 1; 105 | 106 | // configure default state 107 | state_in <= ST_RST_1; 108 | end 109 | ST_RST_1: begin 110 | state_in <= ST_IDLE; 111 | end 112 | 113 | ST_IDLE: begin 114 | // idle state 115 | if(buf_in_commit_2 & ~buf_in_commit_3) begin 116 | // external device has written to this endpoint 117 | len_in <= buf_in_commit_len; 118 | dc <= 0; 119 | state_in <= ST_IN_COMMIT; 120 | end 121 | end 122 | ST_IN_COMMIT: begin 123 | // generate ACK pulse, 4 cycles long for slower clock domains 124 | if(dc == 3) begin 125 | state_in <= ST_IN_SWAP; 126 | end 127 | end 128 | ST_IN_SWAP: begin 129 | // swap the current buffer 130 | ptr_in <= ~ptr_in; 131 | 132 | // current buffer is now not ready anymore 133 | case(ptr_in) 134 | 0: ready_in_a <= 0; 135 | 1: ready_in_b <= 0; 136 | endcase 137 | 138 | // tell output FSM this has data 139 | case(ptr_in) 140 | 0: hasdata_out_a <= 1; 141 | 1: hasdata_out_b <= 1; 142 | endcase 143 | 144 | // copy over the amount of data intended to be sent 145 | case(ptr_in) 146 | 0: len_out_a <= len_in; 147 | 1: len_out_b <= len_in; 148 | endcase 149 | 150 | state_in <= ST_IDLE; 151 | end 152 | default: state_in <= ST_RST_0; 153 | endcase 154 | 155 | ////////////////////////////////////////////////////// 156 | 157 | // output FSM 158 | // 159 | case(state_out) 160 | ST_RST_0: begin 161 | // reset buffer index 162 | ptr_out <= 0; 163 | 164 | hasdata_out_a <= 0; 165 | hasdata_out_b <= 0; 166 | 167 | // configure default state 168 | state_out <= ST_RST_1; 169 | end 170 | ST_RST_1: begin 171 | state_out <= ST_IDLE; 172 | end 173 | ST_IDLE: begin 174 | // idle state 175 | if(buf_out_arm_2 & ~buf_out_arm_3) begin 176 | // free up this endpoint 177 | dc <= 0; 178 | state_out <= ST_OUT_ARM; 179 | end 180 | end 181 | ST_OUT_ARM: begin 182 | // generate ARM_ACK pulse, several cycles for compat with slower FSMs 183 | if(dc == 3) begin 184 | state_out <= ST_OUT_SWAP; 185 | end 186 | end 187 | ST_OUT_SWAP: begin 188 | // swap the current buffer 189 | ptr_out <= ~ptr_out; 190 | 191 | // current buffer is now ready for data 192 | case(ptr_out) 193 | 0: ready_in_a <= 1; 194 | 1: ready_in_b <= 1; 195 | endcase 196 | 197 | // update hasdata status 198 | case(ptr_out) 199 | 0: hasdata_out_a <= 0; 200 | 1: hasdata_out_b <= 0; 201 | endcase 202 | 203 | state_out <= ST_IDLE; 204 | end 205 | default: state_out <= ST_RST_0; 206 | endcase 207 | 208 | if(~reset_2) begin 209 | // reset 210 | state_in <= ST_RST_0; 211 | state_out <= ST_RST_0; 212 | end 213 | 214 | end 215 | 216 | // endpoint bram 217 | // 218 | 219 | // segment the space into two 1024 byte (256 word) buffers 220 | // 221 | wire [9:0] rd_addr = buf_out_addr + (ptr_out ? 10'd256 : 10'h0); 222 | wire [9:0] wr_addr = buf_in_addr + (ptr_in ? 10'd256 : 10'h0); 223 | 224 | usb3_ep_ram iu3ep ( 225 | .rd_clk ( rd_clk ), 226 | .rd_adr ( rd_addr ), 227 | .rd_dat_r ( buf_out_q ), 228 | 229 | .wr_clk ( wr_clk ), 230 | .wr_adr ( wr_addr ), 231 | .wr_dat_w ( buf_in_data ), 232 | .wr_we ( buf_in_wren ) 233 | ); 234 | 235 | 236 | endmodule 237 | -------------------------------------------------------------------------------- /core/usb2/usb2_ep.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 2.0 endpoint abstract 4 | // 5 | // Copyright (c) 2012-2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb2_ep ( 12 | 13 | // top-level interface 14 | input wire phy_clk, 15 | input wire rd_clk, 16 | input wire wr_clk, 17 | input wire reset_n, 18 | 19 | // PROTOCOL 20 | input wire [8:0] buf_in_addr, 21 | input wire [7:0] buf_in_data, 22 | input wire buf_in_wren, 23 | output wire buf_in_ready, 24 | input wire buf_in_commit, 25 | input wire [9:0] buf_in_commit_len, 26 | output wire buf_in_commit_ack, 27 | 28 | input wire [8:0] buf_out_addr, 29 | output wire [7:0] buf_out_q, 30 | output wire [9:0] buf_out_len, 31 | output wire buf_out_hasdata, 32 | input wire buf_out_arm, 33 | output wire buf_out_arm_ack, 34 | 35 | input wire [1:0] mode, 36 | 37 | input wire data_toggle_act, 38 | output reg [1:0] data_toggle 39 | 40 | ); 41 | 42 | // synchronizers 43 | reg reset_1, reset_2; 44 | reg buf_in_commit_1, buf_in_commit_2, buf_in_commit_3; 45 | reg buf_out_arm_1, buf_out_arm_2, buf_out_arm_3; 46 | 47 | parameter [1:0] DATA_TOGGLE_0 = 2'b00; 48 | parameter [1:0] DATA_TOGGLE_1 = 2'b01; 49 | parameter [1:0] DATA_TOGGLE_2 = 2'b10; 50 | parameter [1:0] DATA_TOGGLE_M = 2'b11; 51 | 52 | // for keeping track of the endpoint double buffering 53 | reg ptr_in; 54 | reg ptr_out; 55 | 56 | reg [9:0] len_in; 57 | reg ready_in_a; 58 | reg ready_in_b; 59 | assign buf_in_ready = ptr_in ? ready_in_b : ready_in_a; 60 | assign buf_in_commit_ack = (state_in == ST_IN_COMMIT || state_in == ST_IN_SWAP); 61 | 62 | reg [9:0] len_out_a; 63 | reg [9:0] len_out_b; 64 | reg hasdata_out_a; 65 | reg hasdata_out_b; 66 | assign buf_out_len = ptr_out ? len_out_b : len_out_a; 67 | assign buf_out_hasdata = ptr_out ? hasdata_out_b : hasdata_out_a; 68 | assign buf_out_arm_ack = (state_out == ST_OUT_ARM || state_out == ST_OUT_SWAP); 69 | 70 | parameter [1:0] EP_MODE_CONTROL = 2'd0, 71 | EP_MODE_ISOCH = 2'd1, 72 | EP_MODE_BULK = 2'd2, 73 | EP_MODE_INTERRUPT = 2'd3; 74 | 75 | reg [3:0] dc; 76 | 77 | reg [5:0] state_in; 78 | parameter [5:0] ST_RST_0 = 6'd0, 79 | ST_RST_1 = 6'd1, 80 | ST_IDLE = 6'd10, 81 | ST_IN_COMMIT = 6'd11, 82 | ST_IN_SWAP = 6'd12; 83 | 84 | reg [5:0] state_out; 85 | parameter [5:0] ST_OUT_ARM = 6'd11, 86 | ST_OUT_SWAP = 6'd12; 87 | 88 | always @(posedge phy_clk) begin 89 | 90 | // synchronizers 91 | {reset_2, reset_1} <= {reset_1, reset_n}; 92 | {buf_in_commit_3, buf_in_commit_2, buf_in_commit_1} <= 93 | {buf_in_commit_2, buf_in_commit_1, buf_in_commit}; 94 | {buf_out_arm_3, buf_out_arm_2, buf_out_arm_1} <= 95 | {buf_out_arm_2, buf_out_arm_1, buf_out_arm}; 96 | 97 | dc <= dc + 1'b1; 98 | 99 | if(data_toggle_act) begin 100 | data_toggle <= data_toggle + 1'b1; 101 | // modify for non-bulk endpoints 102 | // bulk transfers only utilize DATA0 and DATA1 103 | if(data_toggle == DATA_TOGGLE_1) data_toggle <= DATA_TOGGLE_0; 104 | end 105 | 106 | // input FSM 107 | // 108 | case(state_in) 109 | ST_RST_0: begin 110 | // reset buffer index 111 | ptr_in <= 0; 112 | data_toggle <= DATA_TOGGLE_0; 113 | 114 | ready_in_a <= 1; 115 | ready_in_b <= 1; 116 | 117 | // configure default state 118 | state_in <= ST_RST_1; 119 | end 120 | ST_RST_1: begin 121 | state_in <= ST_IDLE; 122 | end 123 | 124 | ST_IDLE: begin 125 | // idle state 126 | if(buf_in_commit_2 & ~buf_in_commit_3) begin 127 | // external device has written to this endpoint 128 | len_in <= buf_in_commit_len; 129 | dc <= 0; 130 | state_in <= ST_IN_COMMIT; 131 | end 132 | end 133 | ST_IN_COMMIT: begin 134 | // generate ACK pulse, 4 cycles long for slower clock domains 135 | if(dc == 3) begin 136 | state_in <= ST_IN_SWAP; 137 | end 138 | end 139 | ST_IN_SWAP: begin 140 | // swap the current buffer 141 | ptr_in <= ~ptr_in; 142 | 143 | // current buffer is now not ready anymore 144 | case(ptr_in) 145 | 0: ready_in_a <= 0; 146 | 1: ready_in_b <= 0; 147 | endcase 148 | 149 | // tell output FSM this has data 150 | case(ptr_in) 151 | 0: hasdata_out_a <= 1; 152 | 1: hasdata_out_b <= 1; 153 | endcase 154 | 155 | // copy over the amount of data intended to be sent 156 | case(ptr_in) 157 | 0: len_out_a <= len_in; 158 | 1: len_out_b <= len_in; 159 | endcase 160 | 161 | state_in <= ST_IDLE; 162 | end 163 | default: state_in <= ST_RST_0; 164 | endcase 165 | 166 | ////////////////////////////////////////////////////// 167 | 168 | // output FSM 169 | // 170 | case(state_out) 171 | ST_RST_0: begin 172 | // reset buffer index 173 | ptr_out <= 0; 174 | 175 | hasdata_out_a <= 0; 176 | hasdata_out_b <= 0; 177 | 178 | // configure default state 179 | state_out <= ST_RST_1; 180 | end 181 | ST_RST_1: begin 182 | state_out <= ST_IDLE; 183 | end 184 | ST_IDLE: begin 185 | // idle state 186 | if(buf_out_arm_2 & ~buf_out_arm_3) begin 187 | // free up this endpoint 188 | dc <= 0; 189 | state_out <= ST_OUT_ARM; 190 | end 191 | end 192 | ST_OUT_ARM: begin 193 | // generate ARM_ACK pulse, several cycles for compat with slower FSMs 194 | if(dc == 3) begin 195 | state_out <= ST_OUT_SWAP; 196 | end 197 | end 198 | ST_OUT_SWAP: begin 199 | // swap the current buffer 200 | ptr_out <= ~ptr_out; 201 | 202 | // current buffer is now ready for data 203 | case(ptr_out) 204 | 0: ready_in_a <= 1; 205 | 1: ready_in_b <= 1; 206 | endcase 207 | 208 | // update hasdata status 209 | case(ptr_out) 210 | 0: hasdata_out_a <= 0; 211 | 1: hasdata_out_b <= 0; 212 | endcase 213 | 214 | state_out <= ST_IDLE; 215 | end 216 | default: state_out <= ST_RST_0; 217 | endcase 218 | 219 | if(~reset_2) begin 220 | // reset 221 | state_in <= ST_RST_0; 222 | state_out <= ST_RST_0; 223 | end 224 | 225 | end 226 | 227 | // endpoint bram 228 | // 229 | 230 | // segment the space into two 512 byte buffers 231 | // 232 | wire [9:0] rd_addr = buf_out_addr + (ptr_out ? 10'd512 : 10'h0); 233 | wire [9:0] wr_addr = buf_in_addr + (ptr_in ? 10'd512 : 10'h0); 234 | 235 | usb2_ep_ram iu2ep ( 236 | .rd_clk ( rd_clk ), 237 | .rd_adr ( rd_addr ), 238 | .rd_dat_r ( buf_out_q ), 239 | 240 | .wr_clk ( wr_clk ), 241 | .wr_adr ( wr_addr ), 242 | .wr_dat_w ( buf_in_data ), 243 | .wr_we ( buf_in_wren ) 244 | ); 245 | 246 | 247 | endmodule 248 | -------------------------------------------------------------------------------- /core/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | USB 3.0 Device Controller Core 4 | ------------------------------ 5 | 6 | Copyright (c) 2012-2014 Marshall H. All rights reserved. 7 | Code in this folder is released under the terms of the simplified BSD license. 8 | See LICENSE.TXT for details. 9 | 10 | Part of the Daisho project, by Michael Ossmann. http://greatscottgadgets.com/ 11 | 12 | 13 | Revision 0.1, 06/01/14 14 | -------------------------------------------------------------------------------- 15 | 16 | 17 | 18 | Overview 19 | -------- 20 | 21 | This is a device-side controller. This means you can use it to implement a 22 | device talking to a host, whether it be a PC, smartphone, embedded platform... 23 | 24 | The controller supports both USB 3.0 (5.0Gbps) and USB 2.0 (480Mbps) operation. 25 | During enumeration if a SuperSpeed receiver is not detected, it will fall 26 | back to 2.0 operation. 27 | 28 | Written in Verilog-2001, it aims to be somewhat easily adaptable to other 29 | devices. It handles PHY strapping and initialization, LFPS with partner, link 30 | training and receiver equalization, link layer data scrambling, elastic buffer 31 | management, device enumeration, and block data transfer. 32 | 33 | If you don't know anything about USB, you will have a rough time. If you have 34 | no experience with FPGAs, you will suffer even more. Read the USB 2.0 spec 35 | overview, then read about USB 3.0 functionality and how they are incorporated 36 | into each other. Be familiar with the PHY you will use. 37 | 38 | 39 | 40 | Capabilities 41 | ------------ 42 | 43 | The following transfer modes are supported in USB 2.0: 44 | - Control (intrinsic) 45 | - Bulk 46 | - Interrupt 47 | - Isochronous 48 | 49 | And in USB 3.0 mode: 50 | - Control, Link management 51 | - Bulk 52 | 53 | By default, both controllers implement one BULK IN and one BULK OUT endpoint 54 | in addition to the default Endpoint0 for control transfers. 55 | Additional endpoints may be added with some rework of the protocol layers. 56 | 57 | Setting the endpoints to different transfer modes requires editing of the RTL 58 | and also the device descriptors. Consult the USB specifications or your 59 | favorite search engine for details on the descriptors. 60 | 61 | 62 | 63 | Limitations 64 | ----------- 65 | 66 | Does not implement the following USB 2.0 functionality: 67 | - Power saving via SuspendM bit in ULPI 68 | - Low speed (1.5Mbps) is unimplemented 69 | - Full speed (11Mbps) is unsupported, but may work 70 | 71 | Does not implement the following USB 3.0 functionality: 72 | - Compliance testing mode 73 | - Loopback BERT 74 | - Assertion of disabled data scrambling 75 | - Tolerance of link command glitches 76 | - Stream transfer mode 77 | 78 | Details: 79 | 1. USB devices operating via the 2.0 connection should enter suspend when 80 | not transmitting any data on the bus for over 3.0ms. After a total of 10ms 81 | have passed, it may not draw more than the rated suspend-mode 82 | current instead of the normal current draw. 83 | This is normally entered when the host stops sending StartOfFrame packets 84 | and allows this idle condition. Due to the target platform's fixed current 85 | draw this is not an option that can be supported. 86 | 2. For compliance testing, the USB 3.0 LTSSM should support a special 87 | Compliance state that is entered under certain conditions detailed in the 88 | USB specification, for PHY characterization. This mode is not implemented. 89 | 3. Also, USB 3.0 Loopback mode is used for benchmarking the bit error rate of 90 | a connection. As this is not used under normal operation, it is omitted to 91 | save device resources. 92 | 4. During link training, one partner may choose to signal it wishes to disable 93 | data scrambling. The other partner should signal its acknowledgement in the 94 | next training sequence. This is supported but basically untested. 95 | 5. Per the specification, link commands (which are 4 consecutive, redundant 96 | K-symbols) can have up to 1 invalid symbol and still be considered valid. 97 | To simplify functionality the controller will simply ignore these and 98 | cause a sequence error. Because the protocol is robust anyway, these will 99 | at most cause a small performance blip in adverse environments (poor 100 | cabling, bad connectors, etc) 101 | 6. Streams are unsupported, if you need them in your application you are 102 | exceeding the expected use case 103 | 104 | 105 | Implementation Results 106 | ---------------------- 107 | 108 | Logic utilization: 109 | Approx. 1100 LEs for USB 2.0 110 | Approx. 6300 LEs for USB 3.0 111 | 1 PLL 112 | ~40 DDR I/O 113 | 8-10Kbyte distributed block RAM (flexible) 114 | 115 | Targeted PHY: 116 | Texas Instruments TUSB1310A SuperSpeed PHY 117 | 118 | Targeted FPGA: 119 | Altera Cyclone IV EP4CE30 speed grade 8 120 | 121 | Build system: 122 | Altera Quartus II 13.1sp1 123 | 124 | 125 | 126 | Porting Notes 127 | ------------- 128 | 129 | This controller relies upon several vendor and family-specific features such as 130 | PLLs, pipelined DDR I/O, distributed block RAM, and so on. 131 | Altera calls these "Megafunctions" and they are denoted by "mf_*.v" filenames. 132 | 133 | If you are going to port this to Xilinx, Lattice, silicon then you will want to 134 | blow these away and use the vendor's equivalent tools to get the same result. 135 | 136 | I would recommend that you download Quartus and use the Megawizard Plug-in 137 | Manager to open these files so that you can see how they are supposed to work, 138 | and how you would write wrappers for slightly different device functionality. 139 | 140 | You're on your own here, this is not something I would recommend to an FPGA 141 | newcomer (though arguably using this core itself is not trivial.) 142 | 143 | 144 | 145 | Usage Considerations 146 | -------------------- 147 | 148 | There are a number of design decisions and small things that may affect your 149 | success using the code. 150 | 151 | 1. Device descriptors 152 | When running the core with only USB 2.0, edit the device descriptors so that 153 | the "bcdDevice" entry denotes 200h instead of 210h. The latter indicates the 154 | device has latent SuperSpeed functionality. 155 | And obviously, if you want to change the enumerated display name you'll want 156 | to change these. They must always match the RTL endpoint configuration. 157 | 158 | 2. I/O constraints 159 | It's your responsibility to constrain the top level I/O to meet your PCB 160 | layout. Consult your PHY datasheet, and read FPGA vendor datasheets. 161 | PIPE bus I/O is fast enough that timing driven synthesis is recommended 162 | 163 | 3. SSRX/TX polarity 164 | The core can tell when the RX data pair has its polarity swapped and will 165 | configure the PHY accordingly during link training. You can swap either TX 166 | or RX pairs for more convenient PCB routing. Consult your PHY documentation. 167 | 168 | 4. Reset 169 | To reset the core to its power-on state, assert reset for at least a few 170 | hundred cycles (around 10 uS would be a safe bet.). Additionally, your PHY 171 | chip may have its own requirements for this. Reset for whichever duration is 172 | longest. 173 | 174 | 175 | 176 | Troubleshooting 177 | --------------- 178 | 179 | It's highly unlikely that things will work properly the first time. You would 180 | be well advised to buy/lease/borrow a competent protocol analyzer. Units are 181 | available from the major vendors, which include: 182 | 183 | - Teledyne Lecroy 184 | - Agilent 185 | - Tektronix 186 | - Total Phase 187 | 188 | The Beagle 5000v2 from Total Phase was used for the core's development. It 189 | runs about $5-6k. Additionally, the Lecroy Voyagyer M3x was used to test 190 | compliance cases to identify rare problems. 191 | Other vendors provide add-on packages for their higher end scopes, but if 192 | you could afford those, you'd be licensing a USB core from DesignWare 193 | anyhow. :) 194 | If you have access to proper verification IP you'd probably want to test this 195 | core against it. I welcome any changes that will make the core more robust. 196 | 197 | If you have some knowledge of the protocols you can trigger on the RTL with 198 | Chipscope, Signaltap, Reveal, et al. This will only give you a very narrow 199 | window but it's better than nothing. 200 | 201 | 202 | 203 | Contact 204 | ------- 205 | 206 | I do not provide support! I will not answer STUPID questions or ones that 207 | make it clear you are going to be wasting not only your own time but mine too. 208 | 209 | Bugfixes are welcome if you can clearly demonstrate what is fixed and that no 210 | regressions are caused. 211 | 212 | If you successfully implement the core and ship a product I would appreciate 213 | sending an email to let me know it worked. 214 | 215 | usb3ipcore, at outlookdotcom 216 | 217 | 218 | 219 | EOF -------------------------------------------------------------------------------- /core/usb3/usb3_descramble.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 3.0 rx descrambling and alignment 4 | // 5 | // Copyright (c) 2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb3_descramble ( 12 | 13 | input wire clock, 14 | input wire local_clk, 15 | input wire reset_n, 16 | 17 | input wire enable, 18 | 19 | input wire [1:0] raw_valid, 20 | input wire [5:0] raw_status, 21 | input wire [1:0] raw_phy_status, 22 | input wire [3:0] raw_datak, 23 | input wire [31:0] raw_data, 24 | 25 | //output reg [1:0] proc_valid, 26 | //output reg [5:0] proc_status, 27 | //output reg [1:0] proc_phy_status, 28 | output reg [3:0] proc_datak, 29 | output reg [31:0] proc_data, 30 | output reg proc_active, 31 | 32 | output reg err_skp_unexpected 33 | ); 34 | 35 | `include "usb3_const.vh" 36 | 37 | // what this module does is filtering of the input symbol stream 38 | // to remove everything that >PHY layer is not interested in. 39 | // 40 | // example: scrambled stream with skip padding 41 | // BE40A73C3C3CE62CD3E2B20702772A (D) 42 | // 000000111111000000000000000000 (K) 43 | // > 44 | // 000000000000000000000000 (D) 45 | // 000000000000000000000000 (K) 46 | // 47 | // this would be fairly trivial if we could clock this module at 500mhz 48 | // and only process 1 symbol at a time. however, due to timing constraints 49 | // it's working at 125mhz instead, and on 4 symbols at once. this is where 50 | // symbol alignment gets sticky, and why there are so many cases. 51 | // 52 | // 10/08/13 - edge case discovered where SKP immediately following the end of a 53 | // packet on the next cycle will cause a 1 cycle deassertion of ACTIVE, and 54 | // push the last word of the packet onto the following cycle where ACTIVE 55 | // is asserted again. 56 | 57 | 58 | // indicates presence of SKP at any symbol position 59 | wire [3:0] skip = { (raw_data[31:24] == 8'h3C) & raw_datak[3], (raw_data[23:16] == 8'h3C) & raw_datak[2], 60 | (raw_data[15:8] == 8'h3C) & raw_datak[1], (raw_data[7:0] == 8'h3C) & raw_datak[0] }; 61 | // indicates presence of COM at any symbol position (K28.5) 62 | wire [3:0] comma = { (coll_data[31:24] == 8'hBC) & coll_datak[3], (coll_data[23:16] == 8'hBC) & coll_datak[2], 63 | (coll_data[15:8] == 8'hBC) & coll_datak[1], (coll_data[7:0] == 8'hBC) & coll_datak[0] }; 64 | 65 | // step 1. 66 | // collapse incoming stream to remove all SKP symbols. 67 | // these may be sent as 0x3C, 0x3C3C, 0x3C3C3C and so on. 68 | 69 | //reg [5:0] skr_status; 70 | reg [31:0] skr_data; 71 | reg [3:0] skr_datak; 72 | reg [2:0] skr_num; 73 | reg [1:0] skr_valid; 74 | 75 | always @(posedge local_clk) begin 76 | 77 | case(skip) 78 | 4'b0000: begin 79 | skr_data <= raw_data; 80 | skr_datak <= raw_datak; end 81 | 4'b0001: begin 82 | skr_data <= raw_data[31:8]; 83 | skr_datak <= raw_datak[3:1]; end 84 | 4'b0010: begin 85 | skr_data <= {raw_data[31:16], raw_data[7:0]}; 86 | skr_datak <= {raw_datak[3:2], raw_datak[0]}; end 87 | 4'b0011: begin 88 | skr_data <= raw_data[31:16]; 89 | skr_datak <= raw_datak[3:2]; end 90 | 4'b0100: begin 91 | skr_data <= {raw_data[31:24], raw_data[15:0]}; 92 | skr_datak <= {raw_datak[3], raw_datak[1:0]}; end 93 | 4'b0110: begin 94 | skr_data <= {raw_data[31:24], raw_data[7:0]}; 95 | skr_datak <= {raw_datak[3], raw_datak[0]}; end 96 | 4'b0111: begin 97 | skr_data <= raw_data[31:24]; 98 | skr_datak <= raw_datak[3]; end 99 | 4'b1110: begin 100 | skr_data <= raw_data[7:0]; 101 | skr_datak <= raw_datak[0]; end 102 | 4'b1100: begin 103 | skr_data <= raw_data[15:0]; 104 | skr_datak <= raw_datak[1:0]; end 105 | 4'b1000: begin 106 | skr_data <= raw_data[23:0]; 107 | skr_datak <= raw_datak[2:0]; end 108 | 4'b1111: begin 109 | skr_data <= 0; 110 | skr_datak <= 0; end 111 | default: begin 112 | //{skr_status, skr_data, skr_datak} <= 0; 113 | {skr_data, skr_datak} <= 0; 114 | err_skp_unexpected <= 1; 115 | end 116 | endcase 117 | 118 | // count valid symbols 119 | skr_num <= 3'h4 - (skip[3] + skip[2] + skip[1] + skip[0]); 120 | //skr_status <= raw_status; 121 | skr_valid <= raw_valid; 122 | 123 | if(~reset_n) begin 124 | err_skp_unexpected <= 0; 125 | end 126 | end 127 | 128 | 129 | 130 | // step 2. 131 | // accumulate these fragments and then squeeze them out 132 | // 32bits at a time. 133 | 134 | reg [5:0] acc_status; 135 | reg [63:0] acc_data; 136 | reg [7:0] acc_datak; 137 | 138 | reg [2:0] acc_depth; 139 | 140 | always @(posedge local_clk) begin 141 | 142 | // take in either 8, 16, 24, or 32 bits of data from the prior stage 143 | case(skr_num) 144 | 0: begin end 145 | 1: begin 146 | acc_data <= {acc_data[55:0], skr_data[7:0]}; 147 | acc_datak <= {acc_datak[6:0], skr_datak[0:0]}; 148 | acc_depth <= acc_depth + 3'd1; 149 | end 150 | 2: begin 151 | acc_data <= {acc_data[47:0], skr_data[15:0]}; 152 | acc_datak <= {acc_datak[5:0], skr_datak[1:0]}; 153 | acc_depth <= acc_depth + 3'd2; 154 | end 155 | 3: begin 156 | acc_data <= {acc_data[39:0], skr_data[23:0]}; 157 | acc_datak <= {acc_datak[4:0], skr_datak[2:0]}; 158 | acc_depth <= acc_depth + 3'd3; 159 | end 160 | 4: begin 161 | acc_data <= {acc_data[31:0], skr_data[31:0]}; 162 | acc_datak <= {acc_datak[3:0], skr_datak[3:0]}; 163 | acc_depth <= acc_depth + 3'd4; 164 | end 165 | endcase 166 | 167 | // pick off 32bits and decrement the accumulator 168 | coll_valid <= skr_valid; 169 | coll_active <= (acc_depth > 3); 170 | case(acc_depth) 171 | 4: begin 172 | {coll_data, coll_datak} <= {acc_data[31:0], acc_datak[3:0]}; 173 | acc_depth <= 3'd0 + skr_num; 174 | end 175 | 5: begin 176 | {coll_data, coll_datak} <= {acc_data[39:8], acc_datak[4:1]}; 177 | acc_depth <= 3'd1 + skr_num; 178 | end 179 | 6: begin 180 | {coll_data, coll_datak} <= {acc_data[47:16], acc_datak[5:2]}; 181 | acc_depth <= 3'd2 + skr_num; 182 | end 183 | 7: begin 184 | {coll_data, coll_datak} <= {acc_data[55:24], acc_datak[6:3]}; 185 | acc_depth <= 3'd3 + skr_num; 186 | end 187 | endcase 188 | 189 | if(~reset_n) begin 190 | acc_depth <= 0; 191 | end 192 | end 193 | 194 | 195 | // step 3. 196 | // handle descrambling LFSR, resetting upon COM with 197 | // proper symbol alignment. 198 | 199 | reg [31:0] coll_data ; 200 | reg [3:0] coll_datak; 201 | reg coll_active; 202 | reg [1:0] coll_valid; 203 | 204 | reg [2:0] ds_align; 205 | reg [2:0] scr_defer; 206 | 207 | always @(posedge local_clk) begin 208 | 209 | if(scr_defer < 3) scr_defer <= scr_defer + 1'b1; 210 | if(|comma) scr_defer <= 0; 211 | 212 | case(comma) 213 | 4'b1111: begin 214 | ds_align <= 0; 215 | end 216 | 4'b1110: begin 217 | ds_align <= 1; 218 | end 219 | 4'b1100: begin 220 | ds_align <= 2; 221 | end 222 | 4'b1000: begin 223 | ds_align <= 3; 224 | end 225 | endcase 226 | 227 | if(coll_active) begin 228 | // only apply descrambling to data, not K-symbols 229 | next_data[31:24] <= coll_data[31:24] ^ (coll_datak[3] ? 8'h0 : ds_delay[31:24]); 230 | next_data[23:16] <= coll_data[23:16] ^ (coll_datak[2] ? 8'h0 : ds_delay[23:16]); 231 | next_data[15:8] <= coll_data[15:8] ^ (coll_datak[1] ? 8'h0 : ds_delay[15:8]); 232 | next_data[7:0] <= coll_data[7:0] ^ (coll_datak[0] ? 8'h0 : ds_delay[7:0]); 233 | next_datak <= coll_datak; 234 | 235 | // match incoming alignment 236 | case(ds_align) 237 | 0: ds_delay <= {ds_last}; 238 | 1: ds_delay <= {ds_last[23:0], ds_out[31:24]}; 239 | 2: ds_delay <= {ds_last[15:0], ds_out[31:16]}; 240 | 3: ds_delay <= {ds_last[7:0], ds_out[31:8]}; 241 | endcase 242 | ds_last <= ds_out; 243 | end 244 | 245 | next_active <= coll_active; 246 | 247 | // squelch invalids 248 | if(~coll_valid || ~coll_active) begin 249 | next_data <= 32'h0; 250 | next_datak <= 4'b0; 251 | next_active <= 0; 252 | end 253 | 254 | end 255 | 256 | // step 4. 257 | // pipeline data to relax timing 258 | 259 | reg [31:0] next_data; 260 | reg [3:0] next_datak; 261 | reg next_active; 262 | 263 | always @(posedge local_clk) begin 264 | proc_data <= next_data; 265 | proc_datak <= next_datak; 266 | proc_active <= next_active; 267 | end 268 | 269 | // 270 | // data de-scrambling for RX 271 | // 272 | reg [31:0] ds_delay; 273 | reg [31:0] ds_last; 274 | wire ds_suppress = |comma || (scr_defer < 3); 275 | wire ds_enable = enable && !ds_suppress; 276 | wire [31:0] ds_out_swap; 277 | wire [31:0] ds_out = ds_enable ? 278 | {ds_out_swap[7:0], ds_out_swap[15:8], ds_out_swap[23:16], ds_out_swap[31:24]} 279 | : 0; 280 | usb3_lfsr iu3srx( 281 | 282 | .clock ( local_clk ), 283 | .reset_n ( reset_n ), 284 | 285 | .data_in ( 32'h0 ), 286 | .scram_en ( coll_active ), 287 | .scram_rst ( |comma ), 288 | .scram_init ( 16'h7DBD ), // reset to FFFF + 3 cycles 289 | .data_out_reg ( ds_out_swap ) 290 | 291 | ); 292 | 293 | endmodule 294 | -------------------------------------------------------------------------------- /core/usb2/usb2_top.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 2.0 top-level 4 | // 5 | // Copyright (c) 2012-2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb2_top ( 12 | 13 | input wire ext_clk, 14 | input wire reset_n, 15 | output wire reset_n_out, 16 | 17 | input wire phy_ulpi_clk, 18 | inout wire [7:0] phy_ulpi_d, 19 | input wire phy_ulpi_dir, 20 | output wire phy_ulpi_stp, 21 | input wire phy_ulpi_nxt, 22 | 23 | input wire opt_disable_all, 24 | input wire opt_enable_hs, 25 | input wire opt_ignore_vbus, 26 | output wire stat_connected, 27 | output wire stat_fs, 28 | output wire stat_hs, 29 | output wire stat_configured, 30 | 31 | input wire [8:0] buf_in_addr, 32 | input wire [7:0] buf_in_data, 33 | input wire buf_in_wren, 34 | output wire buf_in_ready, 35 | input wire buf_in_commit, 36 | input wire [9:0] buf_in_commit_len, 37 | output wire buf_in_commit_ack, 38 | input wire [8:0] buf_out_addr, 39 | output wire [7:0] buf_out_q, 40 | output wire [9:0] buf_out_len, 41 | output wire buf_out_hasdata, 42 | input wire buf_out_arm, 43 | output wire buf_out_arm_ack, 44 | 45 | output wire vend_req_act, 46 | output wire [7:0] vend_req_request, 47 | output wire [15:0] vend_req_val, 48 | 49 | output wire err_crc_pid, 50 | output wire err_crc_tok, 51 | output wire err_crc_pkt, 52 | output wire err_pid_out_of_seq, 53 | output wire err_setup_pkt, 54 | 55 | output wire [10:0] dbg_frame_num, 56 | output wire [1:0] dbg_linestate 57 | 58 | ); 59 | 60 | reg reset_1, reset_2; // local reset 61 | 62 | // allow reset-time pin strapping for the usb 3.0 phy. 63 | // this should not affect regular usb 2.0 PHYs 64 | // 65 | assign phy_ulpi_d = (reset_2 ? (phy_ulpi_d_oe ? phy_ulpi_d_out : 8'bZZZZZZZZ) : 66 | { 67 | 1'b0, // ISO_START PIPE Isolate Mode 68 | 1'b0, // ULPI_8BIT Bus Width ULPI 69 | 2'b11, // REFCLKSEL Reference clock freq 70 | 4'b0 71 | }); 72 | 73 | wire [7:0] phy_ulpi_d_in = phy_ulpi_d; 74 | wire [7:0] phy_ulpi_d_out; 75 | wire phy_ulpi_d_oe; 76 | 77 | always @(posedge ext_clk) begin 78 | // synchronize external reset to local domain 79 | {reset_2, reset_1} <= {reset_1, reset_n}; 80 | end 81 | 82 | //////////////////////////////////////////////////////////// 83 | // 84 | // USB 2.0 ULPI interface 85 | // 86 | //////////////////////////////////////////////////////////// 87 | 88 | wire ulpi_out_act; 89 | wire [7:0] ulpi_out_byte; 90 | wire ulpi_out_latch; 91 | wire ulpi_in_nxt; 92 | wire ulpi_in_cts; 93 | wire [7:0] ulpi_in_byte; 94 | wire ulpi_in_latch; 95 | wire ulpi_in_stp; 96 | 97 | usb2_ulpi ia ( 98 | // reset signal frome external clock domain, must be synchronized 99 | .reset_n ( reset_n ), 100 | 101 | // locally generated reset, triggers local USB reset when cable is 102 | // unplugged, OR'd with external reset above 103 | .reset_local ( reset_n_out ), 104 | 105 | // easy flag that will cause all modules to stay in reset and be optimized out 106 | // useful for testing 3.0 only 107 | .opt_disable_all ( opt_disable_all ), 108 | 109 | // high-speed enable, full speed enumeration works but data transmission 110 | // is not guaranteed 111 | .opt_enable_hs ( opt_enable_hs ), 112 | 113 | // normally a change in Vbus signals that the device has been disconnected. 114 | // on some PHYs this may be unreliable (such as TUSB1310A) 115 | .opt_ignore_vbus (opt_ignore_vbus), 116 | 117 | // status signals 118 | .stat_connected ( stat_connected ), 119 | .stat_fs ( stat_fs ), 120 | .stat_hs ( stat_hs ), 121 | 122 | // external PHY interface 123 | .phy_clk ( phy_ulpi_clk ), 124 | .phy_d_in ( phy_ulpi_d_in ), 125 | .phy_d_out_mux ( phy_ulpi_d_out ), 126 | .phy_d_oe ( phy_ulpi_d_oe ), 127 | .phy_dir ( phy_ulpi_dir ), 128 | .phy_stp ( phy_ulpi_stp ), 129 | .phy_nxt ( phy_ulpi_nxt ), 130 | 131 | // packet layer interface 132 | .pkt_out_act ( ulpi_out_act ), 133 | .pkt_out_byte ( ulpi_out_byte ), 134 | .pkt_out_latch ( ulpi_out_latch ), 135 | .pkt_in_cts ( ulpi_in_cts ), 136 | .pkt_in_nxt ( ulpi_in_nxt ), 137 | .pkt_in_byte ( ulpi_in_byte ), 138 | .pkt_in_latch ( ulpi_in_latch ), 139 | .pkt_in_stp ( ulpi_in_stp ), 140 | 141 | .dbg_linestate ( dbg_linestate ) 142 | ); 143 | 144 | 145 | //////////////////////////////////////////////////////////// 146 | // 147 | // USB 2.0 Packet layer 148 | // 149 | //////////////////////////////////////////////////////////// 150 | 151 | wire packet_xfer_in; 152 | wire packet_xfer_in_ok; 153 | wire packet_xfer_out; 154 | wire packet_xfer_out_ok; 155 | wire packet_xfer_query; 156 | wire [3:0] packet_xfer_endp; 157 | wire [3:0] packet_xfer_pid; 158 | 159 | usb2_packet ip ( 160 | // note this is the locally generated reset driven by the ULPI module 161 | .reset_n ( reset_n_out ), 162 | 163 | // clock (60mhz) driven by external PHY 164 | .phy_clk ( phy_ulpi_clk ), 165 | 166 | // connections to ULPI module 167 | .in_act ( ulpi_out_act ), 168 | .in_byte ( ulpi_out_byte ), 169 | .in_latch ( ulpi_out_latch ), 170 | .out_cts ( ulpi_in_cts ), 171 | .out_nxt ( ulpi_in_nxt ), 172 | .out_byte ( ulpi_in_byte ), 173 | .out_latch ( ulpi_in_latch ), 174 | .out_stp ( ulpi_in_stp ), 175 | 176 | // currently selected endpoint buffer 177 | .sel_endp ( prot_sel_endp ), 178 | 179 | .buf_in_addr ( prot_buf_in_addr ), 180 | .buf_in_data ( prot_buf_in_data ), 181 | .buf_in_wren ( prot_buf_in_wren ), 182 | .buf_in_ready ( prot_buf_in_ready ), 183 | .buf_in_commit ( prot_buf_in_commit ), 184 | .buf_in_commit_len ( prot_buf_in_commit_len ), 185 | .buf_in_commit_ack ( prot_buf_in_commit_ack ), 186 | 187 | .buf_out_addr ( prot_buf_out_addr ), 188 | .buf_out_q ( prot_buf_out_q ), 189 | .buf_out_len ( prot_buf_out_len ), 190 | .buf_out_hasdata ( prot_buf_out_hasdata ), 191 | .buf_out_arm ( prot_buf_out_arm ), 192 | .buf_out_arm_ack ( prot_buf_out_arm_ack ), 193 | 194 | .endp_mode ( prot_endp_mode ), 195 | 196 | .data_toggle_act ( prot_data_toggle_act ), 197 | .data_toggle ( prot_data_toggle ), 198 | 199 | // current device address, driven by endpoint 0 200 | .dev_addr ( prot_dev_addr ), 201 | 202 | // error signals, put your LA on these 203 | .err_crc_pid ( err_crc_pid ), 204 | .err_crc_tok ( err_crc_tok ), 205 | .err_crc_pkt ( err_crc_pkt ), 206 | .err_pid_out_of_seq ( err_pid_out_of_seq ), 207 | 208 | .dbg_frame_num ( dbg_frame_num ) 209 | ); 210 | 211 | 212 | //////////////////////////////////////////////////////////// 213 | // 214 | // USB 2.0 Protocol layer 215 | // 216 | //////////////////////////////////////////////////////////// 217 | 218 | wire [3:0] prot_sel_endp; 219 | wire [8:0] prot_buf_in_addr; 220 | wire [7:0] prot_buf_in_data; 221 | wire prot_buf_in_wren; 222 | wire prot_buf_in_ready; 223 | wire prot_buf_in_commit; 224 | wire [9:0] prot_buf_in_commit_len; 225 | wire prot_buf_in_commit_ack; 226 | 227 | wire [8:0] prot_buf_out_addr; 228 | wire [7:0] prot_buf_out_q; 229 | wire [9:0] prot_buf_out_len; 230 | wire prot_buf_out_hasdata; 231 | wire prot_buf_out_arm; 232 | wire prot_buf_out_arm_ack; 233 | wire [6:0] prot_dev_addr; 234 | 235 | wire [1:0] prot_endp_mode; 236 | wire prot_data_toggle_act; 237 | wire [1:0] prot_data_toggle; 238 | 239 | usb2_protocol ipr ( 240 | .reset_n ( reset_n_out ), 241 | 242 | // external interface clock. the dual-port endpoint block rams 243 | // have one port clocked with the ULPI, and the other with this 244 | // externally provided clock. 245 | .ext_clk ( ext_clk ), 246 | .phy_clk ( phy_ulpi_clk ), 247 | 248 | // muxed endpoint signals 249 | .sel_endp ( prot_sel_endp ), 250 | 251 | .buf_in_addr ( prot_buf_in_addr ), 252 | .buf_in_data ( prot_buf_in_data ), 253 | .buf_in_wren ( prot_buf_in_wren ), 254 | .buf_in_ready ( prot_buf_in_ready ), 255 | .buf_in_commit ( prot_buf_in_commit ), 256 | .buf_in_commit_len ( prot_buf_in_commit_len ), 257 | .buf_in_commit_ack ( prot_buf_in_commit_ack ), 258 | 259 | .buf_out_addr ( prot_buf_out_addr ), 260 | .buf_out_q ( prot_buf_out_q ), 261 | .buf_out_len ( prot_buf_out_len ), 262 | .buf_out_hasdata ( prot_buf_out_hasdata ), 263 | .buf_out_arm ( prot_buf_out_arm ), 264 | .buf_out_arm_ack ( prot_buf_out_arm_ack ), 265 | 266 | // external interface 267 | .ext_buf_in_addr ( buf_in_addr ), 268 | .ext_buf_in_data ( buf_in_data ), 269 | .ext_buf_in_wren ( buf_in_wren ), 270 | .ext_buf_in_ready ( buf_in_ready ), 271 | .ext_buf_in_commit ( buf_in_commit ), 272 | .ext_buf_in_commit_len ( buf_in_commit_len ), 273 | .ext_buf_in_commit_ack ( buf_in_commit_ack ), 274 | 275 | .ext_buf_out_addr ( buf_out_addr ), 276 | .ext_buf_out_q ( buf_out_q ), 277 | .ext_buf_out_len ( buf_out_len ), 278 | .ext_buf_out_hasdata ( buf_out_hasdata ), 279 | .ext_buf_out_arm ( buf_out_arm ), 280 | .ext_buf_out_arm_ack ( buf_out_arm_ack ), 281 | 282 | .vend_req_act ( vend_req_act ), 283 | .vend_req_request ( vend_req_request ), 284 | .vend_req_val ( vend_req_val ), 285 | 286 | .endp_mode ( prot_endp_mode ), 287 | 288 | .data_toggle_act ( prot_data_toggle_act ), 289 | .data_toggle ( prot_data_toggle ), 290 | 291 | .err_setup_pkt ( err_setup_pkt ), 292 | 293 | // tell the rest of the USB controller about what 294 | // our current device address is, assigned by host 295 | .dev_addr ( prot_dev_addr ), 296 | .configured ( stat_configured ) 297 | ); 298 | 299 | 300 | endmodule 301 | -------------------------------------------------------------------------------- /core/usb2/usb2_protocol.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 2.0 protocol layer 4 | // 5 | // Copyright (c) 2012-2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb2_protocol ( 12 | 13 | // top-level interface 14 | input wire phy_clk, 15 | input wire ext_clk, 16 | input wire reset_n, 17 | 18 | // PACKET 19 | input wire [3:0] sel_endp, 20 | 21 | input wire [8:0] buf_in_addr, 22 | input wire [7:0] buf_in_data, 23 | input wire buf_in_wren, 24 | output wire buf_in_ready, 25 | input wire buf_in_commit, 26 | input wire [9:0] buf_in_commit_len, 27 | output wire buf_in_commit_ack, 28 | 29 | input wire [8:0] buf_out_addr, 30 | output wire [7:0] buf_out_q, 31 | output wire [9:0] buf_out_len, 32 | output wire buf_out_hasdata, 33 | input wire buf_out_arm, 34 | output wire buf_out_arm_ack, 35 | 36 | // EXTERNAL 37 | input wire [8:0] ext_buf_in_addr, 38 | input wire [7:0] ext_buf_in_data, 39 | input wire ext_buf_in_wren, 40 | output wire ext_buf_in_ready, 41 | input wire ext_buf_in_commit, 42 | input wire [9:0] ext_buf_in_commit_len, 43 | output wire ext_buf_in_commit_ack, 44 | input wire [8:0] ext_buf_out_addr, 45 | output wire [7:0] ext_buf_out_q, 46 | output wire [9:0] ext_buf_out_len, 47 | output wire ext_buf_out_hasdata, 48 | input wire ext_buf_out_arm, 49 | output wire ext_buf_out_arm_ack, 50 | 51 | output wire [1:0] endp_mode, 52 | 53 | input wire data_toggle_act, 54 | output wire [1:0] data_toggle, 55 | 56 | output wire vend_req_act, 57 | output wire [7:0] vend_req_request, 58 | output wire [15:0] vend_req_val, 59 | 60 | output wire [6:0] dev_addr, 61 | output wire configured, 62 | 63 | output wire err_setup_pkt 64 | 65 | ); 66 | 67 | reg reset_1, reset_2; 68 | 69 | // mux bram signals 70 | wire [5:0] ep0_buf_in_addr = sel_endp == SEL_ENDP0 ? buf_in_addr[5:0] : 6'h0; 71 | wire [7:0] ep0_buf_in_data = sel_endp == SEL_ENDP0 ? buf_in_data : 8'h0; 72 | wire ep0_buf_in_wren = sel_endp == SEL_ENDP0 ? buf_in_wren : 1'h0; 73 | wire ep0_buf_in_ready; 74 | wire ep0_buf_in_commit = sel_endp == SEL_ENDP0 ? buf_in_commit : 1'h0; 75 | wire [9:0] ep0_buf_in_commit_len = sel_endp == SEL_ENDP0 ? buf_in_commit_len : 10'h0; 76 | wire ep0_buf_in_commit_ack; 77 | wire ep0_data_toggle_act = sel_endp == SEL_ENDP0 ? data_toggle_act : 1'h0; 78 | wire [1:0] ep0_data_toggle; 79 | 80 | wire [7:0] ep0_buf_out_addr = sel_endp == SEL_ENDP0 ? buf_out_addr[7:0] : 7'h0; 81 | wire [7:0] ep0_buf_out_q; 82 | wire [9:0] ep0_buf_out_len; 83 | wire ep0_buf_out_hasdata; 84 | wire ep0_buf_out_arm = sel_endp == SEL_ENDP0 ? buf_out_arm : 1'h0; 85 | wire ep0_buf_out_arm_ack; 86 | 87 | wire [8:0] ep1_buf_out_addr = sel_endp == SEL_ENDP1 ? buf_out_addr : 9'h0; 88 | wire [7:0] ep1_buf_out_q; 89 | wire [9:0] ep1_buf_out_len; 90 | wire ep1_buf_out_hasdata; 91 | wire ep1_buf_out_arm = sel_endp == SEL_ENDP1 ? buf_out_arm : 1'h0; 92 | wire ep1_buf_out_arm_ack; 93 | wire ep1_data_toggle_act = sel_endp == SEL_ENDP1 ? data_toggle_act : 1'h0; 94 | wire [1:0] ep1_data_toggle; 95 | 96 | wire [8:0] ep2_buf_in_addr = sel_endp == SEL_ENDP2 ? buf_in_addr : 9'h0; 97 | wire [7:0] ep2_buf_in_data = sel_endp == SEL_ENDP2 ? buf_in_data : 8'h0; 98 | wire ep2_buf_in_wren = sel_endp == SEL_ENDP2 ? buf_in_wren : 1'h0; 99 | wire ep2_buf_in_ready; 100 | wire ep2_buf_in_commit = sel_endp == SEL_ENDP2 ? buf_in_commit : 1'h0; 101 | wire [9:0] ep2_buf_in_commit_len = sel_endp == SEL_ENDP2 ? buf_in_commit_len : 10'h0; 102 | wire ep2_buf_in_commit_ack; 103 | wire ep2_data_toggle_act = sel_endp == SEL_ENDP2 ? data_toggle_act : 1'h0; 104 | wire [1:0] ep2_data_toggle; 105 | 106 | 107 | assign buf_in_ready = sel_endp == SEL_ENDP0 ? ep0_buf_in_ready : 108 | sel_endp == SEL_ENDP2 ? ep2_buf_in_ready : 1'h0; 109 | 110 | assign buf_in_commit_ack = sel_endp == SEL_ENDP0 ? ep0_buf_in_commit_ack : 111 | sel_endp == SEL_ENDP2 ? ep2_buf_in_commit_ack : 1'h0; 112 | 113 | assign buf_out_q = sel_endp == SEL_ENDP0 ? ep0_buf_out_q : 114 | sel_endp == SEL_ENDP1 ? ep1_buf_out_q : 8'h0; 115 | 116 | assign buf_out_len = sel_endp == SEL_ENDP0 ? ep0_buf_out_len : 117 | sel_endp == SEL_ENDP1 ? ep1_buf_out_len : 10'h0; 118 | 119 | assign buf_out_hasdata = sel_endp == SEL_ENDP0 ? ep0_buf_out_hasdata : 120 | sel_endp == SEL_ENDP1 ? ep1_buf_out_hasdata : 1'h0; 121 | 122 | assign buf_out_arm_ack = sel_endp == SEL_ENDP0 ? ep0_buf_out_arm_ack : 123 | sel_endp == SEL_ENDP1 ? ep1_buf_out_arm_ack : 1'h0; 124 | 125 | assign endp_mode = sel_endp == SEL_ENDP1 ? EP1_MODE : 126 | sel_endp == SEL_ENDP2 ? EP2_MODE : EP_MODE_CONTROL; 127 | 128 | assign data_toggle = sel_endp == SEL_ENDP0 ? ep0_data_toggle : 129 | sel_endp == SEL_ENDP1 ? ep1_data_toggle : 130 | sel_endp == SEL_ENDP2 ? ep2_data_toggle : 2'h0; 131 | 132 | parameter [3:0] SEL_ENDP0 = 4'd0, 133 | SEL_ENDP1 = 4'd1, 134 | SEL_ENDP2 = 4'd2; 135 | 136 | parameter [1:0] EP_MODE_CONTROL = 2'd0, 137 | EP_MODE_ISOCH = 2'd1, 138 | EP_MODE_BULK = 2'd2, 139 | EP_MODE_INTERRUPT = 2'd3; 140 | 141 | // assign endpoint modes here and also 142 | // in the descriptor strings 143 | wire [1:0] EP1_MODE = EP_MODE_BULK; 144 | wire [1:0] EP2_MODE = EP_MODE_BULK; 145 | 146 | reg [5:0] dc; 147 | 148 | reg [5:0] state; 149 | parameter [5:0] ST_RST_0 = 6'd0, 150 | ST_RST_1 = 6'd1, 151 | ST_IDLE = 6'd10; 152 | 153 | always @(posedge phy_clk) begin 154 | 155 | {reset_2, reset_1} <= {reset_1, reset_n}; 156 | 157 | dc <= dc + 1'b1; 158 | 159 | case(state) 160 | ST_RST_0: begin 161 | // reset state 162 | state <= ST_RST_1; 163 | end 164 | ST_RST_1: begin 165 | state <= ST_IDLE; 166 | end 167 | ST_IDLE: begin 168 | 169 | end 170 | default: state <= ST_RST_0; 171 | endcase 172 | 173 | if(~reset_2) begin 174 | // reset 175 | state <= ST_RST_0; 176 | end 177 | 178 | end 179 | 180 | 181 | 182 | //////////////////////////////////////////////////////////// 183 | // 184 | // ENDPOINT 0 IN/OUT 185 | // 186 | //////////////////////////////////////////////////////////// 187 | 188 | usb2_ep0 iep0 ( 189 | .phy_clk ( phy_clk ), 190 | .reset_n ( reset_n ), 191 | 192 | .buf_in_addr ( ep0_buf_in_addr ), 193 | .buf_in_data ( ep0_buf_in_data ), 194 | .buf_in_wren ( ep0_buf_in_wren ), 195 | .buf_in_ready ( ep0_buf_in_ready ), 196 | .buf_in_commit ( ep0_buf_in_commit ), 197 | .buf_in_commit_len ( ep0_buf_in_commit_len ), 198 | .buf_in_commit_ack ( ep0_buf_in_commit_ack ), 199 | 200 | .buf_out_addr ( ep0_buf_out_addr ), 201 | .buf_out_q ( ep0_buf_out_q ), 202 | .buf_out_len ( ep0_buf_out_len ), 203 | .buf_out_hasdata ( ep0_buf_out_hasdata ), 204 | .buf_out_arm ( ep0_buf_out_arm ), 205 | .buf_out_arm_ack ( ep0_buf_out_arm_ack ), 206 | 207 | .vend_req_act ( vend_req_act ), 208 | .vend_req_request ( vend_req_request ), 209 | .vend_req_val ( vend_req_val ), 210 | 211 | .data_toggle_act ( ep0_data_toggle_act ), 212 | .data_toggle ( ep0_data_toggle ), 213 | 214 | .dev_addr ( dev_addr ), 215 | .configured ( configured ), 216 | 217 | .err_setup_pkt ( err_setup_pkt ) 218 | ); 219 | 220 | 221 | //////////////////////////////////////////////////////////// 222 | // 223 | // ENDPOINT 1 IN 224 | // 225 | //////////////////////////////////////////////////////////// 226 | 227 | usb2_ep iep1 ( 228 | .phy_clk ( phy_clk ), 229 | .rd_clk ( phy_clk ), 230 | .wr_clk ( ext_clk ), 231 | 232 | .reset_n ( reset_n ), 233 | 234 | .buf_in_addr ( ext_buf_in_addr ), 235 | .buf_in_data ( ext_buf_in_data ), 236 | .buf_in_wren ( ext_buf_in_wren ), 237 | .buf_in_ready ( ext_buf_in_ready ), 238 | .buf_in_commit ( ext_buf_in_commit ), 239 | .buf_in_commit_len ( ext_buf_in_commit_len ), 240 | .buf_in_commit_ack ( ext_buf_in_commit_ack ), 241 | 242 | .buf_out_addr ( ep1_buf_out_addr ), 243 | .buf_out_q ( ep1_buf_out_q ), 244 | .buf_out_len ( ep1_buf_out_len ), 245 | .buf_out_hasdata ( ep1_buf_out_hasdata ), 246 | .buf_out_arm ( ep1_buf_out_arm ), 247 | .buf_out_arm_ack ( ep1_buf_out_arm_ack ), 248 | 249 | .mode ( EP1_MODE ), 250 | 251 | .data_toggle_act ( ep1_data_toggle_act ), 252 | .data_toggle ( ep1_data_toggle ) 253 | ); 254 | 255 | //////////////////////////////////////////////////////////// 256 | // 257 | // ENDPOINT 2 OUT 258 | // 259 | //////////////////////////////////////////////////////////// 260 | 261 | usb2_ep iep2 ( 262 | .phy_clk ( phy_clk ), 263 | .rd_clk ( ext_clk ), 264 | .wr_clk ( phy_clk ), 265 | 266 | .reset_n ( reset_n ), 267 | 268 | .buf_in_addr ( ep2_buf_in_addr ), 269 | .buf_in_data ( ep2_buf_in_data ), 270 | .buf_in_wren ( ep2_buf_in_wren ), 271 | .buf_in_ready ( ep2_buf_in_ready ), 272 | .buf_in_commit ( ep2_buf_in_commit ), 273 | .buf_in_commit_len ( ep2_buf_in_commit_len ), 274 | .buf_in_commit_ack ( ep2_buf_in_commit_ack ), 275 | 276 | .buf_out_addr ( ext_buf_out_addr ), 277 | .buf_out_q ( ext_buf_out_q ), 278 | .buf_out_len ( ext_buf_out_len ), 279 | .buf_out_hasdata ( ext_buf_out_hasdata ), 280 | .buf_out_arm ( ext_buf_out_arm ), 281 | .buf_out_arm_ack ( ext_buf_out_arm_ack ), 282 | 283 | .mode ( EP2_MODE ), 284 | 285 | .data_toggle_act ( ep2_data_toggle_act ), 286 | .data_toggle ( ep2_data_toggle ) 287 | ); 288 | 289 | 290 | 291 | endmodule 292 | 293 | -------------------------------------------------------------------------------- /core/usb3/usb3_const.vh: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 3.0 constants include file 4 | // 5 | // Copyright (c) 2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | 12 | // 13 | // LTSSM state definitions 14 | // 15 | parameter [4:0] LT_SS_DISABLED = 'd01, 16 | LT_SS_INACTIVE = 'd02, 17 | LT_SS_INACTIVE_QUIET = 'd03, 18 | LT_SS_INACTIVE_DETECT_0 = 'd04, 19 | LT_SS_INACTIVE_DETECT_1 = 'd05, 20 | LT_RX_DETECT_RESET = 'd06, 21 | LT_RX_DETECT_ACTIVE_0 = 'd07, 22 | LT_RX_DETECT_ACTIVE_1 = 'd08, 23 | LT_RX_DETECT_QUIET = 'd09, 24 | LT_POLLING_LFPS = 'd10, 25 | LT_POLLING_RXEQ_0 = 'd11, 26 | LT_POLLING_RXEQ_1 = 'd12, 27 | LT_POLLING_ACTIVE = 'd13, 28 | LT_POLLING_CONFIG = 'd14, 29 | LT_POLLING_IDLE = 'd15, 30 | LT_U0 = 'd16, 31 | LT_U1 = 'd17, 32 | LT_U2 = 'd18, 33 | LT_U3 = 'd19, 34 | LT_COMPLIANCE = 'd20, 35 | LT_LOOPBACK = 'd21, 36 | LT_HOTRESET = 'd22, 37 | LT_HOTRESET_ACTIVE = 'd23, 38 | LT_HOTRESET_EXIT = 'd24, 39 | LT_RECOVERY = 'd25, 40 | LT_RECOVERY_WAIT = 'd26, 41 | LT_RECOVERY_ACTIVE = 'd27, 42 | LT_RECOVERY_CONFIG = 'd28, 43 | LT_RECOVERY_IDLE = 'd29, 44 | LT_RESET = 'd30, 45 | LT_LAST = 'b11111; 46 | 47 | parameter [4:0] LFPS_RESET = 'h00, 48 | LFPS_IDLE = 'h01, 49 | LFPS_RECV_1 = 'h02, 50 | LFPS_RECV_2 = 'h03, 51 | LFPS_RECV_3 = 'h04, 52 | LFPS_SEND_1 = 'h05, 53 | LFPS_SEND_2 = 'h06, 54 | LFPS_SEND_3 = 'h07, 55 | LFPS_0 = 'h08, 56 | LFPS_LAST = 'b11111; 57 | 58 | // timing parameters 59 | // all are calculated for local clock of 62.5 MHz (1/4 PIPE CLK) 60 | // except those denoted by *2 which compensates for 125 MHz Link clock domain. 61 | // 62 | parameter [23:0] LFPS_POLLING_MIN = 'd37; // 0.6 uS (nom 1.0 us) 63 | parameter [23:0] LFPS_POLLING_NOM = 'd62; // 1.0 uS 64 | parameter [23:0] LFPS_POLLING_MAX = 'd87; // 1.4 uS 65 | parameter [23:0] LFPS_PING_MIN = 'd2; // 40 ns 66 | parameter [23:0] LFPS_PING_NOM = 'd6; // 96 ns 67 | parameter [23:0] LFPS_PING_MAX = 'd12; // 200 ns 68 | parameter [23:0] LFPS_RESET_MIN = 'd5000000; // 80 ms (nom 100 ms) 69 | parameter [23:0] LFPS_RESET_DELAY = 'd1875000; // 30 ms 70 | parameter [23:0] LFPS_RESET_MAX = 'd7500000; // 120 ms 71 | parameter [23:0] LFPS_U1EXIT_MIN = 'd36; // 656 ns // now 616ns due to lecroy 72 | parameter [23:0] LFPS_U1EXIT_NOM = 'd42; // 656 ns // was 625*4 in testing 73 | parameter [23:0] LFPS_U1EXIT_MAX = 'd125000; // 2 ms (1.5, fudged) 74 | parameter [23:0] LFPS_U2LBEXIT_MIN = 'd5100; // 80 us 75 | parameter [23:0] LFPS_U2LBEXIT_NOM = 'd6250; // 100 us // 5362 76 | parameter [23:0] LFPS_U2LBEXIT_MAX = 'd125000+62500; // 2 ms 77 | parameter [23:0] LFPS_U3WAKEUP_MIN = 'd5000; // 80 us 78 | parameter [23:0] LFPS_U3WAKEUP_NOM = 'd62500; // 1 ms 79 | parameter [23:0] LFPS_U3WAKEUP_MAX = 'd625000; // 10 ms 80 | 81 | parameter [23:0] LFPS_BURST_POLL_MIN = 'd375; // 6 us (nom 10 uS) 82 | parameter [23:0] LFPS_BURST_POLL_NOM = 'd625; // 10 uS 83 | parameter [23:0] LFPS_BURST_POLL_MAX = 'd875; // 14 us 84 | parameter [23:0] LFPS_BURST_PING_MIN = 'd10000000; // 160 ms (nom 200 ms) 85 | parameter [23:0] LFPS_BURST_PING_NOM = 'd12500000; // 200 ms 86 | parameter [23:0] LFPS_BURST_PING_MAX = 'd15000000; // 240 ms 87 | 88 | parameter [24:0] T_SS_INACTIVE_QUIET = 'd750000; // 12 ms 89 | parameter [24:0] T_RX_DETECT_QUIET = 'd7500000; // 120 ms 90 | parameter [24:0] T_POLLING_LFPS = 'd22500000; // 360 ms 91 | parameter [24:0] T_POLLING_ACTIVE = 'd750000; // 12 ms 92 | parameter [24:0] T_POLLING_CONFIG = 'd750000; // 12 ms 93 | parameter [24:0] T_POLLING_IDLE = 'd125000; // 2 ms 94 | parameter [24:0] T_U0_RECOVERY = 'd125000; // 1 ms used in Link Layer, double cycles 95 | parameter [24:0] T_U0L_TIMEOUT = 'd1250; // 10 us used in Link Layer, double cycles 96 | parameter [24:0] T_PENDING_HP = 'd376; // 3 us used in Link Layer, double cycles 97 | parameter [24:0] T_CREDIT_HP = 'd625000; // 5000 us used in Link Layer, double cycles 98 | parameter [24:0] T_NOLFPS_U1 = 'd125000; // 2 ms 99 | parameter [24:0] T_U1_PING = 'd18750000; // 300 ms 100 | parameter [24:0] T_NOLFPS_U2 = 'd125000; // 2 ms 101 | parameter [24:0] T_NOLFPS_U3 = 'd625000; // 10 ms 102 | parameter [24:0] T_RECOV_ACTIVE = 'd750000; // 12 ms 103 | parameter [24:0] T_RECOV_CONFIG = 'd375000; // 6 ms 104 | parameter [24:0] T_RECOV_IDLE = 'd125000; // 2 ms 105 | parameter [24:0] T_LOOPBACK_EXIT = 'd125000; // 2 ms 106 | 107 | parameter [24:0] T_PM_LC = 'd376; // 3 us used in Link Layer, double cycles 108 | parameter [24:0] T_PM_ENTRY = 'd752; // 6 us used in Link Layer, double cycles 109 | parameter [24:0] T_UX_EXIT = 'd750000; // 6 ms used in Link Layer, double cycles 110 | 111 | parameter [24:0] T_PORT_CONFIG = 'd2550; // 20 us used in Link Layer, double cycles 112 | 113 | parameter [1:0] POWERDOWN_0 = 2'd0, // active transmitting 114 | POWERDOWN_1 = 2'd1, // slight powerdown 115 | POWERDOWN_2 = 2'd2, // slowest 116 | POWERDOWN_3 = 2'd3; // deep sleep, clock stopped 117 | parameter SWING_FULL = 1'b0, // transmitter voltage swing 118 | SWING_HALF = 1'b1; 119 | parameter ELASBUF_HALF = 1'b0, // elastic buffer mode 120 | ELASBUF_EMPTY = 1'b1; 121 | parameter [2:0] MARGIN_A = 3'b000, // Normal range 122 | MARGIN_B = 3'b001, // Decreasing voltage levels 123 | MARGIN_C = 3'b010, // See PHY datasheet 124 | MARGIN_D = 3'b011, 125 | MARGIN_E = 3'b100; 126 | parameter [1:0] DEEMPH_6_0_DB = 2'b00, // -6.0dB TX de-emphasis 127 | DEEMPH_3_5_DB = 2'b01, // -3.5dB TX de-emphasis 128 | DEEMPH_NONE = 2'b10, // no TX de-emphasis 129 | DEEMPH_RESVD = 2'b11; 130 | 131 | // 132 | // Link constants 133 | // 134 | 135 | parameter [10:0] LCMD_LGOOD = 'b00_00_000_0_xxx, 136 | LCMD_LGOOD_0 = 'b00_00_000_0_000, 137 | LCMD_LGOOD_1 = 'b00_00_000_0_001, 138 | LCMD_LGOOD_2 = 'b00_00_000_0_010, 139 | LCMD_LGOOD_3 = 'b00_00_000_0_011, 140 | LCMD_LGOOD_4 = 'b00_00_000_0_100, 141 | LCMD_LGOOD_5 = 'b00_00_000_0_101, 142 | LCMD_LGOOD_6 = 'b00_00_000_0_110, 143 | LCMD_LGOOD_7 = 'b00_00_000_0_111; 144 | 145 | parameter [10:0] LCMD_LCRD = 'b00_01_000_00_xx, 146 | LCMD_LCRD_A = 'b00_01_000_00_00, 147 | LCMD_LCRD_B = 'b00_01_000_00_01, 148 | LCMD_LCRD_C = 'b00_01_000_00_10, 149 | LCMD_LCRD_D = 'b00_01_000_00_11; 150 | 151 | parameter [10:0] LCMD_LRTY = 'b00_10_000_0000, 152 | LCMD_LBAD = 'b00_11_000_0000; 153 | 154 | parameter [10:0] LCMD_LGO = 'b01_00_000_00xx, 155 | LCMD_LGO_U1 = 'b01_00_000_0001, 156 | LCMD_LGO_U2 = 'b01_00_000_0010, 157 | LCMD_LGO_U3 = 'b01_00_000_0011; 158 | 159 | parameter [10:0] LCMD_LAU = 'b01_01_000_0000, 160 | LCMD_LXU = 'b01_10_000_0000, 161 | LCMD_LPMA = 'b01_11_000_0000; 162 | 163 | parameter [10:0] LCMD_LDN = 'b10_11_000_0000, 164 | LCMD_LUP = 'b10_00_000_0000; 165 | 166 | parameter [4:0] LP_TYPE_LMP = 'b00000, 167 | LP_TYPE_TP = 'b00100, 168 | LP_TYPE_DP = 'b01000, 169 | LP_TYPE_ITP = 'b01100; 170 | 171 | parameter [3:0] LP_LMP_SUB_RSVD = 'b0000, 172 | LP_LMP_SUB_SETLINK = 'b0001, 173 | LP_LMP_SUB_U2INACT = 'b0010, 174 | LP_LMP_SUB_VENDTEST = 'b0011, 175 | LP_LMP_SUB_PORTCAP = 'b0100, 176 | LP_LMP_SUB_PORTCFG = 'b0101, 177 | LP_LMP_SUB_PORTCFGRSP = 'b0110; 178 | 179 | parameter [6:0] LP_LMP_SPEED_5GBPS = 'b000000_1; 180 | parameter [6:0] LP_LMP_SPEED_DECLINE = 'b000000_0; 181 | parameter [6:0] LP_LMP_SPEED_ACCEPT = 'b000000_1; 182 | parameter [7:0] LP_LMP_NUM_HP_4 = 'd4; 183 | parameter [1:0] LP_LMP_DIR_DOWN = 'b01; 184 | parameter [1:0] LP_LMP_DIR_UP = 'b10; 185 | parameter [0:0] LP_LMP_OTG_INCAPABLE = 'b0; 186 | parameter [0:0] LP_LMP_OTG_CAPABLE = 'b1; 187 | parameter [3:0] LP_LMP_TIEBREAK = 'b0000; 188 | 189 | parameter [3:0] LP_TP_SUB_RSVD = 'b0000, 190 | LP_TP_SUB_ACK = 'b0001, 191 | LP_TP_SUB_NRDY = 'b0010, 192 | LP_TP_SUB_ERDY = 'b0011, 193 | LP_TP_SUB_STATUS = 'b0100, 194 | LP_TP_SUB_STALL = 'b0101, 195 | LP_TP_SUB_DEVNOTIFY = 'b0110, 196 | LP_TP_SUB_PING = 'b0111, 197 | LP_TP_SUB_PINGRSP = 'b1000; 198 | 199 | parameter [19:0] LP_TP_ROUTE0 = 'b0; 200 | parameter [0:0] LP_TP_NORETRY = 'b0, 201 | LP_TP_RETRY = 'b1; 202 | parameter [0:0] LP_TP_HOSTTODEVICE = 'b0, 203 | LP_TP_DEVICETOHOST = 'b1; 204 | parameter [15:0] LP_TP_STREAMID = 'h0; 205 | // 206 | // the following are for isochronous endpoints only (Table 8-12) 207 | // 208 | parameter [0:0] LP_TP_SSI_NO = 'b0, // Support Smart Isochronous 209 | LP_TP_SSI_YES = 'b1; 210 | parameter [0:0] LP_TP_WPA_NO = 'b0, // Will Ping Again 211 | LP_TP_WPA_YES = 'b1; 212 | parameter [0:0] LP_TP_DBI_NO = 'b0, // Data in Bus Interval Done 213 | LP_TP_DBI_YES = 'b1; 214 | // 215 | parameter [0:0] LP_TP_PPEND_NO = 'b0, // Packets Pending from Host 216 | LP_TP_PPEND_YES = 'b1; 217 | parameter [3:0] LP_TP_NBI_0 = 'b0; // Number of Bus Intervals 218 | 219 | parameter [3:0] LP_TP_DN_FUNC_AWAKE = 'b0001, 220 | LP_TP_DN_LAT_TOL_MSG = 'b0010, 221 | LP_TP_DN_BUS_INTER_ADJ = 'b0011, 222 | LP_TP_DN_HOST_ROLE_REQ = 'b0100; 223 | 224 | parameter [0:0] LP_DP_EOB_LPF_NO = 1'b0, 225 | LP_DP_EOB_LPF_YES = 1'b1; 226 | 227 | function [15:0] swap16; 228 | input [15:0] i; 229 | swap16 = {i[7:0], i[15:8]}; 230 | endfunction 231 | 232 | function [31:0] swap32; 233 | input [31:0] i; 234 | swap32 = {i[7:0], i[15:8], i[23:16], i[31:24]}; 235 | endfunction 236 | 237 | `define INC(x) x<=x+1'b1 238 | `define DEC(x) x<=x-1'b1 239 | 240 | // 241 | // end usb3_const.vh 242 | // 243 | -------------------------------------------------------------------------------- /core/usb3/usb3_ep0.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 3.0 endpoint 0 4 | // 5 | // Copyright (c) 2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb3_ep0 ( 12 | 13 | input wire slow_clk, 14 | input wire local_clk, 15 | input wire reset_n, 16 | 17 | input wire [8:0] buf_in_addr, 18 | input wire [31:0] buf_in_data, 19 | input wire buf_in_wren, 20 | output wire buf_in_ready, 21 | input wire buf_in_commit, 22 | input wire [10:0] buf_in_commit_len, 23 | output wire buf_in_commit_ack, 24 | 25 | input wire [8:0] buf_out_addr, 26 | output wire [31:0] buf_out_q, 27 | output wire [10:0] buf_out_len, 28 | output wire buf_out_hasdata, 29 | input wire buf_out_arm, 30 | output wire buf_out_arm_ack, 31 | 32 | output reg vend_req_act, 33 | output reg [7:0] vend_req_request, 34 | output reg [15:0] vend_req_val, 35 | output reg [15:0] vend_req_index, 36 | //output reg [15:0] vend_req_len, 37 | 38 | output reg [6:0] dev_addr, 39 | output reg configured, 40 | output reg reset_dp_seq, 41 | 42 | output reg err_setup_pkt 43 | 44 | ); 45 | 46 | `include "usb3_const.vh" 47 | `include "usb_descrip.vh" 48 | 49 | reg buf_in_commit_1, buf_in_commit_2; 50 | reg buf_out_arm_1, buf_out_arm_2; 51 | 52 | reg [63:0] packet_setup; 53 | wire [7:0] packet_setup_reqtype = packet_setup[63:56]; 54 | wire packet_setup_dir = packet_setup_reqtype[7]; 55 | parameter SETUP_DIR_HOSTTODEV = 1'b0, 56 | SETUP_DIR_DEVTOHOST = 1'b1; 57 | wire [1:0] packet_setup_type = packet_setup_reqtype[6:5]; 58 | parameter [1:0] SETUP_TYPE_STANDARD = 2'h0, 59 | SETUP_TYPE_CLASS = 2'h1, 60 | SETUP_TYPE_VENDOR = 2'h2, 61 | SETUP_TYPE_RESVD = 2'h3; 62 | wire [4:0] packet_setup_recpt = packet_setup_reqtype[4:0]; 63 | parameter [4:0] SETUP_RECPT_DEVICE = 5'h0, 64 | SETUP_RECPT_IFACE = 5'h1, 65 | SETUP_RECPT_ENDP = 5'h2, 66 | SETUP_RECPT_OTHER = 5'h3; 67 | wire [7:0] packet_setup_req = packet_setup[55:48]; 68 | parameter [7:0] REQ_GET_STATUS = 8'h0, 69 | REQ_CLEAR_FEAT = 8'h1, 70 | REQ_SET_FEAT = 8'h3, 71 | REQ_SET_ADDR = 8'h5, 72 | REQ_GET_DESCR = 8'h6, 73 | REQ_SET_DESCR = 8'h7, 74 | REQ_GET_CONFIG = 8'h8, 75 | REQ_SET_CONFIG = 8'h9, 76 | REQ_SET_INTERFACE = 8'hB, 77 | REQ_SYNCH_FRAME = 8'h12, 78 | REQ_SET_SEL = 8'h30; 79 | wire [15:0] packet_setup_wval = {packet_setup[39:32], packet_setup[47:40]}; 80 | wire [15:0] packet_setup_widx = {packet_setup[23:16], packet_setup[31:24]}; 81 | wire [15:0] packet_setup_wlen = {packet_setup[7:0], packet_setup[15:8]}; 82 | 83 | reg [10:0] desired_out_len; 84 | reg [10:0] packet_out_len; 85 | reg [3:0] dev_config; 86 | 87 | reg ptr_in; 88 | reg ptr_out; 89 | 90 | reg [10:0] len_in; 91 | reg ready_in; 92 | assign buf_in_ready = ready_in; 93 | assign buf_in_commit_ack = (state_in == ST_IN_COMMIT); 94 | 95 | reg [10:0] len_out; 96 | reg hasdata_out; 97 | assign buf_out_len = len_out; 98 | assign buf_out_hasdata = hasdata_out; 99 | assign buf_out_arm_ack = (state_out == ST_OUT_ARM); 100 | 101 | reg [6:0] dc; 102 | 103 | reg [5:0] state_in; 104 | parameter [5:0] ST_RST_0 = 6'd0, 105 | ST_RST_1 = 6'd1, 106 | ST_IDLE = 6'd10, 107 | ST_IN_COMMIT = 6'd11, 108 | ST_IN_SWAP = 6'd20, 109 | ST_IN_PARSE_0 = 6'd21, 110 | ST_IN_PARSE_1 = 6'd22, 111 | ST_REQ_DESCR = 6'd30, 112 | ST_RDLEN_0 = 6'd31, 113 | ST_RDLEN_1 = 6'd32, 114 | ST_RDLEN_2 = 6'd33, 115 | ST_RDLEN_3 = 6'd34, 116 | ST_REQ_GETCONFIG = 6'd35, 117 | ST_REQ_SETCONFIG = 6'd36, 118 | ST_REQ_SETINTERFACE = 6'd37, 119 | ST_REQ_SETADDR = 6'd38, 120 | ST_REQ_VENDOR = 6'd39, 121 | ST_REQ_SETSEL = 6'd40, 122 | ST_REQ_SETFEAT = 6'd41, 123 | ST_REQ_CLRFEAT = 6'd42; 124 | 125 | reg [5:0] state_out; 126 | parameter [5:0] ST_OUT_ARM = 6'd11, 127 | ST_OUT_SWAP = 6'd20; 128 | 129 | always @(posedge local_clk) begin 130 | 131 | {buf_in_commit_2, buf_in_commit_1} <= {buf_in_commit_1, buf_in_commit}; 132 | {buf_out_arm_2, buf_out_arm_1} <= {buf_out_arm_1, buf_out_arm}; 133 | 134 | configured <= dev_config ? 1'b1 : 1'b0; 135 | 136 | reset_dp_seq <= 0; 137 | 138 | `INC(dc); 139 | 140 | // clear act strobe after 4 cycles 141 | if(dc == 3) vend_req_act <= 1'b0; 142 | 143 | // main fsm 144 | case(state_in) 145 | ST_RST_0: begin 146 | len_out <= 0; 147 | 148 | desired_out_len <= 0; 149 | dev_addr <= 0; 150 | dev_config <= 0; 151 | err_setup_pkt <= 0; 152 | 153 | ready_in <= 1; 154 | 155 | state_in <= ST_RST_1; 156 | end 157 | ST_RST_1: begin 158 | state_in <= ST_IDLE; 159 | end 160 | ST_IDLE: begin 161 | // idle state 162 | if(buf_in_commit_1 & ~buf_in_commit_2) begin 163 | // link/protocol layer has written to this endpoint 164 | len_in <= buf_in_commit_len; 165 | 166 | ready_in <= 0; 167 | 168 | dc <= 0; 169 | state_in <= ST_IN_COMMIT; 170 | end 171 | end 172 | ST_IN_COMMIT: begin 173 | // generate ACK pulse 174 | if(dc == 3) begin 175 | dc <= 0; 176 | buf_in_rdaddr <= 0; 177 | state_in <= ST_IN_PARSE_0; 178 | end 179 | end 180 | 181 | ST_IN_PARSE_0: begin 182 | // parse setup packet 183 | `INC(buf_in_rdaddr); 184 | 185 | packet_setup <= {packet_setup[31:0], buf_in_q[31:0]}; 186 | if(dc == (2+2-1)) state_in <= ST_IN_PARSE_1; 187 | end 188 | ST_IN_PARSE_1: begin 189 | // parse setup packet 190 | packet_out_len <= packet_setup_wlen; 191 | 192 | // confirm this is going in the right direction 193 | //if(packet_setup_dir != SETUP_DIR_DEVTOHOST) begin 194 | // err_setup_pkt <= 1; 195 | // state <= 10; 196 | //end else begin 197 | 198 | if(packet_setup_type == SETUP_TYPE_VENDOR) begin 199 | // parse vendor request 200 | state_in <= ST_REQ_VENDOR; 201 | end else begin 202 | // proceed with parsing 203 | 204 | case(packet_setup_req) 205 | REQ_GET_DESCR: begin 206 | state_in <= ST_REQ_DESCR; 207 | end 208 | REQ_GET_CONFIG: begin 209 | state_in <= ST_REQ_GETCONFIG; 210 | end 211 | REQ_SET_CONFIG: begin 212 | state_in <= ST_REQ_SETCONFIG; 213 | end 214 | REQ_SET_INTERFACE: begin 215 | state_in <= ST_REQ_SETINTERFACE; 216 | end 217 | REQ_SET_ADDR: begin 218 | state_in <= ST_REQ_SETADDR; 219 | end 220 | REQ_SET_FEAT: begin 221 | state_in <= ST_REQ_SETFEAT; 222 | end 223 | REQ_CLEAR_FEAT: begin 224 | state_in <= ST_REQ_CLRFEAT; 225 | end 226 | REQ_SET_SEL: begin 227 | state_in <= ST_REQ_SETSEL; 228 | end 229 | default: begin 230 | ready_in <= 1; 231 | state_in <= ST_IDLE; 232 | end 233 | endcase 234 | end 235 | end 236 | 237 | ST_REQ_DESCR: begin 238 | state_in <= ST_RDLEN_0; 239 | 240 | // GET_DESCRIPTOR 241 | case(packet_setup_wval) 242 | 16'h0100: begin 243 | // device descriptor 244 | descrip_addr_offset <= DESCR_USB3_DEVICE; 245 | end 246 | 16'h0200: begin 247 | // config descriptor 248 | descrip_addr_offset <= DESCR_USB3_CONFIG; 249 | desired_out_len <= DESCR_USB3_CONFIG_LEN; 250 | state_in <= ST_RDLEN_3; 251 | end 252 | 16'h0300: begin 253 | // string: languages 254 | descrip_addr_offset <= DESCR_USB3_STRING0; 255 | end 256 | 16'h0301: begin 257 | // string: manufacturer 258 | descrip_addr_offset <= DESCR_USB3_STRING1; 259 | end 260 | 16'h0302: begin 261 | // string: product name 262 | descrip_addr_offset <= DESCR_USB3_STRING2; 263 | end 264 | 16'h0303: begin 265 | // string: serial number 266 | descrip_addr_offset <= DESCR_USB3_STRING3; 267 | end 268 | //16'h0600: begin 269 | // device qualifier descriptor 270 | //descrip_addr_offset <= DESCR_OFF_DEVQUAL; 271 | //end 272 | 16'h0f00: begin 273 | // BOS #0 274 | descrip_addr_offset <= DESCR_USB3_BOS; 275 | desired_out_len <= DESCR_USB3_BOS_LEN; 276 | state_in <= ST_RDLEN_3; 277 | end 278 | default: begin 279 | packet_out_len <= 0; 280 | end 281 | endcase 282 | end 283 | ST_RDLEN_0: begin 284 | // wait cycle if descriptor BRAM has a buffered output 285 | state_in <= ST_RDLEN_1; 286 | end 287 | ST_RDLEN_1: begin 288 | // wait cycle if descriptor BRAM has a buffered output 289 | state_in <= ST_RDLEN_2; 290 | end 291 | ST_RDLEN_2: begin 292 | // pick off the first byte at the pointer 293 | desired_out_len <= buf_out_q[31:24]; 294 | state_in <= ST_RDLEN_3; 295 | end 296 | ST_RDLEN_3: begin 297 | // pick smaller of the setup packet's wanted length and the stored length 298 | len_out <= packet_out_len < desired_out_len ? packet_out_len : desired_out_len; 299 | // send response 300 | ready_in <= 1; 301 | hasdata_out <= 1; 302 | state_in <= ST_IDLE; 303 | end 304 | ST_REQ_GETCONFIG: begin 305 | // GET DEVICE CONFIGURATION 306 | 307 | // send 1byte response 308 | len_out <= 1; 309 | ready_in <= 1; 310 | hasdata_out <= 1; 311 | descrip_addr_offset <= dev_config ? DESCR_USB3_CONFSET : DESCR_USB3_CONFUNSET; 312 | state_in <= ST_IDLE; 313 | end 314 | ST_REQ_SETCONFIG: begin 315 | // SET DEVICE CONFIGURATION 316 | dev_config <= packet_setup_wval[6:0]; 317 | reset_dp_seq <= 1; 318 | 319 | // send 0byte response 320 | len_out <= 0; 321 | ready_in <= 1; 322 | hasdata_out <= 1; 323 | state_in <= ST_IDLE; 324 | end 325 | ST_REQ_SETINTERFACE: begin 326 | // SET INTERFACE 327 | //dev_config <= packet_setup_wval[6:0]; 328 | reset_dp_seq <= 1; 329 | 330 | // send 0byte response 331 | len_out <= 0; 332 | ready_in <= 1; 333 | hasdata_out <= 1; 334 | state_in <= ST_IDLE; 335 | end 336 | ST_REQ_SETADDR: begin 337 | // SET DEVICE ADDRESS 338 | dev_addr <= packet_setup_wval[6:0]; 339 | 340 | // send 0byte response 341 | len_out <= 0; 342 | ready_in <= 1; 343 | hasdata_out <= 1; 344 | state_in <= ST_IDLE; 345 | end 346 | ST_REQ_VENDOR: begin 347 | // VENDOR REQUEST 348 | vend_req_request <= packet_setup_req; 349 | vend_req_val <= packet_setup_wval; 350 | vend_req_index <= packet_setup_widx; 351 | // optional data stage for bidir control transfers 352 | // would require additional unsupported code in this endpoint 353 | //vend_req_len <= packet_setup_wlen; 354 | // signal to external interface there was a vend_req 355 | vend_req_act <= 1'b1; 356 | dc <= 0; 357 | // send 0byte response 358 | len_out <= 0; 359 | ready_in <= 1; 360 | hasdata_out <= 1; 361 | state_in <= ST_IDLE; 362 | end 363 | ST_REQ_SETSEL: begin 364 | // send 0byte response 365 | len_out <= 0; 366 | ready_in <= 1; 367 | hasdata_out <= 1; 368 | state_in <= ST_IDLE; 369 | end 370 | ST_REQ_SETFEAT: begin 371 | // U1/U2 Enable; parse wValue TODO 372 | len_out <= 0; 373 | ready_in <= 1; 374 | hasdata_out <= 1; 375 | state_in <= ST_IDLE; 376 | end 377 | ST_REQ_CLRFEAT: begin 378 | reset_dp_seq <= 1; 379 | 380 | len_out <= 0; 381 | ready_in <= 1; 382 | hasdata_out <= 1; 383 | state_in <= ST_IDLE; 384 | end 385 | 386 | 387 | 388 | 389 | default: state_in <= ST_RST_0; 390 | endcase 391 | 392 | 393 | 394 | // output FSM 395 | // 396 | case(state_out) 397 | ST_RST_0: begin 398 | hasdata_out <= 0; 399 | 400 | // configure default state 401 | state_out <= ST_RST_1; 402 | end 403 | ST_RST_1: begin 404 | state_out <= ST_IDLE; 405 | end 406 | ST_IDLE: begin 407 | // idle state 408 | if(buf_out_arm_1 & ~buf_out_arm_2) begin 409 | // free up this endpoint 410 | dc <= 0; 411 | state_out <= ST_OUT_ARM; 412 | end 413 | end 414 | ST_OUT_ARM: begin 415 | // generate ARM_ACK pulse, several cycles for compat with slower FSMs 416 | if(dc == 3) begin 417 | state_out <= ST_OUT_SWAP; 418 | end 419 | end 420 | ST_OUT_SWAP: begin 421 | // this endpoint is not double buffered! 422 | // current buffer is now ready for data 423 | ready_in <= 1; 424 | // update hasdata status 425 | hasdata_out <= 0; 426 | 427 | state_out <= ST_IDLE; 428 | end 429 | default: state_out <= ST_RST_0; 430 | endcase 431 | 432 | if(~reset_n) begin 433 | // reset 434 | state_in <= ST_RST_0; 435 | state_out <= ST_RST_0; 436 | 437 | end 438 | 439 | end 440 | 441 | 442 | reg [3:0] buf_in_rdaddr; 443 | wire [31:0] buf_in_q; 444 | 445 | usb3_ep0in_ram iu3ep0i ( 446 | .clk ( local_clk ), 447 | .wr_dat_w ( buf_in_data ), 448 | .rd_adr ( buf_in_rdaddr ), 449 | .wr_adr ( buf_in_addr ), 450 | .wr_we ( buf_in_wren ), 451 | .rd_dat_r ( buf_in_q ) 452 | ); 453 | 454 | reg [7:0] descrip_addr_offset; 455 | 456 | usb3_descrip_rom iu3d ( 457 | .clk ( local_clk ), 458 | .adr ( buf_out_addr + descrip_addr_offset), 459 | .dat_r ( buf_out_q ) 460 | ); 461 | 462 | 463 | endmodule 464 | -------------------------------------------------------------------------------- /core/usb2/usb2_ep0.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 2.0 endpoint 0 control 4 | // 5 | // Copyright (c) 2012-2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb2_ep0 ( 12 | 13 | // top-level interface 14 | input wire phy_clk, 15 | input wire reset_n, 16 | 17 | // PROTOCOL 18 | input wire [3:0] buf_in_pid, 19 | 20 | input wire [8:0] buf_in_addr, 21 | input wire [7:0] buf_in_data, 22 | input wire buf_in_wren, 23 | output wire buf_in_ready, 24 | input wire buf_in_commit, 25 | input wire [9:0] buf_in_commit_len, 26 | output wire buf_in_commit_ack, 27 | 28 | input wire [8:0] buf_out_addr, 29 | output wire [7:0] buf_out_q, 30 | output wire [9:0] buf_out_len, 31 | output wire buf_out_hasdata, 32 | input wire buf_out_arm, 33 | output wire buf_out_arm_ack, 34 | 35 | output reg vend_req_act, 36 | output reg [7:0] vend_req_request, 37 | output reg [15:0] vend_req_val, 38 | //output reg [15:0] vend_req_index, 39 | //output reg [15:0] vend_req_len, 40 | 41 | input wire data_toggle_act, 42 | output reg [1:0] data_toggle, 43 | 44 | output reg [6:0] dev_addr, 45 | output reg configured, 46 | 47 | output reg err_setup_pkt 48 | 49 | ); 50 | 51 | `include "usb_descrip.vh" 52 | 53 | reg reset_1, reset_2; 54 | reg buf_in_commit_1, buf_in_commit_2; 55 | reg buf_out_arm_1, buf_out_arm_2; 56 | 57 | parameter [3:0] PID_TOKEN_OUT = 4'hE, 58 | PID_TOKEN_IN = 4'h6, 59 | PID_TOKEN_SOF = 4'hA, 60 | PID_TOKEN_SETUP = 4'h2, 61 | PID_DATA_0 = 4'hC, 62 | PID_DATA_1 = 4'h4, 63 | PID_DATA_2 = 4'h8, 64 | PID_DATA_M = 4'h0, 65 | PID_HAND_ACK = 4'hD, 66 | PID_HAND_NAK = 4'h5, 67 | PID_HAND_STALL = 4'h1, 68 | PID_HAND_NYET = 4'h9, 69 | PID_SPEC_PREERR = 4'h3, 70 | PID_SPEC_SPLIT = 4'h7, 71 | PID_SPEC_PING = 4'hB, 72 | PID_SPEC_LPM = 4'hF; 73 | 74 | reg [79:0] packet_setup; 75 | wire [7:0] packet_setup_reqtype = packet_setup[79:72]; 76 | wire packet_setup_dir = packet_setup_reqtype[7]; 77 | parameter SETUP_DIR_HOSTTODEV = 1'b0, 78 | SETUP_DIR_DEVTOHOST = 1'b1; 79 | wire [1:0] packet_setup_type = packet_setup_reqtype[6:5]; 80 | parameter [1:0] SETUP_TYPE_STANDARD = 2'h0, 81 | SETUP_TYPE_CLASS = 2'h1, 82 | SETUP_TYPE_VENDOR = 2'h2, 83 | SETUP_TYPE_RESVD = 2'h3; 84 | wire [4:0] packet_setup_recpt = packet_setup_reqtype[4:0]; 85 | parameter [4:0] SETUP_RECPT_DEVICE = 5'h0, 86 | SETUP_RECPT_IFACE = 5'h1, 87 | SETUP_RECPT_ENDP = 5'h2, 88 | SETUP_RECPT_OTHER = 5'h3; 89 | wire [7:0] packet_setup_req = packet_setup[71:64]; 90 | parameter [7:0] REQ_GET_STATUS = 8'h0, 91 | REQ_CLEAR_FEAT = 8'h1, 92 | REQ_SET_FEAT = 8'h3, 93 | REQ_SET_ADDR = 8'h5, 94 | REQ_GET_DESCR = 8'h6, 95 | REQ_SET_DESCR = 8'h7, 96 | REQ_GET_CONFIG = 8'h8, 97 | REQ_SET_CONFIG = 8'h9, 98 | REQ_SET_INTERFACE = 8'hB, 99 | REQ_SYNCH_FRAME = 8'h12; 100 | wire [15:0] packet_setup_wval = {packet_setup[55:48], packet_setup[63:56]}; 101 | wire [15:0] packet_setup_widx = {packet_setup[39:32], packet_setup[47:40]}; 102 | wire [15:0] packet_setup_wlen = {packet_setup[23:16], packet_setup[31:24]}; 103 | wire [15:0] packet_setup_crc16 = packet_setup[15:0]; 104 | 105 | reg [5:0] desired_out_len; 106 | reg [15:0] packet_out_len; 107 | reg [3:0] dev_config; 108 | 109 | reg ptr_in; 110 | reg ptr_out; 111 | 112 | reg [9:0] len_in; 113 | reg ready_in; 114 | assign buf_in_ready = ready_in; 115 | assign buf_in_commit_ack = (state_in == ST_IN_COMMIT); 116 | 117 | reg [9:0] len_out; 118 | reg hasdata_out; 119 | assign buf_out_len = len_out; 120 | assign buf_out_hasdata = hasdata_out; 121 | assign buf_out_arm_ack = (state_out == ST_OUT_ARM); 122 | 123 | reg [6:0] dc; 124 | 125 | reg [5:0] state_in; 126 | parameter [5:0] ST_RST_0 = 6'd0, 127 | ST_RST_1 = 6'd1, 128 | ST_IDLE = 6'd10, 129 | ST_IN_COMMIT = 6'd11, 130 | ST_IN_SWAP = 6'd20, 131 | ST_IN_PARSE_0 = 6'd21, 132 | ST_IN_PARSE_1 = 6'd22, 133 | ST_REQ_DESCR = 6'd30, 134 | ST_RDLEN_0 = 6'd31, 135 | ST_RDLEN_1 = 6'd32, 136 | ST_RDLEN_2 = 6'd33, 137 | ST_REQ_GETCONFIG = 6'd34, 138 | ST_REQ_SETCONFIG = 6'd35, 139 | ST_REQ_SETINTERFACE = 6'd36, 140 | ST_REQ_SETADDR = 6'd37, 141 | ST_REQ_VENDOR = 6'd38; 142 | 143 | reg [5:0] state_out; 144 | parameter [5:0] ST_OUT_ARM = 6'd11, 145 | ST_OUT_SWAP = 6'd20; 146 | 147 | 148 | always @(posedge phy_clk) begin 149 | 150 | // synchronizers 151 | {reset_2, reset_1} <= {reset_1, reset_n}; 152 | {buf_in_commit_2, buf_in_commit_1} <= {buf_in_commit_1, buf_in_commit}; 153 | {buf_out_arm_2, buf_out_arm_1} <= {buf_out_arm_1, buf_out_arm}; 154 | 155 | configured <= dev_config ? 1 : 0; 156 | 157 | dc <= dc + 1'b1; 158 | 159 | // clear act strobe after 4 cycles 160 | if(dc == 3) vend_req_act <= 1'b0; 161 | 162 | // main fsm 163 | case(state_in) 164 | ST_RST_0: begin 165 | len_out <= 0; 166 | 167 | // data toggle is fixed at DATA1 168 | data_toggle <= 2'b01; 169 | 170 | desired_out_len <= 0; 171 | dev_addr <= 0; 172 | dev_config <= 0; 173 | err_setup_pkt <= 0; 174 | 175 | ready_in <= 1; 176 | 177 | state_in <= ST_RST_1; 178 | end 179 | ST_RST_1: begin 180 | state_in <= ST_IDLE; 181 | end 182 | ST_IDLE: begin 183 | // idle state 184 | if(buf_in_commit_1 & ~buf_in_commit_2) begin 185 | // external device has written to this endpoint 186 | len_in <= buf_in_commit_len; 187 | 188 | ready_in <= 0; 189 | //if(buf_in_pid == PID_TOKEN_SETUP) begin 190 | // wait for data latch 191 | dc <= 0; 192 | state_in <= ST_IN_COMMIT; 193 | //end 194 | end 195 | end 196 | ST_IN_COMMIT: begin 197 | // generate ACK pulse 198 | if(dc == 3) begin 199 | dc <= 0; 200 | buf_in_rdaddr <= 0; 201 | state_in <= ST_IN_PARSE_0; 202 | end 203 | end 204 | 205 | ST_IN_PARSE_0: begin 206 | // parse setup packet 207 | buf_in_rdaddr <= buf_in_rdaddr + 1'b1; 208 | 209 | packet_setup <= {packet_setup[71:0], buf_in_q[7:0]}; 210 | if(dc == (10+2-1)) state_in <= ST_IN_PARSE_1; 211 | end 212 | ST_IN_PARSE_1: begin 213 | // parse setup packet 214 | packet_out_len <= packet_setup_wlen; 215 | 216 | // confirm this is going in the right direction 217 | //if(packet_setup_dir != SETUP_DIR_DEVTOHOST) begin 218 | // err_setup_pkt <= 1; 219 | // state <= 10; 220 | //end else begin 221 | 222 | if(packet_setup_type == SETUP_TYPE_VENDOR) begin 223 | // parse vendor request 224 | state_in <= ST_REQ_VENDOR; 225 | end else begin 226 | // proceed with parsing 227 | 228 | case(packet_setup_req) 229 | REQ_GET_DESCR: begin 230 | state_in <= ST_REQ_DESCR; 231 | end 232 | REQ_GET_CONFIG: begin 233 | state_in <= ST_REQ_GETCONFIG; 234 | end 235 | REQ_SET_CONFIG: begin 236 | state_in <= ST_REQ_SETCONFIG; 237 | end 238 | REQ_SET_INTERFACE: begin 239 | state_in <= ST_REQ_SETINTERFACE; 240 | end 241 | REQ_SET_ADDR: begin 242 | state_in <= ST_REQ_SETADDR; 243 | end 244 | default: begin 245 | ready_in <= 1; 246 | state_in <= ST_IDLE; 247 | end 248 | endcase 249 | end 250 | end 251 | 252 | ST_REQ_DESCR: begin 253 | 254 | state_in <= ST_RDLEN_0; 255 | 256 | // GET_DESCRIPTOR 257 | case(packet_setup_wval) 258 | 16'h0100: begin 259 | // device descriptor 260 | descrip_addr_offset <= DESCR_USB2_DEVICE; 261 | end 262 | 16'h0200: begin 263 | // config descriptor 264 | descrip_addr_offset <= DESCR_USB2_CONFIG; 265 | desired_out_len <= DESCR_USB2_CONFIG_LEN; 266 | state_in <= ST_RDLEN_2; 267 | end 268 | 16'h0300: begin 269 | // string: languages 270 | descrip_addr_offset <= DESCR_USB2_STRING0; 271 | end 272 | 16'h0301: begin 273 | // string: manufacturer 274 | descrip_addr_offset <= DESCR_USB2_STRING1; 275 | end 276 | 16'h0302: begin 277 | // string: product name 278 | descrip_addr_offset <= DESCR_USB2_STRING2; 279 | end 280 | 16'h0303: begin 281 | // string: serial number 282 | descrip_addr_offset <= DESCR_USB2_STRING3; 283 | end 284 | 16'h0600: begin 285 | // device qualifier descriptor 286 | descrip_addr_offset <= DESCR_USB2_DEVICE_QUAL; 287 | end 288 | default: begin 289 | packet_out_len <= 0; 290 | end 291 | endcase 292 | 293 | end 294 | ST_RDLEN_0: begin 295 | // wait cycle if descriptor BRAM has a buffered output 296 | state_in <= ST_RDLEN_1; 297 | end 298 | ST_RDLEN_1: begin 299 | // pick off the first byte at the pointer 300 | desired_out_len <= buf_out_q; 301 | state_in <= ST_RDLEN_2; 302 | end 303 | ST_RDLEN_2: begin 304 | // pick smaller of the setup packet's wanted length and the stored length 305 | len_out <= packet_out_len < desired_out_len ? packet_out_len : desired_out_len; 306 | // send response (DATA1) 307 | ready_in <= 1; 308 | hasdata_out <= 1; 309 | state_in <= ST_IDLE; 310 | end 311 | ST_REQ_GETCONFIG: begin 312 | // GET DEVICE CONFIGURATION 313 | 314 | // send 1byte response (DATA1) 315 | len_out <= 1; 316 | ready_in <= 1; 317 | hasdata_out <= 1; 318 | descrip_addr_offset <= dev_config ? DESCR_USB2_CONFSET : DESCR_USB2_CONFUNSET; 319 | state_in <= ST_IDLE; 320 | end 321 | ST_REQ_SETCONFIG: begin 322 | // SET DEVICE CONFIGURATION 323 | dev_config <= packet_setup_wval[6:0]; 324 | 325 | // send 0byte response (DATA1) 326 | len_out <= 0; 327 | ready_in <= 1; 328 | hasdata_out <= 1; 329 | state_in <= ST_IDLE; 330 | end 331 | ST_REQ_SETINTERFACE: begin 332 | // SET INTERFACE 333 | //dev_config <= packet_setup_wval[6:0]; 334 | 335 | // send 0byte response (DATA1) 336 | len_out <= 0; 337 | ready_in <= 1; 338 | hasdata_out <= 1; 339 | state_in <= ST_IDLE; 340 | end 341 | ST_REQ_SETADDR: begin 342 | // SET DEVICE ADDRESS 343 | dev_addr <= packet_setup_wval[6:0]; 344 | 345 | // send 0byte response (DATA1) 346 | len_out <= 0; 347 | ready_in <= 1; 348 | hasdata_out <= 1; 349 | state_in <= ST_IDLE; 350 | end 351 | 352 | ST_REQ_VENDOR: begin 353 | // VENDOR REQUEST 354 | vend_req_request <= packet_setup_req; 355 | vend_req_val <= packet_setup_wval; 356 | //vend_req_index <= packet_setup_widx; 357 | // optional data stage for bidir control transfers 358 | // would require additional unsupported code in this endpoint 359 | //vend_req_len <= packet_setup_wlen; 360 | // signal to external interface there was a vend_req 361 | vend_req_act <= 1'b1; 362 | dc <= 0; 363 | // send 0byte response (DATA1) 364 | len_out <= 0; 365 | ready_in <= 1; 366 | hasdata_out <= 1; 367 | state_in <= ST_IDLE; 368 | end 369 | default: state_in <= ST_RST_0; 370 | endcase 371 | 372 | 373 | 374 | // output FSM 375 | // 376 | case(state_out) 377 | ST_RST_0: begin 378 | hasdata_out <= 0; 379 | 380 | // configure default state 381 | state_out <= ST_RST_1; 382 | end 383 | ST_RST_1: begin 384 | state_out <= ST_IDLE; 385 | end 386 | ST_IDLE: begin 387 | // idle state 388 | if(buf_out_arm_1 & ~buf_out_arm_2) begin 389 | // free up this endpoint 390 | dc <= 0; 391 | state_out <= ST_OUT_ARM; 392 | end 393 | end 394 | ST_OUT_ARM: begin 395 | // generate ARM_ACK pulse, several cycles for compat with slower FSMs 396 | if(dc == 3) begin 397 | state_out <= ST_OUT_SWAP; 398 | end 399 | end 400 | ST_OUT_SWAP: begin 401 | // this endpoint is not double buffered! 402 | // current buffer is now ready for data 403 | ready_in <= 1; 404 | // update hasdata status 405 | hasdata_out <= 0; 406 | 407 | state_out <= ST_IDLE; 408 | end 409 | default: state_out <= ST_RST_0; 410 | endcase 411 | 412 | if(~reset_2) begin 413 | // reset 414 | state_in <= ST_RST_0; 415 | state_out <= ST_RST_0; 416 | end 417 | 418 | end 419 | 420 | 421 | // endpoint OUT buffer 422 | // 64 bytes 423 | // terminology here: USB specs defines IN as device reads going into the PC, 424 | // and OUT transfers as device writes from the PC. from a device standpoint 425 | // this may seem backwards but it's just for consistency, which is not entirely 426 | // reflected in these conventions locally 427 | 428 | reg [5:0] buf_in_rdaddr; 429 | wire [7:0] buf_in_q; 430 | 431 | usb2_ep0in_ram iu2ep0i ( 432 | .clk ( phy_clk ), 433 | .wr_dat_w ( buf_in_data ), 434 | .rd_adr ( buf_in_rdaddr ), 435 | .wr_adr ( buf_in_addr ), 436 | .wr_we ( buf_in_wren ), 437 | .rd_dat_r ( buf_in_q ) 438 | ); 439 | 440 | 441 | // endpoint IN buffer 442 | // segmented 443 | // relevant descriptors (device, interface, endpoint etc) 444 | 445 | reg [7:0] descrip_addr_offset; 446 | 447 | usb2_descrip_rom iu2d ( 448 | .clk ( phy_clk ), 449 | .adr ( buf_out_addr + descrip_addr_offset), 450 | .dat_r ( buf_out_q ) 451 | ); 452 | 453 | 454 | endmodule 455 | -------------------------------------------------------------------------------- /core/usb2/usb2_ulpi.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 2.0 ulpi 4 | // 5 | // Copyright (c) 2012-2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb2_ulpi ( 12 | 13 | // top-level interface 14 | input wire reset_n, 15 | output wire reset_local, 16 | input wire opt_disable_all, 17 | input wire opt_enable_hs, 18 | input wire opt_ignore_vbus, 19 | output wire stat_connected, 20 | output reg stat_fs, 21 | output reg stat_hs, 22 | 23 | // ulpi usb phy connection 24 | input wire phy_clk, 25 | input wire [7:0] phy_d_in, 26 | output wire [7:0] phy_d_out_mux, 27 | output wire phy_d_oe, 28 | input wire phy_dir, 29 | output wire phy_stp, 30 | input wire phy_nxt, 31 | 32 | // connection to packet layer 33 | output wire pkt_out_act, 34 | output wire [7:0] pkt_out_byte, 35 | output wire pkt_out_latch, 36 | 37 | output wire pkt_in_cts, 38 | output wire pkt_in_nxt, 39 | input wire [7:0] pkt_in_byte, 40 | input wire pkt_in_latch, 41 | input wire pkt_in_stp, 42 | 43 | output wire se0_reset, 44 | 45 | // debug signals 46 | output wire [1:0] dbg_linestate 47 | 48 | ); 49 | 50 | 51 | //////////////////////////////////////////////////////////////////// 52 | // 53 | // 60mhz ulpi clock domain 54 | // 55 | //////////////////////////////////////////////////////////////////// 56 | 57 | reg reset_1, reset_2; 58 | reg reset_ulpi; 59 | assign reset_local = reset_n & reset_ulpi; 60 | reg opt_enable_hs_1, opt_enable_hs_2; 61 | reg opt_ignore_vbus_1, opt_ignore_vbus_2; 62 | reg phy_dir_1; 63 | reg [7:0] phy_d_out; 64 | reg [7:0] phy_d_next; 65 | reg phy_d_sel; 66 | assign phy_d_out_mux = phy_d_sel ? pkt_in_byte : phy_d_out; 67 | assign phy_d_oe = !phy_dir_1; 68 | reg phy_stp_out; 69 | assign phy_stp = phy_stp_out ^ pkt_in_stp; 70 | reg [7:0] in_rx_cmd; 71 | reg know_recv_packet; // phy will drive NXT and DIR high 72 | // simultaneously to signify a receive 73 | // packet as opposed to normal RX_CMD 74 | // in any case the RX_CMD will reflect this 75 | // just a bit later anyway 76 | reg [1:0] last_line_state; 77 | wire [1:0] line_state = in_rx_cmd[1:0]; 78 | wire [1:0] vbus_state = in_rx_cmd[3:2]; 79 | wire [1:0] rx_event = in_rx_cmd[5:4]; 80 | //wire id_gnd = in_rx_cmd[6]; 81 | //wire alt_int = in_rx_cmd[7]; 82 | 83 | //wire sess_end = (vbus_state == 2'b00); 84 | //wire sess_valid = (vbus_state == 2'b10); 85 | wire vbus_valid = (vbus_state == 2'b11); 86 | reg vbus_valid_1; 87 | assign stat_connected = vbus_valid; // in HS mode explicit bit-stuff error will 88 | // also signal EOP but this is Good Enough(tm) 89 | wire rx_active = (rx_event[0]); 90 | //wire rx_error = (rx_event == 2'b11); 91 | //wire host_discon = (rx_event == 2'b10); // only valid in host mode 92 | 93 | reg [2:0] tx_cmd_code; // ULPI TX_CMD code with extra bit 94 | reg [7:0] tx_reg_addr; // register address (6 and 8bit) 95 | reg [7:0] tx_reg_data_rd; // data read 96 | reg [7:0] tx_reg_data_wr; // data to write 97 | reg [3:0] tx_pid; // packet ID for sending data 98 | parameter [2:0] TX_CMD_XMIT_NOPID = 3'b001, // two LSB are ULPI cmdcode 99 | TX_CMD_XMIT_PID = 3'b101, 100 | TX_CMD_REGWR_IMM = 3'b010, 101 | TX_CMD_REGWR_EXT = 3'b110, 102 | TX_CMD_REGRD_IMM = 3'b011, 103 | TX_CMD_REGRD_EXT = 3'b111; 104 | 105 | // mux local ULPI control with packet layer 106 | assign pkt_out_latch = pkt_out_act & phy_dir & phy_nxt; 107 | assign pkt_out_byte = pkt_out_latch ? phy_d_in : 8'h0; 108 | assign pkt_out_act = (rx_active | know_recv_packet) & phy_dir; 109 | 110 | assign pkt_in_cts = ~phy_dir & can_send; 111 | assign pkt_in_nxt = phy_nxt && (state == ST_PKT_1 || state == ST_PKT_2); 112 | 113 | reg pkt_in_latch_defer; 114 | 115 | reg can_send; 116 | reg [3:0] can_send_delay; 117 | 118 | reg [6:0] state; 119 | reg [6:0] state_next; 120 | parameter [6:0] ST_RST_0 = 7'd0, 121 | ST_RST_1 = 7'd1, 122 | ST_RST_2 = 7'd2, 123 | ST_RST_3 = 7'd3, 124 | ST_RST_4 = 7'd4, 125 | ST_IDLE = 7'd10, 126 | ST_RX_0 = 7'd20, 127 | ST_TXCMD_0 = 7'd30, 128 | ST_TXCMD_1 = 7'd31, 129 | ST_TXCMD_2 = 7'd32, 130 | ST_TXCMD_3 = 7'd33, 131 | ST_PKT_0 = 7'd40, 132 | ST_PKT_1 = 7'd41, 133 | ST_PKT_2 = 7'd42, 134 | ST_CHIRP_0 = 7'd50, 135 | ST_CHIRP_1 = 7'd51, 136 | ST_CHIRP_2 = 7'd52, 137 | ST_CHIRP_3 = 7'd53, 138 | ST_CHIRP_4 = 7'd54, 139 | ST_CHIRP_5 = 7'd55; 140 | 141 | reg [7:0] dc; 142 | reg [11:0] dc_wrap; 143 | 144 | // about 3ms from start of SE0 145 | wire se0_bus_reset = (dc_wrap == 710); 146 | assign se0_reset = se0_bus_reset; 147 | 148 | assign dbg_linestate = line_state; 149 | 150 | always @(posedge phy_clk) begin 151 | 152 | // edge detection / synchronize 153 | {reset_2, reset_1} <= {reset_1, reset_n}; 154 | {opt_enable_hs_2, opt_enable_hs_1} <= {opt_enable_hs_1, opt_enable_hs}; 155 | {opt_ignore_vbus_2, opt_ignore_vbus_1} <= {opt_ignore_vbus_1, opt_ignore_vbus}; 156 | 157 | vbus_valid_1 <= vbus_valid; 158 | phy_dir_1 <= phy_dir; 159 | 160 | dc <= dc + 1'b1; 161 | 162 | // clear to send (for packet layer) generation 163 | if(can_send) begin 164 | if(can_send_delay < stat_hs ? 4'hF : 4'h0) 165 | can_send_delay <= can_send_delay + 1'b1; 166 | end else begin 167 | can_send_delay <= 0; 168 | end 169 | 170 | // default state 171 | phy_stp_out <= 1'b0; 172 | // account for the turnaround cycle delay 173 | phy_d_out <= phy_d_next; 174 | // catch latches while receiving 175 | if(pkt_in_latch) pkt_in_latch_defer <= 1; 176 | 177 | // main fsm 178 | // 179 | case(state) 180 | ST_RST_0: begin 181 | // reset state 182 | phy_d_out <= 8'h0; 183 | phy_d_next <= 8'h0; 184 | phy_stp_out <= 1'b0; 185 | phy_dir_1 <= 1'b1; 186 | stat_fs <= 1'b0; 187 | stat_hs <= 1'b0; 188 | can_send <= 1'b0; 189 | vbus_valid_1 <= 1'b0; 190 | dc <= 0; 191 | dc_wrap <= 0; 192 | pkt_in_latch_defer <= 0; 193 | 194 | // stay stuck in reset, if disable is specified 195 | if(opt_disable_all) 196 | state <= ST_RST_0; 197 | else 198 | state <= ST_RST_1; 199 | end 200 | ST_RST_1: begin 201 | // take other modules out of reset, whether initial or caused by 202 | // usb cable disconnect 203 | reset_ulpi <= 1; 204 | // reset phy and set mode 205 | tx_cmd_code <= TX_CMD_REGWR_IMM; 206 | tx_reg_addr <= 6'h4; 207 | tx_reg_data_wr <= { 2'b01, // Resvd, SuspendM [disabled] 208 | 1'b1, // Reset (auto-cleared by PHY) 209 | 2'b00, // OpMode [normal] 210 | 1'b1, // TermSelect [enable] 211 | 2'b01 // XcvrSel [full speed] 212 | }; 213 | // wait 10ms for debounce on prior disconnect 214 | if(dc == 255) dc_wrap <= dc_wrap + 1'b1; 215 | if(~phy_dir & dc_wrap == 2000) begin 216 | state <= ST_TXCMD_0; 217 | state_next <= ST_RST_2; 218 | end 219 | end 220 | ST_RST_2: begin 221 | // wait for phy to begin reset 222 | // if times out, try again 223 | if(dc == 255) state <= ST_RST_0; 224 | if(phy_dir) state <= ST_RST_3; 225 | end 226 | ST_RST_3: begin 227 | // wait for next rising edge 228 | // then receive initial RX_CMD 229 | if(phy_dir) state <= ST_RX_0; 230 | state_next <= ST_RST_4; 231 | end 232 | ST_RST_4: begin 233 | // turn off OTG pulldowns and disable pullup 234 | // on ID pin (OTG would drive low if connected) 235 | tx_cmd_code <= TX_CMD_REGWR_IMM; 236 | tx_reg_addr <= 6'hA; 237 | tx_reg_data_wr <= 8'h0; 238 | 239 | state <= ST_TXCMD_0; 240 | state_next <= ST_IDLE; 241 | end 242 | 243 | 244 | // idle dispatch 245 | // 246 | ST_IDLE: begin 247 | // increment SE0 detection counter 248 | if(line_state == 2'b00) begin 249 | if(dc == 255) dc_wrap <= dc_wrap + 1'b1; 250 | end else begin 251 | dc_wrap <= 0; 252 | end 253 | 254 | know_recv_packet <= 0; 255 | 256 | // see if PHY has stuff for us 257 | if(phy_dir & ~phy_dir_1) begin 258 | // rising edge of dir 259 | 260 | // make sure we're not clobbering a request from the packet layer 261 | can_send <= 0; 262 | know_recv_packet <= phy_nxt; 263 | dc <= 0; 264 | state <= ST_RX_0; 265 | state_next <= ST_IDLE; 266 | end else begin 267 | // do other stuff 268 | can_send <= 1; 269 | 270 | // accept packet data 271 | if(pkt_in_latch | pkt_in_latch_defer) begin 272 | state <= ST_PKT_0; 273 | end else 274 | if(se0_bus_reset & opt_enable_hs_2) begin 275 | // currently full speed, want to enumerate as high speed 276 | state <= ST_CHIRP_0; 277 | end 278 | end 279 | end 280 | 281 | // process RX CMD or start packet 282 | // 283 | ST_RX_0: begin 284 | // data is passed up to the packet layer 285 | // see combinational logic near the top 286 | if(~phy_nxt) in_rx_cmd <= phy_d_in; 287 | // wait for end of transmission 288 | if(~phy_dir) begin 289 | state <= state_next; 290 | end 291 | end 292 | 293 | // transmit command TXCMD 294 | // 295 | ST_TXCMD_0: begin 296 | 297 | // drive command onto bus 298 | if(~tx_cmd_code[2]) begin 299 | if(~tx_cmd_code[1]) 300 | phy_d_next <= {tx_cmd_code[1:0], 6'b0}; // transmit no PID 301 | else 302 | phy_d_next <= {tx_cmd_code[1:0], tx_reg_addr[5:0]}; // immediate reg r/w 303 | end else begin 304 | if(~tx_cmd_code[1]) 305 | phy_d_next <= {tx_cmd_code[1:0], 2'b0, tx_pid[3:0]}; // transmit with PID 306 | else 307 | phy_d_next <= {tx_cmd_code[1:0], 6'b101111}; // extended reg r/w 308 | end 309 | 310 | if(phy_nxt) begin 311 | // phy has acknowledged the command 312 | 313 | if(tx_cmd_code[0]) begin 314 | // read reg 315 | // immediate only for now 316 | // need to insert additional branches for extended addr 317 | phy_d_out <= 0; 318 | state <= ST_TXCMD_2; 319 | end else begin 320 | // write reg 321 | // immediate only for now 322 | phy_d_out <= tx_reg_data_wr; 323 | phy_d_next <= 0; 324 | state <= ST_TXCMD_1; // assert STP 325 | end 326 | end 327 | 328 | if(~tx_cmd_code[1]) begin 329 | // transmit packet 330 | // can't afford to dally around 331 | state <= state_next; 332 | end 333 | end 334 | ST_TXCMD_1: begin 335 | // assert STP on reg write 336 | phy_stp_out <= 1'b1; 337 | state <= state_next; 338 | end 339 | ST_TXCMD_2: begin 340 | // latch reg read 341 | if(phy_dir) state <= ST_TXCMD_3; 342 | end 343 | ST_TXCMD_3: begin 344 | // read value from PHY 345 | tx_reg_data_rd <= phy_d_in; 346 | state <= state_next; 347 | end 348 | 349 | // data packet send 350 | // 351 | ST_PKT_0: begin 352 | // accept packet data 353 | // implied that first byte is PID 354 | tx_cmd_code <= TX_CMD_XMIT_PID; 355 | tx_pid <= pkt_in_byte[3:0]; 356 | can_send <= 0; 357 | // call TXCMD 358 | state <= ST_TXCMD_0; 359 | state_next <= ST_PKT_1; 360 | end 361 | ST_PKT_1: begin 362 | // packet layer now has control 363 | // and is handling lines 364 | if(phy_nxt) begin 365 | state <= ST_PKT_2; 366 | phy_d_sel <= 1; 367 | end 368 | end 369 | ST_PKT_2: begin 370 | if(pkt_in_stp) begin 371 | phy_d_sel <= 0; 372 | phy_d_out <= 0; 373 | phy_d_next <= 0; 374 | pkt_in_latch_defer <= 0; 375 | state <= ST_IDLE; 376 | end 377 | end 378 | 379 | // high-speed handshake chirp 380 | // 381 | ST_CHIRP_0: begin 382 | tx_cmd_code <= TX_CMD_REGWR_IMM; 383 | tx_reg_addr <= 6'h4; 384 | tx_reg_data_wr <= { 2'b01, // Resvd, SuspendM [disabled] 385 | 1'b0, // Reset (auto-cleared by PHY) 386 | 2'b10, // OpMode [chirp] 387 | 1'b0, // TermSelect [enable] 388 | 2'b00 // XcvrSel [high speed] 389 | }; 390 | state <= ST_TXCMD_0; 391 | state_next <= ST_CHIRP_1; 392 | end 393 | ST_CHIRP_1: begin 394 | // transmit chirp K for >1ms (2ms) 395 | tx_cmd_code <= TX_CMD_XMIT_NOPID; 396 | tx_reg_addr <= 6'h4; 397 | dc_wrap <= 0; 398 | state <= ST_TXCMD_0; 399 | state_next <= ST_CHIRP_2; 400 | end 401 | ST_CHIRP_2: begin 402 | if(phy_nxt) begin 403 | phy_d_out <= 8'h0; 404 | phy_d_next <= 8'h0; 405 | if(dc == 255) dc_wrap <= dc_wrap + 1'b1; 406 | if(dc_wrap == 600) begin 407 | // a bit over 2ms has passed 408 | phy_stp_out <= 1'b1; 409 | state <= ST_CHIRP_3; 410 | end 411 | end 412 | end 413 | ST_CHIRP_3: begin 414 | if(phy_dir & ~phy_dir_1) begin 415 | // rising edge of dir 416 | state <= ST_RX_0; 417 | state_next <= ST_CHIRP_4; 418 | end 419 | end 420 | ST_CHIRP_4: begin 421 | tx_cmd_code <= TX_CMD_REGWR_IMM; 422 | tx_reg_addr <= 6'h4; 423 | tx_reg_data_wr <= { 2'b01, // Resvd, SuspendM [disabled] 424 | 1'b0, // Reset (auto-cleared by PHY) 425 | 2'b00, // OpMode [normal] 426 | 1'b0, // TermSelect [enable] 427 | 2'b00 // XcvrSel [high speed] 428 | }; 429 | if(~phy_dir && phy_d_in == 8'h0) state <= ST_TXCMD_0; 430 | state_next <= ST_CHIRP_5; 431 | end 432 | ST_CHIRP_5: begin 433 | stat_hs <= 1'b1; 434 | state <= ST_IDLE; 435 | end 436 | default: state <= ST_RST_0; 437 | endcase 438 | 439 | if(~reset_2) state <= ST_RST_0; 440 | 441 | // detect a change in Vbus 442 | // 443 | // this works fine with regular USB 2.0 PHYs, however 444 | // the TUSB1310A has a silicon bug where the ULPI Vbus 445 | // status is incorrectly reported, causing erratic 446 | // disconnects. 447 | // 448 | if(~opt_ignore_vbus_2) begin 449 | if(~vbus_valid & vbus_valid_1) begin 450 | reset_ulpi <= 0; 451 | state <= ST_RST_0; 452 | end 453 | end 454 | end 455 | 456 | endmodule 457 | -------------------------------------------------------------------------------- /core/usb_descrip_gen.c: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // USB 3.0/2.0 IP core descriptor generator 4 | // 5 | // Copyright (c) 2013 Marshall H. 6 | // Copyright (c) 2017 Florent Kermarrec 7 | // All rights reserved. 8 | // This code is released under the terms of the simplified BSD license. 9 | // See LICENSE.TXT for details. 10 | // 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #define WIN32_LEAN_AND_MEAN 17 | #include // just to ruffle jared's feathers 18 | 19 | #define u8 unsigned char 20 | #define u16 unsigned short 21 | #define u32 unsigned int 22 | 23 | // to add endpoints, change strings etc, just skip to main() at bottom 24 | // 25 | // warning: objectionable C code ahead 26 | // proceed with extreme prejudice 27 | 28 | char filename_usb2_init[] = "./usb2/usb2_descrip_rom.init"; 29 | char filename_usb3_init[] = "./usb3/usb3_descrip_rom.init"; 30 | char filename_usb2_bin[] = "./usb2/usb2_descrip.bin"; 31 | char filename_usb3_bin[] = "./usb3/usb3_descrip.bin"; 32 | char filename_descrip_vh[] = "usb_descrip.vh"; 33 | 34 | 35 | FILE *bin_2, *bin_3, *init_2, *init_3, *descrip_vh; 36 | u32 i_2, i_3; 37 | u32 c_2, c_3; 38 | 39 | u8 *a; 40 | u8 *z; 41 | u8 buf_2[1024] = {0, }; 42 | u8 buf_3[1024] = {0, }; 43 | u32 bytes_pending_2; 44 | u32 bytes_pending_3; 45 | u8 bitwidth_2; 46 | u8 bitwidth_3; 47 | u32 bytes_written_2 = 0; 48 | u32 bytes_written_3 = 0; 49 | 50 | void fail(void *ret, char *str) 51 | { 52 | if(ret == NULL){ 53 | printf("\n* FAIL: %s\n", str); 54 | exit(-1); 55 | } 56 | } 57 | 58 | void write_buf8(u8 *buf, u32 size) 59 | { 60 | u32 i; 61 | for(i = 0; i < size; i++){ 62 | fprintf(init_2, "%02X\n", *buf++); 63 | fwrite(buf-1, 1, 1, bin_2); 64 | bytes_written_2 ++; 65 | } 66 | } 67 | 68 | void write_buf32(u32 *buf, u32 size) 69 | { 70 | u32 i, w; 71 | for(i = 0; i < size; i+=4){ 72 | w = *buf; 73 | w = (w & 0xff) << 24 | (w & 0xff00) << 8 | (w & 0xff0000) >> 8 | (w & 0xff000000) >> 24 ; 74 | fprintf(init_3, "%08X\n", w); 75 | fwrite(buf, 4, 1, bin_3); 76 | *buf++; 77 | bytes_written_3 += 4; 78 | } 79 | } 80 | 81 | void write_buf(void *buf, u32 size) 82 | { 83 | write_buf8(buf, size); 84 | write_buf32(buf, size); 85 | } 86 | 87 | void print_offsets(char *name, u8 for_usb2, u8 for_usb3) 88 | { 89 | if(for_usb2) fprintf(descrip_vh, "parameter\t[%d:0]\tDESCR_USB2_%s = 'd%d;\n", bitwidth_2-1, name, i_2); 90 | if(for_usb3) fprintf(descrip_vh, "parameter\t[%d:0]\tDESCR_USB3_%s = 'd%d;\n", bitwidth_3-1, name, i_3); 91 | } 92 | 93 | void add_device_qual(u16 usb_spec, u8 class_code, u8 subclass, u8 protocol_code, u8 max_size_ep0, 94 | u8 num_possible_config) 95 | { 96 | a = buf_2; 97 | print_offsets("DEVICE_QUAL", 1, 0); 98 | 99 | // usb spec 2.10 100 | // this is not included in USB3 descriptors 101 | *a++ = 0x0A; 102 | *a++ = 0x06; 103 | *a++ = (usb_spec == 0x300) ? (0x210&0xff) : (0x200&0xff); 104 | *a++ = (usb_spec == 0x300) ? (0x210>>8) : (0x200>>8); 105 | *a++ = class_code; 106 | *a++ = subclass; 107 | *a++ = protocol_code; 108 | *a++ = max_size_ep0; 109 | *a++ = num_possible_config; 110 | *a++ = 0; 111 | write_buf8(buf_2, 0xA); 112 | } 113 | 114 | void add_device_descr(u16 usb_spec, u8 class_code, u8 subclass, u8 protocol_code, u8 max_size_ep0, 115 | u16 vid, u16 pid, u16 dev_num, 116 | u8 idx_mfg, u8 idx_prod, u8 idx_serial, u8 num_possible_config) 117 | { 118 | a = buf_2; 119 | print_offsets("DEVICE", 1, 1); 120 | 121 | // usb spec 2.10 122 | *a++ = 0x12; // length 123 | *a++ = 0x01; // descriptor ID 124 | *a++ = (usb_spec == 0x300) ? (0x210&0xff) : (0x200&0xff); // bcdUSB 125 | *a++ = (usb_spec == 0x300) ? (0x210>>8) : (0x200>>8); // bcdUSB 126 | write_buf8(buf_2, 4); a = buf_2+2; 127 | // usb spec 3.00 128 | *a++ = (0x300&0xff); // bcdUSB 129 | *a++ = (0x300>>8); // bcdUSB 130 | write_buf32((u32 *)buf_2, 4); a = buf_2; 131 | 132 | *a++ = class_code; // bDeviceClass 133 | *a++ = subclass; // bDeviceSubClass 134 | *a++ = protocol_code; // bDeviceProtocol 135 | *a++ = max_size_ep0; // bMaxPacketSize0 136 | write_buf8(buf_2, 4); a--; 137 | *a++ = 0x09; // USB3: 512 bytes fixed EP0 138 | write_buf32((u32 *)buf_2, 4); a = buf_2; 139 | 140 | *a++ = (vid&0xff); 141 | *a++ = (vid>>8); 142 | *a++ = (pid&0xff); 143 | *a++ = (pid>>8); 144 | *a++ = (dev_num&0xff); 145 | *a++ = (dev_num>>8); 146 | *a++ = idx_mfg; 147 | *a++ = idx_prod; 148 | *a++ = idx_serial; 149 | *a++ = num_possible_config; // bNumConfigurations 150 | write_buf(buf_2, 10); 151 | 152 | add_device_qual( usb_spec, // USB spec number (2.xx only) 153 | class_code, // Device Class 154 | subclass, // Device subclass 155 | protocol_code, // Device protocol code 156 | max_size_ep0, // Endpoint0 Max packet 157 | num_possible_config 158 | ); 159 | } 160 | 161 | void add_config_start(u16 usb_spec, u8 attrib, u32 power_ma, u8 num_endpoints) 162 | { 163 | a = buf_2; 164 | z = buf_3; 165 | c_2 = i_2; 166 | c_3 = i_3; 167 | print_offsets("CONFIG", 1, 1); 168 | bytes_pending_2 = 0; 169 | bytes_pending_3 = 0; 170 | 171 | // write Config descriptor 172 | *a++ = 0x09; // length 173 | *a++ = 0x02; // descriptor ID 174 | *a++ = (0xffff&0xff); // total length, must be overwritten later 175 | *a++ = (0xffff>>8); // total length, must be overwritten later 176 | *a++ = 0x01; // bNumInterfaces 177 | *a++ = 0x01; // bConfigurationValue 178 | *a++ = 0x00; // iConfiguration 179 | *a++ = attrib; // bmAttributes 180 | *a++ = (usb_spec == 0x300) ? power_ma / 8 : power_ma / 2; 181 | bytes_pending_2 += 0x9; 182 | bytes_pending_3 += 0x9; 183 | 184 | // write Interface descriptor 185 | *a++ = 0x09; // length 186 | *a++ = 0x04; // descriptor ID 187 | *a++ = 0x00; // bInterfaceNumber 188 | *a++ = 0x00; // bAlternateSetting 189 | *a++ = num_endpoints; // bNumEndpoints 190 | *a++ = 0xFF; // bInterfaceClass 191 | *a++ = 0xFF; // bInterfaceSubClass 192 | *a++ = 0xFF; // bInterfaceProtocol 193 | *a++ = 0x02; // iInterface 194 | bytes_pending_2 += 0x9; 195 | bytes_pending_3 += 0x9; 196 | 197 | // now here's the annoying part... 198 | // create a second buffer just for usb3 199 | // since it has companion descriptors 200 | memcpy(buf_3, buf_2, bytes_pending_2); 201 | z += bytes_pending_3; 202 | } 203 | 204 | void add_endpoint(u8 idx, u8 dir, u8 attrib, u16 max_pkt, u8 interval, u8 max_burst, 205 | u8 attrib_3, u16 bytes_per_interval ) 206 | { 207 | u8 *c = a; 208 | 209 | // write Endpoint descriptor 210 | *a++ = 0x07; // length 211 | *a++ = 0x05; // descriptor ID 212 | *a++ = idx | (dir ? 0x80 : 0x0); 213 | *a++ = attrib; // bmAttributes 214 | *a++ = (max_pkt&0xff); // max packet size 215 | *a++ = (max_pkt>>8); // max packet size 216 | *a++ = interval; // bInterval 217 | bytes_pending_2 += 0x7; 218 | bytes_pending_3 += 0x7; 219 | 220 | // copy this endpoint over to USB3 221 | memcpy(z, c, 0x7); 222 | z += 0x7; 223 | // patch max packet size to 1024 224 | *(z-2) = 0x04; 225 | *(z-3) = 0x00; 226 | 227 | // add companion descriptor only to USB3 buffer 228 | *z++ = 0x06; // length 229 | *z++ = 0x30; // descriptor ID 230 | *z++ = max_burst-1; 231 | *z++ = attrib_3; // bmAttributes 232 | *z++ = (bytes_per_interval&0xff); // wBytesPerInterval 233 | *z++ = (bytes_per_interval>>8); // wBytesPerInterval 234 | bytes_pending_3 += 0x6; 235 | 236 | } 237 | 238 | 239 | void add_config_end() 240 | { 241 | u8 *c = a; 242 | // add alternate interface 243 | // this is needed so that windows can select it if isoch. bandwidth 244 | // is not able to be reserved 245 | *a++ = 0x09; // length 246 | *a++ = 0x04; // descriptor ID 247 | *a++ = 0x00; // bInterfaceNumber 248 | *a++ = 0x01; // bAlternateSetting 249 | *a++ = 0x0; // bNumEndpoints 250 | *a++ = 0xFF; // bInterfaceClass 251 | *a++ = 0xFF; // bInterfaceSubClass 252 | *a++ = 0xFF; // bInterfaceProtocol 253 | *a++ = 0x02; // iInterface 254 | bytes_pending_2 += 0x9; 255 | bytes_pending_3 += 0x9; 256 | 257 | // copy this interface over to USB3 258 | memcpy(z, c, 0x9); 259 | z += 0x9; 260 | 261 | // patch total descriptor lengths 262 | memcpy(&buf_2[2], &bytes_pending_2, 2); 263 | memcpy(&buf_3[2], &bytes_pending_3, 2); 264 | 265 | write_buf8(buf_2, bytes_pending_2); 266 | write_buf32((u32 *)buf_3, bytes_pending_3); 267 | } 268 | 269 | void add_bos() 270 | { 271 | z = buf_3; 272 | print_offsets("BOS ", 0, 1); 273 | 274 | *z++ = 0x05; // bLength 275 | *z++ = 0x0F; // bDescriptorType 276 | *z++ = 0x16; // wTotalLength 277 | *z++ = 0x00; // 278 | 279 | *z++ = 0x02; // bNumDeviceCaps 280 | 281 | *z++ = 0x07; // bLength 282 | *z++ = 0x10; // bDescriptorType 283 | *z++ = 0x02; // bDevCapabilityType (USB 2.0 EXTENSION) 284 | 285 | *z++ = 0x02; // 32bit field: LPM Supported (SS Required) 286 | *z++ = 0x00; // 32bit field: LPM Supported (SS Required) 287 | *z++ = 0x00; // 32bit field: LPM Supported (SS Required) 288 | *z++ = 0x00; // 32bit field: LPM Supported (SS Required) 289 | 290 | *z++ = 0x0A; // bLength 291 | *z++ = 0x10; // bDescriptorType 292 | *z++ = 0x03; // bDevCapabilityType (SUPERSPEED_USB) 293 | *z++ = 0x00; // bmAttributes (8bit) (LTM Generation Incapable) 294 | *z++ = 0x0E; // wSpeedsSupported (Operation supported FS, HS, SS) 295 | *z++ = 0x00; // wSpeedsSupported (Operation supported FS, HS, SS) 296 | *z++ = 0x02; // bFunctionalitySupported (Valid operation starts with HS) 297 | *z++ = 0x08; // bU1DevExitLat (Less than 8uS) 298 | *z++ = 0x64; // wU2DevExitLat (Less than 100uS) 299 | *z++ = 0x00; // wU2DevExitLat (Less than 100uS) 300 | 301 | 302 | write_buf32((u32 *)buf_3, z - buf_3); 303 | } 304 | 305 | void add_string(u8 idx, char* str) 306 | { 307 | char temp[32]; 308 | wchar_t w_str[128]; 309 | u32 len; 310 | if(idx == 0) 311 | len = 4; // string0 is fixed at 4 bytes for language code 312 | else 313 | len = strlen(str)*2+2; 314 | 315 | memset(buf_2, 0, sizeof(buf_2)); 316 | a = buf_2; 317 | 318 | sprintf(temp, "STRING%d", idx); 319 | print_offsets(temp, 1, 1); 320 | 321 | if(idx > 0) 322 | mbstowcs(w_str, str, 128); 323 | else 324 | memcpy(&w_str[0], str, 2); 325 | 326 | *a++ = len; 327 | *a++ = 0x03; 328 | memcpy(a, w_str, len-2); 329 | write_buf(buf_2, len); 330 | } 331 | 332 | void add_set() 333 | { 334 | print_offsets("CONFUNSET", 1, 1); 335 | write_buf("\x00", 1); 336 | print_offsets("CONFSET", 1, 1); 337 | write_buf("\x01", 1); 338 | } 339 | 340 | int main(int argc, char *argv[]) 341 | { 342 | u32 temp1, temp2; 343 | i_2 = 0; 344 | i_3 = 0; 345 | 346 | printf("\n* Daisho USB 3.0 / USB 2.0 descriptor export tool\n by marshallh, 2013\n"); 347 | 348 | fail(init_2 = fopen(filename_usb2_init, "w"), "Failed opening USB2.0 INIT"); 349 | fail(init_3 = fopen(filename_usb3_init, "w"), "Failed opening USB3.0 INIT"); 350 | fail(bin_2 = fopen(filename_usb2_bin, "wb"), "Failed opening USB2.0 BIN"); 351 | fail(bin_3 = fopen(filename_usb3_bin, "wb"), "Failed opening USB3.0 BIN"); 352 | fail(descrip_vh = fopen(filename_descrip_vh, "w"), "Failed opening descriptor include"); 353 | 354 | // set your BRAM address bit widths 355 | bitwidth_2 = 8; // [7:0] 356 | bitwidth_3 = 7; // [6:0] 357 | 358 | printf ("* Generating...\n"); 359 | 360 | add_device_descr( 0x300, // USB spec number (auto fixed 2.10 for 2.0) 361 | // put 0x200 if you only use USB 2.0 core 362 | 0xFF, // Class Code 363 | 0xFF, // Subclass 364 | 0xFF, // Protocol Code 365 | 64, // Endpoint0 Max packet (ignored for 3.0) 366 | 0x1D50, // Vendor ID 367 | 0x605A, // Product ID 368 | 0x1, // Device release number 369 | 1, // Index of Manufacturer Str Descriptor 370 | 2, // Index of Product Str Descriptor 371 | 3, // Index of Serial Number Str Descriptor 372 | 1 // Number of Possible Configs 373 | ); 374 | 375 | add_config_start( 0x300, // USB spec number (auto fixed 2.10 for 2.0), 376 | 0x80, // TODO attributes (self powered) 377 | 500, // Power draw in mA 378 | 2 // Number of endpoints 379 | ); 380 | 381 | add_endpoint( 1, // EP1 382 | 1, // IN 383 | 2, // BULK 384 | 512, // Max packet size (autofixed to 1024 for USB3) 385 | 0x1, // Interval for isoch. endpoints 386 | 16, // Max burst packets for usb 3.0 387 | 0x00, // No stream support 388 | 0 // 0bytes per interval (BULK) 389 | ); 390 | 391 | add_endpoint( 2, // EP2 392 | 0, // OUT 393 | 2, // BULK 394 | 512, // Max packet size (autofixed to 1024 for USB3) 395 | 0x1, // Interval for isoch. endpoints 396 | 16, // Max burst packets for usb 3.0 397 | 0x00, // No stream support 398 | 0 // 0bytes per interval (BULK) 399 | ); 400 | 401 | add_config_end(); 402 | 403 | // hack to print out CONFIG length 404 | temp1 = i_2; 405 | temp2 = i_3; 406 | i_2 = bytes_pending_2; 407 | i_3 = bytes_pending_3; 408 | print_offsets("CONFIG_LEN", 1, 1); 409 | i_2 = temp1; 410 | i_3 = temp2; 411 | 412 | add_bos(); 413 | 414 | // hack to print out BOS length 415 | temp2 = i_3; 416 | i_3 = z - buf_3; 417 | print_offsets("BOS_LEN", 0, 1); 418 | i_3 = temp2; 419 | 420 | add_string(0, "\x09\x04\0"); 421 | add_string(1, "Great Scott Gadgets"); 422 | add_string(2, "Daisho USB test"); 423 | add_string(3, "DAISHOUSB000"); 424 | 425 | add_set(); 426 | 427 | print_offsets("EOF ", 1, 1); 428 | 429 | // pad out files to their max address space 430 | while(bytes_written_2 < pow(2, bitwidth_2)) write_buf8("\0", 1); 431 | while(bytes_written_3 < pow(2, bitwidth_3)*4) write_buf32((u32 *)"\0\0\0\0", 1); 432 | 433 | printf("* Finished\n"); 434 | fclose(bin_2); 435 | fclose(bin_3); 436 | fclose(init_2); 437 | fclose(init_3); 438 | fclose(descrip_vh); 439 | return 0; 440 | } 441 | 442 | 443 | -------------------------------------------------------------------------------- /core/usb2/usb2_packet.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 2.0 packet handler 4 | // 5 | // Copyright (c) 2012-2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb2_packet ( 12 | 13 | // top-level interface 14 | input wire phy_clk, 15 | input wire reset_n, 16 | 17 | // ULPI 18 | input wire in_act, 19 | input wire [7:0] in_byte, 20 | input wire in_latch, 21 | input wire out_cts, 22 | input wire out_nxt, 23 | output wire [7:0] out_byte, 24 | output reg out_latch, 25 | output reg out_stp, 26 | 27 | // PROTOCOL 28 | output reg [3:0] sel_endp, 29 | 30 | output wire [8:0] buf_in_addr, 31 | output wire [7:0] buf_in_data, 32 | output wire buf_in_wren, 33 | input wire buf_in_ready, 34 | output reg buf_in_commit, 35 | output reg [9:0] buf_in_commit_len, 36 | input wire buf_in_commit_ack, 37 | 38 | output reg [9:0] buf_out_addr, 39 | input wire [7:0] buf_out_q, 40 | input wire [9:0] buf_out_len, 41 | input wire buf_out_hasdata, 42 | output reg buf_out_arm, 43 | input wire buf_out_arm_ack, 44 | 45 | input wire [1:0] endp_mode, 46 | 47 | output reg data_toggle_act, 48 | input wire [1:0] data_toggle, 49 | 50 | input wire [6:0] dev_addr, 51 | 52 | // status 53 | output reg err_crc_pid, 54 | output reg err_crc_tok, 55 | output reg err_crc_pkt, 56 | output reg err_pid_out_of_seq, 57 | 58 | output reg [10:0] dbg_frame_num, 59 | output wire [2:0] dbg_pkt_type 60 | 61 | ); 62 | 63 | // edge detection / synch 64 | reg reset_1, reset_2; 65 | reg in_act_1; 66 | reg out_nxt_1, out_nxt_2; 67 | 68 | // pid input 69 | wire [3:0] pid = in_byte[7:4]; 70 | wire pid_valid = (pid == ~in_byte[3:0]); 71 | reg [3:0] pid_stored; 72 | reg [3:0] pid_last; 73 | // pid output 74 | reg [3:0] pid_send; 75 | 76 | parameter [3:0] PID_TOKEN_OUT = 4'hE, 77 | PID_TOKEN_IN = 4'h6, 78 | PID_TOKEN_SOF = 4'hA, 79 | PID_TOKEN_SETUP = 4'h2, 80 | PID_TOKEN_PING = 4'hB, 81 | PID_DATA_0 = 4'hC, 82 | PID_DATA_1 = 4'h4, 83 | PID_DATA_2 = 4'h8, 84 | PID_DATA_M = 4'h0, 85 | PID_HAND_ACK = 4'hD, 86 | PID_HAND_NAK = 4'h5, 87 | PID_HAND_STALL = 4'h1, 88 | PID_HAND_NYET = 4'h9, 89 | PID_SPEC_PREERR = 4'h3, 90 | PID_SPEC_SPLIT = 4'h7, 91 | PID_SPEC_LPM = 4'hF; 92 | 93 | reg [2:0] pkt_type; 94 | 95 | parameter [2:0] PKT_TYPE_UNDEF = 3'h0, 96 | PKT_TYPE_TOKEN = 3'h1, 97 | PKT_TYPE_DATA = 3'h2, 98 | PKT_TYPE_HAND = 3'h3, 99 | PKT_TYPE_SPEC = 3'h4; 100 | 101 | reg [15:0] packet_crc; 102 | 103 | parameter [1:0] EP_MODE_CONTROL = 2'd0, 104 | EP_MODE_ISOCH = 2'd1, 105 | EP_MODE_BULK = 2'd2, 106 | EP_MODE_INTERRUPT = 2'd3; 107 | 108 | wire [3:0] data_pid = data_toggle == DATA_TOGGLE_1 ? PID_DATA_1 : 109 | data_toggle == DATA_TOGGLE_2 ? PID_DATA_2 : 110 | data_toggle == DATA_TOGGLE_M ? PID_DATA_M : PID_DATA_0; 111 | 112 | parameter [1:0] DATA_TOGGLE_0 = 2'b00; 113 | parameter [1:0] DATA_TOGGLE_1 = 2'b01; 114 | parameter [1:0] DATA_TOGGLE_2 = 2'b10; 115 | parameter [1:0] DATA_TOGGLE_M = 2'b11; 116 | 117 | // usb token data has reversed bitfields. in addition, the data is sent 118 | // in reverse bit order, which is reversed per-byte by the PHY. 119 | // these are not valid for SOF 120 | reg [15:0] packet_token; 121 | wire [6:0] packet_token_addr = packet_token[14:8] /* synthesis keep */; 122 | reg [6:0] packet_token_addr_stored; 123 | wire [3:0] packet_token_endp = {packet_token[2:0], packet_token[15]} /* synthesis keep */; 124 | wire [4:0] packet_token_crc5 = packet_token[7:3]; 125 | wire [10:0] packet_token_frame = {packet_token[2:0], packet_token[15:8]}; 126 | 127 | reg [10:0] dc; // delay counter 128 | reg [10:0] bc; // byte counter 129 | 130 | reg [6:0] local_dev_addr; 131 | // TODO flatten 132 | reg [15:0] crc16, crc16_1, crc16_2; 133 | wire [15:0] crc16_fix = ~{crc16_2[8], crc16_2[9], crc16_2[10], crc16_2[11], 134 | crc16_2[12], crc16_2[13], crc16_2[14], crc16_2[15], 135 | crc16_2[0], crc16_2[1], crc16_2[2], crc16_2[3], 136 | crc16_2[4], crc16_2[5], crc16_2[6], crc16_2[7]}; 137 | 138 | wire [15:0] crc16_fix_out = ~{crc16[8], crc16[9], crc16[10], crc16[11], 139 | crc16[12], crc16[13], crc16[14], crc16[15], 140 | crc16[0], crc16[1], crc16[2], crc16[3], 141 | crc16[4], crc16[5], crc16[6], crc16[7]}; 142 | 143 | // two byte delay for incoming data 144 | // 145 | assign buf_in_addr = buf_in_addr_0; 146 | assign buf_in_data = buf_in_data_0; 147 | assign buf_in_wren = buf_in_wren_0 && (state == ST_IN_1) && (pkt_type == PKT_TYPE_DATA); 148 | 149 | reg [8:0] buf_in_addr_2, buf_in_addr_1, buf_in_addr_0; 150 | reg [7:0] buf_in_data_1, buf_in_data_0; 151 | reg buf_in_wren_1, buf_in_wren_0; 152 | 153 | reg buf_in_ready_latch; 154 | reg buf_out_ready_latch; 155 | 156 | reg out_byte_buf; 157 | reg [7:0] out_byte_out; 158 | reg [1:0] out_byte_crc; 159 | wire [7:0] out_crc_mux = out_byte_crc[0] ? crc16_fix_out[15:8] : crc16_fix_out[7:0]; 160 | assign out_byte = out_byte_crc[1] ? out_crc_mux : 161 | out_byte_buf ? buf_out_q : out_byte_out; 162 | //reg [9:0] bytes_tosend /* synthesis noprune */; 163 | //reg [9:0] bytes_sent /* synthesis noprune */; 164 | 165 | reg [5:0] state; 166 | parameter [5:0] ST_RST_0 = 6'd0, 167 | ST_RST_1 = 6'd1, 168 | ST_IDLE = 6'd10, 169 | ST_IN_1 = 6'd21, 170 | ST_IN_TOK = 6'd22, 171 | ST_IN_TOK_PING = 6'd23, 172 | ST_PRE_EOP = 6'd24, 173 | ST_WAIT_EOP = 6'd25, 174 | ST_DATA_CRC = 6'd26, 175 | ST_OUT_PRE_0 = 6'd38, 176 | ST_OUT_PRE_1 = 6'd39, 177 | ST_OUT_0 = 6'd40, 178 | ST_OUT_1 = 6'd41, 179 | ST_OUT_2 = 6'd42, 180 | ST_OUT_3 = 6'd43; 181 | 182 | assign dbg_pkt_type = pkt_type; 183 | 184 | always @(posedge phy_clk) begin 185 | 186 | in_act_1 <= in_act; 187 | out_nxt_1 <= out_nxt; 188 | out_nxt_2 <= out_nxt_1; 189 | {reset_2, reset_1} <= {reset_1, reset_n}; 190 | 191 | if(in_latch) begin 192 | // delay incoming data by 2 bytes 193 | // we don't know incoming packet size, only that the last two bytes are CRC 194 | {buf_in_addr_1, buf_in_addr_0} <= {buf_in_addr_2, buf_in_addr_1}; 195 | {buf_in_data_1, buf_in_data_0} <= {in_byte, buf_in_data_1}; 196 | {buf_in_wren_1, buf_in_wren_0} <= {in_latch && (bc < 512) && buf_in_ready_latch && 197 | (packet_token_addr_stored == dev_addr), buf_in_wren_1}; 198 | end 199 | 200 | dc <= dc + 1'b1; 201 | 202 | out_stp <= 0; 203 | buf_in_commit <= 0; 204 | buf_out_arm <= 0; 205 | data_toggle_act <= 0; 206 | 207 | case(state) 208 | ST_RST_0: begin 209 | // reset state 210 | // NOTE: assigned address from host is lost 211 | bc <= 0; 212 | err_crc_pid <= 0; 213 | err_crc_tok <= 0; 214 | err_crc_pkt <= 0; 215 | err_pid_out_of_seq <= 0; 216 | pid_send <= 0; 217 | pid_stored <= 0; 218 | pid_last <= 0; 219 | local_dev_addr <= 0; 220 | 221 | buf_in_commit <= 0; 222 | buf_out_arm <= 0; 223 | 224 | state <= ST_RST_1; 225 | end 226 | ST_RST_1: begin 227 | // housekeeping goes here 228 | state <= ST_IDLE; 229 | end 230 | 231 | 232 | ST_IDLE: begin 233 | // idle state 234 | 235 | if(in_act) begin 236 | 237 | // wait for valid bytes 238 | if(in_latch) begin 239 | // check validity of PID 240 | if(pid_valid) begin 241 | 242 | // save it for later 243 | pid_stored <= pid; 244 | pid_last <= pid_stored; 245 | 246 | case(pid) 247 | PID_TOKEN_OUT, 248 | PID_TOKEN_IN, 249 | PID_TOKEN_SOF, 250 | PID_TOKEN_PING, 251 | PID_TOKEN_SETUP: pkt_type <= PKT_TYPE_TOKEN; // expect 16 bits of data 252 | 253 | PID_DATA_0, 254 | PID_DATA_1, 255 | PID_DATA_2, 256 | PID_DATA_M: pkt_type <= PKT_TYPE_DATA; // variable length 257 | 258 | PID_HAND_ACK, 259 | PID_HAND_NAK, 260 | PID_HAND_STALL, 261 | PID_HAND_NYET: pkt_type <= PKT_TYPE_HAND; // handshaking, very short 262 | 263 | PID_SPEC_PREERR, 264 | PID_SPEC_SPLIT, 265 | PID_SPEC_LPM: pkt_type <= PKT_TYPE_SPEC; // special cases 266 | endcase 267 | 268 | // reset byte count and latch in packet 269 | bc <= 0; 270 | crc16 <= 16'hffff; 271 | buf_in_addr_2 <= 0; 272 | state <= ST_IN_1; 273 | buf_in_ready_latch <= buf_in_ready; 274 | end else begin 275 | // sit out the rest of the packet, flag error 276 | err_crc_pid <= 1; 277 | state <= ST_WAIT_EOP; 278 | end 279 | end 280 | end 281 | end 282 | 283 | ST_IN_1: begin 284 | // read in packet data 285 | crc16_byte_sel <= 0; 286 | 287 | if(in_latch) begin 288 | bc <= bc + 1'b1; 289 | buf_in_addr_2 <= buf_in_addr_2 + 1'b1; 290 | 291 | // advance CRCs 292 | crc16 <= next_crc16; 293 | crc16_1 <= crc16; 294 | crc16_2 <= crc16_1; 295 | 296 | // this only handles TOKEN packets 297 | if(pkt_type == PKT_TYPE_TOKEN) begin 298 | case(bc) 299 | 0: packet_token[15:8] <= in_byte; 300 | 1: begin 301 | packet_token[7:0] <= in_byte; 302 | crc5_data <= {in_byte[2:0], packet_token[15:8]}; 303 | // finished, process TOKEN 304 | state <= ST_IN_TOK; 305 | end 306 | endcase 307 | end 308 | 309 | // setup packets are 10 bytes long (8 without CRC) 310 | packet_crc <= {packet_crc[7:0], in_byte}; 311 | end 312 | 313 | // detect EOP 314 | if(~in_act) begin 315 | // default is to IDLE 316 | state <= ST_IDLE; 317 | 318 | // data toggle 319 | if(packet_token_addr_stored == local_dev_addr) begin 320 | if(pid_stored == PID_HAND_ACK) begin 321 | // yay 322 | data_toggle_act <= 1; 323 | // tell endpoints transfer succeeded 324 | if(pid_last == PID_TOKEN_IN) begin 325 | //bytes_tosend <= 0; 326 | //bytes_sent <= 0; 327 | buf_out_arm <= 1; 328 | end 329 | end 330 | end 331 | 332 | if(packet_token_addr == local_dev_addr) begin 333 | // was it a zero-length OUT? 334 | if(pid_last == PID_TOKEN_OUT && bc == 2) begin 335 | pid_send <= PID_HAND_ACK; 336 | bc <= 0; 337 | state <= ST_OUT_0; 338 | buf_in_commit <= 1; 339 | buf_in_commit_len <= 0; 340 | end else if(pid_last == PID_TOKEN_OUT || pid_last == PID_TOKEN_SETUP) begin 341 | state <= ST_DATA_CRC; 342 | buf_in_commit <= 1; 343 | buf_in_commit_len <= bc-10'h2; 344 | end 345 | end 346 | end 347 | end 348 | 349 | ST_IN_TOK: begin 350 | // default is to wait for EOP 351 | state <= ST_WAIT_EOP; 352 | 353 | // next default is confirm token CRC5 354 | if(packet_token_crc5 != next_crc5) begin 355 | err_crc_tok <= 1; 356 | state <= ST_PRE_EOP; 357 | end 358 | 359 | case(pid_stored) 360 | PID_TOKEN_SOF: begin 361 | dbg_frame_num <= packet_token_frame; 362 | end 363 | endcase 364 | 365 | // only parse tokens at our address 366 | if(packet_token_addr == local_dev_addr) begin 367 | 368 | case(pid_stored) 369 | PID_TOKEN_IN: begin 370 | // switch protocol layer to proper endpoint 371 | local_dev_addr <= dev_addr; 372 | // send endpoint OUT buffer 373 | state <= ST_OUT_PRE_0; 374 | end 375 | PID_TOKEN_OUT: begin 376 | // 377 | end 378 | PID_TOKEN_SETUP: begin 379 | // 380 | end 381 | PID_TOKEN_PING: begin 382 | // 383 | // special case: reply to PING 384 | dc <= 0; 385 | state <= ST_IN_TOK_PING; 386 | end 387 | endcase 388 | 389 | // in case of IN/OUT/SETUP/PING 390 | if(pid_stored != PID_TOKEN_SOF) begin 391 | // tell protocol layer which endpoint was selected 392 | sel_endp <= packet_token_endp; 393 | end 394 | end 395 | 396 | if(pid_stored != PID_TOKEN_SOF) begin 397 | // save intended device address for later data stages 398 | packet_token_addr_stored <= packet_token_addr; 399 | end 400 | end 401 | ST_IN_TOK_PING: begin 402 | // reply to PING if endpoint is open 403 | // allow 8 cycles for protocol layer to select EP and propagate status 404 | if(dc == 7) begin 405 | pid_send <= buf_in_ready ? PID_HAND_ACK : PID_HAND_NAK; 406 | bc <= 0; 407 | state <= ST_OUT_0; 408 | end 409 | end 410 | 411 | ST_PRE_EOP: begin 412 | state <= ST_WAIT_EOP; 413 | end 414 | ST_WAIT_EOP: begin 415 | // detect EOP 416 | out_latch <= 0; 417 | if(~in_act) state <= ST_IDLE; 418 | end 419 | 420 | 421 | ST_DATA_CRC: begin 422 | // check CRC16 423 | if(packet_crc == crc16_fix) begin 424 | // good, process etc 425 | // send ACK 426 | pid_send <= buf_in_ready_latch ? PID_HAND_ACK : PID_HAND_NAK; 427 | bc <= 0; 428 | // don't ACK isochronous transfers 429 | state <= (endp_mode == EP_MODE_ISOCH) ? ST_WAIT_EOP : ST_OUT_0; 430 | end else begin 431 | // invalid CRC, wait for packet to end (it probably did) 432 | err_crc_pkt <= 1; 433 | state <= ST_WAIT_EOP; 434 | end 435 | end 436 | 437 | 438 | ST_OUT_PRE_0: begin 439 | dc <= 0; 440 | pid_send <= data_pid; 441 | state <= ST_OUT_PRE_1; 442 | end 443 | ST_OUT_PRE_1: begin 444 | // wait for protocol FSM/endpoint FSM to be ready (usually already is) 445 | 446 | if(buf_out_hasdata) begin 447 | // good to go 448 | bc <= buf_out_len + 11'h2; 449 | // note: needs more work to allow 450 | // multipart transfers not exactly 512 bytes 451 | //bytes_tosend <= buf_out_len; 452 | //bytes_sent <= 0; 453 | state <= ST_OUT_0; 454 | end else begin 455 | // wait a bit 456 | if(dc == 31) begin 457 | // not ready, NAK 458 | //if(bytes_sent != bytes_tosend) begin 459 | pid_send <= PID_HAND_NAK; 460 | bc <= 0; 461 | //end else begin 462 | // bc <= 2; 463 | //end 464 | state <= (endp_mode == EP_MODE_ISOCH) ? ST_WAIT_EOP : ST_OUT_0; 465 | end 466 | end 467 | end 468 | ST_OUT_0: begin 469 | // send packet through ULPI 470 | 471 | // wait for any rx to complete 472 | crc16_byte_sel <= 1; 473 | crc16 <= 16'hffff; 474 | // switch mux from bram to local reg 475 | out_byte_buf <= 0; 476 | if(out_cts) state <= ST_OUT_1; 477 | end 478 | ST_OUT_1: begin 479 | // write PID 480 | out_byte_out <= {4'h4, ~pid_send}; 481 | out_latch <= 1; 482 | buf_out_addr <= 0; 483 | state <= ST_OUT_2; 484 | end 485 | ST_OUT_2: begin 486 | out_latch <= 1'b0; 487 | if(bc > 0) begin 488 | out_latch <= 1; 489 | state <= ST_OUT_3; 490 | end else begin 491 | if(out_nxt) begin 492 | // packet send complete 493 | out_stp <= 1; 494 | if(endp_mode == EP_MODE_ISOCH) begin 495 | // normally the endpoint buffer is not freed until 496 | // a correspending ACK is received from the host, 497 | // but with isochronous there will never be an ACK. 498 | // re-arm the buffer right after completion. 499 | data_toggle_act <= 1; 500 | buf_out_arm <= 1; 501 | end 502 | state <= ST_WAIT_EOP; 503 | end 504 | end 505 | end 506 | ST_OUT_3: begin 507 | if(out_nxt) begin 508 | // phy wants another byte 509 | if(bc == 0) begin 510 | out_stp <= 1; 511 | state <= ST_WAIT_EOP; 512 | // reset latch 513 | buf_out_ready_latch <= 0; 514 | out_byte_crc <= 2'b00; 515 | end else begin 516 | // switch mux to bram 517 | out_byte_buf <= 1; 518 | end 519 | 520 | buf_out_addr <= buf_out_addr + 1'b1; 521 | bc <= bc - 1'b1; 522 | 523 | // NOTE: a nominal 9bit address reg here 524 | // will wrap to 0 and confuse this, solution 525 | // is to make it 10 bits :) 526 | if(buf_out_addr > 0 && bc > 1) begin 527 | crc16 <= next_crc16; 528 | //bytes_sent <= bytes_sent + 1'b1; 529 | end 530 | 531 | if(bc == 2) out_byte_crc <= 2'b11; 532 | if(bc == 1) out_byte_crc <= 2'b10; 533 | end 534 | if(~out_nxt & out_nxt_1 ) begin 535 | // falling edge 536 | // keep this byte 537 | out_byte_out <= buf_out_q; 538 | out_byte_buf <= 0; 539 | end 540 | end 541 | default: state <= ST_RST_0; 542 | endcase 543 | 544 | if(~reset_2) begin 545 | // reset 546 | state <= ST_RST_0; 547 | end 548 | 549 | end 550 | 551 | // 552 | // crc5-usb 553 | // 554 | wire [4:0] next_crc5; 555 | reg [10:0] crc5_data; 556 | 557 | usb2_crc5 ic5 ( 558 | .c ( 5'h1F ), 559 | .data ( crc5_data ), 560 | .next_crc ( next_crc5 ) 561 | ); 562 | 563 | // 564 | // crc16-usb 565 | // 566 | wire [15:0] next_crc16; 567 | reg crc16_byte_sel; 568 | wire [7:0] crc16_byte = crc16_byte_sel ? out_byte : in_byte; 569 | 570 | usb2_crc16 ic16 ( 571 | .c ( crc16 ), 572 | .data ( crc16_byte ), 573 | .next_crc ( next_crc16 ) 574 | ); 575 | 576 | 577 | endmodule 578 | -------------------------------------------------------------------------------- /core/usb3/usb3_protocol.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 3.0 protocol layer 4 | // 5 | // Copyright (c) 2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb3_protocol ( 12 | 13 | input wire slow_clk, 14 | input wire local_clk, 15 | input wire ext_clk, 16 | input wire reset_n, 17 | input wire [4:0] ltssm_state, 18 | 19 | // link interface 20 | input wire rx_tp, 21 | input wire rx_tp_hosterr, 22 | input wire rx_tp_retry, 23 | input wire rx_tp_pktpend, 24 | input wire [3:0] rx_tp_subtype, 25 | input wire [3:0] rx_tp_endp, 26 | input wire [4:0] rx_tp_nump, 27 | input wire [4:0] rx_tp_seq, 28 | input wire [15:0] rx_tp_stream, 29 | 30 | input wire rx_dph, 31 | input wire rx_dph_eob, 32 | input wire rx_dph_setup, 33 | input wire rx_dph_pktpend, 34 | input wire [3:0] rx_dph_endp, 35 | input wire [4:0] rx_dph_seq, 36 | input wire [15:0] rx_dph_len, 37 | input wire rx_dpp_start, 38 | input wire rx_dpp_done, 39 | input wire rx_dpp_crcgood, 40 | 41 | output reg tx_tp_a, 42 | output reg tx_tp_a_retry, 43 | output reg tx_tp_a_dir, 44 | output reg [3:0] tx_tp_a_subtype, 45 | output reg [3:0] tx_tp_a_endp, 46 | output reg [4:0] tx_tp_a_nump, 47 | output reg [4:0] tx_tp_a_seq, 48 | output reg [15:0] tx_tp_a_stream, 49 | input wire tx_tp_a_ack, 50 | 51 | output reg tx_tp_b, 52 | output reg tx_tp_b_retry, 53 | output reg tx_tp_b_dir, 54 | output reg [3:0] tx_tp_b_subtype, 55 | output reg [3:0] tx_tp_b_endp, 56 | output reg [4:0] tx_tp_b_nump, 57 | output reg [4:0] tx_tp_b_seq, 58 | output reg [15:0] tx_tp_b_stream, 59 | input wire tx_tp_b_ack, 60 | 61 | output reg tx_tp_c, 62 | output reg tx_tp_c_retry, 63 | output reg tx_tp_c_dir, 64 | output reg [3:0] tx_tp_c_subtype, 65 | output reg [3:0] tx_tp_c_endp, 66 | output reg [4:0] tx_tp_c_nump, 67 | output reg [4:0] tx_tp_c_seq, 68 | output reg [15:0] tx_tp_c_stream, 69 | input wire tx_tp_c_ack, 70 | 71 | output reg tx_dph, 72 | output reg tx_dph_eob, 73 | output reg tx_dph_dir, 74 | output reg [3:0] tx_dph_endp, 75 | output reg [4:0] tx_dph_seq, 76 | output reg [15:0] tx_dph_len, 77 | input wire tx_dpp_ack, 78 | input wire tx_dpp_done, 79 | 80 | 81 | input wire [8:0] buf_in_addr, 82 | input wire [31:0] buf_in_data, 83 | input wire buf_in_wren, 84 | output wire buf_in_ready, 85 | input wire buf_in_commit, 86 | input wire [10:0] buf_in_commit_len, 87 | output wire buf_in_commit_ack, 88 | 89 | input wire [8:0] buf_out_addr, 90 | output wire [31:0] buf_out_q, 91 | output wire [10:0] buf_out_len, 92 | output wire buf_out_hasdata, 93 | input wire buf_out_arm, 94 | output wire buf_out_arm_ack, 95 | 96 | // external interface 97 | input wire [8:0] ext_buf_in_addr, 98 | input wire [31:0] ext_buf_in_data, 99 | input wire ext_buf_in_wren, 100 | output reg ext_buf_in_request, 101 | output wire ext_buf_in_ready, 102 | input wire ext_buf_in_commit, 103 | input wire [10:0] ext_buf_in_commit_len, 104 | output wire ext_buf_in_commit_ack, 105 | 106 | input wire [8:0] ext_buf_out_addr, 107 | output wire [31:0] ext_buf_out_q, 108 | output wire [10:0] ext_buf_out_len, 109 | output wire ext_buf_out_hasdata, 110 | input wire ext_buf_out_arm, 111 | output wire ext_buf_out_arm_ack, 112 | 113 | output wire [1:0] endp_mode_rx, 114 | output wire [1:0] endp_mode_tx, 115 | 116 | output wire vend_req_act, 117 | output wire [7:0] vend_req_request, 118 | output wire [15:0] vend_req_val, 119 | 120 | output wire [6:0] dev_addr, 121 | output wire configured, 122 | 123 | output reg err_miss_rx, 124 | output reg err_miss_tx, 125 | output reg err_tp_subtype, 126 | output reg err_missed_dpp_start, 127 | output reg err_missed_dpp_done 128 | 129 | ); 130 | 131 | `include "usb3_const.vh" 132 | 133 | // mux bram signals 134 | wire [8:0] ep0_buf_in_addr = rx_endp == SEL_ENDP0 ? buf_in_addr : 'h0; 135 | wire [31:0] ep0_buf_in_data = rx_endp == SEL_ENDP0 ? buf_in_data : 'h0; 136 | wire ep0_buf_in_wren = rx_endp == SEL_ENDP0 ? buf_in_wren : 'h0; 137 | wire ep0_buf_in_ready; 138 | wire ep0_buf_in_commit = rx_endp == SEL_ENDP0 ? buf_in_commit : 'h0; 139 | wire [10:0] ep0_buf_in_commit_len = rx_endp == SEL_ENDP0 ? buf_in_commit_len : 'h0; 140 | wire ep0_buf_in_commit_ack; 141 | 142 | wire [8:0] ep0_buf_out_addr = tx_endp == SEL_ENDP0 ? buf_out_addr : 'h0; 143 | wire [31:0] ep0_buf_out_q; 144 | wire [10:0] ep0_buf_out_len; 145 | wire ep0_buf_out_hasdata; 146 | wire ep0_buf_out_arm = tx_endp == SEL_ENDP0 ? buf_out_arm : 'h0; 147 | wire ep0_buf_out_arm_ack; 148 | 149 | wire [8:0] ep1_buf_out_addr = tx_endp == SEL_ENDP1 ? buf_out_addr : 'h0; 150 | wire [31:0] ep1_buf_out_q; 151 | wire [10:0] ep1_buf_out_len; 152 | wire ep1_buf_out_hasdata; 153 | wire ep1_buf_out_arm = tx_endp == SEL_ENDP1 ? buf_out_arm : 'h0; 154 | wire ep1_buf_out_arm_ack; 155 | 156 | wire [8:0] ep2_buf_in_addr = rx_endp == SEL_ENDP2 ? buf_in_addr : 'h0; 157 | wire [31:0] ep2_buf_in_data = rx_endp == SEL_ENDP2 ? buf_in_data : 'h0; 158 | wire ep2_buf_in_wren = rx_endp == SEL_ENDP2 ? buf_in_wren : 'h0; 159 | wire ep2_buf_in_ready; 160 | wire ep2_buf_in_commit = rx_endp == SEL_ENDP2 ? buf_in_commit : 'h0; 161 | wire [10:0] ep2_buf_in_commit_len = rx_endp == SEL_ENDP2 ? buf_in_commit_len : 'h0; 162 | wire ep2_buf_in_commit_ack; 163 | 164 | 165 | assign buf_in_ready = rx_endp == SEL_ENDP0 ? ep0_buf_in_ready : 166 | rx_endp == SEL_ENDP2 ? ep2_buf_in_ready : 'h0; 167 | 168 | assign buf_in_commit_ack = rx_endp == SEL_ENDP0 ? ep0_buf_in_commit_ack : 169 | rx_endp == SEL_ENDP2 ? ep2_buf_in_commit_ack : 'h0; 170 | 171 | assign buf_out_q = tx_endp == SEL_ENDP0 ? ep0_buf_out_q : 172 | tx_endp == SEL_ENDP1 ? ep1_buf_out_q : 'h0; 173 | 174 | assign buf_out_len = tx_endp == SEL_ENDP0 ? ep0_buf_out_len : 175 | tx_endp == SEL_ENDP1 ? ep1_buf_out_len : 'h0; 176 | 177 | assign buf_out_hasdata = tx_endp == SEL_ENDP0 ? ep0_buf_out_hasdata : 178 | tx_endp == SEL_ENDP1 ? ep1_buf_out_hasdata : 'h0; 179 | 180 | assign buf_out_arm_ack = tx_endp == SEL_ENDP0 ? ep0_buf_out_arm_ack : 181 | tx_endp == SEL_ENDP1 ? ep1_buf_out_arm_ack : 'h0; 182 | 183 | assign endp_mode_tx = tx_endp == SEL_ENDP1 ? EP1_MODE : 184 | tx_endp == SEL_ENDP2 ? EP2_MODE : EP_MODE_CONTROL; 185 | 186 | assign endp_mode_rx = rx_endp == SEL_ENDP1 ? EP1_MODE : 187 | rx_endp == SEL_ENDP2 ? EP2_MODE : EP_MODE_CONTROL; 188 | 189 | parameter [3:0] SEL_ENDP0 = 4'd0, 190 | SEL_ENDP1 = 4'd1, 191 | SEL_ENDP2 = 4'd2, 192 | SEL_ENDP3 = 4'd3, 193 | SEL_ENDP4 = 4'd4, 194 | SEL_ENDP5 = 4'd5, 195 | SEL_ENDP6 = 4'd6, 196 | SEL_ENDP7 = 4'd7; 197 | 198 | parameter [1:0] EP_MODE_CONTROL = 2'd0, 199 | EP_MODE_ISOCH = 2'd1, 200 | EP_MODE_BULK = 2'd2, 201 | EP_MODE_INTERRUPT = 2'd3; 202 | 203 | // assign endpoint modes here and also 204 | // in the descriptor strings 205 | wire [1:0] EP1_MODE = EP_MODE_BULK; 206 | wire [1:0] EP2_MODE = EP_MODE_BULK; 207 | 208 | reg [4:0] rx_state; 209 | parameter [4:0] RX_RESET = 'd0, 210 | RX_IDLE = 'd1, 211 | RX_0 = 'd2, 212 | RX_1 = 'd3, 213 | RX_2 = 'd4, 214 | RX_TP_0 = 'd10, 215 | RX_TP_1 = 'd11, 216 | RX_TP_2 = 'd12, 217 | RX_DPH_0 = 'd20, 218 | RX_DPH_1 = 'd21, 219 | RX_DPH_2 = 'd22; 220 | 221 | reg [4:0] tx_state; 222 | parameter [4:0] TX_RESET = 'd0, 223 | TX_IDLE = 'd1, 224 | TX_DP_WAITDATA = 'd2, 225 | TX_DP_0 = 'd3, 226 | TX_DP_1 = 'd4, 227 | TX_DP_2 = 'd5, 228 | TX_DP_3 = 'd6, 229 | TX_DP_NRDY = 'd7, 230 | TX_DP_ERDY = 'd8; 231 | 232 | reg [4:0] in_dpp_seq /* synthesis noprune */; 233 | reg [4:0] out_dpp_seq /* synthesis noprune */; 234 | wire reset_dp_seq; 235 | 236 | reg [15:0] out_length; 237 | reg [4:0] out_nump; 238 | 239 | reg do_send_dpp; 240 | 241 | reg [10:0] recv_count; 242 | reg [10:0] dc; 243 | 244 | reg [3:0] rx_endp; 245 | reg [3:0] tx_endp; 246 | 247 | always @(posedge local_clk) begin 248 | 249 | tx_tp_a <= 0; 250 | tx_tp_b <= 0; 251 | tx_tp_c <= 0; 252 | tx_dph <= 0; 253 | 254 | do_send_dpp <= 0; 255 | 256 | ext_buf_in_request <= 0; 257 | 258 | `INC(dc); 259 | `INC(recv_count); 260 | 261 | case(rx_state) 262 | RX_RESET: rx_state <= RX_IDLE; 263 | RX_IDLE: begin 264 | if(rx_dph) begin 265 | // receiving data packet header, link layer is stuffing payload 266 | // into the endpoint buffer 267 | in_dpp_seq <= rx_dph_seq; 268 | rx_endp <= rx_dph_endp; 269 | rx_state <= RX_DPH_0; 270 | recv_count <= 0; 271 | end else 272 | if(rx_tp) begin 273 | // receving transaction packet, could be ACK or something else 274 | rx_state <= RX_TP_0; 275 | end 276 | end 277 | RX_DPH_0: begin 278 | if(rx_dpp_start) begin 279 | // received DPP start ordered set 280 | rx_state <= RX_DPH_1; 281 | end 282 | if(ltssm_state != LT_U0 || recv_count == 20) begin 283 | // we waited too long for DPP start and it hasn't come yet 284 | err_missed_dpp_start <= 1; 285 | rx_state <= RX_DPH_2; 286 | end 287 | end 288 | RX_DPH_1: begin 289 | if(rx_dpp_done) begin 290 | if(rx_dpp_crcgood) `INC(in_dpp_seq); 291 | err_missed_dpp_start <= 0; 292 | err_missed_dpp_done <= 0; 293 | rx_state <= RX_DPH_2; 294 | end 295 | if(ltssm_state != LT_U0 || recv_count == 270) begin 296 | err_missed_dpp_done <= 1; 297 | rx_state <= RX_DPH_2; 298 | end 299 | end 300 | RX_DPH_2: begin 301 | // send ACK 302 | tx_tp_a <= 1'b1; 303 | tx_tp_a_retry <= ( rx_dpp_crcgood && 304 | !err_missed_dpp_start && 305 | !err_missed_dpp_done 306 | ) ? LP_TP_NORETRY : LP_TP_RETRY; 307 | tx_tp_a_dir <= LP_TP_HOSTTODEVICE; 308 | tx_tp_a_subtype <= LP_TP_SUB_ACK; 309 | tx_tp_a_endp <= rx_dph_endp; 310 | tx_tp_a_nump <= 5'h1; 311 | tx_tp_a_seq <= in_dpp_seq; 312 | tx_tp_a_stream <= 16'h0; 313 | 314 | if(tx_tp_a_ack) rx_state <= RX_IDLE; 315 | end 316 | RX_TP_0: begin 317 | // unless otherwise directed, immediately return 318 | rx_state <= RX_IDLE; 319 | 320 | case(rx_tp_subtype) 321 | LP_TP_SUB_ACK: begin 322 | if(rx_tp_pktpend && rx_tp_nump > 0) begin 323 | // IN, expecting us to send data 324 | // switch endpoint mux 325 | tx_endp <= rx_tp_endp; 326 | out_nump <= rx_tp_nump; 327 | out_dpp_seq <= rx_tp_seq; 328 | 329 | do_send_dpp <= 1; 330 | end else begin 331 | // ACK from a previously sent packet 332 | end 333 | end 334 | LP_TP_SUB_NRDY: begin 335 | 336 | end 337 | LP_TP_SUB_ERDY: begin 338 | 339 | end 340 | LP_TP_SUB_STATUS: begin 341 | // for control transfers 342 | tx_tp_b <= 1'b1; 343 | tx_tp_b_retry <= LP_TP_NORETRY; 344 | tx_tp_b_dir <= LP_TP_HOSTTODEVICE; 345 | tx_tp_b_subtype <= LP_TP_SUB_ACK; 346 | tx_tp_b_endp <= rx_tp_endp; 347 | tx_tp_b_nump <= 5'h0; 348 | tx_tp_b_seq <= in_dpp_seq; 349 | tx_tp_b_stream <= 16'h0; 350 | 351 | if(!tx_tp_b_ack) rx_state <= rx_state; 352 | end 353 | LP_TP_SUB_PING: begin 354 | 355 | end 356 | default: begin 357 | // invalid subtype 358 | err_tp_subtype <= 1; 359 | end 360 | endcase 361 | end 362 | 363 | RX_0: begin 364 | 365 | end 366 | RX_1: begin 367 | 368 | end 369 | endcase 370 | 371 | case(tx_state) 372 | TX_RESET: tx_state <= TX_IDLE; 373 | TX_IDLE: begin 374 | if(do_send_dpp) begin 375 | // if you had multiple IN endpoints you would rewrite this part 376 | if(tx_endp == SEL_ENDP1) ext_buf_in_request <= 1; 377 | if(buf_out_hasdata) begin 378 | // data is already in EP buffer 379 | // note: overall transfer length 380 | 381 | out_length <= buf_out_len; 382 | tx_state <= TX_DP_0; 383 | end else begin 384 | // no data is ready yet, send NRDY and wait 385 | tx_state <= TX_DP_NRDY; 386 | end 387 | end 388 | end 389 | TX_DP_NRDY: begin 390 | tx_tp_c <= 1'b1; 391 | tx_tp_c_retry <= LP_TP_NORETRY; 392 | tx_tp_c_dir <= LP_TP_HOSTTODEVICE; 393 | tx_tp_c_subtype <= LP_TP_SUB_NRDY; 394 | tx_tp_c_endp <= tx_endp; 395 | tx_tp_c_nump <= 5'h0; 396 | tx_tp_c_seq <= 5'h0; 397 | tx_tp_c_stream <= 16'h0; 398 | 399 | if(tx_tp_c_ack) tx_state <= TX_DP_WAITDATA; 400 | end 401 | TX_DP_WAITDATA: begin 402 | if(tx_endp == SEL_ENDP1) ext_buf_in_request <= 1; 403 | 404 | if(buf_out_hasdata) begin 405 | // data is already in EP buffer 406 | // note: overall transfer length 407 | out_length <= buf_out_len; 408 | tx_state <= TX_DP_ERDY; 409 | end 410 | end 411 | TX_DP_ERDY: begin 412 | tx_tp_c <= 1'b1; 413 | tx_tp_c_retry <= LP_TP_NORETRY; 414 | tx_tp_c_dir <= LP_TP_HOSTTODEVICE; 415 | tx_tp_c_subtype <= LP_TP_SUB_ERDY; 416 | tx_tp_c_endp <= tx_endp; 417 | tx_tp_c_nump <= 5'h1; 418 | tx_tp_c_seq <= 5'h0; 419 | tx_tp_c_stream <= 16'h0; 420 | 421 | if(tx_tp_c_ack) tx_state <= TX_DP_0; 422 | end 423 | TX_DP_0: begin 424 | tx_dph <= 1'b1; 425 | tx_dph_eob <= 0; // TODO 426 | tx_dph_dir <= tx_endp == 0 ? 0 : LP_TP_DEVICETOHOST; // rx_tp_endp 427 | tx_dph_endp <= tx_endp; 428 | tx_dph_seq <= out_dpp_seq; 429 | tx_dph_len <= out_length; // TODO 430 | 431 | dc <= 0; 432 | if(tx_dpp_ack) tx_state <= TX_DP_1; 433 | end 434 | TX_DP_1: begin 435 | if(tx_dpp_done) tx_state <= TX_IDLE; 436 | end 437 | endcase 438 | 439 | 440 | 441 | if(rx_state != RX_IDLE) begin 442 | // missed an incoming transaction! 443 | if(rx_dph || rx_tp) err_miss_rx <= 1; 444 | end 445 | if(tx_state != TX_IDLE) begin 446 | if(do_send_dpp) err_miss_tx <= 1; 447 | end 448 | 449 | 450 | if(~reset_n) begin 451 | rx_state <= RX_RESET; 452 | tx_state <= TX_RESET; 453 | end 454 | 455 | if(~reset_n) begin 456 | err_miss_rx <= 0; 457 | err_miss_tx <= 0; 458 | err_tp_subtype <= 0; 459 | err_missed_dpp_start <= 0; 460 | err_missed_dpp_done <= 0; 461 | end 462 | end 463 | 464 | //////////////////////////////////////////////////////////// 465 | // 466 | // ENDPOINT 0 IN/OUT 467 | // 468 | //////////////////////////////////////////////////////////// 469 | 470 | usb3_ep0 iu3ep0 ( 471 | .slow_clk ( slow_clk ), 472 | .local_clk ( local_clk ), 473 | .reset_n ( reset_n ), 474 | 475 | .buf_in_addr ( ep0_buf_in_addr ), 476 | .buf_in_data ( ep0_buf_in_data ), 477 | .buf_in_wren ( ep0_buf_in_wren ), 478 | .buf_in_ready ( ep0_buf_in_ready ), 479 | .buf_in_commit ( ep0_buf_in_commit ), 480 | .buf_in_commit_len ( ep0_buf_in_commit_len ), 481 | .buf_in_commit_ack ( ep0_buf_in_commit_ack ), 482 | 483 | .buf_out_addr ( ep0_buf_out_addr ), 484 | .buf_out_q ( ep0_buf_out_q ), 485 | .buf_out_len ( ep0_buf_out_len ), 486 | .buf_out_hasdata ( ep0_buf_out_hasdata ), 487 | .buf_out_arm ( ep0_buf_out_arm ), 488 | .buf_out_arm_ack ( ep0_buf_out_arm_ack ), 489 | 490 | .vend_req_act ( vend_req_act ), 491 | .vend_req_request ( vend_req_request ), 492 | .vend_req_val ( vend_req_val ), 493 | 494 | .dev_addr ( dev_addr ), 495 | .configured ( configured ), 496 | .reset_dp_seq ( reset_dp_seq ) 497 | 498 | //.err_setup_pkt ( err_setup_pkt ) 499 | ); 500 | 501 | 502 | //////////////////////////////////////////////////////////// 503 | // 504 | // ENDPOINT 1 IN (DATA TO PC) 505 | // 506 | //////////////////////////////////////////////////////////// 507 | 508 | usb3_ep iu3ep1 ( 509 | .slow_clk ( slow_clk ), 510 | .local_clk ( local_clk ), 511 | .rd_clk ( local_clk ), 512 | .wr_clk ( ext_clk ), 513 | 514 | .reset_n ( reset_n ), 515 | 516 | .buf_in_addr ( ext_buf_in_addr ), 517 | .buf_in_data ( ext_buf_in_data ), 518 | .buf_in_wren ( ext_buf_in_wren ), 519 | .buf_in_ready ( ext_buf_in_ready ), 520 | .buf_in_commit ( ext_buf_in_commit ), 521 | .buf_in_commit_len ( ext_buf_in_commit_len ), 522 | .buf_in_commit_ack ( ext_buf_in_commit_ack ), 523 | 524 | .buf_out_addr ( ep1_buf_out_addr ), 525 | .buf_out_q ( ep1_buf_out_q ), 526 | .buf_out_len ( ep1_buf_out_len ), 527 | .buf_out_hasdata ( ep1_buf_out_hasdata ), 528 | .buf_out_arm ( ep1_buf_out_arm ), 529 | .buf_out_arm_ack ( ep1_buf_out_arm_ack ), 530 | 531 | .mode ( EP1_MODE ) 532 | ); 533 | 534 | //////////////////////////////////////////////////////////// 535 | // 536 | // ENDPOINT 2 OUT (DATA FROM PC) 537 | // 538 | //////////////////////////////////////////////////////////// 539 | 540 | usb3_ep iu3ep2 ( 541 | .slow_clk ( slow_clk ), 542 | .local_clk ( local_clk ), 543 | .rd_clk ( ext_clk ), 544 | .wr_clk ( local_clk ), 545 | 546 | .reset_n ( reset_n ), 547 | 548 | .buf_in_addr ( ep2_buf_in_addr ), 549 | .buf_in_data ( ep2_buf_in_data ), 550 | .buf_in_wren ( ep2_buf_in_wren ), 551 | .buf_in_ready ( ep2_buf_in_ready ), 552 | .buf_in_commit ( ep2_buf_in_commit ), 553 | .buf_in_commit_len ( ep2_buf_in_commit_len ), 554 | .buf_in_commit_ack ( ep2_buf_in_commit_ack ), 555 | 556 | .buf_out_addr ( ext_buf_out_addr ), 557 | .buf_out_q ( ext_buf_out_q ), 558 | .buf_out_len ( ext_buf_out_len ), 559 | .buf_out_hasdata ( ext_buf_out_hasdata ), 560 | .buf_out_arm ( ext_buf_out_arm ), 561 | .buf_out_arm_ack ( ext_buf_out_arm_ack ), 562 | 563 | .mode ( EP2_MODE ) 564 | ); 565 | 566 | endmodule 567 | -------------------------------------------------------------------------------- /core/usb3/usb3_top.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 3.0 top-level 4 | // 5 | // Copyright (c) 2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb3_top ( 12 | 13 | input wire ext_clk, 14 | input wire reset_n, 15 | 16 | input wire phy_pipe_half_clk, // 125MHz: 1/2 PCLK 17 | input wire phy_pipe_half_clk_phase, // 125MHz: 1/2 PCLK, phase shift 90 18 | input wire phy_pipe_quarter_clk, // 62.5MHz: 1/4 PCLK 19 | input wire [31:0] phy_pipe_rx_data, 20 | input wire [3:0] phy_pipe_rx_datak, 21 | input wire [1:0] phy_pipe_rx_valid, 22 | output wire [31:0] phy_pipe_tx_data, 23 | output wire [3:0] phy_pipe_tx_datak, 24 | 25 | output wire phy_reset_n, 26 | output wire phy_out_enable, 27 | output wire phy_phy_reset_n, 28 | output wire phy_tx_detrx_lpbk, 29 | output wire phy_tx_elecidle, 30 | inout wire phy_rx_elecidle, 31 | input wire [5:0] phy_rx_status, 32 | output wire [1:0] phy_power_down, 33 | input wire [1:0] phy_phy_status_i, 34 | output wire phy_phy_status_o, 35 | input wire phy_pwrpresent, 36 | 37 | output wire phy_tx_oneszeros, 38 | output wire [1:0] phy_tx_deemph, 39 | output wire [2:0] phy_tx_margin, 40 | output wire phy_tx_swing, 41 | output wire phy_rx_polarity, 42 | output wire phy_rx_termination, 43 | output wire phy_rate, 44 | output wire phy_elas_buf_mode, 45 | 46 | input wire [8:0] buf_in_addr, 47 | input wire [31:0] buf_in_data, 48 | input wire buf_in_wren, 49 | output wire buf_in_request, 50 | output wire buf_in_ready, 51 | input wire buf_in_commit, 52 | input wire [10:0] buf_in_commit_len, 53 | output wire buf_in_commit_ack, 54 | 55 | input wire [8:0] buf_out_addr, 56 | output wire [31:0] buf_out_q, 57 | output wire [10:0] buf_out_len, 58 | output wire buf_out_hasdata, 59 | input wire buf_out_arm, 60 | output wire buf_out_arm_ack, 61 | 62 | output wire vend_req_act, 63 | output wire [7:0] vend_req_request, 64 | output wire [15:0] vend_req_val, 65 | output wire [5:0] dbg_pipe_state, 66 | output wire [4:0] dbg_ltssm_state 67 | ); 68 | 69 | reg reset_1, reset_2; // local reset 70 | wire local_reset = reset_n & phy_pwrpresent; 71 | 72 | always @(posedge phy_pipe_half_clk ) begin 73 | 74 | // synchronize external reset to local domain 75 | {reset_2, reset_1} <= {reset_1, local_reset}; 76 | 77 | end 78 | 79 | assign phy_reset_n = reset_n; // TUSB1310A has minimum 1uS pulse width for RESET 80 | // responsibility of the toplevel module to supply this reset 81 | // NOTE: reset entire phy will cause loss of PLL lock 82 | assign phy_phy_reset_n = reset_n & phy_pwrpresent; 83 | // reset the PHY along with all our core code if cable unplugged 84 | assign phy_out_enable = 1'b1; 85 | 86 | wire [1:0] mux_tx_margin; 87 | 88 | parameter XTAL_SEL = 1'b0; // crystal input 89 | parameter OSC_SEL = 1'b1; // clock input 90 | parameter [2:0] SSC_DIS = 2'b11; // spread spectrum clock disable 91 | parameter [2:0] SSC_EN = 2'b00; // spread spectrum clock enable 92 | parameter PIPE_16BIT = 1'b0; // sdr 16bit pipe interface 93 | // strap pins 94 | assign phy_rx_elecidle = reset_2 ? 1'bZ : XTAL_SEL; 95 | assign phy_tx_margin = reset_2 ? mux_tx_margin : SSC_DIS; 96 | assign phy_phy_status_o = reset_2 ? 1'bZ : PIPE_16BIT; 97 | 98 | //////////////////////////////////////////////////////////// 99 | // 100 | // USB 3.0 PIPE3 interface 101 | // 102 | //////////////////////////////////////////////////////////// 103 | 104 | wire ltssm_reset_n; 105 | 106 | usb3_pipe iu3p ( 107 | 108 | .slow_clk ( phy_pipe_quarter_clk ), 109 | .local_clk ( phy_pipe_half_clk ), 110 | .local_clk_capture ( phy_pipe_half_clk_phase ), 111 | .reset_n ( reset_2 ), 112 | .ltssm_reset_n ( ltssm_reset_n ), 113 | 114 | .phy_pipe_rx_data ( phy_pipe_rx_data ), 115 | .phy_pipe_rx_datak ( phy_pipe_rx_datak ), 116 | .phy_pipe_rx_valid ( phy_pipe_rx_valid ), 117 | .phy_pipe_tx_data ( phy_pipe_tx_data ), 118 | .phy_pipe_tx_datak ( phy_pipe_tx_datak ), 119 | 120 | .phy_tx_detrx_lpbk ( phy_tx_detrx_lpbk ), 121 | .phy_tx_elecidle ( phy_tx_elecidle ), 122 | .phy_rx_elecidle ( phy_rx_elecidle ), 123 | .phy_rx_status ( phy_rx_status ), 124 | .phy_power_down ( phy_power_down ), 125 | .phy_phy_status ( phy_phy_status_i ), 126 | .phy_pwrpresent ( phy_pwrpresent ), 127 | 128 | .phy_tx_oneszeros ( phy_tx_oneszeros ), 129 | .phy_tx_deemph ( phy_tx_deemph ), 130 | .phy_tx_margin ( mux_tx_margin ), 131 | .phy_tx_swing ( phy_tx_swing ), 132 | .phy_rx_polarity ( phy_rx_polarity ), 133 | .phy_rx_termination ( phy_rx_termination ), 134 | .phy_rate ( phy_rate ), 135 | .phy_elas_buf_mode ( phy_elas_buf_mode ), 136 | 137 | .link_in_data ( link_in_data ), 138 | .link_in_datak ( link_in_datak ), 139 | .link_in_active ( link_in_active ), 140 | .link_out_data ( link_out_data ), 141 | .link_out_datak ( link_out_datak ), 142 | .link_out_active ( link_out_active ), 143 | .link_out_stall ( link_out_stall ), 144 | 145 | .partner_detect ( partner_detect ), 146 | .partner_looking ( partner_looking ), 147 | .partner_detected ( partner_detected ), 148 | 149 | .ltssm_tx_detrx_lpbk ( port_tx_detrx_lpbk ), 150 | .ltssm_tx_elecidle ( port_tx_elecidle ), 151 | .ltssm_power_down ( port_power_down ), 152 | .ltssm_power_go ( port_power_go ), 153 | .ltssm_power_ack ( port_power_ack ), 154 | .ltssm_hot_reset ( ltssm_hot_reset ), 155 | 156 | .ltssm_state ( ltssm_state ), 157 | .ltssm_training ( ltssm_training ), 158 | .ltssm_train_rxeq ( ltssm_train_rxeq ), 159 | .ltssm_train_rxeq_pass ( ltssm_train_rxeq_pass ), 160 | .ltssm_train_active ( ltssm_train_active ), 161 | .ltssm_train_ts1 ( ltssm_train_ts1 ), 162 | .ltssm_train_ts2 ( ltssm_train_ts2 ), 163 | .ltssm_train_config ( ltssm_train_config ), 164 | .ltssm_train_idle ( ltssm_train_idle ), 165 | .ltssm_train_idle_pass ( ltssm_train_idle_pass ), 166 | 167 | .lfps_recv_active ( lfps_recv_active ), 168 | .lfps_recv_poll_u1 ( lfps_recv_poll_u1 ), 169 | .lfps_recv_ping ( lfps_recv_ping ), 170 | .lfps_recv_reset ( lfps_recv_reset ), 171 | .lfps_recv_u2lb ( lfps_recv_u2lb ), 172 | .lfps_recv_u3 ( lfps_recv_u3 ), 173 | .dbg_state ( dbg_pipe_state ) 174 | 175 | ); 176 | 177 | //////////////////////////////////////////////////////////// 178 | // 179 | // USB 3.0 LTSSM, LFPS 180 | // 181 | //////////////////////////////////////////////////////////// 182 | 183 | wire [4:0] ltssm_state; 184 | wire port_rx_term; 185 | wire port_tx_detrx_lpbk; 186 | wire port_tx_elecidle; 187 | 188 | wire [1:0] port_power_down; 189 | wire port_power_go; 190 | wire port_power_ack; 191 | wire port_power_err; 192 | wire ltssm_hot_reset; 193 | 194 | wire ltssm_training; 195 | wire ltssm_train_rxeq; 196 | wire ltssm_train_rxeq_pass; 197 | wire ltssm_train_active; 198 | wire ltssm_train_ts1; 199 | wire ltssm_train_ts2; 200 | wire ltssm_train_config; 201 | wire ltssm_train_idle; 202 | wire ltssm_train_idle_pass; 203 | 204 | wire partner_detect; 205 | wire partner_looking; 206 | wire partner_detected; 207 | 208 | wire lfps_recv_active; 209 | wire lfps_recv_poll_u1; 210 | wire lfps_recv_ping; 211 | wire lfps_recv_reset; 212 | wire lfps_recv_u2lb; 213 | wire lfps_recv_u3; 214 | 215 | wire ltssm_warm_reset; 216 | 217 | usb3_ltssm iu3lt ( 218 | 219 | .slow_clk ( phy_pipe_quarter_clk ), 220 | .local_clk ( phy_pipe_half_clk ), 221 | .reset_n ( ltssm_reset_n ), 222 | 223 | // inputs 224 | .vbus_present ( phy_pwrpresent ), 225 | .port_rx_valid ( phy_pipe_rx_valid ), // these signals are in the 250mhz source 226 | .port_rx_elecidle ( phy_rx_elecidle ), // domain, but no problem for lfps in 62.5mhz 227 | .partner_looking ( partner_looking ), 228 | .partner_detected ( partner_detected ), 229 | .port_power_state ( phy_power_down ), // reflect actual value driven by PIPE pd_fsm 230 | .port_power_ack ( port_power_ack ), 231 | .port_power_err ( port_power_err ), 232 | 233 | .train_rxeq_pass ( ltssm_train_rxeq_pass ), 234 | .train_idle_pass ( ltssm_train_idle_pass ), 235 | .train_ts1 ( ltssm_train_ts1 ), 236 | .train_ts2 ( ltssm_train_ts2 ), 237 | .go_disabled ( ltssm_go_disabled ), 238 | .go_recovery ( ltssm_go_recovery ), 239 | .go_u ( ltssm_go_u ), 240 | .hot_reset ( ltssm_hot_reset ), 241 | 242 | // outputs 243 | .ltssm_state ( ltssm_state ), 244 | .port_rx_term ( port_rx_term ), 245 | .port_tx_detrx_lpbk ( port_tx_detrx_lpbk ), 246 | .port_tx_elecidle ( port_tx_elecidle ), 247 | .port_power_down ( port_power_down ), 248 | .port_power_go ( port_power_go ), 249 | .partner_detect ( partner_detect ), 250 | 251 | .training ( ltssm_training ), 252 | .train_rxeq ( ltssm_train_rxeq ), 253 | .train_active ( ltssm_train_active ), 254 | .train_config ( ltssm_train_config ), 255 | .train_idle ( ltssm_train_idle ), 256 | 257 | .lfps_recv_active ( lfps_recv_active ), 258 | .lfps_recv_poll_u1 ( lfps_recv_poll_u1 ), 259 | .lfps_recv_ping ( lfps_recv_ping ), 260 | .lfps_recv_reset ( lfps_recv_reset ), 261 | .lfps_recv_u2lb ( lfps_recv_u2lb ), 262 | .lfps_recv_u3 ( lfps_recv_u3 ), 263 | 264 | .warm_reset ( ltssm_warm_reset ), 265 | .dbg_state ( dbg_ltssm_state ) 266 | ); 267 | 268 | 269 | //////////////////////////////////////////////////////////// 270 | // 271 | // USB 3.0 Link layer interface 272 | // 273 | //////////////////////////////////////////////////////////// 274 | 275 | wire [31:0] link_in_data; 276 | wire [3:0] link_in_datak; 277 | wire link_in_active; 278 | wire [31:0] link_out_data; 279 | wire [3:0] link_out_datak; 280 | wire link_out_active; 281 | wire link_out_stall; 282 | wire ltssm_go_disabled; 283 | wire ltssm_go_recovery; 284 | wire [2:0] ltssm_go_u; 285 | 286 | usb3_link iu3l ( 287 | 288 | .local_clk ( phy_pipe_half_clk ), 289 | .reset_n ( reset_2 ), 290 | 291 | .ltssm_state ( ltssm_state ), 292 | .ltssm_hot_reset ( ltssm_hot_reset ), 293 | .ltssm_go_disabled ( ltssm_go_disabled ), 294 | .ltssm_go_recovery ( ltssm_go_recovery ), 295 | .ltssm_go_u ( ltssm_go_u), 296 | .in_data ( link_in_data ), 297 | .in_datak ( link_in_datak ), 298 | .in_active ( link_in_active ), 299 | 300 | .outp_data ( link_out_data ), 301 | .outp_datak ( link_out_datak ), 302 | .outp_active ( link_out_active ), 303 | .out_stall ( link_out_stall ), 304 | 305 | .endp_mode_rx ( prot_endp_mode_rx ), 306 | .endp_mode_tx ( prot_endp_mode_tx ), 307 | 308 | .prot_rx_tp ( prot_rx_tp ), 309 | .prot_rx_tp_hosterr ( prot_rx_tp_hosterr ), 310 | .prot_rx_tp_retry ( prot_rx_tp_retry ), 311 | .prot_rx_tp_pktpend ( prot_rx_tp_pktpend ), 312 | .prot_rx_tp_subtype ( prot_rx_tp_subtype ), 313 | .prot_rx_tp_endp ( prot_rx_tp_endp ), 314 | .prot_rx_tp_nump ( prot_rx_tp_nump ), 315 | .prot_rx_tp_seq ( prot_rx_tp_seq ), 316 | .prot_rx_tp_stream ( prot_rx_tp_stream ), 317 | 318 | .prot_rx_dph ( prot_rx_dph ), 319 | .prot_rx_dph_eob ( prot_rx_dph_eob ), 320 | .prot_rx_dph_setup ( prot_rx_dph_setup ), 321 | .prot_rx_dph_pktpend ( prot_rx_dph_pktpend ), 322 | .prot_rx_dph_endp ( prot_rx_dph_endp ), 323 | .prot_rx_dph_seq ( prot_rx_dph_seq ), 324 | .prot_rx_dph_len ( prot_rx_dph_len ), 325 | .prot_rx_dpp_start ( prot_rx_dpp_start ), 326 | .prot_rx_dpp_done ( prot_rx_dpp_done ), 327 | .prot_rx_dpp_crcgood ( prot_rx_dpp_crcgood ), 328 | 329 | .prot_tx_tp_a ( prot_tx_tp_a ), 330 | .prot_tx_tp_a_retry ( prot_tx_tp_a_retry ), 331 | .prot_tx_tp_a_dir ( prot_tx_tp_a_dir ), 332 | .prot_tx_tp_a_subtype ( prot_tx_tp_a_subtype ), 333 | .prot_tx_tp_a_endp ( prot_tx_tp_a_endp ), 334 | .prot_tx_tp_a_nump ( prot_tx_tp_a_nump ), 335 | .prot_tx_tp_a_seq ( prot_tx_tp_a_seq ), 336 | .prot_tx_tp_a_stream ( prot_tx_tp_a_stream ), 337 | .prot_tx_tp_a_ack ( prot_tx_tp_a_ack ), 338 | 339 | .prot_tx_tp_b ( prot_tx_tp_b ), 340 | .prot_tx_tp_b_retry ( prot_tx_tp_b_retry ), 341 | .prot_tx_tp_b_dir ( prot_tx_tp_b_dir ), 342 | .prot_tx_tp_b_subtype ( prot_tx_tp_b_subtype ), 343 | .prot_tx_tp_b_endp ( prot_tx_tp_b_endp ), 344 | .prot_tx_tp_b_nump ( prot_tx_tp_b_nump ), 345 | .prot_tx_tp_b_seq ( prot_tx_tp_b_seq ), 346 | .prot_tx_tp_b_stream ( prot_tx_tp_b_stream ), 347 | .prot_tx_tp_b_ack ( prot_tx_tp_b_ack ), 348 | 349 | .prot_tx_tp_c ( prot_tx_tp_c ), 350 | .prot_tx_tp_c_retry ( prot_tx_tp_c_retry ), 351 | .prot_tx_tp_c_dir ( prot_tx_tp_c_dir ), 352 | .prot_tx_tp_c_subtype ( prot_tx_tp_c_subtype ), 353 | .prot_tx_tp_c_endp ( prot_tx_tp_c_endp ), 354 | .prot_tx_tp_c_nump ( prot_tx_tp_c_nump ), 355 | .prot_tx_tp_c_seq ( prot_tx_tp_c_seq ), 356 | .prot_tx_tp_c_stream ( prot_tx_tp_c_stream ), 357 | .prot_tx_tp_c_ack ( prot_tx_tp_c_ack ), 358 | 359 | .prot_tx_dph ( prot_tx_dph ), 360 | .prot_tx_dph_eob ( prot_tx_dph_eob ), 361 | .prot_tx_dph_dir ( prot_tx_dph_dir ), 362 | .prot_tx_dph_endp ( prot_tx_dph_endp ), 363 | .prot_tx_dph_seq ( prot_tx_dph_seq ), 364 | .prot_tx_dph_len ( prot_tx_dph_len ), 365 | .prot_tx_dpp_ack ( prot_tx_dpp_ack ), 366 | .prot_tx_dpp_done ( prot_tx_dpp_done ), 367 | 368 | .buf_in_addr ( prot_buf_in_addr ), 369 | .buf_in_data ( prot_buf_in_data ), 370 | .buf_in_wren ( prot_buf_in_wren ), 371 | .buf_in_ready ( prot_buf_in_ready ), 372 | .buf_in_commit ( prot_buf_in_commit ), 373 | .buf_in_commit_len ( prot_buf_in_commit_len ), 374 | .buf_in_commit_ack ( prot_buf_in_commit_ack ), 375 | 376 | .buf_out_addr ( prot_buf_out_addr ), 377 | .buf_out_q ( prot_buf_out_q ), 378 | .buf_out_len ( prot_buf_out_len ), 379 | .buf_out_hasdata ( prot_buf_out_hasdata ), 380 | .buf_out_arm ( prot_buf_out_arm ), 381 | .buf_out_arm_ack ( prot_buf_out_arm_ack ), 382 | 383 | // current device address, driven by endpoint 0 384 | .dev_addr ( prot_dev_addr ) 385 | ); 386 | 387 | 388 | 389 | //////////////////////////////////////////////////////////// 390 | // 391 | // USB 3.0 Protocol layer interface 392 | // 393 | //////////////////////////////////////////////////////////// 394 | 395 | //wire [31:0] prot_in_data; 396 | //wire [3:0] prot_in_datak; 397 | //wire prot_in_active; 398 | 399 | wire [1:0] prot_endp_mode_rx; 400 | wire [1:0] prot_endp_mode_tx; 401 | wire [6:0] prot_dev_addr; 402 | wire prot_configured; 403 | 404 | wire prot_rx_tp; 405 | wire prot_rx_tp_hosterr; 406 | wire prot_rx_tp_retry; 407 | wire prot_rx_tp_pktpend; 408 | wire [3:0] prot_rx_tp_subtype; 409 | wire [3:0] prot_rx_tp_endp; 410 | wire [4:0] prot_rx_tp_nump; 411 | wire [4:0] prot_rx_tp_seq; 412 | wire [15:0] prot_rx_tp_stream; 413 | 414 | wire prot_rx_dph; 415 | wire prot_rx_dph_eob; 416 | wire prot_rx_dph_setup; 417 | wire prot_rx_dph_pktpend; 418 | wire [3:0] prot_rx_dph_endp; 419 | wire [4:0] prot_rx_dph_seq; 420 | wire [15:0] prot_rx_dph_len; 421 | wire prot_rx_dpp_start; 422 | wire prot_rx_dpp_done; 423 | wire prot_rx_dpp_crcgood; 424 | 425 | wire prot_tx_tp_a; 426 | wire prot_tx_tp_a_retry; 427 | wire prot_tx_tp_a_dir; 428 | wire [3:0] prot_tx_tp_a_subtype; 429 | wire [3:0] prot_tx_tp_a_endp; 430 | wire [4:0] prot_tx_tp_a_nump; 431 | wire [4:0] prot_tx_tp_a_seq; 432 | wire [15:0] prot_tx_tp_a_stream; 433 | wire prot_tx_tp_a_ack; 434 | 435 | wire prot_tx_tp_b; 436 | wire prot_tx_tp_b_retry; 437 | wire prot_tx_tp_b_dir; 438 | wire [3:0] prot_tx_tp_b_subtype; 439 | wire [3:0] prot_tx_tp_b_endp; 440 | wire [4:0] prot_tx_tp_b_nump; 441 | wire [4:0] prot_tx_tp_b_seq; 442 | wire [15:0] prot_tx_tp_b_stream; 443 | wire prot_tx_tp_b_ack; 444 | 445 | wire prot_tx_tp_c; 446 | wire prot_tx_tp_c_retry; 447 | wire prot_tx_tp_c_dir; 448 | wire [3:0] prot_tx_tp_c_subtype; 449 | wire [3:0] prot_tx_tp_c_endp; 450 | wire [4:0] prot_tx_tp_c_nump; 451 | wire [4:0] prot_tx_tp_c_seq; 452 | wire [15:0] prot_tx_tp_c_stream; 453 | wire prot_tx_tp_c_ack; 454 | 455 | wire prot_tx_dph; 456 | wire prot_tx_dph_eob; 457 | wire prot_tx_dph_dir; 458 | wire [3:0] prot_tx_dph_endp; 459 | wire [4:0] prot_tx_dph_seq; 460 | wire [15:0] prot_tx_dph_len; 461 | wire prot_tx_dpp_ack; 462 | wire prot_tx_dpp_done; 463 | 464 | 465 | wire [8:0] prot_buf_in_addr; 466 | wire [31:0] prot_buf_in_data; 467 | wire prot_buf_in_wren; 468 | wire prot_buf_in_ready; 469 | wire prot_buf_in_commit; 470 | wire [10:0] prot_buf_in_commit_len; 471 | wire prot_buf_in_commit_ack; 472 | 473 | wire [8:0] prot_buf_out_addr; 474 | wire [31:0] prot_buf_out_q; 475 | wire [10:0] prot_buf_out_len; 476 | wire prot_buf_out_hasdata; 477 | wire prot_buf_out_arm; 478 | wire prot_buf_out_arm_ack; 479 | 480 | 481 | 482 | usb3_protocol iu3r ( 483 | 484 | .local_clk ( phy_pipe_half_clk ), 485 | .slow_clk ( phy_pipe_quarter_clk ), 486 | .ext_clk ( ext_clk ), 487 | 488 | .reset_n ( reset_2 | ~ltssm_warm_reset), 489 | .ltssm_state ( ltssm_state ), 490 | 491 | // muxed endpoint signals 492 | .endp_mode_rx ( prot_endp_mode_rx ), 493 | .endp_mode_tx ( prot_endp_mode_tx ), 494 | 495 | .rx_tp ( prot_rx_tp ), 496 | .rx_tp_hosterr ( prot_rx_tp_hosterr ), 497 | .rx_tp_retry ( prot_rx_tp_retry ), 498 | .rx_tp_pktpend ( prot_rx_tp_pktpend ), 499 | .rx_tp_subtype ( prot_rx_tp_subtype ), 500 | .rx_tp_endp ( prot_rx_tp_endp ), 501 | .rx_tp_nump ( prot_rx_tp_nump ), 502 | .rx_tp_seq ( prot_rx_tp_seq ), 503 | .rx_tp_stream ( prot_rx_tp_stream ), 504 | 505 | .rx_dph ( prot_rx_dph ), 506 | .rx_dph_eob ( prot_rx_dph_eob ), 507 | .rx_dph_setup ( prot_rx_dph_setup ), 508 | .rx_dph_pktpend ( prot_rx_dph_pktpend ), 509 | .rx_dph_endp ( prot_rx_dph_endp ), 510 | .rx_dph_seq ( prot_rx_dph_seq ), 511 | .rx_dph_len ( prot_rx_dph_len ), 512 | .rx_dpp_start ( prot_rx_dpp_start ), 513 | .rx_dpp_done ( prot_rx_dpp_done ), 514 | .rx_dpp_crcgood ( prot_rx_dpp_crcgood ), 515 | 516 | .tx_tp_a ( prot_tx_tp_a ), 517 | .tx_tp_a_retry ( prot_tx_tp_a_retry ), 518 | .tx_tp_a_dir ( prot_tx_tp_a_dir ), 519 | .tx_tp_a_subtype ( prot_tx_tp_a_subtype ), 520 | .tx_tp_a_endp ( prot_tx_tp_a_endp ), 521 | .tx_tp_a_nump ( prot_tx_tp_a_nump ), 522 | .tx_tp_a_seq ( prot_tx_tp_a_seq ), 523 | .tx_tp_a_stream ( prot_tx_tp_a_stream ), 524 | .tx_tp_a_ack ( prot_tx_tp_a_ack ), 525 | 526 | .tx_tp_b ( prot_tx_tp_b ), 527 | .tx_tp_b_retry ( prot_tx_tp_b_retry ), 528 | .tx_tp_b_dir ( prot_tx_tp_b_dir ), 529 | .tx_tp_b_subtype ( prot_tx_tp_b_subtype ), 530 | .tx_tp_b_endp ( prot_tx_tp_b_endp ), 531 | .tx_tp_b_nump ( prot_tx_tp_b_nump ), 532 | .tx_tp_b_seq ( prot_tx_tp_b_seq ), 533 | .tx_tp_b_stream ( prot_tx_tp_b_stream ), 534 | .tx_tp_b_ack ( prot_tx_tp_b_ack ), 535 | 536 | .tx_tp_c ( prot_tx_tp_c ), 537 | .tx_tp_c_retry ( prot_tx_tp_c_retry ), 538 | .tx_tp_c_dir ( prot_tx_tp_c_dir ), 539 | .tx_tp_c_subtype ( prot_tx_tp_c_subtype ), 540 | .tx_tp_c_endp ( prot_tx_tp_c_endp ), 541 | .tx_tp_c_nump ( prot_tx_tp_c_nump ), 542 | .tx_tp_c_seq ( prot_tx_tp_c_seq ), 543 | .tx_tp_c_stream ( prot_tx_tp_c_stream ), 544 | .tx_tp_c_ack ( prot_tx_tp_c_ack ), 545 | 546 | .tx_dph ( prot_tx_dph ), 547 | .tx_dph_eob ( prot_tx_dph_eob ), 548 | .tx_dph_dir ( prot_tx_dph_dir ), 549 | .tx_dph_endp ( prot_tx_dph_endp ), 550 | .tx_dph_seq ( prot_tx_dph_seq ), 551 | .tx_dph_len ( prot_tx_dph_len ), 552 | .tx_dpp_ack ( prot_tx_dpp_ack ), 553 | .tx_dpp_done ( prot_tx_dpp_done ), 554 | 555 | .buf_in_addr ( prot_buf_in_addr ), 556 | .buf_in_data ( prot_buf_in_data ), 557 | .buf_in_wren ( prot_buf_in_wren ), 558 | .buf_in_ready ( prot_buf_in_ready ), 559 | .buf_in_commit ( prot_buf_in_commit ), 560 | .buf_in_commit_len ( prot_buf_in_commit_len ), 561 | .buf_in_commit_ack ( prot_buf_in_commit_ack ), 562 | 563 | .buf_out_addr ( prot_buf_out_addr ), 564 | .buf_out_q ( prot_buf_out_q ), 565 | .buf_out_len ( prot_buf_out_len ), 566 | .buf_out_hasdata ( prot_buf_out_hasdata ), 567 | .buf_out_arm ( prot_buf_out_arm ), 568 | .buf_out_arm_ack ( prot_buf_out_arm_ack ), 569 | 570 | // external interface 571 | 572 | .ext_buf_in_addr ( buf_in_addr ), 573 | .ext_buf_in_data ( buf_in_data ), 574 | .ext_buf_in_wren ( buf_in_wren ), 575 | .ext_buf_in_request ( buf_in_request ), 576 | .ext_buf_in_ready ( buf_in_ready ), 577 | .ext_buf_in_commit ( buf_in_commit ), 578 | .ext_buf_in_commit_len ( buf_in_commit_len ), 579 | .ext_buf_in_commit_ack ( buf_in_commit_ack ), 580 | 581 | .ext_buf_out_addr ( buf_out_addr ), 582 | .ext_buf_out_q ( buf_out_q ), 583 | .ext_buf_out_len ( buf_out_len ), 584 | .ext_buf_out_hasdata ( buf_out_hasdata ), 585 | .ext_buf_out_arm ( buf_out_arm ), 586 | .ext_buf_out_arm_ack ( buf_out_arm_ack ), 587 | 588 | .vend_req_act ( vend_req_act ), 589 | .vend_req_request ( vend_req_request ), 590 | .vend_req_val ( vend_req_val ), 591 | 592 | // tell the rest of the USB controller about what 593 | // our current device address is, assigned by host 594 | .dev_addr ( prot_dev_addr ), 595 | .configured ( prot_configured ) 596 | ); 597 | 598 | endmodule 599 | -------------------------------------------------------------------------------- /core/usb3/usb3_ltssm.v: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // usb 3.0 ltssm and lfps 4 | // 5 | // Copyright (c) 2013 Marshall H. 6 | // All rights reserved. 7 | // This code is released under the terms of the simplified BSD license. 8 | // See LICENSE.TXT for details. 9 | // 10 | 11 | module usb3_ltssm ( 12 | 13 | input wire slow_clk, 14 | input wire local_clk, 15 | input wire reset_n, 16 | 17 | input wire vbus_present, 18 | input wire port_rx_valid, 19 | input wire port_rx_elecidle, 20 | input wire [1:0] port_power_state, 21 | output reg port_rx_term, 22 | output reg port_tx_detrx_lpbk, 23 | output reg port_tx_elecidle, 24 | output wire [4:0] ltssm_state, 25 | 26 | input wire partner_looking, 27 | input wire partner_detected, 28 | output reg partner_detect, 29 | 30 | input wire port_power_ack, 31 | input wire port_power_err, 32 | output reg [1:0] port_power_down, 33 | output reg port_power_go, 34 | 35 | output reg training, 36 | output reg train_rxeq, 37 | input wire train_rxeq_pass, 38 | output reg train_active, 39 | input wire train_ts1, 40 | input wire train_ts2, 41 | output reg train_config, 42 | output reg train_idle, 43 | input wire train_idle_pass, 44 | 45 | input wire hot_reset, 46 | input wire go_disabled, 47 | input wire go_recovery, 48 | input wire [2:0] go_u, 49 | 50 | output reg lfps_send_ack, 51 | input wire lfps_send_poll, 52 | input wire lfps_send_ping, 53 | input wire lfps_send_u1, 54 | input wire lfps_send_u2lb, 55 | input wire lfps_send_u3, 56 | 57 | output reg lfps_recv_active, 58 | output reg lfps_recv_poll_u1, 59 | output reg lfps_recv_ping, 60 | output reg lfps_recv_reset, 61 | output reg lfps_recv_u2lb, 62 | output reg lfps_recv_u3, 63 | 64 | output reg warm_reset, 65 | output wire [4:0] dbg_state 66 | 67 | ); 68 | 69 | `include "usb3_const.vh" 70 | 71 | reg vbus_present_1, vbus_present_2; 72 | reg port_rx_elecidle_1, port_rx_elecidle_2; 73 | reg port_rx_valid_1, port_rx_valid_2; 74 | 75 | reg [4:0] state; 76 | assign dbg_state = state; 77 | reg [4:0] lfps_send_state; 78 | reg [4:0] lfps_recv_state; 79 | 80 | reg [24:0] dc; // delay count 81 | reg [4:0] tc; // train count 82 | reg [7:0] tsc; // train send count 83 | //reg [24:0] ic; // interval count 84 | reg [24:0] sc; // send FSM count 85 | reg [24:0] sic; // send internal count 86 | reg [24:0] rc; // receive FSM count 87 | reg [24:0] ric; // receive interval count 88 | 89 | reg lfps_send_poll_local; // OR'd with external LFPS request 90 | reg lfps_send_ping_local; // inputs, so either source may invoke 91 | reg lfps_send_u1_local; // an LFPS transmission 92 | reg lfps_send_u2lb_local; 93 | reg lfps_send_u3_local; 94 | reg lfps_send_reset_local; 95 | 96 | reg lfps_recv_poll_u1_prev; // used to detect these specific two LFPS 97 | reg lfps_recv_ping_prev; // patterns that dictate repeat lengths 98 | 99 | reg [3:0] rx_detect_attempts; 100 | reg [5:0] polling_lfps_sent; 101 | reg [3:0] polling_lfps_received; 102 | reg [3:0] polling_lfps_sent_after_recv; 103 | reg has_trained; 104 | reg go_recovery_latch; 105 | 106 | assign ltssm_state = state; 107 | 108 | always @(posedge slow_clk) begin 109 | 110 | // synchronizers 111 | {vbus_present_2, vbus_present_1} <= {vbus_present_1, vbus_present}; 112 | {port_rx_elecidle_2, port_rx_elecidle_1} <= {port_rx_elecidle_1, port_rx_elecidle}; 113 | {port_rx_valid_2, port_rx_valid_1} <= {port_rx_valid_1, port_rx_valid}; 114 | 115 | // default levels for outputs 116 | port_rx_term <= 1; 117 | port_tx_detrx_lpbk <= 0; 118 | port_tx_elecidle <= 1; 119 | partner_detect <= 0; 120 | port_power_go <= 0; 121 | 122 | training <= 0; 123 | train_rxeq <= 0; 124 | train_active <= 0; 125 | train_config <= 0; 126 | train_idle <= 0; 127 | 128 | lfps_send_ack <= 0; 129 | lfps_send_poll_local <= 0; 130 | lfps_send_ping_local <= 0; 131 | lfps_send_u1_local <= 0; 132 | lfps_send_u2lb_local <= 0; 133 | lfps_send_u3_local <= 0; 134 | lfps_send_reset_local <= 0; 135 | 136 | lfps_recv_active <= 0; 137 | lfps_recv_poll_u1 <= 0; 138 | lfps_recv_ping <= 0; 139 | lfps_recv_reset <= 0; 140 | lfps_recv_u2lb <= 0; 141 | lfps_recv_u3 <= 0; 142 | 143 | warm_reset <= 0; 144 | go_recovery_latch <= go_recovery; 145 | 146 | // counters 147 | `INC(dc); 148 | `INC(sc); 149 | `INC(sic); 150 | `INC(rc); 151 | `INC(ric); 152 | 153 | 154 | /////////////////////////////////////// 155 | // LTSSM FSM 156 | /////////////////////////////////////// 157 | case(state) 158 | LT_SS_DISABLED: begin 159 | port_power_down <= POWERDOWN_2; 160 | port_power_go <= 1; 161 | //port_rx_term <= 0; 162 | 163 | //if(lfps_recv_reset) state <= LT_RX_DETECT_RESET; 164 | end 165 | LT_SS_INACTIVE: begin 166 | // reset timeout counter and drop to P2 if not already 167 | dc <= 0; 168 | port_power_down <= POWERDOWN_2; 169 | port_power_go <= 1; 170 | if(port_power_ack) state <= LT_SS_INACTIVE_QUIET; 171 | end 172 | LT_SS_INACTIVE_QUIET: begin 173 | if(dc == T_SS_INACTIVE_QUIET) begin 174 | state <= LT_SS_INACTIVE_DETECT_0; 175 | end 176 | end 177 | LT_SS_INACTIVE_DETECT_0: begin 178 | partner_detect <= 1; 179 | if(partner_looking) state <= LT_SS_INACTIVE_DETECT_1; 180 | end 181 | LT_SS_INACTIVE_DETECT_1: begin 182 | dc <= 0; 183 | if(~partner_looking) begin 184 | if(partner_detected) begin 185 | // we're still connected to the host, continue waiting for unplug 186 | state <= LT_SS_INACTIVE_QUIET; 187 | end else begin 188 | // disconnect, start looking for new host 189 | state <= LT_RX_DETECT_RESET; 190 | end 191 | end 192 | end 193 | 194 | LT_RX_DETECT_RESET: begin 195 | // IF WARM RESET: 196 | // finish transmitting LFPS.Reset until the duration 197 | // is reached. (TODO) 198 | rx_detect_attempts <= 0; 199 | state <= LT_RX_DETECT_ACTIVE_0; 200 | end 201 | LT_RX_DETECT_ACTIVE_0: begin 202 | partner_detect <= 1; 203 | if(partner_looking) state <= LT_RX_DETECT_ACTIVE_1; 204 | end 205 | LT_RX_DETECT_ACTIVE_1: begin 206 | if(~partner_looking) begin 207 | dc <= 0; 208 | if(partner_detected) begin 209 | // far-end termination detected 210 | polling_lfps_sent <= 0; 211 | polling_lfps_received <= 0; 212 | polling_lfps_sent_after_recv <= 0; 213 | state <= LT_POLLING_LFPS; 214 | end else begin 215 | // not found 216 | `INC(rx_detect_attempts); 217 | if(rx_detect_attempts == 7) begin 218 | state <= LT_SS_DISABLED; 219 | end else begin 220 | state <= LT_RX_DETECT_QUIET; 221 | end 222 | end 223 | end 224 | end 225 | LT_RX_DETECT_QUIET: begin 226 | // wait a bit, then run the farend detection again 227 | if(dc == T_RX_DETECT_QUIET) begin 228 | state <= LT_RX_DETECT_ACTIVE_0; 229 | end 230 | end 231 | LT_POLLING_LFPS: begin 232 | lfps_send_poll_local <= 1; 233 | 234 | // receiving Polling.LFPS from link partner 235 | if(lfps_recv_poll_u1) begin 236 | if(polling_lfps_received < 15) 237 | `INC(polling_lfps_received); 238 | end 239 | 240 | // confirmed LFPS fsm sent 241 | if(lfps_send_ack) begin 242 | if(polling_lfps_sent_after_recv < 15 && polling_lfps_received > 0) 243 | `INC(polling_lfps_sent_after_recv); 244 | if(polling_lfps_sent < 20) 245 | `INC(polling_lfps_sent); 246 | end 247 | 248 | // exit conditions 249 | if( polling_lfps_sent_after_recv >= 4 && 250 | polling_lfps_sent >= 16 && 251 | polling_lfps_received >= 2) begin 252 | 253 | // done 254 | lfps_send_poll_local <= 0; 255 | state <= LT_POLLING_RXEQ_0; 256 | end 257 | 258 | if(dc == T_POLLING_LFPS) begin 259 | // timed out 260 | if(has_trained) state <= LT_SS_DISABLED; 261 | dc <= 0; 262 | end 263 | end 264 | LT_POLLING_RXEQ_0: begin 265 | // wait for any straggling LFPS sends to clear 266 | dc <= 0; 267 | if(lfps_send_state == LFPS_IDLE) state <= LT_POLLING_RXEQ_1; 268 | end 269 | LT_POLLING_RXEQ_1: begin 270 | port_power_down <= POWERDOWN_0; 271 | port_power_go <= 1; 272 | 273 | // maintain values, unless overridden below 274 | training <= 1; 275 | train_rxeq <= train_rxeq; 276 | 277 | // wait until P0 powerdown is entered so that 278 | // the transceiver proper is ready 279 | if(port_power_ack) begin 280 | // signal to PIPE module, TSEQ 65536 send 281 | train_rxeq <= 1; 282 | end 283 | if(train_rxeq_pass) begin 284 | // reset timeout count and proceed 285 | dc <= 0; 286 | tc <= 0; 287 | state <= LT_POLLING_ACTIVE; 288 | end 289 | end 290 | LT_POLLING_ACTIVE: begin 291 | // send TS1 until 8 consecutive TS are received 292 | training <= 1; 293 | train_active <= 1; 294 | 295 | if(train_ts1 | train_ts2) `INC(tc); 296 | 297 | if(tc == 8) begin 298 | // received 8 consecutive(TODO?) TS1/TS2 299 | // reset timeout count and proceed 300 | dc <= 0; 301 | tc <= 0; 302 | tsc <= 0; 303 | state <= LT_POLLING_CONFIG; 304 | end 305 | 306 | // timeout 307 | if(dc == T_POLLING_ACTIVE) state <= LT_SS_DISABLED; 308 | end 309 | LT_POLLING_CONFIG: begin 310 | training <= 1; 311 | train_config <= 1; 312 | 313 | // increment TS2 receive count up to 8 314 | if(train_ts2) begin 315 | if(tc < 8) `INC(tc); 316 | end 317 | // increment TS2 send count, sequence is 2 cycles long 318 | if(tc > 0) if(tsc < 16*2) `INC(tsc); 319 | 320 | // exit criteria 321 | // received 8 and sent 16 322 | if(tc == 8 && tsc == 16*2) begin 323 | // reset timeout count and proceed 324 | dc <= 0; 325 | tc <= 0; 326 | tsc <= 0; 327 | state <= LT_POLLING_IDLE; 328 | end 329 | 330 | // timeout 331 | if(dc == T_POLLING_CONFIG) state <= LT_SS_DISABLED; 332 | end 333 | LT_POLLING_IDLE: begin 334 | training <= 1; 335 | train_idle <= 1; 336 | 337 | if(train_idle_pass) begin 338 | // exit conditions: 339 | // 16 IDLE symbol sent after receiving 340 | // first of at least 8 symbols. 341 | dc <= 0; 342 | if(hot_reset) 343 | state <= LT_HOTRESET; 344 | else 345 | state <= LT_U0; 346 | end 347 | 348 | // timeout 349 | if(dc == T_POLLING_IDLE) state <= LT_SS_DISABLED; 350 | end 351 | LT_U0: begin 352 | // N.B. relevant LTSSM timeouts were moved to the Link Layer 353 | // module since it is more practical to have them there, and not here 354 | 355 | if(train_ts1) begin 356 | // TS1 detected, go to Recovery 357 | state <= LT_RECOVERY; 358 | end else 359 | if(go_recovery_latch) begin 360 | // link layer had a problem, Recovery 361 | state <= LT_RECOVERY; 362 | end else 363 | if(go_u == 3'b101) begin 364 | // link layer requests U1 365 | port_power_down <= POWERDOWN_1; 366 | port_power_go <= 1; 367 | if(port_power_ack) begin 368 | dc <= 0; 369 | state <= LT_U1; 370 | end 371 | end else 372 | if(go_u == 3'b110) begin 373 | // link layer requests U2 374 | port_power_down <= POWERDOWN_2; 375 | port_power_go <= 1; 376 | if(port_power_ack) state <= LT_U2; 377 | end 378 | if(go_u == 3'b111) begin 379 | // link layer requests U3 380 | port_power_down <= POWERDOWN_2; // our clock depends on PHY so don't suicide 381 | port_power_go <= 1; 382 | if(port_power_ack) state <= LT_U3; 383 | end 384 | end 385 | LT_U1: begin 386 | // U1 power saving state 387 | // PIPE module should turn off its bus and only use LFPS to resume 388 | 389 | if(lfps_recv_poll_u1) begin 390 | lfps_send_u1_local <= 1; 391 | end else 392 | //if(lfps_recv_u2lb ) begin 393 | // lfps_send_u2lb_local <= 1; 394 | //end else 395 | if(lfps_send_ack) begin 396 | state <= LT_RECOVERY; 397 | end else 398 | if(go_u == 3'b110) begin 399 | // link layer requests U2 400 | port_power_down <= POWERDOWN_2; 401 | port_power_go <= 1; 402 | if(port_power_ack) state <= LT_U2; 403 | end else 404 | if(dc == LFPS_BURST_PING_NOM) begin 405 | // send Ping.LFPS every 200ms 406 | dc <= 0; 407 | lfps_send_ping_local <= 1; 408 | end 409 | end 410 | LT_U2: begin 411 | // U2 power saving state 412 | 413 | if(lfps_recv_u2lb) begin 414 | lfps_send_u2lb_local <= 1; 415 | end 416 | if(lfps_send_ack) begin 417 | state <= LT_RECOVERY; 418 | end 419 | end 420 | LT_U3: begin 421 | // U3 power saving state 422 | 423 | if(lfps_recv_u3) begin 424 | lfps_send_u3_local <= 1; 425 | end 426 | if(lfps_send_ack) begin 427 | state <= LT_RECOVERY; 428 | end 429 | end 430 | 431 | LT_RECOVERY: begin 432 | dc <= -10; 433 | state <= LT_RECOVERY_WAIT; 434 | end 435 | LT_RECOVERY_WAIT: begin 436 | if(dc == 0) begin 437 | dc <= 0; 438 | tc <= 0; 439 | tsc <= 0; 440 | 441 | port_power_down <= POWERDOWN_0; 442 | port_power_go <= 1; 443 | 444 | if(port_power_ack) state <= LT_RECOVERY_ACTIVE; 445 | end 446 | end 447 | LT_RECOVERY_ACTIVE: begin 448 | // send TS1 until 8 consecutive TS are received 449 | training <= 1; 450 | train_active <= 1; 451 | 452 | if(train_ts1 | train_ts2) `INC(tc); 453 | 454 | if(tc == 8) begin 455 | // received 8 consecutive(TODO?) TS1/TS2 456 | // reset timeout count and proceed 457 | dc <= 0; 458 | tc <= 0; 459 | tsc <= 0; 460 | state <= LT_RECOVERY_CONFIG; 461 | end 462 | 463 | if(dc == T_RECOV_ACTIVE) state <= LT_SS_INACTIVE; 464 | end 465 | LT_RECOVERY_CONFIG: begin 466 | training <= 1; 467 | train_config <= 1; 468 | 469 | // increment TS2 receive count up to 8 470 | if(train_ts2) begin 471 | if(tc < 8) `INC(tc); 472 | end 473 | // increment TS2 send count, sequence is 2 cycles long 474 | // (remember we are in 62.5mhz domain, not 125mhz link) 475 | if(tc > 0) if(tsc < 16*2) `INC(tsc); 476 | 477 | // exit criteria 478 | // received 8 and sent 16 479 | if(tc == 8 && tsc == 16*2) begin 480 | // reset timeout count and proceed 481 | dc <= 0; 482 | tc <= 0; 483 | tsc <= 0; 484 | state <= LT_RECOVERY_IDLE; 485 | end 486 | 487 | if(dc == T_RECOV_CONFIG) state <= LT_SS_INACTIVE; 488 | end 489 | LT_RECOVERY_IDLE: begin 490 | training <= 1; 491 | train_idle <= 1; 492 | 493 | if(train_idle_pass) begin 494 | // exit conditions: 495 | // 16 IDLE symbol sent after receiving 496 | // first of at least 8 symbols. 497 | dc <= 0; 498 | if(hot_reset) 499 | state <= LT_HOTRESET; 500 | else 501 | state <= LT_U0; 502 | end 503 | 504 | if(dc == T_RECOV_IDLE) state <= LT_SS_INACTIVE; 505 | end 506 | 507 | LT_COMPLIANCE: begin 508 | end 509 | LT_LOOPBACK: begin 510 | end 511 | LT_HOTRESET: begin 512 | // reset Link Error Count is done by Link Layer 513 | if(dc == 3) state <= LT_HOTRESET_ACTIVE; 514 | end 515 | LT_HOTRESET_ACTIVE: begin 516 | state <= LT_HOTRESET_EXIT; 517 | end 518 | LT_HOTRESET_EXIT: begin 519 | state <= LT_U0; 520 | end 521 | LT_RESET: begin 522 | port_rx_term <= 0; 523 | port_power_down <= POWERDOWN_2; 524 | has_trained <= 0; 525 | state <= LT_RX_DETECT_RESET; 526 | end 527 | default: state <= LT_RESET; 528 | endcase 529 | 530 | 531 | 532 | /////////////////////////////////////// 533 | // LFPS SEND FSM 534 | /////////////////////////////////////// 535 | case(lfps_send_state) 536 | LFPS_RESET: begin 537 | lfps_send_state <= LFPS_IDLE; 538 | end 539 | LFPS_IDLE: begin 540 | if(!training) begin // port_rx_elecidle_2 && 541 | // clear to go 542 | if(lfps_send_poll | lfps_send_poll_local) begin 543 | // Polling.LFPS 544 | sc <= LFPS_POLLING_NOM; 545 | sic <= LFPS_BURST_POLL_NOM; 546 | lfps_send_state <= LFPS_SEND_1; 547 | end else if(lfps_send_ping | lfps_send_ping_local) begin 548 | // Ping.LFPS 549 | sc <= LFPS_PING_NOM; 550 | sic <= LFPS_BURST_PING_NOM; 551 | lfps_send_state <= LFPS_SEND_1; 552 | end else if(lfps_send_u1 | lfps_send_u1_local) begin 553 | // U1 Exit 554 | sc <= LFPS_U1EXIT_NOM; 555 | sic <= LFPS_U1EXIT_NOM; 556 | lfps_send_state <= LFPS_SEND_1; 557 | end else if(lfps_send_u2lb | lfps_send_u2lb_local) begin 558 | // U2 Exit 559 | sc <= LFPS_U2LBEXIT_NOM; 560 | sic <= LFPS_U2LBEXIT_NOM; 561 | lfps_send_state <= LFPS_SEND_1; 562 | end else if(lfps_send_u3 | lfps_send_u3_local) begin 563 | // U3 Exit 564 | sc <= LFPS_U3WAKEUP_NOM; 565 | sic <= LFPS_U3WAKEUP_NOM; 566 | lfps_send_state <= LFPS_SEND_1; 567 | end 568 | end 569 | if(lfps_send_reset_local) begin 570 | // WarmReset 571 | lfps_send_state <= LFPS_SEND_1; 572 | end 573 | end 574 | LFPS_SEND_1: begin 575 | // decide how to send LFPS based on power state 576 | if(port_power_state == POWERDOWN_0) begin 577 | port_tx_elecidle <= 1; 578 | port_tx_detrx_lpbk <= 1; 579 | end else begin 580 | port_tx_elecidle <= 0; 581 | end 582 | // decrement pulse width and repeat interval 583 | `DEC(sc); 584 | `DEC(sic); 585 | if(sc == 1) lfps_send_state <= LFPS_SEND_2; 586 | 587 | if(lfps_send_reset_local) begin 588 | // special case here -- WarmReset must be ack'd 589 | // and in response send LFPS until it's deasserted by host 590 | lfps_send_state <= lfps_send_state; 591 | // catch the rising edge 592 | if(port_rx_elecidle_2) begin 593 | lfps_send_state <= LFPS_IDLE; 594 | end 595 | end 596 | end 597 | LFPS_SEND_2: begin 598 | // decrement repeat interval 599 | `DEC(sic); 600 | if(sic == 0) begin 601 | lfps_send_ack <= 1; 602 | lfps_send_state <= LFPS_IDLE; 603 | end 604 | end 605 | LFPS_SEND_3: begin 606 | // keep 607 | end 608 | default: lfps_send_state <= LFPS_RESET; 609 | endcase 610 | 611 | 612 | 613 | /////////////////////////////////////// 614 | // LFPS RECEIVE FSM 615 | /////////////////////////////////////// 616 | case(lfps_recv_state) 617 | LFPS_RESET: begin 618 | lfps_recv_state <= LFPS_IDLE; 619 | lfps_recv_poll_u1_prev <= 0; 620 | lfps_recv_ping_prev <= 0; 621 | end 622 | LFPS_IDLE: begin 623 | // lfps burst begin 624 | if(~port_rx_elecidle_2 & ~port_rx_valid_2) begin 625 | rc <= 0; 626 | lfps_recv_state <= LFPS_RECV_1; 627 | end 628 | end 629 | LFPS_RECV_1: begin 630 | // lfps burst end 631 | 632 | // detect WarmReset by seeing if LFPS continues past tResetDelay 633 | if(rc > LFPS_RESET_DELAY) begin 634 | // want to send LFPS to signal we acknowledge the WarmReset 635 | // N.B. per spec this is not acceptable during SS.Disabled 636 | if(~port_rx_elecidle_2) lfps_send_reset_local <= 1; 637 | end 638 | 639 | if(rc == LFPS_U1EXIT_MIN) begin 640 | // link partner is sending U1Exit handshake, reciprocate 641 | lfps_recv_active <= 1; 642 | lfps_recv_poll_u1 <= 1; 643 | end 644 | 645 | if(rc == LFPS_U2LBEXIT_MIN) begin 646 | // link partner is sending U2/LBExit handshake, reciprocate 647 | lfps_recv_active <= 1; 648 | lfps_recv_u2lb <= 1; 649 | end 650 | 651 | if(rc == LFPS_U3WAKEUP_MIN) begin 652 | // link partner is sending U3 wakeup, reciprocate 653 | lfps_recv_active <= 1; 654 | lfps_recv_u3 <= 1; 655 | end 656 | 657 | // wait for rising edge 658 | if(port_rx_elecidle_2) begin 659 | lfps_recv_state <= LFPS_IDLE; 660 | lfps_recv_active <= 1; 661 | 662 | // reset these by default 663 | lfps_recv_poll_u1_prev <= 0; 664 | lfps_recv_ping_prev <= 0; 665 | 666 | ric <= 0; 667 | 668 | if(rc >= LFPS_POLLING_MIN && rc < LFPS_POLLING_MAX) begin 669 | // Polling.LFPS (or U1.Exit) 670 | if(lfps_recv_poll_u1_prev) begin 671 | // we've received this once already 672 | // now check burst length parameters 673 | if(ric >= LFPS_BURST_POLL_MIN && ric < LFPS_BURST_POLL_MAX) 674 | lfps_recv_poll_u1 <= 1; 675 | end else 676 | lfps_recv_active <= 0; 677 | 678 | lfps_recv_poll_u1_prev <= 1; 679 | ric <= 0; 680 | end else if(rc >= LFPS_PING_MIN && rc < LFPS_PING_MAX) begin 681 | // Ping.LFPS 682 | if(lfps_recv_ping_prev) begin 683 | // we've received this once already 684 | // now check burst length parameters 685 | if(ric >= LFPS_BURST_PING_MIN && ric < LFPS_BURST_PING_MAX) 686 | lfps_recv_ping <= 1; 687 | end else 688 | lfps_recv_active <= 0; 689 | 690 | lfps_recv_ping_prev <= 1; 691 | ric <= 0; 692 | end else if(rc >= LFPS_RESET_MIN && rc < LFPS_RESET_MAX) begin 693 | // WarmReset 694 | lfps_recv_reset <= 1; 695 | //end else if(rc >= LFPS_U1EXIT_MIN && rc < LFPS_U1EXIT_MAX) begin 696 | // U1.Exit 697 | // lfps_recv_poll_u1 <= 1; 698 | //end else if(rc >= LFPS_U2LBEXIT_MIN && rc < LFPS_U2LBEXIT_MAX) begin 699 | // U2/Loopback.Exit 700 | // lfps_recv_u2lb <= 1; 701 | //end else if(rc >= LFPS_U3WAKEUP_MIN && rc < LFPS_U3WAKEUP_MAX) begin 702 | // U3.Wakeup 703 | // lfps_recv_u3 <= 1; 704 | end else begin 705 | // invalid burst 706 | //lfps_recv_state <= LFPS_IDLE; 707 | lfps_recv_active <= 0; 708 | end 709 | end 710 | end 711 | LFPS_RECV_2: begin 712 | // just wait for end of host LFPS to squelch generation of erroneous transfers 713 | if(port_rx_elecidle_2) begin 714 | ric <= 0; 715 | lfps_recv_state <= LFPS_IDLE; 716 | end 717 | end 718 | LFPS_RECV_3: begin 719 | end 720 | default: lfps_recv_state <= LFPS_RESET; 721 | endcase 722 | 723 | if(go_disabled) begin 724 | // SS.Disabled 725 | state <= LT_SS_DISABLED; 726 | end 727 | 728 | //if(hot_reset && state != LT_SS_DISABLED) begin 729 | // Hot Reset (TS2 Reset bit) 730 | // dc <= 0; 731 | // state <= LT_HOTRESET; 732 | //end 733 | 734 | if(lfps_recv_reset && state != LT_SS_DISABLED) begin 735 | // Warm Reset (LFPS) 736 | warm_reset <= 1; 737 | state <= LT_RX_DETECT_RESET; 738 | end 739 | 740 | if(~reset_n | ~vbus_present_2) begin 741 | // reset 742 | state <= LT_RESET; 743 | lfps_send_state <= LFPS_RESET; 744 | lfps_recv_state <= LFPS_RESET; 745 | end 746 | end 747 | 748 | endmodule 749 | --------------------------------------------------------------------------------