├── Software └── SPI_Flasher │ ├── CMakeLists.txt │ ├── spi_flasher.h │ ├── spi_flasher.c │ └── main.c ├── UCF ├── numato_saturn6_main.ucf ├── numato_saturn6_flash.ucf ├── numato_saturn6_dbg.ucf └── numato_saturn6_ulpi.ucf ├── LICENSE ├── Extra ├── extra_pkg.vhdl ├── blk_ep_out_ctl.vhdl ├── sync_fifo.vhdl ├── blk_ep_in_ctl.vhdl └── usb_flasher.vhdl ├── Xilinx_IP ├── blk_in_fifo │ ├── blk_in_fifo.xise │ └── blk_in_fifo.xco └── blk_out_fifo │ ├── blk_out_fifo.xise │ └── blk_out_fifo.xco ├── Test └── usb_flasher_tb.vhdl ├── Examples ├── EP1_Loopback │ └── ep1_loopback.vhdl └── SPI_Flasher │ └── spi_flasher.vhdl └── Core ├── core_pkg.vhdl ├── ulpi_port.vhdl ├── usb_std_request.vhdl ├── usb_packet.vhdl ├── usb_tlp.vhdl └── usb_xfer.vhdl /Software/SPI_Flasher/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT(SPI_Flasher) 2 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 3 | 4 | INCLUDE_DIRECTORIES( 5 | /usr/include/libusb-1.0 6 | ) 7 | 8 | ADD_EXECUTABLE(usbcore_spi_flasher main.c spi_flasher.c) 9 | TARGET_LINK_LIBRARIES(usbcore_spi_flasher usb-1.0) -------------------------------------------------------------------------------- /UCF/numato_saturn6_main.ucf: -------------------------------------------------------------------------------- 1 | # Constraints for Numato Saturn - Spartan 6 FPGA Development Board with DDR SDRAM 2 | # http://numato.com/fpga-boards/xilinx/spartan6/saturn-spartan-6-fpga-development-board-with-ddr-sdram.html 3 | # Main constraints 4 | 5 | NET "main_clk" PERIOD = 10 ns; 6 | 7 | NET "main_clk" IOSTANDARD = LVTTL; 8 | 9 | NET "main_clk" LOC = V10; 10 | -------------------------------------------------------------------------------- /UCF/numato_saturn6_flash.ucf: -------------------------------------------------------------------------------- 1 | # Constraints for Numato Saturn - Spartan 6 FPGA Development Board with DDR SDRAM 2 | # http://numato.com/fpga-boards/xilinx/spartan6/saturn-spartan-6-fpga-development-board-with-ddr-sdram.html 3 | # SPI flash constraints 4 | 5 | NET "spi_cs" IOSTANDARD = LVTTL; 6 | NET "spi_sck" IOSTANDARD = LVTTL; 7 | NET "spi_mosi" IOSTANDARD = LVTTL; 8 | NET "spi_miso" IOSTANDARD = LVTTL; 9 | 10 | NET "spi_cs" LOC = V3; 11 | NET "spi_sck" LOC = R15; 12 | NET "spi_mosi" LOC = T13; 13 | NET "spi_miso" LOC = R13; 14 | -------------------------------------------------------------------------------- /UCF/numato_saturn6_dbg.ucf: -------------------------------------------------------------------------------- 1 | # Constraints for Numato Saturn - Spartan 6 FPGA Development Board with DDR SDRAM 2 | # http://numato.com/fpga-boards/xilinx/spartan6/saturn-spartan-6-fpga-development-board-with-ddr-sdram.html 3 | # Openbench Logic Sniffer 4 | 5 | NET "dbg[0]" LOC = J13; 6 | NET "dbg[1]" LOC = H13; 7 | NET "dbg[2]" LOC = G16; 8 | NET "dbg[3]" LOC = F17; 9 | NET "dbg[4]" LOC = D17; 10 | NET "dbg[5]" LOC = B16; 11 | NET "dbg[6]" LOC = D14; 12 | NET "dbg[7]" LOC = F13; 13 | NET "dbg[8]" LOC = F12; 14 | NET "dbg[9]" LOC = B12; 15 | NET "dbg[10]" LOC = D11; 16 | NET "dbg[11]" LOC = B11; 17 | NET "dbg[12]" LOC = G9; 18 | NET "dbg[13]" LOC = B9; 19 | NET "dbg[14]" LOC = E7; 20 | 21 | NET "dbg_clk" LOC = C11; 22 | NET "dbg_trig" LOC = A12; 23 | -------------------------------------------------------------------------------- /UCF/numato_saturn6_ulpi.ucf: -------------------------------------------------------------------------------- 1 | # Constraints for Numato Saturn - Spartan 6 FPGA Development Board with DDR SDRAM 2 | # http://numato.com/fpga-boards/xilinx/spartan6/saturn-spartan-6-fpga-development-board-with-ddr-sdram.html 3 | # ULPI shield constraints 4 | 5 | NET "ulpi_clk60" PERIOD = 16666 ps; 6 | 7 | NET "ulpi_data[*]" IOSTANDARD = LVTTL; 8 | NET "ulpi_clk60" IOSTANDARD = LVTTL; 9 | NET "ulpi_dir" IOSTANDARD = LVTTL; 10 | NET "ulpi_nxt" IOSTANDARD = LVTTL; 11 | NET "ulpi_reset" IOSTANDARD = LVTTL; 12 | NET "ulpi_stp" IOSTANDARD = LVTTL; 13 | NET "led" IOSTANDARD = LVTTL; 14 | 15 | NET "ulpi_clk60" LOC = R8; 16 | NET "ulpi_data[0]" LOC = T4; 17 | NET "ulpi_data[1]" LOC = V4; 18 | NET "ulpi_data[2]" LOC = U5; 19 | NET "ulpi_data[3]" LOC = V5; 20 | NET "ulpi_data[4]" LOC = T6; 21 | NET "ulpi_data[5]" LOC = V6; 22 | NET "ulpi_data[6]" LOC = N6; 23 | NET "ulpi_data[7]" LOC = P7; 24 | NET "ulpi_stp" LOC = V8; 25 | NET "ulpi_dir" LOC = U8; 26 | NET "ulpi_nxt" LOC = N8; 27 | NET "ulpi_reset" LOC = M8; 28 | NET "led" LOC = T8; 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Konstantin Oblaukhov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Software/SPI_Flasher/spi_flasher.h: -------------------------------------------------------------------------------- 1 | /* 2 | * USB Full-Speed/Hi-Speed Device Controller core - SPI Flasher Utility 3 | * 4 | * Copyright (c) 2015 Konstantin Oblaukhov 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #ifndef SPI_FLAHSER_H 26 | #define SPI_FLAHSER_H 27 | 28 | #include 29 | #include 30 | 31 | #define USB_CTL_TYPE 0x40 32 | 33 | #define USB_TIMEOUT 1000 34 | 35 | #define REQ_TYPE_WRITE 0x00 36 | #define REQ_TYPE_READ 0x01 37 | #define REQ_TYPE_PAGE_WRITE 0x02 38 | #define REQ_TYPE_PAGE_READ 0x03 39 | 40 | #define REQ_COMMAND 0x04 41 | #define REQ_PROGRAM 0x05 42 | #define REQ_READ 0x06 43 | 44 | int flash_command(libusb_device_handle* dev, uint8_t direction, uint8_t command, uint8_t *data, int length); 45 | int flash_wait(libusb_device_handle* dev); 46 | int flash_write_enable(libusb_device_handle* dev); 47 | 48 | int flash_erase_sector(libusb_device_handle* dev, uint8_t sector_addr); 49 | int flash_write_data(libusb_device_handle* dev, uint32_t address, uint8_t *data, int length); 50 | int flash_program(libusb_device_handle* dev, uint32_t address, uint8_t *data, int length); 51 | 52 | int flash_read_page(libusb_device_handle* dev, uint32_t address, uint8_t *data); 53 | int flash_read(libusb_device_handle* dev, uint32_t address, uint8_t *data, int length); 54 | 55 | #endif -------------------------------------------------------------------------------- /Extra/extra_pkg.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - extra_pkg.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.all; 27 | use IEEE.STD_LOGIC_UNSIGNED.all; 28 | use IEEE.NUMERIC_STD.all; 29 | 30 | library work; 31 | use work.USBCore.all; 32 | 33 | package USBExtra is 34 | component blk_ep_out_ctl is 35 | generic ( 36 | USE_ASYNC_FIFO : boolean := false 37 | ); 38 | port ( 39 | rst : in std_logic; 40 | usb_clk : in std_logic; 41 | axis_clk : in std_logic; 42 | 43 | blk_out_xfer : in std_logic; 44 | 45 | blk_xfer_out_ready_read : out std_logic; 46 | blk_xfer_out_data : in std_logic_vector(7 downto 0); 47 | blk_xfer_out_data_valid : in std_logic; 48 | 49 | axis_tdata : out std_logic_vector(7 downto 0); 50 | axis_tvalid : out std_logic; 51 | axis_tready : in std_logic; 52 | axis_tlast : out std_logic 53 | ); 54 | end component; 55 | 56 | component blk_ep_in_ctl is 57 | generic ( 58 | USE_ASYNC_FIFO : boolean := false 59 | ); 60 | port ( 61 | rst : in std_logic; 62 | usb_clk : in std_logic; 63 | axis_clk : in std_logic; 64 | 65 | blk_in_xfer : in std_logic; 66 | 67 | blk_xfer_in_has_data : out std_logic; 68 | blk_xfer_in_data : out std_logic_vector(7 downto 0); 69 | blk_xfer_in_data_valid : out std_logic; 70 | blk_xfer_in_data_ready : in std_logic; 71 | blk_xfer_in_data_last : out std_logic; 72 | 73 | axis_tdata : in std_logic_vector(7 downto 0); 74 | axis_tvalid : in std_logic; 75 | axis_tready : out std_logic; 76 | axis_tlast : in std_logic 77 | ); 78 | end component; 79 | 80 | component sync_fifo 81 | generic ( 82 | constant FIFO_WIDTH : positive; 83 | constant FIFO_DEPTH : positive; 84 | constant PROG_FULL_VALUE: positive 85 | ); 86 | port ( 87 | clk : in std_logic; 88 | rst : in std_logic; 89 | 90 | s_axis_tvalid : in std_logic; 91 | s_axis_tready : out std_logic; 92 | s_axis_tdata : in std_logic_vector(7 downto 0); 93 | s_axis_tlast : in std_logic; 94 | 95 | m_axis_tvalid : out std_logic; 96 | m_axis_tready : in std_logic; 97 | m_axis_tdata : out std_logic_vector(7 downto 0); 98 | m_axis_tlast : out std_logic; 99 | 100 | prog_full : out std_logic 101 | ); 102 | end component; 103 | end USBExtra; -------------------------------------------------------------------------------- /Extra/blk_ep_out_ctl.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - blk_ep_out_ctl.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.ALL; 27 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 28 | use IEEE.NUMERIC_STD.ALL; 29 | 30 | library work; 31 | use work.USBCore.all; 32 | use work.USBExtra.all; 33 | 34 | entity blk_ep_out_ctl is 35 | generic ( 36 | USE_ASYNC_FIFO : boolean := false 37 | ); 38 | port ( 39 | rst : in std_logic; 40 | usb_clk : in std_logic; 41 | axis_clk : in std_logic; 42 | 43 | blk_out_xfer : in std_logic; 44 | 45 | blk_xfer_out_ready_read : out std_logic; 46 | blk_xfer_out_data : in std_logic_vector(7 downto 0); 47 | blk_xfer_out_data_valid : in std_logic; 48 | 49 | axis_tdata : out std_logic_vector(7 downto 0); 50 | axis_tvalid : out std_logic; 51 | axis_tready : in std_logic; 52 | axis_tlast : out std_logic 53 | ); 54 | end blk_ep_out_ctl; 55 | 56 | architecture blk_ep_out_ctl of blk_ep_out_ctl is 57 | component blk_out_fifo 58 | port ( 59 | m_aclk : in std_logic; 60 | s_aclk : in std_logic; 61 | 62 | s_aresetn : in std_logic; 63 | 64 | s_axis_tvalid : in std_logic; 65 | s_axis_tready : out std_logic; 66 | s_axis_tdata : in std_logic_vector(7 downto 0); 67 | 68 | m_axis_tvalid : out std_logic; 69 | m_axis_tready : in std_logic; 70 | m_axis_tdata : out std_logic_vector(7 downto 0); 71 | 72 | axis_prog_full : out std_logic 73 | ); 74 | end component; 75 | 76 | signal s_axis_tvalid : std_logic; 77 | signal s_axis_tready : std_logic; 78 | signal s_axis_tdata : std_logic_vector(7 downto 0); 79 | 80 | signal prog_full : std_logic; 81 | begin 82 | FULL_LATCH: process(usb_clk) is 83 | begin 84 | if rising_edge(usb_clk) then 85 | blk_xfer_out_ready_read <= NOT prog_full; 86 | end if; 87 | end process; 88 | 89 | ASYNC: if USE_ASYNC_FIFO generate 90 | FIFO: blk_out_fifo 91 | port map ( 92 | m_aclk => axis_clk, 93 | s_aclk => usb_clk, 94 | 95 | s_aresetn => NOT rst, 96 | 97 | s_axis_tvalid => blk_xfer_out_data_valid, 98 | s_axis_tready => open, 99 | s_axis_tdata => blk_xfer_out_data, 100 | 101 | m_axis_tvalid => axis_tvalid, 102 | m_axis_tready => axis_tready, 103 | m_axis_tdata => axis_tdata, 104 | 105 | axis_prog_full => prog_full 106 | ); 107 | end generate; 108 | 109 | SYNC: if not USE_ASYNC_FIFO generate 110 | FIFO: sync_fifo 111 | generic map ( 112 | FIFO_WIDTH => 8, 113 | FIFO_DEPTH => 1024, 114 | PROG_FULL_VALUE => 960 115 | ) 116 | port map ( 117 | clk => usb_clk, 118 | rst => rst, 119 | 120 | s_axis_tvalid => blk_xfer_out_data_valid, 121 | s_axis_tready => open, 122 | s_axis_tdata => blk_xfer_out_data, 123 | s_axis_tlast => '0', 124 | 125 | m_axis_tvalid => axis_tvalid, 126 | m_axis_tready => axis_tready, 127 | m_axis_tdata => axis_tdata, 128 | m_axis_tlast => open, 129 | 130 | prog_full => prog_full 131 | ); 132 | end generate; 133 | 134 | axis_tlast <= '0'; 135 | 136 | end blk_ep_out_ctl; -------------------------------------------------------------------------------- /Xilinx_IP/blk_in_fifo/blk_in_fifo.xise: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
74 | -------------------------------------------------------------------------------- /Xilinx_IP/blk_out_fifo/blk_out_fifo.xise: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
74 | -------------------------------------------------------------------------------- /Software/SPI_Flasher/spi_flasher.c: -------------------------------------------------------------------------------- 1 | /* 2 | * USB Full-Speed/Hi-Speed Device Controller core - SPI Flasher Utility 3 | * 4 | * Copyright (c) 2015 Konstantin Oblaukhov 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "spi_flasher.h" 26 | #include "string.h" 27 | 28 | int flash_command(libusb_device_handle* dev, uint8_t type, uint8_t command, uint8_t *data, int length) 29 | { 30 | int res = -1; 31 | 32 | if (type == REQ_TYPE_PAGE_WRITE) 33 | res = libusb_control_transfer(dev, USB_CTL_TYPE, REQ_PROGRAM, command, 0x0000, data, length, USB_TIMEOUT); 34 | else if (type == REQ_TYPE_PAGE_READ) 35 | res = libusb_control_transfer(dev, USB_CTL_TYPE, REQ_READ, command, 0x0000, data, length, USB_TIMEOUT); 36 | else if (type == REQ_TYPE_WRITE) 37 | res = libusb_control_transfer(dev, USB_CTL_TYPE, REQ_COMMAND, command, 0x0000, data, length, USB_TIMEOUT); 38 | else if (type == REQ_TYPE_READ) 39 | res = libusb_control_transfer(dev, 0x80 | USB_CTL_TYPE, REQ_COMMAND, command, 0x0000, data, length, USB_TIMEOUT); 40 | 41 | return res > 0 ? 0 : res; 42 | } 43 | 44 | int flash_wait(libusb_device_handle* dev) 45 | { 46 | unsigned char reg = 0xFF; 47 | int res; 48 | 49 | while (reg & 0x01) 50 | { 51 | res = flash_command(dev, REQ_TYPE_READ, 0x05, ®, 1); 52 | if (res) 53 | return res; 54 | } 55 | return 0; 56 | } 57 | 58 | int flash_write_enable(libusb_device_handle* dev) 59 | { 60 | flash_command(dev, REQ_TYPE_WRITE, 0x06, 0, 0); 61 | } 62 | 63 | int flash_erase_sector(libusb_device_handle* dev, uint8_t sector_addr) 64 | { 65 | unsigned char addr[3] = {sector_addr, 0x00, 0x00}; 66 | int res; 67 | 68 | res = flash_write_enable(dev); 69 | if (res) 70 | return res; 71 | 72 | res = flash_command(dev, REQ_TYPE_WRITE, 0xD8, addr, 3); 73 | if (res) 74 | return res; 75 | 76 | res = flash_wait(dev); 77 | if (res) 78 | return res; 79 | return 0; 80 | } 81 | 82 | int flash_write_data(libusb_device_handle* dev, uint32_t address, uint8_t *data, int length) 83 | { 84 | unsigned char addr[3]; 85 | int transferred; 86 | int sended = 0; 87 | int res; 88 | 89 | while (sended < length) 90 | { 91 | int current_addr = address + sended; 92 | int chunk_size = length - sended > 256 ? 256 : length - sended; 93 | 94 | if (((current_addr & 0xFF) != 0) && ((current_addr & 0xFF) + chunk_size > 256)) 95 | chunk_size -= current_addr & 0xFF; 96 | 97 | addr[0] = (current_addr >> 16) & 0xff; 98 | addr[1] = (current_addr >> 8) & 0xff; 99 | addr[2] = current_addr & 0xff; 100 | 101 | res = flash_write_enable(dev); 102 | if (res) 103 | return res; 104 | 105 | res = libusb_bulk_transfer(dev, 0x01, data + sended, chunk_size, &transferred, 1000); 106 | if (res) 107 | return res; 108 | 109 | if (transferred != chunk_size) 110 | return -1; 111 | 112 | res = flash_command(dev, REQ_TYPE_PAGE_WRITE, 0x02, addr, 3); 113 | if (res) 114 | return res; 115 | 116 | res = flash_wait(dev); 117 | if (res) 118 | return res; 119 | 120 | sended += chunk_size; 121 | } 122 | return 0; 123 | } 124 | 125 | int flash_program(libusb_device_handle* dev, uint32_t address, uint8_t *data, int length) 126 | { 127 | int sector_count = (length - 1) / 65536 + 1; 128 | int offset = 0; 129 | int i; 130 | int res; 131 | 132 | for (i = 0; i < sector_count; i++) 133 | { 134 | int write_size = (i == sector_count - 1) ? (length % 65536) : 65536; 135 | offset = i << 16; 136 | 137 | res = flash_erase_sector(dev, ((address >> 16) + i) & 0xFF); 138 | if (res) 139 | return res; 140 | 141 | res = flash_write_data(dev, address + offset, data + offset, write_size); 142 | if (res) 143 | return res; 144 | } 145 | return 0; 146 | } 147 | 148 | int flash_read_page(libusb_device_handle* dev, uint32_t address, uint8_t *data) 149 | { 150 | unsigned char addr[3] = {(address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff}; 151 | int transferred; 152 | int res; 153 | 154 | res = flash_command(dev, REQ_TYPE_PAGE_READ, 0x03, addr, 3); 155 | if (res) 156 | return res; 157 | 158 | res = libusb_bulk_transfer(dev, 0x81, data, 256, &transferred, 1000); 159 | if (res) 160 | return res; 161 | 162 | if (transferred != 256) 163 | return -1; 164 | 165 | return 0; 166 | } 167 | 168 | int flash_read(libusb_device_handle* dev, uint32_t address, uint8_t *data, int length) 169 | { 170 | char pagebuf[256]; 171 | int readed = 0; 172 | int res; 173 | 174 | while (readed < length) 175 | { 176 | uint32_t cur_addr = address + readed; 177 | res = flash_read_page(dev, cur_addr, pagebuf); 178 | if (res) 179 | return res; 180 | 181 | int copy_size = (length - readed > 256) ? 256 : length - readed; 182 | memcpy(data + readed, pagebuf, copy_size); 183 | readed += copy_size; 184 | } 185 | return 0; 186 | } 187 | 188 | -------------------------------------------------------------------------------- /Extra/sync_fifo.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - sync_fifo.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- Copyright (c) 2015 daniel@deathbylogic.com 6 | -- http://www.deathbylogic.com/2015/01/vhdl-first-word-fall-through-fifo/ 7 | -- 8 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 9 | -- of this software and associated documentation files (the "Software"), to deal 10 | -- in the Software without restriction, including without limitation the rights 11 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | -- copies of the Software, and to permit persons to whom the Software is 13 | -- furnished to do so, subject to the following conditions: 14 | -- 15 | -- The above copyright notice and this permission notice shall be included in 16 | -- all copies or substantial portions of the Software. 17 | -- 18 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | -- THE SOFTWARE. 25 | -- 26 | 27 | library IEEE; 28 | use IEEE.STD_LOGIC_1164.all; 29 | use IEEE.NUMERIC_STD.all; 30 | 31 | library work; 32 | use work.USBCore.all; 33 | 34 | entity sync_fifo is 35 | generic ( 36 | constant FIFO_WIDTH : positive := 8; 37 | constant FIFO_DEPTH : positive := 256; 38 | constant PROG_FULL_VALUE: positive := 128 39 | ); 40 | port ( 41 | clk : in std_logic; 42 | rst : in std_logic; 43 | 44 | s_axis_tvalid : in std_logic; 45 | s_axis_tready : out std_logic; 46 | s_axis_tdata : in std_logic_vector(FIFO_WIDTH - 1 downto 0); 47 | s_axis_tlast : in std_logic; 48 | 49 | m_axis_tvalid : out std_logic; 50 | m_axis_tready : in std_logic; 51 | m_axis_tdata : out std_logic_vector(FIFO_WIDTH - 1 downto 0); 52 | m_axis_tlast : out std_logic; 53 | 54 | prog_full : out std_logic 55 | ); 56 | end sync_fifo; 57 | 58 | architecture sync_fifo of sync_fifo is 59 | type FIFO_MEMORY is array (0 to FIFO_DEPTH - 1) of std_logic_vector (FIFO_WIDTH downto 0); 60 | signal memory : FIFO_MEMORY; 61 | 62 | subtype ADDRESS_TYPE is natural range 0 to FIFO_DEPTH - 1; 63 | 64 | signal rd_addr : ADDRESS_TYPE; 65 | signal wr_addr : ADDRESS_TYPE; 66 | 67 | signal mem_we : std_logic; 68 | signal mem_in : std_logic_vector(FIFO_WIDTH downto 0); 69 | signal mem_out : std_logic_vector(FIFO_WIDTH downto 0); 70 | 71 | signal buf_we : std_logic; 72 | signal buf : std_logic_vector(FIFO_WIDTH downto 0); 73 | signal buf_valid : std_logic; 74 | 75 | signal full : std_logic; 76 | signal empty : std_logic; 77 | signal empty_d : std_logic; 78 | signal empty_dd : std_logic; 79 | signal looped : std_logic; 80 | 81 | signal count : ADDRESS_TYPE; 82 | 83 | signal first : std_logic; 84 | begin 85 | -- That structure guaranteed that dual-port BRAM will be inferred. 86 | -- At least on Xilinx... 87 | mem_we <= '1' when s_axis_tvalid = '1' and full = '0' else 88 | '0'; 89 | mem_in <= s_axis_tlast & s_axis_tdata; 90 | 91 | MEM_PROC: process(clk) is 92 | begin 93 | if rising_edge(clk) then 94 | mem_out <= memory(rd_addr); 95 | if mem_we = '1' then 96 | memory(wr_addr) <= mem_in; 97 | end if; 98 | end if; 99 | end process; 100 | 101 | -- Sync empty signal with memory reading 102 | EMPTY_OUT: process(clk) is 103 | begin 104 | if rising_edge(clk) then 105 | empty_d <= empty; 106 | empty_dd <= empty_d; 107 | end if; 108 | end process; 109 | 110 | FWFT_BUF: process(clk) is 111 | begin 112 | if rising_edge(clk) then 113 | if rst = '1' then 114 | buf_valid <= '0'; 115 | else 116 | if buf_we = '1' then 117 | buf <= mem_out; 118 | buf_valid <= '1'; 119 | elsif buf_valid = '1' and m_axis_tready = '1' then 120 | buf_valid <= '0'; 121 | end if; 122 | end if; 123 | end if; 124 | end process; 125 | 126 | 127 | 128 | FIFO_PROC: process(clk) is 129 | begin 130 | if rising_edge(clk) then 131 | if rst = '1' then 132 | wr_addr <= 0; 133 | rd_addr <= 0; 134 | looped <= '0'; 135 | else 136 | if mem_we = '1' then 137 | if wr_addr = FIFO_DEPTH - 1 then 138 | wr_addr <= 0; 139 | looped <= '1'; 140 | else 141 | wr_addr <= wr_addr + 1; 142 | end if; 143 | end if; 144 | if (empty = '0' and m_axis_tready = '1') or first = '1' then 145 | if rd_addr = FIFO_DEPTH - 1 then 146 | rd_addr <= 0; 147 | looped <= '0'; 148 | else 149 | rd_addr <= rd_addr + 1; 150 | end if; 151 | end if; 152 | if buf_valid = '1' then 153 | if count >= PROG_FULL_VALUE - 1 then 154 | prog_full <= '1'; 155 | else 156 | prog_full <= '0'; 157 | end if; 158 | else 159 | if count >= PROG_FULL_VALUE then 160 | prog_full <= '1'; 161 | else 162 | prog_full <= '0'; 163 | end if; 164 | end if; 165 | end if; 166 | end if; 167 | end process; 168 | 169 | count <= FIFO_DEPTH - rd_addr + wr_addr when looped = '1' else 170 | wr_addr - rd_addr; 171 | 172 | first <= '1' when empty_d = '0' and buf_valid = '0' and empty_dd = '1' else 173 | '0'; 174 | 175 | buf_we <= '1' when first = '1' else 176 | '1' when empty_d = '0' and buf_valid = '0' and m_axis_tready = '0' else 177 | '0'; 178 | 179 | full <= '1' when looped = '1' AND wr_addr = rd_addr else 180 | '0'; 181 | 182 | empty <= '1' when looped = '0' AND wr_addr = rd_addr else 183 | '0'; 184 | 185 | m_axis_tdata <= buf(FIFO_WIDTH - 1 downto 0) when buf_valid = '1' else 186 | mem_out(FIFO_WIDTH - 1 downto 0); 187 | m_axis_tlast <= buf(FIFO_WIDTH) when buf_valid = '1' else 188 | mem_out(FIFO_WIDTH); 189 | m_axis_tvalid <= (((NOT empty_dd) AND (NOT empty_d)) OR buf_valid); 190 | 191 | s_axis_tready <= NOT full; 192 | end sync_fifo; 193 | -------------------------------------------------------------------------------- /Extra/blk_ep_in_ctl.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - blk_ep_in_ctl.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.ALL; 27 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 28 | use IEEE.NUMERIC_STD.ALL; 29 | 30 | library work; 31 | use work.USBCore.all; 32 | use work.USBExtra.all; 33 | 34 | entity blk_ep_in_ctl is 35 | generic ( 36 | USE_ASYNC_FIFO : boolean := false 37 | ); 38 | port ( 39 | rst : in std_logic; 40 | usb_clk : in std_logic; 41 | axis_clk : in std_logic; 42 | 43 | blk_in_xfer : in std_logic; 44 | 45 | blk_xfer_in_has_data : out std_logic; 46 | blk_xfer_in_data : out std_logic_vector(7 downto 0); 47 | blk_xfer_in_data_valid : out std_logic; 48 | blk_xfer_in_data_ready : in std_logic; 49 | blk_xfer_in_data_last : out std_logic; 50 | 51 | axis_tdata : in std_logic_vector(7 downto 0); 52 | axis_tvalid : in std_logic; 53 | axis_tready : out std_logic; 54 | axis_tlast : in std_logic 55 | ); 56 | end blk_ep_in_ctl; 57 | 58 | architecture blk_ep_in_ctl of blk_ep_in_ctl is 59 | component blk_in_fifo 60 | port ( 61 | m_aclk : in std_logic; 62 | s_aclk : in std_logic; 63 | 64 | s_aresetn : in std_logic; 65 | 66 | s_axis_tvalid : in std_logic; 67 | s_axis_tready : out std_logic; 68 | s_axis_tdata : in std_logic_vector(7 downto 0); 69 | s_axis_tlast : in std_logic; 70 | 71 | m_axis_tvalid : out std_logic; 72 | m_axis_tready : in std_logic; 73 | m_axis_tdata : out std_logic_vector(7 downto 0); 74 | m_axis_tlast : in std_logic; 75 | 76 | axis_prog_full : out std_logic 77 | ); 78 | end component; 79 | 80 | type MACHINE is (S_Idle, S_Xfer); 81 | signal state : MACHINE := S_Idle; 82 | 83 | signal s_axis_tvalid : std_logic; 84 | signal s_axis_tready : std_logic; 85 | signal s_axis_tdata : std_logic_vector(7 downto 0); 86 | signal s_axis_tlast : std_logic; 87 | 88 | signal m_axis_tvalid : std_logic; 89 | signal m_axis_tready : std_logic; 90 | signal m_axis_tdata : std_logic_vector(7 downto 0); 91 | signal m_axis_tlast : std_logic; 92 | 93 | signal prog_full : std_logic; 94 | 95 | signal was_last_usb : std_logic; 96 | signal was_last : std_logic; 97 | signal was_last_d : std_logic; 98 | signal was_last_dd : std_logic; 99 | begin 100 | FSM: process(usb_clk) is 101 | begin 102 | if rst = '1' then 103 | state <= S_Idle; 104 | blk_xfer_in_has_data <= '0'; 105 | elsif rising_edge(usb_clk) then 106 | case state is 107 | when S_Idle => 108 | if was_last_usb = '1' OR prog_full = '1' then 109 | blk_xfer_in_has_data <= '1'; 110 | end if; 111 | if blk_in_xfer = '1' then 112 | state <= S_Xfer; 113 | end if; 114 | 115 | when S_Xfer => 116 | if blk_in_xfer = '0' then 117 | blk_xfer_in_has_data <= '0'; 118 | state <= S_Idle; 119 | end if; 120 | end case; 121 | end if; 122 | end process; 123 | 124 | ASYNC: if USE_ASYNC_FIFO generate 125 | -- 3 of data clk => axis_clk < 180 MHz if usb_clk = 60 MHz 126 | was_last_usb <= was_last OR was_last_d OR was_last_dd; 127 | 128 | FIFO: blk_in_fifo 129 | port map ( 130 | m_aclk => usb_clk, 131 | s_aclk => axis_clk, 132 | 133 | s_aresetn => NOT rst, 134 | 135 | s_axis_tvalid => s_axis_tvalid, 136 | s_axis_tready => s_axis_tready, 137 | s_axis_tdata => s_axis_tdata, 138 | s_axis_tlast => s_axis_tlast, 139 | 140 | m_axis_tvalid => m_axis_tvalid, 141 | m_axis_tready => m_axis_tready, 142 | m_axis_tdata => m_axis_tdata, 143 | m_axis_tlast => m_axis_tlast, 144 | 145 | axis_prog_full => prog_full 146 | ); 147 | end generate; 148 | 149 | SYNC: if not USE_ASYNC_FIFO generate 150 | was_last_usb <= was_last; 151 | 152 | FIFO: sync_fifo 153 | generic map ( 154 | FIFO_WIDTH => 8, 155 | FIFO_DEPTH => 1024, 156 | PROG_FULL_VALUE => 64 157 | ) 158 | port map ( 159 | clk => usb_clk, 160 | rst => rst, 161 | 162 | s_axis_tvalid => s_axis_tvalid, 163 | s_axis_tready => s_axis_tready, 164 | s_axis_tdata => s_axis_tdata, 165 | s_axis_tlast => s_axis_tlast, 166 | 167 | m_axis_tvalid => m_axis_tvalid, 168 | m_axis_tready => m_axis_tready, 169 | m_axis_tdata => m_axis_tdata, 170 | m_axis_tlast => m_axis_tlast, 171 | 172 | prog_full => prog_full 173 | ); 174 | end generate; 175 | 176 | WAS_LAST_LATCHER: process(axis_clk) is 177 | begin 178 | if rst = '1' then 179 | was_last <= '0'; 180 | was_last_d <= '0'; 181 | was_last_dd <= '0'; 182 | elsif rising_edge(axis_clk) then 183 | if s_axis_tvalid = '1' AND s_axis_tready = '1' AND s_axis_tlast = '1' then 184 | was_last <= '1'; 185 | elsif s_axis_tvalid = '1' AND s_axis_tready = '1' AND s_axis_tlast = '0' then 186 | was_last <= '0'; 187 | end if; 188 | was_last_d <= was_last; 189 | was_last_dd <= was_last_d; 190 | end if; 191 | end process; 192 | 193 | s_axis_tdata <= axis_tdata; 194 | s_axis_tvalid <= axis_tvalid; 195 | axis_tready <= s_axis_tready; 196 | s_axis_tlast <= axis_tlast; 197 | 198 | blk_xfer_in_data <= m_axis_tdata; 199 | blk_xfer_in_data_valid <= m_axis_tvalid; 200 | m_axis_tready <= blk_xfer_in_data_ready; 201 | blk_xfer_in_data_last <= m_axis_tlast; 202 | 203 | end blk_ep_in_ctl; -------------------------------------------------------------------------------- /Software/SPI_Flasher/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * USB Full-Speed/Hi-Speed Device Controller core - SPI Flasher Utility 3 | * 4 | * Copyright (c) 2015 Konstantin Oblaukhov 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | #include "spi_flasher.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | int main(int argc, char **argv) 33 | { 34 | if (argc < 3) 35 | { 36 | printf("Usage: spi_flasher [options] \n"); 37 | printf("Options are:\n"); 38 | printf(" -r: read flash content\n"); 39 | printf(" -w: program flash\n"); 40 | printf(" -a : start address of flash\n"); 41 | printf(" -s : read/write size\n"); 42 | printf(" -e : device vendor id (in HEX)\n"); 43 | printf(" -p : device product id (in HEX)\n"); 44 | printf(" -f: don't verify flash content after writing\n"); 45 | printf(" -v: verbose output\n"); 46 | return 0; 47 | } 48 | 49 | char opt; 50 | 51 | char cmd = 0; 52 | uint32_t addr = 0; 53 | int size = 0; 54 | uint16_t vid = 0xdead, pid = 0xbeef; 55 | int force = 0; 56 | int verbose = 0; 57 | 58 | while ((opt = getopt(argc, argv, "rwa:s:e:p:fv")) != -1) 59 | { 60 | switch (opt) 61 | { 62 | case 'r': 63 | cmd = 'r'; 64 | break; 65 | case 'w': 66 | cmd = 'w'; 67 | break; 68 | case 'a': 69 | addr = strtol(optarg, NULL, 0); 70 | break; 71 | case 's': 72 | size = strtol(optarg, NULL, 0); 73 | break; 74 | case 'e': 75 | vid = strtol(optarg, NULL, 16); 76 | break; 77 | case 'p': 78 | pid = strtol(optarg, NULL, 16); 79 | break; 80 | case 'f': 81 | force = 1; 82 | break; 83 | case 'v': 84 | verbose = 1; 85 | break; 86 | } 87 | } 88 | 89 | if (!cmd) 90 | { 91 | printf("Please specify command (-r or -w)"); 92 | return 0; 93 | } 94 | 95 | if (optind >= argc) 96 | { 97 | printf("Please specify file"); 98 | return 0; 99 | } 100 | 101 | libusb_context *usb; 102 | libusb_init(&usb); 103 | 104 | libusb_device_handle* dev; 105 | dev = libusb_open_device_with_vid_pid(usb, vid, pid); 106 | 107 | if (!dev) 108 | { 109 | printf("Cannot open usb device\n"); 110 | return -1; 111 | } 112 | 113 | libusb_claim_interface(dev, 0); 114 | 115 | int ret; 116 | 117 | if (cmd == 'w') 118 | { 119 | FILE *inf = fopen(argv[optind], "rb"); 120 | if (!inf) 121 | { 122 | printf("Cannot open input file\n"); 123 | return -1; 124 | } 125 | 126 | if (!size) 127 | { 128 | fseek(inf, 0, SEEK_END); 129 | size = ftell(inf); 130 | fseek(inf, 0, SEEK_SET); 131 | } 132 | 133 | uint8_t *data = malloc(size); 134 | 135 | ret = fread(data, size, 1, inf); 136 | if (ret != 1) 137 | { 138 | printf("Cannot read input file\n"); 139 | free(data); 140 | fclose(inf); 141 | return -1; 142 | } 143 | fclose(inf); 144 | 145 | printf("Programming flash (%d sectors, %d pages)...\n", ((size - 1) >> 16) + 1, ((size - 1) >> 8) + 1); 146 | if ((ret = flash_program(dev, addr, data, size)) != 0) 147 | { 148 | printf("Cannot program flash: %s\n", libusb_error_name(ret)); 149 | free(data); 150 | return -1; 151 | } 152 | 153 | if (!force) 154 | { 155 | uint8_t *rdata = malloc(size); 156 | 157 | printf("Reading data from flash...\n"); 158 | if ((ret = flash_read(dev, addr, rdata, size)) != 0) 159 | { 160 | printf("Cannot read flash: %s\n", libusb_error_name(ret)); 161 | free(rdata); 162 | free(data); 163 | return -1; 164 | } 165 | 166 | int i; 167 | 168 | printf("Compare...\n"); 169 | for (i = 0; i < size; i++) 170 | { 171 | if (data[i] != rdata[i]) 172 | { 173 | printf("Flash compare error at 0x%x: 0x%x != 0x%x\n", i, data[i], rdata[i]); 174 | free(rdata); 175 | free(data); 176 | return -1; 177 | } 178 | } 179 | free(rdata); 180 | } 181 | free(data); 182 | } 183 | else 184 | { 185 | if (!size) 186 | { 187 | printf("Please specify size for reading\n"); 188 | return 0; 189 | } 190 | 191 | uint8_t *data = malloc(size); 192 | 193 | printf("Reading data from flash (%d pages)...\n", ((size - 1) >> 8) + 1); 194 | if ((ret = flash_read(dev, addr, data, size)) != 0) 195 | { 196 | printf("Cannot read flash: %s\n", libusb_error_name(ret)); 197 | free(data); 198 | return -1; 199 | } 200 | 201 | FILE *outf = fopen(argv[optind], "wb"); 202 | if (!outf) 203 | { 204 | printf("Cannot open output file\n"); 205 | return -1; 206 | } 207 | 208 | ret = fwrite(data, size, 1, outf); 209 | if (ret != 1) 210 | { 211 | printf("Cannot write to output file\n"); 212 | free(data); 213 | fclose(outf); 214 | return -1; 215 | } 216 | 217 | free(data); 218 | fclose(outf); 219 | } 220 | printf("Done!\n"); 221 | 222 | libusb_close(dev); 223 | libusb_exit(usb); 224 | return 0; 225 | } 226 | -------------------------------------------------------------------------------- /Xilinx_IP/blk_in_fifo/blk_in_fifo.xco: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # Xilinx Core Generator version 14.7 4 | # Date: Sun Mar 29 12:59:19 2015 5 | # 6 | ############################################################## 7 | # 8 | # This file contains the customisation parameters for a 9 | # Xilinx CORE Generator IP GUI. It is strongly recommended 10 | # that you do not manually alter this file as it may cause 11 | # unexpected and unsupported behavior. 12 | # 13 | ############################################################## 14 | # 15 | # Generated from component: xilinx.com:ip:fifo_generator:9.3 16 | # 17 | ############################################################## 18 | # 19 | # BEGIN Project Options 20 | SET addpads = false 21 | SET asysymbol = true 22 | SET busformat = BusFormatAngleBracketNotRipped 23 | SET createndf = false 24 | SET designentry = VHDL 25 | SET device = xc6slx16 26 | SET devicefamily = spartan6 27 | SET flowvendor = Other 28 | SET formalverification = false 29 | SET foundationsym = false 30 | SET implementationfiletype = Ngc 31 | SET package = csg324 32 | SET removerpms = false 33 | SET simulationfiles = Behavioral 34 | SET speedgrade = -2 35 | SET verilogsim = false 36 | SET vhdlsim = true 37 | # END Project Options 38 | # BEGIN Select 39 | SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3 40 | # END Select 41 | # BEGIN Parameters 42 | CSET add_ngc_constraint_axi=false 43 | CSET almost_empty_flag=false 44 | CSET almost_full_flag=false 45 | CSET aruser_width=1 46 | CSET awuser_width=1 47 | CSET axi_address_width=32 48 | CSET axi_data_width=64 49 | CSET axi_type=AXI4_Stream 50 | CSET axis_type=FIFO 51 | CSET buser_width=1 52 | CSET clock_enable_type=Slave_Interface_Clock_Enable 53 | CSET clock_type_axi=Independent_Clock 54 | CSET component_name=blk_in_fifo 55 | CSET data_count=false 56 | CSET data_count_width=10 57 | CSET disable_timing_violations=false 58 | CSET disable_timing_violations_axi=false 59 | CSET dout_reset_value=0 60 | CSET empty_threshold_assert_value=2 61 | CSET empty_threshold_assert_value_axis=1021 62 | CSET empty_threshold_assert_value_rach=13 63 | CSET empty_threshold_assert_value_rdch=1021 64 | CSET empty_threshold_assert_value_wach=13 65 | CSET empty_threshold_assert_value_wdch=1021 66 | CSET empty_threshold_assert_value_wrch=13 67 | CSET empty_threshold_negate_value=3 68 | CSET enable_aruser=false 69 | CSET enable_awuser=false 70 | CSET enable_buser=false 71 | CSET enable_common_overflow=false 72 | CSET enable_common_underflow=false 73 | CSET enable_data_counts_axis=false 74 | CSET enable_data_counts_rach=false 75 | CSET enable_data_counts_rdch=false 76 | CSET enable_data_counts_wach=false 77 | CSET enable_data_counts_wdch=false 78 | CSET enable_data_counts_wrch=false 79 | CSET enable_ecc=false 80 | CSET enable_ecc_axis=false 81 | CSET enable_ecc_rach=false 82 | CSET enable_ecc_rdch=false 83 | CSET enable_ecc_wach=false 84 | CSET enable_ecc_wdch=false 85 | CSET enable_ecc_wrch=false 86 | CSET enable_read_channel=false 87 | CSET enable_read_pointer_increment_by2=false 88 | CSET enable_reset_synchronization=true 89 | CSET enable_ruser=false 90 | CSET enable_tdata=true 91 | CSET enable_tdest=false 92 | CSET enable_tid=false 93 | CSET enable_tkeep=false 94 | CSET enable_tlast=true 95 | CSET enable_tready=true 96 | CSET enable_tstrobe=false 97 | CSET enable_tuser=false 98 | CSET enable_write_channel=false 99 | CSET enable_wuser=false 100 | CSET fifo_application_type_axis=Data_FIFO 101 | CSET fifo_application_type_rach=Data_FIFO 102 | CSET fifo_application_type_rdch=Data_FIFO 103 | CSET fifo_application_type_wach=Data_FIFO 104 | CSET fifo_application_type_wdch=Data_FIFO 105 | CSET fifo_application_type_wrch=Data_FIFO 106 | CSET fifo_implementation=Common_Clock_Block_RAM 107 | CSET fifo_implementation_axis=Independent_Clocks_Block_RAM 108 | CSET fifo_implementation_rach=Independent_Clocks_Distributed_RAM 109 | CSET fifo_implementation_rdch=Independent_Clocks_Block_RAM 110 | CSET fifo_implementation_wach=Independent_Clocks_Distributed_RAM 111 | CSET fifo_implementation_wdch=Independent_Clocks_Block_RAM 112 | CSET fifo_implementation_wrch=Independent_Clocks_Distributed_RAM 113 | CSET full_flags_reset_value=1 114 | CSET full_threshold_assert_value=1022 115 | CSET full_threshold_assert_value_axis=64 116 | CSET full_threshold_assert_value_rach=15 117 | CSET full_threshold_assert_value_rdch=1023 118 | CSET full_threshold_assert_value_wach=15 119 | CSET full_threshold_assert_value_wdch=1023 120 | CSET full_threshold_assert_value_wrch=15 121 | CSET full_threshold_negate_value=1021 122 | CSET id_width=4 123 | CSET inject_dbit_error=false 124 | CSET inject_dbit_error_axis=false 125 | CSET inject_dbit_error_rach=false 126 | CSET inject_dbit_error_rdch=false 127 | CSET inject_dbit_error_wach=false 128 | CSET inject_dbit_error_wdch=false 129 | CSET inject_dbit_error_wrch=false 130 | CSET inject_sbit_error=false 131 | CSET inject_sbit_error_axis=false 132 | CSET inject_sbit_error_rach=false 133 | CSET inject_sbit_error_rdch=false 134 | CSET inject_sbit_error_wach=false 135 | CSET inject_sbit_error_wdch=false 136 | CSET inject_sbit_error_wrch=false 137 | CSET input_data_width=18 138 | CSET input_depth=1024 139 | CSET input_depth_axis=1024 140 | CSET input_depth_rach=16 141 | CSET input_depth_rdch=1024 142 | CSET input_depth_wach=16 143 | CSET input_depth_wdch=1024 144 | CSET input_depth_wrch=16 145 | CSET interface_type=AXI4 146 | CSET output_data_width=18 147 | CSET output_depth=1024 148 | CSET overflow_flag=false 149 | CSET overflow_flag_axi=false 150 | CSET overflow_sense=Active_High 151 | CSET overflow_sense_axi=Active_High 152 | CSET performance_options=Standard_FIFO 153 | CSET programmable_empty_type=No_Programmable_Empty_Threshold 154 | CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold 155 | CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold 156 | CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold 157 | CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold 158 | CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold 159 | CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold 160 | CSET programmable_full_type=No_Programmable_Full_Threshold 161 | CSET programmable_full_type_axis=Single_Programmable_Full_Threshold_Constant 162 | CSET programmable_full_type_rach=No_Programmable_Full_Threshold 163 | CSET programmable_full_type_rdch=No_Programmable_Full_Threshold 164 | CSET programmable_full_type_wach=No_Programmable_Full_Threshold 165 | CSET programmable_full_type_wdch=No_Programmable_Full_Threshold 166 | CSET programmable_full_type_wrch=No_Programmable_Full_Threshold 167 | CSET rach_type=FIFO 168 | CSET rdch_type=FIFO 169 | CSET read_clock_frequency=1 170 | CSET read_data_count=false 171 | CSET read_data_count_width=10 172 | CSET register_slice_mode_axis=Fully_Registered 173 | CSET register_slice_mode_rach=Fully_Registered 174 | CSET register_slice_mode_rdch=Fully_Registered 175 | CSET register_slice_mode_wach=Fully_Registered 176 | CSET register_slice_mode_wdch=Fully_Registered 177 | CSET register_slice_mode_wrch=Fully_Registered 178 | CSET reset_pin=true 179 | CSET reset_type=Asynchronous_Reset 180 | CSET ruser_width=1 181 | CSET synchronization_stages=2 182 | CSET synchronization_stages_axi=2 183 | CSET tdata_width=8 184 | CSET tdest_width=4 185 | CSET tid_width=8 186 | CSET tkeep_width=1 187 | CSET tstrb_width=1 188 | CSET tuser_width=4 189 | CSET underflow_flag=false 190 | CSET underflow_flag_axi=false 191 | CSET underflow_sense=Active_High 192 | CSET underflow_sense_axi=Active_High 193 | CSET use_clock_enable=false 194 | CSET use_dout_reset=true 195 | CSET use_embedded_registers=false 196 | CSET use_extra_logic=false 197 | CSET valid_flag=false 198 | CSET valid_sense=Active_High 199 | CSET wach_type=FIFO 200 | CSET wdch_type=FIFO 201 | CSET wrch_type=FIFO 202 | CSET write_acknowledge_flag=false 203 | CSET write_acknowledge_sense=Active_High 204 | CSET write_clock_frequency=1 205 | CSET write_data_count=false 206 | CSET write_data_count_width=10 207 | CSET wuser_width=1 208 | # END Parameters 209 | # BEGIN Extra information 210 | MISC pkg_timestamp=2012-11-19T12:39:56Z 211 | # END Extra information 212 | GENERATE 213 | # CRC: d3658584 214 | -------------------------------------------------------------------------------- /Xilinx_IP/blk_out_fifo/blk_out_fifo.xco: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # 3 | # Xilinx Core Generator version 14.7 4 | # Date: Sun Mar 29 12:56:38 2015 5 | # 6 | ############################################################## 7 | # 8 | # This file contains the customisation parameters for a 9 | # Xilinx CORE Generator IP GUI. It is strongly recommended 10 | # that you do not manually alter this file as it may cause 11 | # unexpected and unsupported behavior. 12 | # 13 | ############################################################## 14 | # 15 | # Generated from component: xilinx.com:ip:fifo_generator:9.3 16 | # 17 | ############################################################## 18 | # 19 | # BEGIN Project Options 20 | SET addpads = false 21 | SET asysymbol = true 22 | SET busformat = BusFormatAngleBracketNotRipped 23 | SET createndf = false 24 | SET designentry = VHDL 25 | SET device = xc6slx16 26 | SET devicefamily = spartan6 27 | SET flowvendor = Other 28 | SET formalverification = false 29 | SET foundationsym = false 30 | SET implementationfiletype = Ngc 31 | SET package = csg324 32 | SET removerpms = false 33 | SET simulationfiles = Behavioral 34 | SET speedgrade = -2 35 | SET verilogsim = false 36 | SET vhdlsim = true 37 | # END Project Options 38 | # BEGIN Select 39 | SELECT FIFO_Generator xilinx.com:ip:fifo_generator:9.3 40 | # END Select 41 | # BEGIN Parameters 42 | CSET add_ngc_constraint_axi=false 43 | CSET almost_empty_flag=false 44 | CSET almost_full_flag=false 45 | CSET aruser_width=1 46 | CSET awuser_width=1 47 | CSET axi_address_width=32 48 | CSET axi_data_width=64 49 | CSET axi_type=AXI4_Stream 50 | CSET axis_type=FIFO 51 | CSET buser_width=1 52 | CSET clock_enable_type=Slave_Interface_Clock_Enable 53 | CSET clock_type_axi=Independent_Clock 54 | CSET component_name=blk_out_fifo 55 | CSET data_count=false 56 | CSET data_count_width=10 57 | CSET disable_timing_violations=false 58 | CSET disable_timing_violations_axi=false 59 | CSET dout_reset_value=0 60 | CSET empty_threshold_assert_value=2 61 | CSET empty_threshold_assert_value_axis=1021 62 | CSET empty_threshold_assert_value_rach=13 63 | CSET empty_threshold_assert_value_rdch=1021 64 | CSET empty_threshold_assert_value_wach=13 65 | CSET empty_threshold_assert_value_wdch=1021 66 | CSET empty_threshold_assert_value_wrch=13 67 | CSET empty_threshold_negate_value=3 68 | CSET enable_aruser=false 69 | CSET enable_awuser=false 70 | CSET enable_buser=false 71 | CSET enable_common_overflow=false 72 | CSET enable_common_underflow=false 73 | CSET enable_data_counts_axis=false 74 | CSET enable_data_counts_rach=false 75 | CSET enable_data_counts_rdch=false 76 | CSET enable_data_counts_wach=false 77 | CSET enable_data_counts_wdch=false 78 | CSET enable_data_counts_wrch=false 79 | CSET enable_ecc=false 80 | CSET enable_ecc_axis=false 81 | CSET enable_ecc_rach=false 82 | CSET enable_ecc_rdch=false 83 | CSET enable_ecc_wach=false 84 | CSET enable_ecc_wdch=false 85 | CSET enable_ecc_wrch=false 86 | CSET enable_read_channel=false 87 | CSET enable_read_pointer_increment_by2=false 88 | CSET enable_reset_synchronization=true 89 | CSET enable_ruser=false 90 | CSET enable_tdata=true 91 | CSET enable_tdest=false 92 | CSET enable_tid=false 93 | CSET enable_tkeep=false 94 | CSET enable_tlast=false 95 | CSET enable_tready=true 96 | CSET enable_tstrobe=false 97 | CSET enable_tuser=false 98 | CSET enable_write_channel=false 99 | CSET enable_wuser=false 100 | CSET fifo_application_type_axis=Data_FIFO 101 | CSET fifo_application_type_rach=Data_FIFO 102 | CSET fifo_application_type_rdch=Data_FIFO 103 | CSET fifo_application_type_wach=Data_FIFO 104 | CSET fifo_application_type_wdch=Data_FIFO 105 | CSET fifo_application_type_wrch=Data_FIFO 106 | CSET fifo_implementation=Common_Clock_Block_RAM 107 | CSET fifo_implementation_axis=Independent_Clocks_Block_RAM 108 | CSET fifo_implementation_rach=Independent_Clocks_Distributed_RAM 109 | CSET fifo_implementation_rdch=Independent_Clocks_Block_RAM 110 | CSET fifo_implementation_wach=Independent_Clocks_Distributed_RAM 111 | CSET fifo_implementation_wdch=Independent_Clocks_Block_RAM 112 | CSET fifo_implementation_wrch=Independent_Clocks_Distributed_RAM 113 | CSET full_flags_reset_value=1 114 | CSET full_threshold_assert_value=1022 115 | CSET full_threshold_assert_value_axis=960 116 | CSET full_threshold_assert_value_rach=15 117 | CSET full_threshold_assert_value_rdch=1023 118 | CSET full_threshold_assert_value_wach=15 119 | CSET full_threshold_assert_value_wdch=1023 120 | CSET full_threshold_assert_value_wrch=15 121 | CSET full_threshold_negate_value=1021 122 | CSET id_width=4 123 | CSET inject_dbit_error=false 124 | CSET inject_dbit_error_axis=false 125 | CSET inject_dbit_error_rach=false 126 | CSET inject_dbit_error_rdch=false 127 | CSET inject_dbit_error_wach=false 128 | CSET inject_dbit_error_wdch=false 129 | CSET inject_dbit_error_wrch=false 130 | CSET inject_sbit_error=false 131 | CSET inject_sbit_error_axis=false 132 | CSET inject_sbit_error_rach=false 133 | CSET inject_sbit_error_rdch=false 134 | CSET inject_sbit_error_wach=false 135 | CSET inject_sbit_error_wdch=false 136 | CSET inject_sbit_error_wrch=false 137 | CSET input_data_width=18 138 | CSET input_depth=1024 139 | CSET input_depth_axis=1024 140 | CSET input_depth_rach=16 141 | CSET input_depth_rdch=1024 142 | CSET input_depth_wach=16 143 | CSET input_depth_wdch=1024 144 | CSET input_depth_wrch=16 145 | CSET interface_type=AXI4 146 | CSET output_data_width=18 147 | CSET output_depth=1024 148 | CSET overflow_flag=false 149 | CSET overflow_flag_axi=false 150 | CSET overflow_sense=Active_High 151 | CSET overflow_sense_axi=Active_High 152 | CSET performance_options=Standard_FIFO 153 | CSET programmable_empty_type=No_Programmable_Empty_Threshold 154 | CSET programmable_empty_type_axis=No_Programmable_Empty_Threshold 155 | CSET programmable_empty_type_rach=No_Programmable_Empty_Threshold 156 | CSET programmable_empty_type_rdch=No_Programmable_Empty_Threshold 157 | CSET programmable_empty_type_wach=No_Programmable_Empty_Threshold 158 | CSET programmable_empty_type_wdch=No_Programmable_Empty_Threshold 159 | CSET programmable_empty_type_wrch=No_Programmable_Empty_Threshold 160 | CSET programmable_full_type=No_Programmable_Full_Threshold 161 | CSET programmable_full_type_axis=Single_Programmable_Full_Threshold_Constant 162 | CSET programmable_full_type_rach=No_Programmable_Full_Threshold 163 | CSET programmable_full_type_rdch=No_Programmable_Full_Threshold 164 | CSET programmable_full_type_wach=No_Programmable_Full_Threshold 165 | CSET programmable_full_type_wdch=No_Programmable_Full_Threshold 166 | CSET programmable_full_type_wrch=No_Programmable_Full_Threshold 167 | CSET rach_type=FIFO 168 | CSET rdch_type=FIFO 169 | CSET read_clock_frequency=1 170 | CSET read_data_count=false 171 | CSET read_data_count_width=10 172 | CSET register_slice_mode_axis=Fully_Registered 173 | CSET register_slice_mode_rach=Fully_Registered 174 | CSET register_slice_mode_rdch=Fully_Registered 175 | CSET register_slice_mode_wach=Fully_Registered 176 | CSET register_slice_mode_wdch=Fully_Registered 177 | CSET register_slice_mode_wrch=Fully_Registered 178 | CSET reset_pin=true 179 | CSET reset_type=Asynchronous_Reset 180 | CSET ruser_width=1 181 | CSET synchronization_stages=2 182 | CSET synchronization_stages_axi=2 183 | CSET tdata_width=8 184 | CSET tdest_width=4 185 | CSET tid_width=8 186 | CSET tkeep_width=1 187 | CSET tstrb_width=1 188 | CSET tuser_width=4 189 | CSET underflow_flag=false 190 | CSET underflow_flag_axi=false 191 | CSET underflow_sense=Active_High 192 | CSET underflow_sense_axi=Active_High 193 | CSET use_clock_enable=false 194 | CSET use_dout_reset=true 195 | CSET use_embedded_registers=false 196 | CSET use_extra_logic=false 197 | CSET valid_flag=false 198 | CSET valid_sense=Active_High 199 | CSET wach_type=FIFO 200 | CSET wdch_type=FIFO 201 | CSET wrch_type=FIFO 202 | CSET write_acknowledge_flag=false 203 | CSET write_acknowledge_sense=Active_High 204 | CSET write_clock_frequency=1 205 | CSET write_data_count=false 206 | CSET write_data_count_width=10 207 | CSET wuser_width=1 208 | # END Parameters 209 | # BEGIN Extra information 210 | MISC pkg_timestamp=2012-11-19T12:39:56Z 211 | # END Extra information 212 | GENERATE 213 | # CRC: d96ea664 214 | -------------------------------------------------------------------------------- /Test/usb_flasher_tb.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - usb_flasher_tb.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.all; 27 | use IEEE.STD_LOGIC_UNSIGNED.all; 28 | use IEEE.NUMERIC_STD.all; 29 | 30 | ENTITY usb_flasher_tb IS 31 | END usb_flasher_tb; 32 | 33 | architecture usb_flasher_tb of usb_flasher_tb is 34 | component usb_flasher 35 | port( 36 | clk : in std_logic; 37 | rst : in std_logic; 38 | 39 | ctl_xfer_endpoint : in std_logic_vector(3 downto 0); 40 | ctl_xfer_type : in std_logic_vector(7 downto 0); 41 | ctl_xfer_request : in std_logic_vector(7 downto 0); 42 | ctl_xfer_value : in std_logic_vector(15 downto 0); 43 | ctl_xfer_index : in std_logic_vector(15 downto 0); 44 | ctl_xfer_length : in std_logic_vector(15 downto 0); 45 | ctl_xfer_accept : out std_logic; 46 | ctl_xfer : in std_logic; 47 | ctl_xfer_done : out std_logic; 48 | ctl_xfer_data_out : in std_logic_vector(7 downto 0); 49 | ctl_xfer_data_out_valid : in std_logic; 50 | ctl_xfer_data_in : out std_logic_vector(7 downto 0); 51 | ctl_xfer_data_in_valid : out std_logic; 52 | ctl_xfer_data_in_last : out std_logic; 53 | ctl_xfer_data_in_ready : in std_logic; 54 | 55 | blk_xfer_endpoint : in std_logic_vector(3 downto 0); 56 | blk_in_xfer : in std_logic; 57 | blk_out_xfer : in std_logic; 58 | blk_xfer_in_has_data : out std_logic; 59 | blk_xfer_in_data : out std_logic_vector(7 downto 0); 60 | blk_xfer_in_data_valid : out std_logic; 61 | blk_xfer_in_data_ready : in std_logic; 62 | blk_xfer_in_data_last : out std_logic; 63 | blk_xfer_out_ready_read : out std_logic; 64 | blk_xfer_out_data : in std_logic_vector(7 downto 0); 65 | blk_xfer_out_data_valid : in std_logic; 66 | 67 | spi_cs : out std_logic; 68 | spi_sck : out std_logic; 69 | spi_mosi : out std_logic; 70 | spi_miso : in std_logic 71 | ); 72 | end component; 73 | 74 | 75 | --Inputs 76 | signal clk : std_logic := '0'; 77 | signal rst : std_logic := '0'; 78 | 79 | signal ctl_xfer_endpoint : std_logic_vector(3 downto 0) := (others => '0'); 80 | signal ctl_xfer_type : std_logic_vector(7 downto 0) := (others => '0'); 81 | signal ctl_xfer_request : std_logic_vector(7 downto 0) := (others => '0'); 82 | signal ctl_xfer_value : std_logic_vector(15 downto 0) := (others => '0'); 83 | signal ctl_xfer_index : std_logic_vector(15 downto 0) := (others => '0'); 84 | signal ctl_xfer_length : std_logic_vector(15 downto 0) := (others => '0'); 85 | signal ctl_xfer : std_logic := '0'; 86 | signal ctl_xfer_data_out : std_logic_vector(7 downto 0) := (others => '0'); 87 | signal ctl_xfer_data_out_valid : std_logic := '0'; 88 | signal ctl_xfer_data_in_ready : std_logic := '0'; 89 | 90 | signal blk_xfer_endpoint : std_logic_vector(3 downto 0) := (others => '0'); 91 | signal blk_in_xfer : std_logic := '0'; 92 | signal blk_out_xfer : std_logic := '0'; 93 | signal blk_xfer_in_data_ready : std_logic := '0'; 94 | signal blk_xfer_out_data : std_logic_vector(7 downto 0) := (others => '0'); 95 | signal blk_xfer_out_data_valid : std_logic := '0'; 96 | 97 | signal spi_miso : std_logic := '0'; 98 | 99 | --Outputs 100 | signal ctl_xfer_accept : std_logic; 101 | signal ctl_xfer_done : std_logic; 102 | signal ctl_xfer_data_in : std_logic_vector(7 downto 0); 103 | signal ctl_xfer_data_in_valid : std_logic; 104 | signal ctl_xfer_data_in_last : std_logic; 105 | signal blk_xfer_in_has_data : std_logic; 106 | signal blk_xfer_in_data : std_logic_vector(7 downto 0); 107 | signal blk_xfer_in_data_valid : std_logic; 108 | signal blk_xfer_in_data_last : std_logic; 109 | signal blk_xfer_out_ready_read : std_logic; 110 | 111 | signal spi_cs : std_logic; 112 | signal spi_sck : std_logic; 113 | signal spi_mosi : std_logic; 114 | 115 | constant clk_period : time := 10 ns; 116 | 117 | BEGIN 118 | FLASHER: usb_flasher 119 | port map ( 120 | clk => clk, 121 | rst => rst, 122 | 123 | ctl_xfer_endpoint => ctl_xfer_endpoint, 124 | ctl_xfer_type => ctl_xfer_type, 125 | ctl_xfer_request => ctl_xfer_request, 126 | ctl_xfer_value => ctl_xfer_value, 127 | ctl_xfer_index => ctl_xfer_index, 128 | ctl_xfer_length => ctl_xfer_length, 129 | ctl_xfer_accept => ctl_xfer_accept, 130 | ctl_xfer => ctl_xfer, 131 | ctl_xfer_done => ctl_xfer_done, 132 | ctl_xfer_data_out => ctl_xfer_data_out, 133 | ctl_xfer_data_out_valid => ctl_xfer_data_out_valid, 134 | ctl_xfer_data_in => ctl_xfer_data_in, 135 | ctl_xfer_data_in_valid => ctl_xfer_data_in_valid, 136 | ctl_xfer_data_in_last => ctl_xfer_data_in_last, 137 | ctl_xfer_data_in_ready => ctl_xfer_data_in_ready, 138 | 139 | blk_xfer_endpoint => blk_xfer_endpoint, 140 | blk_in_xfer => blk_in_xfer, 141 | blk_out_xfer => blk_out_xfer, 142 | blk_xfer_in_has_data => blk_xfer_in_has_data, 143 | blk_xfer_in_data => blk_xfer_in_data, 144 | blk_xfer_in_data_valid => blk_xfer_in_data_valid, 145 | blk_xfer_in_data_ready => blk_xfer_in_data_ready, 146 | blk_xfer_in_data_last => blk_xfer_in_data_last, 147 | blk_xfer_out_ready_read => blk_xfer_out_ready_read, 148 | blk_xfer_out_data => blk_xfer_out_data, 149 | blk_xfer_out_data_valid => blk_xfer_out_data_valid, 150 | 151 | spi_cs => spi_cs, 152 | spi_sck => spi_sck, 153 | spi_mosi => spi_mosi, 154 | spi_miso => spi_miso 155 | ); 156 | 157 | ctl_xfer_endpoint <= X"0"; 158 | ctl_xfer_type <= X"C0"; 159 | ctl_xfer_request <= X"04"; 160 | ctl_xfer_value <= X"0085"; 161 | ctl_xfer_index <= (others => '0'); 162 | ctl_xfer_length <= X"0001"; 163 | ctl_xfer_data_in_ready <= '0'; 164 | 165 | ctl_xfer_data_out <= X"A5"; 166 | 167 | CLK_GEN: process 168 | begin 169 | clk <= '0'; 170 | wait for clk_period/2; 171 | clk <= '1'; 172 | wait for clk_period/2; 173 | end process; 174 | 175 | STIM: process 176 | begin 177 | wait for 100 ns; 178 | rst <= '1'; 179 | wait for clk_period*10; 180 | rst <= '0'; 181 | wait for clk_period; 182 | 183 | -- blk_out_xfer <= '1'; 184 | -- blk_xfer_out_data_valid <= '1'; 185 | -- blk_xfer_out_data <= X"A5"; 186 | -- 187 | -- wait for clk_period; 188 | -- blk_xfer_out_data <= X"88"; 189 | -- 190 | -- wait for clk_period*255; 191 | -- blk_out_xfer <= '0'; 192 | -- blk_xfer_out_data_valid <= '0'; 193 | 194 | ctl_xfer <= '1'; 195 | ctl_xfer_data_out_valid <= '1'; 196 | wait for clk_period*100; 197 | ctl_xfer <= '0'; 198 | 199 | --blk_in_xfer <= '1'; 200 | --blk_xfer_in_data_ready <= '1'; 201 | 202 | --wait for clk_period*256; 203 | --blk_in_xfer <= '0'; 204 | --blk_xfer_in_data_ready <= '0'; 205 | 206 | wait; 207 | end process; 208 | 209 | end; 210 | -------------------------------------------------------------------------------- /Examples/EP1_Loopback/ep1_loopback.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - ep1_loopback.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.ALL; 27 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 28 | use IEEE.NUMERIC_STD.ALL; 29 | 30 | library UNISIM; 31 | use UNISIM.VCOMPONENTS.ALL; 32 | 33 | library work; 34 | use work.USBCore.all; 35 | use work.USBExtra.all; 36 | 37 | entity ep1_loopback is 38 | port ( 39 | led : out std_logic; 40 | ulpi_data : inout std_logic_vector(7 downto 0); 41 | ulpi_dir : in std_logic; 42 | ulpi_nxt : in std_logic; 43 | ulpi_stp : out std_logic; 44 | ulpi_reset : out std_logic; 45 | ulpi_clk60 : in std_logic; 46 | 47 | main_clk : in std_logic 48 | ); 49 | end ep1_loopback; 50 | 51 | architecture ep1_loopback of ep1_loopback is 52 | constant USE_HIGH_SPEED: boolean := true; 53 | 54 | constant CONFIG_DESC : BYTE_ARRAY(0 to 8) := ( 55 | X"09", -- bLength = 9 56 | X"02", -- bDescriptionType = Configuration Descriptor 57 | X"20", X"00", -- wTotalLength = 32 58 | X"01", -- bNumInterfaces = 1 59 | X"01", -- bConfigurationValue 60 | X"00", -- iConfiguration 61 | X"C0", -- bmAttributes = Self-powered 62 | X"32" -- bMaxPower = 100 mA 63 | ); 64 | 65 | constant INTERFACE_DESC : BYTE_ARRAY(0 to 8) := ( 66 | X"09", -- bLength = 9 67 | X"04", -- bDescriptorType = Interface Descriptor 68 | X"00", -- bInterfaceNumber = 0 69 | X"00", -- bAlternateSetting 70 | X"02", -- bNumEndpoints = 2 71 | X"00", -- bInterfaceClass 72 | X"00", -- bInterfaceSubClass 73 | X"00", -- bInterfaceProtocol 74 | X"00" -- iInterface 75 | ); 76 | 77 | constant EP1_IN_DESC : BYTE_ARRAY(0 to 6) := ( 78 | X"07", -- bLength = 7 79 | X"05", -- bDescriptorType = Endpoint Descriptor 80 | X"81", -- bEndpointAddress = IN1 81 | B"00_00_00_10", -- bmAttributes = Bulk 82 | X"00", X"02", -- wMaxPacketSize = 512 bytes 83 | X"00" -- bInterval 84 | ); 85 | 86 | constant EP1_OUT_DESC : BYTE_ARRAY(0 to 6) := ( 87 | X"07", -- bLength = 7 88 | X"05", -- bDescriptorType = Endpoint Descriptor 89 | X"01", -- bEndpointAddress = OUT1 90 | B"00_00_00_10", -- bmAttributes = Bulk 91 | X"00", X"02", -- wMaxPacketSize = 512 bytes 92 | X"00" -- bInterval 93 | ); 94 | 95 | signal ulpi_data_in : std_logic_vector(7 downto 0); 96 | signal ulpi_data_out : std_logic_vector(7 downto 0); 97 | 98 | signal usb_clk : std_logic; 99 | signal usb_reset : std_logic; 100 | 101 | signal usb_idle : std_logic; 102 | signal usb_suspend : std_logic; 103 | signal usb_configured : std_logic; 104 | signal usb_crc_error : std_logic; 105 | signal usb_sof : std_logic; 106 | 107 | signal ctl_xfer_endpoint : std_logic_vector(3 downto 0); 108 | signal ctl_xfer_type : std_logic_vector(7 downto 0); 109 | signal ctl_xfer_request : std_logic_vector(7 downto 0); 110 | signal ctl_xfer_value : std_logic_vector(15 downto 0); 111 | signal ctl_xfer_index : std_logic_vector(15 downto 0); 112 | signal ctl_xfer_length : std_logic_vector(15 downto 0); 113 | signal ctl_xfer_accept : std_logic; 114 | signal ctl_xfer : std_logic; 115 | signal ctl_xfer_done : std_logic; 116 | 117 | signal ctl_xfer_data_out : std_logic_vector(7 downto 0); 118 | signal ctl_xfer_data_out_valid: std_logic; 119 | 120 | signal ctl_xfer_data_in : std_logic_vector(7 downto 0); 121 | signal ctl_xfer_data_in_valid : std_logic; 122 | signal ctl_xfer_data_in_last : std_logic; 123 | signal ctl_xfer_data_in_ready : std_logic; 124 | 125 | signal blk_xfer_endpoint : std_logic_vector(3 downto 0); 126 | signal blk_in_xfer : std_logic; 127 | signal blk_out_xfer : std_logic; 128 | 129 | signal blk_xfer_in_has_data : std_logic; 130 | signal blk_xfer_in_data : std_logic_vector(7 downto 0); 131 | signal blk_xfer_in_data_valid : std_logic; 132 | signal blk_xfer_in_data_ready : std_logic; 133 | signal blk_xfer_in_data_last : std_logic; 134 | 135 | signal blk_xfer_out_ready_read: std_logic; 136 | signal blk_xfer_out_data : std_logic_vector(7 downto 0); 137 | signal blk_xfer_out_data_valid: std_logic; 138 | 139 | signal ep1_in_axis_tdata : std_logic_vector(7 downto 0); 140 | signal ep1_in_axis_tvalid : std_logic; 141 | signal ep1_in_axis_tready : std_logic; 142 | signal ep1_in_axis_tlast : std_logic; 143 | 144 | signal ep1_out_axis_tdata : std_logic_vector(7 downto 0); 145 | signal ep1_out_axis_tvalid : std_logic; 146 | signal ep1_out_axis_tready : std_logic; 147 | signal ep1_out_axis_tlast : std_logic; 148 | 149 | signal led_counter : std_logic_vector(25 downto 0); 150 | 151 | signal ulpi_stp_int : std_logic; 152 | 153 | 154 | begin 155 | ULPI_IO: for i in 7 downto 0 generate 156 | begin 157 | ULPI_IOBUF : IOBUF 158 | port map ( 159 | O => ulpi_data_in(i), 160 | IO => ulpi_data(i), 161 | I => ulpi_data_out(i), 162 | T => ulpi_dir 163 | ); 164 | end generate; 165 | 166 | USB_CONTROLLER: usb_tlp 167 | generic map ( 168 | VENDOR_ID => X"DEAD", 169 | PRODUCT_ID => X"BEEF", 170 | MANUFACTURER => "USBCore", 171 | PRODUCT => "Endpoint 1 Loopback Device", 172 | SERIAL => "", 173 | CONFIG_DESC => CONFIG_DESC & INTERFACE_DESC & 174 | EP1_IN_DESC & EP1_OUT_DESC, 175 | HIGH_SPEED => USE_HIGH_SPEED 176 | ) 177 | port map ( 178 | ulpi_data_in => ulpi_data_in, 179 | ulpi_data_out => ulpi_data_out, 180 | ulpi_dir => ulpi_dir, 181 | ulpi_nxt => ulpi_nxt, 182 | ulpi_stp => ulpi_stp, 183 | ulpi_reset => ulpi_reset, 184 | ulpi_clk60 => ulpi_clk60, 185 | 186 | usb_clk => usb_clk, 187 | usb_reset => usb_reset, 188 | 189 | usb_idle => usb_idle, 190 | usb_suspend => usb_suspend, 191 | usb_configured => usb_configured, 192 | usb_crc_error => usb_crc_error, 193 | usb_sof => usb_sof, 194 | 195 | ctl_xfer_endpoint => ctl_xfer_endpoint, 196 | ctl_xfer_type => ctl_xfer_type, 197 | ctl_xfer_request => ctl_xfer_request, 198 | ctl_xfer_value => ctl_xfer_value, 199 | ctl_xfer_index => ctl_xfer_index, 200 | ctl_xfer_length => ctl_xfer_length, 201 | ctl_xfer_accept => ctl_xfer_accept, 202 | ctl_xfer => ctl_xfer, 203 | ctl_xfer_done => ctl_xfer_done, 204 | 205 | ctl_xfer_data_out => ctl_xfer_data_out, 206 | ctl_xfer_data_out_valid => ctl_xfer_data_out_valid, 207 | 208 | ctl_xfer_data_in => ctl_xfer_data_in, 209 | ctl_xfer_data_in_valid => ctl_xfer_data_in_valid, 210 | ctl_xfer_data_in_last => ctl_xfer_data_in_last, 211 | ctl_xfer_data_in_ready => ctl_xfer_data_in_ready, 212 | 213 | blk_xfer_endpoint => blk_xfer_endpoint, 214 | blk_in_xfer => blk_in_xfer, 215 | blk_out_xfer => blk_out_xfer, 216 | 217 | blk_xfer_in_has_data => blk_xfer_in_has_data, 218 | blk_xfer_in_data => blk_xfer_in_data, 219 | blk_xfer_in_data_valid => blk_xfer_in_data_valid, 220 | blk_xfer_in_data_ready => blk_xfer_in_data_ready, 221 | blk_xfer_in_data_last => blk_xfer_in_data_last, 222 | 223 | blk_xfer_out_ready_read => blk_xfer_out_ready_read, 224 | blk_xfer_out_data => blk_xfer_out_data, 225 | blk_xfer_out_data_valid => blk_xfer_out_data_valid 226 | ); 227 | 228 | EP1_IN_CTL: blk_ep_in_ctl 229 | generic map ( 230 | USE_ASYNC_FIFO => true 231 | ) 232 | port map ( 233 | rst => usb_reset, 234 | usb_clk => usb_clk, 235 | axis_clk => main_clk, 236 | 237 | blk_in_xfer => blk_in_xfer, 238 | 239 | blk_xfer_in_has_data => blk_xfer_in_has_data, 240 | blk_xfer_in_data => blk_xfer_in_data, 241 | blk_xfer_in_data_valid => blk_xfer_in_data_valid, 242 | blk_xfer_in_data_ready => blk_xfer_in_data_ready, 243 | blk_xfer_in_data_last => blk_xfer_in_data_last, 244 | 245 | axis_tdata => ep1_in_axis_tdata, 246 | axis_tvalid => ep1_in_axis_tvalid, 247 | axis_tready => ep1_in_axis_tready, 248 | axis_tlast => ep1_in_axis_tlast 249 | ); 250 | 251 | EP1_OUT_CTL: blk_ep_out_ctl 252 | generic map ( 253 | USE_ASYNC_FIFO => true 254 | ) 255 | port map ( 256 | rst => usb_reset, 257 | usb_clk => usb_clk, 258 | axis_clk => main_clk, 259 | 260 | blk_out_xfer => blk_out_xfer, 261 | 262 | blk_xfer_out_ready_read => blk_xfer_out_ready_read, 263 | blk_xfer_out_data => blk_xfer_out_data, 264 | blk_xfer_out_data_valid => blk_xfer_out_data_valid, 265 | 266 | axis_tdata => ep1_out_axis_tdata, 267 | axis_tvalid => ep1_out_axis_tvalid, 268 | axis_tready => ep1_out_axis_tready, 269 | axis_tlast => ep1_out_axis_tlast 270 | ); 271 | 272 | ep1_in_axis_tdata <= ep1_out_axis_tdata; 273 | ep1_in_axis_tvalid <= ep1_out_axis_tvalid; 274 | ep1_out_axis_tready <= ep1_in_axis_tready; 275 | ep1_in_axis_tlast <= ep1_out_axis_tlast; 276 | 277 | COUNT: process(usb_clk) is 278 | begin 279 | if rising_edge(usb_clk) then 280 | led_counter <= led_counter + 1; 281 | end if; 282 | end process; 283 | 284 | led <= '1' when usb_idle = '1' AND usb_configured = '1' else 285 | led_counter(led_counter'left) when usb_idle = '1' else 286 | '1' when led_counter(led_counter'left downto led_counter'left - 2) = "000" else 287 | '0'; 288 | 289 | end ep1_loopback; 290 | -------------------------------------------------------------------------------- /Core/core_pkg.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - core_pkg.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.all; 27 | use IEEE.STD_LOGIC_UNSIGNED.all; 28 | use IEEE.NUMERIC_STD.all; 29 | 30 | package usbcore is 31 | type BYTE_ARRAY is array(natural range <>) of std_logic_vector(7 downto 0); 32 | 33 | component usb_std_request is 34 | generic ( 35 | VENDOR_ID : std_logic_vector(15 downto 0); 36 | PRODUCT_ID : std_logic_vector(15 downto 0); 37 | MANUFACTURER : string; 38 | PRODUCT : string; 39 | SERIAL : string; 40 | CONFIG_DESC : BYTE_ARRAY; 41 | HIGH_SPEED : boolean 42 | ); 43 | port ( 44 | rst : in std_logic; 45 | clk : in std_logic; 46 | 47 | ctl_xfer_endpoint : in std_logic_vector(3 downto 0); 48 | ctl_xfer_type : in std_logic_vector(7 downto 0); 49 | ctl_xfer_request : in std_logic_vector(7 downto 0); 50 | ctl_xfer_value : in std_logic_vector(15 downto 0); 51 | ctl_xfer_index : in std_logic_vector(15 downto 0); 52 | ctl_xfer_length : in std_logic_vector(15 downto 0); 53 | 54 | ctl_xfer_accept : out std_logic; 55 | ctl_xfer : in std_logic; 56 | ctl_xfer_done : out std_logic; 57 | 58 | ctl_xfer_data_out : in std_logic_vector(7 downto 0); 59 | ctl_xfer_data_out_valid : in std_logic; 60 | 61 | ctl_xfer_data_in : out std_logic_vector(7 downto 0); 62 | ctl_xfer_data_in_valid : out std_logic; 63 | ctl_xfer_data_in_last : out std_logic; 64 | ctl_xfer_data_in_ready : in std_logic; 65 | 66 | device_address : out std_logic_vector(6 downto 0); 67 | current_configuration : out std_logic_vector(7 downto 0); 68 | configured : out std_logic; 69 | 70 | standart_request : out std_logic 71 | ); 72 | end component; 73 | 74 | component ulpi_port is 75 | generic ( 76 | HIGH_SPEED: boolean 77 | ); 78 | port ( 79 | rst : in std_logic; 80 | 81 | ulpi_data_in : in std_logic_vector(7 downto 0); 82 | ulpi_data_out : out std_logic_vector(7 downto 0); 83 | ulpi_dir : in std_logic; 84 | ulpi_nxt : in std_logic; 85 | ulpi_stp : out std_logic; 86 | ulpi_reset : out std_logic; 87 | ulpi_clk : in std_logic; 88 | 89 | axis_rx_tvalid : out std_logic; 90 | axis_rx_tready : in std_logic; 91 | axis_rx_tlast : out std_logic; 92 | axis_rx_tdata : out std_logic_vector(7 downto 0); 93 | 94 | axis_tx_tvalid : in std_logic; 95 | axis_tx_tready : out std_logic; 96 | axis_tx_tlast : in std_logic; 97 | axis_tx_tdata : in std_logic_vector(7 downto 0); 98 | 99 | usb_vbus_valid : out std_logic; 100 | usb_reset : out std_logic; 101 | usb_idle : out std_logic; 102 | usb_suspend : out std_logic 103 | ); 104 | end component; 105 | 106 | component usb_packet is 107 | port ( 108 | rst : in std_logic; 109 | clk : in std_logic; 110 | 111 | axis_rx_tvalid : in std_logic; 112 | axis_rx_tready : out std_logic; 113 | axis_rx_tlast : in std_logic; 114 | axis_rx_tdata : in std_logic_vector(7 downto 0); 115 | 116 | axis_tx_tvalid : out std_logic; 117 | axis_tx_tready : in std_logic; 118 | axis_tx_tlast : out std_logic; 119 | axis_tx_tdata : out std_logic_vector(7 downto 0); 120 | 121 | trn_type : out std_logic_vector(1 downto 0); 122 | trn_address : out std_logic_vector(6 downto 0); 123 | trn_endpoint : out std_logic_vector(3 downto 0); 124 | trn_start : out std_logic; 125 | 126 | rx_trn_data_type : out std_logic_vector(1 downto 0); 127 | rx_trn_end : out std_logic; 128 | rx_trn_data : out std_logic_vector(7 downto 0); 129 | rx_trn_valid : out std_logic; 130 | 131 | rx_trn_hsk_type : out std_logic_vector(1 downto 0); 132 | rx_trn_hsk_received : out std_logic; 133 | 134 | tx_trn_hsk_type : in std_logic_vector(1 downto 0); 135 | tx_trn_send_hsk : in std_logic; 136 | tx_trn_hsk_sended : out std_logic; 137 | 138 | tx_trn_data_type : in std_logic_vector(1 downto 0); 139 | tx_trn_data_start : in std_logic; 140 | 141 | tx_trn_data : in std_logic_vector(7 downto 0); 142 | tx_trn_data_valid : in std_logic; 143 | tx_trn_data_ready : out std_logic; 144 | tx_trn_data_last : in std_logic; 145 | 146 | start_of_frame : out std_logic; 147 | crc_error : out std_logic; 148 | device_address : in std_logic_vector(6 downto 0) 149 | ); 150 | end component; 151 | 152 | component usb_xfer is 153 | generic ( 154 | HIGH_SPEED: boolean 155 | ); 156 | port ( 157 | rst : in std_logic; 158 | clk : in std_logic; 159 | 160 | trn_type : in std_logic_vector(1 downto 0); 161 | trn_address : in std_logic_vector(6 downto 0); 162 | trn_endpoint : in std_logic_vector(3 downto 0); 163 | trn_start : in std_logic; 164 | 165 | rx_trn_data_type : in std_logic_vector(1 downto 0); 166 | rx_trn_end : in std_logic; 167 | rx_trn_data : in std_logic_vector(7 downto 0); 168 | rx_trn_valid : in std_logic; 169 | 170 | rx_trn_hsk_type : in std_logic_vector(1 downto 0); 171 | rx_trn_hsk_received : in std_logic; 172 | 173 | tx_trn_hsk_type : out std_logic_vector(1 downto 0); 174 | tx_trn_send_hsk : out std_logic; 175 | tx_trn_hsk_sended : in std_logic; 176 | 177 | tx_trn_data_type : out std_logic_vector(1 downto 0); 178 | tx_trn_data_start : out std_logic; 179 | 180 | tx_trn_data : out std_logic_vector(7 downto 0); 181 | tx_trn_data_valid : out std_logic; 182 | tx_trn_data_ready : in std_logic; 183 | tx_trn_data_last : out std_logic; 184 | 185 | crc_error : in std_logic; 186 | 187 | ctl_xfer_endpoint : out std_logic_vector(3 downto 0); 188 | ctl_xfer_type : out std_logic_vector(7 downto 0); 189 | ctl_xfer_request : out std_logic_vector(7 downto 0); 190 | ctl_xfer_value : out std_logic_vector(15 downto 0); 191 | ctl_xfer_index : out std_logic_vector(15 downto 0); 192 | ctl_xfer_length : out std_logic_vector(15 downto 0); 193 | ctl_xfer_accept : in std_logic; 194 | ctl_xfer : out std_logic; 195 | ctl_xfer_done : in std_logic; 196 | 197 | ctl_xfer_data_out : out std_logic_vector(7 downto 0); 198 | ctl_xfer_data_out_valid : out std_logic; 199 | 200 | ctl_xfer_data_in : in std_logic_vector(7 downto 0); 201 | ctl_xfer_data_in_valid : in std_logic; 202 | ctl_xfer_data_in_last : in std_logic; 203 | ctl_xfer_data_in_ready : out std_logic; 204 | 205 | blk_xfer_endpoint : out std_logic_vector(3 downto 0); 206 | blk_in_xfer : out std_logic; 207 | blk_out_xfer : out std_logic; 208 | 209 | -- Has complete packet 210 | blk_xfer_in_has_data : in std_logic; 211 | blk_xfer_in_data : in std_logic_vector(7 downto 0); 212 | blk_xfer_in_data_valid : in std_logic; 213 | blk_xfer_in_data_ready : out std_logic; 214 | blk_xfer_in_data_last : in std_logic; 215 | 216 | -- Can accept full packet 217 | blk_xfer_out_ready_read : in std_logic; 218 | blk_xfer_out_data : out std_logic_vector(7 downto 0); 219 | blk_xfer_out_data_valid : out std_logic 220 | ); 221 | end component; 222 | 223 | component usb_tlp is 224 | generic ( 225 | VENDOR_ID : std_logic_vector(15 downto 0); 226 | PRODUCT_ID : std_logic_vector(15 downto 0); 227 | MANUFACTURER : string; 228 | PRODUCT : string; 229 | SERIAL : string; 230 | CONFIG_DESC : BYTE_ARRAY; 231 | HIGH_SPEED : boolean 232 | ); 233 | port ( 234 | ulpi_data_in : in std_logic_vector(7 downto 0); 235 | ulpi_data_out : out std_logic_vector(7 downto 0); 236 | ulpi_dir : in std_logic; 237 | ulpi_nxt : in std_logic; 238 | ulpi_stp : out std_logic; 239 | ulpi_reset : out std_logic; 240 | ulpi_clk60 : in std_logic; 241 | 242 | usb_clk : out std_logic; 243 | usb_reset : out std_logic; 244 | 245 | usb_idle : out std_logic; 246 | usb_suspend : out std_logic; 247 | usb_configured : out std_logic; 248 | usb_crc_error : out std_logic; 249 | usb_sof : out std_logic; 250 | 251 | ctl_xfer_endpoint : out std_logic_vector(3 downto 0); 252 | ctl_xfer_type : out std_logic_vector(7 downto 0); 253 | ctl_xfer_request : out std_logic_vector(7 downto 0); 254 | ctl_xfer_value : out std_logic_vector(15 downto 0); 255 | ctl_xfer_index : out std_logic_vector(15 downto 0); 256 | ctl_xfer_length : out std_logic_vector(15 downto 0); 257 | ctl_xfer_accept : in std_logic; 258 | ctl_xfer : out std_logic; 259 | ctl_xfer_done : in std_logic; 260 | 261 | ctl_xfer_data_out : out std_logic_vector(7 downto 0); 262 | ctl_xfer_data_out_valid : out std_logic; 263 | 264 | ctl_xfer_data_in : in std_logic_vector(7 downto 0); 265 | ctl_xfer_data_in_valid : in std_logic; 266 | ctl_xfer_data_in_last : in std_logic; 267 | ctl_xfer_data_in_ready : out std_logic; 268 | 269 | blk_xfer_endpoint : out std_logic_vector(3 downto 0); 270 | blk_in_xfer : out std_logic; 271 | blk_out_xfer : out std_logic; 272 | 273 | blk_xfer_in_has_data : in std_logic; 274 | blk_xfer_in_data : in std_logic_vector(7 downto 0); 275 | blk_xfer_in_data_valid : in std_logic; 276 | blk_xfer_in_data_ready : out std_logic; 277 | blk_xfer_in_data_last : in std_logic; 278 | 279 | blk_xfer_out_ready_read : in std_logic; 280 | blk_xfer_out_data : out std_logic_vector(7 downto 0); 281 | blk_xfer_out_data_valid : out std_logic 282 | ); 283 | end component; 284 | end usbcore; -------------------------------------------------------------------------------- /Core/ulpi_port.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - ulpi_port.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.all; 27 | use IEEE.STD_LOGIC_UNSIGNED.all; 28 | use IEEE.NUMERIC_STD.all; 29 | 30 | library work; 31 | use work.USBCore.all; 32 | 33 | --! ULPI PHY controller 34 | entity ulpi_port is 35 | generic ( 36 | HIGH_SPEED: boolean := true 37 | ); 38 | port ( 39 | rst : in std_logic; --! Global external asynchronous reset 40 | 41 | --! ULPI PHY signals 42 | ulpi_data_in : in std_logic_vector(7 downto 0); 43 | ulpi_data_out : out std_logic_vector(7 downto 0); 44 | ulpi_dir : in std_logic; 45 | ulpi_nxt : in std_logic; 46 | ulpi_stp : out std_logic; 47 | ulpi_reset : out std_logic; 48 | ulpi_clk : in std_logic; 49 | 50 | --! RX AXI-Stream, first data is PID 51 | axis_rx_tvalid : out std_logic; 52 | axis_rx_tready : in std_logic; 53 | axis_rx_tlast : out std_logic; 54 | axis_rx_tdata : out std_logic_vector(7 downto 0); 55 | 56 | --! TX AXI-Stream, first data should be PID (in 4 least significant bits) 57 | axis_tx_tvalid : in std_logic; 58 | axis_tx_tready : out std_logic; 59 | axis_tx_tlast : in std_logic; 60 | axis_tx_tdata : in std_logic_vector(7 downto 0); 61 | 62 | usb_vbus_valid : out std_logic; --! VBUS has valid voltage 63 | usb_reset : out std_logic; --! USB bus is in reset state 64 | usb_idle : out std_logic; --! USB bus is in idle state 65 | usb_suspend : out std_logic --! USB bus is in suspend state 66 | ); 67 | end ulpi_port; 68 | 69 | architecture ulpi_port of ulpi_port is 70 | constant SUSPEND_TIME : integer := 190000; -- = ~3 ms 71 | constant RESET_TIME : integer := 190000; -- = ~3 ms 72 | constant CHIRP_K_TIME : integer := 66000; -- = ~1 ms 73 | constant CHIRP_KJ_TIME: integer := 120; -- = ~2 us 74 | constant SWITCH_TIME : integer := 6000; -- = ~100 us 75 | 76 | type MACHINE is (S_Init, S_WriteReg_A, S_WriteReg_D, S_STP, S_Reset, S_Suspend, 77 | S_Idle, S_TX, S_TX_Last, S_ChirpStart, S_ChirpStartK, S_ChirpK, 78 | S_ChirpKJ, S_SwitchFSStart, S_SwitchFS); 79 | 80 | signal state : MACHINE; 81 | signal state_after : MACHINE; 82 | signal dir_d : std_logic; 83 | signal tx_pid : std_logic_vector(3 downto 0); 84 | 85 | signal reg_data : std_logic_vector(7 downto 0); 86 | 87 | signal buf_data : std_logic_vector(7 downto 0); 88 | signal buf_last : std_logic; 89 | signal buf_valid : std_logic; 90 | 91 | signal tx_eop : std_logic := '0'; 92 | signal bus_tx_ready : std_logic := '0'; 93 | 94 | signal chirp_kj_counter : std_logic_vector(2 downto 0); 95 | signal hs_enabled : std_logic := '0'; 96 | 97 | signal usb_line_state : std_logic_vector(1 downto 0); 98 | signal state_counter : std_logic_vector(17 downto 0); 99 | 100 | signal packet : std_logic := '0'; 101 | signal packet_buf : std_logic_vector(7 downto 0); 102 | begin 103 | OUTER : process(ulpi_clk) is 104 | begin 105 | if rising_edge(ulpi_clk) then 106 | if dir_d = ulpi_dir and ulpi_dir = '1' and ulpi_nxt = '1' then 107 | packet_buf <= ulpi_data_in; 108 | if packet = '0' then 109 | axis_rx_tvalid <= '0'; 110 | packet <= '1'; 111 | else 112 | axis_rx_tdata <= packet_buf; 113 | axis_rx_tvalid <= '1'; 114 | end if; 115 | axis_rx_tlast <= '0'; 116 | elsif packet = '1' and dir_d = ulpi_dir and 117 | ((ulpi_dir = '1' and ulpi_data_in(4) = '0') or (ulpi_dir = '0')) then 118 | axis_rx_tdata <= packet_buf; 119 | axis_rx_tvalid <= '1'; 120 | axis_rx_tlast <= '1'; 121 | packet <= '0'; 122 | else 123 | axis_rx_tvalid <= '0'; 124 | axis_rx_tlast <= '0'; 125 | end if; 126 | end if; 127 | end process; 128 | 129 | STATE_COUNT: process(ulpi_clk) is 130 | begin 131 | if rising_edge(ulpi_clk) then 132 | if dir_d = ulpi_dir and ulpi_dir = '1' and ulpi_nxt = '0' AND ulpi_data_in(1 downto 0) /= usb_line_state then 133 | if state = S_ChirpKJ then 134 | if ulpi_data_in(1 downto 0) = "01" then 135 | chirp_kj_counter <= chirp_kj_counter + 1; 136 | end if; 137 | else 138 | chirp_kj_counter <= (others => '0'); 139 | end if; 140 | usb_line_state <= ulpi_data_in(1 downto 0); 141 | state_counter <= (others => '0'); 142 | elsif state = S_ChirpStartK then 143 | state_counter <= (others => '0'); 144 | elsif state = S_SwitchFSStart then 145 | state_counter <= (others => '0'); 146 | else 147 | state_counter <= state_counter + 1; 148 | end if; 149 | end if; 150 | end process; 151 | 152 | FSM : process(ulpi_clk) is 153 | begin 154 | if rising_edge(ulpi_clk) then 155 | dir_d <= ulpi_dir; 156 | 157 | if dir_d = ulpi_dir then 158 | if ulpi_dir = '1' and ulpi_nxt = '0' then 159 | if ulpi_data_in(3 downto 2) = "11" then 160 | usb_vbus_valid <= '1'; 161 | else 162 | usb_vbus_valid <= '0'; 163 | end if; 164 | elsif ulpi_dir = '0' then 165 | case state is 166 | when S_Init => 167 | ulpi_data_out <= X"8A"; 168 | reg_data <= X"00"; 169 | state <= S_WriteReg_A; 170 | state_after <= S_SwitchFSStart; 171 | 172 | when S_WriteReg_A => 173 | if ulpi_nxt = '1' then 174 | ulpi_data_out <= reg_data; 175 | state <= S_WriteReg_D; 176 | end if; 177 | 178 | when S_WriteReg_D => 179 | if ulpi_nxt = '1' then 180 | ulpi_data_out <= X"00"; 181 | state <= S_STP; 182 | end if; 183 | 184 | when S_Reset => 185 | usb_reset <= '1'; 186 | if hs_enabled = '0' and HIGH_SPEED then 187 | state <= S_ChirpStart; 188 | elsif HIGH_SPEED then 189 | state <= S_SwitchFSStart; 190 | else 191 | if usb_line_state /= "00" then 192 | state <= S_Idle; 193 | end if; 194 | end if; 195 | 196 | when S_Suspend => 197 | -- Should be J state for 20 ms, but I'm too lazy 198 | -- FIXME: Need valid resume sequence for HS 199 | if usb_line_state /= "01" then 200 | state <= S_Idle; 201 | end if; 202 | 203 | when S_STP => 204 | state <= state_after; 205 | 206 | when S_Idle => 207 | usb_reset <= '0'; 208 | if usb_line_state = "00" and state_counter > RESET_TIME then 209 | state <= S_Reset; 210 | elsif hs_enabled = '0' and usb_line_state = "01" and state_counter > SUSPEND_TIME then 211 | state <= S_Suspend; 212 | elsif bus_tx_ready = '1' and axis_tx_tvalid = '1' then 213 | ulpi_data_out <= "0100" & axis_tx_tdata(3 downto 0); 214 | buf_valid <= '0'; 215 | if axis_tx_tlast = '1' then 216 | state <= S_TX_Last; 217 | else 218 | state <= S_TX; 219 | end if; 220 | end if; 221 | 222 | when S_TX => 223 | if ulpi_nxt = '1' then 224 | if axis_tx_tvalid = '1' and buf_valid = '0' then 225 | ulpi_data_out <= axis_tx_tdata; 226 | if axis_tx_tlast = '1' then 227 | state <= S_TX_Last; 228 | end if; 229 | elsif buf_valid = '1' then 230 | ulpi_data_out <= buf_data; 231 | buf_valid <= '0'; 232 | if buf_last = '1' then 233 | state <= S_TX_Last; 234 | end if; 235 | else 236 | ulpi_data_out <= X"00"; 237 | end if; 238 | else 239 | if axis_tx_tvalid = '1' and buf_valid = '0' then 240 | buf_data <= axis_tx_tdata; 241 | buf_last <= axis_tx_tlast; 242 | buf_valid <= '1'; 243 | end if; 244 | end if; 245 | 246 | when S_TX_Last => 247 | if ulpi_nxt = '1' then 248 | ulpi_data_out <= X"00"; 249 | state_after <= S_Idle; 250 | state <= S_STP; 251 | end if; 252 | 253 | when S_ChirpStart => 254 | reg_data <= b"0_1_0_10_1_00"; 255 | ulpi_data_out <= X"84"; 256 | state <= S_WriteReg_A; 257 | state_after <= S_ChirpStartK; 258 | 259 | when S_ChirpStartK => 260 | if ulpi_nxt = '1' then 261 | ulpi_data_out <= X"00"; 262 | state <= S_ChirpK; 263 | else 264 | ulpi_data_out <= X"40"; 265 | end if; 266 | 267 | when S_ChirpK => 268 | if state_counter > CHIRP_K_TIME then 269 | ulpi_data_out <= X"00"; 270 | state <= S_STP; 271 | state_after <= S_ChirpKJ; 272 | end if; 273 | 274 | when S_ChirpKJ => 275 | if chirp_kj_counter > 3 AND state_counter > CHIRP_KJ_TIME then 276 | reg_data <= b"0_1_0_00_0_00"; 277 | ulpi_data_out <= X"84"; 278 | state <= S_WriteReg_A; 279 | state_after <= S_Idle; 280 | hs_enabled <= '1'; 281 | end if; 282 | 283 | when S_SwitchFSStart => 284 | reg_data <= b"0_1_0_00_1_01"; 285 | ulpi_data_out <= X"84"; 286 | state <= S_WriteReg_A; 287 | hs_enabled <= '0'; 288 | state_after <= S_SwitchFS; 289 | 290 | when S_SwitchFS => 291 | if state_counter > SWITCH_TIME then 292 | if usb_line_state = "00" AND HIGH_SPEED then 293 | state <= S_ChirpStart; 294 | else 295 | state <= S_Idle; 296 | end if; 297 | end if; 298 | 299 | end case; 300 | end if; 301 | end if; 302 | end if; 303 | end process; 304 | 305 | ulpi_stp <= '1' when ulpi_dir = '1' and axis_rx_tready = '0' else 306 | '1' when state = S_STP else 307 | '0'; 308 | 309 | ulpi_reset <= rst; 310 | 311 | bus_tx_ready <= '1' when ulpi_dir = '0' and ulpi_dir = dir_d else 312 | '0'; 313 | 314 | axis_tx_tready <= '1' when bus_tx_ready = '1' and state = S_Idle else 315 | '1' when bus_tx_ready = '1' and state = S_TX and buf_valid = '0' else 316 | '0'; 317 | 318 | usb_idle <= '1' when state = S_Idle else 319 | '0'; 320 | usb_suspend <= '1' when state = S_Suspend else 321 | '0'; 322 | end ulpi_port; 323 | -------------------------------------------------------------------------------- /Examples/SPI_Flasher/spi_flasher.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - spi_flasher.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.ALL; 27 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 28 | use IEEE.NUMERIC_STD.ALL; 29 | 30 | library UNISIM; 31 | use UNISIM.VCOMPONENTS.ALL; 32 | 33 | library work; 34 | use work.USBCore.all; 35 | use work.USBExtra.all; 36 | 37 | entity spi_flasher is 38 | port ( 39 | led : out std_logic; 40 | ulpi_data : inout std_logic_vector(7 downto 0); 41 | ulpi_dir : in std_logic; 42 | ulpi_nxt : in std_logic; 43 | ulpi_stp : out std_logic; 44 | ulpi_reset : out std_logic; 45 | ulpi_clk60 : in std_logic; 46 | 47 | spi_cs : out std_logic; 48 | spi_sck : out std_logic; 49 | spi_mosi : out std_logic; 50 | spi_miso : in std_logic 51 | ); 52 | end spi_flasher; 53 | 54 | architecture spi_flasher of spi_flasher is 55 | constant USE_HIGH_SPEED: boolean := true; 56 | 57 | constant CONFIG_DESC : BYTE_ARRAY(0 to 8) := ( 58 | X"09", -- bLength = 9 59 | X"02", -- bDescriptionType = Configuration Descriptor 60 | X"20", X"00", -- wTotalLength = 32 61 | X"01", -- bNumInterfaces = 1 62 | X"01", -- bConfigurationValue 63 | X"00", -- iConfiguration 64 | X"C0", -- bmAttributes = Self-powered 65 | X"32" -- bMaxPower = 100 mA 66 | ); 67 | 68 | constant INTERFACE_DESC : BYTE_ARRAY(0 to 8) := ( 69 | X"09", -- bLength = 9 70 | X"04", -- bDescriptorType = Interface Descriptor 71 | X"00", -- bInterfaceNumber = 0 72 | X"00", -- bAlternateSetting 73 | X"02", -- bNumEndpoints = 2 74 | X"00", -- bInterfaceClass 75 | X"00", -- bInterfaceSubClass 76 | X"00", -- bInterfaceProtocol 77 | X"00" -- iInterface 78 | ); 79 | 80 | constant EP1_IN_DESC : BYTE_ARRAY(0 to 6) := ( 81 | X"07", -- bLength = 7 82 | X"05", -- bDescriptorType = Endpoint Descriptor 83 | X"81", -- bEndpointAddress = IN1 84 | B"00_00_00_10", -- bmAttributes = Bulk 85 | X"00", X"02", -- wMaxPacketSize = 512 bytes 86 | X"00" -- bInterval 87 | ); 88 | 89 | constant EP1_OUT_DESC : BYTE_ARRAY(0 to 6) := ( 90 | X"07", -- bLength = 7 91 | X"05", -- bDescriptorType = Endpoint Descriptor 92 | X"01", -- bEndpointAddress = OUT1 93 | B"00_00_00_10", -- bmAttributes = Bulk 94 | X"00", X"02", -- wMaxPacketSize = 512 bytes 95 | X"00" -- bInterval 96 | ); 97 | 98 | signal ulpi_data_in : std_logic_vector(7 downto 0); 99 | signal ulpi_data_out : std_logic_vector(7 downto 0); 100 | 101 | signal usb_clk : std_logic; 102 | signal usb_reset : std_logic; 103 | 104 | signal usb_idle : std_logic; 105 | signal usb_suspend : std_logic; 106 | signal usb_configured : std_logic; 107 | signal usb_crc_error : std_logic; 108 | signal usb_sof : std_logic; 109 | 110 | signal ctl_xfer_endpoint : std_logic_vector(3 downto 0); 111 | signal ctl_xfer_type : std_logic_vector(7 downto 0); 112 | signal ctl_xfer_request : std_logic_vector(7 downto 0); 113 | signal ctl_xfer_value : std_logic_vector(15 downto 0); 114 | signal ctl_xfer_index : std_logic_vector(15 downto 0); 115 | signal ctl_xfer_length : std_logic_vector(15 downto 0); 116 | signal ctl_xfer_accept : std_logic; 117 | signal ctl_xfer : std_logic; 118 | signal ctl_xfer_done : std_logic; 119 | 120 | signal ctl_xfer_data_out : std_logic_vector(7 downto 0); 121 | signal ctl_xfer_data_out_valid: std_logic; 122 | 123 | signal ctl_xfer_data_in : std_logic_vector(7 downto 0); 124 | signal ctl_xfer_data_in_valid : std_logic; 125 | signal ctl_xfer_data_in_last : std_logic; 126 | signal ctl_xfer_data_in_ready : std_logic; 127 | 128 | signal blk_xfer_endpoint : std_logic_vector(3 downto 0); 129 | signal blk_in_xfer : std_logic; 130 | signal blk_out_xfer : std_logic; 131 | 132 | signal blk_xfer_in_has_data : std_logic; 133 | signal blk_xfer_in_data : std_logic_vector(7 downto 0); 134 | signal blk_xfer_in_data_valid : std_logic; 135 | signal blk_xfer_in_data_ready : std_logic; 136 | signal blk_xfer_in_data_last : std_logic; 137 | 138 | signal blk_xfer_out_ready_read: std_logic; 139 | signal blk_xfer_out_data : std_logic_vector(7 downto 0); 140 | signal blk_xfer_out_data_valid: std_logic; 141 | 142 | signal led_counter : std_logic_vector(25 downto 0); 143 | 144 | component usb_flasher is 145 | port ( 146 | clk : in std_logic; 147 | rst : in std_logic; 148 | 149 | ctl_xfer_endpoint : in std_logic_vector(3 downto 0); 150 | ctl_xfer_type : in std_logic_vector(7 downto 0); 151 | ctl_xfer_request : in std_logic_vector(7 downto 0); 152 | ctl_xfer_value : in std_logic_vector(15 downto 0); 153 | ctl_xfer_index : in std_logic_vector(15 downto 0); 154 | ctl_xfer_length : in std_logic_vector(15 downto 0); 155 | ctl_xfer_accept : out std_logic; 156 | ctl_xfer : in std_logic; 157 | ctl_xfer_done : out std_logic; 158 | 159 | ctl_xfer_data_out : in std_logic_vector(7 downto 0); 160 | ctl_xfer_data_out_valid : in std_logic; 161 | 162 | ctl_xfer_data_in : out std_logic_vector(7 downto 0); 163 | ctl_xfer_data_in_valid : out std_logic; 164 | ctl_xfer_data_in_last : out std_logic; 165 | ctl_xfer_data_in_ready : in std_logic; 166 | 167 | blk_xfer_endpoint : in std_logic_vector(3 downto 0); 168 | blk_in_xfer : in std_logic; 169 | blk_out_xfer : in std_logic; 170 | 171 | blk_xfer_in_has_data : out std_logic; 172 | blk_xfer_in_data : out std_logic_vector(7 downto 0); 173 | blk_xfer_in_data_valid : out std_logic; 174 | blk_xfer_in_data_ready : in std_logic; 175 | blk_xfer_in_data_last : out std_logic; 176 | 177 | blk_xfer_out_ready_read : out std_logic; 178 | blk_xfer_out_data : in std_logic_vector(7 downto 0); 179 | blk_xfer_out_data_valid : in std_logic; 180 | 181 | spi_cs : out std_logic; 182 | spi_sck : out std_logic; 183 | spi_mosi : out std_logic; 184 | spi_miso : in std_logic 185 | ); 186 | end component; 187 | 188 | begin 189 | ULPI_IO: for i in 7 downto 0 generate 190 | begin 191 | ULPI_IOBUF : IOBUF 192 | port map ( 193 | O => ulpi_data_in(i), 194 | IO => ulpi_data(i), 195 | I => ulpi_data_out(i), 196 | T => ulpi_dir 197 | ); 198 | end generate; 199 | 200 | USB_CONTROLLER: usb_tlp 201 | generic map ( 202 | VENDOR_ID => X"DEAD", 203 | PRODUCT_ID => X"BEEF", 204 | MANUFACTURER => "USBCore", 205 | PRODUCT => "SPI Flasher", 206 | SERIAL => "", 207 | CONFIG_DESC => CONFIG_DESC & INTERFACE_DESC & 208 | EP1_IN_DESC & EP1_OUT_DESC, 209 | HIGH_SPEED => USE_HIGH_SPEED 210 | ) 211 | port map ( 212 | ulpi_data_in => ulpi_data_in, 213 | ulpi_data_out => ulpi_data_out, 214 | ulpi_dir => ulpi_dir, 215 | ulpi_nxt => ulpi_nxt, 216 | ulpi_stp => ulpi_stp, 217 | ulpi_reset => ulpi_reset, 218 | ulpi_clk60 => ulpi_clk60, 219 | 220 | usb_clk => usb_clk, 221 | usb_reset => usb_reset, 222 | 223 | usb_idle => usb_idle, 224 | usb_suspend => usb_suspend, 225 | usb_configured => usb_configured, 226 | usb_crc_error => usb_crc_error, 227 | usb_sof => usb_sof, 228 | 229 | ctl_xfer_endpoint => ctl_xfer_endpoint, 230 | ctl_xfer_type => ctl_xfer_type, 231 | ctl_xfer_request => ctl_xfer_request, 232 | ctl_xfer_value => ctl_xfer_value, 233 | ctl_xfer_index => ctl_xfer_index, 234 | ctl_xfer_length => ctl_xfer_length, 235 | ctl_xfer_accept => ctl_xfer_accept, 236 | ctl_xfer => ctl_xfer, 237 | ctl_xfer_done => ctl_xfer_done, 238 | 239 | ctl_xfer_data_out => ctl_xfer_data_out, 240 | ctl_xfer_data_out_valid => ctl_xfer_data_out_valid, 241 | 242 | ctl_xfer_data_in => ctl_xfer_data_in, 243 | ctl_xfer_data_in_valid => ctl_xfer_data_in_valid, 244 | ctl_xfer_data_in_last => ctl_xfer_data_in_last, 245 | ctl_xfer_data_in_ready => ctl_xfer_data_in_ready, 246 | 247 | blk_xfer_endpoint => blk_xfer_endpoint, 248 | blk_in_xfer => blk_in_xfer, 249 | blk_out_xfer => blk_out_xfer, 250 | 251 | blk_xfer_in_has_data => blk_xfer_in_has_data, 252 | blk_xfer_in_data => blk_xfer_in_data, 253 | blk_xfer_in_data_valid => blk_xfer_in_data_valid, 254 | blk_xfer_in_data_ready => blk_xfer_in_data_ready, 255 | blk_xfer_in_data_last => blk_xfer_in_data_last, 256 | 257 | blk_xfer_out_ready_read => blk_xfer_out_ready_read, 258 | blk_xfer_out_data => blk_xfer_out_data, 259 | blk_xfer_out_data_valid => blk_xfer_out_data_valid 260 | ); 261 | 262 | FLASHER: usb_flasher 263 | port map ( 264 | clk => usb_clk, 265 | rst => usb_reset, 266 | 267 | ctl_xfer_endpoint => ctl_xfer_endpoint, 268 | ctl_xfer_type => ctl_xfer_type, 269 | ctl_xfer_request => ctl_xfer_request, 270 | ctl_xfer_value => ctl_xfer_value, 271 | ctl_xfer_index => ctl_xfer_index, 272 | ctl_xfer_length => ctl_xfer_length, 273 | ctl_xfer_accept => ctl_xfer_accept, 274 | ctl_xfer => ctl_xfer, 275 | ctl_xfer_done => ctl_xfer_done, 276 | 277 | ctl_xfer_data_out => ctl_xfer_data_out, 278 | ctl_xfer_data_out_valid => ctl_xfer_data_out_valid, 279 | 280 | ctl_xfer_data_in => ctl_xfer_data_in, 281 | ctl_xfer_data_in_valid => ctl_xfer_data_in_valid, 282 | ctl_xfer_data_in_last => ctl_xfer_data_in_last, 283 | ctl_xfer_data_in_ready => ctl_xfer_data_in_ready, 284 | 285 | blk_xfer_endpoint => blk_xfer_endpoint, 286 | blk_in_xfer => blk_in_xfer, 287 | blk_out_xfer => blk_out_xfer, 288 | 289 | blk_xfer_in_has_data => blk_xfer_in_has_data, 290 | blk_xfer_in_data => blk_xfer_in_data, 291 | blk_xfer_in_data_valid => blk_xfer_in_data_valid, 292 | blk_xfer_in_data_ready => blk_xfer_in_data_ready, 293 | blk_xfer_in_data_last => blk_xfer_in_data_last, 294 | 295 | blk_xfer_out_ready_read => blk_xfer_out_ready_read, 296 | blk_xfer_out_data => blk_xfer_out_data, 297 | blk_xfer_out_data_valid => blk_xfer_out_data_valid, 298 | 299 | spi_cs => spi_cs, 300 | spi_sck => spi_sck, 301 | spi_mosi => spi_mosi, 302 | spi_miso => spi_miso 303 | ); 304 | 305 | COUNT: process(usb_clk) is 306 | begin 307 | if rising_edge(usb_clk) then 308 | led_counter <= led_counter + 1; 309 | end if; 310 | end process; 311 | 312 | led <= '1' when usb_idle = '1' AND usb_configured = '1' else 313 | led_counter(led_counter'left) when usb_idle = '1' else 314 | '1' when led_counter(led_counter'left downto led_counter'left - 2) = "000" else 315 | '0'; 316 | 317 | end spi_flasher; 318 | -------------------------------------------------------------------------------- /Core/usb_std_request.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - usb_std_request.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.all; 27 | use IEEE.STD_LOGIC_UNSIGNED.all; 28 | use IEEE.NUMERIC_STD.all; 29 | 30 | library work; 31 | use work.USBCore.all; 32 | 33 | entity usb_std_request is 34 | generic ( 35 | VENDOR_ID : std_logic_vector(15 downto 0) := X"DEAD"; 36 | PRODUCT_ID : std_logic_vector(15 downto 0) := X"BEEF"; 37 | MANUFACTURER : string := ""; 38 | PRODUCT : string := ""; 39 | SERIAL : string := ""; 40 | CONFIG_DESC : BYTE_ARRAY := ( 41 | -- Configuration descriptor 42 | X"09", -- bLength = 9 43 | X"02", -- bDescriptionType = Configuration Descriptor 44 | X"12", X"00", -- wTotalLength = 18 45 | X"01", -- bNumInterfaces = 1 46 | X"01", -- bConfigurationValue 47 | X"00", -- iConfiguration 48 | X"C0", -- bmAttributes = Self-powered 49 | X"32", -- bMaxPower = 100 mA 50 | -- Interface descriptor 51 | X"09", -- bLength = 9 52 | X"04", -- bDescriptorType = Interface Descriptor 53 | X"00", -- bInterfaceNumber = 0 54 | X"00", -- bAlternateSetting 55 | X"00", -- bNumEndpoints = 0 56 | X"00", -- bInterfaceClass 57 | X"00", -- bInterfaceSubClass 58 | X"00", -- bInterfaceProtocol 59 | X"00" -- iInterface 60 | ); 61 | HIGH_SPEED: boolean := true 62 | ); 63 | port ( 64 | rst : in std_logic; 65 | clk : in std_logic; 66 | 67 | ctl_xfer_endpoint : in std_logic_vector(3 downto 0); 68 | ctl_xfer_type : in std_logic_vector(7 downto 0); 69 | ctl_xfer_request : in std_logic_vector(7 downto 0); 70 | ctl_xfer_value : in std_logic_vector(15 downto 0); 71 | ctl_xfer_index : in std_logic_vector(15 downto 0); 72 | ctl_xfer_length : in std_logic_vector(15 downto 0); 73 | ctl_xfer_accept : out std_logic; 74 | ctl_xfer : in std_logic; 75 | ctl_xfer_done : out std_logic; 76 | 77 | ctl_xfer_data_out : in std_logic_vector(7 downto 0); 78 | ctl_xfer_data_out_valid : in std_logic; 79 | 80 | ctl_xfer_data_in : out std_logic_vector(7 downto 0); 81 | ctl_xfer_data_in_valid : out std_logic; 82 | ctl_xfer_data_in_last : out std_logic; 83 | ctl_xfer_data_in_ready : in std_logic; 84 | 85 | device_address : out std_logic_vector(6 downto 0); 86 | current_configuration : out std_logic_vector(7 downto 0); 87 | configured : out std_logic := '0'; 88 | 89 | standart_request : out std_logic 90 | ); 91 | end usb_std_request; 92 | 93 | architecture usb_std_request of usb_std_request is 94 | function indexOrZero(s : in string; i : in std_logic_vector) 95 | return std_logic_vector is 96 | begin 97 | if s = "" then 98 | return X"00"; 99 | else 100 | return i; 101 | end if; 102 | end function; 103 | 104 | function string2descriptor(s : in string) 105 | return BYTE_ARRAY is 106 | variable a : BYTE_ARRAY(0 to 2 + 2 * s'length - 1); 107 | begin 108 | a(0) := std_logic_vector(to_unsigned(2 + 2 * s'length, 8)); 109 | a(1) := X"03"; 110 | if s'length > 0 then 111 | for i in s'range loop 112 | a(2 * (i - s'low) + 2) := std_logic_vector(to_unsigned(character'pos(s(i)), 8)); 113 | a(2 * (i - s'low) + 3) := (others => '0'); 114 | end loop; 115 | end if; 116 | return a; 117 | end function; 118 | 119 | function selectInt(cond : in boolean; a : in integer; b : integer) 120 | return integer is 121 | begin 122 | if cond then 123 | return a; 124 | else 125 | return b; 126 | end if; 127 | end function; 128 | 129 | function selectArray(cond : in boolean; a : in BYTE_ARRAY; b : BYTE_ARRAY) 130 | return BYTE_ARRAY is 131 | begin 132 | if cond then 133 | return a; 134 | else 135 | return b; 136 | end if; 137 | end function; 138 | 139 | constant DEVICE_DESC_FS : BYTE_ARRAY(0 to 17) := ( 140 | X"12", -- bLength = 18 141 | X"01", -- bDescriptionType = Device Descriptor 142 | X"10", X"01", -- bcdUSB = USB 1.1 143 | X"FF", -- bDeviceClass = None 144 | X"00", -- bDeviceSubClass 145 | X"00", -- bDeviceProtocol 146 | X"40", -- bMaxPacketSize = 64 147 | VENDOR_ID(7 downto 0), VENDOR_ID(15 downto 8), -- idVendor 148 | PRODUCT_ID(7 downto 0), PRODUCT_ID(15 downto 8), -- idProduct 149 | X"00", X"00", -- bcdDevice 150 | indexOrZero(MANUFACTURER, X"01"), -- iManufacturer 151 | indexOrZero(PRODUCT, X"02"), -- iProduct 152 | indexOrZero(SERIAL, X"03"), -- iSerialNumber 153 | X"01" -- bNumConfigurations = 1 154 | ); 155 | 156 | constant DEVICE_DESC_HS : BYTE_ARRAY(0 to 17) := ( 157 | X"12", -- bLength = 18 158 | X"01", -- bDescriptionType = Device Descriptor 159 | X"00", X"02", -- bcdUSB = USB 2.0 160 | X"FF", -- bDeviceClass = None 161 | X"00", -- bDeviceSubClass 162 | X"00", -- bDeviceProtocol 163 | X"40", -- bMaxPacketSize = 64 164 | VENDOR_ID(7 downto 0), VENDOR_ID(15 downto 8), -- idVendor 165 | PRODUCT_ID(7 downto 0), PRODUCT_ID(15 downto 8), -- idProduct 166 | X"00", X"00", -- bcdDevice 167 | indexOrZero(MANUFACTURER, X"01"), -- iManufacturer 168 | indexOrZero(PRODUCT, X"02"), -- iProduct 169 | indexOrZero(SERIAL, X"03"), -- iSerialNumber 170 | X"01" -- bNumConfigurations = 1 171 | ); 172 | 173 | constant DEVICE_DESC : BYTE_ARRAY(0 to 17) := selectArray(HIGH_SPEED, DEVICE_DESC_HS, DEVICE_DESC_FS); 174 | 175 | constant STR_DESC : BYTE_ARRAY(0 to 3) := ( 176 | X"04", -- bLength = 4 177 | X"03", -- bDescriptorType = String Descriptor 178 | X"09", X"04" 179 | ); 180 | constant MANUFACTURER_STR_DESC : BYTE_ARRAY(0 to 2 + 2 * MANUFACTURER'length - 1) := string2descriptor(MANUFACTURER); 181 | constant PRODUCT_STR_DESC : BYTE_ARRAY(0 to 2 + 2 * PRODUCT'length - 1) := string2descriptor(PRODUCT); 182 | constant SERIAL_STR_DESC : BYTE_ARRAY(0 to 2 + 2 * SERIAL'length - 1) := string2descriptor(SERIAL); 183 | 184 | constant DESC_SIZE_STR : integer := DEVICE_DESC'length + CONFIG_DESC'length + STR_DESC'length + 185 | MANUFACTURER_STR_DESC'length + PRODUCT_STR_DESC'length + SERIAL_STR_DESC'length; 186 | constant DESC_SIZE_NOSTR : integer := DEVICE_DESC'length + CONFIG_DESC'length; 187 | 188 | constant DESC_HAS_STRINGS : boolean := (MANUFACTURER'length > 0) or (PRODUCT'length > 0) or (SERIAL'length > 0); 189 | 190 | constant DESC_SIZE : integer := selectInt(DESC_HAS_STRINGS, DESC_SIZE_STR, DESC_SIZE_NOSTR); 191 | 192 | constant USB_DESC : BYTE_ARRAY(0 to DESC_SIZE - 1) := selectArray(DESC_HAS_STRINGS, 193 | DEVICE_DESC & CONFIG_DESC & STR_DESC 194 | & MANUFACTURER_STR_DESC & PRODUCT_STR_DESC & SERIAL_STR_DESC, 195 | DEVICE_DESC & CONFIG_DESC); 196 | 197 | constant DESC_CONFIG_START : integer := DEVICE_DESC'length; 198 | constant DESC_STRING_START : integer := DEVICE_DESC'length + CONFIG_DESC'length; 199 | 200 | type MACHINE is (S_Idle, S_GetDescriptor, S_SetConfiguration, S_SetAddress); 201 | 202 | signal state : MACHINE := S_Idle; 203 | 204 | signal mem_addr : std_logic_vector(7 downto 0); 205 | signal max_mem_addr : std_logic_vector(7 downto 0); 206 | 207 | -- 000 - None 208 | -- 001 - Get device descriptor 209 | -- 010 - Set address 210 | -- 011 - Get configuration descriptor 211 | -- 100 - Set configuration 212 | -- 101 - Get string descriptor 213 | signal req_type : std_logic_vector(2 downto 0); 214 | 215 | signal is_std_req : std_logic; 216 | signal is_dev_req : std_logic; 217 | signal handle_req : std_logic; 218 | 219 | begin 220 | MEM_ADDRESSER : process(clk) is 221 | begin 222 | if rising_edge(clk) then 223 | if state = S_Idle then 224 | if ctl_xfer = '1' then 225 | if req_type = "011" then 226 | mem_addr <= std_logic_vector(to_unsigned(DESC_CONFIG_START, mem_addr'length)); 227 | max_mem_addr <= std_logic_vector(to_unsigned(DESC_STRING_START - 1, mem_addr'length)); 228 | elsif DESC_HAS_STRINGS and req_type = "101" then 229 | if ctl_xfer_value(7 downto 0) = X"00" then 230 | mem_addr <= std_logic_vector(to_unsigned(DESC_STRING_START, mem_addr'length)); 231 | max_mem_addr <= std_logic_vector(to_unsigned(DESC_STRING_START + STR_DESC'length - 1, mem_addr'length)); 232 | elsif ctl_xfer_value(7 downto 0) = X"01" then 233 | mem_addr <= std_logic_vector(to_unsigned(DESC_STRING_START + STR_DESC'length, mem_addr'length)); 234 | max_mem_addr <= std_logic_vector(to_unsigned(DESC_STRING_START + STR_DESC'length + MANUFACTURER_STR_DESC'length - 1, mem_addr'length)); 235 | elsif ctl_xfer_value(7 downto 0) = X"02" then 236 | mem_addr <= std_logic_vector(to_unsigned(DESC_STRING_START + STR_DESC'length + MANUFACTURER_STR_DESC'length, mem_addr'length)); 237 | max_mem_addr <= std_logic_vector(to_unsigned(DESC_STRING_START + STR_DESC'length + MANUFACTURER_STR_DESC'length + 238 | PRODUCT_STR_DESC'length - 1, mem_addr'length)); 239 | elsif ctl_xfer_value(7 downto 0) = X"03" then 240 | mem_addr <= std_logic_vector(to_unsigned(DESC_STRING_START + STR_DESC'length + MANUFACTURER_STR_DESC'length + 241 | PRODUCT_STR_DESC'length, mem_addr'length)); 242 | max_mem_addr <= std_logic_vector(to_unsigned(DESC_SIZE - 1, mem_addr'length)); 243 | end if; 244 | else 245 | mem_addr <= (others => '0'); 246 | max_mem_addr <= std_logic_vector(to_unsigned(DESC_CONFIG_START - 1, mem_addr'length)); 247 | end if; 248 | else 249 | mem_addr <= (others => '0'); 250 | end if; 251 | elsif state = S_GetDescriptor and ctl_xfer_data_in_ready = '1' then 252 | if mem_addr /= max_mem_addr then 253 | mem_addr <= mem_addr + 1; 254 | end if; 255 | end if; 256 | end if; 257 | end process; 258 | 259 | FSM : process(clk) is 260 | begin 261 | if rising_edge(clk) then 262 | if rst = '1' then 263 | state <= S_Idle; 264 | device_address <= (others => '0'); 265 | else 266 | case state is 267 | when S_Idle => 268 | if ctl_xfer = '1' then 269 | if req_type = "001" or req_type = "011" or req_type = "101" then 270 | state <= S_GetDescriptor; 271 | elsif req_type = "010" then 272 | state <= S_SetAddress; 273 | elsif req_type = "100" then 274 | current_configuration <= ctl_xfer_value(7 downto 0); 275 | state <= S_SetConfiguration; 276 | end if; 277 | end if; 278 | 279 | when S_SetAddress => 280 | if ctl_xfer = '0' then 281 | state <= S_Idle; 282 | device_address <= ctl_xfer_value(6 downto 0); 283 | end if; 284 | 285 | when S_GetDescriptor => 286 | if ctl_xfer = '0' then 287 | state <= S_Idle; 288 | end if; 289 | 290 | when S_SetConfiguration => 291 | if ctl_xfer = '0' then 292 | configured <= '1'; 293 | state <= S_Idle; 294 | end if; 295 | 296 | end case; 297 | end if; 298 | end if; 299 | end process; 300 | 301 | req_type <= "001" when handle_req = '1' and ctl_xfer_request = X"06" and ctl_xfer_value(15 downto 8) = X"01" else 302 | "010" when handle_req = '1' and ctl_xfer_request = X"05" else 303 | "011" when handle_req = '1' and ctl_xfer_request = X"06" and ctl_xfer_value(15 downto 8) = X"02" else 304 | "100" when handle_req = '1' and ctl_xfer_request = X"09" else 305 | "101" when handle_req = '1' and ctl_xfer_request = X"06" and ctl_xfer_value(15 downto 8) = X"03" else 306 | "000"; 307 | 308 | is_std_req <= '1' when ctl_xfer_endpoint = X"0" and ctl_xfer_type(6 downto 5) = "00" else 309 | '0'; 310 | 311 | is_dev_req <= '1' when ctl_xfer_type(4 downto 0) = "00000" else 312 | '0'; 313 | 314 | handle_req <= is_std_req AND is_dev_req; 315 | 316 | standart_request <= is_std_req; 317 | 318 | ctl_xfer_data_in_valid <= '1' when state = S_GetDescriptor else 319 | '0'; 320 | 321 | ctl_xfer_data_in <= USB_DESC(conv_integer(mem_addr)); 322 | 323 | ctl_xfer_data_in_last <= '1' when state = S_GetDescriptor and mem_addr = max_mem_addr else 324 | '0'; 325 | 326 | ctl_xfer_done <= '1'; 327 | 328 | ctl_xfer_accept <= '0' when req_type = "000" else 329 | '1'; 330 | 331 | end usb_std_request; 332 | -------------------------------------------------------------------------------- /Core/usb_packet.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - usb_packet.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.all; 27 | use IEEE.STD_LOGIC_UNSIGNED.all; 28 | use IEEE.NUMERIC_STD.all; 29 | 30 | library work; 31 | use work.USBCore.all; 32 | 33 | entity usb_packet is 34 | port ( 35 | rst : in std_logic; 36 | clk : in std_logic; 37 | 38 | axis_rx_tvalid : in std_logic; 39 | axis_rx_tready : out std_logic; 40 | axis_rx_tlast : in std_logic; 41 | axis_rx_tdata : in std_logic_vector(7 downto 0); 42 | 43 | axis_tx_tvalid : out std_logic; 44 | axis_tx_tready : in std_logic; 45 | axis_tx_tlast : out std_logic; 46 | axis_tx_tdata : out std_logic_vector(7 downto 0); 47 | 48 | trn_type : out std_logic_vector(1 downto 0); 49 | trn_address : out std_logic_vector(6 downto 0); 50 | trn_endpoint : out std_logic_vector(3 downto 0); 51 | trn_start : out std_logic; 52 | 53 | -- DATA0/1/2 MDATA 54 | rx_trn_data_type : out std_logic_vector(1 downto 0); 55 | rx_trn_end : out std_logic; 56 | rx_trn_data : out std_logic_vector(7 downto 0); 57 | rx_trn_valid : out std_logic; 58 | 59 | rx_trn_hsk_type : out std_logic_vector(1 downto 0); 60 | rx_trn_hsk_received : out std_logic; 61 | 62 | -- 00 - ACK, 10 - NAK, 11 - STALL, 01 - NYET 63 | tx_trn_hsk_type : in std_logic_vector(1 downto 0); 64 | tx_trn_send_hsk : in std_logic; 65 | tx_trn_hsk_sended : out std_logic; 66 | 67 | -- DATA0/1/2 MDATA 68 | tx_trn_data_type : in std_logic_vector(1 downto 0); 69 | -- Set tx_trn_data_last to '1' when start for zero packet 70 | tx_trn_data_start : in std_logic; 71 | 72 | tx_trn_data : in std_logic_vector(7 downto 0); 73 | tx_trn_data_valid : in std_logic; 74 | tx_trn_data_ready : out std_logic; 75 | tx_trn_data_last : in std_logic; 76 | 77 | start_of_frame : out std_logic; 78 | crc_error : out std_logic; 79 | device_address : in std_logic_vector(6 downto 0) 80 | ); 81 | end usb_packet; 82 | 83 | architecture usb_packet of usb_packet is 84 | type RX_MACHINE is (S_Idle, S_SOF, S_SOFCRC, S_Token, S_TokenCRC, S_Data, S_DataCRC); 85 | type TX_MACHINE is (S_Idle, S_HSK, S_HSK_Wait, S_DataPID, S_Data, S_DataCRC1, S_DataCRC2); 86 | 87 | function crc5(data : std_logic_vector) return std_logic_vector is 88 | variable crc : std_logic_vector(4 downto 0); 89 | begin 90 | crc(4) := not ('1' xor data(10) xor data(7) xor data(5) xor data(4) xor data(1) xor data(0)); 91 | crc(3) := not ('1' xor data(9) xor data(6) xor data(4) xor data(3) xor data(0)); 92 | crc(2) := not ('1' xor data(10) xor data(8) xor data(7) xor data(4) xor data(3) xor data(2) xor data(1) xor data(0)); 93 | crc(1) := not ('0' xor data(9) xor data(7) xor data(6) xor data(3) xor data(2) xor data(1) xor data(0)); 94 | crc(0) := not ('1' xor data(8) xor data(6) xor data(5) xor data(2) xor data(1) xor data(0)); 95 | return crc; 96 | end; 97 | 98 | function crc16(d : std_logic_vector; c : std_logic_vector) return std_logic_vector is 99 | variable crc : std_logic_vector(15 downto 0); 100 | begin 101 | crc(0) := d(0) xor d(1) xor d(2) xor d(3) xor d(4) xor d(5) xor d(6) xor d(7) xor c(8) xor c(9) xor c(10) xor c(11) xor c(12) xor c(13) xor c(14) xor c(15); 102 | crc(1) := d(0) xor d(1) xor d(2) xor d(3) xor d(4) xor d(5) xor d(6) xor c(9) xor c(10) xor c(11) xor c(12) xor c(13) xor c(14) xor c(15); 103 | crc(2) := d(6) xor d(7) xor c(8) xor c(9); 104 | crc(3) := d(5) xor d(6) xor c(9) xor c(10); 105 | crc(4) := d(4) xor d(5) xor c(10) xor c(11); 106 | crc(5) := d(3) xor d(4) xor c(11) xor c(12); 107 | crc(6) := d(2) xor d(3) xor c(12) xor c(13); 108 | crc(7) := d(1) xor d(2) xor c(13) xor c(14); 109 | crc(8) := d(0) xor d(1) xor c(0) xor c(14) xor c(15); 110 | crc(9) := d(0) xor c(1) xor c(15); 111 | crc(10) := c(2); 112 | crc(11) := c(3); 113 | crc(12) := c(4); 114 | crc(13) := c(5); 115 | crc(14) := c(6); 116 | crc(15) := d(0) xor d(1) xor d(2) xor d(3) xor d(4) xor d(5) xor d(6) xor d(7) xor c(7) xor c(8) xor c(9) xor c(10) xor c(11) xor c(12) xor c(13) xor c(14) xor c(15); 117 | return crc; 118 | end; 119 | 120 | signal rx_state : RX_MACHINE := S_Idle; 121 | signal tx_state : TX_MACHINE := S_Idle; 122 | 123 | signal rx_crc5 : std_logic_vector(4 downto 0); 124 | 125 | signal rx_pid : std_logic_vector(3 downto 0); 126 | signal rx_counter : std_logic_vector(10 downto 0); 127 | 128 | signal token_data : std_logic_vector(10 downto 0); 129 | signal token_crc5 : std_logic_vector(4 downto 0); 130 | 131 | signal rx_crc16 : std_logic_vector(15 downto 0); 132 | signal rx_data_crc : std_logic_vector(15 downto 0); 133 | 134 | signal tx_crc16 : std_logic_vector(15 downto 0); 135 | signal tx_crc16_r : std_logic_vector(15 downto 0); 136 | 137 | signal rx_buf1 : std_logic_vector(7 downto 0); 138 | signal rx_buf2 : std_logic_vector(7 downto 0); 139 | 140 | signal tx_zero_packet : std_logic; 141 | 142 | begin 143 | RX_COUNT : process(clk) is 144 | begin 145 | if rising_edge(clk) then 146 | if rx_state = S_Idle then 147 | rx_counter <= (others => '0'); 148 | elsif axis_rx_tvalid = '1' then 149 | rx_counter <= rx_counter + 1; 150 | end if; 151 | end if; 152 | end process; 153 | 154 | DATA_CRC_CALC : process(clk) is 155 | begin 156 | if rising_edge(clk) then 157 | if rx_state = S_Idle then 158 | rx_crc16 <= (others => '1'); 159 | elsif rx_state = S_Data and axis_rx_tvalid = '1' and rx_counter > 1 then 160 | rx_crc16 <= crc16(rx_buf1, rx_crc16); 161 | end if; 162 | end if; 163 | end process; 164 | 165 | TX_DATA_CRC_CALC : process(clk) is 166 | begin 167 | if rising_edge(clk) then 168 | if tx_state = S_Idle then 169 | tx_crc16 <= (others => '1'); 170 | elsif tx_state = S_Data and axis_tx_tready = '1' and tx_trn_data_valid = '1' then 171 | tx_crc16 <= crc16(tx_trn_data, tx_crc16); 172 | end if; 173 | end if; 174 | end process; 175 | 176 | rx_trn_data <= rx_buf1; 177 | rx_trn_valid <= '1' when rx_state = S_Data and axis_rx_tvalid = '1' and rx_counter > 1 else 178 | '0'; 179 | 180 | rx_crc5 <= crc5(token_data); 181 | rx_data_crc <= rx_buf2 & rx_buf1; 182 | 183 | trn_address <= token_data(6 downto 0); 184 | trn_endpoint <= token_data(10 downto 7); 185 | 186 | RX_FSM : process(clk) is 187 | begin 188 | if rising_edge(clk) then 189 | if rst = '1' then 190 | start_of_frame <= '0'; 191 | crc_error <= '0'; 192 | trn_start <= '0'; 193 | rx_trn_end <= '0'; 194 | rx_trn_hsk_received <= '0'; 195 | rx_state <= S_Idle; 196 | else 197 | case rx_state is 198 | when S_Idle => 199 | start_of_frame <= '0'; 200 | crc_error <= '0'; 201 | trn_start <= '0'; 202 | rx_trn_end <= '0'; 203 | rx_trn_hsk_received <= '0'; 204 | 205 | if axis_rx_tvalid = '1' and rx_pid = (not axis_rx_tdata(7 downto 4)) then 206 | if rx_pid = "0101" then 207 | rx_state <= S_SOF; 208 | elsif rx_pid(1 downto 0) = "01" then 209 | trn_type <= rx_pid(3 downto 2); 210 | rx_state <= S_Token; 211 | elsif rx_pid(1 downto 0) = "11" then 212 | rx_trn_data_type <= rx_pid(3 downto 2); 213 | rx_state <= S_Data; 214 | elsif rx_pid(1 downto 0) = "10" then 215 | rx_trn_hsk_type <= rx_pid(3 downto 2); 216 | rx_trn_hsk_received <= '1'; 217 | end if; 218 | end if; 219 | 220 | when S_SOF => 221 | if axis_rx_tvalid = '1' then 222 | if rx_counter = 0 then 223 | token_data(7 downto 0) <= axis_rx_tdata; 224 | elsif rx_counter = 1 then 225 | token_data(10 downto 8) <= axis_rx_tdata(2 downto 0); 226 | token_crc5 <= axis_rx_tdata(7 downto 3); 227 | end if; 228 | if axis_rx_tlast = '1' then 229 | rx_state <= S_SOFCRC; 230 | end if; 231 | end if; 232 | 233 | when S_SOFCRC => 234 | if token_crc5 /= rx_crc5 then 235 | crc_error <= '1'; 236 | else 237 | start_of_frame <= '1'; 238 | end if; 239 | rx_state <= S_Idle; 240 | 241 | when S_Token => 242 | if axis_rx_tvalid = '1' then 243 | if rx_counter = 0 then 244 | token_data(7 downto 0) <= axis_rx_tdata; 245 | elsif rx_counter = 1 then 246 | token_data(10 downto 8) <= axis_rx_tdata(2 downto 0); 247 | token_crc5 <= axis_rx_tdata(7 downto 3); 248 | end if; 249 | if axis_rx_tlast = '1' then 250 | rx_state <= S_TokenCRC; 251 | end if; 252 | end if; 253 | 254 | when S_TokenCRC => 255 | if device_address = token_data(6 downto 0) then 256 | if token_crc5 = rx_crc5 then 257 | trn_start <= '1'; 258 | else 259 | crc_error <= '1'; 260 | end if; 261 | end if; 262 | rx_state <= S_Idle; 263 | 264 | when S_Data => 265 | if axis_rx_tvalid = '1' then 266 | if rx_counter = 0 then 267 | rx_buf1 <= axis_rx_tdata; 268 | elsif rx_counter = 1 then 269 | rx_buf2 <= axis_rx_tdata; 270 | else 271 | rx_buf1 <= rx_buf2; 272 | rx_buf2 <= axis_rx_tdata; 273 | end if; 274 | if axis_rx_tlast = '1' then 275 | rx_state <= S_DataCRC; 276 | end if; 277 | end if; 278 | 279 | when S_DataCRC => 280 | rx_trn_end <= '1'; 281 | if rx_data_crc /= rx_crc16 then 282 | crc_error <= '1'; 283 | end if; 284 | rx_state <= S_Idle; 285 | 286 | end case; 287 | end if; 288 | end if; 289 | end process; 290 | 291 | TX_FSM : process(clk) is 292 | begin 293 | if rising_edge(clk) then 294 | if rst = '1' then 295 | tx_state <= S_Idle; 296 | else 297 | case tx_state is 298 | when S_Idle => 299 | if tx_trn_send_hsk = '1' then 300 | tx_state <= S_HSK; 301 | elsif tx_trn_data_start = '1' then 302 | if tx_trn_data_last = '1' and tx_trn_data_valid = '0' then 303 | tx_zero_packet <= '1'; 304 | else 305 | tx_zero_packet <= '0'; 306 | end if; 307 | tx_state <= S_DataPID; 308 | end if; 309 | 310 | when S_HSK => 311 | if axis_tx_tready = '1' then 312 | tx_state <= S_HSK_Wait; 313 | end if; 314 | 315 | when S_HSK_Wait => 316 | if tx_trn_send_hsk = '0' then 317 | tx_state <= S_Idle; 318 | end if; 319 | 320 | when S_DataPID => 321 | if axis_tx_tready = '1' then 322 | if tx_zero_packet = '1' then 323 | tx_state <= S_DataCRC1; 324 | else 325 | tx_state <= S_Data; 326 | end if; 327 | end if; 328 | 329 | when S_Data => 330 | if axis_tx_tready = '1' and tx_trn_data_valid = '1' then 331 | if tx_trn_data_last = '1' then 332 | tx_state <= S_DataCRC1; 333 | end if; 334 | elsif tx_trn_data_valid = '0' then 335 | tx_state <= S_DataCRC2; 336 | end if; 337 | 338 | when S_DataCRC1 => 339 | if axis_tx_tready = '1' then 340 | tx_state <= S_DataCRC2; 341 | end if; 342 | 343 | when S_DataCRC2 => 344 | if axis_tx_tready = '1' then 345 | tx_state <= S_Idle; 346 | end if; 347 | 348 | end case; 349 | end if; 350 | end if; 351 | end process; 352 | 353 | axis_tx_tdata <= (not (tx_trn_data_type & "11")) & tx_trn_data_type & "11" when tx_state = S_DataPID else 354 | (not (tx_trn_hsk_type & "10")) & tx_trn_hsk_type & "10" when tx_state = S_HSK else 355 | tx_crc16_r(7 downto 0) when tx_state = S_DataCRC1 or (tx_state = S_Data and tx_trn_data_valid = '0') else 356 | tx_crc16_r(15 downto 8) when tx_state = S_DataCRC2 else 357 | tx_trn_data; 358 | 359 | axis_tx_tvalid <= '1' when tx_state = S_DataPID or tx_state = S_HSK or tx_state = S_DataCRC1 or tx_state = S_DataCRC2 else 360 | '1' when tx_state = S_Data else 361 | '0'; 362 | 363 | axis_tx_tlast <= '1' when tx_state = S_HSK else 364 | '1' when tx_state = S_DataCRC2 else 365 | '0'; 366 | 367 | tx_trn_data_ready <= axis_tx_tready when tx_state = S_Data else 368 | '0'; 369 | 370 | tx_trn_hsk_sended <= '1' when tx_state = S_HSK_Wait else 371 | '0'; 372 | 373 | tx_crc16_r <= (not (tx_crc16(0) & tx_crc16(1) & tx_crc16(2) & tx_crc16(3) & 374 | tx_crc16(4) & tx_crc16(5) & tx_crc16(6) & tx_crc16(7) & 375 | tx_crc16(8) & tx_crc16(9) & tx_crc16(10) & tx_crc16(11) & 376 | tx_crc16(12) & tx_crc16(13) & tx_crc16(14) & tx_crc16(15))); 377 | 378 | rx_pid <= axis_rx_tdata(3 downto 0); 379 | 380 | axis_rx_tready <= '1'; 381 | end usb_packet; 382 | -------------------------------------------------------------------------------- /Core/usb_tlp.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - usb_tlp.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.all; 27 | use IEEE.STD_LOGIC_UNSIGNED.all; 28 | use IEEE.NUMERIC_STD.all; 29 | 30 | library work; 31 | use work.USBCore.all; 32 | 33 | entity usb_tlp is 34 | generic ( 35 | VENDOR_ID : std_logic_vector(15 downto 0) := X"DEAD"; 36 | PRODUCT_ID : std_logic_vector(15 downto 0) := X"BEEF"; 37 | MANUFACTURER : string := ""; 38 | PRODUCT : string := ""; 39 | SERIAL : string := ""; 40 | CONFIG_DESC : BYTE_ARRAY := ( 41 | -- Configuration descriptor 42 | X"09", -- bLength = 9 43 | X"02", -- bDescriptionType = Configuration Descriptor 44 | X"12", X"00", -- wTotalLength = 18 45 | X"01", -- bNumInterfaces = 1 46 | X"01", -- bConfigurationValue 47 | X"00", -- iConfiguration 48 | X"C0", -- bmAttributes = Self-powered 49 | X"32", -- bMaxPower = 100 mA 50 | -- Interface descriptor 51 | X"09", -- bLength = 9 52 | X"04", -- bDescriptorType = Interface Descriptor 53 | X"00", -- bInterfaceNumber = 0 54 | X"00", -- bAlternateSetting 55 | X"00", -- bNumEndpoints = 0 56 | X"00", -- bInterfaceClass 57 | X"00", -- bInterfaceSubClass 58 | X"00", -- bInterfaceProtocol 59 | X"00" -- iInterface 60 | ); 61 | HIGH_SPEED : boolean := true 62 | ); 63 | port ( 64 | ulpi_data_in : in std_logic_vector(7 downto 0); 65 | ulpi_data_out : out std_logic_vector(7 downto 0); 66 | ulpi_dir : in std_logic; 67 | ulpi_nxt : in std_logic; 68 | ulpi_stp : out std_logic; 69 | ulpi_reset : out std_logic; 70 | ulpi_clk60 : in std_logic; 71 | 72 | usb_clk : out std_logic; 73 | usb_reset : out std_logic; 74 | 75 | usb_idle : out std_logic; 76 | usb_suspend : out std_logic; 77 | usb_configured : out std_logic; 78 | usb_crc_error : out std_logic; 79 | -- Pulse when SOF packet received 80 | usb_sof : out std_logic; 81 | 82 | -- Control transfer signals 83 | ctl_xfer_endpoint : out std_logic_vector(3 downto 0); 84 | ctl_xfer_type : out std_logic_vector(7 downto 0); 85 | ctl_xfer_request : out std_logic_vector(7 downto 0); 86 | ctl_xfer_value : out std_logic_vector(15 downto 0); 87 | ctl_xfer_index : out std_logic_vector(15 downto 0); 88 | ctl_xfer_length : out std_logic_vector(15 downto 0); 89 | ctl_xfer_accept : in std_logic; 90 | ctl_xfer : out std_logic; 91 | ctl_xfer_done : in std_logic; 92 | 93 | ctl_xfer_data_out : out std_logic_vector(7 downto 0); 94 | ctl_xfer_data_out_valid : out std_logic; 95 | 96 | ctl_xfer_data_in : in std_logic_vector(7 downto 0); 97 | ctl_xfer_data_in_valid : in std_logic; 98 | ctl_xfer_data_in_last : in std_logic; 99 | ctl_xfer_data_in_ready : out std_logic; 100 | 101 | -- Bulk transfer signals 102 | blk_xfer_endpoint : out std_logic_vector(3 downto 0); 103 | blk_in_xfer : out std_logic; 104 | blk_out_xfer : out std_logic; 105 | 106 | -- Has complete packet 107 | blk_xfer_in_has_data : in std_logic; 108 | blk_xfer_in_data : in std_logic_vector(7 downto 0); 109 | blk_xfer_in_data_valid : in std_logic; 110 | blk_xfer_in_data_ready : out std_logic; 111 | blk_xfer_in_data_last : in std_logic; 112 | 113 | -- Can accept full packet 114 | blk_xfer_out_ready_read : in std_logic; 115 | blk_xfer_out_data : out std_logic_vector(7 downto 0); 116 | blk_xfer_out_data_valid : out std_logic 117 | ); 118 | end usb_tlp; 119 | 120 | architecture usb_tlp of usb_tlp is 121 | signal axis_rx_tvalid : std_logic; 122 | signal axis_rx_tready : std_logic; 123 | signal axis_rx_tlast : std_logic; 124 | signal axis_rx_tdata : std_logic_vector(7 downto 0); 125 | 126 | signal axis_tx_tvalid : std_logic; 127 | signal axis_tx_tready : std_logic; 128 | signal axis_tx_tlast : std_logic; 129 | signal axis_tx_tdata : std_logic_vector(7 downto 0); 130 | 131 | signal usb_vbus_valid : std_logic; 132 | 133 | signal trn_type : std_logic_vector(1 downto 0); 134 | signal trn_address : std_logic_vector(6 downto 0); 135 | signal trn_endpoint : std_logic_vector(3 downto 0); 136 | signal trn_start : std_logic; 137 | 138 | signal rx_trn_data_type : std_logic_vector(1 downto 0); 139 | signal rx_trn_end : std_logic; 140 | signal rx_trn_data : std_logic_vector(7 downto 0); 141 | signal rx_trn_valid : std_logic; 142 | 143 | signal rx_trn_hsk_type : std_logic_vector(1 downto 0); 144 | signal rx_trn_hsk_received : std_logic; 145 | 146 | signal tx_trn_hsk_type : std_logic_vector(1 downto 0); 147 | signal tx_trn_send_hsk : std_logic; 148 | signal tx_trn_hsk_sended : std_logic; 149 | 150 | signal tx_trn_data_type : std_logic_vector(1 downto 0); 151 | signal tx_trn_data_start : std_logic; 152 | 153 | signal tx_trn_data : std_logic_vector(7 downto 0); 154 | signal tx_trn_data_valid : std_logic; 155 | signal tx_trn_data_ready : std_logic; 156 | signal tx_trn_data_last : std_logic; 157 | 158 | signal ctl_xfer_endpoint_int : std_logic_vector(3 downto 0); 159 | signal ctl_xfer_type_int : std_logic_vector(7 downto 0); 160 | signal ctl_xfer_request_int : std_logic_vector(7 downto 0); 161 | signal ctl_xfer_value_int : std_logic_vector(15 downto 0); 162 | signal ctl_xfer_index_int : std_logic_vector(15 downto 0); 163 | signal ctl_xfer_length_int : std_logic_vector(15 downto 0); 164 | signal ctl_xfer_accept_int : std_logic; 165 | signal ctl_xfer_int : std_logic; 166 | signal ctl_xfer_done_int : std_logic; 167 | 168 | signal ctl_xfer_accept_std : std_logic; 169 | signal ctl_xfer_std : std_logic; 170 | signal ctl_xfer_done_std : std_logic; 171 | 172 | signal ctl_xfer_data_out_int : std_logic_vector(7 downto 0); 173 | signal ctl_xfer_data_out_valid_int : std_logic; 174 | 175 | signal ctl_xfer_data_in_int : std_logic_vector(7 downto 0); 176 | signal ctl_xfer_data_in_valid_int : std_logic; 177 | signal ctl_xfer_data_in_last_int : std_logic; 178 | signal ctl_xfer_data_in_ready_int : std_logic; 179 | 180 | signal ctl_xfer_data_in_std : std_logic_vector(7 downto 0); 181 | signal ctl_xfer_data_in_valid_std : std_logic; 182 | signal ctl_xfer_data_in_last_std : std_logic; 183 | 184 | signal current_configuration : std_logic_vector(7 downto 0); 185 | 186 | signal usb_reset_int : std_logic; 187 | signal usb_crc_error_int : std_logic; 188 | 189 | signal standart_request : std_logic; 190 | 191 | signal device_address : std_logic_vector(6 downto 0); 192 | begin 193 | ULPI : ulpi_port 194 | generic map ( 195 | HIGH_SPEED => HIGH_SPEED 196 | ) 197 | port map ( 198 | rst => '0', 199 | 200 | ulpi_data_in => ulpi_data_in, 201 | ulpi_data_out => ulpi_data_out, 202 | ulpi_dir => ulpi_dir, 203 | ulpi_nxt => ulpi_nxt, 204 | ulpi_stp => ulpi_stp, 205 | ulpi_reset => ulpi_reset, 206 | ulpi_clk => ulpi_clk60, 207 | 208 | axis_rx_tvalid => axis_rx_tvalid, 209 | axis_rx_tready => axis_rx_tready, 210 | axis_rx_tlast => axis_rx_tlast, 211 | axis_rx_tdata => axis_rx_tdata, 212 | 213 | axis_tx_tvalid => axis_tx_tvalid, 214 | axis_tx_tready => axis_tx_tready, 215 | axis_tx_tlast => axis_tx_tlast, 216 | axis_tx_tdata => axis_tx_tdata, 217 | 218 | usb_vbus_valid => usb_vbus_valid, 219 | usb_reset => usb_reset_int, 220 | usb_idle => usb_idle, 221 | usb_suspend => usb_suspend 222 | ); 223 | 224 | PACKET_CONTROLLER : usb_packet 225 | port map ( 226 | rst => usb_reset_int, 227 | clk => ulpi_clk60, 228 | 229 | axis_rx_tvalid => axis_rx_tvalid, 230 | axis_rx_tready => axis_rx_tready, 231 | axis_rx_tlast => axis_rx_tlast, 232 | axis_rx_tdata => axis_rx_tdata, 233 | 234 | axis_tx_tvalid => axis_tx_tvalid, 235 | axis_tx_tready => axis_tx_tready, 236 | axis_tx_tlast => axis_tx_tlast, 237 | axis_tx_tdata => axis_tx_tdata, 238 | 239 | trn_type => trn_type, 240 | trn_address => trn_address, 241 | trn_endpoint => trn_endpoint, 242 | trn_start => trn_start, 243 | 244 | rx_trn_data_type => rx_trn_data_type, 245 | rx_trn_end => rx_trn_end, 246 | rx_trn_data => rx_trn_data, 247 | rx_trn_valid => rx_trn_valid, 248 | 249 | rx_trn_hsk_type => rx_trn_hsk_type, 250 | rx_trn_hsk_received => rx_trn_hsk_received, 251 | 252 | tx_trn_hsk_type => tx_trn_hsk_type, 253 | tx_trn_send_hsk => tx_trn_send_hsk, 254 | tx_trn_hsk_sended => tx_trn_hsk_sended, 255 | 256 | tx_trn_data_type => tx_trn_data_type, 257 | tx_trn_data_start => tx_trn_data_start, 258 | 259 | tx_trn_data => tx_trn_data, 260 | tx_trn_data_valid => tx_trn_data_valid, 261 | tx_trn_data_ready => tx_trn_data_ready, 262 | tx_trn_data_last => tx_trn_data_last, 263 | 264 | start_of_frame => usb_sof, 265 | crc_error => usb_crc_error_int, 266 | device_address => device_address 267 | ); 268 | 269 | TRANSFER_CONTROLLER : usb_xfer 270 | generic map ( 271 | HIGH_SPEED => HIGH_SPEED 272 | ) 273 | port map ( 274 | rst => usb_reset_int, 275 | clk => ulpi_clk60, 276 | 277 | trn_type => trn_type, 278 | trn_address => trn_address, 279 | trn_endpoint => trn_endpoint, 280 | trn_start => trn_start, 281 | 282 | rx_trn_data_type => rx_trn_data_type, 283 | rx_trn_end => rx_trn_end, 284 | rx_trn_data => rx_trn_data, 285 | rx_trn_valid => rx_trn_valid, 286 | 287 | rx_trn_hsk_type => rx_trn_hsk_type, 288 | rx_trn_hsk_received => rx_trn_hsk_received, 289 | 290 | tx_trn_hsk_type => tx_trn_hsk_type, 291 | tx_trn_send_hsk => tx_trn_send_hsk, 292 | tx_trn_hsk_sended => tx_trn_hsk_sended, 293 | 294 | tx_trn_data_type => tx_trn_data_type, 295 | tx_trn_data_start => tx_trn_data_start, 296 | 297 | tx_trn_data => tx_trn_data, 298 | tx_trn_data_valid => tx_trn_data_valid, 299 | tx_trn_data_ready => tx_trn_data_ready, 300 | tx_trn_data_last => tx_trn_data_last, 301 | 302 | crc_error => usb_crc_error_int, 303 | 304 | ctl_xfer_endpoint => ctl_xfer_endpoint_int, 305 | ctl_xfer_type => ctl_xfer_type_int, 306 | ctl_xfer_request => ctl_xfer_request_int, 307 | ctl_xfer_value => ctl_xfer_value_int, 308 | ctl_xfer_index => ctl_xfer_index_int, 309 | ctl_xfer_length => ctl_xfer_length_int, 310 | ctl_xfer_accept => ctl_xfer_accept_int, 311 | ctl_xfer => ctl_xfer_int, 312 | ctl_xfer_done => ctl_xfer_done_int, 313 | 314 | ctl_xfer_data_out => ctl_xfer_data_out_int, 315 | ctl_xfer_data_out_valid => ctl_xfer_data_out_valid_int, 316 | 317 | ctl_xfer_data_in => ctl_xfer_data_in_int, 318 | ctl_xfer_data_in_valid => ctl_xfer_data_in_valid_int, 319 | ctl_xfer_data_in_last => ctl_xfer_data_in_last_int, 320 | ctl_xfer_data_in_ready => ctl_xfer_data_in_ready_int, 321 | 322 | blk_xfer_endpoint => blk_xfer_endpoint, 323 | blk_in_xfer => blk_in_xfer, 324 | blk_out_xfer => blk_out_xfer, 325 | 326 | blk_xfer_in_has_data => blk_xfer_in_has_data, 327 | blk_xfer_in_data => blk_xfer_in_data, 328 | blk_xfer_in_data_valid => blk_xfer_in_data_valid, 329 | blk_xfer_in_data_ready => blk_xfer_in_data_ready, 330 | blk_xfer_in_data_last => blk_xfer_in_data_last, 331 | 332 | blk_xfer_out_ready_read => blk_xfer_out_ready_read, 333 | blk_xfer_out_data => blk_xfer_out_data, 334 | blk_xfer_out_data_valid => blk_xfer_out_data_valid 335 | ); 336 | 337 | STD_REQ_CONTROLLER : usb_std_request 338 | generic map ( 339 | VENDOR_ID => VENDOR_ID, 340 | PRODUCT_ID => PRODUCT_ID, 341 | MANUFACTURER => MANUFACTURER, 342 | PRODUCT => PRODUCT, 343 | SERIAL => SERIAL, 344 | CONFIG_DESC => CONFIG_DESC, 345 | HIGH_SPEED => HIGH_SPEED 346 | ) 347 | port map ( 348 | rst => usb_reset_int, 349 | clk => ulpi_clk60, 350 | 351 | ctl_xfer_endpoint => ctl_xfer_endpoint_int, 352 | ctl_xfer_type => ctl_xfer_type_int, 353 | ctl_xfer_request => ctl_xfer_request_int, 354 | ctl_xfer_value => ctl_xfer_value_int, 355 | ctl_xfer_index => ctl_xfer_index_int, 356 | ctl_xfer_length => ctl_xfer_length_int, 357 | ctl_xfer_accept => ctl_xfer_accept_std, 358 | ctl_xfer => ctl_xfer_int, 359 | ctl_xfer_done => ctl_xfer_done_std, 360 | 361 | ctl_xfer_data_out => ctl_xfer_data_out_int, 362 | ctl_xfer_data_out_valid => ctl_xfer_data_out_valid_int, 363 | 364 | ctl_xfer_data_in => ctl_xfer_data_in_std, 365 | ctl_xfer_data_in_valid => ctl_xfer_data_in_valid_std, 366 | ctl_xfer_data_in_last => ctl_xfer_data_in_last_std, 367 | ctl_xfer_data_in_ready => ctl_xfer_data_in_ready_int, 368 | 369 | device_address => device_address, 370 | current_configuration => current_configuration, 371 | configured => usb_configured, 372 | 373 | standart_request => standart_request 374 | ); 375 | 376 | usb_clk <= ulpi_clk60; 377 | usb_reset <= usb_reset_int; 378 | usb_crc_error <= usb_crc_error_int; 379 | 380 | ctl_xfer_endpoint <= ctl_xfer_endpoint_int; 381 | ctl_xfer_type <= ctl_xfer_type_int; 382 | ctl_xfer_request <= ctl_xfer_request_int; 383 | ctl_xfer_value <= ctl_xfer_value_int; 384 | ctl_xfer_index <= ctl_xfer_index_int; 385 | ctl_xfer_length <= ctl_xfer_length_int; 386 | 387 | ctl_xfer_accept_int <= ctl_xfer_accept_std when standart_request = '1' else 388 | ctl_xfer_accept; 389 | ctl_xfer <= ctl_xfer_int when standart_request = '0' else 390 | '0'; 391 | ctl_xfer_done_int <= ctl_xfer_done_std when standart_request = '1' else 392 | ctl_xfer_done; 393 | 394 | ctl_xfer_data_out <= ctl_xfer_data_out_int; 395 | ctl_xfer_data_out_valid <= ctl_xfer_data_out_valid_int when standart_request = '0' else 396 | '0'; 397 | 398 | ctl_xfer_data_in_int <= ctl_xfer_data_in_std when standart_request = '1' else 399 | ctl_xfer_data_in; 400 | ctl_xfer_data_in_valid_int <= ctl_xfer_data_in_valid_std when standart_request = '1' else 401 | ctl_xfer_data_in_valid; 402 | ctl_xfer_data_in_last_int <= ctl_xfer_data_in_last_std when standart_request = '1' else 403 | ctl_xfer_data_in_last; 404 | ctl_xfer_data_in_ready <= ctl_xfer_data_in_ready_int when standart_request = '0' else 405 | '0'; 406 | end usb_tlp; 407 | -------------------------------------------------------------------------------- /Extra/usb_flasher.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - usb_flasher.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.all; 27 | use IEEE.STD_LOGIC_UNSIGNED.all; 28 | use IEEE.NUMERIC_STD.all; 29 | 30 | library work; 31 | use work.USBCore.all; 32 | use work.USBExtra.all; 33 | 34 | entity usb_flasher is 35 | port ( 36 | clk : in std_logic; 37 | rst : in std_logic; 38 | 39 | ctl_xfer_endpoint : in std_logic_vector(3 downto 0); 40 | ctl_xfer_type : in std_logic_vector(7 downto 0); 41 | ctl_xfer_request : in std_logic_vector(7 downto 0); 42 | ctl_xfer_value : in std_logic_vector(15 downto 0); 43 | ctl_xfer_index : in std_logic_vector(15 downto 0); 44 | ctl_xfer_length : in std_logic_vector(15 downto 0); 45 | ctl_xfer_accept : out std_logic; 46 | ctl_xfer : in std_logic; 47 | ctl_xfer_done : out std_logic; 48 | 49 | ctl_xfer_data_out : in std_logic_vector(7 downto 0); 50 | ctl_xfer_data_out_valid : in std_logic; 51 | 52 | ctl_xfer_data_in : out std_logic_vector(7 downto 0); 53 | ctl_xfer_data_in_valid : out std_logic; 54 | ctl_xfer_data_in_last : out std_logic; 55 | ctl_xfer_data_in_ready : in std_logic; 56 | 57 | blk_xfer_endpoint : in std_logic_vector(3 downto 0); 58 | blk_in_xfer : in std_logic; 59 | blk_out_xfer : in std_logic; 60 | 61 | blk_xfer_in_has_data : out std_logic; 62 | blk_xfer_in_data : out std_logic_vector(7 downto 0); 63 | blk_xfer_in_data_valid : out std_logic; 64 | blk_xfer_in_data_ready : in std_logic; 65 | blk_xfer_in_data_last : out std_logic; 66 | 67 | blk_xfer_out_ready_read : out std_logic; 68 | blk_xfer_out_data : in std_logic_vector(7 downto 0); 69 | blk_xfer_out_data_valid : in std_logic; 70 | 71 | spi_cs : out std_logic; 72 | spi_sck : out std_logic; 73 | spi_mosi : out std_logic; 74 | spi_miso : in std_logic 75 | ); 76 | end usb_flasher; 77 | 78 | architecture usb_flasher of usb_flasher is 79 | type FLASH_MACHINE is (S_Idle, S_WriteCommand, S_ReadResponse, S_CtlResponse, S_CtlStartReceive, 80 | S_CtlReceive, S_WriteData, S_Wait, S_ReadResponseLast, S_PageProg, 81 | S_PageRead, S_PageReadLast); 82 | type SPI_MACHINE is (S_Idle, S_Xfer); 83 | 84 | signal spi_state : SPI_MACHINE; 85 | signal flash_state : FLASH_MACHINE; 86 | 87 | signal flash_clk : std_logic := '0'; 88 | signal flash_clk180 : std_logic; 89 | 90 | signal clk_en : std_logic; 91 | 92 | signal out_data : std_logic_vector(7 downto 0); 93 | signal in_data : std_logic_vector(7 downto 0); 94 | signal in_data_valid : std_logic; 95 | 96 | signal recieve_data : std_logic; 97 | signal recieve_data_d : std_logic; 98 | 99 | signal out_reg : std_logic_vector(7 downto 0); 100 | signal in_reg : std_logic_vector(7 downto 0); 101 | signal in_latch : std_logic; 102 | 103 | signal is_edge : std_logic; 104 | 105 | signal xfer_count : std_logic_vector(2 downto 0); 106 | signal xfer_last : std_logic; 107 | signal xfer_valid : std_logic; 108 | 109 | signal flash_cmd : std_logic_vector(7 downto 0); 110 | signal flash_resp_size : std_logic_vector(2 downto 0); 111 | 112 | signal flash_xfer_count : std_logic_vector(7 downto 0); 113 | signal flash_xfer_max_count : std_logic_vector(7 downto 0); 114 | 115 | signal data_dir : std_logic; 116 | signal page_prog : std_logic; 117 | signal page_read : std_logic; 118 | 119 | signal ctl_wr_addr : std_logic_vector(1 downto 0); 120 | signal ctl_rd_addr : std_logic_vector(1 downto 0); 121 | signal ctl_buf : BYTE_ARRAY(0 to 3); 122 | 123 | signal blk_out_tvalid : std_logic; 124 | signal blk_out_tready : std_logic; 125 | signal blk_out_tdata : std_logic_vector(7 downto 0); 126 | signal blk_out_tlast : std_logic; 127 | 128 | signal blk_in_tvalid : std_logic; 129 | signal blk_in_tready : std_logic; 130 | signal blk_in_tdata : std_logic_vector(7 downto 0); 131 | signal blk_in_tlast : std_logic; 132 | 133 | begin 134 | OUT_ENDPOINT: blk_ep_out_ctl 135 | generic map ( 136 | USE_ASYNC_FIFO => false 137 | ) 138 | port map ( 139 | rst => rst, 140 | usb_clk => clk, 141 | axis_clk => clk, 142 | 143 | blk_out_xfer => blk_out_xfer, 144 | 145 | blk_xfer_out_ready_read => blk_xfer_out_ready_read, 146 | blk_xfer_out_data => blk_xfer_out_data, 147 | blk_xfer_out_data_valid => blk_xfer_out_data_valid, 148 | 149 | axis_tdata => blk_out_tdata, 150 | axis_tvalid => blk_out_tvalid, 151 | axis_tready => blk_out_tready, 152 | axis_tlast => blk_out_tlast 153 | ); 154 | 155 | IN_ENDPOINT: blk_ep_in_ctl 156 | generic map ( 157 | USE_ASYNC_FIFO => false 158 | ) 159 | port map ( 160 | rst => rst, 161 | usb_clk => clk, 162 | axis_clk => clk, 163 | 164 | blk_in_xfer => blk_in_xfer, 165 | 166 | blk_xfer_in_has_data => blk_xfer_in_has_data, 167 | blk_xfer_in_data => blk_xfer_in_data, 168 | blk_xfer_in_data_valid => blk_xfer_in_data_valid, 169 | blk_xfer_in_data_ready => blk_xfer_in_data_ready, 170 | blk_xfer_in_data_last => blk_xfer_in_data_last, 171 | 172 | axis_tdata => blk_in_tdata, 173 | axis_tvalid => blk_in_tvalid, 174 | axis_tready => blk_in_tready, 175 | axis_tlast => blk_in_tlast 176 | ); 177 | 178 | flash_clk180 <= not flash_clk; 179 | 180 | CLK_GEN : process(clk) is 181 | begin 182 | if rising_edge(clk) then 183 | if spi_state = S_Xfer then 184 | flash_clk <= not flash_clk; 185 | else 186 | flash_clk <= '0'; 187 | end if; 188 | end if; 189 | end process; 190 | 191 | is_edge <= flash_clk; 192 | 193 | SPI_OUT : process(clk) is 194 | begin 195 | if rising_edge(clk) then 196 | if (spi_state = S_Idle and xfer_valid = '1') or 197 | (spi_state = S_Xfer and xfer_count = "000" and xfer_valid = '1' and is_edge = '1') then 198 | out_reg <= out_data; 199 | elsif is_edge = '1' and spi_state = S_Xfer then 200 | out_reg(7) <= out_reg(6); 201 | out_reg(6) <= out_reg(5); 202 | out_reg(5) <= out_reg(4); 203 | out_reg(4) <= out_reg(3); 204 | out_reg(3) <= out_reg(2); 205 | out_reg(2) <= out_reg(1); 206 | out_reg(1) <= out_reg(0); 207 | end if; 208 | end if; 209 | end process; 210 | 211 | SPI_IN : process(clk) is 212 | begin 213 | if rising_edge(clk) then 214 | --if (spi_state = S_Idle AND xfer_valid = '1') OR 215 | -- (spi_state = S_Xfer AND xfer_count = "000" AND xfer_valid = '1' AND is_edge = '1') then 216 | -- out_reg <= out_data; 217 | if is_edge = '1' and spi_state = S_Xfer then 218 | in_reg(7) <= in_reg(6); 219 | in_reg(6) <= in_reg(5); 220 | in_reg(5) <= in_reg(4); 221 | in_reg(4) <= in_reg(3); 222 | in_reg(3) <= in_reg(2); 223 | in_reg(2) <= in_reg(1); 224 | in_reg(1) <= in_reg(0); 225 | in_reg(0) <= spi_miso; 226 | end if; 227 | 228 | recieve_data_d <= recieve_data; 229 | 230 | if is_edge = '1' and spi_state = S_Xfer and xfer_count = "000" and recieve_data_d = '1' then 231 | in_latch <= '1'; 232 | else 233 | in_latch <= '0'; 234 | end if; 235 | 236 | if in_latch = '1' then 237 | in_data <= in_reg; 238 | in_data_valid <= '1'; 239 | else 240 | in_data_valid <= '0'; 241 | end if; 242 | 243 | end if; 244 | end process; 245 | 246 | SPI_FSM : process(clk) is 247 | begin 248 | if rising_edge(clk) then 249 | if rst = '1' then 250 | spi_state <= S_Idle; 251 | else 252 | case spi_state is 253 | when S_Idle => 254 | if xfer_valid = '1' then 255 | spi_state <= S_Xfer; 256 | xfer_count <= (others => '0'); 257 | end if; 258 | 259 | when S_Xfer => 260 | if is_edge = '0' then 261 | xfer_count <= xfer_count + 1; 262 | else 263 | if xfer_count = "000" then 264 | if xfer_valid = '0' then 265 | spi_state <= S_Idle; 266 | end if; 267 | end if; 268 | end if; 269 | 270 | end case; 271 | end if; 272 | end if; 273 | end process; 274 | 275 | CTL_BUFFER : process(clk) is 276 | begin 277 | if rising_edge(clk) then 278 | if flash_state = S_Idle then 279 | ctl_wr_addr <= (others => '0'); 280 | ctl_rd_addr <= (others => '0'); 281 | elsif flash_state = S_ReadResponse or flash_state = S_ReadResponseLast then 282 | if in_data_valid = '1' then 283 | ctl_buf(to_integer(unsigned(ctl_wr_addr))) <= in_data; 284 | ctl_wr_addr <= ctl_wr_addr + 1; 285 | end if; 286 | elsif flash_state = S_CtlResponse then 287 | if ctl_xfer_data_in_ready = '1' then 288 | ctl_rd_addr <= ctl_rd_addr + 1; 289 | end if; 290 | elsif flash_state = S_CtlReceive then 291 | if ctl_xfer_data_out_valid = '1' then 292 | ctl_buf(to_integer(unsigned(ctl_wr_addr))) <= ctl_xfer_data_out; 293 | ctl_wr_addr <= ctl_wr_addr + 1; 294 | end if; 295 | elsif flash_state = S_WriteData then 296 | if xfer_last = '1' then 297 | ctl_rd_addr <= ctl_rd_addr + 1; 298 | end if; 299 | end if; 300 | end if; 301 | end process; 302 | 303 | FLASH_FSM : process(clk) is 304 | begin 305 | if rising_edge(clk) then 306 | if rst = '1' then 307 | flash_state <= S_Idle; 308 | else 309 | case flash_state is 310 | when S_Idle => 311 | if ctl_xfer = '1' then 312 | data_dir <= ctl_xfer_type(7); 313 | if ctl_xfer_request(7 downto 2) = "000001" then 314 | flash_cmd <= ctl_xfer_value(7 downto 0); 315 | flash_resp_size <= ctl_xfer_length(2 downto 0); 316 | 317 | if ctl_xfer_type(7) = '1' then 318 | flash_state <= S_WriteCommand; 319 | else 320 | flash_state <= S_CtlStartReceive; 321 | end if; 322 | 323 | if ctl_xfer_request(0) = '1' then 324 | page_prog <= '1'; 325 | else 326 | page_prog <= '0'; 327 | end if; 328 | 329 | if ctl_xfer_request(1) = '1' then 330 | page_read <= '1'; 331 | else 332 | page_read <= '0'; 333 | end if; 334 | 335 | ctl_xfer_accept <= '1'; 336 | ctl_xfer_done <= '0'; 337 | else 338 | ctl_xfer_accept <= '0'; 339 | ctl_xfer_done <= '1'; 340 | end if; 341 | else 342 | ctl_xfer_accept <= '0'; 343 | ctl_xfer_done <= '1'; 344 | end if; 345 | 346 | when S_WriteCommand => 347 | if xfer_last = '1' then 348 | if flash_resp_size = 0 then 349 | flash_state <= S_Wait; 350 | else 351 | flash_xfer_count <= flash_xfer_max_count; 352 | if data_dir = '1' then 353 | flash_state <= S_ReadResponse; 354 | else 355 | flash_state <= S_WriteData; 356 | end if; 357 | end if; 358 | end if; 359 | 360 | when S_ReadResponse => 361 | if xfer_last = '1' then 362 | if flash_xfer_count = 0 then 363 | flash_state <= S_ReadResponseLast; 364 | else 365 | flash_xfer_count <= flash_xfer_count - 1; 366 | end if; 367 | end if; 368 | 369 | when S_ReadResponseLast => 370 | if in_data_valid = '1' then 371 | flash_xfer_count <= flash_xfer_max_count; 372 | ctl_xfer_done <= '1'; 373 | flash_state <= S_CtlResponse; 374 | end if; 375 | 376 | when S_CtlResponse => 377 | if ctl_xfer_data_in_ready = '1' then 378 | if flash_xfer_count = 0 then 379 | flash_state <= S_Wait; 380 | else 381 | flash_xfer_count <= flash_xfer_count - 1; 382 | end if; 383 | end if; 384 | 385 | when S_CtlStartReceive => 386 | if flash_resp_size > 0 then 387 | flash_xfer_count <= flash_xfer_max_count; 388 | flash_state <= S_CtlReceive; 389 | else 390 | flash_state <= S_WriteCommand; 391 | end if; 392 | 393 | when S_CtlReceive => 394 | if ctl_xfer_data_out_valid = '1' then 395 | if flash_xfer_count = 0 then 396 | flash_state <= S_WriteCommand; 397 | else 398 | flash_xfer_count <= flash_xfer_count - 1; 399 | end if; 400 | end if; 401 | 402 | when S_WriteData => 403 | if xfer_last = '1' then 404 | if flash_xfer_count = 0 then 405 | if page_prog = '0' and page_read = '0' then 406 | flash_state <= S_Wait; 407 | elsif page_prog = '1' and blk_out_tvalid = '0' then 408 | flash_state <= S_Wait; 409 | elsif page_prog = '1' then 410 | flash_state <= S_PageProg; 411 | elsif page_read = '1' then 412 | flash_xfer_count <= (others => '1'); 413 | flash_state <= S_PageRead; 414 | end if; 415 | else 416 | flash_xfer_count <= flash_xfer_count - 1; 417 | end if; 418 | end if; 419 | 420 | when S_Wait => 421 | ctl_xfer_done <= '1'; 422 | if ctl_xfer = '0' then 423 | flash_state <= S_Idle; 424 | end if; 425 | 426 | when S_PageProg => 427 | if xfer_last = '1' then 428 | if blk_out_tvalid = '0' then 429 | flash_state <= S_Wait; 430 | end if; 431 | end if; 432 | 433 | when S_PageRead => 434 | if xfer_last = '1' then 435 | if flash_xfer_count = 0 then 436 | flash_state <= S_PageReadLast; 437 | else 438 | flash_xfer_count <= flash_xfer_count - 1; 439 | end if; 440 | end if; 441 | 442 | when S_PageReadLast => 443 | if in_data_valid = '1' then 444 | flash_state <= S_Wait; 445 | end if; 446 | 447 | end case; 448 | end if; 449 | end if; 450 | end process; 451 | 452 | flash_xfer_max_count <= "00000" & (flash_resp_size - 1); --when flash_state = S_ReadResponseLast OR flash_state = S_WriteCommand 453 | 454 | out_data <= ctl_buf(to_integer(unsigned(ctl_rd_addr))) when flash_state = S_WriteData else 455 | blk_out_tdata when flash_state = S_PageProg else 456 | flash_cmd; 457 | 458 | xfer_valid <= '1' when flash_state = S_WriteCommand or flash_state = S_ReadResponse or 459 | flash_state = S_WriteData or flash_state = S_PageProg or 460 | flash_state = S_PageRead else 461 | '0'; 462 | 463 | recieve_data <= '1' when flash_state = S_ReadResponse or flash_state = S_PageRead else 464 | '0'; 465 | 466 | xfer_last <= '1' when xfer_count = "111" and is_edge = '0' else 467 | '0'; 468 | 469 | ctl_xfer_data_in <= ctl_buf(to_integer(unsigned(ctl_rd_addr))); 470 | ctl_xfer_data_in_valid <= '1' when flash_state = S_CtlResponse else 471 | '0'; 472 | ctl_xfer_data_in_last <= '1' when flash_state = S_CtlResponse and flash_xfer_count = 0 else 473 | '0'; 474 | 475 | blk_out_tready <= '1' when flash_state = S_PageProg and xfer_count = "000" and is_edge = '1' else 476 | '0'; 477 | 478 | blk_in_tlast <= '1' when flash_state = S_PageReadLast else 479 | '0'; 480 | blk_in_tdata <= in_data; 481 | blk_in_tvalid <= in_data_valid when flash_state = S_PageRead or flash_state = S_PageReadLast else 482 | '0'; 483 | 484 | spi_mosi <= out_reg(7); 485 | spi_sck <= flash_clk; 486 | spi_cs <= '0' when spi_state = S_Xfer else 487 | '1'; 488 | 489 | end usb_flasher; 490 | -------------------------------------------------------------------------------- /Core/usb_xfer.vhdl: -------------------------------------------------------------------------------- 1 | -- 2 | -- USB Full-Speed/Hi-Speed Device Controller core - usb_xfer.vhdl 3 | -- 4 | -- Copyright (c) 2015 Konstantin Oblaukhov 5 | -- 6 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 7 | -- of this software and associated documentation files (the "Software"), to deal 8 | -- in the Software without restriction, including without limitation the rights 9 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | -- copies of the Software, and to permit persons to whom the Software is 11 | -- furnished to do so, subject to the following conditions: 12 | -- 13 | -- The above copyright notice and this permission notice shall be included in 14 | -- all copies or substantial portions of the Software. 15 | -- 16 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | -- THE SOFTWARE. 23 | -- 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.all; 27 | use IEEE.STD_LOGIC_UNSIGNED.all; 28 | use IEEE.NUMERIC_STD.all; 29 | 30 | library work; 31 | use work.USBCore.all; 32 | 33 | entity usb_xfer is 34 | generic ( 35 | HIGH_SPEED: boolean := true 36 | ); 37 | port ( 38 | rst : in std_logic; 39 | clk : in std_logic; 40 | 41 | trn_type : in std_logic_vector(1 downto 0); 42 | trn_address : in std_logic_vector(6 downto 0); 43 | trn_endpoint : in std_logic_vector(3 downto 0); 44 | trn_start : in std_logic; 45 | 46 | -- DATA0/1/2 MDATA 47 | rx_trn_data_type : in std_logic_vector(1 downto 0); 48 | rx_trn_end : in std_logic; 49 | rx_trn_data : in std_logic_vector(7 downto 0); 50 | rx_trn_valid : in std_logic; 51 | 52 | rx_trn_hsk_type : in std_logic_vector(1 downto 0); 53 | rx_trn_hsk_received : in std_logic; 54 | 55 | -- 00 - ACK, 10 - NAK, 11 - STALL, 01 - NYET 56 | tx_trn_hsk_type : out std_logic_vector(1 downto 0); 57 | tx_trn_send_hsk : out std_logic; 58 | tx_trn_hsk_sended : in std_logic; 59 | 60 | tx_trn_data_type : out std_logic_vector(1 downto 0); 61 | tx_trn_data_start : out std_logic; 62 | 63 | tx_trn_data : out std_logic_vector(7 downto 0); 64 | tx_trn_data_valid : out std_logic; 65 | tx_trn_data_ready : in std_logic; 66 | tx_trn_data_last : out std_logic; 67 | 68 | crc_error : in std_logic; 69 | 70 | ctl_xfer_endpoint : out std_logic_vector(3 downto 0); 71 | ctl_xfer_type : out std_logic_vector(7 downto 0); 72 | ctl_xfer_request : out std_logic_vector(7 downto 0); 73 | ctl_xfer_value : out std_logic_vector(15 downto 0); 74 | ctl_xfer_index : out std_logic_vector(15 downto 0); 75 | ctl_xfer_length : out std_logic_vector(15 downto 0); 76 | ctl_xfer_accept : in std_logic; 77 | -- '1' when processing control transfer 78 | ctl_xfer : out std_logic; 79 | -- '1' when control request completed 80 | ctl_xfer_done : in std_logic; 81 | 82 | ctl_xfer_data_out : out std_logic_vector(7 downto 0); 83 | ctl_xfer_data_out_valid : out std_logic; 84 | 85 | ctl_xfer_data_in : in std_logic_vector(7 downto 0); 86 | ctl_xfer_data_in_valid : in std_logic; 87 | ctl_xfer_data_in_last : in std_logic; 88 | ctl_xfer_data_in_ready : out std_logic; 89 | 90 | blk_xfer_endpoint : out std_logic_vector(3 downto 0); 91 | blk_in_xfer : out std_logic; 92 | blk_out_xfer : out std_logic; 93 | 94 | -- Has complete packet 95 | blk_xfer_in_has_data : in std_logic; 96 | blk_xfer_in_data : in std_logic_vector(7 downto 0); 97 | blk_xfer_in_data_valid : in std_logic; 98 | blk_xfer_in_data_ready : out std_logic; 99 | blk_xfer_in_data_last : in std_logic; 100 | 101 | -- Can accept full packet 102 | blk_xfer_out_ready_read : in std_logic; 103 | blk_xfer_out_data : out std_logic_vector(7 downto 0); 104 | blk_xfer_out_data_valid : out std_logic 105 | ); 106 | end usb_xfer; 107 | 108 | architecture usb_xfer of usb_xfer is 109 | type MACHINE is (S_Idle, S_ControlSetup, S_ControlSetupACK, S_ControlWaitDataIN, 110 | S_ControlDataIN, S_ControlDataIN_Z, S_ControlDataIN_ACK, S_ControlWaitDataOUT, 111 | S_ControlDataOUT, S_ControlDataOUT_MyACK, S_ControlStatusOUT, S_ControlStatusOUT_D, 112 | S_ControlStatusOUT_ACK, S_ControlStatusIN, S_ControlStatusIN_MyACK, S_ControlStatusIN_D, 113 | S_ControlStatusIN_ACK, S_BulkIN, S_BulkIN_MyACK, S_BulkIN_ACK, S_BulkOUT, 114 | S_BulkOUT_ACK); 115 | 116 | signal state : MACHINE := S_Idle; 117 | 118 | signal rx_counter : std_logic_vector(10 downto 0); 119 | signal tx_counter : std_logic_vector(15 downto 0); 120 | 121 | signal ctl_xfer_length_int : std_logic_vector(15 downto 0); 122 | signal ctl_xfer_type_int : std_logic_vector(7 downto 0); 123 | 124 | signal data_types : std_logic_vector(15 downto 0); 125 | signal current_endpoint : std_logic_vector(3 downto 0); 126 | 127 | signal ctl_status : std_logic_vector(1 downto 0); 128 | signal ctl_xfer_eop : std_logic; 129 | 130 | signal tx_counter_over : std_logic; 131 | 132 | begin 133 | RX_DATA_COUNT : process(clk) is 134 | begin 135 | if rising_edge(clk) then 136 | if state = S_Idle or state = S_ControlSetupACK then 137 | rx_counter <= (others => '0'); 138 | elsif rx_trn_valid = '1' then 139 | rx_counter <= rx_counter + 1; 140 | end if; 141 | end if; 142 | end process; 143 | 144 | BIT_TOGGLING : process(clk) is 145 | variable i : integer; 146 | begin 147 | if rising_edge(clk) then 148 | if rst = '1' then 149 | data_types <= (others => '0'); 150 | else 151 | i := to_integer(unsigned(current_endpoint)); 152 | if state = S_ControlSetupACK then 153 | data_types(i) <= '1'; 154 | elsif state = S_ControlDataIN_ACK then 155 | if rx_trn_hsk_received = '1' and rx_trn_hsk_type = "00" then 156 | data_types(i) <= not data_types(i); 157 | end if; 158 | elsif state = S_ControlStatusIN_ACK then 159 | if rx_trn_hsk_received = '1' and rx_trn_hsk_type = "00" then 160 | data_types(i) <= not data_types(i); 161 | end if; 162 | elsif state = S_BulkIN_ACK then 163 | if rx_trn_hsk_received = '1' and rx_trn_hsk_type = "00" then 164 | data_types(i) <= not data_types(i); 165 | end if; 166 | elsif state = S_BulkOUT_ACK then 167 | if tx_trn_hsk_sended = '1' and ctl_status = "00" then 168 | data_types(i) <= not data_types(i); 169 | end if; 170 | end if; 171 | end if; 172 | end if; 173 | end process; 174 | 175 | FSM : process(clk) is 176 | begin 177 | if rising_edge(clk) then 178 | if rst = '1' then 179 | state <= S_Idle; 180 | ctl_xfer <= '0'; 181 | else 182 | case state is 183 | when S_Idle => 184 | ctl_xfer <= '0'; 185 | blk_in_xfer <= '0'; 186 | blk_out_xfer <= '0'; 187 | 188 | if trn_start = '1' then 189 | if trn_type = "11" then 190 | state <= S_ControlSetup; 191 | current_endpoint <= trn_endpoint; 192 | elsif trn_type = "10" then 193 | current_endpoint <= trn_endpoint; 194 | if blk_xfer_in_has_data = '1' then 195 | blk_in_xfer <= '1'; 196 | tx_trn_data_start <= '1'; 197 | tx_counter <= (others => '0'); 198 | state <= S_BulkIN; 199 | else 200 | ctl_status <= "11"; 201 | state <= S_BulkIN_MyACK; 202 | end if; 203 | elsif trn_type = "00" then 204 | blk_out_xfer <= '1'; 205 | current_endpoint <= trn_endpoint; 206 | if blk_xfer_out_ready_read = '1' then 207 | ctl_status <= "00"; 208 | else 209 | ctl_status <= "11"; 210 | end if; 211 | state <= S_BulkOUT; 212 | end if; 213 | end if; 214 | 215 | when S_ControlSetup => 216 | if rx_trn_valid = '1' then 217 | if rx_counter = 0 then 218 | ctl_xfer_type_int <= rx_trn_data; 219 | elsif rx_counter = 1 then 220 | ctl_xfer_request <= rx_trn_data; 221 | elsif rx_counter = 2 then 222 | ctl_xfer_value(7 downto 0) <= rx_trn_data; 223 | elsif rx_counter = 3 then 224 | ctl_xfer_value(15 downto 8) <= rx_trn_data; 225 | elsif rx_counter = 4 then 226 | ctl_xfer_index(7 downto 0) <= rx_trn_data; 227 | elsif rx_counter = 5 then 228 | ctl_xfer_index(15 downto 8) <= rx_trn_data; 229 | elsif rx_counter = 6 then 230 | ctl_xfer_length_int(7 downto 0) <= rx_trn_data; 231 | elsif rx_counter = 7 then 232 | ctl_xfer_length_int(15 downto 8) <= rx_trn_data; 233 | state <= S_ControlSetupACK; 234 | ctl_xfer <= '1'; 235 | end if; 236 | end if; 237 | 238 | when S_ControlSetupACK => 239 | if tx_trn_hsk_sended = '1' then 240 | if ctl_xfer_length_int = 0 then 241 | if ctl_xfer_type_int(7) = '1' then 242 | state <= S_ControlStatusOUT; 243 | else 244 | state <= S_ControlStatusIN; 245 | end if; 246 | elsif ctl_xfer_type_int(7) = '1' then 247 | state <= S_ControlWaitDataIN; 248 | tx_counter <= (others => '0'); 249 | elsif ctl_xfer_type_int(7) = '0' then 250 | state <= S_ControlWaitDataOUT; 251 | end if; 252 | end if; 253 | 254 | when S_ControlWaitDataIN => 255 | -- IN Token 256 | if trn_start = '1' and trn_type = "10" then 257 | if ctl_xfer_accept = '1' then 258 | state <= S_ControlDataIN; 259 | else 260 | state <= S_ControlDataIN_Z; 261 | end if; 262 | tx_trn_data_start <= '1'; 263 | end if; 264 | 265 | when S_ControlWaitDataOUT => 266 | -- OUT Token 267 | if trn_start = '1' and trn_type = "00" then 268 | if ctl_xfer_accept = '1' then 269 | ctl_status <= "00"; 270 | else 271 | ctl_status <= "10"; 272 | end if; 273 | state <= S_ControlDataOUT; 274 | end if; 275 | 276 | when S_ControlDataOUT => 277 | if rx_trn_valid = '1' or rx_trn_end = '1' then 278 | if rx_counter(5 downto 0) = 63 or rx_counter = ctl_xfer_length_int - 1 or rx_trn_end = '1' then 279 | state <= S_ControlDataOUT_MyACK; 280 | end if; 281 | end if; 282 | 283 | when S_ControlDataOUT_MyACK => 284 | if tx_trn_hsk_sended = '1' then 285 | if rx_counter = ctl_xfer_length_int then 286 | state <= S_ControlStatusIN; 287 | else 288 | state <= S_ControlWaitDataOUT; 289 | end if; 290 | end if; 291 | 292 | when S_ControlDataIN => 293 | if ctl_xfer_data_in_valid = '1' and tx_trn_data_ready = '1' then 294 | if tx_counter(5 downto 0) = 63 or tx_counter = ctl_xfer_length_int - 1 or 295 | ctl_xfer_data_in_last = '1' then 296 | tx_trn_data_start <= '0'; 297 | state <= S_ControlDataIN_ACK; 298 | if ctl_xfer_data_in_last = '1' then 299 | ctl_xfer_eop <= '1'; 300 | end if; 301 | end if; 302 | tx_counter <= tx_counter + 1; 303 | end if; 304 | 305 | when S_ControlDataIN_Z => 306 | tx_trn_data_start <= '0'; 307 | ctl_xfer_eop <= '1'; 308 | state <= S_ControlDataIN_ACK; 309 | 310 | when S_ControlDataIN_ACK => 311 | if rx_trn_hsk_received = '1' then 312 | if rx_trn_hsk_type = "00" then 313 | if tx_counter = ctl_xfer_length_int or ctl_xfer_eop = '1' then 314 | ctl_xfer_eop <= '0'; 315 | state <= S_ControlStatusOUT; 316 | else 317 | state <= S_ControlWaitDataIN; 318 | end if; 319 | else 320 | state <= S_Idle; 321 | end if; 322 | end if; 323 | 324 | when S_ControlStatusOUT => 325 | -- OUT Token 326 | if trn_start = '1' and trn_type = "00" then 327 | state <= S_ControlStatusOUT_D; 328 | end if; 329 | 330 | when S_ControlStatusOUT_D => 331 | if rx_trn_end = '1' then 332 | state <= S_ControlStatusOUT_ACK; 333 | if ctl_xfer_done = '1' then 334 | ctl_status <= "00"; 335 | else 336 | ctl_status <= "10"; 337 | end if; 338 | end if; 339 | 340 | when S_ControlStatusOUT_ACK => 341 | if tx_trn_hsk_sended = '1' then 342 | if ctl_status = "10" then 343 | state <= S_ControlStatusOUT; 344 | else 345 | state <= S_Idle; 346 | end if; 347 | end if; 348 | 349 | when S_ControlStatusIN => 350 | -- IN Token 351 | if trn_start = '1' and trn_type = "10" then 352 | if ctl_xfer_done = '1' then 353 | tx_trn_data_start <= '1'; 354 | state <= S_ControlStatusIN_D; 355 | else 356 | ctl_status <= "10"; 357 | state <= S_ControlStatusIN_MyACK; 358 | end if; 359 | end if; 360 | 361 | when S_ControlStatusIN_MyACK => 362 | if tx_trn_hsk_sended = '1' then 363 | state <= S_ControlStatusIN; 364 | end if; 365 | 366 | when S_ControlStatusIN_D => 367 | tx_trn_data_start <= '0'; 368 | state <= S_ControlStatusIN_ACK; 369 | 370 | when S_ControlStatusIN_ACK => 371 | if rx_trn_hsk_received = '1' then 372 | state <= S_Idle; 373 | end if; 374 | 375 | when S_BulkIN => 376 | if blk_xfer_in_data_valid = '1' and tx_trn_data_ready = '1' then 377 | if tx_counter_over = '1' or blk_xfer_in_data_last = '1' then 378 | tx_trn_data_start <= '0'; 379 | state <= S_BulkIN_ACK; 380 | end if; 381 | tx_counter <= tx_counter + 1; 382 | elsif blk_xfer_in_data_valid = '0' then 383 | tx_trn_data_start <= '0'; 384 | state <= S_BulkIN_ACK; 385 | end if; 386 | 387 | when S_BulkIN_ACK => 388 | if rx_trn_hsk_received = '1' then 389 | state <= S_Idle; 390 | end if; 391 | 392 | when S_BulkIN_MyACK => 393 | if tx_trn_hsk_sended = '1' then 394 | state <= S_Idle; 395 | end if; 396 | 397 | when S_BulkOUT => 398 | if rx_trn_end = '1' then 399 | state <= S_BulkOUT_ACK; 400 | end if; 401 | 402 | when S_BulkOUT_ACK => 403 | if tx_trn_hsk_sended = '1' then 404 | state <= S_Idle; 405 | end if; 406 | 407 | end case; 408 | end if; 409 | end if; 410 | end process; 411 | 412 | ctl_xfer_endpoint <= current_endpoint; 413 | blk_xfer_endpoint <= current_endpoint; 414 | 415 | tx_trn_hsk_type <= "00" when state = S_ControlSetupACK else 416 | ctl_status; 417 | 418 | tx_trn_send_hsk <= '1' when state = S_ControlSetupACK else 419 | '1' when state = S_ControlStatusOUT_ACK else 420 | '1' when state = S_ControlStatusIN_MyACK else 421 | '1' when state = S_BulkIN_MyACK else 422 | '1' when state = S_BulkOUT_ACK else 423 | '1' when state = S_ControlDataOUT_MyACK else 424 | '0'; 425 | 426 | ctl_xfer_length <= ctl_xfer_length_int; 427 | ctl_xfer_type <= ctl_xfer_type_int; 428 | 429 | ctl_xfer_data_in_ready <= tx_trn_data_ready when state = S_ControlDataIN else 430 | '0'; 431 | 432 | blk_xfer_in_data_ready <= tx_trn_data_ready when state = S_BulkIN else 433 | '0'; 434 | 435 | tx_trn_data_type <= data_types(to_integer(unsigned(current_endpoint))) & '0'; 436 | 437 | tx_trn_data <= ctl_xfer_data_in when state = S_ControlDataIN else 438 | blk_xfer_in_data; 439 | tx_trn_data_valid <= ctl_xfer_data_in_valid when state = S_ControlDataIN else 440 | blk_xfer_in_data_valid when state = S_BulkIN else 441 | '0'; 442 | 443 | tx_counter_over <= '1' when tx_counter(5 downto 0) = 63 AND HIGH_SPEED = false else 444 | '1' when tx_counter(8 downto 0) = 511 AND HIGH_SPEED = true else 445 | '0'; 446 | 447 | tx_trn_data_last <= '1' when state = S_ControlDataIN and (tx_counter(5 downto 0) = 63 or tx_counter = ctl_xfer_length_int - 1) else 448 | '1' when state = S_BulkIN and (tx_counter_over = '1' or blk_xfer_in_data_last = '1') else 449 | '1' when state = S_ControlStatusIN_D else 450 | '1' when state = S_ControlDataIN_Z else 451 | ctl_xfer_data_in_last when state = S_ControlDataIN else 452 | '0'; 453 | 454 | blk_xfer_out_data <= rx_trn_data; 455 | blk_xfer_out_data_valid <= rx_trn_valid when state = S_BulkOUT else 456 | '0'; 457 | 458 | ctl_xfer_data_out <= rx_trn_data; 459 | ctl_xfer_data_out_valid <= rx_trn_valid; 460 | 461 | end usb_xfer; 462 | --------------------------------------------------------------------------------