├── readme_files ├── sync.png ├── usb_dfu.png ├── usb_dfu.vsdx ├── bit_samples.png ├── fifo_timings.png └── fifo_protocol.png ├── examples ├── TinyFPGA-BX │ ├── OSS_CAD_Suite │ │ ├── input │ │ │ ├── bootloader │ │ │ │ ├── gtkwave │ │ │ │ │ ├── sie.pid.map │ │ │ │ │ ├── flash_spi.state.map │ │ │ │ │ ├── flash_spi.status.map │ │ │ │ │ ├── app.state.map │ │ │ │ │ └── procs.tcl │ │ │ │ ├── pre-pack.py │ │ │ │ ├── pins.pcf │ │ │ │ └── hdl_files.mk │ │ │ └── loopback │ │ │ │ ├── gtkwave │ │ │ │ ├── sie.pid.map │ │ │ │ └── procs.tcl │ │ │ │ ├── pre-pack.py │ │ │ │ ├── pins.pcf │ │ │ │ └── hdl_files.mk │ │ ├── output │ │ │ ├── loopback │ │ │ │ ├── loopback.bin │ │ │ │ └── loopback.rpt │ │ │ └── bootloader │ │ │ │ ├── bootloader.bin │ │ │ │ ├── fw_bootloader.bin │ │ │ │ └── bootloader.rpt │ │ └── Makefile │ ├── python │ │ └── bootloader │ │ │ ├── bootloader-1.0.1.bin │ │ │ ├── dump.py │ │ │ ├── run.py │ │ │ └── tinyfpga.py │ ├── iCEcube2 │ │ ├── loopback │ │ │ ├── usb_dfu_Implmnt │ │ │ │ ├── sbt │ │ │ │ │ └── outputs │ │ │ │ │ │ ├── bitmap │ │ │ │ │ │ └── loopback_bitmap.bin │ │ │ │ │ │ └── loopback_sbt.rpt │ │ │ │ ├── mylog.txt │ │ │ │ └── all_registers.txt │ │ │ ├── constraints │ │ │ │ ├── pins.pcf │ │ │ │ └── clk.sdc │ │ │ ├── usb_dfu_syn.prj │ │ │ └── usb_dfu_sbt.project │ │ └── bootloader │ │ │ ├── usb_dfu_Implmnt │ │ │ ├── sbt │ │ │ │ └── outputs │ │ │ │ │ ├── bitmap │ │ │ │ │ └── bootloader_bitmap.bin │ │ │ │ │ └── bootloader_sbt.rpt │ │ │ ├── mylog.txt │ │ │ └── all_registers.txt │ │ │ ├── constraints │ │ │ ├── pins.pcf │ │ │ └── clk.sdc │ │ │ ├── usb_dfu_syn.prj │ │ │ └── usb_dfu_sbt.project │ └── hdl │ │ ├── bootloader │ │ ├── bootloader_tasks.v │ │ ├── bootloader.v │ │ └── bootloader_defs.v │ │ └── loopback │ │ ├── loopback_defs.v │ │ └── loopback.v ├── common │ ├── gtkwave │ │ ├── phy_rx.nrzi.map │ │ ├── out_fifo.out_state.map │ │ ├── ctrl_endp.dev_state.map │ │ ├── phy_tx.tx_state.map │ │ ├── phy_rx.rx_state.map │ │ ├── phy_rx.state.map │ │ ├── flash_spi.status.map │ │ ├── ctrl_endp.state.map │ │ ├── sie.pid.map │ │ ├── sie.phy_state.map │ │ ├── ctrl_endp.dfu_state.map │ │ ├── flash_spi.state.map │ │ ├── ctrl_endp.req.map │ │ └── procs.tcl │ ├── hdl │ │ ├── prescaler.v │ │ ├── ice40 │ │ │ ├── cells_sim.v.patch │ │ │ ├── SB_RAM256x16.v │ │ │ ├── SB_PLL40_CORE.v │ │ │ ├── rom.v │ │ │ └── ram.v │ │ ├── usb_monitor.v │ │ ├── sim_tasks.v │ │ ├── ram_fifo_if.v │ │ ├── flash │ │ │ └── spi.v │ │ └── ram_if.v │ └── synplifypro │ │ └── usb_dfu.sdc └── README.md ├── LICENSE ├── usb_dfu ├── README.md ├── phy_tx.v └── fifo.v └── README.md /readme_files/sync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/readme_files/sync.png -------------------------------------------------------------------------------- /readme_files/usb_dfu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/readme_files/usb_dfu.png -------------------------------------------------------------------------------- /readme_files/usb_dfu.vsdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/readme_files/usb_dfu.vsdx -------------------------------------------------------------------------------- /readme_files/bit_samples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/readme_files/bit_samples.png -------------------------------------------------------------------------------- /readme_files/fifo_timings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/readme_files/fifo_timings.png -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/bootloader/gtkwave/sie.pid.map: -------------------------------------------------------------------------------- 1 | ../../../../../common/gtkwave/sie.pid.map -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/loopback/gtkwave/sie.pid.map: -------------------------------------------------------------------------------- 1 | ../../../../../common/gtkwave/sie.pid.map -------------------------------------------------------------------------------- /readme_files/fifo_protocol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/readme_files/fifo_protocol.png -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/bootloader/pre-pack.py: -------------------------------------------------------------------------------- 1 | ctx.addClock("clk", 16) 2 | ctx.addClock("clk_pll", 48) 3 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/loopback/pre-pack.py: -------------------------------------------------------------------------------- 1 | ctx.addClock("clk", 16) 2 | ctx.addClock("clk_pll", 48) 3 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/bootloader/gtkwave/flash_spi.state.map: -------------------------------------------------------------------------------- 1 | ../../../../../common/gtkwave/flash_spi.state.map -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/bootloader/gtkwave/flash_spi.status.map: -------------------------------------------------------------------------------- 1 | ../../../../../common/gtkwave/flash_spi.status.map -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/python/bootloader/bootloader-1.0.1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/examples/TinyFPGA-BX/python/bootloader/bootloader-1.0.1.bin -------------------------------------------------------------------------------- /examples/common/gtkwave/phy_rx.nrzi.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## phy_rx\.nrzi 3 | ## color ## Blue 4 | ## data ## Decimal 5 | 6 | 0 SE0 7 | 1 DJ 8 | 2 DK 9 | 3 SE1 10 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/output/loopback/loopback.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/examples/TinyFPGA-BX/OSS_CAD_Suite/output/loopback/loopback.bin -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/output/bootloader/bootloader.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/examples/TinyFPGA-BX/OSS_CAD_Suite/output/bootloader/bootloader.bin -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/output/bootloader/fw_bootloader.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/examples/TinyFPGA-BX/OSS_CAD_Suite/output/bootloader/fw_bootloader.bin -------------------------------------------------------------------------------- /examples/common/gtkwave/out_fifo.out_state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## out_fifo\.out_state 3 | ## color ## Blue 4 | ## data ## Decimal 5 | 6 | 0 ST_OUT_IDLE 7 | 1 ST_OUT_DATA 8 | 2 ST_OUT_NAK 9 | -------------------------------------------------------------------------------- /examples/common/gtkwave/ctrl_endp.dev_state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## ctrl_endp\.dev_state 3 | ## color ## Blue 4 | ## data ## Decimal 5 | 6 | 0 POWERED_STATE 7 | 1 DEFAULT_STATE 8 | 2 ADDRESS_STATE 9 | 3 CONFIGURED_STATE 10 | -------------------------------------------------------------------------------- /examples/common/gtkwave/phy_tx.tx_state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## phy_tx\.tx_state_q 3 | ## name ## phy_tx\.tx_state_d 4 | ## color ## Blue 5 | ## data ## Decimal 6 | 7 | 0 ST_IDLE 8 | 1 ST_SYNC 9 | 2 ST_DATA 10 | 3 ST_EOP 11 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/loopback/usb_dfu_Implmnt/sbt/outputs/bitmap/loopback_bitmap.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/examples/TinyFPGA-BX/iCEcube2/loopback/usb_dfu_Implmnt/sbt/outputs/bitmap/loopback_bitmap.bin -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/bootloader/usb_dfu_Implmnt/sbt/outputs/bitmap/bootloader_bitmap.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ulixxe/usb_dfu/HEAD/examples/TinyFPGA-BX/iCEcube2/bootloader/usb_dfu_Implmnt/sbt/outputs/bitmap/bootloader_bitmap.bin -------------------------------------------------------------------------------- /examples/common/gtkwave/phy_rx.rx_state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## phy_rx\.rx_state_q 3 | ## name ## phy_rx\.rx_state_d 4 | ## color ## Blue 5 | ## data ## Decimal 6 | 7 | 0 ST_IDLE 8 | 1 ST_SYNC 9 | 2 ST_DATA 10 | 3 ST_EOP 11 | 4 ST_ERR 12 | -------------------------------------------------------------------------------- /examples/common/gtkwave/phy_rx.state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## phy_rx\.state_q 3 | ## name ## phy_rx\.state_d 4 | ## color ## Blue 5 | ## data ## Decimal 6 | 7 | 0 ST_RESET 8 | 1 ST_DETACHED 9 | 2 ST_ATTACHED 10 | 3 ST_ENABLED 11 | 4 ST_DETACH -------------------------------------------------------------------------------- /examples/common/gtkwave/flash_spi.status.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## flash_[^.]+\.status_o\[.*\]$ 3 | ## color ## Red 4 | ## data ## Hex 5 | 6 | 0 STATUS_OK 7 | 5 STATUS_errCHECK_ERASED 8 | 7 STATUS_errVERIFY 9 | 8 STATUS_errADDRESS 10 | F STATUS_END 11 | -------------------------------------------------------------------------------- /examples/common/gtkwave/ctrl_endp.state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## ctrl_endp\.state 3 | ## color ## Blue 4 | ## data ## Decimal 5 | 6 | 0 ST_IDLE 7 | 1 ST_STALL 8 | 2 ST_SETUP 9 | 3 ST_IN_DATA 10 | 4 ST_OUT_DATA 11 | 5 ST_PRE_IN_STATUS 12 | 6 ST_IN_STATUS 13 | 7 ST_OUT_STATUS 14 | -------------------------------------------------------------------------------- /examples/common/gtkwave/sie.pid.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## \.pid 3 | ## color ## Blue 4 | ## data ## Binary 5 | 6 | 0000 PID_RESERVED 7 | 0001 PID_OUT 8 | 1001 PID_IN 9 | 0101 PID_SOF 10 | 1101 PID_SETUP 11 | 0011 PID_DATA0 12 | 1011 PID_DATA1 13 | 0010 PID_ACK 14 | 1010 PID_NAK 15 | 1110 PID_STALL 16 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/bootloader/gtkwave/app.state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## app\.state_q 3 | ## name ## app\.state_d 4 | ## color ## Blue 5 | ## data ## Decimal 6 | 7 | 0 ST_IDLE 8 | 1 ST_WR_LO_LENGTH 9 | 2 ST_WR_HI_LENGTH 10 | 3 ST_RD_LO_LENGTH 11 | 4 ST_RD_HI_LENGTH 12 | 5 ST_WR_DATA 13 | 6 ST_RD_DATA 14 | 7 ST_BOOT 15 | -------------------------------------------------------------------------------- /examples/common/gtkwave/sie.phy_state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## sie\.phy_state_q 3 | ## name ## sie\.phy_state_d 4 | ## color ## Blue 5 | ## data ## Decimal 6 | 7 | 0 PHY_IDLE 8 | 1 PHY_RX_PID 9 | 2 PHY_RX_ADDR 10 | 3 PHY_RX_ENDP 11 | 4 PHY_RX_DATA0 12 | 5 PHY_RX_DATA 13 | 6 PHY_RX_WAIT_EOP 14 | 7 PHY_TX_HANDSHAKE_PID 15 | 8 PHY_TX_DATA_PID 16 | 9 PHY_TX_DATA 17 | 10 PHY_TX_CRC16_0 18 | 11 PHY_TX_CRC16_1 -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/loopback/pins.pcf: -------------------------------------------------------------------------------- 1 | # ############################################################################## 2 | # TinyFPGA BX 3 | # ############################################################################## 4 | 5 | set_io usb_pu A3 6 | set_io usb_n A4 7 | set_io usb_p B4 8 | set_io led B3 9 | set_io clk B2 10 | set_io sck G7 11 | set_io ss F7 12 | set_io sdo G6 13 | set_io sdi H7 14 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/bootloader/pins.pcf: -------------------------------------------------------------------------------- 1 | # ############################################################################## 2 | # TinyFPGA BX 3 | # ############################################################################## 4 | 5 | set_io usb_pu A3 6 | set_io usb_n A4 7 | set_io usb_p B4 8 | set_io led B3 9 | set_io clk B2 10 | set_io sck G7 11 | set_io ss F7 12 | set_io sdo G6 13 | set_io sdi H7 14 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/bootloader/constraints/pins.pcf: -------------------------------------------------------------------------------- 1 | # ############################################################################## 2 | # TinyFPGA BX 3 | # ############################################################################## 4 | 5 | set_io usb_pu A3 6 | set_io usb_n A4 7 | set_io usb_p B4 8 | set_io led B3 9 | set_io clk B2 10 | set_io sck G7 11 | set_io ss F7 12 | set_io sdo G6 13 | set_io sdi H7 14 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/loopback/constraints/pins.pcf: -------------------------------------------------------------------------------- 1 | # ############################################################################## 2 | # TinyFPGA BX 3 | # ############################################################################## 4 | 5 | set_io usb_pu A3 6 | set_io usb_n A4 7 | set_io usb_p B4 8 | set_io led B3 9 | set_io clk B2 10 | set_io sck G7 11 | set_io ss F7 12 | set_io sdo G6 13 | set_io sdi H7 14 | -------------------------------------------------------------------------------- /examples/common/gtkwave/ctrl_endp.dfu_state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## ctrl_endp\.dfu_state 3 | ## color ## Blue 4 | ## data ## Decimal 5 | 6 | 0 DFU_ST_appIDLE 7 | 1 DFU_ST_appDETACH 8 | 2 DFU_ST_dfuIDLE 9 | 3 DFU_ST_dfuDNLOAD_SYNC 10 | 4 DFU_ST_dfuDNBUSY 11 | 5 DFU_ST_dfuDNLOAD_IDLE 12 | 6 DFU_ST_dfuMANIFEST_SYNC 13 | 7 DFU_ST_dfuMANIFEST 14 | 8 DFU_ST_dfuMANIFEST_WAIT_RESET 15 | 9 DFU_ST_dfuUPLOAD_IDLE 16 | 10 DFU_ST_dfuERROR 17 | 11 DFU_ST_dfuIDLE0 18 | -------------------------------------------------------------------------------- /examples/common/gtkwave/flash_spi.state.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## flash_[^.]+\.state_q\[.*\]$ 3 | ## color ## Blue 4 | ## data ## Decimal 5 | 6 | 0 ST_IDLE 7 | 1 ST_RESUME_DPD 8 | 2 ST_RD_DATA_CMD 9 | 3 ST_RD_DATA 10 | 4 ST_WR_ERASE_ENABLE 11 | 5 ST_WR_ERASE 12 | 6 ST_WR_ERASE_STATUS 13 | 7 ST_WR_ERASE_RD_DATA_CMD 14 | 8 ST_WR_ERASE_RD_DATA 15 | 9 ST_WR_ERASE_END 16 | 10 ST_WR_ERASE_ERROR 17 | 11 ST_WR_DATA_ENABLE 18 | 12 ST_WR_DATA_CMD 19 | 13 ST_WR_DATA 20 | 14 ST_WR_EOP 21 | 15 ST_WR_DATA_STATUS 22 | 16 ST_WR_RD_DATA_CMD 23 | 17 ST_WR_RD_DATA 24 | 18 ST_WR_DATA_CHECK 25 | 19 ST_WR_DATA_ERROR 26 | 20 ST_WR_ADDR_ERROR 27 | 21 ST_DPD 28 | 22 ST_DPD_END 29 | 23 ST_END 30 | -------------------------------------------------------------------------------- /examples/common/hdl/prescaler.v: -------------------------------------------------------------------------------- 1 | 2 | module prescaler 3 | ( 4 | input clk_i, 5 | input rstn_i, 6 | output clk_div16_o, 7 | output clk_div8_o, 8 | output clk_div4_o, 9 | output clk_div2_o 10 | ); 11 | 12 | reg [3:0] prescaler_cnt; 13 | 14 | always @(posedge clk_i or negedge rstn_i) begin 15 | if (~rstn_i) begin 16 | prescaler_cnt <= 'd0; 17 | end else begin 18 | prescaler_cnt <= prescaler_cnt + 1; 19 | end 20 | end 21 | 22 | assign clk_div16_o = prescaler_cnt[3]; 23 | assign clk_div8_o = prescaler_cnt[2]; 24 | assign clk_div4_o = prescaler_cnt[1]; 25 | assign clk_div2_o = prescaler_cnt[0]; 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/bootloader/hdl_files.mk: -------------------------------------------------------------------------------- 1 | # HDL files 2 | HDL_FILES = \ 3 | phy_tx.v \ 4 | phy_rx.v \ 5 | sie.v \ 6 | ctrl_endp.v \ 7 | in_fifo.v \ 8 | out_fifo.v \ 9 | fifo.v \ 10 | usb_dfu.v \ 11 | SB_RAM256x16.v \ 12 | dpram.v \ 13 | spi.v \ 14 | flash_if.v \ 15 | ram_fifo_if.v \ 16 | app.v \ 17 | bootloader.v \ 18 | 19 | # Testbench HDL files 20 | TB_HDL_FILES = \ 21 | SB_PLL40_CORE.v \ 22 | AT25SF081.v \ 23 | usb_monitor.v \ 24 | tb_bootloader.v \ 25 | 26 | # list of HDL files directories separated by ":" 27 | VPATH = ../../../usb_dfu: \ 28 | ../hdl/bootloader: \ 29 | ../../common/hdl: \ 30 | ../../common/hdl/ice40: \ 31 | ../../common/hdl/flash: \ 32 | -------------------------------------------------------------------------------- /examples/common/gtkwave/ctrl_endp.req.map: -------------------------------------------------------------------------------- 1 | # 2 | ## name ## ctrl_endp\.req_ 3 | ## color ## Blue 4 | ## data ## Decimal 5 | 6 | 0 REQ_NONE 7 | 1 REQ_CLEAR_FEATURE 8 | 2 REQ_GET_CONFIGURATION 9 | 3 REQ_GET_DESCRIPTOR 10 | 4 REQ_GET_DESCRIPTOR_DEVICE 11 | 5 REQ_GET_DESCRIPTOR_CONFIGURATION 12 | 6 REQ_GET_DESCRIPTOR_STRING 13 | 7 REQ_GET_DESCRIPTOR_BOS 14 | 8 REQ_GET_INTERFACE 15 | 9 REQ_GET_STATUS 16 | 10 REQ_SET_ADDRESS 17 | 11 REQ_SET_CONFIGURATION 18 | 12 REQ_SET_INTERFACE 19 | 13 REQ_DFU_DETACH 20 | 14 REQ_DFU_DNLOAD 21 | 15 REQ_DFU_UPLOAD 22 | 16 REQ_DFU_GETSTATUS 23 | 17 REQ_DFU_CLRSTATUS 24 | 18 REQ_DFU_GETSTATE 25 | 19 REQ_DFU_ABORT 26 | 20 REQ_MS20 27 | 21 REQ_WCID 28 | 22 REQ_EXT_WCID 29 | 23 REQ_DUMMY 30 | 24 REQ_UNSUPPORTED 31 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/loopback/hdl_files.mk: -------------------------------------------------------------------------------- 1 | # HDL files 2 | HDL_FILES = \ 3 | phy_tx.v \ 4 | phy_rx.v \ 5 | sie.v \ 6 | ctrl_endp.v \ 7 | in_fifo.v \ 8 | out_fifo.v \ 9 | fifo.v \ 10 | usb_dfu.v \ 11 | SB_RAM256x16.v \ 12 | ram.v \ 13 | dpram.v \ 14 | spi.v \ 15 | flash_spi.v \ 16 | ram_if.v \ 17 | ram_fifo_if.v \ 18 | dfu_app.v \ 19 | prescaler.v \ 20 | loopback.v \ 21 | 22 | # Testbench HDL files 23 | TB_HDL_FILES = \ 24 | SB_PLL40_CORE.v \ 25 | AT25SF081.v \ 26 | usb_monitor.v \ 27 | tb_loopback.v \ 28 | 29 | # list of HDL files directories separated by ":" 30 | VPATH = ../../../usb_dfu: \ 31 | ../hdl/loopback: \ 32 | ../../common/hdl: \ 33 | ../../common/hdl/ice40: \ 34 | ../../common/hdl/flash: \ 35 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/python/bootloader/dump.py: -------------------------------------------------------------------------------- 1 | def data_dump(data, col=16): 2 | import ctypes 3 | 4 | s = '' 5 | n = 0 6 | lines = [] 7 | 8 | if len(data) == 0: 9 | return '' 10 | 11 | for i in range(0, len(data), col): 12 | line = '' 13 | line += '%04x: ' % (i) 14 | n += col 15 | 16 | for j in range(n-col, n): 17 | if j >= len(data): break 18 | line += '%02x ' % abs(data[j]) 19 | 20 | line += ' ' * (3 * col + 6 - len(line)) + '| ' 21 | 22 | for j in range(n-col, n): 23 | if j >= len(data): break 24 | c = data[j] if not (data[j] < 0x20 or data[j] > 0x7e) else '.' 25 | line += '%c' % c 26 | 27 | lines.append(line) 28 | return '\n'.join(lines) 29 | 30 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/bootloader/constraints/clk.sdc: -------------------------------------------------------------------------------- 1 | ####---- CreateClock list ---- 2 | set BIT_SAMPLES 4 3 | set BIT_PERIOD [expr 1000 / 12.0] 4 | set CLK_PERIOD [expr $BIT_PERIOD / $BIT_SAMPLES] 5 | set BYTE_PERIOD [expr $BIT_PERIOD * 8] 6 | 7 | create_clock -name {clk} -period [expr 1000 / 16.0] [get_ports {clk}] 8 | create_clock -name {clk_usb} -period $CLK_PERIOD [get_nets {clk_pll}] 9 | 10 | # Somehow "create_generated_clock" confuses SynplifyPro and induces it to mess with global buffers. 11 | #create_generated_clock -name {clk_app} -source [get_ports {clk}] [get_nets {clk_2mhz}] -divide_by 8 12 | #create_clock -name {clk_app} -period [expr 1000 / 2.0] [get_nets {clk_2mhz}] 13 | 14 | set_clock_groups -asynchronous -group {clk} -group {clk_usb} 15 | 16 | set_false_path -to [get_ports {led usb_pu}] 17 | 18 | set root_path "u_usb_dfu" 19 | source ../../../../common/synplifypro/usb_dfu.sdc 20 | 21 | set fid [open all_registers.txt w] 22 | file_puts $fid "all_registers:" [all_registers] 23 | close $fid 24 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/loopback/constraints/clk.sdc: -------------------------------------------------------------------------------- 1 | ####---- CreateClock list ---- 2 | set BIT_SAMPLES 4 3 | set BIT_PERIOD [expr 1000 / 12.0] 4 | set CLK_PERIOD [expr $BIT_PERIOD / $BIT_SAMPLES] 5 | set BYTE_PERIOD [expr $BIT_PERIOD * 8] 6 | 7 | create_clock -name {clk} -period [expr 1000 / 16.0] [get_ports {clk}] 8 | create_clock -name {clk_usb} -period $CLK_PERIOD [get_nets {clk_pll}] 9 | 10 | # Somehow "create_generated_clock" confuses SynplifyPro and induces it to mess with global buffers. 11 | #create_generated_clock -name {clk_app} -source [get_ports {clk}] [get_nets {clk_2mhz}] -divide_by 8 12 | #create_clock -name {clk_app} -period [expr 1000 / 2.0] [get_nets {clk_2mhz}] 13 | 14 | set_clock_groups -asynchronous -group {clk} -group {clk_usb} 15 | 16 | set_false_path -to [get_ports {led usb_pu}] 17 | 18 | set root_path "u_usb_dfu" 19 | source ../../../../common/synplifypro/usb_dfu.sdc 20 | 21 | set fid [open all_registers.txt w] 22 | file_puts $fid "all_registers:" [all_registers] 23 | close $fid 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 ulixxe 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 | -------------------------------------------------------------------------------- /examples/common/hdl/ice40/cells_sim.v.patch: -------------------------------------------------------------------------------- 1 | --- cells_sim.v.orig 2021-11-15 22:28:52.006942786 +0100 2 | +++ cells_sim.v 2021-12-07 18:51:55.789342565 +0100 3 | @@ -2394,37 +2394,6 @@ 4 | // SiliconBlue PLL Cells 5 | 6 | (* blackbox *) 7 | -module SB_PLL40_CORE ( 8 | - input REFERENCECLK, 9 | - output PLLOUTCORE, 10 | - output PLLOUTGLOBAL, 11 | - input EXTFEEDBACK, 12 | - input [7:0] DYNAMICDELAY, 13 | - output LOCK, 14 | - input BYPASS, 15 | - input RESETB, 16 | - input LATCHINPUTVALUE, 17 | - output SDO, 18 | - input SDI, 19 | - input SCLK 20 | -); 21 | - parameter FEEDBACK_PATH = "SIMPLE"; 22 | - parameter DELAY_ADJUSTMENT_MODE_FEEDBACK = "FIXED"; 23 | - parameter DELAY_ADJUSTMENT_MODE_RELATIVE = "FIXED"; 24 | - parameter SHIFTREG_DIV_MODE = 1'b0; 25 | - parameter FDA_FEEDBACK = 4'b0000; 26 | - parameter FDA_RELATIVE = 4'b0000; 27 | - parameter PLLOUT_SELECT = "GENCLK"; 28 | - parameter DIVR = 4'b0000; 29 | - parameter DIVF = 7'b0000000; 30 | - parameter DIVQ = 3'b000; 31 | - parameter FILTER_RANGE = 3'b000; 32 | - parameter ENABLE_ICEGATE = 1'b0; 33 | - parameter TEST_MODE = 1'b0; 34 | - parameter EXTERNAL_DIVIDE_FACTOR = 1; 35 | -endmodule 36 | - 37 | -(* blackbox *) 38 | module SB_PLL40_PAD ( 39 | input PACKAGEPIN, 40 | output PLLOUTCORE, 41 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/python/bootloader/run.py: -------------------------------------------------------------------------------- 1 | import tinyfpga 2 | import time 3 | import os 4 | import base64 5 | import dump 6 | import filecmp 7 | 8 | #tinyfpga.boot() 9 | 10 | ser = tinyfpga.open() 11 | tinyfpga.wake(ser) 12 | 13 | with open("out.bin", "wb") as binary_file: 14 | binary_file.write(bytes(tinyfpga.read_data(0xA0, 135100, ser))) 15 | 16 | #with open("out.bin", "wb") as binary_file: 17 | # binary_file.write(bytes(tinyfpga.read_data(0x28000, 135100, ser))) 18 | 19 | #with open("out.bin", "wb") as binary_file: 20 | # binary_file.write(bytes(tinyfpga.read_data(0x0, 298940, ser))) 21 | 22 | if (filecmp.cmp("out.bin", "./bootloader-1.0.1.bin")): 23 | print(f"\033[94mOK: data is correct!\033[0m") 24 | else: 25 | print(f"\033[91mERROR: file missmatch!\033[0m") 26 | 27 | #tinyfpga.write_data(0x28000, tinyfpga.slurp("../../OSS_CAD_Suite/output/bootloader/bootloader.bin"), ser) 28 | #tinyfpga.write_data(0x28000, tinyfpga.slurp("../../iCEcube2/bootloader/usb_dfu_Implmnt/sbt/outputs/bitmap/bootloader_bitmap.bin"), ser) 29 | 30 | #tinyfpga.read_data(0x28000, 8*1024, ser, 2) 31 | tinyfpga.read_security_register(1, ser, 2) 32 | tinyfpga.read_security_register(2, ser, 2) 33 | 34 | #tinyfpga.write_data(0x70FFF, tinyfpga.slurp("out.hex"), ser) 35 | 36 | 37 | tinyfpga.sleep(ser) 38 | 39 | time.sleep(1) 40 | if (ser.inWaiting() != 0): 41 | print(f"\033[91mERROR: read buffer not empty!\033[0m") 42 | -------------------------------------------------------------------------------- /examples/common/hdl/usb_monitor.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns/10 ps // time-unit/precision 2 | `define BIT_TIME (1000/12) 3 | 4 | module usb_monitor 5 | #(parameter MAX_BITS = 128, 6 | parameter MAX_BYTES = 8*1024) 7 | ( 8 | input usb_dp_i, 9 | input usb_dn_i 10 | ); 11 | 12 | localparam MAX_STRING = 8; 13 | 14 | integer errors; 15 | integer warnings; 16 | 17 | wire dp_sense; 18 | wire dn_sense; 19 | 20 | `include "usb_rx_tasks.v" 21 | 22 | reg [3:0] pid; 23 | reg [6:0] addr; 24 | reg [3:0] endp; 25 | reg [10:0] frame; 26 | reg [8*MAX_BYTES-1:0] data; 27 | reg [8*MAX_STRING-1:0] info; 28 | 29 | integer bytes; 30 | 31 | assign dp_sense = usb_dp_i; 32 | assign dn_sense = usb_dn_i; 33 | 34 | initial begin 35 | errors = 0; 36 | warnings = 0; 37 | forever begin 38 | packet_rx(pid, addr, endp, frame, data, bytes, 39 | `BIT_TIME, 2000000); 40 | case (pid) 41 | PID_OUT : info = "OUT"; 42 | PID_IN : info = "IN"; 43 | PID_SOF : info = "SOF"; 44 | PID_SETUP : info = "SETUP"; 45 | PID_DATA0 : info = "DATA0"; 46 | PID_DATA1 : info = "DATA1"; 47 | PID_ACK : info = "ACK"; 48 | PID_NAK : info = "NAK"; 49 | PID_STALL : info = "STALL"; 50 | default : info = ""; 51 | endcase 52 | end 53 | end 54 | 55 | endmodule 56 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/loopback/gtkwave/procs.tcl: -------------------------------------------------------------------------------- 1 | 2 | proc monitor {} { 3 | gtkwave::/Edit/Insert_Comment "MONITOR" 4 | set sigFilterList [list \ 5 | {u_usb_monitor\.info\[.*\]$} \ 6 | {u_usb_monitor\.pid\[.*\]$} \ 7 | {u_usb_monitor\.frame\[.*\]$} \ 8 | {u_usb_monitor\.addr\[.*\]$} \ 9 | {u_usb_monitor\.endp\[.*\]$} \ 10 | {u_usb_monitor\.bytes$} \ 11 | {u_usb_monitor\.data\[.*\]$} \ 12 | {u_usb_monitor\.warnings$}\ 13 | ] 14 | addSignals $sigFilterList 15 | wavesFormat input/loopback/gtkwave 16 | setData { {u_usb_monitor\.info\[.*\]$} } ASCII 17 | setColor { {u_usb_monitor\.info\[.*\]$} } Blue 18 | setColor { {u_usb_monitor\.warnings$} } Yellow 19 | } 20 | 21 | proc top {} { 22 | gtkwave::/Edit/Insert_Comment "TOP" 23 | set sigFilterList [list \ 24 | {^[^.]*\.test\[.*\]$} \ 25 | {^[^.]*\.dp_sense$} \ 26 | {^[^.]*\.dn_sense$} \ 27 | {^[^.]*\.errors$} \ 28 | {^[^.]*\.csn$} \ 29 | {^[^.]*\.sck$} \ 30 | {^[^.]*\.mosi$} \ 31 | {^[^.]*\.miso$} \ 32 | ] 33 | addSignals $sigFilterList 34 | wavesFormat input/loopback/gtkwave 35 | setData { {^[^.]*\.test\[.*\]$} } ASCII 36 | setColor { {^[^.]*\.test\[.*\]$} } Blue 37 | setColor { {^[^.]*\.errors$} } Red 38 | } 39 | 40 | set cmds "monitor top $cmds" 41 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/hdl/bootloader/bootloader_tasks.v: -------------------------------------------------------------------------------- 1 | 2 | task automatic test_cmd 3 | ( 4 | input [7:0] opcode, 5 | input integer wr_length, 6 | input integer rd_length, 7 | input [6:0] address, 8 | input integer wMaxPacketSize, 9 | input time timeout, 10 | inout [15:0] dataout_toggle 11 | ); 12 | integer wr_total_length; 13 | begin : u_test_cmd_task 14 | wr_total_length = wr_length + 1; // add opcode 15 | 16 | test_data_out(address, ENDP_BULK, 17 | {8'h01, 18 | wr_total_length[7:0], wr_total_length[15:8], 19 | rd_length[7:0], rd_length[15:8], 20 | opcode}, 21 | 6, PID_ACK, wMaxPacketSize, timeout, 0, dataout_toggle); 22 | end 23 | endtask 24 | 25 | task automatic test_read 26 | ( 27 | input integer rd_addr, 28 | input [8*MAX_BYTES-1:0] data, 29 | input integer bytes, 30 | input [6:0] address, 31 | input integer in_wMaxPacketSize, 32 | input integer out_wMaxPacketSize, 33 | input time timeout, 34 | inout [15:0] datain_toggle, 35 | inout [15:0] dataout_toggle 36 | ); 37 | integer wr_length; 38 | integer rd_length; 39 | begin : u_test_read_task 40 | wr_length = 5; 41 | rd_length = bytes; 42 | 43 | test_data_out(address, ENDP_BULK, 44 | {8'h01, wr_length[7:0], wr_length[15:8], rd_length[7:0], rd_length[15:8], 45 | 8'h0B, rd_addr[23:16], rd_addr[15:8], rd_addr[7:0], 8'd0}, 46 | 10, PID_ACK, out_wMaxPacketSize, timeout, 0, dataout_toggle); 47 | test_data_in(address, ENDP_BULK, 48 | data, 49 | bytes, PID_ACK, in_wMaxPacketSize, timeout, 0, datain_toggle, ZLP); 50 | end 51 | endtask 52 | -------------------------------------------------------------------------------- /examples/common/hdl/sim_tasks.v: -------------------------------------------------------------------------------- 1 | 2 | `define assert_error(msg, signal, value) \ 3 | if ((signal) !== (value)) begin \ 4 | errors = errors + 1; \ 5 | $display("%c[1;31m",27); \ 6 | $display("ERROR @ %t: %s", $time, msg); \ 7 | $display(" actual: %x", signal); \ 8 | $display(" expected: %x", value); \ 9 | $display("%c[0m",27); \ 10 | #(1*`BIT_TIME); \ 11 | $finish; \ 12 | end 13 | 14 | `define report_error(msg) \ 15 | errors = errors + 1; \ 16 | $display("%c[1;31m",27); \ 17 | $display("ERROR @ %t\n %s", $time, msg); \ 18 | $display("%c[0m",27); \ 19 | #(1*`BIT_TIME); \ 20 | $finish; 21 | 22 | `define assert_warning(msg, signal, value) \ 23 | if ((signal) !== (value)) begin \ 24 | warnings = warnings + 1; \ 25 | $display("%c[1;31m",27); \ 26 | $display("WARNING @ %t: %s", $time, msg); \ 27 | $display(" actual: %x", signal); \ 28 | $display(" expected: %x", value); \ 29 | $display("%c[0m",27); \ 30 | end 31 | 32 | `define report_warning(msg) \ 33 | warnings = warnings + 1; \ 34 | $display("%c[1;33m",27); \ 35 | $display("WARNING @ %t\n %s", $time, msg); \ 36 | $display("%c[0m",27); 37 | 38 | `define report_end(msg) \ 39 | $display("%c[1;32m",27); \ 40 | $display("@ %t\n %s", $time, msg); \ 41 | $display("%c[0m",27); \ 42 | $finish; 43 | 44 | `define progress_bar(msg, end_ms) \ 45 | integer time_ms; \ 46 | initial begin \ 47 | time_ms = 0; \ 48 | forever begin \ 49 | #(1000000/83*`BIT_TIME); \ 50 | time_ms = time_ms + 1; \ 51 | $write("%4d ms", time_ms); \ 52 | if (end_ms > 0) \ 53 | $write(" (%3d%%)", 100*time_ms/end_ms); \ 54 | if (msg != "") \ 55 | $write(": %0s", msg); \ 56 | $write(" \015"); \ 57 | $fflush(32'h8000_0001); // flush STDOUT \ 58 | end \ 59 | end 60 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/bootloader/usb_dfu_syn.prj: -------------------------------------------------------------------------------- 1 | #-- Synopsys, Inc. 2 | #-- Project file /mnt/hgfs/Projects/Bitbucket/uf16/libs/uf16/fpga/TinyFPGA-BX/usb_dfu/usb_dfu_syn.prj 3 | #project files 4 | 5 | add_file -verilog -lib work "../../../../usb_dfu/phy_tx.v" 6 | add_file -verilog -lib work "../../../../usb_dfu/phy_rx.v" 7 | add_file -verilog -lib work "../../../../usb_dfu/sie.v" 8 | add_file -verilog -lib work "../../../../usb_dfu/ctrl_endp.v" 9 | add_file -verilog -lib work "../../../../usb_dfu/in_fifo.v" 10 | add_file -verilog -lib work "../../../../usb_dfu/out_fifo.v" 11 | add_file -verilog -lib work "../../../../usb_dfu/fifo.v" 12 | add_file -verilog -lib work "../../../../usb_dfu/usb_dfu.v" 13 | add_file -verilog -lib work "../../../common/hdl/ice40/dpram.v" 14 | add_file -verilog -lib work "../../../common/hdl/flash/spi.v" 15 | add_file -verilog -lib work "../../../common/hdl/flash/flash_if.v" 16 | add_file -verilog -lib work "../../../common/hdl/ram_fifo_if.v" 17 | add_file -verilog -lib work "../../hdl/bootloader/app.v" 18 | add_file -verilog -lib work "../../hdl/bootloader/bootloader.v" 19 | add_file -constraint -lib work "constraints/clk.sdc" 20 | #implementation: "usb_dfu_Implmnt" 21 | impl -add usb_dfu_Implmnt -type fpga 22 | 23 | #implementation attributes 24 | set_option -vlog_std v2001 25 | set_option -project_relative_includes 1 26 | 27 | #device options 28 | set_option -technology SBTiCE40 29 | set_option -part iCE40LP8K 30 | set_option -package CM81 31 | set_option -speed_grade 32 | set_option -part_companion "" 33 | 34 | #compilation/mapping options 35 | set_option -top_module "bootloader" 36 | 37 | # mapper_options 38 | set_option -frequency auto 39 | set_option -write_verilog 0 40 | set_option -write_vhdl 0 41 | 42 | # Silicon Blue iCE40 43 | set_option -maxfan 10000 44 | set_option -disable_io_insertion 0 45 | set_option -pipe 1 46 | set_option -retiming 0 47 | set_option -update_models_cp 0 48 | set_option -fixgatedclocks 2 49 | set_option -fixgeneratedclocks 0 50 | 51 | # NFilter 52 | set_option -popfeed 0 53 | set_option -constprop 0 54 | set_option -createhierarchy 0 55 | 56 | # sequential_optimization_options 57 | set_option -symbolic_fsm_compiler 1 58 | 59 | # Compiler Options 60 | set_option -compiler_compatible 0 61 | set_option -resource_sharing 1 62 | 63 | #automatic place and route (vendor) options 64 | set_option -write_apr_constraint 1 65 | 66 | #set result format/file last 67 | project -result_format "edif" 68 | project -result_file ./usb_dfu_Implmnt/usb_dfu.edf 69 | project -log_file "./usb_dfu_Implmnt/usb_dfu.srr" 70 | impl -active usb_dfu_Implmnt 71 | project -run synthesis -clean 72 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/input/bootloader/gtkwave/procs.tcl: -------------------------------------------------------------------------------- 1 | 2 | proc flash {} { 3 | gtkwave::/Edit/Insert_Comment "FLASH" 4 | set sigFilterList [list \ 5 | {flash_[^.]+\.state_q\[.*\]$} \ 6 | {flash_[^.]+\.status_o\[.*\]$} \ 7 | {flash_[^.]+\.byte_cnt_q\[.*\]$} \ 8 | ] 9 | addSignals $sigFilterList 10 | wavesFormat input/bootloader/gtkwave 11 | setData { {flash_[^.]+\.state_q\[.*\]$} } Decimal 12 | setData { {flash_[^.]+\.byte_cnt_q\[.*\]$} } Decimal 13 | } 14 | 15 | proc app {} { 16 | gtkwave::/Edit/Insert_Comment "APP" 17 | set sigFilterList [list \ 18 | {app\.wr_length_q\[.*\]$} \ 19 | {app\.rd_length_q\[.*\]$} \ 20 | {app\.timer_q\[.*\]$} \ 21 | {app\.state_q\[.*\]$}\ 22 | ] 23 | addSignals $sigFilterList 24 | wavesFormat input/bootloader/gtkwave 25 | setData { {app\.timer_q\[.*\]$} } Decimal 26 | } 27 | 28 | proc monitor {} { 29 | gtkwave::/Edit/Insert_Comment "MONITOR" 30 | set sigFilterList [list \ 31 | {u_usb_monitor\.info\[.*\]$} \ 32 | {u_usb_monitor\.pid\[.*\]$} \ 33 | {u_usb_monitor\.frame\[.*\]$} \ 34 | {u_usb_monitor\.addr\[.*\]$} \ 35 | {u_usb_monitor\.endp\[.*\]$} \ 36 | {u_usb_monitor\.bytes$} \ 37 | {u_usb_monitor\.data\[.*\]$} \ 38 | {u_usb_monitor\.warnings$}\ 39 | ] 40 | addSignals $sigFilterList 41 | wavesFormat input/bootloader/gtkwave 42 | setData { {u_usb_monitor\.info\[.*\]$} } ASCII 43 | setColor { {u_usb_monitor\.info\[.*\]$} } Blue 44 | setColor { {u_usb_monitor\.warnings$} } Yellow 45 | } 46 | 47 | proc top {} { 48 | gtkwave::/Edit/Insert_Comment "TOP" 49 | set sigFilterList [list \ 50 | {^[^.]*\.test\[.*\]$} \ 51 | {^[^.]*\.dp_sense$} \ 52 | {^[^.]*\.dn_sense$} \ 53 | {^[^.]*\.errors$} \ 54 | {^[^.]*\.csn$} \ 55 | {^[^.]*\.sck$} \ 56 | {^[^.]*\.mosi$} \ 57 | {^[^.]*\.miso$} \ 58 | ] 59 | addSignals $sigFilterList 60 | wavesFormat input/bootloader/gtkwave 61 | setData { {^[^.]*\.test\[.*\]$} } ASCII 62 | setColor { {^[^.]*\.test\[.*\]$} } Blue 63 | setColor { {^[^.]*\.errors$} } Red 64 | } 65 | 66 | set cmds "flash app monitor top $cmds" 67 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/loopback/usb_dfu_syn.prj: -------------------------------------------------------------------------------- 1 | #-- Synopsys, Inc. 2 | #-- Project file /mnt/hgfs/Projects/Bitbucket/uf16/libs/uf16/fpga/TinyFPGA-BX/usb_dfu/usb_dfu_syn.prj 3 | #project files 4 | 5 | add_file -verilog -lib work "../../../../usb_dfu/phy_tx.v" 6 | add_file -verilog -lib work "../../../../usb_dfu/phy_rx.v" 7 | add_file -verilog -lib work "../../../../usb_dfu/sie.v" 8 | add_file -verilog -lib work "../../../../usb_dfu/ctrl_endp.v" 9 | add_file -verilog -lib work "../../../../usb_dfu/in_fifo.v" 10 | add_file -verilog -lib work "../../../../usb_dfu/out_fifo.v" 11 | add_file -verilog -lib work "../../../../usb_dfu/fifo.v" 12 | add_file -verilog -lib work "../../../../usb_dfu/usb_dfu.v" 13 | add_file -verilog -lib work "../../../common/hdl/ice40/ram.v" 14 | add_file -verilog -lib work "../../../common/hdl/ice40/dpram.v" 15 | add_file -verilog -lib work "../../../common/hdl/flash/spi.v" 16 | add_file -verilog -lib work "../../../common/hdl/flash/flash_spi.v" 17 | add_file -verilog -lib work "../../../common/hdl/ram_if.v" 18 | add_file -verilog -lib work "../../../common/hdl/ram_fifo_if.v" 19 | add_file -verilog -lib work "../../hdl/loopback/dfu_app.v" 20 | add_file -verilog -lib work "../../../common/hdl/prescaler.v" 21 | add_file -verilog -lib work "../../hdl/loopback/loopback.v" 22 | add_file -constraint -lib work "constraints/clk.sdc" 23 | #implementation: "usb_dfu_Implmnt" 24 | impl -add usb_dfu_Implmnt -type fpga 25 | 26 | #implementation attributes 27 | set_option -vlog_std v2001 28 | set_option -project_relative_includes 1 29 | 30 | #device options 31 | set_option -technology SBTiCE40 32 | set_option -part iCE40LP8K 33 | set_option -package CM81 34 | set_option -speed_grade 35 | set_option -part_companion "" 36 | 37 | #compilation/mapping options 38 | set_option -top_module "loopback" 39 | 40 | # mapper_options 41 | set_option -frequency auto 42 | set_option -write_verilog 0 43 | set_option -write_vhdl 0 44 | 45 | # Silicon Blue iCE40 46 | set_option -maxfan 10000 47 | set_option -disable_io_insertion 0 48 | set_option -pipe 1 49 | set_option -retiming 0 50 | set_option -update_models_cp 0 51 | set_option -fixgatedclocks 2 52 | set_option -fixgeneratedclocks 0 53 | 54 | # NFilter 55 | set_option -popfeed 0 56 | set_option -constprop 0 57 | set_option -createhierarchy 0 58 | 59 | # sequential_optimization_options 60 | set_option -symbolic_fsm_compiler 1 61 | 62 | # Compiler Options 63 | set_option -compiler_compatible 0 64 | set_option -resource_sharing 1 65 | 66 | #automatic place and route (vendor) options 67 | set_option -write_apr_constraint 1 68 | 69 | #set result format/file last 70 | project -result_format "edif" 71 | project -result_file ./usb_dfu_Implmnt/usb_dfu.edf 72 | project -log_file "./usb_dfu_Implmnt/usb_dfu.srr" 73 | impl -active usb_dfu_Implmnt 74 | project -run synthesis -clean 75 | -------------------------------------------------------------------------------- /examples/common/hdl/ice40/SB_RAM256x16.v: -------------------------------------------------------------------------------- 1 | 2 | module SB_RAM256x16 3 | #(parameter INIT_0 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 4 | parameter INIT_1 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 5 | parameter INIT_2 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 6 | parameter INIT_3 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 7 | parameter INIT_4 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 8 | parameter INIT_5 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 9 | parameter INIT_6 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 10 | parameter INIT_7 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 11 | parameter INIT_8 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 12 | parameter INIT_9 = 256'h0000000000000000000000000000000000000000000000000000000000000000, 13 | parameter INIT_A = 256'h0000000000000000000000000000000000000000000000000000000000000000, 14 | parameter INIT_B = 256'h0000000000000000000000000000000000000000000000000000000000000000, 15 | parameter INIT_C = 256'h0000000000000000000000000000000000000000000000000000000000000000, 16 | parameter INIT_D = 256'h0000000000000000000000000000000000000000000000000000000000000000, 17 | parameter INIT_E = 256'h0000000000000000000000000000000000000000000000000000000000000000, 18 | parameter INIT_F = 256'h0000000000000000000000000000000000000000000000000000000000000000) 19 | ( 20 | output [15:0] RDATA, 21 | input RCLK, 22 | input RCLKE, 23 | input RE, 24 | input [7:0] RADDR, 25 | input WCLK, 26 | input WCLKE, 27 | input WE, 28 | input [7:0] WADDR, 29 | input [15:0] MASK, 30 | input [15:0] WDATA 31 | ); 32 | 33 | SB_RAM40_4K #(.INIT_0(INIT_0), 34 | .INIT_1(INIT_1), 35 | .INIT_2(INIT_2), 36 | .INIT_3(INIT_3), 37 | .INIT_4(INIT_4), 38 | .INIT_5(INIT_5), 39 | .INIT_6(INIT_6), 40 | .INIT_7(INIT_7), 41 | .INIT_8(INIT_8), 42 | .INIT_9(INIT_9), 43 | .INIT_A(INIT_A), 44 | .INIT_B(INIT_B), 45 | .INIT_C(INIT_C), 46 | .INIT_D(INIT_D), 47 | .INIT_E(INIT_E), 48 | .INIT_F(INIT_F)) 49 | u_ram40_4k (.RDATA(RDATA), 50 | .RADDR({3'b0, RADDR}), 51 | .RCLK(RCLK), 52 | .RCLKE(RCLKE), 53 | .RE(RE), 54 | .WADDR({3'b0, WADDR}), 55 | .WCLK(WCLK), 56 | .WCLKE(WCLKE), 57 | .WDATA(WDATA), 58 | .WE(WE), 59 | .MASK(MASK)); 60 | endmodule 61 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # override the default with: make all PROJ=loopback 3 | PROJ = loopback 4 | 5 | PIN_DEF = pins.pcf 6 | DEVICE = lp8k 7 | PKG = cm81 8 | IN_DIR = input/$(PROJ) 9 | OUT_DIR = output/$(PROJ) 10 | INC_DIRS = -I../../common/hdl -I../hdl/$(PROJ) 11 | ICE40_LIB = $(shell yosys-config --datdir/ice40/cells_sim.v) 12 | RUN_ONCE = 13 | NEXTPNR_ARGS = --timing-allow-fail 14 | run = $(if $(RUN_ONCE),$(1),until $$($(1)) ; do true ; done) 15 | 16 | include $(IN_DIR)/hdl_files.mk 17 | 18 | all: $(OUT_DIR)/$(PROJ).rpt $(OUT_DIR)/$(PROJ).bin 19 | fw: $(OUT_DIR)/fw_$(PROJ).bin 20 | 21 | $(OUT_DIR): 22 | mkdir -p $@ 23 | 24 | $(OUT_DIR)/%.json: $(HDL_FILES) | $(OUT_DIR) 25 | yosys -l $(OUT_DIR)/log_yosys_$(PROJ).txt -p '$(foreach file,$^,read_verilog $(file);)' -p 'synth_ice40 -top $(PROJ); write_json $@' 26 | 27 | $(OUT_DIR)/%.asc: $(OUT_DIR)/%.json $(IN_DIR)/$(PIN_DEF) 28 | $(call run,nextpnr-ice40 $(NEXTPNR_ARGS) --randomize-seed --$(DEVICE) --package $(PKG) -l $(OUT_DIR)/log_nextpnr_$*.txt --pcf $(IN_DIR)/$(PIN_DEF) --json $< --pre-pack $(IN_DIR)/pre-pack.py --asc $@) 29 | 30 | $(OUT_DIR)/%.rpt: $(OUT_DIR)/%.asc 31 | icetime -d $(DEVICE) -mtr $@ $< 32 | 33 | $(OUT_DIR)/%.bin: $(OUT_DIR)/%.asc 34 | icepack $< $@ 35 | 36 | $(OUT_DIR)/fw_%.bin: $(OUT_DIR)/%.bin 37 | cp $< $(OUT_DIR)/$*_0.bin 38 | cp $< $(OUT_DIR)/$*_1.bin 39 | icemulti -v -o $@ -a15 -p0 $(OUT_DIR)/$*_0.bin $(OUT_DIR)/$*_1.bin 40 | rm $(OUT_DIR)/$*_0.bin $(OUT_DIR)/$*_1.bin 41 | 42 | prog: $(OUT_DIR)/$(PROJ).bin 43 | tinyprog -p $< 44 | 45 | lint: $(HDL_FILES) 46 | verilator --lint-only --default-language 1364-2001 -Wall -Wno-UNUSED -Wno-UNDRIVEN -Wno-TIMESCALEMOD -DBLACKBOX -DNO_ICE40_DEFAULT_ASSIGNMENTS --top $(PROJ) $(INC_DIRS) -v $(ICE40_LIB) $^ 47 | 48 | $(OUT_DIR)/cells_sim.v: 49 | patch $(ICE40_LIB) -o $(OUT_DIR)/cells_sim.v < ../../common/hdl/ice40/cells_sim.v.patch 50 | 51 | $(OUT_DIR)/%.vvp: $(HDL_FILES) $(TB_HDL_FILES) | $(OUT_DIR) $(OUT_DIR)/cells_sim.v 52 | iverilog -g2001 -DNO_ICE40_DEFAULT_ASSIGNMENTS -t vvp -s tb_$(PROJ) $(INC_DIRS) -l $(OUT_DIR)/cells_sim.v -o $@ $^ 53 | 54 | $(OUT_DIR)/%.fst: $(OUT_DIR)/%.vvp 55 | vvp -N $< -fst && mv tb.dump $@ 56 | 57 | sim: $(OUT_DIR)/$(PROJ).fst 58 | 59 | $(OUT_DIR)/%.xml: $(HDL_FILES) $(TB_HDL_FILES) | $(OUT_DIR) $(OUT_DIR)/cells_sim.v 60 | verilator --no-timing -xml-only --bbox-unsup --bbox-sys -Wno-lint -Wno-MULTIDRIVEN -Wno-TIMESCALEMOD -Wno-STMTDLY -Wno-INFINITELOOP -DBLACKBOX -DNO_ICE40_DEFAULT_ASSIGNMENTS --top tb_$(PROJ) $(INC_DIRS) -v $(OUT_DIR)/cells_sim.v $^ --xml-output $@ 61 | 62 | $(OUT_DIR)/%.stems: $(OUT_DIR)/%.xml 63 | xml2stems $< $@ 64 | 65 | wave: $(OUT_DIR)/$(PROJ).stems $(OUT_DIR)/$(PROJ).fst 66 | gtkwave --autosavename --saveonexit --tcl_init=../../common/gtkwave/procs.tcl --wish --stems $^ --rcvar 'do_initial_zoom_fit yes' --rcvar 'splash_disable yes' 67 | 68 | clean: 69 | rm -rf $(OUT_DIR) 70 | 71 | .SECONDARY: 72 | .PHONY: all prog lint sim wave clean 73 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/bootloader/usb_dfu_sbt.project: -------------------------------------------------------------------------------- 1 | [Project] 2 | ProjectVersion=2.0 3 | Version=Lattice Semiconductor Corporation iCEcube - Release: 2020.12.27943 - Build Date: Dec 10 2020 18:03:29 4 | ProjectName=usb_dfu 5 | Vendor=SiliconBlue 6 | Synthesis=synplify 7 | ProjectVFiles=../../../../usb_dfu/phy_tx.v=work,../../../../usb_dfu/phy_rx.v=work,../../../../usb_dfu/sie.v=work,../../../../usb_dfu/ctrl_endp.v=work,../../../../usb_dfu/in_fifo.v=work,../../../../usb_dfu/out_fifo.v=work,../../../../usb_dfu/fifo.v=work,../../../../usb_dfu/usb_dfu.v=work,../../../common/hdl/ice40/dpram.v=work,../../../common/hdl/flash/spi.v=work,../../../common/hdl/flash/flash_if.v=work,../../../common/hdl/ram_fifo_if.v=work,../../hdl/bootloader/app.v=work,../../hdl/bootloader/bootloader.v=work 8 | ProjectCFiles=constraints/clk.sdc 9 | CurImplementation=usb_dfu_Implmnt 10 | Implementations=usb_dfu_Implmnt 11 | StartFromSynthesis=yes 12 | IPGeneration=false 13 | 14 | [lse options] 15 | CarryChain=True 16 | CarryChainLength=0 17 | CommandLineOptions= 18 | EBRUtilization=100.00 19 | FSMEncodingStyle=Auto 20 | FixGatedClocks=True 21 | I/OInsertion=True 22 | IntermediateFileDump=False 23 | LoopLimit=1950 24 | MaximalFanout=10000 25 | MemoryInitialValueFileSearchPath= 26 | NumberOfCriticalPaths=3 27 | OptimizationGoal=Area 28 | PropagateConstants=True 29 | RAMStyle=Auto 30 | ROMStyle=Auto 31 | RWCheckOnRam=False 32 | RemoveDuplicateRegisters=True 33 | ResolvedMixedDrivers=False 34 | ResourceSharing=True 35 | TargetFrequency= 36 | TopLevelUnit= 37 | UseIORegister=Auto 38 | VHDL2008=False 39 | VerilogIncludeSearchPath= 40 | 41 | [tool options] 42 | PlacerEffortLevel=std 43 | PlacerAutoLutCascade=yes 44 | PlacerAutoRamCascade=yes 45 | PlacerPowerDriven=no 46 | PlacerAreaDriven=no 47 | RouteWithTimingDriven=yes 48 | RouteWithPinPermutation=yes 49 | BitmapSPIFlashMode=yes 50 | BitmapRAM4KInit=yes 51 | BitmapInitRamBank=1111 52 | BitmapOscillatorFR=low 53 | BitmapEnableWarmBoot=yes 54 | BitmapDisableHeader=no 55 | BitmapSetSecurity=no 56 | BitmapSetNoUsedIONoPullup=no 57 | FloorPlannerShowFanInNets=yes 58 | FloorPlannerShowFanOutNets=yes 59 | HookTo3rdPartyTextEditor=no 60 | 61 | [usb_dfu_Implmnt] 62 | DeviceFamily=iCE40 63 | Device=LP8K 64 | DevicePackage=CM81 65 | DevicePower= 66 | NetlistFile=usb_dfu_Implmnt/usb_dfu.edf 67 | AdditionalEDIFFile= 68 | IPEDIFFile= 69 | DesignLib=usb_dfu_Implmnt/sbt/netlist/oadb-bootloader 70 | DesignView=_rt 71 | DesignCell=bootloader 72 | SynthesisSDCFile=usb_dfu_Implmnt/usb_dfu.scf 73 | UserPinConstraintFile= 74 | UserSDCFile= 75 | PhysicalConstraintFile=constraints/pins.pcf 76 | BackendImplPathName= 77 | Devicevoltage=1.14 78 | DevicevoltagePerformance=+/-5%(datasheet default) 79 | DeviceTemperature=85 80 | TimingAnalysisBasedOn=Worst 81 | OperationRange=Commercial 82 | TypicalCustomTemperature=25 83 | WorstCustomTemperature=85 84 | BestCustomTemperature=0 85 | IOBankVoltages=topBank,3.3 bottomBank,3.3 leftBank,3.3 rightBank,3.3 86 | derValue=1.03369 87 | TimingPathNumberStick=0 88 | 89 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/loopback/usb_dfu_sbt.project: -------------------------------------------------------------------------------- 1 | [Project] 2 | ProjectVersion=2.0 3 | Version=Lattice Semiconductor Corporation iCEcube - Release: 2020.12.27943 - Build Date: Dec 10 2020 18:03:29 4 | ProjectName=usb_dfu 5 | Vendor=SiliconBlue 6 | Synthesis=synplify 7 | ProjectVFiles=../../../../usb_dfu/phy_tx.v=work,../../../../usb_dfu/phy_rx.v=work,../../../../usb_dfu/sie.v=work,../../../../usb_dfu/ctrl_endp.v=work,../../../../usb_dfu/in_fifo.v=work,../../../../usb_dfu/out_fifo.v=work,../../../../usb_dfu/fifo.v=work,../../../../usb_dfu/usb_dfu.v=work,../../../common/hdl/ice40/ram.v=work,../../../common/hdl/ice40/dpram.v=work,../../../common/hdl/flash/spi.v=work,../../../common/hdl/flash/flash_spi.v=work,../../../common/hdl/ram_if.v=work,../../../common/hdl/ram_fifo_if.v=work,../../hdl/loopback/dfu_app.v=work,../../../common/hdl/prescaler.v=work,../../hdl/loopback/loopback.v=work 8 | ProjectCFiles=constraints/clk.sdc 9 | CurImplementation=usb_dfu_Implmnt 10 | Implementations=usb_dfu_Implmnt 11 | StartFromSynthesis=yes 12 | IPGeneration=false 13 | 14 | [lse options] 15 | CarryChain=True 16 | CarryChainLength=0 17 | CommandLineOptions= 18 | EBRUtilization=100.00 19 | FSMEncodingStyle=Auto 20 | FixGatedClocks=True 21 | I/OInsertion=True 22 | IntermediateFileDump=False 23 | LoopLimit=1950 24 | MaximalFanout=10000 25 | MemoryInitialValueFileSearchPath= 26 | NumberOfCriticalPaths=3 27 | OptimizationGoal=Area 28 | PropagateConstants=True 29 | RAMStyle=Auto 30 | ROMStyle=Auto 31 | RWCheckOnRam=False 32 | RemoveDuplicateRegisters=True 33 | ResolvedMixedDrivers=False 34 | ResourceSharing=True 35 | TargetFrequency= 36 | TopLevelUnit= 37 | UseIORegister=Auto 38 | VHDL2008=False 39 | VerilogIncludeSearchPath= 40 | 41 | [tool options] 42 | PlacerEffortLevel=std 43 | PlacerAutoLutCascade=yes 44 | PlacerAutoRamCascade=yes 45 | PlacerPowerDriven=no 46 | PlacerAreaDriven=no 47 | RouteWithTimingDriven=yes 48 | RouteWithPinPermutation=yes 49 | BitmapSPIFlashMode=yes 50 | BitmapRAM4KInit=yes 51 | BitmapInitRamBank=1111 52 | BitmapOscillatorFR=low 53 | BitmapEnableWarmBoot=yes 54 | BitmapDisableHeader=no 55 | BitmapSetSecurity=no 56 | BitmapSetNoUsedIONoPullup=no 57 | FloorPlannerShowFanInNets=yes 58 | FloorPlannerShowFanOutNets=yes 59 | HookTo3rdPartyTextEditor=no 60 | 61 | [usb_dfu_Implmnt] 62 | DeviceFamily=iCE40 63 | Device=LP8K 64 | DevicePackage=CM81 65 | DevicePower= 66 | NetlistFile=usb_dfu_Implmnt/usb_dfu.edf 67 | AdditionalEDIFFile= 68 | IPEDIFFile= 69 | DesignLib=usb_dfu_Implmnt/sbt/netlist/oadb-loopback 70 | DesignView=_rt 71 | DesignCell=loopback 72 | SynthesisSDCFile=usb_dfu_Implmnt/usb_dfu.scf 73 | UserPinConstraintFile= 74 | UserSDCFile= 75 | PhysicalConstraintFile=constraints/pins.pcf 76 | BackendImplPathName= 77 | Devicevoltage=1.14 78 | DevicevoltagePerformance=+/-5%(datasheet default) 79 | DeviceTemperature=85 80 | TimingAnalysisBasedOn=Worst 81 | OperationRange=Commercial 82 | TypicalCustomTemperature=25 83 | WorstCustomTemperature=85 84 | BestCustomTemperature=0 85 | IOBankVoltages=topBank,3.3 bottomBank,3.3 leftBank,3.3 rightBank,3.3 86 | derValue=1.03369 87 | TimingPathNumberStick=0 88 | 89 | -------------------------------------------------------------------------------- /examples/common/hdl/ice40/SB_PLL40_CORE.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ps/1 ps 2 | `define abs(a)((a) >= 0 ? (a) : (-a)) 3 | 4 | module SB_PLL40_CORE ( 5 | input REFERENCECLK, 6 | output PLLOUTCORE, 7 | output PLLOUTGLOBAL, 8 | input EXTFEEDBACK, 9 | input [7:0] DYNAMICDELAY, 10 | output LOCK, 11 | input BYPASS, 12 | input RESETB, 13 | input LATCHINPUTVALUE, 14 | output SDO, 15 | input SDI, 16 | input SCLK 17 | ); 18 | parameter FEEDBACK_PATH = "SIMPLE"; 19 | parameter DELAY_ADJUSTMENT_MODE_FEEDBACK = "FIXED"; 20 | parameter DELAY_ADJUSTMENT_MODE_RELATIVE = "FIXED"; 21 | parameter SHIFTREG_DIV_MODE = 1'b0; 22 | parameter FDA_FEEDBACK = 4'b0000; 23 | parameter FDA_RELATIVE = 4'b0000; 24 | parameter PLLOUT_SELECT = "GENCLK"; 25 | parameter DIVR = 4'b0000; 26 | parameter DIVF = 7'b0000000; 27 | parameter DIVQ = 3'b000; 28 | parameter FILTER_RANGE = 3'b000; 29 | parameter ENABLE_ICEGATE = 1'b0; 30 | parameter TEST_MODE = 1'b0; 31 | parameter EXTERNAL_DIVIDE_FACTOR = 1; 32 | 33 | localparam CLK_RATIO = (DIVF+1)/(2**DIVQ*(DIVR+1)); 34 | 35 | time ref_per; 36 | time clk_per; 37 | time last_ref_rising; 38 | 39 | integer timeout; 40 | 41 | reg clk; 42 | reg lock_reg; 43 | 44 | assign #(clk_per/4) PLLOUTGLOBAL = clk; // glitch filter 45 | assign #(clk_per+ref_per) LOCK = lock_reg; // glitch filter 46 | 47 | initial begin 48 | ref_per = 0; 49 | clk_per = 10; 50 | last_ref_rising = $time; 51 | clk = 0; 52 | lock_reg = 1; 53 | timeout = 4*CLK_RATIO; 54 | #1 lock_reg = 0; // negedge to trigger reset 55 | #100; 56 | ref_per = 0; 57 | clk_per = 100000000; 58 | end 59 | 60 | always @(posedge REFERENCECLK) begin 61 | if (`abs($time - last_ref_rising - ref_per)*100/ref_per < 1) 62 | lock_reg = 1; 63 | else 64 | lock_reg = 0; 65 | ref_per = $time - last_ref_rising; 66 | last_ref_rising = $time; 67 | if (clk_per != 2**DIVQ * (DIVR + 1) * ref_per / (DIVF + 1)) begin 68 | clk_per = 2**DIVQ * (DIVR + 1) * ref_per / (DIVF + 1); 69 | clk <= ~clk; 70 | end 71 | timeout = 4*CLK_RATIO; 72 | end 73 | 74 | always @(clk) 75 | if (timeout > 0) begin 76 | clk <= #(clk_per/2) ~clk; 77 | if (clk) 78 | timeout = timeout - 1; 79 | end else 80 | lock_reg = 0; 81 | endmodule 82 | 83 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/loopback/usb_dfu_Implmnt/mylog.txt: -------------------------------------------------------------------------------- 1 | 2 | 01 3 | i:u_usb_dfu.u_sie.u_phy_tx.bit_cnt_q[2:0] 4 | i:u_usb_dfu.u_sie.u_phy_tx.data_q[7:0] 5 | i:u_usb_dfu.u_sie.u_phy_tx.nrzi_q 6 | i:u_usb_dfu.u_sie.u_phy_tx.stuffing_cnt_q[2:0] 7 | i:u_usb_dfu.u_sie.u_phy_tx.tx_state_q[3:0] 8 | 9 | 02 10 | i:u_usb_dfu.u_sie.u_phy_rx.rx_data_q[7:0] 11 | i:u_usb_dfu.u_sie.u_phy_rx.rx_state_q[4:0] 12 | i:u_usb_dfu.u_sie.u_phy_rx.shift_register_q[8:0] 13 | i:u_usb_dfu.u_sie.u_phy_rx.stuffing_cnt_q[2:0] 14 | 15 | 03 16 | i:u_usb_dfu.u_sie.u_phy_rx.bus_reset_q 17 | i:u_usb_dfu.u_sie.u_phy_rx.cnt_q[17:0] 18 | i:u_usb_dfu.u_sie.u_phy_rx.dp_pu_q 19 | i:u_usb_dfu.u_sie.u_phy_rx.state_q[4:0] 20 | 21 | 04 22 | i:u_usb_dfu.u_sie.u_phy_rx.rx_data_q[7:0] 23 | i:u_usb_dfu.u_sie.u_phy_rx.rx_eop_qq 24 | i:u_usb_dfu.u_sie.u_phy_rx.rx_err_qq 25 | i:u_usb_dfu.u_sie.u_phy_rx.rx_valid_qq 26 | 27 | 05 28 | t:u_usb_dfu.u_sie.u_phy_rx.rx_data_o[7:0] 29 | t:u_usb_dfu.u_sie.u_phy_rx.rx_valid_o 30 | t:u_usb_dfu.u_sie.u_phy_rx.rx_err_o 31 | t:u_usb_dfu.u_sie.u_phy_rx.rx_ready_o 32 | 33 | 06 34 | i:u_usb_dfu.u_sie.addr_q[6:0] 35 | i:u_usb_dfu.u_sie.crc16_q[15:0] 36 | i:u_usb_dfu.u_sie.data_q[15:0] 37 | i:u_usb_dfu.u_sie.delay_cnt_q[2:0] 38 | i:u_usb_dfu.u_sie.endp_q[3:0] 39 | i:u_usb_dfu.u_sie.frame_q[10:0] 40 | i:u_usb_dfu.u_sie.in_byte_q[3:0] 41 | i:u_usb_dfu.u_sie.in_data_ack_q 42 | i:u_usb_dfu.u_sie.in_req_q 43 | i:u_usb_dfu.u_sie.in_toggle_q[15:0] 44 | i:u_usb_dfu.u_sie.in_zlp_q[15:0] 45 | i:u_usb_dfu.u_sie.out_eop_q 46 | i:u_usb_dfu.u_sie.out_err_q 47 | i:u_usb_dfu.u_sie.out_toggle_q[15:0] 48 | i:u_usb_dfu.u_sie.phy_state_q[11:0] 49 | i:u_usb_dfu.u_sie.pid_q[3:0] 50 | 51 | 07 52 | i:u_usb_dfu.u_ctrl_endp.addr_q[6:0] 53 | i:u_usb_dfu.u_ctrl_endp.addr_qq[6:0] 54 | i:u_usb_dfu.u_ctrl_endp.alternate_setting_q[1:0] 55 | i:u_usb_dfu.u_ctrl_endp.blocknum_q[15:0] 56 | i:u_usb_dfu.u_ctrl_endp.byte_cnt_q[8:0] 57 | i:u_usb_dfu.u_ctrl_endp.class_q 58 | i:u_usb_dfu.u_ctrl_endp.dev_state_q[1:0] 59 | i:u_usb_dfu.u_ctrl_endp.dev_state_qq[1:0] 60 | i:u_usb_dfu.u_ctrl_endp.dfu_done_q 61 | i:u_usb_dfu.u_ctrl_endp.dfu_state_q[10:0] 62 | i:u_usb_dfu.u_ctrl_endp.endp_q[3:0] 63 | i:u_usb_dfu.u_ctrl_endp.in_dir_q 64 | i:u_usb_dfu.u_ctrl_endp.in_endp_q 65 | i:u_usb_dfu.u_ctrl_endp.max_length_q[8:0] 66 | i:u_usb_dfu.u_ctrl_endp.rec_q[1:0] 67 | i:u_usb_dfu.u_ctrl_endp.req_q[24:0] 68 | i:u_usb_dfu.u_ctrl_endp.state_q[7:0] 69 | i:u_usb_dfu.u_ctrl_endp.string_index_q[3:0] 70 | i:u_usb_dfu.u_ctrl_endp.string_index_q[7:5] 71 | i:u_usb_dfu.u_ctrl_endp.vendor_q 72 | 73 | 08 74 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_first_q[3:0] 75 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_first_qq[3:0] 76 | 77 | 09 78 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_empty_o 79 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_full_o 80 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_data_o[7:0] 81 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_valid_o 82 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_ready_i 83 | 84 | 10 85 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_fifo_q[71:0] 86 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_last_q[3:0] 87 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_last_qq[3:0] 88 | 89 | 11 90 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_fifo_q[71:0] 91 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_last_q[3:0] 92 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_last_qq[3:0] 93 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_nak_q 94 | 95 | 12 96 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_empty_o 97 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_full_o 98 | 99 | 13 100 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.out_first_q[3:0] 101 | 102 | 14 103 | i:u_usb_dfu.clk_gate_q 104 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/bootloader/usb_dfu_Implmnt/mylog.txt: -------------------------------------------------------------------------------- 1 | 2 | 01 3 | i:u_usb_dfu.u_sie.u_phy_tx.bit_cnt_q[2:0] 4 | i:u_usb_dfu.u_sie.u_phy_tx.data_q[7:0] 5 | i:u_usb_dfu.u_sie.u_phy_tx.nrzi_q 6 | i:u_usb_dfu.u_sie.u_phy_tx.stuffing_cnt_q[2:0] 7 | i:u_usb_dfu.u_sie.u_phy_tx.tx_state_q[3:0] 8 | 9 | 02 10 | i:u_usb_dfu.u_sie.u_phy_rx.rx_data_q[7:0] 11 | i:u_usb_dfu.u_sie.u_phy_rx.rx_state_q[4:0] 12 | i:u_usb_dfu.u_sie.u_phy_rx.shift_register_q[8:0] 13 | i:u_usb_dfu.u_sie.u_phy_rx.stuffing_cnt_q[2:0] 14 | 15 | 03 16 | i:u_usb_dfu.u_sie.u_phy_rx.bus_reset_q 17 | i:u_usb_dfu.u_sie.u_phy_rx.cnt_q[17:0] 18 | i:u_usb_dfu.u_sie.u_phy_rx.dp_pu_q 19 | i:u_usb_dfu.u_sie.u_phy_rx.state_q[4:0] 20 | 21 | 04 22 | i:u_usb_dfu.u_sie.u_phy_rx.rx_data_q[7:0] 23 | i:u_usb_dfu.u_sie.u_phy_rx.rx_eop_qq 24 | i:u_usb_dfu.u_sie.u_phy_rx.rx_err_qq 25 | i:u_usb_dfu.u_sie.u_phy_rx.rx_valid_qq 26 | 27 | 05 28 | t:u_usb_dfu.u_sie.u_phy_rx.rx_data_o[7:0] 29 | t:u_usb_dfu.u_sie.u_phy_rx.rx_valid_o 30 | t:u_usb_dfu.u_sie.u_phy_rx.rx_err_o 31 | t:u_usb_dfu.u_sie.u_phy_rx.rx_ready_o 32 | 33 | 06 34 | i:u_usb_dfu.u_sie.addr_q[6:0] 35 | i:u_usb_dfu.u_sie.crc16_q[15:0] 36 | i:u_usb_dfu.u_sie.data_q[15:0] 37 | i:u_usb_dfu.u_sie.delay_cnt_q[2:0] 38 | i:u_usb_dfu.u_sie.endp_q[3:0] 39 | i:u_usb_dfu.u_sie.frame_q[10:0] 40 | i:u_usb_dfu.u_sie.in_byte_q[3:0] 41 | i:u_usb_dfu.u_sie.in_data_ack_q 42 | i:u_usb_dfu.u_sie.in_req_q 43 | i:u_usb_dfu.u_sie.in_toggle_q[15:0] 44 | i:u_usb_dfu.u_sie.in_zlp_q[15:0] 45 | i:u_usb_dfu.u_sie.out_eop_q 46 | i:u_usb_dfu.u_sie.out_err_q 47 | i:u_usb_dfu.u_sie.out_toggle_q[15:0] 48 | i:u_usb_dfu.u_sie.phy_state_q[11:0] 49 | i:u_usb_dfu.u_sie.pid_q[3:0] 50 | 51 | 07 52 | i:u_usb_dfu.u_ctrl_endp.addr_q[6:0] 53 | i:u_usb_dfu.u_ctrl_endp.addr_qq[6:0] 54 | i:u_usb_dfu.u_ctrl_endp.alternate_setting_q[1:0] 55 | i:u_usb_dfu.u_ctrl_endp.blocknum_q[15:0] 56 | i:u_usb_dfu.u_ctrl_endp.byte_cnt_q[8:0] 57 | i:u_usb_dfu.u_ctrl_endp.class_q 58 | i:u_usb_dfu.u_ctrl_endp.dev_state_q[1:0] 59 | i:u_usb_dfu.u_ctrl_endp.dev_state_qq[1:0] 60 | i:u_usb_dfu.u_ctrl_endp.dfu_done_q 61 | i:u_usb_dfu.u_ctrl_endp.dfu_state_q[10:0] 62 | i:u_usb_dfu.u_ctrl_endp.endp_q[3:0] 63 | i:u_usb_dfu.u_ctrl_endp.in_dir_q 64 | i:u_usb_dfu.u_ctrl_endp.in_endp_q 65 | i:u_usb_dfu.u_ctrl_endp.max_length_q[8:0] 66 | i:u_usb_dfu.u_ctrl_endp.rec_q[1:0] 67 | i:u_usb_dfu.u_ctrl_endp.req_q[24:0] 68 | i:u_usb_dfu.u_ctrl_endp.state_q[7:0] 69 | i:u_usb_dfu.u_ctrl_endp.string_index_q[3:0] 70 | i:u_usb_dfu.u_ctrl_endp.string_index_q[7:5] 71 | i:u_usb_dfu.u_ctrl_endp.vendor_q 72 | 73 | 08 74 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_first_q[3:0] 75 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_first_qq[3:0] 76 | 77 | 09 78 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_empty_o 79 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_full_o 80 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_data_o[7:0] 81 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_valid_o 82 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_ready_i 83 | 84 | 10 85 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_fifo_q[71:0] 86 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_last_q[3:0] 87 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_last_qq[3:0] 88 | 89 | 11 90 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_fifo_q[71:0] 91 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_last_q[3:0] 92 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_last_qq[3:0] 93 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_nak_q 94 | 95 | 12 96 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_empty_o 97 | t:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_full_o 98 | 99 | 13 100 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.out_first_q[3:0] 101 | 102 | 14 103 | i:u_usb_dfu.clk_gate_q 104 | -------------------------------------------------------------------------------- /examples/common/hdl/ram_fifo_if.v: -------------------------------------------------------------------------------- 1 | // FLASH memory serial interface. 2 | // Written in verilog 2001 3 | 4 | // FLASH_SPI module shall provide access to read/program serial FLASH memory: 5 | // - When en_i changes from low to high, a new read/program operation shall start. 6 | // - Memory read shall start at byte address specified by start_block_addr_i+read_addr_offset_i. 7 | // - Memory programming shall start at beginning of the block addressed by start_block_addr_i. 8 | // - Memory read/program operation shall end at the end of the block addressed by end_block_addr_i. 9 | // FLASH_SPI module shall check correct block erasing and correct data programming: 10 | // - Erase/Programming failures shall be reported by status_o. 11 | // - When status_o reports a failure, FLASH_SPI shall wait a clear_status_i pulse to clear status_o 12 | // and to allow the next read/program operation. 13 | 14 | module ram_fifo_if 15 | #(parameter RAM_SIZE = 'd1024) // byte size 16 | ( 17 | input clk_i, 18 | input rstn_i, 19 | // While rstn_i is low (active low), the module shall be reset 20 | 21 | // ---- to/from application module -------------- 22 | input en_i, 23 | input in_valid_i, 24 | output in_ready_o, 25 | output out_valid_o, 26 | input out_ready_i, 27 | output empty_o, 28 | output full_o, 29 | output in_clke_o, 30 | output out_clke_o, 31 | output [ceil_log2(RAM_SIZE)-1:0] in_addr_o, 32 | output [ceil_log2(RAM_SIZE)-1:0] out_addr_o 33 | ); 34 | 35 | function integer ceil_log2; 36 | input [31:0] arg; 37 | integer i; 38 | begin 39 | ceil_log2 = 0; 40 | for (i = 0; i < 32; i = i + 1) begin 41 | if (arg > (1 << i)) 42 | ceil_log2 = ceil_log2 + 1; 43 | end 44 | end 45 | endfunction 46 | 47 | reg [ceil_log2(RAM_SIZE)+1-1:0] in_addr_q, in_addr_d; 48 | reg [ceil_log2(RAM_SIZE)+1-1:0] out_addr_q, out_addr_d; 49 | reg out_valid_q, out_valid_d; 50 | 51 | wire empty, full; 52 | 53 | assign empty_o = empty & ~out_valid_q; 54 | assign full_o = full; 55 | assign empty = (in_addr_q == out_addr_q) ? 1'b1 : 1'b0; 56 | assign full = (in_addr_q[ceil_log2(RAM_SIZE)-1:0] == out_addr_q[ceil_log2(RAM_SIZE)-1:0] && 57 | in_addr_q[ceil_log2(RAM_SIZE)+1-1] != out_addr_q[ceil_log2(RAM_SIZE)+1-1]) ? 58 | 1'b1 : 1'b0; 59 | assign in_ready_o = ~full; 60 | assign out_valid_o = out_valid_q; 61 | assign in_addr_o = in_addr_q[ceil_log2(RAM_SIZE)-1:0]; 62 | assign out_addr_o = out_addr_q[ceil_log2(RAM_SIZE)-1:0]; 63 | 64 | always @(posedge clk_i or negedge rstn_i) begin 65 | if (~rstn_i) begin 66 | in_addr_q <= 'd0; 67 | out_addr_q <= 'd0; 68 | out_valid_q <= 1'b0; 69 | end else begin 70 | in_addr_q <= in_addr_d; 71 | out_addr_q <= out_addr_d; 72 | out_valid_q <= out_valid_d; 73 | end 74 | end 75 | 76 | reg in_clke; 77 | reg out_clke; 78 | 79 | assign in_clke_o = in_clke; 80 | assign out_clke_o = out_clke; 81 | 82 | always @(/*AS*/empty or en_i or full or in_addr_q or in_valid_i 83 | or out_addr_q or out_ready_i or out_valid_q) begin 84 | in_addr_d = in_addr_q; 85 | out_addr_d = out_addr_q; 86 | out_valid_d = out_valid_q; 87 | in_clke = 1'b0; 88 | out_clke = 1'b0; 89 | 90 | if (~en_i) begin 91 | in_addr_d = 'd0; 92 | out_addr_d = 'd0; 93 | out_valid_d = 1'b0; 94 | end else begin 95 | if (in_valid_i & ~full) begin 96 | in_addr_d = in_addr_q + 1; 97 | in_clke = 1'b1; 98 | end 99 | 100 | if (~empty | out_valid_q) begin 101 | if (~out_valid_q) begin 102 | out_addr_d = out_addr_q + 1; 103 | out_valid_d = 1'b1; 104 | out_clke = 1'b1; 105 | end else if (out_ready_i) begin 106 | if (~empty) begin 107 | out_addr_d = out_addr_q + 1; 108 | out_clke = 1'b1; 109 | end else begin 110 | out_valid_d = 1'b0; 111 | end 112 | end 113 | end 114 | end 115 | end 116 | 117 | endmodule 118 | -------------------------------------------------------------------------------- /usb_dfu/README.md: -------------------------------------------------------------------------------- 1 | ### Design goals: 2 | 1. Full implementation of USB CDC/DFU device features with in mind future reuse for other USB device classes. 3 | 2. Asynchronous clocks between internal USB stuff and the rest of FPGA logic. 4 | 3. Small footprint and no use of EBR memories for an easy ASIC implementation. 5 | 4. Architecture that support an high clock frequency for internal USB\_DFU logic to allow implementation on a wide range of FPGA and ASIC technologies. 6 | 5. Low power consumption. 7 | 8 | ### Architecture 9 | USB\_DFU is built on a minimum number of functional blocks: 10 | 11 | 1. PHY\_RX shall sample USB lines at 12MHz * BIT\_SAMPLES and manage physical layer signaling such as NRZI decoding, bit stuffing removal, and data deserialization. It detects USB reset too. 12 | 2. PHY\_TX shall manage physical layer signaling such as NRZI encoding, bit stuffed insertion, and data serialization. 13 | 3. SIE shall embed PHY\_RX and PHY\_TX modules and manage physical and protocol layers with packet recognition, transaction sequencing, CRC generation/checking, packet ID (PID) generation, and checking/decoding. 14 | 4. CTRL\_ENDP shall implement IN/OUT Control Endpoint. It shall manage control transfers by providing device descriptors, keeping device status/address, and responding to standard and ACM subclass requests. 15 | 5. FIFO shall implement IN/OUT Bulk Endpoint, DFU control data transfer and IN/OUT FIFO interfaces. To save FPGA resources the same instance is used for both CDC/ACM (in Run-time) and DFU (in DFU mode) data transfers. 16 | 6. USB\_DFU shall implement the top level by embedding SIE and control/bulk endpoints. 17 | 18 | This partitioning helps to confine the modifications in case of reuse for a new device class implementation. For example, PHY\_TX, PHY\_RX, SIE and both IN\_FIFO and OUT\_FIFO shall remain unchanged. CTRL\_ENDP shall be changed to implement the new class-specific descriptors and request responses. FIFO shall be removed/modified to meet new class requirements. New isochronous/interrupt/bulk endpoints shall be added to meet new class requirements. 19 | 20 | ### Data flow and FIFO 21 | Data flows from/to PHY\_RX/PHY\_TX directly through SIE to OUT/IN endpoints. SIE keeps the minimum data necessary to check/generate CRC. This keeps logic utilization at a minimum. Furthermore, this helps to meet timings too. Indeed USB data is elaborated byte by byte at the full-speed USB rate (1.5MBs), and there is plenty of time between one byte and the next one. 22 | 23 | CTRL_ENDP elaborates this data in real-time without storing it. If an error is detected, then the current operation is aborted, and a proper response is provided to SIE. 24 | 25 | FIFO collects OUT data into OUT\_FIFO, and at the end of an OUT bulk transfer without errors makes it available to the external logic. Otherwise, OUT\_FIFO is flushed from incomplete data. Just after each OUT byte is consumed, it is flushed from FIFO. Conversely, when FIFO receives IN data from external logic, it stores it into IN\_FIFO and makes it available immediately to SIE. After IN data is transferred to the USB host without errors, it is flushed from IN\_FIFO. Otherwise, it is kept to be retransmitted with the next IN transfer. 26 | 27 | ### Asynchronous clock domains 28 | USB data can be exchanged with external USB\_DFU logic through the same clock `clk_i` or with an asynchronous one `app_clk_i`. 29 | This choice is made through a Verilog parameter and implemented through a generate construct. 30 | 31 | Synchronization between the two clock domains is made on valid/ready control signals with double synchronization flip-flops to avoid metastability. These flip-flops are clocked by `app_clk_i` for signals that belong to the `clk_i` domain and vice versa by `clk_i` for signals that belong to the `app_clk_i` domain. So, to synchronize back and forth the control signals, this requires on average about 2\*2.5 `app_clk_i` cycles + 2\*2.5 `clk_i` cycles. 32 | If freq(`app_clk_i`) ≤ 12MHz then it is possible to guarantee a safe synchronization with double synchronization flip-flops clocked by `clk_i` only. This improves data throughput. 33 | 34 | If freq(`app_clk_i`) ≤ 12MHz then data is exchanged at every 1 or 2 `app_clk_i` cycles. 35 | 36 | ![](../readme_files/sync.png) 37 | 38 | USB data is transferred at a maximum byte rate of 1.5MHz, so data transfer is limited by USB if freq(`app_clk_i`) >= 1.5MHz. Otherwise, data is exchanged at a byte rate of freq(`app_clk_i`). 39 | 40 | ### Clock gating 41 | Clock gating is extensively used to allow high clock frequencies and reduce power consumption by exploiting USB peculiarities. 42 | 43 | A frequency of 12MHz * BIT\_SAMPLES is exclusively employed in PHY\_RX and IN\_FIFO/OUT\_FIFO for signal synchronization between asynchronous clock domains. For all other logic circuitry, a clock gating mechanism is utilized to enable the clock every BIT\_SAMPLES cycles. This approach eases the timing closure to adhere to the 12MHz clock frequency by implementing a multi-cycle path constraint equal to BIT\_SAMPLES. 44 | 45 | USB device serializes data at 12MHz frequency. Data is transferred internally at byte chunks with a lower frequency of 1.5MHz. 46 | Synplify Pro is aware of these timings with the definition of multi-cycle path constraints. Yosys/nextpnr doesn't allow to specify timing constraints, so if timings are not met, there is a good chance that USB\_DFU works correctly. 47 | 48 | In an ASIC device, clock gating is implemented directly on the clock tree. This significantly reduces power consumption by shutting down clock switching when data transfer is not requested. 49 | 50 | In an FPGA device, clock gating is implemented through the flip-flop enable pin. This additional path makes easier the timing closure. 51 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/loopback/usb_dfu_Implmnt/sbt/outputs/loopback_sbt.rpt: -------------------------------------------------------------------------------- 1 | * ****************************************************************************** 2 | 3 | * iCEcube Report 4 | 5 | * Version: 2020.12.27943 6 | 7 | * Build Date: Dec 10 2020 17:24:17 8 | 9 | * File Generated: Mar 10 2024 17:19:17 10 | 11 | * Purpose: General info of design implementation 12 | 13 | * Copyright (C) 2006-2010 by Lattice Semiconductor Corp. All rights reserved. 14 | 15 | * ****************************************************************************** 16 | 17 | Synthesis/Placement Summary: 18 | ---------------------------- 19 | Status: Successful 20 | Runtime: 3 seconds 21 | 22 | Device Info: 23 | ------------ 24 | Device Family: iCE40 25 | Device: iCE40LP8K 26 | Package: CM81 27 | 28 | Design statistics: 29 | ------------------ 30 | FFs: 647 31 | LUTs: 2719 32 | RAMs: 3 33 | IOBs: 9 34 | GBs: 7 35 | PLLs: 1 36 | Warm Boots: 0 37 | 38 | Logic Resource Utilization: 39 | --------------------------- 40 | Total Logic Cells: 2739/7680 41 | Combinational Logic Cells: 2092 out of 7680 27.2396% 42 | Sequential Logic Cells: 647 out of 7680 8.42448% 43 | Logic Tiles: 449 out of 960 46.7708% 44 | Registers: 45 | Logic Registers: 647 out of 7680 8.42448% 46 | IO Registers: 0 out of 1280 0 47 | Block RAMs: 3 out of 32 9.375% 48 | Warm Boots: 0 out of 1 0% 49 | Pins: 50 | Input Pins: 2 out of 63 3.1746% 51 | Output Pins: 5 out of 63 7.93651% 52 | InOut Pins: 2 out of 63 3.1746% 53 | Global Buffers: 7 out of 8 87.5% 54 | PLLs: 1 out of 1 100% 55 | 56 | IO Bank Utilization: 57 | -------------------- 58 | Bank 3: 1 out of 18 5.55556% 59 | Bank 1: 0 out of 15 0% 60 | Bank 0: 4 out of 17 23.5294% 61 | Bank 2: 4 out of 13 30.7692% 62 | 63 | Detailed I/O Info: 64 | ------------------ 65 | Input Pins: 66 | Pin Number Direction IO Standard Pull Up IO Bank IO Function Signal Name 67 | ---------- --------- ----------- ------- ------- ----------- ----------- 68 | B2 Input SB_LVCMOS No 3 Simple Input clk 69 | H7 Input SB_LVCMOS No 2 Simple Input sdi 70 | 71 | Output Pins: 72 | Pin Number Direction IO Standard Pull Up IO Bank IO Function Signal Name 73 | ---------- --------- ----------- ------- ------- ----------- ----------- 74 | A3 Output SB_LVCMOS No 0 Output Tristatable by Enable usb_pu 75 | B3 Output SB_LVCMOS No 0 Simple Output led 76 | F7 Output SB_LVCMOS No 2 Simple Output ss 77 | G6 Output SB_LVCMOS No 2 Simple Output sdo 78 | G7 Output SB_LVCMOS No 2 Simple Output sck 79 | 80 | Inoutput Pins: 81 | Pin Number Direction IO Standard Pull Up IO Bank IO Function Signal Name 82 | ---------- --------- ----------- ------- ------- ----------- ----------- 83 | A4 InOut SB_LVCMOS No 0 Simple Input Output Tristatable by Enable usb_n 84 | B4 InOut SB_LVCMOS No 0 Simple Input Output Tristatable by Enable usb_p 85 | 86 | Detailed Global Buffer Info: 87 | ---------------------------- 88 | Buffer Number IO Bank Driven By Fanout Signal Name 89 | ------------- ------- --------- ------ ----------- 90 | 5 2 188 clk_c_g 91 | 3 3 41 u_usb_dfu.u_sie.in_zlp_q_0_sqmuxa_g 92 | 7 1 184 u_usb_dfu.rstn_i_g 93 | 0 2 186 u_usb_dfu.u_fifo_endps_0__u_fifo.rstn_i_g 94 | 2 1 92 u_usb_dfu.rstn_sq_i_g_0 95 | 1 0 109 u_usb_dfu.clk_gate_q_g 96 | 4 0 160 u_dfu_app_rstn_sq_i_g_0 97 | 98 | 99 | Router Summary: 100 | --------------- 101 | Status: Successful 102 | Runtime: 26 seconds 103 | 104 | Routing Resource Utilization: 105 | ----------------------------- 106 | Local line of tile 19865 out of 146184 13.589% 107 | Span 4 5584 out of 29696 18.8039% 108 | Span 12 809 out of 5632 14.3643% 109 | Global network 8 out of 8 100% 110 | Vertical Inter-LUT Connect 764 out of 6720 11.369% 111 | 112 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/bootloader/usb_dfu_Implmnt/sbt/outputs/bootloader_sbt.rpt: -------------------------------------------------------------------------------- 1 | * ****************************************************************************** 2 | 3 | * iCEcube Report 4 | 5 | * Version: 2020.12.27943 6 | 7 | * Build Date: Dec 10 2020 17:24:17 8 | 9 | * File Generated: Mar 10 2024 17:06:14 10 | 11 | * Purpose: General info of design implementation 12 | 13 | * Copyright (C) 2006-2010 by Lattice Semiconductor Corp. All rights reserved. 14 | 15 | * ****************************************************************************** 16 | 17 | Synthesis/Placement Summary: 18 | ---------------------------- 19 | Status: Successful 20 | Runtime: 3 seconds 21 | 22 | Device Info: 23 | ------------ 24 | Device Family: iCE40 25 | Device: iCE40LP8K 26 | Package: CM81 27 | 28 | Design statistics: 29 | ------------------ 30 | FFs: 694 31 | LUTs: 2793 32 | RAMs: 1 33 | IOBs: 9 34 | GBs: 7 35 | PLLs: 1 36 | Warm Boots: 1 37 | 38 | Logic Resource Utilization: 39 | --------------------------- 40 | Total Logic Cells: 2804/7680 41 | Combinational Logic Cells: 2110 out of 7680 27.474% 42 | Sequential Logic Cells: 694 out of 7680 9.03646% 43 | Logic Tiles: 439 out of 960 45.7292% 44 | Registers: 45 | Logic Registers: 694 out of 7680 9.03646% 46 | IO Registers: 0 out of 1280 0 47 | Block RAMs: 1 out of 32 3.125% 48 | Warm Boots: 1 out of 1 0% 49 | Pins: 50 | Input Pins: 2 out of 63 3.1746% 51 | Output Pins: 5 out of 63 7.93651% 52 | InOut Pins: 2 out of 63 3.1746% 53 | Global Buffers: 7 out of 8 87.5% 54 | PLLs: 1 out of 1 100% 55 | 56 | IO Bank Utilization: 57 | -------------------- 58 | Bank 3: 1 out of 18 5.55556% 59 | Bank 1: 0 out of 15 0% 60 | Bank 0: 4 out of 17 23.5294% 61 | Bank 2: 4 out of 13 30.7692% 62 | 63 | Detailed I/O Info: 64 | ------------------ 65 | Input Pins: 66 | Pin Number Direction IO Standard Pull Up IO Bank IO Function Signal Name 67 | ---------- --------- ----------- ------- ------- ----------- ----------- 68 | B2 Input SB_LVCMOS No 3 Simple Input clk 69 | H7 Input SB_LVCMOS No 2 Simple Input sdi 70 | 71 | Output Pins: 72 | Pin Number Direction IO Standard Pull Up IO Bank IO Function Signal Name 73 | ---------- --------- ----------- ------- ------- ----------- ----------- 74 | A3 Output SB_LVCMOS No 0 Output Tristatable by Enable usb_pu 75 | B3 Output SB_LVCMOS No 0 Simple Output led 76 | F7 Output SB_LVCMOS No 2 Simple Output ss 77 | G6 Output SB_LVCMOS No 2 Simple Output sdo 78 | G7 Output SB_LVCMOS No 2 Simple Output sck 79 | 80 | Inoutput Pins: 81 | Pin Number Direction IO Standard Pull Up IO Bank IO Function Signal Name 82 | ---------- --------- ----------- ------- ------- ----------- ----------- 83 | A4 InOut SB_LVCMOS No 0 Simple Input Output Tristatable by Enable usb_n 84 | B4 InOut SB_LVCMOS No 0 Simple Input Output Tristatable by Enable usb_p 85 | 86 | Detailed Global Buffer Info: 87 | ---------------------------- 88 | Buffer Number IO Bank Driven By Fanout Signal Name 89 | ------------- ------- --------- ------ ----------- 90 | 5 2 231 clk_c_g 91 | 7 1 184 u_usb_dfu.rstn_i_g 92 | 1 0 186 u_usb_dfu.u_fifo_endps_0__u_fifo.rstn_i_g 93 | 0 2 92 u_usb_dfu.rstn_sq_i_g_0 94 | 3 3 106 u_usb_dfu.clk_gate_q_g 95 | 2 1 69 u_app.rt_rstn_i_g 96 | 4 0 107 u_app.N_170_g 97 | 98 | 99 | Router Summary: 100 | --------------- 101 | Status: Successful 102 | Runtime: 25 seconds 103 | 104 | Routing Resource Utilization: 105 | ----------------------------- 106 | Local line of tile 20158 out of 146184 13.7895% 107 | Span 4 5200 out of 29696 17.5108% 108 | Span 12 700 out of 5632 12.429% 109 | Global network 8 out of 8 100% 110 | Vertical Inter-LUT Connect 789 out of 6720 11.7411% 111 | 112 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/bootloader/usb_dfu_Implmnt/all_registers.txt: -------------------------------------------------------------------------------- 1 | 2 | all_registers: 3 | i:u_app.boot_q 4 | i:u_app.heartbeat_sq[2:0] 5 | i:u_app.rd_length_q[15:0] 6 | i:u_app.rstn_sq[1:0] 7 | i:u_app.state_q[7:0] 8 | i:u_app.timer_q[25:0] 9 | i:u_app.u_dpram.u_8bit\.byte_raddr_q 10 | i:u_app.u_flash_if.byte_cnt_q[7:0] 11 | i:u_app.u_flash_if.crc16_q[15:0] 12 | i:u_app.u_flash_if.in_en_q 13 | i:u_app.u_flash_if.last_byte_q[7:0] 14 | i:u_app.u_flash_if.out_en_q 15 | i:u_app.u_flash_if.page_addr_q[11:0] 16 | i:u_app.u_flash_if.state_q[23:0] 17 | i:u_app.u_flash_if.wait_cnt_q[15:0] 18 | i:u_app.u_ram_fifo_if.in_addr_q[9:0] 19 | i:u_app.u_ram_fifo_if.out_addr_q[9:0] 20 | i:u_app.u_ram_fifo_if.out_valid_q 21 | i:u_app.u_spi.bit_cnt_q[2:0] 22 | i:u_app.u_spi.en_q 23 | i:u_app.u_spi.rd_data_q[7:0] 24 | i:u_app.u_spi.sck_q 25 | i:u_app.u_spi.state_q[3:0] 26 | i:u_app.u_spi.wr_data_q[7:0] 27 | i:u_app.wr_length_q[15:0] 28 | i:u_usb_dfu.clk_cnt_q[1:0] 29 | i:u_usb_dfu.clk_gate_q 30 | i:u_usb_dfu.dfu_clear_status_q 31 | i:u_usb_dfu.fifo_rstn_q 32 | i:u_usb_dfu.rstn_sq[1:0] 33 | i:u_usb_dfu.u_async_app\.app_rstn_sq[1:0] 34 | i:u_usb_dfu.u_async_app\.dfu_busy_sq[1:0] 35 | i:u_usb_dfu.u_async_app\.dfu_clear_status_sq[1:0] 36 | i:u_usb_dfu.u_async_app\.dfu_in_en_sq[1:0] 37 | i:u_usb_dfu.u_async_app\.dfu_mode_sq[1:0] 38 | i:u_usb_dfu.u_async_app\.dfu_out_en_sq[1:0] 39 | i:u_usb_dfu.u_async_app\.dfu_status_sq[1:0] 40 | i:u_usb_dfu.u_ctrl_endp.addr_q[6:0] 41 | i:u_usb_dfu.u_ctrl_endp.addr_qq[6:0] 42 | i:u_usb_dfu.u_ctrl_endp.alternate_setting_q[1:0] 43 | i:u_usb_dfu.u_ctrl_endp.blocknum_q[15:0] 44 | i:u_usb_dfu.u_ctrl_endp.byte_cnt_q[8:0] 45 | i:u_usb_dfu.u_ctrl_endp.class_q 46 | i:u_usb_dfu.u_ctrl_endp.dev_state_q[1:0] 47 | i:u_usb_dfu.u_ctrl_endp.dev_state_qq[1:0] 48 | i:u_usb_dfu.u_ctrl_endp.dfu_done_q 49 | i:u_usb_dfu.u_ctrl_endp.dfu_state_q[10:0] 50 | i:u_usb_dfu.u_ctrl_endp.endp_q[3:0] 51 | i:u_usb_dfu.u_ctrl_endp.in_dir_q 52 | i:u_usb_dfu.u_ctrl_endp.in_endp_q 53 | i:u_usb_dfu.u_ctrl_endp.max_length_q[8:0] 54 | i:u_usb_dfu.u_ctrl_endp.rec_q[1:0] 55 | i:u_usb_dfu.u_ctrl_endp.req_q[24:0] 56 | i:u_usb_dfu.u_ctrl_endp.state_q[7:0] 57 | i:u_usb_dfu.u_ctrl_endp.string_index_q[3:0] 58 | i:u_usb_dfu.u_ctrl_endp.string_index_q[7:5] 59 | i:u_usb_dfu.u_ctrl_endp.vendor_q 60 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_async_app_rstn\.app_rstn_sq[1:0] 61 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_first_q[3:0] 62 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_first_qq[3:0] 63 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_data_q[7:0] 64 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_ready_q 65 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_ready_sq[1:0] 66 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_valid_q 67 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_valid_qq 68 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_valid_sq[1:0] 69 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_fifo_q[71:0] 70 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_last_q[3:0] 71 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_last_qq[3:0] 72 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_fifo_q[71:0] 73 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_last_q[3:0] 74 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_last_qq[3:0] 75 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_nak_q 76 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.app_out_consumed_q 77 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.app_out_consumed_sq[1:0] 78 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.app_out_data_q[7:0] 79 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.app_out_valid_q 80 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.out_first_q[3:0] 81 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.out_valid_sq[1:0] 82 | i:u_usb_dfu.u_sie.addr_q[6:0] 83 | i:u_usb_dfu.u_sie.crc16_q[15:0] 84 | i:u_usb_dfu.u_sie.data_q[15:0] 85 | i:u_usb_dfu.u_sie.delay_cnt_q[2:0] 86 | i:u_usb_dfu.u_sie.endp_q[3:0] 87 | i:u_usb_dfu.u_sie.frame_q[10:0] 88 | i:u_usb_dfu.u_sie.in_byte_q[3:0] 89 | i:u_usb_dfu.u_sie.in_data_ack_q 90 | i:u_usb_dfu.u_sie.in_req_q 91 | i:u_usb_dfu.u_sie.in_toggle_q[15:0] 92 | i:u_usb_dfu.u_sie.in_zlp_q[15:0] 93 | i:u_usb_dfu.u_sie.out_eop_q 94 | i:u_usb_dfu.u_sie.out_err_q 95 | i:u_usb_dfu.u_sie.out_toggle_q[15:0] 96 | i:u_usb_dfu.u_sie.phy_state_q[11:0] 97 | i:u_usb_dfu.u_sie.pid_q[3:0] 98 | i:u_usb_dfu.u_sie.u_phy_rx.bus_reset_q 99 | i:u_usb_dfu.u_sie.u_phy_rx.cnt_q[17:0] 100 | i:u_usb_dfu.u_sie.u_phy_rx.dn_q[2:0] 101 | i:u_usb_dfu.u_sie.u_phy_rx.dp_pu_q 102 | i:u_usb_dfu.u_sie.u_phy_rx.dp_q[2:0] 103 | i:u_usb_dfu.u_sie.u_phy_rx.nrzi_q[3:0] 104 | i:u_usb_dfu.u_sie.u_phy_rx.rx_data_q[7:0] 105 | i:u_usb_dfu.u_sie.u_phy_rx.rx_en_q 106 | i:u_usb_dfu.u_sie.u_phy_rx.rx_eop_q 107 | i:u_usb_dfu.u_sie.u_phy_rx.rx_eop_qq 108 | i:u_usb_dfu.u_sie.u_phy_rx.rx_err_q 109 | i:u_usb_dfu.u_sie.u_phy_rx.rx_err_qq 110 | i:u_usb_dfu.u_sie.u_phy_rx.rx_state_q[4:0] 111 | i:u_usb_dfu.u_sie.u_phy_rx.rx_valid_q 112 | i:u_usb_dfu.u_sie.u_phy_rx.rx_valid_qq 113 | i:u_usb_dfu.u_sie.u_phy_rx.sample_cnt_q[1:0] 114 | i:u_usb_dfu.u_sie.u_phy_rx.se0_q 115 | i:u_usb_dfu.u_sie.u_phy_rx.shift_register_q[8:0] 116 | i:u_usb_dfu.u_sie.u_phy_rx.state_q[4:0] 117 | i:u_usb_dfu.u_sie.u_phy_rx.stuffing_cnt_q[2:0] 118 | i:u_usb_dfu.u_sie.u_phy_tx.bit_cnt_q[2:0] 119 | i:u_usb_dfu.u_sie.u_phy_tx.data_q[7:0] 120 | i:u_usb_dfu.u_sie.u_phy_tx.nrzi_q 121 | i:u_usb_dfu.u_sie.u_phy_tx.stuffing_cnt_q[2:0] 122 | i:u_usb_dfu.u_sie.u_phy_tx.tx_state_q[3:0] 123 | i:u_usb_n 124 | i:u_usb_p 125 | i:u_usb_pu 126 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/iCEcube2/loopback/usb_dfu_Implmnt/all_registers.txt: -------------------------------------------------------------------------------- 1 | 2 | all_registers: 3 | i:u_dfu_app.rstn_sq[1:0] 4 | i:u_dfu_app.u_dpram.u_8bit\.byte_raddr_q 5 | i:u_dfu_app.u_flash_spi.byte_cnt_q[7:0] 6 | i:u_dfu_app.u_flash_spi.crc16_q[15:0] 7 | i:u_dfu_app.u_flash_spi.in_en_q 8 | i:u_dfu_app.u_flash_spi.last_byte_q[7:0] 9 | i:u_dfu_app.u_flash_spi.out_en_q 10 | i:u_dfu_app.u_flash_spi.page_addr_q[11:0] 11 | i:u_dfu_app.u_flash_spi.state_q[23:0] 12 | i:u_dfu_app.u_flash_spi.u_spi.bit_cnt_q[2:0] 13 | i:u_dfu_app.u_flash_spi.u_spi.en_q 14 | i:u_dfu_app.u_flash_spi.u_spi.rd_data_q[7:0] 15 | i:u_dfu_app.u_flash_spi.u_spi.sck_q 16 | i:u_dfu_app.u_flash_spi.u_spi.state_q[3:0] 17 | i:u_dfu_app.u_flash_spi.u_spi.wr_data_q[7:0] 18 | i:u_dfu_app.u_flash_spi.wait_cnt_q[15:0] 19 | i:u_dfu_app.u_ram.u_8bit\.byte_addr_q 20 | i:u_dfu_app.u_ram.u_multi_bank\.block_addr_q[0] 21 | i:u_dfu_app.u_ram_fifo_if.in_addr_q[9:0] 22 | i:u_dfu_app.u_ram_fifo_if.out_addr_q[9:0] 23 | i:u_dfu_app.u_ram_fifo_if.out_valid_q 24 | i:u_dfu_app.u_ram_if.mem_addr_q[10:0] 25 | i:u_dfu_app.u_ram_if.mem_valid_q 26 | i:u_dfu_app.u_ram_if.state_q[1:0] 27 | i:u_dfu_app.u_ram_if.status_q[1:0] 28 | i:u_dfu_app.u_ram_if.status_q[3] 29 | i:u_dfu_app.wait_cnt_q[3:0] 30 | i:u_usb_dfu.clk_cnt_q[1:0] 31 | i:u_usb_dfu.clk_gate_q 32 | i:u_usb_dfu.dfu_clear_status_q 33 | i:u_usb_dfu.fifo_rstn_q 34 | i:u_usb_dfu.rstn_sq[1:0] 35 | i:u_usb_dfu.u_async_app\.app_rstn_sq[1:0] 36 | i:u_usb_dfu.u_async_app\.dfu_busy_sq[1:0] 37 | i:u_usb_dfu.u_async_app\.dfu_clear_status_sq[1:0] 38 | i:u_usb_dfu.u_async_app\.dfu_in_en_sq[1:0] 39 | i:u_usb_dfu.u_async_app\.dfu_mode_sq[1:0] 40 | i:u_usb_dfu.u_async_app\.dfu_out_en_sq[1:0] 41 | i:u_usb_dfu.u_async_app\.dfu_status_sq[1:0] 42 | i:u_usb_dfu.u_ctrl_endp.addr_q[6:0] 43 | i:u_usb_dfu.u_ctrl_endp.addr_qq[6:0] 44 | i:u_usb_dfu.u_ctrl_endp.alternate_setting_q[1:0] 45 | i:u_usb_dfu.u_ctrl_endp.blocknum_q[15:0] 46 | i:u_usb_dfu.u_ctrl_endp.byte_cnt_q[8:0] 47 | i:u_usb_dfu.u_ctrl_endp.class_q 48 | i:u_usb_dfu.u_ctrl_endp.dev_state_q[1:0] 49 | i:u_usb_dfu.u_ctrl_endp.dev_state_qq[1:0] 50 | i:u_usb_dfu.u_ctrl_endp.dfu_done_q 51 | i:u_usb_dfu.u_ctrl_endp.dfu_state_q[10:0] 52 | i:u_usb_dfu.u_ctrl_endp.endp_q[3:0] 53 | i:u_usb_dfu.u_ctrl_endp.in_dir_q 54 | i:u_usb_dfu.u_ctrl_endp.in_endp_q 55 | i:u_usb_dfu.u_ctrl_endp.max_length_q[8:0] 56 | i:u_usb_dfu.u_ctrl_endp.rec_q[1:0] 57 | i:u_usb_dfu.u_ctrl_endp.req_q[24:0] 58 | i:u_usb_dfu.u_ctrl_endp.state_q[7:0] 59 | i:u_usb_dfu.u_ctrl_endp.string_index_q[3:0] 60 | i:u_usb_dfu.u_ctrl_endp.string_index_q[7:5] 61 | i:u_usb_dfu.u_ctrl_endp.vendor_q 62 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_async_app_rstn\.app_rstn_sq[1:0] 63 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_first_q[3:0] 64 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.in_first_qq[3:0] 65 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_data_q[7:0] 66 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_ready_q 67 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_ready_sq[1:0] 68 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_valid_q 69 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_valid_qq 70 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.app_in_valid_sq[1:0] 71 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_fifo_q[71:0] 72 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_last_q[3:0] 73 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_in_fifo.u_gt12mhz_async_data\.in_last_qq[3:0] 74 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_fifo_q[71:0] 75 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_last_q[3:0] 76 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_last_qq[3:0] 77 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.out_nak_q 78 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.app_out_consumed_q 79 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.app_out_consumed_sq[1:0] 80 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.app_out_data_q[7:0] 81 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.app_out_valid_q 82 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.out_first_q[3:0] 83 | i:u_usb_dfu.u_fifo_endps\[0\]\.u_fifo.u_out_fifo.u_gt12mhz_async_data\.out_valid_sq[1:0] 84 | i:u_usb_dfu.u_sie.addr_q[6:0] 85 | i:u_usb_dfu.u_sie.crc16_q[15:0] 86 | i:u_usb_dfu.u_sie.data_q[15:0] 87 | i:u_usb_dfu.u_sie.delay_cnt_q[2:0] 88 | i:u_usb_dfu.u_sie.endp_q[3:0] 89 | i:u_usb_dfu.u_sie.frame_q[10:0] 90 | i:u_usb_dfu.u_sie.in_byte_q[3:0] 91 | i:u_usb_dfu.u_sie.in_data_ack_q 92 | i:u_usb_dfu.u_sie.in_req_q 93 | i:u_usb_dfu.u_sie.in_toggle_q[15:0] 94 | i:u_usb_dfu.u_sie.in_zlp_q[15:0] 95 | i:u_usb_dfu.u_sie.out_eop_q 96 | i:u_usb_dfu.u_sie.out_err_q 97 | i:u_usb_dfu.u_sie.out_toggle_q[15:0] 98 | i:u_usb_dfu.u_sie.phy_state_q[11:0] 99 | i:u_usb_dfu.u_sie.pid_q[3:0] 100 | i:u_usb_dfu.u_sie.u_phy_rx.bus_reset_q 101 | i:u_usb_dfu.u_sie.u_phy_rx.cnt_q[17:0] 102 | i:u_usb_dfu.u_sie.u_phy_rx.dn_q[2:0] 103 | i:u_usb_dfu.u_sie.u_phy_rx.dp_pu_q 104 | i:u_usb_dfu.u_sie.u_phy_rx.dp_q[2:0] 105 | i:u_usb_dfu.u_sie.u_phy_rx.nrzi_q[3:0] 106 | i:u_usb_dfu.u_sie.u_phy_rx.rx_data_q[7:0] 107 | i:u_usb_dfu.u_sie.u_phy_rx.rx_en_q 108 | i:u_usb_dfu.u_sie.u_phy_rx.rx_eop_q 109 | i:u_usb_dfu.u_sie.u_phy_rx.rx_eop_qq 110 | i:u_usb_dfu.u_sie.u_phy_rx.rx_err_q 111 | i:u_usb_dfu.u_sie.u_phy_rx.rx_err_qq 112 | i:u_usb_dfu.u_sie.u_phy_rx.rx_state_q[4:0] 113 | i:u_usb_dfu.u_sie.u_phy_rx.rx_valid_q 114 | i:u_usb_dfu.u_sie.u_phy_rx.rx_valid_qq 115 | i:u_usb_dfu.u_sie.u_phy_rx.sample_cnt_q[1:0] 116 | i:u_usb_dfu.u_sie.u_phy_rx.se0_q 117 | i:u_usb_dfu.u_sie.u_phy_rx.shift_register_q[8:0] 118 | i:u_usb_dfu.u_sie.u_phy_rx.state_q[4:0] 119 | i:u_usb_dfu.u_sie.u_phy_rx.stuffing_cnt_q[2:0] 120 | i:u_usb_dfu.u_sie.u_phy_tx.bit_cnt_q[2:0] 121 | i:u_usb_dfu.u_sie.u_phy_tx.data_q[7:0] 122 | i:u_usb_dfu.u_sie.u_phy_tx.nrzi_q 123 | i:u_usb_dfu.u_sie.u_phy_tx.stuffing_cnt_q[2:0] 124 | i:u_usb_dfu.u_sie.u_phy_tx.tx_state_q[3:0] 125 | i:u_usb_n 126 | i:u_usb_p 127 | i:u_usb_pu 128 | -------------------------------------------------------------------------------- /usb_dfu/phy_tx.v: -------------------------------------------------------------------------------- 1 | // USB 2.0 full speed transmitter physical layer. 2 | // Written in verilog 2001 3 | 4 | // PHY_TX module shall manage physical layer signaling of USB 2.0 5 | // full speed transmitter (USB2.0 Chap. 7): 6 | // - Start-Of-Packet (SOP) and Sync Pattern generation. 7 | // - NRZI Data encoding. 8 | // - Bit Stuffing insertion. 9 | // - End-Of-Packet (EOP) generation. 10 | // PHY_TX module shall convert 8-bit parallel data from the SIE 11 | // module to bitstream for the USB bus physical transmitters. 12 | 13 | module phy_tx 14 | ( 15 | // ---- to USB bus physical transmitters ---------------------- 16 | output tx_en_o, 17 | output dp_tx_o, 18 | output dn_tx_o, 19 | // dp_tx_o and dn_tx_o shall have a negligible timing mismatch 20 | // (< clk_i period /2). 21 | 22 | // ---- to/from SIE module ------------------------------------ 23 | output tx_ready_o, 24 | // tx_ready_o shall be high only for one clk_gate_i multi-cycle period. 25 | // When both tx_valid_i and tx_ready_o are high, the 8-bit tx_data_i shall be consumed. 26 | // When clk_gate_i is high, tx_ready_o shall be updated. 27 | input clk_i, 28 | // clk_i clock shall have a frequency of 12MHz*BIT_SAMPLES. 29 | input rstn_i, 30 | // While rstn_i is low (active low), the module shall be reset. 31 | input clk_gate_i, 32 | // clk_gate_i shall be high for only one clk_i period within every BIT_SAMPLES clk_i periods. 33 | // When clk_gate_i is high, the registers that are gated by it shall be updated. 34 | input tx_valid_i, 35 | // When tx_valid_i changes from low to high, PHY_TX shall start a 36 | // new packet transmission as soon as possible (USB2.0 7.1.18.1). 37 | // When the last packet byte is consumed, tx_valid_i shall return low. 38 | // When clk_gate_i is high, tx_valid_i shall be updated. 39 | input [7:0] tx_data_i 40 | // While tx_valid_i is high, the tx_data_i shall be valid and both 41 | // tx_valid_i and tx_data_i shall not change until consumed. 42 | ); 43 | 44 | localparam [1:0] ST_IDLE = 2'd0, 45 | ST_SYNC = 2'd1, 46 | ST_DATA = 2'd2, 47 | ST_EOP = 2'd3; 48 | 49 | reg [1:0] tx_state_q, tx_state_d; 50 | reg [2:0] bit_cnt_q, bit_cnt_d; 51 | reg [7:0] data_q, data_d; 52 | reg [2:0] stuffing_cnt_q, stuffing_cnt_d; 53 | reg nrzi_q, nrzi_d; 54 | reg tx_ready; 55 | 56 | assign tx_en_o = (tx_state_q == ST_IDLE) ? 1'b0 : 1'b1; 57 | assign dp_tx_o = (tx_state_q == ST_EOP && data_q[0] == 1'b0) ? 1'b0 : nrzi_q; 58 | assign dn_tx_o = (tx_state_q == ST_EOP && data_q[0] == 1'b0) ? 1'b0 : ~nrzi_q; 59 | assign tx_ready_o = tx_ready; 60 | 61 | always @(posedge clk_i or negedge rstn_i) begin 62 | if (~rstn_i) begin 63 | tx_state_q <= ST_IDLE; 64 | bit_cnt_q <= 3'd7; 65 | data_q <= 8'b10000000; 66 | stuffing_cnt_q <= 3'd0; 67 | nrzi_q <= 1'b1; 68 | end else begin 69 | if (clk_gate_i) begin 70 | tx_state_q <= tx_state_d; 71 | bit_cnt_q <= bit_cnt_d; 72 | data_q <= data_d; 73 | stuffing_cnt_q <= stuffing_cnt_d; 74 | nrzi_q <= nrzi_d; 75 | end 76 | end 77 | end 78 | 79 | always @(/*AS*/bit_cnt_q or data_q or nrzi_q or stuffing_cnt_q 80 | or tx_data_i or tx_state_q or tx_valid_i) begin 81 | tx_state_d = tx_state_q; 82 | bit_cnt_d = bit_cnt_q; 83 | data_d = data_q; 84 | stuffing_cnt_d = stuffing_cnt_q; 85 | nrzi_d = nrzi_q; 86 | tx_ready = 1'b0; 87 | 88 | if (stuffing_cnt_q == 3'd6) begin 89 | stuffing_cnt_d = 3'd0; 90 | nrzi_d = ~nrzi_q; 91 | end else begin 92 | bit_cnt_d = bit_cnt_q - 1; 93 | data_d = (data_q >> 1); 94 | if (data_q[0] == 1'b1) begin 95 | stuffing_cnt_d = stuffing_cnt_q + 1; 96 | end else begin 97 | stuffing_cnt_d = 3'd0; 98 | nrzi_d = ~nrzi_q; 99 | end 100 | case (tx_state_q) 101 | ST_IDLE : begin 102 | if (tx_valid_i == 1'b1) begin 103 | tx_state_d = ST_SYNC; 104 | end else begin 105 | bit_cnt_d = 3'd7; 106 | data_d = 8'b10000000; 107 | nrzi_d = 1'b1; 108 | end 109 | stuffing_cnt_d = 3'd0; 110 | end 111 | ST_SYNC : begin 112 | if (bit_cnt_q == 3'd0) begin 113 | if (tx_valid_i == 1'b1) begin 114 | tx_state_d = ST_DATA; 115 | bit_cnt_d = 3'd7; 116 | data_d = tx_data_i; 117 | tx_ready = 1'b1; 118 | end else begin 119 | tx_state_d = ST_IDLE; 120 | bit_cnt_d = 3'd7; 121 | data_d = 8'b10000000; 122 | stuffing_cnt_d = 3'd0; 123 | nrzi_d = 1'b1; 124 | end 125 | end 126 | end 127 | ST_DATA : begin 128 | if (bit_cnt_q == 3'd0) begin 129 | if (tx_valid_i == 1'b1) begin 130 | bit_cnt_d = 3'd7; 131 | data_d = tx_data_i; 132 | tx_ready = 1'b1; 133 | end else begin 134 | tx_state_d = ST_EOP; 135 | bit_cnt_d = 3'd3; 136 | data_d = 8'b11111001; 137 | end 138 | end 139 | end 140 | ST_EOP : begin 141 | if (bit_cnt_q == 3'd0) begin 142 | tx_state_d = ST_IDLE; 143 | bit_cnt_d = 3'd7; 144 | data_d = 8'b10000000; 145 | end 146 | stuffing_cnt_d = 3'd0; 147 | nrzi_d = 1'b1; 148 | end 149 | default : begin 150 | tx_state_d = ST_IDLE; 151 | bit_cnt_d = 3'd7; 152 | data_d = 8'b10000000; 153 | stuffing_cnt_d = 3'd0; 154 | nrzi_d = 1'b1; 155 | end 156 | endcase 157 | end 158 | end 159 | endmodule 160 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/python/bootloader/tinyfpga.py: -------------------------------------------------------------------------------- 1 | import serial.tools.list_ports 2 | import binascii 3 | import time 4 | import dump 5 | import builtins 6 | 7 | class bcolors: 8 | HEADER = '\033[95m' 9 | OKBLUE = '\033[94m' 10 | OKCYAN = '\033[96m' 11 | OKGREEN = '\033[92m' 12 | WARNING = '\033[93m' 13 | FAIL = '\033[91m' 14 | ENDC = '\033[0m' 15 | BOLD = '\033[1m' 16 | UNDERLINE = '\033[4m' 17 | 18 | def port(): 19 | VID = 0x1D50 20 | PID = 0x6130 21 | device_list = serial.tools.list_ports.comports() 22 | portValue = None 23 | for device in device_list: 24 | if (device.vid != None or device.pid != None): 25 | if (device.vid == VID and device.pid == PID): 26 | portValue = device.device 27 | break 28 | return portValue 29 | 30 | 31 | def boot(): 32 | portValue = port() 33 | if (portValue != None): 34 | print(f"TinyFPGA is on {portValue}") 35 | ser = serial.Serial(portValue) 36 | ser.timeout = 1 #non-block read 37 | ser.write(b'\x00') 38 | ser.close() 39 | else: 40 | print(f"{bcolors.FAIL}TinyFPGA not found!{bcolors.ENDC}") 41 | 42 | def open(): 43 | portValue = port() 44 | if (portValue != None): 45 | ser = serial.Serial() 46 | ser.port = portValue 47 | ser.timeout = 1 #non-block read 48 | ser.writeTimeout = 2 #timeout for write 49 | ser.open() 50 | return ser 51 | else: 52 | return None 53 | 54 | def cmd(opcode, wr_length, rd_length, ser): 55 | wr_total_length = wr_length + 1; # add opcode 56 | ser.write(b'\x01' + wr_total_length.to_bytes(2, 'little') + rd_length.to_bytes(2, 'little') + opcode) 57 | 58 | def sleep(ser): 59 | cmd(b'\xB9', 0, 0, ser) 60 | 61 | def wake(ser): 62 | cmd(b'\xAB', 0, 0, ser) 63 | 64 | def write_enable(ser): 65 | cmd(b'\x06', 0, 0, ser) 66 | 67 | def write_disable(ser): 68 | cmd(b'\x04', 0, 0, ser) 69 | 70 | def wait_while_busy(ser): 71 | while int.from_bytes(read_status(ser), 'little') & 1: 72 | pass 73 | 74 | def erase_4k(addr, ser): 75 | write_enable(ser) 76 | cmd(b'\x20', 3, 0, ser) 77 | ser.write(addr.to_bytes(3, 'big')) 78 | wait_while_busy(ser) 79 | 80 | def read_id(ser, p=0): 81 | cmd(b'\x9F', 0, 3, ser) 82 | data = ser.read(3) 83 | if (len(data) < 3): 84 | print(f"{bcolors.FAIL}{3-len(data)} ID bytes are missing{bcolors.ENDC}") 85 | elif (p == 0): 86 | return data 87 | else: 88 | print(f"ID = {hex(int.from_bytes(data, 'little'))}") 89 | 90 | def read_status(ser, p=0): 91 | cmd(b'\x05', 0, 1, ser) 92 | data = ser.read(1) 93 | if (len(data) < 1): 94 | print(f"{bcolors.FAIL}{1-len(data)} STATUS bytes are missing{bcolors.ENDC}") 95 | elif (p == 0): 96 | return data 97 | else: 98 | print(f"STATUS = {hex(int.from_bytes(data, 'little'))}") 99 | 100 | def read_security_register(addr, ser, p=0): 101 | if (addr < 1 or addr > 3): 102 | print(f"{bcolors.FAIL}Address limited to 1-3 {bcolors.ENDC}") 103 | return 104 | length = 256 105 | i = 0 106 | data = bytearray(length) 107 | start = time.time() 108 | cmd(b'\x48', 4, length, ser) 109 | ser.write(addr.to_bytes(2, 'big') + b'\x00\x00') 110 | data = ser.read(length) 111 | end = time.time() 112 | if (p == 1): 113 | print(binascii.hexlify(data)) 114 | elif (p == 2): 115 | print(dump.data_dump(data)) 116 | if (len(data) < length): 117 | print(f"{bcolors.FAIL}{length-len(data)} bytes are missing{bcolors.ENDC}") 118 | elif (p == 0): 119 | return data 120 | elif (end != start): 121 | print(f"{bcolors.OKGREEN}OK! {length} bytes transferred in {round(end-start, 3)} sec ({round(length/1000/(end-start), 1)} kB/s){bcolors.ENDC}") 122 | else: 123 | print(f"{bcolors.OKGREEN}OK! {length} bytes transferred in {round(end-start, 3)} sec{bcolors.ENDC}") 124 | 125 | def read_data(addr, length, ser, p=0): 126 | if (length > 2**24): 127 | length = 2**24 128 | print(f"{bcolors.WARNING}Data length limited to {length} bytes{bcolors.ENDC}") 129 | i = 0 130 | data = bytearray(length) 131 | start = time.time() 132 | while i < length: 133 | chunk_length = min(4096, length-i) 134 | chunk_addr = addr + i 135 | cmd(b'\x0B', 4, chunk_length, ser) 136 | ser.write(chunk_addr.to_bytes(3, 'big') + b'\x00') 137 | data[i:i+chunk_length] = ser.read(chunk_length) 138 | i = i + chunk_length 139 | end = time.time() 140 | if (p == 1): 141 | print(binascii.hexlify(data)) 142 | elif (p == 2): 143 | print(dump.data_dump(data)) 144 | if (len(data) < length): 145 | print(f"{bcolors.FAIL}{length-len(data)} bytes are missing{bcolors.ENDC}") 146 | elif (p == 0): 147 | return data 148 | elif (end != start): 149 | print(f"{bcolors.OKGREEN}OK! {length} bytes transferred in {round(end-start, 3)} sec ({round(length/1000/(end-start), 1)} kB/s){bcolors.ENDC}") 150 | else: 151 | print(f"{bcolors.OKGREEN}OK! {length} bytes transferred in {round(end-start, 3)} sec{bcolors.ENDC}") 152 | 153 | def write_data(addr, data, ser): 154 | length = len(data) 155 | ustart = 0x28000 156 | uend = 0x90000 157 | if (addr < ustart or addr+length >= uend): 158 | print(f"{bcolors.FAIL}Data programming limited to {hex(ustart)}-{hex(uend)} {bcolors.ENDC}") 159 | return 160 | i = 0 161 | erased_addr = -1 162 | start = time.time() 163 | while i < length: 164 | if (int((addr+i)/(4*1024))*4*1024 != erased_addr): 165 | erase_4k(int((addr+i)/(4*1024))*4*1024, ser) 166 | erased_addr = int((addr+i)/(4*1024))*4*1024 167 | write_addr = addr + i 168 | write_length = min(256-write_addr%256, length-i) 169 | write_enable(ser) 170 | cmd(b'\x02', 3+write_length, 0, ser) 171 | ser.write(write_addr.to_bytes(3, 'big')) 172 | ser.write(data[i:i+write_length]) 173 | wait_while_busy(ser) 174 | i = i + write_length 175 | end = time.time() 176 | time.sleep(0.5) 177 | if (end != start): 178 | print(f"{bcolors.OKGREEN}OK! {length} bytes transferred in {round(end-start, 3)} sec ({round(length/1000/(end-start), 1)} kB/s){bcolors.ENDC}") 179 | else: 180 | print(f"{bcolors.OKGREEN}OK! {length} bytes transferred in {round(end-start, 3)} sec{bcolors.ENDC}") 181 | 182 | def slurp(filename): 183 | if filename.endswith('.bit') or filename.endswith('.bin'): 184 | with builtins.open(filename, "rb") as f: 185 | return f.read() 186 | elif filename.endswith('.hex'): 187 | with builtins.open(filename, "rb") as f: 188 | return bytes("".join(chr(int(i, 16)) for i in f.read().split()), encoding='utf-8') 189 | else: 190 | print(f"{bcolors.FAIL}Unknown bitstream extension {bcolors.ENDC}") 191 | return 192 | -------------------------------------------------------------------------------- /usb_dfu/fifo.v: -------------------------------------------------------------------------------- 1 | // USB 2.0 full speed IN/OUT BULK Endpoints. 2 | // Written in verilog 2001 3 | 4 | // FIFO module shall implement IN/OUT Bulk Endpoints and 5 | // FIFO interface of TOP module. 6 | // While IN FIFO is not empty, when required by in_req_i, FIFO 7 | // shall source IN data. 8 | // While OUT FIFO is not full, when OUT data is available, FIFO 9 | // shall sink OUT data. 10 | 11 | module fifo 12 | #(parameter IN_MAXPACKETSIZE = 'd8, 13 | parameter OUT_MAXPACKETSIZE = 'd8, 14 | parameter USE_APP_CLK = 0, 15 | parameter APP_CLK_FREQ = 12) // app_clk frequency in MHz 16 | ( 17 | // ---- to/from Application ------------------------------------ 18 | input app_clk_i, 19 | input [7:0] app_in_data_i, 20 | input app_in_valid_i, 21 | // While app_in_valid_i is high, app_in_data_i shall be valid. 22 | output app_in_ready_o, 23 | // When both app_in_ready_o and app_in_valid_i are high, app_in_data_i shall 24 | // be consumed. 25 | output [7:0] app_out_data_o, 26 | output app_out_valid_o, 27 | // While app_out_valid_o is high, the app_out_data_o shall be valid and both 28 | // app_out_valid_o and app_out_data_o shall not change until consumed. 29 | input app_out_ready_i, 30 | // When both app_out_valid_o and app_out_ready_i are high, the app_out_data_o shall 31 | // be consumed. 32 | 33 | // ---- from TOP module --------------------------------------- 34 | input clk_i, 35 | // clk_i clock shall have a frequency of 12MHz*BIT_SAMPLES 36 | input rstn_i, 37 | // While rstn_i is low (active low), the module shall be reset 38 | input clk_gate_i, 39 | // clk_gate_i shall be high for only one clk_i period within every BIT_SAMPLES clk_i periods. 40 | // When clk_gate_i is high, the registers that are gated by it shall be updated. 41 | input bus_reset_i, 42 | // While bus_reset_i is high, the module shall be reset 43 | // When clk_gate_i is high, bus_reset_i shall be updated. 44 | output in_empty_o, 45 | output in_full_o, 46 | output out_empty_o, 47 | 48 | // ---- to/from SIE module ------------------------------------ 49 | output [7:0] in_data_o, 50 | // While in_valid_o is high, in_data_o shall be valid. 51 | output in_valid_o, 52 | // While IN FIFO is not empty, in_valid_o shall be high. 53 | // When clk_gate_i is high, in_valid_o shall be updated. 54 | input in_req_i, 55 | // When both in_req_i and in_ready_i are high, a new IN packet shall be requested. 56 | // When clk_gate_i is high, in_req_i shall be updated. 57 | input in_ready_i, 58 | // When both in_ready_i and in_valid_o are high, in_data_o shall be consumed. 59 | // in_ready_i shall be high only for one clk_gate_i multi-cycle period. 60 | // When clk_gate_i is high, in_ready_i shall be updated. 61 | input in_data_ack_i, 62 | // When both in_data_ack_i and in_ready_i are high, an ACK packet shall be received. 63 | // When clk_gate_i is high, in_data_ack_i shall be updated. 64 | output out_nak_o, 65 | // While out_valid_i is high, when OUT FIFO is full, out_nak_o shall be 66 | // latched high. 67 | // When either out_valid_i or out_err_i is low and out_ready_i is high, 68 | // out_nak_o shall be low. 69 | // When clk_gate_i is high, out_nak_o shall be updated. 70 | input [7:0] out_data_i, 71 | input out_valid_i, 72 | // While out_valid_i is high, the out_data_i shall be valid and both 73 | // out_valid_i and out_data_i shall not change until consumed. 74 | // When clk_gate_i is high, out_valid_i shall be updated. 75 | input out_err_i, 76 | // When both out_err_i and out_ready_i are high, SIE shall abort the 77 | // current packet reception and OUT Bulk Endpoint shall manage the error 78 | // condition. 79 | // When clk_gate_i is high, out_err_i shall be updated. 80 | input out_ready_i 81 | // When both out_valid_i and out_ready_i are high, the out_data_i shall 82 | // be consumed. 83 | // When out_valid_i and out_err_i are low and out_ready_i is high, the 84 | // on-going OUT packet shall end (EOP). 85 | // out_ready_i shall be high only for one clk_gate_i multi-cycle period. 86 | // When clk_gate_i is high, out_ready_i shall be updated. 87 | ); 88 | 89 | wire rstn; 90 | wire app_rstn; 91 | 92 | assign rstn = rstn_i & ~bus_reset_i; 93 | 94 | generate 95 | if (USE_APP_CLK == 0) begin : u_sync_app_rstn 96 | assign app_rstn = 1'b0; 97 | end else begin : u_async_app_rstn 98 | reg [1:0] app_rstn_sq; 99 | 100 | assign app_rstn = app_rstn_sq[0]; 101 | 102 | always @(posedge app_clk_i or negedge rstn) begin 103 | if (~rstn) begin 104 | app_rstn_sq <= 2'd0; 105 | end else begin 106 | app_rstn_sq <= {1'b1, app_rstn_sq[1]}; 107 | end 108 | end 109 | end 110 | endgenerate 111 | 112 | in_fifo #(.IN_MAXPACKETSIZE(IN_MAXPACKETSIZE), 113 | .USE_APP_CLK(USE_APP_CLK), 114 | .APP_CLK_FREQ(APP_CLK_FREQ)) 115 | u_in_fifo (.in_empty_o(in_empty_o), 116 | .in_full_o(in_full_o), 117 | .in_data_o(in_data_o), 118 | .in_valid_o(in_valid_o), 119 | .app_in_ready_o(app_in_ready_o), 120 | .clk_i(clk_i), 121 | .app_clk_i(app_clk_i), 122 | .rstn_i(rstn), 123 | .app_rstn_i(app_rstn), 124 | .clk_gate_i(clk_gate_i), 125 | .in_req_i(in_req_i), 126 | .in_data_ack_i(in_data_ack_i), 127 | .app_in_data_i(app_in_data_i), 128 | .app_in_valid_i(app_in_valid_i), 129 | .in_ready_i(in_ready_i)); 130 | 131 | out_fifo #(.OUT_MAXPACKETSIZE(OUT_MAXPACKETSIZE), 132 | .USE_APP_CLK(USE_APP_CLK), 133 | .APP_CLK_FREQ(APP_CLK_FREQ)) 134 | u_out_fifo (.out_empty_o(out_empty_o), 135 | .out_full_o(), 136 | .out_nak_o(out_nak_o), 137 | .app_out_valid_o(app_out_valid_o), 138 | .app_out_data_o(app_out_data_o), 139 | .clk_i(clk_i), 140 | .app_clk_i(app_clk_i), 141 | .rstn_i(rstn), 142 | .app_rstn_i(app_rstn), 143 | .clk_gate_i(clk_gate_i), 144 | .out_data_i(out_data_i), 145 | .out_valid_i(out_valid_i), 146 | .out_err_i(out_err_i), 147 | .out_ready_i(out_ready_i), 148 | .app_out_ready_i(app_out_ready_i)); 149 | 150 | endmodule 151 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/output/bootloader/bootloader.rpt: -------------------------------------------------------------------------------- 1 | 2 | icetime topological timing analysis report 3 | ========================================== 4 | 5 | Info: max_span_hack is enabled: estimate is conservative. 6 | 7 | Report for critical path: 8 | ------------------------- 9 | 10 | lc40_7_8_7 (LogicCell40) [clk] -> lcout: 0.896 ns 11 | 0.896 ns net_25438 (u_usb_dfu.dfu_busy_s_SB_LUT4_I3_O_SB_LUT4_O_I2[1]) 12 | odrv_7_8_25438_25571 (Odrv4) I -> O: 0.548 ns 13 | t8836 (Span4Mux_v4) I -> O: 0.548 ns 14 | t8835 (Span4Mux_v4) I -> O: 0.548 ns 15 | t8834 (Span4Mux_v4) I -> O: 0.548 ns 16 | t8833 (LocalMux) I -> O: 0.486 ns 17 | inmux_10_19_42466_42502 (InMux) I -> O: 0.382 ns 18 | lc40_10_19_1 (LogicCell40) in3 -> lcout: 0.465 ns 19 | 4.421 ns net_38343 (u_usb_dfu.u_fifo_endps[0].u_fifo.u_in_fifo.genblk1.u_gt12mhz_async_data.app_in_valid_qq_SB_LUT4_I0_O[2]) 20 | t10296 (LocalMux) I -> O: 0.486 ns 21 | inmux_9_18_38285_38293 (InMux) I -> O: 0.382 ns 22 | lc40_9_18_0 (LogicCell40) in0 -> lcout: 0.662 ns 23 | 5.951 ns net_34427 (u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I2_I3[0]) 24 | odrv_9_18_34427_34278 (Odrv4) I -> O: 0.548 ns 25 | t9810 (Span4Mux_h4) I -> O: 0.465 ns 26 | t9812 (Span4Mux_v4) I -> O: 0.548 ns 27 | t9811 (LocalMux) I -> O: 0.486 ns 28 | inmux_5_13_22013_22058 (InMux) I -> O: 0.382 ns 29 | lc40_5_13_2 (LogicCell40) in3 -> lcout: 0.465 ns 30 | 8.845 ns net_17894 (u_usb_dfu.u_sie.data_d_SB_LUT4_O_15_I0_SB_LUT4_O_1_I0_SB_LUT4_O_I0_SB_LUT4_O_1_I2_SB_LUT4_O_I2_SB_LUT4_I2_O_SB_LUT4_O_1_I3_SB_LUT4_I3_O_SB_LUT4_I0_O[3]) 31 | t6661 (LocalMux) I -> O: 0.486 ns 32 | inmux_5_14_22143_22184 (InMux) I -> O: 0.382 ns 33 | lc40_5_14_3 (LogicCell40) in0 -> lcout: 0.662 ns 34 | 10.375 ns net_18018 (u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I2_O_SB_LUT4_I2_O_SB_LUT4_O_I1[2]) 35 | t6690 (LocalMux) I -> O: 0.486 ns 36 | inmux_5_14_22160_22197 (InMux) I -> O: 0.382 ns 37 | lc40_5_14_5 (LogicCell40) in1 -> lcout: 0.589 ns 38 | 11.832 ns net_18020 (u_usb_dfu.u_sie.data_d_SB_LUT4_O_11_I0_SB_LUT4_O_1_I2[0]) 39 | odrv_5_14_18020_18168 (Odrv4) I -> O: 0.548 ns 40 | t6769 (Span4Mux_v4) I -> O: 0.548 ns 41 | t6768 (LocalMux) I -> O: 0.486 ns 42 | inmux_5_21_23005_23051 (InMux) I -> O: 0.382 ns 43 | lc40_5_21_4 (LogicCell40) in0 -> lcout: 0.662 ns 44 | 14.458 ns net_18880 (u_usb_dfu.u_sie.in_req_q_SB_LUT4_I3_2_O[0]) 45 | t6994 (LocalMux) I -> O: 0.486 ns 46 | inmux_4_22_19044_19111 (InMux) I -> O: 0.382 ns 47 | t668 (CascadeMux) I -> O: 0.000 ns 48 | lc40_4_22_6 (LogicCell40) in2 -> lcout: 0.558 ns 49 | 15.884 ns net_14928 (u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I2_O[1]) 50 | odrv_4_22_14928_18395 (Odrv12) I -> O: 0.796 ns 51 | t5269 (Span12Mux_v12) I -> O: 0.796 ns 52 | t5268 (LocalMux) I -> O: 0.486 ns 53 | inmux_4_9_17464_17489 (InMux) I -> O: 0.382 ns 54 | lc40_4_9_2 (LogicCell40) in3 -> lcout: 0.465 ns 55 | 18.810 ns net_13325 (u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I2_O_SB_LUT4_I2_1_O[0]) 56 | odrv_4_9_13325_13106 (Odrv4) I -> O: 0.548 ns 57 | t4885 (Span4Mux_h4) I -> O: 0.465 ns 58 | t4884 (LocalMux) I -> O: 0.486 ns 59 | inmux_4_5_16961_17009 (InMux) I -> O: 0.382 ns 60 | lc40_4_5_4 (LogicCell40) in3 -> lcout: 0.465 ns 61 | 21.156 ns net_12835 (u_usb_dfu.u_ctrl_endp.req_q_SB_DFFR_Q_1_D_SB_LUT4_O_I1_SB_LUT4_I0_O_SB_LUT4_O_2_I0[2]) 62 | odrv_4_5_12835_12982 (Odrv4) I -> O: 0.548 ns 63 | t4761 (Span4Mux_v4) I -> O: 0.548 ns 64 | t4760 (LocalMux) I -> O: 0.486 ns 65 | inmux_3_12_13749_13778 (InMux) I -> O: 0.382 ns 66 | lc40_3_12_2 (LogicCell40) in0 -> lcout: 0.662 ns 67 | 23.782 ns net_9617 (u_usb_dfu.u_ctrl_endp.endp_q_SB_DFFER_Q_E_SB_LUT4_O_I3[0]) 68 | t3942 (LocalMux) I -> O: 0.486 ns 69 | inmux_4_13_17951_17978 (InMux) I -> O: 0.382 ns 70 | lc40_4_13_2 (LogicCell40) in0 -> lcout: 0.662 ns 71 | 25.312 ns net_13817 (u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E_SB_LUT4_O_I3_SB_LUT4_O_I3[2]) 72 | t5007 (LocalMux) I -> O: 0.486 ns 73 | inmux_3_14_13989_14025 (InMux) I -> O: 0.382 ns 74 | lc40_3_14_2 (LogicCell40) in1 -> lcout: 0.589 ns 75 | 26.769 ns net_9863 (u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E_SB_LUT4_O_I3[3]) 76 | t3973 (LocalMux) I -> O: 0.486 ns 77 | inmux_3_14_13997_14038 (InMux) I -> O: 0.382 ns 78 | t439 (CascadeMux) I -> O: 0.000 ns 79 | lc40_3_14_4 (LogicCell40) in2 -> lcout: 0.558 ns 80 | 28.196 ns net_9865 (u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E) 81 | odrv_3_14_9865_9648 (Odrv4) I -> O: 0.548 ns 82 | t3979 (Span4Mux_h4) I -> O: 0.465 ns 83 | t3978 (LocalMux) I -> O: 0.486 ns 84 | inmux_3_14_13981_14058 (CEMux) I -> O: 0.889 ns 85 | 30.584 ns net_14058 (u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E) 86 | lc40_3_14_5 (LogicCell40) ce [setup]: 0.000 ns 87 | 30.584 ns net_9866 (u_usb_dfu.u_ctrl_endp.dev_state_q[0]) 88 | 89 | Resolvable net names on path: 90 | 0.896 ns .. 3.956 ns u_usb_dfu.dfu_busy_s_SB_LUT4_I3_O_SB_LUT4_O_I2[1] 91 | 4.421 ns .. 5.289 ns u_usb_dfu.u_fifo_endps[0].u_fifo.u_in_fifo.genblk1.u_gt12mhz_async_data.app_in_valid_qq_SB_LUT4_I0_O[2] 92 | 5.951 ns .. 8.380 ns u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I2_I3[0] 93 | 8.845 ns .. 9.713 ns u_usb_dfu.u_sie.data_d_SB_LUT4_O_15_I0_SB_LUT4_O_1_I0_SB_LUT4_O_I0_SB_LUT4_O_1_I2_SB_LUT4_O_I2_SB_LUT4_I2_O_SB_LUT4_O_1_I3_SB_LUT4_I3_O_SB_LUT4_I0_O[3] 94 | 10.375 ns .. 11.243 ns u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I2_O_SB_LUT4_I2_O_SB_LUT4_O_I1[2] 95 | 11.832 ns .. 13.796 ns u_usb_dfu.u_sie.data_d_SB_LUT4_O_11_I0_SB_LUT4_O_1_I2[0] 96 | 14.458 ns .. 15.326 ns u_usb_dfu.u_sie.in_req_q_SB_LUT4_I3_2_O[0] 97 | 15.884 ns .. 18.345 ns u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I2_O[1] 98 | 18.810 ns .. 20.691 ns u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I2_O_SB_LUT4_I2_1_O[0] 99 | 21.156 ns .. 23.120 ns u_usb_dfu.u_ctrl_endp.req_q_SB_DFFR_Q_1_D_SB_LUT4_O_I1_SB_LUT4_I0_O_SB_LUT4_O_2_I0[2] 100 | 23.782 ns .. 24.650 ns u_usb_dfu.u_ctrl_endp.endp_q_SB_DFFER_Q_E_SB_LUT4_O_I3[0] 101 | 25.312 ns .. 26.180 ns u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E_SB_LUT4_O_I3_SB_LUT4_O_I3[2] 102 | 26.769 ns .. 27.638 ns u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E_SB_LUT4_O_I3[3] 103 | 28.196 ns .. 30.584 ns u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E 104 | lcout -> u_usb_dfu.u_ctrl_endp.dev_state_q[0] 105 | 106 | Total number of logic levels: 14 107 | Total path delay: 30.58 ns (32.70 MHz) 108 | 109 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/OSS_CAD_Suite/output/loopback/loopback.rpt: -------------------------------------------------------------------------------- 1 | 2 | icetime topological timing analysis report 3 | ========================================== 4 | 5 | Info: max_span_hack is enabled: estimate is conservative. 6 | 7 | Report for critical path: 8 | ------------------------- 9 | 10 | lc40_11_12_7 (LogicCell40) [clk] -> lcout: 0.896 ns 11 | 0.896 ns net_41565 (u_usb_dfu.dfu_status_s) 12 | odrv_11_12_41565_45539 (Odrv4) I -> O: 0.548 ns 13 | t9485 (Span4Mux_v4) I -> O: 0.548 ns 14 | t9488 (Span4Mux_v4) I -> O: 0.548 ns 15 | t9487 (Span4Mux_h4) I -> O: 0.465 ns 16 | t9486 (LocalMux) I -> O: 0.486 ns 17 | inmux_13_21_54944_55012 (InMux) I -> O: 0.382 ns 18 | lc40_13_21_7 (LogicCell40) in0 -> lcout: 0.662 ns 19 | 4.535 ns net_50826 (u_usb_dfu.u_fifo_endps[0].u_fifo.u_in_fifo.genblk1.u_gt12mhz_async_data.app_in_valid_qq_SB_LUT4_I0_O[3]) 20 | t10605 (LocalMux) I -> O: 0.486 ns 21 | inmux_13_21_54952_55008 (InMux) I -> O: 0.382 ns 22 | t1829 (CascadeMux) I -> O: 0.000 ns 23 | lc40_13_21_6 (LogicCell40) in2 -> lcout: 0.558 ns 24 | 5.961 ns net_50825 (u_usb_dfu.dfu_done) 25 | odrv_13_21_50825_50848 (Odrv4) I -> O: 0.548 ns 26 | t10631 (Span4Mux_v4) I -> O: 0.548 ns 27 | t10630 (Span4Mux_v4) I -> O: 0.548 ns 28 | t10629 (Span4Mux_h4) I -> O: 0.465 ns 29 | t10633 (Span4Mux_h4) I -> O: 0.465 ns 30 | t10632 (LocalMux) I -> O: 0.486 ns 31 | inmux_6_11_25842_25880 (InMux) I -> O: 0.382 ns 32 | lc40_6_11_1 (LogicCell40) in0 -> lcout: 0.662 ns 33 | 10.065 ns net_21724 (u_usb_dfu.u_ctrl_endp.dfu_done_i_SB_LUT4_I1_1_O[2]) 34 | t5808 (LocalMux) I -> O: 0.486 ns 35 | inmux_6_11_25858_25906 (InMux) I -> O: 0.382 ns 36 | t799 (CascadeMux) I -> O: 0.000 ns 37 | lc40_6_11_5 (LogicCell40) in2 -> lcout: 0.558 ns 38 | 11.491 ns net_21728 (u_usb_dfu.dfu_upload_SB_LUT4_I3_I2[0]) 39 | odrv_6_11_21728_25937 (Odrv4) I -> O: 0.548 ns 40 | t5827 (Span4Mux_v4) I -> O: 0.548 ns 41 | t5826 (Span4Mux_v4) I -> O: 0.548 ns 42 | t5825 (LocalMux) I -> O: 0.486 ns 43 | inmux_6_19_26826_26871 (InMux) I -> O: 0.382 ns 44 | lc40_6_19_2 (LogicCell40) in1 -> lcout: 0.589 ns 45 | 14.592 ns net_22709 (u_usb_dfu.dfu_upload_SB_LUT4_I3_O[3]) 46 | t6114 (LocalMux) I -> O: 0.486 ns 47 | inmux_6_20_26950_27007 (InMux) I -> O: 0.382 ns 48 | t853 (CascadeMux) I -> O: 0.000 ns 49 | lc40_6_20_4 (LogicCell40) in2 -> lcout: 0.558 ns 50 | 16.019 ns net_22834 (u_usb_dfu.u_sie.in_req_q_SB_LUT4_I3_2_O[1]) 51 | t6148 (LocalMux) I -> O: 0.486 ns 52 | inmux_6_20_26968_26995 (InMux) I -> O: 0.382 ns 53 | t851 (CascadeMux) I -> O: 0.000 ns 54 | lc40_6_20_2 (LogicCell40) in2 -> lcout: 0.558 ns 55 | 17.445 ns net_22832 (u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I1_O[1]) 56 | odrv_6_20_22832_22976 (Odrv4) I -> O: 0.548 ns 57 | t6164 (Span4Mux_v4) I -> O: 0.548 ns 58 | t6163 (Span4Mux_v4) I -> O: 0.548 ns 59 | t6162 (Span4Mux_v4) I -> O: 0.548 ns 60 | t6161 (Span4Mux_v4) I -> O: 0.548 ns 61 | t6160 (LocalMux) I -> O: 0.486 ns 62 | inmux_4_5_16970_17019 (InMux) I -> O: 0.382 ns 63 | lc40_4_5_6 (LogicCell40) in1 -> lcout: 0.589 ns 64 | 21.642 ns net_12837 (u_usb_dfu.u_ctrl_endp.dfu_state_q_SB_DFFER_Q_D_SB_LUT4_O_I1_SB_LUT4_O_I1_SB_LUT4_I1_O_SB_LUT4_O_1_I2_SB_LUT4_I2_O_SB_LUT4_I3_O_SB_LUT4_I0_O[0]) 65 | t4259 (LocalMux) I -> O: 0.486 ns 66 | inmux_4_6_17086_17113 (InMux) I -> O: 0.382 ns 67 | t465 (CascadeMux) I -> O: 0.000 ns 68 | lc40_4_6_1 (LogicCell40) in2 -> lcout: 0.558 ns 69 | 23.069 ns net_12955 (u_usb_dfu.u_ctrl_endp.dfu_state_q_SB_DFFER_Q_D_SB_LUT4_O_I1[1]) 70 | t4265 (LocalMux) I -> O: 0.486 ns 71 | inmux_3_6_13020_13052 (InMux) I -> O: 0.382 ns 72 | lc40_3_6_4 (LogicCell40) in0 -> lcout: 0.662 ns 73 | 24.599 ns net_8881 (u_usb_dfu.u_ctrl_endp.max_length_d_SB_LUT4_O_8_I1_SB_LUT4_I0_I3_SB_LUT4_I0_O_SB_LUT4_O_I3_SB_LUT4_I3_O_SB_LUT4_O_I0_SB_LUT4_O_1_I3_SB_LUT4_I1_O[1]) 74 | odrv_3_6_8881_12978 (Odrv4) I -> O: 0.548 ns 75 | t3450 (Span4Mux_v4) I -> O: 0.548 ns 76 | t3449 (LocalMux) I -> O: 0.486 ns 77 | inmux_3_11_13638_13649 (InMux) I -> O: 0.382 ns 78 | lc40_3_11_1 (LogicCell40) in0 -> lcout: 0.662 ns 79 | 27.224 ns net_9493 (u_usb_dfu.u_ctrl_endp.req_q_SB_DFFR_Q_5_D_SB_LUT4_O_I3_SB_LUT4_O_I0_SB_LUT4_I3_I0_SB_LUT4_I0_O_SB_LUT4_O_I0_SB_LUT4_I3_O_SB_LUT4_O_I2_SB_LUT4_I2_O[3]) 80 | t3559 (LocalMux) I -> O: 0.486 ns 81 | inmux_3_11_13635_13681 (InMux) I -> O: 0.382 ns 82 | t355 (CascadeMux) I -> O: 0.000 ns 83 | lc40_3_11_6 (LogicCell40) in2 -> lcout: 0.558 ns 84 | 28.651 ns net_9498 (u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E) 85 | odrv_3_11_9498_5291 (Odrv4) I -> O: 0.548 ns 86 | t3566 (Span4Mux_v4) I -> O: 0.548 ns 87 | t3565 (LocalMux) I -> O: 0.486 ns 88 | inmux_4_11_17705_17766 (CEMux) I -> O: 0.889 ns 89 | 31.121 ns net_17766 (u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E) 90 | lc40_4_11_4 (LogicCell40) ce [setup]: 0.000 ns 91 | 31.121 ns net_13573 (u_usb_dfu.u_ctrl_endp.dev_state_q[1]) 92 | 93 | Resolvable net names on path: 94 | 0.896 ns .. 3.873 ns u_usb_dfu.dfu_status_s 95 | 4.535 ns .. 5.403 ns u_usb_dfu.u_fifo_endps[0].u_fifo.u_in_fifo.genblk1.u_gt12mhz_async_data.app_in_valid_qq_SB_LUT4_I0_O[3] 96 | 5.961 ns .. 9.403 ns u_usb_dfu.dfu_done 97 | 10.065 ns .. 10.933 ns u_usb_dfu.u_ctrl_endp.dfu_done_i_SB_LUT4_I1_1_O[2] 98 | 11.491 ns .. 14.003 ns u_usb_dfu.dfu_upload_SB_LUT4_I3_I2[0] 99 | 14.592 ns .. 15.461 ns u_usb_dfu.dfu_upload_SB_LUT4_I3_O[3] 100 | 16.019 ns .. 16.887 ns u_usb_dfu.u_sie.in_req_q_SB_LUT4_I3_2_O[1] 101 | 17.445 ns .. 21.053 ns u_usb_dfu.u_ctrl_endp.dfu_done_q_SB_LUT4_I1_O[1] 102 | 21.642 ns .. 22.510 ns u_usb_dfu.u_ctrl_endp.dfu_state_q_SB_DFFER_Q_D_SB_LUT4_O_I1_SB_LUT4_O_I1_SB_LUT4_I1_O_SB_LUT4_O_1_I2_SB_LUT4_I2_O_SB_LUT4_I3_O_SB_LUT4_I0_O[0] 103 | 23.069 ns .. 23.937 ns u_usb_dfu.u_ctrl_endp.dfu_state_q_SB_DFFER_Q_D_SB_LUT4_O_I1[1] 104 | 24.599 ns .. 26.563 ns u_usb_dfu.u_ctrl_endp.max_length_d_SB_LUT4_O_8_I1_SB_LUT4_I0_I3_SB_LUT4_I0_O_SB_LUT4_O_I3_SB_LUT4_I3_O_SB_LUT4_O_I0_SB_LUT4_O_1_I3_SB_LUT4_I1_O[1] 105 | 27.224 ns .. 28.092 ns u_usb_dfu.u_ctrl_endp.req_q_SB_DFFR_Q_5_D_SB_LUT4_O_I3_SB_LUT4_O_I0_SB_LUT4_I3_I0_SB_LUT4_I0_O_SB_LUT4_O_I0_SB_LUT4_I3_O_SB_LUT4_O_I2_SB_LUT4_I2_O[3] 106 | 28.651 ns .. 31.121 ns u_usb_dfu.u_ctrl_endp.dev_state_q_SB_DFFES_Q_E 107 | lcout -> u_usb_dfu.u_ctrl_endp.dev_state_q[1] 108 | 109 | Total number of logic levels: 13 110 | Total path delay: 31.12 ns (32.13 MHz) 111 | 112 | -------------------------------------------------------------------------------- /examples/common/synplifypro/usb_dfu.sdc: -------------------------------------------------------------------------------- 1 | 2 | ####---- USB_DFU constraints ---- 3 | set fid [open mylog.txt w] 4 | proc file_puts {fid text collection} { 5 | puts $fid "\n$text" 6 | foreach elem [c_list $collection] { 7 | puts $fid $elem 8 | } 9 | } 10 | 11 | set path "${root_path}.u_sie.u_phy_tx" 12 | set tx_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 13 | ${path}.tx_state_q* 14 | ${path}.bit_cnt_q* 15 | ${path}.data_q* 16 | ${path}.stuffing_cnt_q* 17 | ${path}.nrzi_q* 18 | "]] 19 | file_puts $fid "01" $tx_gated_cells 20 | set_multicycle_path -setup [expr $BIT_SAMPLES] -from $tx_gated_cells 21 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -from $tx_gated_cells 22 | set_multicycle_path -setup [expr $BIT_SAMPLES] -to $tx_gated_cells 23 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -to $tx_gated_cells 24 | 25 | set path "${root_path}.u_sie.u_phy_rx" 26 | set rx1_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 27 | ${path}.rx_state_q* 28 | ${path}.shift_register_q* 29 | ${path}.rx_data_q* 30 | ${path}.stuffing_cnt_q* 31 | "]] 32 | file_puts $fid "02" $rx1_gated_cells 33 | set_multicycle_path -setup [expr $BIT_SAMPLES / 2] -from $rx1_gated_cells -to $rx1_gated_cells 34 | set_multicycle_path -hold [expr ($BIT_SAMPLES / 2) - 1] -from $rx1_gated_cells -to $rx1_gated_cells 35 | 36 | set rx2_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 37 | ${path}.cnt_q* 38 | ${path}.state_q* 39 | ${path}.dp_pu_q* 40 | ${path}.bus_reset_q* 41 | "]] 42 | file_puts $fid "03" $rx2_gated_cells 43 | set_multicycle_path -setup [expr $BIT_SAMPLES] -from $rx2_gated_cells -to $rx2_gated_cells 44 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -from $rx2_gated_cells -to $rx2_gated_cells 45 | 46 | set rx3_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 47 | ${path}.rx_valid_qq* 48 | ${path}.rx_err_qq* 49 | ${path}.rx_eop_qq* 50 | ${path}.rx_data_q* 51 | "]] 52 | set rx3_gated_pins [get_pins " 53 | ${path}.rx_valid_o* 54 | ${path}.rx_err_o* 55 | ${path}.rx_ready_o* 56 | ${path}.rx_data_o* 57 | "] 58 | file_puts $fid "04" $rx3_gated_cells 59 | file_puts $fid "05" $rx3_gated_pins 60 | set_multicycle_path -setup [expr $BIT_SAMPLES] -from $rx3_gated_cells -through $rx3_gated_pins 61 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -from $rx3_gated_cells -through $rx3_gated_pins 62 | 63 | set path "${root_path}.u_sie" 64 | set sie_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 65 | ${path}.* 66 | "]] 67 | file_puts $fid "06" $sie_gated_cells 68 | set_multicycle_path -setup [expr 1 * $BIT_SAMPLES] -from $sie_gated_cells 69 | set_multicycle_path -hold [expr 1 * $BIT_SAMPLES - 1] -from $sie_gated_cells 70 | set_multicycle_path -setup [expr 1 * $BIT_SAMPLES] -to $sie_gated_cells 71 | set_multicycle_path -hold [expr 1 * $BIT_SAMPLES - 1] -to $sie_gated_cells 72 | 73 | set path "${root_path}.u_ctrl_endp" 74 | set ctrl_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 75 | ${path}.* 76 | "]] 77 | file_puts $fid "07" $ctrl_gated_cells 78 | set_multicycle_path -setup [expr 1 * $BIT_SAMPLES] -from $ctrl_gated_cells 79 | set_multicycle_path -hold [expr 1 * $BIT_SAMPLES - 1] -from $ctrl_gated_cells 80 | set_multicycle_path -setup [expr 1 * $BIT_SAMPLES] -to $ctrl_gated_cells 81 | set_multicycle_path -hold [expr 1 * $BIT_SAMPLES - 1] -to $ctrl_gated_cells 82 | 83 | set path "${root_path}.*u_fifo.u_in_fifo" 84 | set in_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 85 | ${path}.in_first_q\[* 86 | ${path}.in_first_qq\[* 87 | "]] 88 | set in_gated_pins [get_pins " 89 | ${path}.in_ready_i* 90 | ${path}.in_data_o* 91 | ${path}.in_valid_o* 92 | ${path}.in_empty_o* 93 | ${path}.in_full_o* 94 | "] 95 | file_puts $fid "08" $in_gated_cells 96 | file_puts $fid "09" $in_gated_pins 97 | set_multicycle_path -setup [expr $BIT_SAMPLES] -from $in_gated_cells 98 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -from $in_gated_cells 99 | set_multicycle_path -setup [expr $BIT_SAMPLES] -to $in_gated_cells 100 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -to $in_gated_cells 101 | 102 | set in2_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 103 | ${path}.u_*.in_fifo_q* 104 | ${path}.u_*.in_last_q\[* 105 | ${path}.u_*.in_last_qq\[* 106 | "]] 107 | file_puts $fid "10" $in2_gated_cells 108 | set_multicycle_path -setup [expr $BIT_SAMPLES] -from $in2_gated_cells -to $in2_gated_cells 109 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -from $in2_gated_cells -to $in2_gated_cells 110 | set_multicycle_path -setup [expr $BIT_SAMPLES] -from $in2_gated_cells -through $in_gated_pins 111 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -from $in2_gated_cells -through $in_gated_pins 112 | #set_multicycle_path -setup [expr $BIT_SAMPLES] -to $in2_gated_cells -through $in_gated_pins 113 | #set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -to $in2_gated_cells -through $in_gated_pins 114 | 115 | set path "${root_path}.*u_fifo.u_out_fifo" 116 | set out_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 117 | ${path}.out_fifo_q* 118 | ${path}.out_last_q\[* 119 | ${path}.out_last_qq\[* 120 | ${path}.out_nak_q* 121 | "]] 122 | set out_gated_pins [get_pins " 123 | ${path}.out_empty_o* 124 | ${path}.out_full_o* 125 | "] 126 | file_puts $fid "11" $out_gated_cells 127 | file_puts $fid "12" $out_gated_pins 128 | set_multicycle_path -setup [expr $BIT_SAMPLES] -from $out_gated_cells 129 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -from $out_gated_cells 130 | set_multicycle_path -setup [expr $BIT_SAMPLES] -to $out_gated_cells 131 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -to $out_gated_cells 132 | 133 | set out2_gated_cells [remove_from_collection -intersect [all_registers] [get_cells " 134 | ${path}.u_*.out_first_q* 135 | "]] 136 | file_puts $fid "13" $out2_gated_cells 137 | set_multicycle_path -setup [expr $BIT_SAMPLES] -from $out2_gated_cells -to $out2_gated_cells 138 | set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -from $out2_gated_cells -to $out2_gated_cells 139 | #set_multicycle_path -setup [expr $BIT_SAMPLES] -from $out2_gated_cells -through $out_gated_pins 140 | #set_multicycle_path -hold [expr $BIT_SAMPLES - 1] -from $out2_gated_cells -through $out_gated_pins 141 | 142 | set path "${root_path}" 143 | set clk_gate_cell [remove_from_collection -intersect [all_registers] [get_cells " 144 | ${path}.clk_gate_q* 145 | "]] 146 | file_puts $fid "14" $clk_gate_cell 147 | set_multicycle_path -setup [expr 1] -from $clk_gate_cell 148 | set_multicycle_path -hold [expr 1 - 1] -from $clk_gate_cell 149 | 150 | close $fid 151 | -------------------------------------------------------------------------------- /examples/common/hdl/flash/spi.v: -------------------------------------------------------------------------------- 1 | // Serial Peripheral Interface. 2 | // Written in verilog 2001 3 | 4 | // SPI module shall serialize wr_data_i to mosi_o bitstream 5 | // and de-serialize miso_i bitstream to rd_data_o. 6 | // A SPI bitstream shall have csn_o low and shall start with a write byte. 7 | 8 | module spi 9 | #(parameter SCK_PERIOD_MULTIPLIER = 'd2) 10 | ( 11 | input clk_i, 12 | input rstn_i, 13 | // While rstn_i is low (active low), the module shall be reset 14 | 15 | // ---- to/from application module -------------- 16 | input en_i, 17 | // When en_i changes from high to low, the current bitstream shall end at the 18 | // end of current byte transmission. 19 | input [7:0] wr_data_i, 20 | // While wr_valid_i is high, the wr_data_i shall be valid. 21 | input wr_valid_i, 22 | // While en_i is high and when wr_valid_i changes from low to high, SPI shall start a 23 | // new bitstream transmission as soon as possible. 24 | output wr_ready_o, 25 | // While en_i is high and when both wr_valid_i and wr_ready_o are high, the 8-bit 26 | // wr_data_i shall be consumed. 27 | output [7:0] rd_data_o, 28 | // While en_i is high and when both rd_valid_o and rd_ready_i are high, rd_data_o 29 | // shall be consumed by application module. 30 | output rd_valid_o, 31 | // When rd_data_o is valid, rd_valid_o shall be high only for one clk_i period. 32 | input rd_ready_i, 33 | // While both en_i and rd_ready_i are high, a read bitstream shall continue at 34 | // the end of the current byte transmission. 35 | 36 | // ---- to/from serial bus ---------------------- 37 | output sck_o, 38 | // While en_i is high and both wr_valid_o and rd_ready_i are low, sck_o shall 39 | // wait at the end of current byte transmission. 40 | output csn_o, 41 | // When both en_i and wr_valid_i are high, csn_o shall go low. 42 | // When en_i changes from high to low, csn_o shall go high at the end of current 43 | // byte transmission. 44 | output mosi_o, 45 | input miso_i 46 | ); 47 | 48 | function integer ceil_log2; 49 | input [31:0] arg; 50 | integer i; 51 | begin 52 | ceil_log2 = 0; 53 | for (i = 0; i < 32; i = i + 1) begin 54 | if (arg > (1 << i)) 55 | ceil_log2 = ceil_log2 + 1; 56 | end 57 | end 58 | endfunction 59 | 60 | localparam CLK_STEPS = (SCK_PERIOD_MULTIPLIER+1)/2; 61 | 62 | wire clk_gate; 63 | 64 | generate 65 | if (CLK_STEPS <= 1) begin : u_single_clk_period 66 | assign clk_gate = 1'b1; 67 | end else begin : u_multiple_clk_periods 68 | reg [ceil_log2(CLK_STEPS)-1:0] clk_cnt_q; 69 | 70 | assign clk_gate = ({1'b0, clk_cnt_q} == CLK_STEPS-1) ? 1'b1 : 1'b0; 71 | 72 | always @(posedge clk_i or negedge rstn_i) begin 73 | if (~rstn_i) begin 74 | clk_cnt_q <= 'd0; 75 | end else begin 76 | if ({1'b0, clk_cnt_q} == CLK_STEPS-1) 77 | clk_cnt_q <= 'd0; 78 | else 79 | clk_cnt_q <= clk_cnt_q + 1; 80 | end 81 | end 82 | end 83 | endgenerate 84 | 85 | localparam [1:0] ST_RESET = 2'd0, 86 | ST_IDLE = 2'd1, 87 | ST_DATA_SHIFT = 2'd2, 88 | ST_DATA_WAIT = 2'd3; 89 | 90 | reg [1:0] state_q, state_d; 91 | reg [2:0] bit_cnt_q, bit_cnt_d; 92 | reg [7:0] wr_data_q, wr_data_d; 93 | reg [7:0] rd_data_q, rd_data_d; 94 | reg en_q, en_d; 95 | reg sck_q, sck_d; 96 | 97 | assign csn_o = (state_q != ST_DATA_SHIFT && state_q != ST_DATA_WAIT) ? 1'b1 : 1'b0; 98 | assign sck_o = sck_q; 99 | assign mosi_o = wr_data_q[7]; 100 | assign rd_data_o = rd_data_q; 101 | 102 | always @(posedge clk_i or negedge rstn_i) begin 103 | if (~rstn_i) begin 104 | state_q <= ST_RESET; 105 | bit_cnt_q <= 'd0; 106 | wr_data_q <= 'd0; 107 | rd_data_q <= 'd0; 108 | en_q <= 1'b0; 109 | sck_q <= 1'b0; 110 | end else begin 111 | en_q <= en_i & en_q; 112 | if (clk_gate) begin 113 | state_q <= state_d; 114 | bit_cnt_q <= bit_cnt_d; 115 | wr_data_q <= wr_data_d; 116 | rd_data_q <= rd_data_d; 117 | en_q <= en_d; 118 | sck_q <= sck_d; 119 | end 120 | end 121 | end 122 | 123 | reg wr_ready; 124 | reg rd_valid; 125 | 126 | wire wr_valid; 127 | wire rd_ready; 128 | 129 | assign wr_ready_o = wr_ready & clk_gate; 130 | assign rd_valid_o = rd_valid & clk_gate; 131 | assign wr_valid = wr_valid_i & en_i; 132 | assign rd_ready = rd_ready_i & en_i; 133 | 134 | always @(/*AS*/bit_cnt_q or en_i or en_q or miso_i or rd_data_q 135 | or rd_ready or sck_q or state_q or wr_data_i or wr_data_q 136 | or wr_valid) begin 137 | state_d = state_q; 138 | bit_cnt_d = bit_cnt_q; 139 | wr_data_d = wr_data_q; 140 | rd_data_d = rd_data_q; 141 | en_d = en_i & en_q; 142 | sck_d = 1'b0; 143 | wr_ready = 1'b0; 144 | rd_valid = 1'b0; 145 | 146 | case (state_q) 147 | ST_RESET : begin 148 | state_d = ST_IDLE; 149 | end 150 | ST_IDLE : begin 151 | bit_cnt_d = 'd7; 152 | wr_ready = 1'b1; 153 | if (wr_valid) begin 154 | en_d = 1'b1; 155 | wr_data_d = wr_data_i; 156 | state_d = ST_DATA_SHIFT; 157 | end 158 | end 159 | ST_DATA_SHIFT : begin 160 | sck_d = ~sck_q; 161 | if (sck_q) begin 162 | wr_data_d = {wr_data_q[6:0], 1'b0}; 163 | if (bit_cnt_q == 'd0) begin 164 | bit_cnt_d = 'd7; 165 | rd_valid = 1'b1; 166 | if (en_q) begin 167 | wr_ready = 1'b1; 168 | if (wr_valid) begin 169 | wr_data_d = wr_data_i; 170 | end else 171 | state_d = ST_DATA_WAIT; 172 | end else 173 | state_d = ST_DATA_WAIT; 174 | end else begin 175 | bit_cnt_d = bit_cnt_q - 1; 176 | end 177 | end else begin 178 | rd_data_d = {rd_data_q[6:0], miso_i}; 179 | end 180 | end 181 | ST_DATA_WAIT : begin 182 | bit_cnt_d = 'd7; 183 | if (en_q) begin 184 | wr_ready = 1'b1; 185 | if (wr_valid) begin 186 | wr_data_d = wr_data_i; 187 | state_d = ST_DATA_SHIFT; 188 | end else if (rd_ready) begin 189 | sck_d = 1'b1; 190 | rd_data_d = {rd_data_q[6:0], miso_i}; 191 | state_d = ST_DATA_SHIFT; 192 | end 193 | end else 194 | state_d = ST_IDLE; 195 | end 196 | default : begin 197 | bit_cnt_d = 'd7; 198 | state_d = ST_IDLE; 199 | end 200 | endcase 201 | end 202 | endmodule 203 | -------------------------------------------------------------------------------- /examples/common/hdl/ram_if.v: -------------------------------------------------------------------------------- 1 | // RAM interface. 2 | // Written in verilog 2001 3 | 4 | // RAM_IF module shall provide access to read/write RAM: 5 | // - When en_i changes from low to high, a new read/write operation shall start. 6 | // - Memory read shall start at byte address specified by start_addr_i. 7 | // - Memory write shall start at byte address specified by start_addr_i. 8 | // - Memory read/write operation shall end at byte address specified by end_addr_i. 9 | // RAM_IF module shall verify the number of bytes written and shall report an error 10 | // if it differs from the expected value: 11 | // - When status_o reports a failure, RAM_IF shall wait a clear_status_i pulse to clear status_o 12 | // and to allow the next read/write operation. 13 | 14 | `define min(a,b)((a) < (b) ? (a) : (b)) 15 | 16 | module ram_if 17 | #(parameter RAM_SIZE = 'd1024) // byte size 18 | ( 19 | input clk_i, 20 | input rstn_i, 21 | // While rstn_i is low (active low), the module shall be reset 22 | 23 | // ---- to/from application module -------------- 24 | input en_i, 25 | // When en_i changes from low to high, a new read/program operation shall start. 26 | // When en_i changes from high to low, the current read/program operation shall end. 27 | input [ceil_log2(RAM_SIZE)-1:0] start_addr_i, 28 | input [ceil_log2(RAM_SIZE)-1:0] end_addr_i, 29 | // input [7:0] out_data_i, 30 | // While out_valid_i is high, the out_data_i shall be valid. 31 | input out_valid_i, 32 | // When both en_i and out_valid_i change from low to high, a new write 33 | // operation shall start. 34 | output out_ready_o, 35 | // While en_i is high and when both out_valid_i and out_ready_o are high, out_data_i 36 | // shall be consumed. 37 | // output [7:0] in_data_o, 38 | // While in_valid_o is high, the in_data_o shall be valid. 39 | output in_valid_o, 40 | // While en_i is high and when both in_valid_o and in_ready_i are high, in_data_o 41 | // shall be consumed by application module. 42 | // in_valid_o shall be high only for one clk_i period. 43 | input in_ready_i, 44 | // When both en_i and in_ready_i change from low to high, a new read 45 | // operation shall start. 46 | input clear_status_i, 47 | // While status_o reports an error or the end of write/read operation (4'bF), 48 | // when clear_status_i is high, status_o shall be cleared to 4'h0. 49 | output [3:0] status_o, 50 | // status_o shall report an error (4'h8 or 4'h0) or the end of a correct 51 | // write/read operation (4'hF), otherwise shall be 4'h0. 52 | 53 | output ram_clke_o, 54 | output ram_we_o, 55 | output [ceil_log2(RAM_SIZE)-1:0] ram_addr_o 56 | ); 57 | 58 | function integer ceil_log2; 59 | input [31:0] arg; 60 | integer i; 61 | begin 62 | ceil_log2 = 0; 63 | for (i = 0; i < 32; i = i + 1) begin 64 | if (arg > (1 << i)) 65 | ceil_log2 = ceil_log2 + 1; 66 | end 67 | end 68 | endfunction 69 | 70 | localparam [1:0] IDLE_STATE = 'd0, 71 | READ_RAM_STATE = 'd1, 72 | WRITE_RAM_STATE = 'd2; 73 | localparam [3:0] STATUS_OK = 4'h0, 74 | STATUS_errADDRESS = 4'h8, 75 | STATUS_errNOTDONE = 4'h9, 76 | STATUS_END = 4'hF; 77 | 78 | reg [1:0] state_q, state_d; 79 | reg [3:0] status_q, status_d; 80 | reg mem_valid_q, mem_valid_d; 81 | reg [ceil_log2(RAM_SIZE)+1-1:0] mem_addr_q, mem_addr_d; 82 | 83 | always @(posedge clk_i or negedge rstn_i) begin 84 | if (~rstn_i) begin 85 | state_q <= IDLE_STATE; 86 | status_q <= STATUS_OK; 87 | mem_valid_q <= 1'b0; 88 | mem_addr_q <= 'd0; 89 | end else begin 90 | state_q <= state_d; 91 | status_q <= status_d; 92 | mem_valid_q <= mem_valid_d; 93 | mem_addr_q <= mem_addr_d; 94 | end 95 | end 96 | 97 | reg out_ready; 98 | reg ram_clke; 99 | reg ram_we; 100 | 101 | assign out_ready_o = out_ready; 102 | assign in_valid_o = mem_valid_q; 103 | assign status_o = status_q; 104 | assign ram_clke_o = ram_clke; 105 | assign ram_we_o = ram_we; 106 | assign ram_addr_o = mem_addr_q[ceil_log2(RAM_SIZE)-1:0]; 107 | 108 | always @(/*AS*/clear_status_i or en_i or end_addr_i or in_ready_i 109 | or mem_addr_q or mem_valid_q or out_valid_i 110 | or start_addr_i or state_q or status_q) begin 111 | state_d = state_q; 112 | status_d = status_q; 113 | mem_valid_d = mem_valid_q; 114 | mem_addr_d = mem_addr_q; 115 | out_ready = 1'b0; 116 | ram_clke = 1'b0; 117 | ram_we = 1'b0; 118 | 119 | case (state_q) 120 | IDLE_STATE: begin 121 | if (en_i == 1'b1 && status_q == STATUS_OK) begin 122 | if (out_valid_i) 123 | state_d = WRITE_RAM_STATE; 124 | else if (in_ready_i) 125 | state_d = READ_RAM_STATE; 126 | end 127 | if (clear_status_i) 128 | status_d = STATUS_OK; 129 | mem_valid_d = 1'b0; 130 | mem_addr_d = {1'b0, start_addr_i}; 131 | end 132 | WRITE_RAM_STATE: begin 133 | if (en_i == 1'b1 && mem_addr_q <= {1'b0, end_addr_i}) begin 134 | ram_we = 1'b1; 135 | out_ready = 1'b1; 136 | if (out_valid_i) begin 137 | mem_addr_d = mem_addr_q + 1; 138 | ram_clke = 1'b1; 139 | end 140 | end else begin 141 | if (status_q != STATUS_errADDRESS) begin 142 | if (mem_addr_q <= {1'b0, end_addr_i}) 143 | status_d = STATUS_errNOTDONE; 144 | else 145 | status_d = STATUS_END; 146 | end 147 | if (en_i & out_valid_i) 148 | status_d = STATUS_errADDRESS; 149 | if (~en_i) 150 | state_d = IDLE_STATE; 151 | end 152 | end 153 | READ_RAM_STATE: begin 154 | if (en_i == 1'b1 && (mem_addr_q <= {1'b0, end_addr_i} || mem_valid_q == 1'b1)) begin 155 | if (~mem_valid_q) begin 156 | mem_valid_d = 1'b1; 157 | mem_addr_d = mem_addr_q + 1; 158 | ram_clke = 1'b1; 159 | end else if (in_ready_i) begin 160 | if (mem_addr_q <= {1'b0, end_addr_i}) begin 161 | mem_addr_d = mem_addr_q + 1; 162 | ram_clke = 1'b1; 163 | end else begin 164 | mem_valid_d = 1'b0; 165 | end 166 | end 167 | end else begin 168 | state_d = IDLE_STATE; 169 | status_d = STATUS_END; 170 | end 171 | end 172 | default: begin 173 | state_d = IDLE_STATE; 174 | end 175 | endcase 176 | end 177 | 178 | endmodule 179 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/hdl/bootloader/bootloader.v: -------------------------------------------------------------------------------- 1 | 2 | module bootloader 3 | ( 4 | input clk, // 16MHz Clock 5 | output led, // User LED ON=1, OFF=0 6 | inout usb_p, // USB+ 7 | inout usb_n, // USB- 8 | output usb_pu, // USB 1.5kOhm Pullup EN 9 | output sck, 10 | output ss, 11 | output sdo, 12 | input sdi 13 | ); 14 | 15 | localparam CHANNELS = 'd1; 16 | localparam BIT_SAMPLES = 'd4; 17 | localparam [6:0] DIVF = 12*BIT_SAMPLES-1; 18 | localparam TRANSFER_SIZE = 'd256; 19 | localparam POLLTIMEOUT = 'd10; // ms 20 | localparam MS20 = 1; 21 | localparam WCID = 1; 22 | 23 | wire clk_pll; 24 | wire lock; 25 | wire dp_pu; 26 | wire dp_rx; 27 | wire dn_rx; 28 | wire dp_tx; 29 | wire dn_tx; 30 | wire tx_en; 31 | wire [7:0] out_data; 32 | wire out_valid; 33 | wire in_ready; 34 | wire [7:0] in_data; 35 | wire in_valid; 36 | wire out_ready; 37 | wire [2:0] dfu_alt; 38 | wire dfu_out_en; 39 | wire dfu_in_en; 40 | wire [7:0] dfu_out_data; 41 | wire dfu_out_valid; 42 | wire dfu_in_ready; 43 | wire [7:0] dfu_in_data; 44 | wire dfu_in_valid; 45 | wire dfu_out_ready; 46 | wire dfu_clear_status; 47 | wire dfu_busy; 48 | wire [3:0] dfu_status; 49 | wire boot; 50 | wire [10:0] frame; 51 | wire configured; 52 | wire dfu_mode; 53 | 54 | assign led = (configured) ? ((dfu_mode) ? frame[8] : frame[9]) : ~&frame[4:3]; 55 | 56 | // if FEEDBACK_PATH = SIMPLE: 57 | // clk_freq = (ref_freq * (DIVF + 1)) / (2**DIVQ * (DIVR + 1)); 58 | SB_PLL40_CORE #(.DIVR(4'd0), 59 | .DIVF(DIVF), 60 | .DIVQ(3'd4), 61 | .FILTER_RANGE(3'b001), 62 | .FEEDBACK_PATH("SIMPLE"), 63 | .DELAY_ADJUSTMENT_MODE_FEEDBACK("FIXED"), 64 | .FDA_FEEDBACK(4'b0000), 65 | .DELAY_ADJUSTMENT_MODE_RELATIVE("FIXED"), 66 | .FDA_RELATIVE(4'b0000), 67 | .SHIFTREG_DIV_MODE(2'b00), 68 | .PLLOUT_SELECT("GENCLK"), 69 | .ENABLE_ICEGATE(1'b0)) 70 | u_pll (.REFERENCECLK(clk), // 16MHz 71 | .PLLOUTCORE(), 72 | .PLLOUTGLOBAL(clk_pll), // 48MHz 73 | .EXTFEEDBACK(1'b0), 74 | .DYNAMICDELAY(8'd0), 75 | .LOCK(lock), 76 | .BYPASS(1'b0), 77 | .RESETB(1'b1), 78 | .SDI(1'b0), 79 | .SDO(), 80 | .SCLK(1'b0), 81 | .LATCHINPUTVALUE(1'b1)); 82 | 83 | app u_app (.clk_i(clk), 84 | .rstn_i(lock), 85 | .out_data_i(out_data), 86 | .out_valid_i(out_valid), 87 | .in_ready_i(in_ready), 88 | .out_ready_o(out_ready), 89 | .in_data_o(in_data), 90 | .in_valid_o(in_valid), 91 | .dfu_mode_i(dfu_mode), 92 | .dfu_alt_i(dfu_alt), 93 | .dfu_out_en_i(dfu_out_en), 94 | .dfu_in_en_i(dfu_in_en), 95 | .dfu_out_data_i(dfu_out_data), 96 | .dfu_out_valid_i(dfu_out_valid), 97 | .dfu_out_ready_o(dfu_out_ready), 98 | .dfu_in_data_o(dfu_in_data), 99 | .dfu_in_valid_o(dfu_in_valid), 100 | .dfu_in_ready_i(dfu_in_ready), 101 | .dfu_clear_status_i(dfu_clear_status), 102 | .dfu_busy_o(dfu_busy), 103 | .dfu_status_o(dfu_status), 104 | .heartbeat_i(configured & frame[0]), 105 | .boot_o(boot), 106 | .sck_o(sck), 107 | .csn_o(ss), 108 | .mosi_o(sdo), 109 | .miso_i(sdi)); 110 | 111 | usb_dfu #(.VENDORID(16'h1D50), 112 | .PRODUCTID(16'h6130), 113 | .CHANNELS(CHANNELS), 114 | .RTI_STRING("USB_DFU"), 115 | .SN_STRING("00"), 116 | .ALT_STRINGS("RD/WR\nRD ALL\nBOOT"), 117 | .TRANSFER_SIZE(TRANSFER_SIZE), 118 | .POLLTIMEOUT(POLLTIMEOUT), 119 | .MS20(MS20), 120 | .WCID(WCID), 121 | .MAXPACKETSIZE('d8), 122 | .BIT_SAMPLES(BIT_SAMPLES), 123 | .USE_APP_CLK(1), 124 | .APP_CLK_FREQ(16)) // 16MHz 125 | u_usb_dfu (.frame_o(frame), 126 | .configured_o(configured), 127 | .app_clk_i(clk), 128 | .clk_i(clk_pll), 129 | .rstn_i(lock), 130 | .out_ready_i(out_ready), 131 | .in_data_i(in_data), 132 | .in_valid_i(in_valid), 133 | .dp_rx_i(dp_rx), 134 | .dn_rx_i(dn_rx), 135 | .out_data_o(out_data), 136 | .out_valid_o(out_valid), 137 | .in_ready_o(in_ready), 138 | .dfu_mode_o(dfu_mode), 139 | .dfu_alt_o(dfu_alt), 140 | .dfu_out_en_o(dfu_out_en), 141 | .dfu_in_en_o(dfu_in_en), 142 | .dfu_out_data_o(dfu_out_data), 143 | .dfu_out_valid_o(dfu_out_valid), 144 | .dfu_out_ready_i(dfu_out_ready), 145 | .dfu_in_data_i(dfu_in_data), 146 | .dfu_in_valid_i(dfu_in_valid), 147 | .dfu_in_ready_o(dfu_in_ready), 148 | .dfu_clear_status_o(dfu_clear_status), 149 | .dfu_blocknum_o(), 150 | .dfu_busy_i(dfu_busy), 151 | .dfu_status_i(dfu_status), 152 | .dp_pu_o(dp_pu), 153 | .tx_en_o(tx_en), 154 | .dp_tx_o(dp_tx), 155 | .dn_tx_o(dn_tx)); 156 | 157 | SB_WARMBOOT u_warmboot (.S1(1'b0), 158 | .S0(1'b1), 159 | .BOOT(boot)); 160 | 161 | SB_IO #(.PIN_TYPE(6'b101001), 162 | .PULLUP(1'b0)) 163 | u_usb_p (.PACKAGE_PIN(usb_p), 164 | .OUTPUT_ENABLE(tx_en), 165 | .D_OUT_0(dp_tx), 166 | .D_IN_0(dp_rx), 167 | .D_OUT_1(1'b0), 168 | .D_IN_1(), 169 | .CLOCK_ENABLE(1'b0), 170 | .LATCH_INPUT_VALUE(1'b0), 171 | .INPUT_CLK(1'b0), 172 | .OUTPUT_CLK(1'b0)); 173 | 174 | SB_IO #(.PIN_TYPE(6'b101001), 175 | .PULLUP(1'b0)) 176 | u_usb_n (.PACKAGE_PIN(usb_n), 177 | .OUTPUT_ENABLE(tx_en), 178 | .D_OUT_0(dn_tx), 179 | .D_IN_0(dn_rx), 180 | .D_OUT_1(1'b0), 181 | .D_IN_1(), 182 | .CLOCK_ENABLE(1'b0), 183 | .LATCH_INPUT_VALUE(1'b0), 184 | .INPUT_CLK(1'b0), 185 | .OUTPUT_CLK(1'b0)); 186 | 187 | // drive usb_pu to 3.3V or to high impedance 188 | SB_IO #(.PIN_TYPE(6'b101001), 189 | .PULLUP(1'b0)) 190 | u_usb_pu (.PACKAGE_PIN(usb_pu), 191 | .OUTPUT_ENABLE(dp_pu), 192 | .D_OUT_0(1'b1), 193 | .D_IN_0(), 194 | .D_OUT_1(1'b0), 195 | .D_IN_1(), 196 | .CLOCK_ENABLE(1'b0), 197 | .LATCH_INPUT_VALUE(1'b0), 198 | .INPUT_CLK(1'b0), 199 | .OUTPUT_CLK(1'b0)); 200 | 201 | endmodule 202 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # USB_DFU Examples 2 | 3 | All the examples are built with both [Lattice iCEcube2](https://www.latticesemi.com/iCEcube2) and [OSS CAD Suite](https://github.com/YosysHQ/oss-cad-suite-build) design flows. 4 | 5 | * Lattice design flow 6 | * Open `examples//iCEcube2//usb_dfu_sbt.project` file with iCEcube2. 7 | * OSS CAD Suite flow 8 | * inside `examples//OSS_CAD_Suite` run `make all PROJ=` 9 | 10 | Testbenches can be simulated with iverilog/GTKWave. 11 | To run them, inside `examples//OSS_CAD_Suite` run `make sim PROJ=`. Or run `make wave PROJ=` to show waveforms too. 12 | 13 | The GTKWave console makes available a few commands (such as `top`, `out`, `phy_rx`, etc.) to show various waveforms inside the design. 14 | 15 | ## `bootloader` 16 | The `bootloader` example implements an equivalent of the original TinyFPGA bootloader with the DFU function added. It is fully compatible with the `tinyprog` programmer. 17 | 18 | In Run-time mode (after USB reset), the device can respond to both `tinyprog` and `dfu-util`: 19 | 20 | ``` 21 | > tinyprog -l 22 | 23 | TinyProg CLI 24 | ------------ 25 | Using device id 1d50:6130 26 | Only one board with active bootloader, using it. 27 | 28 | Boards with active bootloaders: 29 | 30 | /dev/cu.usbmodem001: TinyFPGA BX 1.0.0 31 | UUID: a6121c87-091b-4037-90c5-7091192fc44d 32 | FPGA: ice40lp8k-cm81 33 | 34 | ``` 35 | ``` 36 | > dfu-util -lv 37 | dfu-util 0.11 38 | 39 | Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. 40 | Copyright 2010-2021 Tormod Volden and Stefan Schmidt 41 | This program is Free Software and has ABSOLUTELY NO WARRANTY 42 | Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ 43 | 44 | libusb version 1.0.24 (11584) 45 | Found Runtime: [1d50:6130] ver=0100, devnum=10, cfg=1, intf=2, path="20-4.4.4", alt=0, name="USB_DFU", serial="00" 46 | ``` 47 | To switch from Run-time to DFU mode: 48 | 49 | ``` 50 | > dfu-util -ev 51 | dfu-util 0.11 52 | 53 | Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. 54 | Copyright 2010-2021 Tormod Volden and Stefan Schmidt 55 | This program is Free Software and has ABSOLUTELY NO WARRANTY 56 | Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ 57 | 58 | libusb version 1.0.24 (11584) 59 | Opening DFU capable USB device... 60 | Device ID 1d50:6130 61 | Run-Time device DFU version 0110 62 | DFU attributes: (0x0f) bitCanDnload bitCanUpload bitManifestationTolerant bitWillDetach 63 | Detach timeout 1000 ms 64 | Claiming USB DFU (Run-Time) Interface... 65 | Setting Alternate Interface zero... 66 | Determining device status... 67 | Device does not implement get_status, assuming appIDLE 68 | Device really in Run-Time Mode, send DFU detach request... 69 | Device will detach and reattach... 70 | ``` 71 | and then to show the available DFU alternate interface settings: 72 | 73 | ``` 74 | > dfu-util -lv 75 | dfu-util 0.11 76 | 77 | Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. 78 | Copyright 2010-2021 Tormod Volden and Stefan Schmidt 79 | This program is Free Software and has ABSOLUTELY NO WARRANTY 80 | Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ 81 | 82 | libusb version 1.0.24 (11584) 83 | Found DFU: [1d50:ffff] ver=0100, devnum=11, cfg=1, intf=0, path="20-4.4.4", alt=2, name="BOOT", serial="00" 84 | Found DFU: [1d50:ffff] ver=0100, devnum=11, cfg=1, intf=0, path="20-4.4.4", alt=1, name="RD ALL", serial="00" 85 | Found DFU: [1d50:ffff] ver=0100, devnum=11, cfg=1, intf=0, path="20-4.4.4", alt=0, name="RD/WR", serial="00" 86 | ``` 87 | Purpose of alternate interface settings is: 88 | 89 | * `alt=0` to read/write user image at 0x28000-0x4FFFF. 90 | * `alt=1` to read the whole 1Mbyte of flash memory. 91 | * `alt=2` to boot user image with a fake DFU read/write. 92 | 93 | For example to read whole flash memory: 94 | 95 | ``` 96 | > dfu-util -v -a 1 -U flash.bin 97 | dfu-util 0.11 98 | 99 | Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. 100 | Copyright 2010-2021 Tormod Volden and Stefan Schmidt 101 | This program is Free Software and has ABSOLUTELY NO WARRANTY 102 | Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ 103 | 104 | libusb version 1.0.24 (11584) 105 | Opening DFU capable USB device... 106 | Device ID 1d50:ffff 107 | Device DFU version 0110 108 | DFU attributes: (0x0f) bitCanDnload bitCanUpload bitManifestationTolerant bitWillDetach 109 | Detach timeout 1000 ms 110 | Claiming USB DFU Interface... 111 | Setting Alternate Interface #1 ... 112 | Determining device status... 113 | DFU state(2) = dfuIDLE, status(0) = No error condition is present 114 | DFU mode device DFU version 0110 115 | Device returned transfer size 256 116 | Copying data from DFU device to PC 117 | Upload [=========================] 100% 1048576 bytes 118 | Upload done. 119 | Received a total of 1048576 bytes 120 | ``` 121 | Or to write a new user image: 122 | 123 | ``` 124 | > dfu-util -v -a 0 -D ./user_image.bin 125 | dfu-util 0.11 126 | 127 | Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. 128 | Copyright 2010-2021 Tormod Volden and Stefan Schmidt 129 | This program is Free Software and has ABSOLUTELY NO WARRANTY 130 | Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ 131 | 132 | libusb version 1.0.24 (11584) 133 | dfu-util: Warning: Invalid DFU suffix signature 134 | dfu-util: A valid DFU suffix will be required in a future dfu-util release 135 | Opening DFU capable USB device... 136 | Device ID 1d50:ffff 137 | Device DFU version 0110 138 | DFU attributes: (0x0f) bitCanDnload bitCanUpload bitManifestationTolerant bitWillDetach 139 | Detach timeout 1000 ms 140 | Claiming USB DFU Interface... 141 | Setting Alternate Interface #0 ... 142 | Determining device status... 143 | DFU state(2) = dfuIDLE, status(0) = No error condition is present 144 | DFU mode device DFU version 0110 145 | Device returned transfer size 256 146 | Copying data from PC to DFU device 147 | Download [=========================] 100% 135178 bytes 148 | Download done. 149 | Sent a total of 135178 bytes 150 | DFU state(7) = dfuMANIFEST, status(0) = No error condition is present 151 | DFU state(2) = dfuIDLE, status(0) = No error condition is present 152 | Done! 153 | ``` 154 | And after that to boot the new user image: 155 | 156 | ``` 157 | > dfu-util -v -a 2 -U dummy.bin 158 | dfu-util 0.11 159 | 160 | Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. 161 | Copyright 2010-2021 Tormod Volden and Stefan Schmidt 162 | This program is Free Software and has ABSOLUTELY NO WARRANTY 163 | Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ 164 | 165 | libusb version 1.0.24 (11584) 166 | Opening DFU capable USB device... 167 | Device ID 1d50:ffff 168 | Device DFU version 0110 169 | DFU attributes: (0x0f) bitCanDnload bitCanUpload bitManifestationTolerant bitWillDetach 170 | Detach timeout 1000 ms 171 | Claiming USB DFU Interface... 172 | Setting Alternate Interface #2 ... 173 | Determining device status... 174 | DFU state(2) = dfuIDLE, status(0) = No error condition is present 175 | DFU mode device DFU version 0110 176 | Device returned transfer size 256 177 | Copying data from DFU device to PC 178 | Upload [ ] 0% 0 bytesdfu-util: 179 | Error during upload (LIBUSB_ERROR_PIPE) 180 | 181 | 182 | Failed. 183 | ``` 184 | The `LIBUSB_ERROR_PIPE` error is due to device reboot. 185 | 186 | 187 | ## `loopback` 188 | This is an example to test USB\_DFU functionality. 189 | At Run-time it presents a CDC/ACM function in loopback and a DFU function. 190 | 191 | The four DFU alternate interface settings allow to read/write a small RAM and to read/write the flash memory at address 0xB0000-EFFFF. 192 | 193 | 194 | -------------------------------------------------------------------------------- /examples/common/hdl/ice40/rom.v: -------------------------------------------------------------------------------- 1 | 2 | `define max(a,b)((a) > (b) ? (a) : (b)) 3 | `define min(a,b)((a) < (b) ? (a) : (b)) 4 | 5 | module rom 6 | #(parameter VECTOR_LENGTH = 'd512, 7 | parameter WORD_WIDTH = 'd16, // 8, 16 or 32 8 | parameter ADDR_WIDTH = ceil_log2(VECTOR_LENGTH)) 9 | ( 10 | output [WORD_WIDTH-1:0] data_o, 11 | input clk_i, 12 | input clke_i, 13 | input [ADDR_WIDTH-1:0] addr_i 14 | ); 15 | 16 | function integer ceil_log2; 17 | input [31:0] arg; 18 | integer i; 19 | begin 20 | ceil_log2 = 0; 21 | for (i = 0; i < 32; i = i + 1) begin 22 | if (arg > (1 << i)) 23 | ceil_log2 = ceil_log2 + 1; 24 | end 25 | end 26 | endfunction 27 | 28 | wire [31:0] rdata32; 29 | wire [7:0] addr; 30 | 31 | generate 32 | if (WORD_WIDTH == 'd8) begin : u_8bit 33 | reg byte_addr_q; 34 | 35 | assign data_o = byte_addr_q ? rdata32[15:8] : rdata32[7:0]; 36 | assign addr = addr_i[`min(8,ADDR_WIDTH-1):1]; 37 | 38 | always @(posedge clk_i) begin 39 | if (clke_i) 40 | byte_addr_q <= addr_i[0]; 41 | end 42 | end else if (WORD_WIDTH == 'd16) begin : u_16bit 43 | assign data_o = rdata32[15:0]; 44 | assign addr = addr_i[`min(7,ADDR_WIDTH-1):0]; 45 | end else begin : u_32bit 46 | assign data_o = rdata32; 47 | assign addr = addr_i[`min(7,ADDR_WIDTH-1):0]; 48 | end 49 | endgenerate 50 | 51 | localparam ROM_WORDS = (WORD_WIDTH == 'd32) ? 2 : 1; 52 | localparam ROM_BLOCKS = (((WORD_WIDTH == 'd8) ? (VECTOR_LENGTH+1)/2 : VECTOR_LENGTH)+255)/256; 53 | wire [16*ROM_BLOCKS*ROM_WORDS-1:0] rdata; 54 | wire [`max(ceil_log2(ROM_BLOCKS)-1, 0):0] block_addr; 55 | 56 | generate 57 | if (ROM_BLOCKS > 1) begin : u_multi_bank 58 | reg [ceil_log2(ROM_BLOCKS)-1:0] block_addr_q; 59 | 60 | assign block_addr = addr_i[ADDR_WIDTH-1 -:ceil_log2(ROM_BLOCKS)]; 61 | assign rdata32[15:0] = rdata[16*ROM_WORDS*block_addr_q +:16]; 62 | if (ROM_WORDS > 1) begin : u_high_word 63 | assign rdata32[31:16] = rdata[16*(ROM_WORDS*block_addr_q+1) +:16]; 64 | end 65 | 66 | always @(posedge clk_i) begin 67 | if (clke_i) 68 | block_addr_q <= block_addr; 69 | end 70 | end else begin : u_single_bank 71 | assign block_addr = 0; 72 | assign rdata32[15:0] = rdata[15:0]; 73 | if (ROM_WORDS > 1) begin : u_high_word 74 | assign rdata32[31:16] = rdata[31:16]; 75 | end 76 | end 77 | endgenerate 78 | 79 | localparam [256*16*2-1:0] ROM_DATA = {256'h6D331DDB26D153A5B677F5093BBB2DDF689DAC0074F3292285BEA438F37C2984, 80 | 256'h5537818752892D52892CC66E0799AFD3439EB6F21668948E6E7D38998BFDB692, 81 | 256'h012235F6270610D0670129736137B590494FFF2A11C294B22415529CB4E76DC1, 82 | 256'h1991AAE9DB1381A74C2505F0160D0426A7E0E3A1A18F18F73AE7E63FCB45E36D, 83 | 256'h8D508E74DF4C083652BF4BA8C8A9A103A9807CB69AAF546E3744DF9BB3DA4499, 84 | 256'hCCD2F056C832A3122E81F9D3EF6F6BC79B1E442FFF413C2A2468DEF0BFF3954B, 85 | 256'hF62F9CA07F8607AA3C9BD09B2F7ED8B0F084AC6E0873A14E36BD492B29EA1617, 86 | 256'h70BD1BE5E40980220D504634930E82ACE905A24DE8030FADF6AE572B69E7A6B0, 87 | 256'h2EB97F3B3CEC95526D43F131750ECCA56A389B00BEAA3E64B0525F450ACB164D, 88 | 256'h347C301CDB370650D88A2AEC52C14C9D9A0CE27FB988AD066D6DF60FDF3F7FB4, 89 | 256'h43C7E94CD1B7C9FECBA311F3A06C10D84CD13ADF67337DCDA8D0DE715987F3B3, 90 | 256'hDFDF779E14A1000A6E4DC1431CDDD932CF3D99E642AE2EF5CAE093C9F73D61AB, 91 | 256'h04091CA820D4B1774E22802335C2D1AAA44426CD5C2CF6D52FCF8DCE8B469C66, 92 | 256'hA03E404CC381CDA9DCC1A70BA0F3F067E22F65D4E456C6DC9E08E532D4CD7A7D, 93 | 256'hBC44068112661B60E9CA7768AD20D81FF9C769A60EEF63039E091DCAE008B745, 94 | 256'h28A87B0CF7112A239C329C5D04C6DC84C42ADB328B66203DB44B1324CE8C003A, 95 | 256'hD7A5C3CD0203DD451D4E48774153A7FAC62AAB526D6637A3A4E91D4211D72405, 96 | 256'hC91DC8CC90377F1EA3BD9DFD5B76EC44E3BE7C42DD912E60D7713513AD8904CB, 97 | 256'h0E7E3FD65E9FE9D4E09E2DF878ABCDD7958610730BD3C52DCEB19CCB365A1E7B, 98 | 256'h5C05AA6573A66EC30543476D4ED7AF7458CF1436A8FACD38D940D72460683ED3, 99 | 256'h82973E47B9E62E45A6D5A6EF61DDFD205D0B932CBEB0E4D75B9B5232355E5E79, 100 | 256'h555DC8BC5B111C1E6CA30C14C14E17FE3DB60C663AD22D7AD465955F2F541260, 101 | 256'h83007D7E943D305F62F1B974EE8545175DC423C95AE9A8D794568AF6B9809E4E, 102 | 256'hF594CE66FB6668C44BE805CC4CE3E24C0653429E0F4B4B283328034E2132BE6C, 103 | 256'h4CAE3CA135E4A1687C6867CF412EB915158990B50EA16A84B8D1698D763001BD, 104 | 256'hD3493CF28ADE5F98B7F21218171FF47E634EA49C4E491E7CFD67A5DC8FB2A378, 105 | 256'hCF1CE078B591D073D6A82ACE248A7F25BF035D2F71B5EB659A4F407E2D88E9CC, 106 | 256'h0CD51007D1C56720D8B4F5D58B6EFED77B9947109D85A7603021AC6633F83953, 107 | 256'h8B552F6D6227BF85C9E5031FE0139BD1F3B6EE57F9DF9B0FE61A10F529F9636C, 108 | 256'hE4D333CD6DE06FBAF6E0847725216D416357B51B9A09B47BB1B3817667708D93, 109 | 256'hD07F8C6DBD91B75A8C81BD4B1009248657FEA9EA0C88EA3AB5F7F9318920C642, 110 | 256'h6CA93E9696812BC756AA23ABA720A1B0F76A1F284C757BF364505334F670FF6B}; 111 | 112 | genvar i,j; 113 | 114 | generate 115 | for (i = 0; i < ROM_BLOCKS; i = i+1) begin : u_rom_blocks 116 | wire re; 117 | 118 | assign re = (i == block_addr) ? 1'b1 : 1'b0; 119 | 120 | for (j = 0; j < ROM_WORDS; j = j+1) begin : u_rom_words 121 | SB_RAM256x16 #(.INIT_0(ROM_DATA[256*((ROM_WORDS*(0+16*i)+j)%(2*16)) +:256]), 122 | .INIT_1(ROM_DATA[256*((ROM_WORDS*(1+16*i)+j)%(2*16)) +:256]), 123 | .INIT_2(ROM_DATA[256*((ROM_WORDS*(2+16*i)+j)%(2*16)) +:256]), 124 | .INIT_3(ROM_DATA[256*((ROM_WORDS*(3+16*i)+j)%(2*16)) +:256]), 125 | .INIT_4(ROM_DATA[256*((ROM_WORDS*(4+16*i)+j)%(2*16)) +:256]), 126 | .INIT_5(ROM_DATA[256*((ROM_WORDS*(5+16*i)+j)%(2*16)) +:256]), 127 | .INIT_6(ROM_DATA[256*((ROM_WORDS*(6+16*i)+j)%(2*16)) +:256]), 128 | .INIT_7(ROM_DATA[256*((ROM_WORDS*(7+16*i)+j)%(2*16)) +:256]), 129 | .INIT_8(ROM_DATA[256*((ROM_WORDS*(8+16*i)+j)%(2*16)) +:256]), 130 | .INIT_9(ROM_DATA[256*((ROM_WORDS*(9+16*i)+j)%(2*16)) +:256]), 131 | .INIT_A(ROM_DATA[256*((ROM_WORDS*(10+16*i)+j)%(2*16)) +:256]), 132 | .INIT_B(ROM_DATA[256*((ROM_WORDS*(11+16*i)+j)%(2*16)) +:256]), 133 | .INIT_C(ROM_DATA[256*((ROM_WORDS*(12+16*i)+j)%(2*16)) +:256]), 134 | .INIT_D(ROM_DATA[256*((ROM_WORDS*(13+16*i)+j)%(2*16)) +:256]), 135 | .INIT_E(ROM_DATA[256*((ROM_WORDS*(14+16*i)+j)%(2*16)) +:256]), 136 | .INIT_F(ROM_DATA[256*((ROM_WORDS*(15+16*i)+j)%(2*16)) +:256])) 137 | u_ram256x16 (.RDATA(rdata[16*(ROM_WORDS*i+j) +:16]), 138 | .RADDR(addr), 139 | .RCLK(clk_i), 140 | .RCLKE(clke_i), 141 | .RE(re), 142 | .WADDR(8'd0), 143 | .WCLK(1'b0), 144 | .WCLKE(1'b0), 145 | .WDATA(16'b0), 146 | .WE(1'b0), 147 | .MASK(16'b0)); 148 | end 149 | end 150 | endgenerate 151 | endmodule 152 | -------------------------------------------------------------------------------- /examples/common/hdl/ice40/ram.v: -------------------------------------------------------------------------------- 1 | 2 | `define max(a,b)((a) > (b) ? (a) : (b)) 3 | `define min(a,b)((a) < (b) ? (a) : (b)) 4 | 5 | module ram 6 | #(parameter VECTOR_LENGTH = 'd512, 7 | parameter WORD_WIDTH = 'd16, 8 | parameter ADDR_WIDTH = ceil_log2(VECTOR_LENGTH)) 9 | ( 10 | output [WORD_WIDTH-1:0] rdata_o, 11 | input clk_i, 12 | input clke_i, 13 | input we_i, 14 | input [ADDR_WIDTH-1:0] addr_i, 15 | input [WORD_WIDTH-1:0] mask_i, 16 | input [WORD_WIDTH-1:0] wdata_i 17 | ); 18 | 19 | function integer ceil_log2; 20 | input [31:0] arg; 21 | integer i; 22 | begin 23 | ceil_log2 = 0; 24 | for (i = 0; i < 32; i = i + 1) begin 25 | if (arg > (1 << i)) 26 | ceil_log2 = ceil_log2 + 1; 27 | end 28 | end 29 | endfunction 30 | 31 | wire [7:0] addr; 32 | wire [31:0] rdata32; 33 | wire [31:0] wdata32; 34 | wire [31:0] mask32; 35 | 36 | generate 37 | if (WORD_WIDTH == 'd8) begin : u_8bit 38 | reg byte_addr_q; 39 | 40 | assign rdata_o = byte_addr_q ? rdata32[15:8] : rdata32[7:0]; 41 | assign addr = addr_i[`min(8,ADDR_WIDTH-1):1]; 42 | assign wdata32 = {16'h0000, wdata_i, wdata_i}; 43 | assign mask32 = (addr_i[0] == 1'b0) ? {16'hFFFF, 8'hFF, mask_i} : {16'hFFFF, mask_i, 8'hFF}; 44 | 45 | always @(posedge clk_i) begin 46 | if (clke_i ==1'b1 && we_i == 1'b0) 47 | byte_addr_q <= addr_i[0]; 48 | end 49 | end else if (WORD_WIDTH == 'd16) begin : u_16bit 50 | assign rdata_o = rdata32[15:0]; 51 | assign addr = addr_i[`min(7,ADDR_WIDTH-1):0]; 52 | assign wdata32 = {16'h0000, wdata_i}; 53 | assign mask32 = {16'hFFFF, mask_i}; 54 | end else begin : u_32bit 55 | assign rdata_o = rdata32; 56 | assign addr = addr_i[`min(7,ADDR_WIDTH-1):0]; 57 | assign wdata32 = wdata_i; 58 | assign mask32 = mask_i; 59 | end 60 | endgenerate 61 | 62 | localparam RAM_WORDS = (WORD_WIDTH == 'd32) ? 2 : 1; 63 | localparam RAM_BLOCKS = (((WORD_WIDTH == 'd8) ? (VECTOR_LENGTH+1)/2 : VECTOR_LENGTH)+255)/256; 64 | wire [16*RAM_BLOCKS*RAM_WORDS-1:0] rdata; 65 | wire [`max(ceil_log2(RAM_BLOCKS)-1, 0):0] block_addr; 66 | 67 | generate 68 | if (RAM_BLOCKS > 1) begin : u_multi_bank 69 | reg [ceil_log2(RAM_BLOCKS)-1:0] block_addr_q; 70 | 71 | assign block_addr = addr_i[ADDR_WIDTH-1 -:ceil_log2(RAM_BLOCKS)]; 72 | assign rdata32[15:0] = rdata[16*RAM_WORDS*block_addr_q +:16]; 73 | if (RAM_WORDS > 1) begin : u_high_word 74 | assign rdata32[31:16] = rdata[16*(RAM_WORDS*block_addr_q+1) +:16]; 75 | end 76 | 77 | always @(posedge clk_i) begin 78 | if (clke_i == 1'b1 && we_i == 1'b0) 79 | block_addr_q <= block_addr; 80 | end 81 | end else begin : u_single_bank 82 | assign block_addr = 0; 83 | assign rdata32[15:0] = rdata[15:0]; 84 | if (RAM_WORDS > 1) begin : u_high_word 85 | assign rdata32[31:16] = rdata[31:16]; 86 | end 87 | end 88 | endgenerate 89 | 90 | localparam [256*16*2-1:0] RAM_DATA = {256'hC1D4816ED2646D089AE661690164DABE1B873D7F8EC3AF7D8C7DA5C43F9743CD, 91 | 256'hC2FA7C36540E7700BDAC2AFFF42F77777F077A45A204B6274AE8965088EAA7DE, 92 | 256'h83863B4C3D0D002FEDA8C8806A7BC889D79C5AAE9736B416E9D6DA525773D584, 93 | 256'h4A0B90E9CDA6050D51719A2267926CBA03855F698F55CA97178015499BF1B937, 94 | 256'h96CE2E60E1513C6FF180F8F9311D6130777B3F337A0AEC075E278893A872436F, 95 | 256'hB0F7D959D47313F7C2130EDC97E63C4FCAE3CAA66C823BC63EA4F7684CF29649, 96 | 256'hDA32ACFEF1B1AF8C261DA967BB797182429BF220CF49C388C903BA1A36D3C986, 97 | 256'h3B5D98A13C514ECD18A7BA4FB34891B3309FBACE1907F5A134247D57D90A325B, 98 | 256'h3CF03A082F42F0B4D4F6BF9D0A2D6EB16E2BA8BC4E943C31C31D73120C1975D9, 99 | 256'hB32852C021BCD1A3DD59887C4C6E49435C5C08180B267667F7FBD044DE82BF74, 100 | 256'h78839C7F82B455D8FF1BCC32EE5FE613E221369A55CEE4B9391E1F5B7805FBF8, 101 | 256'h61103711B59FACD8277E00A69ADD8A95C9A1F57D36A338268429586157D6D3FC, 102 | 256'hF3D27A5C509539F960CA39F2071F7DB19227CAB90A66D0EC4A5A9BFE1B1C3D62, 103 | 256'h3627910C12045120AAEBEB2614142A709F85B4510BAE7A7DA7A9A098E1D74564, 104 | 256'hAC0890217D4DE966E44E68D1B36111C8D35D87573182754ABF29B7BFFBB8555D, 105 | 256'h4964D879A2D4826B1F68D49D1EF07EDF7DE586970A1304E902EF7754D722C8FF, 106 | 256'hABAC0E61FE578C814D146F0F2707AFE0EE2A22EB0FE41881DD80BE2727E1C9F6, 107 | 256'h5A5E34C6B6454ACA633B8730DACB19A3DD74E8B93672CC2E17BBBBC583EB66B8, 108 | 256'h08C7DEA00021F84186CA1F14329D83CFAF6ABE1015AAD6BE901C534EDAD49EB4, 109 | 256'hE2C09734B901B715DF59B2AC37504F9113FE7166FE00223DD3579BD73AB3817C, 110 | 256'hA6B0E6F8E6375000F84D79DB4613BD1A48872F850CF87FAAC7DD664922ACEE8A, 111 | 256'h4A74546376D57AD2DAD89AD100073076BED6D224292456E276EE3D95FA052B51, 112 | 256'hCB34EC22270804CEEAE6F1B8667B847651945A69658E758377A37BFF854D7C3F, 113 | 256'h2F6FA55973278DC04BF19C26A2DFE912617FEACC8CE3F098099CAF98980E696C, 114 | 256'h7BD8B21B22E37D4A15AAA76D6541C7932ADDD3ADD2A1E0C609FD8B57EE729721, 115 | 256'h60EFC3C3C433737B47CDDF1E4BA9849FF6601365A7E6E7752A7CEF56333792EB, 116 | 256'h613698187C59A3765CC248F5B5DF943B20097B779708D12A7E6723AAE792DE14, 117 | 256'h0B0C6F3F9D4A10A8E6FB097C658C11F68C4C26B1E05F534AA418BED25324A246, 118 | 256'h1ED9655323CE82A8E31812001FFE6AA0E8BB562B81B4E5CCB7EAFF0817ADB955, 119 | 256'h4D43BF34C0A091F49F6410926E5CA9FF116D5AE344DC0362B23E788FE20D8D06, 120 | 256'hDB06F2655983015722DF8BBC539FBD0430A921207E035D10CDD029D72DD727F7, 121 | 256'h440A49737ED1A47239E2824653E8CEF7544C19B1B04F0B19AABAA3B447985F96}; 122 | 123 | genvar i,j; 124 | 125 | generate 126 | for (i = 0; i < RAM_BLOCKS; i = i+1) begin : u_ram_blocks 127 | wire re, we; 128 | 129 | assign re = (i == block_addr && we_i == 1'b0) ? 1'b1 : 1'b0; 130 | assign we = (i == block_addr && we_i == 1'b1) ? 1'b1 : 1'b0; 131 | 132 | for (j = 0; j < RAM_WORDS; j = j+1) begin : u_ram_words 133 | SB_RAM256x16 #(.INIT_0(RAM_DATA[256*((RAM_WORDS*(0+16*i)+j)%(2*16)) +:256]), 134 | .INIT_1(RAM_DATA[256*((RAM_WORDS*(1+16*i)+j)%(2*16)) +:256]), 135 | .INIT_2(RAM_DATA[256*((RAM_WORDS*(2+16*i)+j)%(2*16)) +:256]), 136 | .INIT_3(RAM_DATA[256*((RAM_WORDS*(3+16*i)+j)%(2*16)) +:256]), 137 | .INIT_4(RAM_DATA[256*((RAM_WORDS*(4+16*i)+j)%(2*16)) +:256]), 138 | .INIT_5(RAM_DATA[256*((RAM_WORDS*(5+16*i)+j)%(2*16)) +:256]), 139 | .INIT_6(RAM_DATA[256*((RAM_WORDS*(6+16*i)+j)%(2*16)) +:256]), 140 | .INIT_7(RAM_DATA[256*((RAM_WORDS*(7+16*i)+j)%(2*16)) +:256]), 141 | .INIT_8(RAM_DATA[256*((RAM_WORDS*(8+16*i)+j)%(2*16)) +:256]), 142 | .INIT_9(RAM_DATA[256*((RAM_WORDS*(9+16*i)+j)%(2*16)) +:256]), 143 | .INIT_A(RAM_DATA[256*((RAM_WORDS*(10+16*i)+j)%(2*16)) +:256]), 144 | .INIT_B(RAM_DATA[256*((RAM_WORDS*(11+16*i)+j)%(2*16)) +:256]), 145 | .INIT_C(RAM_DATA[256*((RAM_WORDS*(12+16*i)+j)%(2*16)) +:256]), 146 | .INIT_D(RAM_DATA[256*((RAM_WORDS*(13+16*i)+j)%(2*16)) +:256]), 147 | .INIT_E(RAM_DATA[256*((RAM_WORDS*(14+16*i)+j)%(2*16)) +:256]), 148 | .INIT_F(RAM_DATA[256*((RAM_WORDS*(15+16*i)+j)%(2*16)) +:256])) 149 | u_ram256x16 (.RDATA(rdata[16*(RAM_WORDS*i+j) +:16]), 150 | .RADDR(addr), 151 | .RCLK(clk_i), 152 | .RCLKE(clke_i), 153 | .RE(re), 154 | .WADDR(addr), 155 | .WCLK(clk_i), 156 | .WCLKE(clke_i), 157 | .WDATA(wdata32[16*j +:16]), 158 | .WE(we), 159 | .MASK(mask32[16*j +:16])); 160 | end 161 | end 162 | endgenerate 163 | endmodule 164 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/hdl/bootloader/bootloader_defs.v: -------------------------------------------------------------------------------- 1 | 2 | localparam [15:0] TRANSFER_SIZE = 256; 3 | localparam [15:0] DETACH_TIMEOUT = 1000; 4 | localparam ALT = 3; 5 | 6 | localparam FIRST_ALT_STRING = 'd3; // First Alternate Setting String 7 | // DFU Mode Configuration Descriptor (in reverse order) 8 | localparam DCDL = 'h9+'h9*ALT+'h9; // DFU_CONF_DESCR Length 9 | localparam [8*DCDL-1:0] DFU_CONF_DESCR = { 10 | // Standard Configuration Descriptor, USB1.0 11 | 8'h09, // bLength 12 | 8'h02, // bDescriptorType (CONFIGURATION) 13 | DCDL[7:0], // wTotalLength[0] 14 | DCDL[15:8], // wTotalLength[1] 15 | 8'h01, // bNumInterfaces 16 | 8'h01, // bConfigurationValue 17 | 8'h00, // iConfiguration (no string) 18 | 8'h80, // bmAttributes (bus powered, no remote wakeup) 19 | 8'h32, // bMaxPower (100mA) 20 | 21 | // DFU Interface Descriptor, DFU1.1 4.2.3, page 15-16, Table 4-4 22 | 8'h09, // bLength 23 | 8'h04, // bDescriptorType (INTERFACE) 24 | 8'h00, // bInterfaceNumber 25 | 8'h00, // bAlternateSetting 26 | 8'h00, // bNumEndpoints 27 | 8'hFE, // bInterfaceClass (Application Specific) 28 | 8'h01, // bInterfaceSubClass (Device Firmware Upgrade) 29 | 8'h02, // bInterfaceProtocol (DFU Mode) 30 | 8'h00+FIRST_ALT_STRING[7:0], // iInterface 31 | 32 | // DFU Interface Descriptor, DFU1.1 4.2.3, page 15-16, Table 4-4 33 | 8'h09, // bLength 34 | 8'h04, // bDescriptorType (INTERFACE) 35 | 8'h00, // bInterfaceNumber 36 | 8'h01, // bAlternateSetting 37 | 8'h00, // bNumEndpoints 38 | 8'hFE, // bInterfaceClass (Application Specific) 39 | 8'h01, // bInterfaceSubClass (Device Firmware Upgrade) 40 | 8'h02, // bInterfaceProtocol (DFU Mode) 41 | 8'h01+FIRST_ALT_STRING[7:0], // iInterface 42 | 43 | // DFU Interface Descriptor, DFU1.1 4.2.3, page 15-16, Table 4-4 44 | 8'h09, // bLength 45 | 8'h04, // bDescriptorType (INTERFACE) 46 | 8'h00, // bInterfaceNumber 47 | 8'h02, // bAlternateSetting 48 | 8'h00, // bNumEndpoints 49 | 8'hFE, // bInterfaceClass (Application Specific) 50 | 8'h01, // bInterfaceSubClass (Device Firmware Upgrade) 51 | 8'h02, // bInterfaceProtocol (DFU Mode) 52 | 8'h02+FIRST_ALT_STRING[7:0], // iInterface 53 | 54 | // DFU Functional Descriptor, DFU1.1 4.1.3, page 13-14, Table 4-2 55 | 8'h09, // bLength 56 | 8'h21, // bDescriptorType (DFU FUNCTIONAL) 57 | 8'h0F, // bmAttributes (bitWillDetach, bitManifestationTolerant, bitCanUpload, bitCanDnload) 58 | DETACH_TIMEOUT[7:0], // wDetachTimeOut[0] 59 | DETACH_TIMEOUT[15:8], // wDetachTimeOut[1] 60 | TRANSFER_SIZE[7:0], // wTransferSize[0] 61 | TRANSFER_SIZE[15:8], // wTransferSize[1] 62 | 8'h10, // bcdDFUVersion[0] 63 | 8'h01 // bcdDFUVersion[1] (1.10) 64 | }; 65 | 66 | // String Descriptor 67 | localparam STR01L = 2*2+2; // STRING_DESCR_01 Length 68 | localparam [8*STR01L-1:0] STRING_DESCR_01 = { 69 | // UNICODE String Descriptor, USB2.0 9.6.7, page 273-274, Table 9-16 70 | STR01L[7:0], // bLength 71 | 8'h03, // bDescriptorType (STRING) 72 | "0", // wString[0] 73 | 8'h00, // wString[1] 74 | "0", // wString[0] 75 | 8'h00 // wString[1] 76 | }; 77 | 78 | // String Descriptor 79 | localparam STR02L = 2*7+2; // STRING_DESCR_02 Length 80 | localparam [8*STR02L-1:0] STRING_DESCR_02 = { 81 | // UNICODE String Descriptor, USB2.0 9.6.7, page 273-274, Table 9-16 82 | STR02L[7:0], // bLength 83 | 8'h03, // bDescriptorType (STRING) 84 | "U", // wString[0] 85 | 8'h00, // wString[1] 86 | "S", // wString[0] 87 | 8'h00, // wString[1] 88 | "B", // wString[0] 89 | 8'h00, // wString[1] 90 | "_", // wString[0] 91 | 8'h00, // wString[1] 92 | "D", // wString[0] 93 | 8'h00, // wString[1] 94 | "F", // wString[0] 95 | 8'h00, // wString[1] 96 | "U", // wString[0] 97 | 8'h00 // wString[1] 98 | }; 99 | 100 | // String Descriptor 101 | localparam STR03L = 2*5+2; // STRING_DESCR_03 Length 102 | localparam [8*STR03L-1:0] STRING_DESCR_03 = { 103 | // UNICODE String Descriptor, USB2.0 9.6.7, page 273-274, Table 9-16 104 | STR03L[7:0], // bLength 105 | 8'h03, // bDescriptorType (STRING) 106 | "R", // wString[0] 107 | 8'h00, // wString[1] 108 | "D", // wString[0] 109 | 8'h00, // wString[1] 110 | "/", // wString[0] 111 | 8'h00, // wString[1] 112 | "W", // wString[0] 113 | 8'h00, // wString[1] 114 | "R", // wString[0] 115 | 8'h00 // wString[1] 116 | }; 117 | 118 | // String Descriptor 119 | localparam STR04L = 2*6+2; // STRING_DESCR_04 Length 120 | localparam [8*STR04L-1:0] STRING_DESCR_04 = { 121 | // UNICODE String Descriptor, USB2.0 9.6.7, page 273-274, Table 9-16 122 | STR04L[7:0], // bLength 123 | 8'h03, // bDescriptorType (STRING) 124 | "R", // wString[0] 125 | 8'h00, // wString[1] 126 | "D", // wString[0] 127 | 8'h00, // wString[1] 128 | " ", // wString[0] 129 | 8'h00, // wString[1] 130 | "A", // wString[0] 131 | 8'h00, // wString[1] 132 | "L", // wString[0] 133 | 8'h00, // wString[1] 134 | "L", // wString[0] 135 | 8'h00 // wString[1] 136 | }; 137 | 138 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/hdl/loopback/loopback_defs.v: -------------------------------------------------------------------------------- 1 | 2 | localparam [15:0] TRANSFER_SIZE = 256; 3 | localparam [15:0] DETACH_TIMEOUT = 1000; 4 | localparam ALT = 4; 5 | 6 | localparam FIRST_ALT_STRING = 'd3; // First Alternate Setting String 7 | // DFU Mode Configuration Descriptor (in reverse order) 8 | localparam DCDL = 'h9+'h9*ALT+'h9; // DFU_CONF_DESCR Length 9 | localparam [8*DCDL-1:0] DFU_CONF_DESCR = { 10 | // Standard Configuration Descriptor, USB1.0 11 | 8'h09, // bLength 12 | 8'h02, // bDescriptorType (CONFIGURATION) 13 | DCDL[7:0], // wTotalLength[0] 14 | DCDL[15:8], // wTotalLength[1] 15 | 8'h01, // bNumInterfaces 16 | 8'h01, // bConfigurationValue 17 | 8'h00, // iConfiguration (no string) 18 | 8'h80, // bmAttributes (bus powered, no remote wakeup) 19 | 8'h32, // bMaxPower (100mA) 20 | 21 | // DFU Interface Descriptor, DFU1.1 4.2.3, page 15-16, Table 4-4 22 | 8'h09, // bLength 23 | 8'h04, // bDescriptorType (INTERFACE) 24 | 8'h00, // bInterfaceNumber 25 | 8'h00, // bAlternateSetting 26 | 8'h00, // bNumEndpoints 27 | 8'hFE, // bInterfaceClass (Application Specific) 28 | 8'h01, // bInterfaceSubClass (Device Firmware Upgrade) 29 | 8'h02, // bInterfaceProtocol (DFU Mode) 30 | 8'h00+FIRST_ALT_STRING[7:0], // iInterface 31 | 32 | // DFU Interface Descriptor, DFU1.1 4.2.3, page 15-16, Table 4-4 33 | 8'h09, // bLength 34 | 8'h04, // bDescriptorType (INTERFACE) 35 | 8'h00, // bInterfaceNumber 36 | 8'h01, // bAlternateSetting 37 | 8'h00, // bNumEndpoints 38 | 8'hFE, // bInterfaceClass (Application Specific) 39 | 8'h01, // bInterfaceSubClass (Device Firmware Upgrade) 40 | 8'h02, // bInterfaceProtocol (DFU Mode) 41 | 8'h01+FIRST_ALT_STRING[7:0], // iInterface 42 | 43 | // DFU Interface Descriptor, DFU1.1 4.2.3, page 15-16, Table 4-4 44 | 8'h09, // bLength 45 | 8'h04, // bDescriptorType (INTERFACE) 46 | 8'h00, // bInterfaceNumber 47 | 8'h02, // bAlternateSetting 48 | 8'h00, // bNumEndpoints 49 | 8'hFE, // bInterfaceClass (Application Specific) 50 | 8'h01, // bInterfaceSubClass (Device Firmware Upgrade) 51 | 8'h02, // bInterfaceProtocol (DFU Mode) 52 | 8'h02+FIRST_ALT_STRING[7:0], // iInterface 53 | 54 | // DFU Interface Descriptor, DFU1.1 4.2.3, page 15-16, Table 4-4 55 | 8'h09, // bLength 56 | 8'h04, // bDescriptorType (INTERFACE) 57 | 8'h00, // bInterfaceNumber 58 | 8'h03, // bAlternateSetting 59 | 8'h00, // bNumEndpoints 60 | 8'hFE, // bInterfaceClass (Application Specific) 61 | 8'h01, // bInterfaceSubClass (Device Firmware Upgrade) 62 | 8'h02, // bInterfaceProtocol (DFU Mode) 63 | 8'h03+FIRST_ALT_STRING[7:0], // iInterface 64 | 65 | // DFU Functional Descriptor, DFU1.1 4.1.3, page 13-14, Table 4-2 66 | 8'h09, // bLength 67 | 8'h21, // bDescriptorType (DFU FUNCTIONAL) 68 | 8'h0F, // bmAttributes (bitWillDetach, bitManifestationTolerant, bitCanUpload, bitCanDnload) 69 | DETACH_TIMEOUT[7:0], // wDetachTimeOut[0] 70 | DETACH_TIMEOUT[15:8], // wDetachTimeOut[1] 71 | TRANSFER_SIZE[7:0], // wTransferSize[0] 72 | TRANSFER_SIZE[15:8], // wTransferSize[1] 73 | 8'h10, // bcdDFUVersion[0] 74 | 8'h01 // bcdDFUVersion[1] (1.10) 75 | }; 76 | 77 | // String Descriptor 78 | localparam STR01L = 2*3+2; // STRING_DESCR_01 Length 79 | localparam [8*STR01L-1:0] STRING_DESCR_01 = { 80 | // UNICODE String Descriptor, USB2.0 9.6.7, page 273-274, Table 9-16 81 | STR01L[7:0], // bLength 82 | 8'h03, // bDescriptorType (STRING) 83 | "I", // wString[0] 84 | 8'h00, // wString[1] 85 | "D", // wString[0] 86 | 8'h00, // wString[1] 87 | "0", // wString[0] 88 | 8'h00 // wString[1] 89 | }; 90 | 91 | // String Descriptor 92 | localparam STR02L = 2*7+2; // STRING_DESCR_02 Length 93 | localparam [8*STR02L-1:0] STRING_DESCR_02 = { 94 | // UNICODE String Descriptor, USB2.0 9.6.7, page 273-274, Table 9-16 95 | STR02L[7:0], // bLength 96 | 8'h03, // bDescriptorType (STRING) 97 | "U", // wString[0] 98 | 8'h00, // wString[1] 99 | "S", // wString[0] 100 | 8'h00, // wString[1] 101 | "B", // wString[0] 102 | 8'h00, // wString[1] 103 | "_", // wString[0] 104 | 8'h00, // wString[1] 105 | "D", // wString[0] 106 | 8'h00, // wString[1] 107 | "F", // wString[0] 108 | 8'h00, // wString[1] 109 | "U", // wString[0] 110 | 8'h00 // wString[1] 111 | }; 112 | 113 | // String Descriptor 114 | localparam STR03L = 2*2+2; // STRING_DESCR_03 Length 115 | localparam [8*STR03L-1:0] STRING_DESCR_03 = { 116 | // UNICODE String Descriptor, USB2.0 9.6.7, page 273-274, Table 9-16 117 | STR03L[7:0], // bLength 118 | 8'h03, // bDescriptorType (STRING) 119 | "A", // wString[0] 120 | 8'h00, // wString[1] 121 | "0", // wString[0] 122 | 8'h00 // wString[1] 123 | }; 124 | 125 | // String Descriptor 126 | localparam STR04L = 2*2+2; // STRING_DESCR_04 Length 127 | localparam [8*STR04L-1:0] STRING_DESCR_04 = { 128 | // UNICODE String Descriptor, USB2.0 9.6.7, page 273-274, Table 9-16 129 | STR04L[7:0], // bLength 130 | 8'h03, // bDescriptorType (STRING) 131 | "B", // wString[0] 132 | 8'h00, // wString[1] 133 | "1", // wString[0] 134 | 8'h00 // wString[1] 135 | }; 136 | 137 | -------------------------------------------------------------------------------- /examples/TinyFPGA-BX/hdl/loopback/loopback.v: -------------------------------------------------------------------------------- 1 | 2 | module loopback 3 | ( 4 | input clk, // 16MHz Clock 5 | output led, // User LED ON=1, OFF=0 6 | inout usb_p, // USB+ 7 | inout usb_n, // USB- 8 | output usb_pu, // USB 1.5kOhm Pullup EN 9 | output sck, 10 | output ss, 11 | output sdo, 12 | input sdi 13 | ); 14 | 15 | localparam CHANNELS = 'd1; 16 | localparam BIT_SAMPLES = 'd4; 17 | localparam [6:0] DIVF = 12*BIT_SAMPLES-1; 18 | localparam TRANSFER_SIZE = 'd256; 19 | localparam POLLTIMEOUT = 'd10; // ms 20 | localparam MS20 = 1; 21 | localparam WCID = 1; 22 | 23 | wire clk_pll; 24 | wire clk_prescaler; 25 | wire clk_usb; 26 | wire clk_app; 27 | wire clk_div2; 28 | wire clk_div4; 29 | wire clk_div8; 30 | wire clk_div16; 31 | wire lock; 32 | wire dp_pu; 33 | wire dp_rx; 34 | wire dn_rx; 35 | wire dp_tx; 36 | wire dn_tx; 37 | wire tx_en; 38 | wire [8*CHANNELS-1:0] out_data; 39 | wire [CHANNELS-1:0] out_valid; 40 | wire [CHANNELS-1:0] in_ready; 41 | wire [7:0] in_data; 42 | wire in_valid; 43 | wire out_ready; 44 | wire [2:0] dfu_alt; 45 | wire dfu_out_en; 46 | wire dfu_in_en; 47 | wire [7:0] dfu_out_data; 48 | wire dfu_out_valid; 49 | wire dfu_in_ready; 50 | wire [7:0] dfu_in_data; 51 | wire dfu_in_valid; 52 | wire dfu_out_ready; 53 | wire dfu_clear_status; 54 | wire dfu_busy; 55 | wire [3:0] dfu_status; 56 | wire [10:0] frame; 57 | wire configured; 58 | wire dfu_mode; 59 | 60 | localparam CONF = 3; 61 | localparam [2:0] DIVQ = 62 | (CONF == 0) ? 3'd2 : // 192MHz 63 | (CONF == 1) ? 3'd4 : // 48MHz 64 | (CONF == 2) ? 3'd4 : // 48MHz 65 | (CONF == 3) ? 3'd4 : // 48MHz 66 | 3'd4; // 48MHz 67 | localparam APP_CLK_FREQ = 68 | (CONF == 0) ? 192 : // 192MHz 69 | (CONF == 1) ? 12 : // 12MHz 70 | (CONF == 2) ? 2 : // 2MHz 71 | (CONF == 3) ? 16 : // 16MHz 72 | 48; // 48MHz 73 | localparam USE_APP_CLK = 74 | (CONF == 0) ? 1 : 75 | (CONF == 1) ? 1 : 76 | (CONF == 2) ? 1 : 77 | (CONF == 3) ? 1 : 78 | 0; 79 | 80 | generate 81 | if (CONF == 0) begin : u_conf_0 82 | assign clk_prescaler = clk_pll; // 192MHz 83 | assign clk_app = clk_pll; 84 | assign clk_usb = clk_div4; // 48MHz 85 | end else if (CONF == 1) begin : u_conf_1 86 | assign clk_prescaler = clk_pll; // 48MHz 87 | assign clk_app = clk_div4; // 12MHz 88 | assign clk_usb = clk_pll; 89 | end else if (CONF == 2) begin : u_conf_2 90 | assign clk_prescaler = clk; // 16MHz 91 | assign clk_app = clk_div8; // 2MHz 92 | assign clk_usb = clk_pll; 93 | end else if (CONF == 3) begin : u_conf_3 94 | assign clk_prescaler = 1'b0; // Not used 95 | assign clk_app = clk; // 16MHz 96 | assign clk_usb = clk_pll; 97 | end else begin : u_conf_4 98 | assign clk_prescaler = 1'b0; // Not used 99 | assign clk_app = clk_pll; // 48MHz 100 | assign clk_usb = clk_pll; 101 | end 102 | endgenerate 103 | 104 | assign led = (configured) ? ((dfu_mode) ? frame[8] : frame[9]) : ~&frame[4:3]; 105 | 106 | // if FEEDBACK_PATH = SIMPLE: 107 | // clk_freq = (ref_freq * (DIVF + 1)) / (2**DIVQ * (DIVR + 1)); 108 | SB_PLL40_CORE #(.DIVR(4'd0), 109 | .DIVF(DIVF), 110 | .DIVQ(DIVQ), 111 | .FILTER_RANGE(3'b001), 112 | .FEEDBACK_PATH("SIMPLE"), 113 | .DELAY_ADJUSTMENT_MODE_FEEDBACK("FIXED"), 114 | .FDA_FEEDBACK(4'b0000), 115 | .DELAY_ADJUSTMENT_MODE_RELATIVE("FIXED"), 116 | .FDA_RELATIVE(4'b0000), 117 | .SHIFTREG_DIV_MODE(2'b00), 118 | .PLLOUT_SELECT("GENCLK"), 119 | .ENABLE_ICEGATE(1'b0)) 120 | u_pll (.REFERENCECLK(clk), // 16MHz 121 | .PLLOUTCORE(), 122 | .PLLOUTGLOBAL(clk_pll), 123 | .EXTFEEDBACK(1'b0), 124 | .DYNAMICDELAY(8'd0), 125 | .LOCK(lock), 126 | .BYPASS(1'b0), 127 | .RESETB(1'b1), 128 | .SDI(1'b0), 129 | .SDO(), 130 | .SCLK(1'b0), 131 | .LATCHINPUTVALUE(1'b1)); 132 | 133 | prescaler u_prescaler (.clk_i(clk_prescaler), 134 | .rstn_i(lock), 135 | .clk_div2_o(clk_div2), 136 | .clk_div4_o(clk_div4), 137 | .clk_div8_o(clk_div8), 138 | .clk_div16_o(clk_div16)); 139 | 140 | dfu_app #(.CLK_PERIODS_PER_US(APP_CLK_FREQ)) 141 | u_dfu_app (.clk_i(clk_app), 142 | .rstn_i(lock), 143 | .dfu_alt_i(dfu_alt), 144 | .dfu_out_en_i(dfu_out_en), 145 | .dfu_in_en_i(dfu_in_en), 146 | .dfu_out_data_i(dfu_out_data), 147 | .dfu_out_valid_i(dfu_out_valid), 148 | .dfu_out_ready_o(dfu_out_ready), 149 | .dfu_in_data_o(dfu_in_data), 150 | .dfu_in_valid_o(dfu_in_valid), 151 | .dfu_in_ready_i(dfu_in_ready), 152 | .dfu_clear_status_i(dfu_clear_status), 153 | .dfu_busy_o(dfu_busy), 154 | .dfu_status_o(dfu_status), 155 | .sck_o(sck), 156 | .csn_o(ss), 157 | .mosi_o(sdo), 158 | .miso_i(sdi)); 159 | 160 | usb_dfu #(.VENDORID(16'h1D50), 161 | .PRODUCTID(16'h6130), 162 | .CHANNELS(CHANNELS), 163 | .RTI_STRING("USB_DFU"), 164 | .SN_STRING("ID0"), 165 | .ALT_STRINGS("A0\nB1\nC2\nD3"), 166 | .TRANSFER_SIZE(TRANSFER_SIZE), 167 | .POLLTIMEOUT(POLLTIMEOUT), 168 | .MS20(MS20), 169 | .WCID(WCID), 170 | .MAXPACKETSIZE('d8), 171 | .BIT_SAMPLES(BIT_SAMPLES), 172 | .USE_APP_CLK(USE_APP_CLK), 173 | .APP_CLK_FREQ(APP_CLK_FREQ)) 174 | u_usb_dfu (.frame_o(frame), 175 | .configured_o(configured), 176 | .app_clk_i(clk_app), 177 | .clk_i(clk_usb), 178 | .rstn_i(lock), 179 | .out_ready_i(in_ready), 180 | .in_data_i(out_data), 181 | .in_valid_i(out_valid), 182 | .dp_rx_i(dp_rx), 183 | .dn_rx_i(dn_rx), 184 | .out_data_o(out_data), 185 | .out_valid_o(out_valid), 186 | .in_ready_o(in_ready), 187 | .dfu_mode_o(dfu_mode), 188 | .dfu_alt_o(dfu_alt), 189 | .dfu_out_en_o(dfu_out_en), 190 | .dfu_in_en_o(dfu_in_en), 191 | .dfu_out_data_o(dfu_out_data), 192 | .dfu_out_valid_o(dfu_out_valid), 193 | .dfu_out_ready_i(dfu_out_ready), 194 | .dfu_in_data_i(dfu_in_data), 195 | .dfu_in_valid_i(dfu_in_valid), 196 | .dfu_in_ready_o(dfu_in_ready), 197 | .dfu_clear_status_o(dfu_clear_status), 198 | .dfu_blocknum_o(), 199 | .dfu_busy_i(dfu_busy), 200 | .dfu_status_i(dfu_status), 201 | .dp_pu_o(dp_pu), 202 | .tx_en_o(tx_en), 203 | .dp_tx_o(dp_tx), 204 | .dn_tx_o(dn_tx)); 205 | 206 | SB_IO #(.PIN_TYPE(6'b101001), 207 | .PULLUP(1'b0)) 208 | u_usb_p (.PACKAGE_PIN(usb_p), 209 | .OUTPUT_ENABLE(tx_en), 210 | .D_OUT_0(dp_tx), 211 | .D_IN_0(dp_rx), 212 | .D_OUT_1(1'b0), 213 | .D_IN_1(), 214 | .CLOCK_ENABLE(1'b0), 215 | .LATCH_INPUT_VALUE(1'b0), 216 | .INPUT_CLK(1'b0), 217 | .OUTPUT_CLK(1'b0)); 218 | 219 | SB_IO #(.PIN_TYPE(6'b101001), 220 | .PULLUP(1'b0)) 221 | u_usb_n (.PACKAGE_PIN(usb_n), 222 | .OUTPUT_ENABLE(tx_en), 223 | .D_OUT_0(dn_tx), 224 | .D_IN_0(dn_rx), 225 | .D_OUT_1(1'b0), 226 | .D_IN_1(), 227 | .CLOCK_ENABLE(1'b0), 228 | .LATCH_INPUT_VALUE(1'b0), 229 | .INPUT_CLK(1'b0), 230 | .OUTPUT_CLK(1'b0)); 231 | 232 | // drive usb_pu to 3.3V or to high impedance 233 | SB_IO #(.PIN_TYPE(6'b101001), 234 | .PULLUP(1'b0)) 235 | u_usb_pu (.PACKAGE_PIN(usb_pu), 236 | .OUTPUT_ENABLE(dp_pu), 237 | .D_OUT_0(1'b1), 238 | .D_IN_0(), 239 | .D_OUT_1(1'b0), 240 | .D_IN_1(), 241 | .CLOCK_ENABLE(1'b0), 242 | .LATCH_INPUT_VALUE(1'b0), 243 | .INPUT_CLK(1'b0), 244 | .OUTPUT_CLK(1'b0)); 245 | 246 | endmodule 247 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # USB\_DFU verilog module 2 | 3 | USB\_DFU is a Verilog implementation of the USB Device Class Specification for Device Firmware Upgrade (DFU), version 1.1. 4 | 5 | There are two functional device modes: 6 | 7 | * Run-time. The device starts in this mode and implements the primary CDC/ACM function and a secondary DFU function that allows switching to DFU Mode through the only available DFU\_DETACH class request. 8 | * DFU Mode. The device implements only the DFU function with all its class requests but the DFU\_DETACH one. 9 | 10 | Windows 10/11, macOS, and Linux provide built-in drivers for CDC/ACM and DFU functions. These OSs automatically recognize them. Only Linux requires administrative intervention to grant permissions for a user account to access USB peripherals. DFU function can be accessed by using [`dfu-util`](https://dfu-util.sourceforge.net). 11 | 12 | USB\_DFU is derived from [USB\_CDC](https://github.com/ulixxe/usb_cdc) by adding the DFU function. 13 | 14 | 15 | ## Applications 16 | * Flash programming and RAM read/write capability for microcontrollers and soft cores. USB\_DFU takes little gate resources and no memories, leaving them for the CPU. 17 | * Bootloaders. See the `bootloader` example for completely replacing the original TinyFPGA bootloader with one fully compatible with the `tinyprog` programmer and with DFU capability added. 18 | * Etc, it is up to your imagination. 19 | 20 | ## Block Diagram and Pinout 21 | 22 | ![](readme_files/usb_dfu.png) 23 | 24 | ### Clocks 25 | * `clk_i`: clock with a frequency of 12MHz*BIT\_SAMPLES 26 | * `app_clk_i`: asynchronous clock used if parameter `USE_APP_CLK = 1` 27 | 28 | ### Reset 29 | * `rstn_i`: asynchronous reset, active low 30 | 31 | ### CDC/ACM FIFO out (from the USB host) 32 | * `out_data_o`: data (1 byte if CHANNELS=1, n bytes if CHANNELS=n) 33 | * `out_valid_o`: valid control signal (1 bit if CHANNEL=1, n bits if CHANNELS=n) 34 | * `out_ready_i`: ready control signal (1 bit if CHANNEL=1, n bits if CHANNELS=n) 35 | 36 | ### CDC/ACM FIFO in (to the USB host) 37 | * `in_data_i`: data (1 byte if CHANNELS=1, n bytes if CHANNELS=n) 38 | * `in_valid_i`: valid control signal (1 bit if CHANNEL=1, n bits if CHANNELS=n) 39 | * `in_ready_o`: ready control signal (1 bit if CHANNEL=1, n bits if CHANNELS=n) 40 | 41 | ### DFU FIFO out (from the USB host) 42 | * `dfu_out_data_o`: data byte 43 | * `dfu_out_valid_o`: valid control signal 44 | * `dfu_out_ready_i`: ready control signal 45 | 46 | ### DFU FIFO in (to the USB host) 47 | * `dfu_in_data_i`: data byte 48 | * `dfu_in_valid_i`: valid control signal 49 | * `dfu_in_ready_o`: ready control signal 50 | 51 | ### DFU related signals 52 | * `dfu_mode_o`: 1 if device is in DFU Mode, 0 otherwise (`app_clk_i` sync-ed) 53 | * `dfu_alt_o`: alternate interface setting (`clk_i` sync-ed) 54 | * `dfu_out_en_o`: 1 during image download transfer, 0 otherwise (`app_clk_i` sync-ed) 55 | * `dfu_in_en_o`: 1 during image upload transfer, 0 otherwise (`app_clk_i` sync-ed) 56 | * `dfu_clear_status_o`: 1 to clear dfu\_status\_i (`app_clk_i` sync-ed) 57 | * `dfu_blocknum_o`: wValue field of DFU\_DNLOAD/DFU\_UPLOAD requests (`clk_i` sync-ed) 58 | * `dfu_busy_i`: 1 to make the USB Host wait for Poll Timeout (`app_clk_i` sync-ed) 59 | * `dfu_status_i`: status resulting from the execution of DFU requests (`app_clk_i` sync-ed): 60 | * `0x0`. DFU request execution is still running. 61 | * `0xF`. DFU request execution finished without error. 62 | * DFU error code. DFU request execution finished with error (see table at page 21 of DFU 1.1 standard). 63 | 64 | ### USB I/O buffers 65 | * `dp_rx_i`: D+ input bit stream 66 | * `dn_rx_i`: D- input bit stream 67 | * `dp_tx_o`: D+ output bit stream 68 | * `dn_tx_o`: D- output bit stream 69 | * `tx_en_o`: D+/D- output enable 70 | * `dp_up_o`: 1.5kΩ D+ pullup enable 71 | 72 | ### USB device status 73 | * `frame_o`: last received USB frame number (`clk_i` sync-ed) 74 | * `configured_o`: 1 if USB device is in configured state, 0 otherwise (`clk_i` sync-ed) 75 | 76 | ## FIFO interface 77 | USB\_DFU provides two FIFO interfaces to transfer data to/from FPGA application. One for the CDC/ACM function and the other for the DFU function. All `in_*` and `out_*` channels use the same transmission protocol. 78 | 79 | ![](readme_files/fifo_timings.png) 80 | 81 | Data is consumed on rising `app_clk` when both `valid` and `ready` signals are high (red up arrows on the picture). Tsetup and Thold depend on FPGA/ASIC technology. 82 | 83 | The `valid` signal is high only when new data is available. After data is consumed and there is no new data available, the `valid` signal is asserted low. 84 | 85 | ![](readme_files/fifo_protocol.png) 86 | 87 | 88 | ## Verilog Configuration Parameters 89 | USB\_DFU has few Verilog parameters that allow customizing some module features. 90 | 91 | ### VENDORID and PRODUCTID 92 | VENDORID and PRODUCTID define USB vendor ID (VID) and product ID (PID). 93 | For TinyFPGA: VID=0x1D50 and PID=0x6130. 94 | By default, they are not defined (VENDORID=0x0000 and PRODUCTID=0x0000). 95 | 96 | ### RTI_STRING 97 | Run-time DFU interface string. This will appear as "name" on `dfu-util`. 98 | 99 | ### SN_STRING 100 | Serial number string. This will appear as "serial" on `dfu-util`. 101 | 102 | ### ALT_STRINGS 103 | Concatenation of DFU Mode strings separated by "\000" or by "\n". These will appear as "name" for the various alternate interfaces on `dfu-util`. The number of these strings defines the number of available alternate settings. 104 | 105 | ### TRANSFER_SIZE 106 | Maximum number of bytes that the device can accept for DFU\_DNLOAD/DFU\_UPLOAD requests. 107 | 108 | ### POLLTIMEOUT 109 | Minimum time, in milliseconds, that the host should wait before sending a subsequent DFU\_GETSTATUS request. This is enforced when `dfu_busy_i` is high, otherwise it is internally set to 1ms. 110 | 111 | ### MS20 112 | If 0 Microsoft OS 2.0 Descriptors are disabled, otherwise they are enabled for Run-time mode. 113 | 114 | ### WCID 115 | If 0 Microsoft OS 1.0 Descriptors are disabled, otherwise they are enabled for DFU Mode. 116 | 117 | ### MAXPACKETSIZE 118 | MAXPACKETSIZE defines maximum data payload size for IN and OUT control/bulk transactions. The allowable full-speed values are only 8, 16, 32, and 64 bytes. The default value is 8. 119 | 120 | ### CHANNELS 121 | CHANNELS defines how many CDC channels to implement. It is possible to implement from a minimum of 1 (default) to a maximum of 7 channels. 122 | 123 | ### BIT\_SAMPLES 124 | BIT\_SAMPLES defines the number of samples taken on USB dp/dn lines for each bit. Full Speed USB has a bit rate of 12MHz, so the `clk` clock has to be BIT\_SAMPLES times faster. For example, the default value of 4 needs a `clk` frequency of 48MHz (see the picture below). BIT\_SAMPLES has to be ≥ 4. 125 | 126 | ![](readme_files/bit_samples.png) 127 | 128 | ### USE\_APP\_CLK and APP\_CLK\_FREQ 129 | 130 | USE\_APP\_CLK parameter configures if the FPGA application uses the same USB_CDC internal stuff clock (USE\_APP\_CLK = 0) or a different asynchronous one (USE\_APP\_CLK = 1). If USE\_APP\_CLK = 0 then `app_clk` input is not used and can be connected to a constant value such as `1'b0`. 131 | 132 | When USE\_APP\_CLK = 1, APP\_CLK\_FREQ parameter defines the `app_clk` frequency in MHz. 133 | 134 | 135 | To improve data throughput for lower `app_clk` frequencies, APP\_CLK\_FREQ parameter selects one of two different approaches to synchronize data that cross the two clock domains: 136 | 137 | * APP\_CLK\_FREQ ≤ 12. FPGA application can exchange data at every 1 or 2 `app_clk` cycles. 138 | 139 | * APP\_CLK\_FREQ > 12. FPGA application can exchange data at an average of 2\*2.5 `app_clk` cycles + 2\*2.5 `clk` cycles. 140 | 141 | 142 | Overall, the USB Full-speed protocol caps data throughput to 1.5MB/s. 143 | So, with freq(`clk`) ≥ 48MHz, data throughput is 1.5MB/s if freq(`app_clk`) > 1.5MHz, otherwise it is freq(`app_clk`) bytes. 144 | 145 | 146 | ## Examples 147 | A few examples with complete implementation on TinyFPGA-BX are present in the `examples` directory. In addition, simulation testbenches are provided for each one. 148 | 149 | 150 | ## Directory Structure 151 | 152 | ``` 153 | . 154 | ├── README.md --> This file 155 | ├── usb_dfu --> USB_DFU verilog files 156 | │  ├── ctrl_endp.v 157 | │  ├── fifo.v 158 | │  ├── in_fifo.v 159 | │  ├── out_fifo.v 160 | │  ├── phy_rx.v 161 | │ ├── phy_tx.v 162 | │ ├── sie.v 163 | │ └── usb_dfu.v 164 | └── examples --> Example designs 165 | └── TinyFPGA-BX 166 |   ├── hdl 167 |   │   ├── bootloader 168 |     │   │   ├── bootloader.v --> Top level (verilog) 169 |     │   │   : 170 |     │   │ 171 |     │   └── loopback 172 |     │      ├── loopback.v --> Top level (verilog) 173 |     │      : 174 |     │ 175 |     ├── iCEcube2 --> iCEcube2 projects 176 |   │   ├── bootloader 177 |     │   │   ├── usb_dfu_sbt.project --> iCEcube2 project file 178 |     │   │   : 179 |     │   │ 180 |     │   └── loopback 181 | │ ├── usb_dfu_sbt.project --> iCEcube2 project file 182 |     │   : 183 |     │ 184 |     ├── OSS_CAD_Suite --> OSS CAD Suite projects 185 |   │   ├── Makefile 186 |     │   ├── input 187 |     │ │ ├── bootloader 188 |     │   │   │   : 189 |     │ │ └── loopback 190 |     │   │      : 191 |     │   │ 192 |     │   └── output 193 |     │   : 194 |     │ 195 |    └── python --> test files 196 |     └── bootloader 197 |       ├── run.py 198 |       : 199 | ``` 200 | -------------------------------------------------------------------------------- /examples/common/gtkwave/procs.tcl: -------------------------------------------------------------------------------- 1 | 2 | proc addSignals {sigFilterList} { 3 | foreach sigFilter $sigFilterList { 4 | for {set i 0} {$i < [ gtkwave::getNumFacs ] } {incr i} { 5 | set facname [gtkwave::getFacName $i] 6 | set index [regexp $sigFilter $facname] 7 | if {$index == 1} { 8 | gtkwave::addSignalsFromList "$facname" 9 | } 10 | } 11 | } 12 | } 13 | 14 | proc setColor {sigFilterList color} { 15 | gtkwave::/Edit/UnHighlight_All 16 | foreach sigFilter $sigFilterList { 17 | for {set i 0} {$i < [ gtkwave::getNumFacs ] } {incr i} { 18 | set facname [gtkwave::getFacName $i] 19 | set index [regexp $sigFilter $facname] 20 | if {$index == 1} { 21 | gtkwave::highlightSignalsFromList "$facname" 22 | } 23 | } 24 | } 25 | gtkwave::/Edit/Color_Format/$color 26 | gtkwave::/Edit/UnHighlight_All 27 | } 28 | 29 | proc setData {sigFilterList data} { 30 | gtkwave::/Edit/UnHighlight_All 31 | foreach sigFilter $sigFilterList { 32 | for {set i 0} {$i < [ gtkwave::getNumFacs ] } {incr i} { 33 | set facname [gtkwave::getFacName $i] 34 | set index [regexp $sigFilter $facname] 35 | if {$index == 1} { 36 | gtkwave::highlightSignalsFromList "$facname" 37 | } 38 | } 39 | } 40 | gtkwave::/Edit/Data_Format/$data 41 | gtkwave::/Edit/UnHighlight_All 42 | } 43 | 44 | proc getConfig {mapfile} { 45 | set fd [open $mapfile r] 46 | set data [read $fd] 47 | close $fd 48 | 49 | set data_lines [split $data "\n"] 50 | set config_lines [lsearch -all -regexp $data_lines "^(\\s)*##.*##.*$"] 51 | set config_dict [dict create] 52 | foreach line $config_lines { 53 | set config_data [split [string map [list "##" \001] [lindex $data_lines $line]] \001] 54 | set key [string trim [lindex $config_data 1]] 55 | set value [string trim [lindex $config_data 2]] 56 | if { $key == "name"} { 57 | dict lappend config_dict $key $value 58 | } else { 59 | dict set config_dict $key $value 60 | } 61 | } 62 | return $config_dict 63 | } 64 | 65 | proc wavesTranslate {mapfile} { 66 | set config_dict [getConfig $mapfile] 67 | if {[dict exists $config_dict {name}]} { 68 | gtkwave::/Edit/UnHighlight_All 69 | foreach sigFilter [dict get $config_dict {name}] { 70 | for {set i 0} {$i < [gtkwave::getNumFacs] } {incr i} { 71 | set facname [gtkwave::getFacName $i] 72 | set index [regexp $sigFilter $facname] 73 | if {$index == 1} { 74 | gtkwave::highlightSignalsFromList "$facname" 75 | } 76 | } 77 | } 78 | if {[dict exists $config_dict {color}]} { 79 | gtkwave::/Edit/Color_Format/[dict get $config_dict {color}] 80 | } 81 | if {[dict exists $config_dict {data}]} { 82 | gtkwave::/Edit/Data_Format/[dict get $config_dict {data}] 83 | } 84 | gtkwave::installFileFilter [gtkwave::setCurrentTranslateFile $mapfile] 85 | gtkwave::/Edit/UnHighlight_All 86 | } 87 | } 88 | 89 | proc wavesFormat {mapdir} { 90 | set files [ glob $mapdir/*.map ] 91 | foreach file $files { 92 | wavesTranslate $file 93 | } 94 | } 95 | 96 | proc phy_rx {} { 97 | gtkwave::/Edit/Insert_Comment "PHY_RX" 98 | set sigFilterList [list \ 99 | {phy_rx\.nrzi\[.*\]$} \ 100 | {phy_rx\.state_q\[.*\]$} \ 101 | {phy_rx\.rx_state_q\[.*\]$} \ 102 | {phy_rx\.clk_gate_i$} \ 103 | {phy_rx\.rx_en_i$} \ 104 | {phy_rx\.rx_err_o$} \ 105 | {phy_rx\.rx_ready_o$} \ 106 | {phy_rx\.rx_valid_o$} \ 107 | {phy_rx\.rx_data_o\[.*\]$} \ 108 | {phy_rx\.usb_reset_o$} \ 109 | {phy_rx\.dp_pu_o$} \ 110 | ] 111 | addSignals $sigFilterList 112 | wavesFormat ../../common/gtkwave 113 | } 114 | 115 | proc phy_tx {} { 116 | gtkwave::/Edit/Insert_Comment "PHY_TX" 117 | set sigFilterList [list \ 118 | {phy_tx\.tx_state_q\[.*\]$} \ 119 | {phy_tx\.clk_gate_i$} \ 120 | {phy_tx\.tx_ready_o$} \ 121 | {phy_tx\.tx_valid_i$} \ 122 | {phy_tx\.tx_data_i\[.*\]$} \ 123 | ] 124 | addSignals $sigFilterList 125 | wavesFormat ../../common/gtkwave 126 | } 127 | 128 | proc sie {} { 129 | gtkwave::/Edit/Insert_Comment "SIE" 130 | set sigFilterList [list \ 131 | {sie\.frame_q\[.*\]$} \ 132 | {sie\.pid_q\[.*\]$} \ 133 | {sie\.addr_q\[.*\]$} \ 134 | {sie\.endp_q\[.*\]$} \ 135 | {sie\.phy_state_q\[.*\]$} \ 136 | {sie\.stall_i$} \ 137 | {sie\.setup_o$} \ 138 | ] 139 | addSignals $sigFilterList 140 | wavesFormat ../../common/gtkwave 141 | setData { {sie\.frame_q\[.*\]$} } Decimal 142 | setData { {sie\.addr_q\[.*\]$} } Decimal 143 | } 144 | 145 | proc sie_out {} { 146 | gtkwave::/Edit/Insert_Comment "SIE: OUT" 147 | set sigFilterList [list \ 148 | {sie\.out_err_o$} \ 149 | {sie\.out_ready_o$} \ 150 | {sie\.out_valid_o$} \ 151 | {sie\.out_data_o\[.*\]$} \ 152 | ] 153 | addSignals $sigFilterList 154 | wavesFormat ../../common/gtkwave 155 | setColor { {sie\.out_ready_o} } Red 156 | } 157 | 158 | proc sie_in {} { 159 | gtkwave::/Edit/Insert_Comment "SIE: IN" 160 | set sigFilterList [list \ 161 | {sie\.in_req_o$} \ 162 | {sie\.in_data_ack_o$} \ 163 | {sie\.in_ready_o$} \ 164 | {sie\.in_valid_i$} \ 165 | {sie\.in_zlp_i$} \ 166 | {sie\.in_data_i\[.*\]$} \ 167 | ] 168 | addSignals $sigFilterList 169 | wavesFormat ../../common/gtkwave 170 | setColor { {sie\.in_ready_o} } Red 171 | } 172 | 173 | proc ctrl {} { 174 | gtkwave::/Edit/Insert_Comment "CTRL_ENDP" 175 | set sigFilterList [list \ 176 | {ctrl_endp\.req_q\[.*\]$} \ 177 | {ctrl_endp\.dev_state_qq\[.*\]$} \ 178 | {ctrl_endp\.state_q\[.*\]$} \ 179 | {ctrl_endp\.byte_cnt_q\[.*\]$} \ 180 | {ctrl_endp\.addr_o\[.*\]$} \ 181 | {ctrl_endp\.stall_o$} \ 182 | {ctrl_endp\.dfu_state_q\[.*\]$} \ 183 | {ctrl_endp\.dfu_mode_o$} \ 184 | {ctrl_endp\.dfu_alt_o\[.*\]$} \ 185 | {ctrl_endp\.dfu_upload_o$} \ 186 | {ctrl_endp\.dfu_dnload_o$} \ 187 | {ctrl_endp\.dfu_clear_status_o$} \ 188 | ] 189 | addSignals $sigFilterList 190 | wavesFormat ../../common/gtkwave 191 | setData { {ctrl_endp\.byte_cnt_} } Decimal 192 | } 193 | 194 | proc fifo_out {} { 195 | gtkwave::/Edit/Insert_Comment "FIFO: OUT" 196 | set sigFilterList [list \ 197 | {u_fifo\.u_out_fifo\.app_clk_i$} \ 198 | {u_fifo\.u_out_fifo\.app_out_ready_i$} \ 199 | {u_fifo\.u_out_fifo\.app_out_valid_o$} \ 200 | {u_fifo\.u_out_fifo\.app_out_data_o\[.*\]$} \ 201 | {u_fifo\.u_out_fifo\.out_state_q\[.*\]$} \ 202 | {u_fifo\.u_out_fifo\.out_full_q$} \ 203 | {u_fifo\.u_out_fifo\.out_empty$} \ 204 | ] 205 | addSignals $sigFilterList 206 | wavesFormat ../../common/gtkwave 207 | } 208 | 209 | proc fifo_in {} { 210 | gtkwave::/Edit/Insert_Comment "FIFO: IN" 211 | set sigFilterList [list \ 212 | {u_fifo\.u_in_fifo\.app_clk_i$} \ 213 | {u_fifo\.u_in_fifo\.app_in_ready_o$} \ 214 | {u_fifo\.u_in_fifo\.app_in_valid_i$} \ 215 | {u_fifo\.u_in_fifo\.app_in_data_i\[.*\]$} \ 216 | {u_fifo\.u_in_fifo\.in_state_q$} \ 217 | {u_fifo\.u_in_fifo\.in_full$} \ 218 | ] 219 | addSignals $sigFilterList 220 | wavesFormat ../../common/gtkwave 221 | setColor { {u_fifo\.u_in_fifo\.in_state_q$} } Blue 222 | } 223 | 224 | proc dfu {} { 225 | gtkwave::/Edit/Insert_Comment "DFU" 226 | set sigFilterList [list \ 227 | {usb_dfu\.bus_reset$} \ 228 | ] 229 | addSignals $sigFilterList 230 | wavesFormat ../../common/gtkwave 231 | } 232 | 233 | proc out {} { 234 | phy_rx 235 | sie 236 | sie_out 237 | fifo_out 238 | } 239 | 240 | proc in {} { 241 | fifo_in 242 | sie 243 | sie_in 244 | phy_tx 245 | } 246 | 247 | set cmds "dfu out in phy_rx phy_tx sie sie_out sie_in ctrl fifo_in fifo_out" 248 | if { [file exists input/$env(PROJ)/gtkwave/procs.tcl]} { 249 | source input/$env(PROJ)/gtkwave/procs.tcl 250 | } 251 | 252 | puts "\033\[92m" 253 | puts "gtkwave console" 254 | puts "Available commands to show waveforms:" 255 | puts " $cmds" 256 | puts "\033\[0m" 257 | --------------------------------------------------------------------------------