Browse Source

cores/usb: Replace in-tree core with submodule

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Sylvain Munaut 4 years ago
parent
commit
7679329813
41 changed files with 4 additions and 9492 deletions
  1. 3 0
      .gitmodules
  2. 1 0
      cores/no2usb
  3. 0 4
      cores/usb/Makefile
  4. 0 1
      cores/usb/data/capture_usb_raw_short.bin
  5. 0 256
      cores/usb/data/usb_ep_status.hex
  6. 0 144
      cores/usb/doc/architecture.md
  7. 0 2369
      cores/usb/doc/ice40-usb.svg
  8. 0 181
      cores/usb/doc/mem-map.md
  9. 0 79
      cores/usb/doc/microcode.md
  10. 0 5
      cores/usb/fw/fw.mk
  11. 0 55
      cores/usb/fw/usb_gen_strings.py
  12. 0 25
      cores/usb/fw/v0/fw.mk
  13. 0 134
      cores/usb/fw/v0/include/no2usb/usb.h
  14. 0 27
      cores/usb/fw/v0/include/no2usb/usb_dfu.h
  15. 0 76
      cores/usb/fw/v0/include/no2usb/usb_dfu_proto.h
  16. 0 27
      cores/usb/fw/v0/include/no2usb/usb_dfu_rt.h
  17. 0 95
      cores/usb/fw/v0/include/no2usb/usb_hw.h
  18. 0 108
      cores/usb/fw/v0/include/no2usb/usb_priv.h
  19. 0 213
      cores/usb/fw/v0/include/no2usb/usb_proto.h
  20. 0 682
      cores/usb/fw/v0/src/usb.c
  21. 0 389
      cores/usb/fw/v0/src/usb_ctrl_ep0.c
  22. 0 361
      cores/usb/fw/v0/src/usb_ctrl_std.c
  23. 0 395
      cores/usb/fw/v0/src/usb_dfu.c
  24. 0 114
      cores/usb/fw/v0/src/usb_dfu_rt.c
  25. 0 73
      cores/usb/fw/v0/src/usb_dfu_vendor.c
  26. 0 34
      cores/usb/no2core.mk
  27. 0 628
      cores/usb/rtl/usb.v
  28. 0 68
      cores/usb/rtl/usb_crc.v
  29. 0 44
      cores/usb/rtl/usb_defs.vh
  30. 0 287
      cores/usb/rtl/usb_ep_buf.v
  31. 0 121
      cores/usb/rtl/usb_ep_status.v
  32. 0 151
      cores/usb/rtl/usb_phy.v
  33. 0 213
      cores/usb/rtl/usb_rx_ll.v
  34. 0 393
      cores/usb/rtl/usb_rx_pkt.v
  35. 0 470
      cores/usb/rtl/usb_trans.v
  36. 0 158
      cores/usb/rtl/usb_tx_ll.v
  37. 0 263
      cores/usb/rtl/usb_tx_pkt.v
  38. 0 84
      cores/usb/sim/usb_ep_buf_tb.v
  39. 0 147
      cores/usb/sim/usb_tb.v
  40. 0 171
      cores/usb/sim/usb_tx_tb.v
  41. 0 447
      cores/usb/utils/microcode.py

+ 3 - 0
.gitmodules

@@ -4,3 +4,6 @@
 [submodule "cores/no2misc"]
 	path = cores/no2misc
 	url = https://github.com/no2fpga/no2misc.git
+[submodule "cores/no2usb"]
+	path = cores/no2usb
+	url = https://github.com/no2fpga/no2usb.git

+ 1 - 0
cores/no2usb

@@ -0,0 +1 @@
+Subproject commit 511fe2cd29b1571f0282c02147492595879dd194

+ 0 - 4
cores/usb/Makefile

@@ -1,4 +0,0 @@
-CORE := no2usb
-
-NO2BUILD_DIR ?= $(abspath ../../build)
-include $(NO2BUILD_DIR)/core-rules.mk

File diff suppressed because it is too large
+ 0 - 1
cores/usb/data/capture_usb_raw_short.bin


+ 0 - 256
cores/usb/data/usb_ep_status.hex

@@ -1,256 +0,0 @@
-0006
-0000
-0000
-0000
-4040
-0000
-0000
-0000
-0006
-0000
-0000
-0000
-4012
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000
-0000

+ 0 - 144
cores/usb/doc/architecture.md

@@ -1,144 +0,0 @@
-iCE40 USB Core Architecture
-===========================
-
-Overview
---------
-
-![Architecture diagram](ice40-usb.svg "Architecture diagram")
-
-### Design goals
-
-The goal was to write a core that would be similar to the SIE you find in
-classic microcontrollers that support USBs. That means it requires a soft
-core to implement the actual USB stack, the hardware itself only handle up
-to the _transaction_ layer of USB.
-
-It's designed to be small but still allow full flexibility of what kind
-of device it implements, supports all types of transfers, all packet
-sizes and any combination of end points without having to change the
-hardware configuration at all.
-
-### Operation principle
-
-Each endpoint can be configured as any type and be either single or
-double buffered. When the core receives a token from the host, it will
-look up the EP status and check if there is any buffer ready to send/receive.
-
-The data buffers are fully shared between each end point, the address field
-of each buffer descriptor has to be filled by the software stack to ensure
-no conflicts.
-
-To know if/when transfer happens, the core can either generate/queue event
-in a FIFO or the software can also just poll the EP status fields.
-
-
-### Special handling for Control Endpoints
-
-End Point 0 and Control endpoint in general are almost treated like any
-other endpoint, and you can use control transfer on any endpoint if you
-wish.
-
-However the hardware does offer a couple of special features to make the
-software implementation of control transfer easier.
-
-The first one is called the "Control Endpoint Lockout" or _CEL_ for short.
-If enabled, any `SETUP` packet received by a control endpoint will trigger
-the lockout. This will in turn cause any `IN` or `OUT` transactions on a
-control endpoint to be `NAKed` to make sure that the soft core / usb stack
-has time to properly analyze the received `SETUP` packet before sending
-any response in case previous buffers for `IN`/`OUT` were left overs from
-aborted transactions. This makes handling error cases much easier.
-
-The second feature is a special double buffer mode for control endpoints
-where instead of having two buffers alternating, you have two buffers
-descriptors, the first one is used for `OUT` transactions and the second
-one is used for `SETUP` transactions. Again, this makes the software stack
-implementation a bit easier.
-
-
-### Interfaces
-
- * Wishbone interface for the CSRs and Buffer Descriptors
-    * Clocked at 48 MHz
-    * Details of the [Memory Map](mem-map.md)
- * Dedicated "BRAM-style" interface to access packets payload
-    * TX data buffer are write-only
-    * RX data buffer are read-only
-    * Can be clocked from a different clock
-
-
-### Resources
-
- * About 390 FFs and 530 LUT4s
- * 10 `SB_RAM40_4K`
-    * 8 are used for 2k RX and 2k TX data buffers and could be resized
-      as needed
-
-
-### Remarks
-
-Although the core has been developped with the iCE40 in mind, it should be
-easily portable to other FPGAs as there is very few harware specific blocks
-inside. (Mostly just the IOs and BRAMs)
-
-
-Modules
--------
-
-### PHY `usb_phy.v`
-
-This module mostly just contains the IO tristate buffers and also a small
-glitch filter to improve signal quality.
-
-### TX Low Level `usb_tx_ll.v`
-
-This module implements the transmit side of bit stuffing, differential coding,
-symbol mapping and transmit baudrate timing.
-
-### TX Packet `usb_tx_pkt.v`
-
-This module handles the sending of packet. Handles adding header, CRC and
-serializing into a bitstream.
-
-### RX Low Level `usb_rx_ll.v`
-
-This module takes care of receive clock recovery, symbol unmapping,
-differential decoding and bit-unstuffing. It provides a stream of valid
-bits to the upstream block along with markers for packet sync and
-end-of-packet.
-
-### RX Packet `usb_rx_pkt.v`
-
-This takes the recovered bitstream from the low-level module and reconstructs
-packet, doing checks along the way (PID check / CRC check).
-
-### Transaction `usb_trans.v`
-
-This module is the heart of the USB core. It implements the transaction layer
-of USB. This means all the diagrams of Chapter 8 of the USB specifications.
-
-Because all the decisions to make are rather complex, this block main logic
-is implemented using microcode. So you have a very special purpose CPU (see
-[Microcode instructions](microcode.md) for its very limited instruction set),
-surrounded by some helper peripherals to control the TX/RX packets blocks,
-direct data appropriately and interact with the memory containing all the
-endpoint buffer descriptors and status information.
-
-### EP Status `usb_ep_status.v`
-
-This memory is a BRAM that's used to store all the information about each
-endpoint (status / buffer descriptors / ... ). Because it needs to be accessed
-by both the microcode engine and by the softcore, it contains arbitration
-logic since the iCE40 doesn't suport true-dual-port RAM.
-
-### EP Data Buffers `usb_ep_buf.v`
-
-This is just a dual-port RAM with different read/write clocks and port width.
-
-Because the synthesis tool isn't yet capable of inferring this optimally, it was
-written by instanciating the iCE40 RAM primitives manually.
-
-### Top Level `usb.v`
-
-This is the module that ties it all together and also implement the few global
-CSRs along with the wishbone interface.

File diff suppressed because it is too large
+ 0 - 2369
cores/usb/doc/ice40-usb.svg


+ 0 - 181
cores/usb/doc/mem-map.md

@@ -1,181 +0,0 @@
-iCE40 USB Core Memory Map
-=========================
-
-Global CSRs
------------
-
-### Control / Status (Read / Write addr `0x00`)
-
-```text
-,---------------------------------------------------------------,
-| f | e | d | c | b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|---------------------------------------------------------------|
-| p |evt| cs| ce|bsa|bra|brp|sfp| m |          addr             |
-'---------------------------------------------------------------'
-```
-
-  * `p`   : Enables DP pull-up
-  * `evt` : Event pending
-  * `cs`  : Control Endpoint Lockout - State [Read Only]
-  * `ce`  : Control Endpoint Lockout - Enable
-  * `bsa` : Bus Suspend Asserted
-  * `bra` : Bus Reset Asserted
-  * `brp` : Bus Reset Pending
-  * `sfp` : Start-of-Frame Pending
-  * `m`   : Enable address matching
-  * `addr`: Configure address matching
-
-
-### Action ( Write addr `0x01` )
-
-```text
-,---------------------------------------------------------------,
-| f | e | d | c | b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|---------------------------------------------------------------|
-|  rsvd | cr|     /     |brc|sfc|               /               |
-'---------------------------------------------------------------'
-```
-
-  * `cr` : Control Endpoint Lockout - Release
-  * `brc`: Bus Reset Clear
-  * `sfc`: Start-of-Frame Clear
-
-
-### Events (Read addr `0x02`)
-
-This contains info about the generated events from the transaction
-microcode.
-
-It can either contain info about the last event only along with a
-count of events since last read, or it can be a FIFO depending on
-the core configuration.
-
-Count mode (`EVENT_DEPTH = 0/1`) :
-
-```text
-,---------------------------------------------------------------,
-| f | e | d | c | b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|---------------------------------------------------------------|
-|      cnt      |                 event                         |
-'---------------------------------------------------------------'
-```
-
-  * `cnt`: Counter of events since last read
-  * `event`: Last recorded event data (see below)
-
-
-FIFO mode (`EVENT_DEPTH > 1`) :
-
-```text
-,---------------------------------------------------------------,
-| f | e | d | c | b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|---------------------------------------------------------------|
-| v | o |  rsvd |                 event                         |
-'---------------------------------------------------------------'
-```
-
-  * `v`: Valid (i.e. FIFO is not empty and `event` is valid)
-  * `o`: FIFO Overflow
-  * `event`: event data (see below)
-
-
-Event format:
-
-```text
-,-----------------------------------------------,
-| b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|-----------------------------------------------|
-|     ucnc      |      endp     | d | s | b | / |
-'-----------------------------------------------'
-```
-
-  * `ucnc`: Notification code
-  * `endp`: Endpoint #
-  * `d`: Direction (1=IN, 0=OUT/SETUP)
-  * `s`: Is SETUP ?
-  * `b`: Buffer Descriptor index
-
-
-EP Status
----------
-
-### Address:
-
-```text
-,-----------------------------------------------,
-| b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|-----------------------------------------------|
-| 1   0   0   0 |     ep_num    |dir| 0   0   0 |
-'-----------------------------------------------'
-```
-
-
-### Data:
-
-```text
-,---------------------------------------------------------------,
-| f | e | d | c | b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|---------------------------------------------------------------|
-|                               | t | b |  bdm  |   |  EP type  |
-'---------------------------------------------------------------'
-```
-
-  * `t`: Data Toggle (if relevant for EP type)
-  * `b`: Buffer Descriptor index
-  * 'bdm': Buffer descriptor mode
-    - `00` - Single Buffer (index 0 only)
-    - `01` - Double Buffer
-    - `10` - Special Control EP mode (index 0=data, 1=setup)
-  * EP Type: (`h` indicates if this EP is halted)
-    - `000`: Non-existant
-    - `001`: Isochronous
-    - `01h`: Interrupt
-    - `10h`: Bulk
-    - `11h`: Control
-
-
-Buffer Descriptor
------------------
-
-### Address:
-
-```text
-,-----------------------------------------------,
-| b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|-----------------------------------------------|
-| 1   0   0   0 |     ep_num    |dir| 1 | i | w |
-'-----------------------------------------------'
-```
-
-  * `i`: BD Index (0/1)
-  * `w`: Word select
-
-
-### Word 0:
-
-```text
-,---------------------------------------------------------------,
-| f | e | d | c | b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|---------------------------------------------------------------|
-|   state   | s |  rsvd |           Buffer Length               |
-'---------------------------------------------------------------'
-```
-
-  * `s`: Transactions was setup
-  * BD State:
-    - `000`: Empty / Unused
-    - `010`: Valid, ready for Tx/RX data
-    - `011`: Valid, issue STALL (and drop data)
-    - `100`: Used - Success
-    - `1xx`: Used - Error with xx=01/10/11 error code
-
-
-### Word 1:
-
-```text
-,---------------------------------------------------------------,
-| f | e | d | c | b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-|---------------------------------------------------------------|
-|       (rsvd)      |             Buffer Pointer                |
-'---------------------------------------------------------------'
-```

+ 0 - 79
cores/usb/doc/microcode.md

@@ -1,79 +0,0 @@
-USB Transaction microcode
-=========================
-
-The upper 4 bits of the word determine the operation type.
-
-Data / Ops (`0xxx` )
---------------------
-
-### `0x0`: `NOP` - No OPeration
-
-### `0x1`: `LD` - LoaD
-
-```
-    [2:0] - Source
-            000 - evt          - Pending Events
-                                 bit 0 = RX OK
-                                 bit 1 = RX Error
-                                 bit 2 = TX Done
-                                 bit 3 = Timeout
-
-            010 - pkt_pid      - Packet PID
-            011 - pkt_pid_chk  - Packet PID (DATA0/DATA1 check)
-            100 - ep_type      - End Point type
-            110 - bd_state     - State of Buffer Descriptor
-```
-
-### `0x2`: `EP` - End Point operation
-
-```
-      [8] - Set Control Endpoint Lockout bit
-      [7] - Issue Write Back
-    [5:3] - New Buffer Descriptor State value
-      [2] - Set Buffer Descriptor State
-      [1] - Flip Buffer index bit (active only if EP is dual buffered)
-      [0] - Flip Data Toggle bit
-```
-
-### `0x3`: `ZL` - Zero Length
-
-### `0x4`: `TX` - Transmit packet
-
-```
-      [4] - Auto-Set DataToggle (DATA0/DATA1)
-    [3:0] - Packet PID
-```
-
-### `0x5`: `NOTIFY` - Notify Host
-
-```
-    [3:0] - Notify code
-```
-
-### `0x6`: `EVT_CLR` - EVenT CLeaR
-
-```
-    [3:0] - Bit Mask of events to clear
-```
-
-### `0x7`: `EVT_RTO` - EVenT Receive Time Out
-
-```
-    [7:0] - Timeout value
-```
-
-
-Control flow ( `1xxx` )
------------------------
-
-### `JMP` / `JEQ` / `JNE`
-
-```
-      [15] - Set to 1 to denote control flow operation
-      [14] - Invert the condition
-    [13:8] - Target address (divided by 4)
-     [7:0] - Condition Mask
-     [3:0] - Condition Value
-```
-
-This performs conditional jumps to any address where the two LSBs are clear (i.e. aligned to 4).

+ 0 - 5
cores/usb/fw/fw.mk

@@ -1,5 +0,0 @@
-SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
-
-ifeq ($(NO2USB_FW_VERSION),0)
-include $(SELF_DIR)v0/fw.mk
-endif

+ 0 - 55
cores/usb/fw/usb_gen_strings.py

@@ -1,55 +0,0 @@
-#!/usr/bin/env python3
-
-import json
-import sys
-
-def main(argv0, fn_in, fn_out, board=''):
-
-	with open(fn_in, 'r') as fh_in, open(fn_out, 'w') as fh_out:
-		# Arrays
-		str_d = []
-
-		# String 0
-		str_d.append("""static const struct usb_str_desc _str0_desc = {
-	.bLength		= 4,
-	.bDescriptorType	= USB_DT_STR,
-	.wString		= { 0x0409 },
-};
-""")
-
-		# String 1..n
-		def sep(i, l):
-			if i == l-1:
-				return ''
-			elif ((i & 7) == 7):
-				return '\n\t\t'
-			else:
-				return ' '
-
-		for i, ld in enumerate(fh_in.readlines()):
-			ld = ld.strip()
-			if ld.startswith('!{'):
-				ld = json.loads(ld[1:])
-				ld = ld[board] if board in ld else ld['']
-			ll = len(ld)
-			d = ''.join(['0x%04x,%s' % (ord(c), sep(j, ll)) for j,c in enumerate(ld)])
-			str_d.append("""static const struct usb_str_desc _str%d_desc = {
-	.bLength		= %d,
-	.bDescriptorType	= USB_DT_STR,
-	.wString		= {
-		%s
-	},
-};
-""" % (i+1, ll*2+2, d))
-
-		fh_out.write('\n'.join(str_d))
-
-		# Array
-		fh_out.write("\n")
-		fh_out.write("static const struct usb_str_desc * const _str_desc_array[] = {\n")
-		for i in range(len(str_d)):
-			fh_out.write("\t& _str%d_desc,\n" % i)
-		fh_out.write("};\n")
-
-if __name__ == '__main__':
-	main(*sys.argv)

+ 0 - 25
cores/usb/fw/v0/fw.mk

@@ -1,25 +0,0 @@
-CORE_no2usb_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/../..)
-
-INC_no2usb := -I$(CORE_no2usb_DIR)/fw/v0/include
-
-HEADERS_no2usb=$(addprefix $(CORE_no2usb_DIR)/fw/v0/include/, \
-	no2usb/usb.h \
-	no2usb/usb_dfu.h \
-	no2usb/usb_dfu_proto.h \
-	no2usb/usb_dfu_rt.h \
-	no2usb/usb_hw.h \
-	no2usb/usb_priv.h \
-	no2usb/usb_proto.h \
-)
-
-SOURCES_no2usb=$(addprefix $(CORE_no2usb_DIR)/fw/v0/src/, \
-	usb.c \
-	usb_ctrl_ep0.c \
-	usb_ctrl_std.c \
-	usb_dfu.c \
-	usb_dfu_rt.c \
-	usb_dfu_vendor.c \
-)
-
-usb_str_%.gen.h: usb_str_%.txt
-	$(CORE_no2usb_DIR)/fw/usb_gen_strings.py $< $@ $(BOARD)

+ 0 - 134
cores/usb/fw/v0/include/no2usb/usb.h

@@ -1,134 +0,0 @@
-/*
- * usb.h
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#include <stdbool.h>
-#include <stdint.h>
-
-#include "usb_proto.h"
-
-
-/* Types */
-/* ----- */
-
-struct usb_xfer;
-
-struct usb_stack_descriptors {
-	const struct usb_dev_desc *dev;
-	const struct usb_conf_desc * const *conf;
-	int n_conf;
-	const struct usb_str_desc * const *str;
-	int n_str;
-};
-
-enum usb_dev_state {
-	USB_DS_OFF		= 0,	/* Core is not initialize */
-	USB_DS_DISCONNECTED	= 1,	/* Core is not connected  */
-	USB_DS_CONNECTED	= 2,	/* Core is connected awaiting reset */
-	USB_DS_DEFAULT		= 3,
-	USB_DS_ADDRESS		= 4,
-	USB_DS_CONFIGURED	= 5,
-	USB_DS_SUSPENDED	= 0x80,	/* Bit marking suspend */
-	USB_DS_RESUME		= 0x81,	/* Special value for set_state */
-};
-
-
-enum usb_fnd_resp {
-        USB_FND_CONTINUE = 0,	/* Not handled, continue to next */
-        USB_FND_SUCCESS,	/* Handled: Success */
-        USB_FND_ERROR,		/* Handled: Error   */
-};
-
-typedef void (*usb_fnd_sof_cb)(void);
-typedef void (*usb_fnd_bus_reset_cb)(void);
-typedef void (*usb_fnd_state_chg_cb)(enum usb_dev_state state);
-typedef enum usb_fnd_resp (*usb_fnd_ctrl_req_cb)(struct usb_ctrl_req *req, struct usb_xfer *xfer);
-typedef enum usb_fnd_resp (*usb_fnd_set_conf_cb)(const struct usb_conf_desc *desc);
-typedef enum usb_fnd_resp (*usb_fnd_set_intf_cb)(const struct usb_intf_desc *base, const struct usb_intf_desc *sel);
-typedef enum usb_fnd_resp (*usb_fnd_get_intf_cb)(const struct usb_intf_desc *base, uint8_t *alt);
-
-struct usb_fn_drv {
-	struct usb_fn_drv *next;
-        usb_fnd_sof_cb		sof;
-        usb_fnd_bus_reset_cb	bus_reset;
-        usb_fnd_state_chg_cb	state_chg;
-        usb_fnd_ctrl_req_cb	ctrl_req;
-        usb_fnd_set_conf_cb	set_conf;
-        usb_fnd_set_intf_cb	set_intf;
-        usb_fnd_get_intf_cb	get_intf;
-};
-
-
-typedef bool (*usb_xfer_cb)(struct usb_xfer *xfer);
-
-struct usb_xfer {
-	/* Data buffer */
-	uint8_t *data;
-	int ofs;
-	int len;
-
-	/* Call backs */
-	usb_xfer_cb cb_data;	/* Data call back */
-	usb_xfer_cb cb_done;	/* Completion call back */
-	void *cb_ctx;
-};
-
-
-/* API */
-void usb_init(const struct usb_stack_descriptors *stack_desc);
-void usb_poll(void);
-
-void usb_set_state(enum usb_dev_state new_state);
-enum usb_dev_state usb_get_state(void);
-
-uint32_t usb_get_tick(void);
-
-void usb_connect(void);
-void usb_disconnect(void);
-
-void usb_set_address(uint8_t addr);
-
-void usb_register_function_driver(struct usb_fn_drv *drv);
-void usb_unregister_function_driver(struct usb_fn_drv *drv);
-
-
-	/* EP */
-bool usb_ep_is_configured(uint8_t ep);
-bool usb_ep_is_halted(uint8_t ep);
-bool usb_ep_halt(uint8_t ep);
-bool usb_ep_resume(uint8_t ep);
-
-	/* Descriptors */
-const void *usb_desc_find(const void *sod, const void *eod, uint8_t dt);
-const void *usb_desc_next(const void *sod);
-
-const struct usb_conf_desc *usb_desc_find_conf(uint8_t cfg_value);
-const struct usb_intf_desc *usb_desc_find_intf(const struct usb_conf_desc *conf, uint8_t idx, uint8_t alt,
-                                               const struct usb_intf_desc **base);
-
-
-/* Debug */
-void usb_debug_print_ep(int ep, int dir);
-void usb_debug_print_data(int ofs, int len);
-void usb_debug_print(void);

+ 0 - 27
cores/usb/fw/v0/include/no2usb/usb_dfu.h

@@ -1,27 +0,0 @@
-/*
- * usb_dfu.h
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-void usb_dfu_cb_reboot(void);
-void usb_dfu_init(void);

+ 0 - 76
cores/usb/fw/v0/include/no2usb/usb_dfu_proto.h

@@ -1,76 +0,0 @@
-/*
- * usb_dfu_proto.h
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#define USB_REQ_DFU_DETACH	(0)
-#define USB_REQ_DFU_DNLOAD	(1)
-#define USB_REQ_DFU_UPLOAD	(2)
-#define USB_REQ_DFU_GETSTATUS	(3)
-#define USB_REQ_DFU_CLRSTATUS	(4)
-#define USB_REQ_DFU_GETSTATE	(5)
-#define USB_REQ_DFU_ABORT	(6)
-
-#define USB_RT_DFU_DETACH	((0 << 8) | 0x21)
-#define USB_RT_DFU_DNLOAD	((1 << 8) | 0x21)
-#define USB_RT_DFU_UPLOAD	((2 << 8) | 0xa1)
-#define USB_RT_DFU_GETSTATUS	((3 << 8) | 0xa1)
-#define USB_RT_DFU_CLRSTATUS	((4 << 8) | 0x21)
-#define USB_RT_DFU_GETSTATE	((5 << 8) | 0xa1)
-#define USB_RT_DFU_ABORT	((6 << 8) | 0x21)
-
-
-enum dfu_state {
-	appIDLE = 0,
-	appDETACH,
-	dfuIDLE,
-	dfuDNLOAD_SYNC,
-	dfuDNBUSY,
-	dfuDNLOAD_IDLE,
-	dfuMANIFEST_SYNC,
-	dfuMANIFEST,
-	dfuMANIFEST_WAIT_RESET,
-	dfuUPLOAD_IDLE,
-	dfuERROR,
-	_DFU_MAX_STATE
-};
-
-enum dfu_status {
-	OK = 0,
-	errTARGET,
-	errFILE,
-	errWRITE,
-	errERASE,
-	errCHECK_ERASED,
-	errPROG,
-	errVERIFY,
-	errADDRESS,
-	errNOTDONE,
-	errFIRMWARE,
-	errVENDOR,
-	errUSBR,
-	errPOR,
-	errUNKNOWN,
-	errSTALLEDPKT,
-	_DFU_MAX_STATUS
-};

+ 0 - 27
cores/usb/fw/v0/include/no2usb/usb_dfu_rt.h

@@ -1,27 +0,0 @@
-/*
- * usb_dfu_rt.h
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-void usb_dfu_rt_cb_reboot(void);
-void usb_dfu_rt_init(void);

+ 0 - 95
cores/usb/fw/v0/include/no2usb/usb_hw.h

@@ -1,95 +0,0 @@
-/*
- * usb_hw.h
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#include <stdint.h>
-
-#include "config.h"
-
-
-struct usb_core {
-	uint32_t csr;
-	uint32_t ar;
-	uint32_t evt;
-} __attribute__((packed,aligned(4)));
-
-#define USB_CSR_PU_ENA		(1 << 15)
-#define USB_CSR_EVT_PENDING	(1 << 14)
-#define USB_CSR_CEL_ACTIVE	(1 << 13)
-#define USB_CSR_CEL_ENA		(1 << 12)
-#define USB_CSR_BUS_SUSPEND	(1 << 11)
-#define USB_CSR_BUS_RST		(1 << 10)
-#define USB_CSR_BUS_RST_PENDING	(1 <<  9)
-#define USB_CSR_SOF_PENDING	(1 <<  8)
-#define USB_CSR_ADDR_MATCH	(1 <<  7)
-#define USB_CSR_ADDR(x)		((x) & 0x7f)
-
-#define USB_AR_CEL_RELEASE	(1 << 13)
-#define USB_AR_BUS_RST_CLEAR	(1 <<  9)
-#define USB_AR_SOF_CLEAR	(1 <<  8)
-
-
-struct usb_ep {
-	uint32_t status;
-	uint32_t _rsvd[3];
-	struct {
-		uint32_t csr;
-		uint32_t ptr;
-	} bd[2];
-} __attribute__((packed,aligned(4)));
-
-struct usb_ep_pair {
-	struct usb_ep out;
-	struct usb_ep in;
-} __attribute__((packed,aligned(4)));
-
-#define USB_EP_TYPE_NONE	0x0000
-#define USB_EP_TYPE_ISOC	0x0001
-#define USB_EP_TYPE_INT		0x0002
-#define USB_EP_TYPE_BULK	0x0004
-#define USB_EP_TYPE_CTRL	0x0006
-#define USB_EP_TYPE_HALTED	0x0001
-#define USB_EP_TYPE_IS_BCI(x)	(((x) & 6) != 0)
-#define USB_EP_TYPE(x)		((x) & 7)
-#define USB_EP_TYPE_MSK		0x0007
-
-#define USB_EP_DT_BIT		0x0080
-#define USB_EP_BD_IDX		0x0040
-#define USB_EP_BD_CTRL		0x0020
-#define USB_EP_BD_DUAL		0x0010
-
-#define USB_BD_STATE_MSK	0xe000
-#define USB_BD_STATE_NONE	0x0000
-#define USB_BD_STATE_RDY_DATA	0x4000
-#define USB_BD_STATE_RDY_STALL	0x6000
-#define USB_BD_STATE_DONE_OK	0x8000
-#define USB_BD_STATE_DONE_ERR	0xa000
-#define USB_BD_IS_SETUP		0x1000
-
-#define USB_BD_LEN(l)		((l) & 0x3ff)
-#define USB_BD_LEN_MSK		0x03ff
-
-
-static volatile struct usb_core *    const usb_regs    = (void*) (USB_CORE_BASE);
-static volatile struct usb_ep_pair * const usb_ep_regs = (void*)((USB_CORE_BASE) + (1 << 13));

+ 0 - 108
cores/usb/fw/v0/include/no2usb/usb_priv.h

@@ -1,108 +0,0 @@
-/*
- * usb_priv.h
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#include <stdint.h>
-
-#include "usb.h"
-#include "usb_proto.h"
-
-
-/* Debug logging */
-/* ------------- */
-
-#define USB_LOG_LEVEL 1
-
-#ifdef USB_LOG_LEVEL
-# define USB_LOG(lvl,...)	if ((lvl) >= USB_LOG_LEVEL) printf(__VA_ARGS__)
-#else
-# define USB_LOG(lvl,...)	do {} while(0)
-#endif
-
-#define USB_LOG_ERR(...)	USB_LOG(1, __VA_ARGS__)
-
-
-/* Internal functions */
-/* ------------------ */
-
-/* Stack */
-struct usb_stack {
-	/* Driver config */
-	const struct usb_stack_descriptors *stack_desc;
-
-	/* Device state */
-	enum usb_dev_state state;
-
-	const struct usb_conf_desc *conf;
-	uint32_t intf_alt;
-
-	/* Timebase */
-	uint32_t tick;
-
-	/* EP configuration */
-	struct {
-		unsigned int mem[2];
-	} ep_cfg;
-
-	/* EP0 control state */
-	struct {
-		enum {
-			IDLE,
-			DATA_IN,		/* Data stage via 'IN'        */
-			DATA_OUT,		/* Data stage via 'OUT'       */
-			STATUS_DONE_OUT,	/* Status sent via 'OUT' EP   */
-			STATUS_DONE_IN,		/* Status sent via 'IN' EP    */
-			STALL,			/* Stalled until next `SETUP` */
-		} state;
-
-		uint8_t buf[64];
-
-		struct usb_xfer xfer;
-		struct usb_ctrl_req req;
-	} ctrl;
-
-	/* Function drivers */
-	struct usb_fn_drv *fnd;
-};
-
-extern struct usb_stack g_usb;
-
-/* Helpers for data access */
-void usb_data_write(unsigned int dst_ofs, const void *src, int len);
-void usb_data_read(void *dst, unsigned int src_ofs, int len);
-
-
-void usb_dispatch_sof(void);
-void usb_dipatch_bus_reset(void);
-void usb_dispatch_state_chg(enum usb_dev_state state);
-enum usb_fnd_resp usb_dispatch_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer);
-enum usb_fnd_resp usb_dispatch_set_conf(const struct usb_conf_desc *desc);
-enum usb_fnd_resp usb_dispatch_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel);
-enum usb_fnd_resp usb_dispatch_get_intf(const struct usb_intf_desc *base, uint8_t *sel);
-
-/* Control */
-void usb_ep0_reset(void);
-void usb_ep0_poll(void);
-
-extern struct usb_fn_drv usb_ctrl_std_drv;

+ 0 - 213
cores/usb/fw/v0/include/no2usb/usb_proto.h

@@ -1,213 +0,0 @@
-/*
- * usb_proto.h
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#include <stdint.h>
-
-
-// Descriptors
-// -----------
-
-enum usb_desc_type {
-	USB_DT_DEV		= 1,
-	USB_DT_CONF		= 2,
-	USB_DT_STR		= 3,
-	USB_DT_INTF		= 4,
-	USB_DT_EP		= 5,
-	USB_DT_DEV_QUAL		= 6,
-	USB_DT_OTHER_SPEED_CONF	= 7,
-	USB_DT_INTF_PWR		= 8,
-	USB_DT_OTG		= 9,
-	USB_DT_DEBUG		= 10,
-	USB_DT_INTF_ASSOC	= 11,
-	USB_DT_DFU		= 33,
-	USB_DT_CS_INTF		= 36,
-	USB_DT_CS_EP		= 37,
-};
-
-struct usb_desc_hdr {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-} __attribute__((packed));
-
-struct usb_dev_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint16_t bcdUSB;
-	uint8_t  bDeviceClass;
-	uint8_t  bDeviceSubClass;
-	uint8_t  bDeviceProtocol;
-	uint8_t  bMaxPacketSize0;
-	uint16_t idVendor;
-	uint16_t idProduct;
-	uint16_t bcdDevice;
-	uint8_t  iManufacturer;
-	uint8_t  iProduct;
-	uint8_t  iSerialNumber;
-	uint8_t  bNumConfigurations;
-} __attribute__((packed));
-
-struct usb_conf_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint16_t wTotalLength;
-	uint8_t  bNumInterfaces;
-	uint8_t  bConfigurationValue;
-	uint8_t  iConfiguration;
-	uint8_t  bmAttributes;
-	uint8_t  bMaxPower;
-} __attribute__((packed));
-
-struct usb_intf_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint8_t  bInterfaceNumber;
-	uint8_t  bAlternateSetting;
-	uint8_t  bNumEndpoints;
-	uint8_t  bInterfaceClass;
-	uint8_t  bInterfaceSubClass;
-	uint8_t  bInterfaceProtocol;
-	uint8_t  iInterface;
-} __attribute__((packed));
-
-struct usb_ep_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint8_t  bEndpointAddress;
-	uint8_t  bmAttributes;
-	uint16_t wMaxPacketSize;
-	uint8_t  bInterval;
-} __attribute__((packed));
-
-struct usb_intf_assoc_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint8_t  bFirstInterface;
-	uint8_t  bInterfaceCount;
-	uint8_t  bFunctionClass;
-	uint8_t  bFunctionSubClass;
-	uint8_t  bFunctionProtocol;
-	uint8_t  iFunction;
-} __attribute__((packed));
-
-struct usb_str_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint16_t wString[];
-} __attribute__((packed));
-
-struct usb_dfu_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint8_t  bmAttributes;
-	uint16_t wDetachTimeOut;
-	uint16_t wTransferSize;
-	uint16_t bcdDFUVersion;
-} __attribute__((packed));
-
-struct usb_cs_intf_hdr_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint8_t  bDescriptorsubtype;
-	uint16_t bcdCDC;
-} __attribute__((packed));
-
-struct usb_cs_intf_acm_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint8_t  bDescriptorsubtype;
-	uint8_t  bmCapabilities;
-} __attribute__((packed));
-
-struct usb_cs_intf_union_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint8_t  bDescriptorsubtype;
-	uint8_t  bMasterInterface;
-	/* uint8_t  bSlaveInterface[]; */
-} __attribute__((packed));
-
-struct usb_cs_intf_call_mgmt_desc {
-	uint8_t  bLength;
-	uint8_t  bDescriptorType;
-	uint8_t  bDescriptorsubtype;
-	uint8_t  bmCapabilities;
-	uint8_t  bDataInterface;
-} __attribute__((packed));
-
-
-// Control requests
-// ----------------
-
-struct usb_ctrl_req {
-	union {
-		struct {
-			uint8_t  bmRequestType;
-			uint8_t  bRequest;
-		};
-		uint16_t wRequestAndType;
-	};
-	uint16_t wValue;
-	uint16_t wIndex;
-	uint16_t wLength;
-} __attribute__((packed,aligned(4)));
-
-#define USB_REQ_RCPT_MSK	(0x1f)
-#define USB_REQ_RCPT(req)	((req)->bmRequestType & USB_REQ_RCPT_MSK)
-#define USB_REQ_RCPT_DEV	(0 << 0)
-#define USB_REQ_RCPT_INTF	(1 << 0)
-#define USB_REQ_RCPT_EP		(2 << 0)
-#define USB_REQ_RCPT_OTHER	(3 << 0)
-
-#define USB_REQ_TYPE_MSK	(0x60)
-#define USB_REQ_TYPE(req)	((req)->bmRequestType & USB_REQ_TYPE_MSK)
-#define USB_REQ_TYPE_STD	(0 << 5)
-#define USB_REQ_TYPE_CLASS	(1 << 5)
-#define USB_REQ_TYPE_VENDOR	(2 << 5)
-#define USB_REQ_TYPE_RSVD	(3 << 5)
-
-#define USB_REQ_TYPE_RCPT(req)	((req)->bmRequestType & (USB_REQ_RCPT_MSK | USB_REQ_TYPE_MSK))
-
-#define USB_REQ_READ		(1 << 7)
-#define USB_REQ_IS_READ(req)	(  (req)->bmRequestType & USB_REQ_READ )
-#define USB_REQ_IS_WRITE(req)	(!((req)->bmRequestType & USB_REQ_READ))
-
-	/* wRequestAndType */
-#define USB_RT_GET_STATUS_DEV		(( 0 << 8) | 0x80)
-#define USB_RT_GET_STATUS_INTF		(( 0 << 8) | 0x81)
-#define USB_RT_GET_STATUS_EP		(( 0 << 8) | 0x82)
-#define USB_RT_CLEAR_FEATURE_DEV	(( 1 << 8) | 0x00)
-#define USB_RT_CLEAR_FEATURE_INTF	(( 1 << 8) | 0x01)
-#define USB_RT_CLEAR_FEATURE_EP		(( 1 << 8) | 0x02)
-#define USB_RT_SET_FEATURE_DEV		(( 3 << 8) | 0x00)
-#define USB_RT_SET_FEATURE_INTF		(( 3 << 8) | 0x01)
-#define USB_RT_SET_FEATURE_EP		(( 3 << 8) | 0x02)
-#define USB_RT_SET_ADDRESS		(( 5 << 8) | 0x00)
-#define USB_RT_GET_DESCRIPTOR		(( 6 << 8) | 0x80)
-#define USB_RT_SET_DESCRIPTOR		(( 7 << 8) | 0x00)
-#define USB_RT_GET_CONFIGURATION	(( 8 << 8) | 0x80)
-#define USB_RT_SET_CONFIGURATION	(( 9 << 8) | 0x00)
-#define USB_RT_GET_INTERFACE		((10 << 8) | 0x81)
-#define USB_RT_SET_INTERFACE		((11 << 8) | 0x01)
-#define USB_RT_SYNCHFRAME		((12 << 8) | 0x82)

+ 0 - 682
cores/usb/fw/v0/src/usb.c

@@ -1,682 +0,0 @@
-/*
- * usb.c
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <no2usb/usb_hw.h>
-#include <no2usb/usb_priv.h>
-#include <no2usb/usb.h>
-
-#include "console.h"
-
-
-/* Main stack state */
-struct usb_stack g_usb;
-
-
-/* Helpers */
-/* ------- */
-
-	/* Data buffer access */
-
-void
-usb_data_write(unsigned int dst_ofs, const void *src, int len)
-{
-	/* FIXME unaligned ofs */
-	const uint32_t *src_u32 = src;
-	volatile uint32_t *dst_u32 = (volatile uint32_t *)((USB_DATA_BASE) + dst_ofs);
-
-	len = (len + 3) >> 2;
-	while (len--)
-		*dst_u32++ = *src_u32++;
-}
-
-void
-usb_data_read (void *dst, unsigned int src_ofs, int len)
-{
-	/* FIXME unaligned ofs */
-	volatile uint32_t *src_u32 = (volatile uint32_t *)((USB_DATA_BASE) + src_ofs);
-	uint32_t *dst_u32 = dst;
-
-	int i = len >> 2;
-
-	while (i--)
-		*dst_u32++ = *src_u32++;
-
-	if ((len &= 3) != 0) {
-		uint32_t x = *src_u32;
-		uint8_t  *dst_u8 = (uint8_t *)dst_u32;
-		while (len--) {
-			*dst_u8++ = x & 0xff;
-			x >>= 8;
-		}
-	}
-}
-
-
-	/* Descriptors */
-
-const void *
-usb_desc_find(const void *sod, const void *eod, uint8_t dt)
-{
-	const uint8_t *sod_p = sod, *eod_p = eod;
-	while ((eod_p - sod_p) >= 2) {
-		if (sod_p[1] == dt)
-			return sod_p;
-		sod_p += sod_p[0];
-	}
-	return NULL;
-}
-
-const void *
-usb_desc_next(const void *sod)
-{
-	const uint8_t *sod_p = sod;
-	return sod_p + sod_p[0];
-}
-
-const struct usb_conf_desc *
-usb_desc_find_conf(uint8_t cfg_value)
-{
-	for (int i=0; i<g_usb.stack_desc->n_conf; i++)
-		if (g_usb.stack_desc->conf[i]->bConfigurationValue == cfg_value)
-			return g_usb.stack_desc->conf[i];
-	return NULL;
-}
-
-const struct usb_intf_desc *
-usb_desc_find_intf(const struct usb_conf_desc *conf, uint8_t idx, uint8_t alt,
-                   const struct usb_intf_desc **alt0)
-{
-	const struct usb_intf_desc *intf = NULL;
-	const void *sod, *eod;
-
-	/* Config select */
-	if (!conf)
-		conf = g_usb.conf;
-	if (!conf)
-		return NULL;
-
-	/* Bound the search */
-	sod = conf;
-	eod = sod + conf->wTotalLength;
-
-	while (1) {
-		sod = usb_desc_find(sod, eod, USB_DT_INTF);
-		if (!sod)
-			break;
-
-		intf = (void*)sod;
-		if (intf->bInterfaceNumber == idx) {
-			if (alt0 && !intf->bAlternateSetting)
-				*alt0 = intf;
-			if (intf->bAlternateSetting == alt)
-				return intf;
-		}
-
-		sod = usb_desc_next(sod);
-	}
-
-	return NULL;
-}
-
-
-	/* Callback dispatching */
-
-void
-usb_dispatch_sof(void)
-{
-	struct usb_fn_drv *p = g_usb.fnd;
-
-	while (p) {
-		if (p->sof)
-			p->sof();
-		p = p->next;
-	}
-}
-
-void
-usb_dipatch_bus_reset(void)
-{
-	struct usb_fn_drv *p = g_usb.fnd;
-
-	while (p) {
-		if (p->bus_reset)
-			p->bus_reset();
-		p = p->next;
-	}
-}
-
-void
-usb_dispatch_state_chg(enum usb_dev_state state)
-{
-	struct usb_fn_drv *p = g_usb.fnd;
-
-	while (p) {
-		if (p->state_chg)
-			p->state_chg(state);
-		p = p->next;
-	}
-}
-
-enum usb_fnd_resp
-usb_dispatch_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	struct usb_fn_drv *p = g_usb.fnd;
-	enum usb_fnd_resp rv = USB_FND_CONTINUE;
-
-	while (p) {
-		if (p->ctrl_req) {
-			rv = p->ctrl_req(req, xfer);
-			if (rv != USB_FND_CONTINUE)
-				return rv;
-		}
-		p = p->next;
-	}
-
-	return rv;
-}
-
-enum usb_fnd_resp
-usb_dispatch_set_conf(const struct usb_conf_desc *desc)
-{
-	struct usb_fn_drv *p = g_usb.fnd;
-	enum usb_fnd_resp rv = USB_FND_SUCCESS;
-
-	while (p) {
-		if (p->set_conf) {
-			if (p->set_conf(desc) == USB_FND_ERROR)
-				rv = USB_FND_ERROR;
-		}
-		p = p->next;
-	}
-
-	return rv;
-}
-
-enum usb_fnd_resp
-usb_dispatch_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
-{
-	struct usb_fn_drv *p = g_usb.fnd;
-	enum usb_fnd_resp rv = USB_FND_CONTINUE;
-
-	while (p) {
-		if (p->set_intf) {
-			rv = p->set_intf(base, sel);
-			if (rv != USB_FND_CONTINUE)
-				return rv;
-		}
-		p = p->next;
-	}
-
-	return rv;
-}
-
-enum usb_fnd_resp
-usb_dispatch_get_intf(const struct usb_intf_desc *base, uint8_t *sel)
-{
-	struct usb_fn_drv *p = g_usb.fnd;
-	enum usb_fnd_resp rv = USB_FND_CONTINUE;
-
-	while (p) {
-		if (p->get_intf) {
-			rv = p->get_intf(base, sel);
-			if (rv != USB_FND_CONTINUE)
-				return rv;
-		}
-		p = p->next;
-	}
-
-	return rv;
-}
-
-
-/* Debug */
-/* ----- */
-
-static void
-_fast_print_hex(uint32_t v)
-{
-	const char _hex[] = "0123456789abcdef";
-	int i;
-
-	for (i=0; i<4; i++) {
-		putchar(_hex[(v & 0xf0) >> 4]);
-		putchar(_hex[ v & 0x0f      ]);
-		putchar(' ');
-		v >>= 8;
-	}
-}
-
-void
-usb_debug_print_ep(int ep, int dir)
-{
-	volatile struct usb_ep *ep_regs = dir ? &usb_ep_regs[ep].in : &usb_ep_regs[ep].out;
-
-	printf("EP%d %s\n", ep, dir ? "IN" : "OUT");
-	printf("\tS     %04x\n", ep_regs->status);
-	printf("\tBD0.0 %04x\n", ep_regs->bd[0].csr);
-	printf("\tBD0.1 %04x\n", ep_regs->bd[0].ptr);
-	printf("\tBD1.0 %04x\n", ep_regs->bd[1].csr);
-	printf("\tBD1.1 %04x\n", ep_regs->bd[1].ptr);
-	printf("\n");
-}
-
-void
-usb_debug_print_data(int ofs, int len)
-{
-	volatile uint32_t *data = (volatile uint32_t *)((USB_DATA_BASE) + (ofs << 2));
-	int i;
-
-	for (i=0; i<len; i++) {
-		_fast_print_hex(*data++);
-		putchar((((i & 3) == 3) | (i == (len-1))) ? '\n' : ' ');
-	}
-	puts("\n");
-}
-
-void
-usb_debug_print(void)
-{
-	printf("Stack:\n");
-	printf("\tState: %d\n", g_usb.state);
-	printf("HW:\n");
-	printf("\tSR   : %04x\n", usb_regs->csr);
-	printf("\tTick : %04x\n", g_usb.tick);
-	printf("\n");
-
-	usb_debug_print_ep(0, 0);
-	usb_debug_print_ep(0, 1);
-
-	printf("Data:\n");
-	usb_debug_print_data(0, 4);
-}
-
-
-/* Internal API */
-/* ------------ */
-
-static volatile struct usb_ep *
-_usb_hw_get_ep(uint8_t ep_addr)
-{
-	return (ep_addr & 0x80) ?
-		&usb_ep_regs[ep_addr & 0xf].in :
-		&usb_ep_regs[ep_addr & 0xf].out;
-}
-
-static void
-_usb_hw_reset_ep(volatile struct usb_ep *ep)
-{
-	ep->status = 0;
-	ep->bd[0].csr = 0;
-	ep->bd[0].ptr = 0;
-	ep->bd[1].csr = 0;
-	ep->bd[1].ptr = 0;
-}
-
-static void
-_usb_hw_reset(bool pu)
-{
-	/* Clear all descriptors */
-	for (int i=0; i<16; i++) {
-		_usb_hw_reset_ep(&usb_ep_regs[i].out);
-		_usb_hw_reset_ep(&usb_ep_regs[i].in);
-	}
-
-	/* Main control */
-	usb_regs->csr = (pu ? USB_CSR_PU_ENA : 0) | USB_CSR_CEL_ENA | USB_CSR_ADDR_MATCH | USB_CSR_ADDR(0);
-	usb_regs->ar  = USB_AR_BUS_RST_CLEAR | USB_AR_SOF_CLEAR | USB_AR_CEL_RELEASE;
-}
-
-static void
-usb_bus_reset(void)
-{
-	/* Reset hw */
-	_usb_hw_reset(true);
-
-	/* Reset memory alloc */
-	g_usb.ep_cfg.mem[0] = 0x80;	// 2 * 64b for EP0 OUT/SETUP
-	g_usb.ep_cfg.mem[1] = 0x40;	// 1 * 64b for EP0 IN
-
-	/* Reset EP0 */
-	usb_ep0_reset();
-
-	/* Dispatch event */
-	usb_dipatch_bus_reset();
-
-	/* Set state */
-	usb_set_state(USB_DS_DEFAULT);
-}
-
-
-/* Exposed API */
-/* ----------- */
-
-void
-usb_init(const struct usb_stack_descriptors *stack_desc)
-{
-	/* Main state reset */
-	memset(&g_usb, 0x00, sizeof(g_usb));
-
-	/* Stack setup */
-	g_usb.state = USB_DS_DISCONNECTED;
-	g_usb.stack_desc = stack_desc;
-
-	usb_register_function_driver(&usb_ctrl_std_drv);
-
-	/* Reset and enable the core */
-	_usb_hw_reset(false);
-}
-
-void
-usb_poll(void)
-{
-	uint32_t csr;
-
-	/* Active ? */
-	if (g_usb.state < USB_DS_CONNECTED)
-		return;
-
-	/* Read CSR */
-	csr = usb_regs->csr;
-
-	/* Check for pending bus reset */
-	if (csr & USB_CSR_BUS_RST_PENDING) {
-		if (csr & USB_CSR_BUS_RST)
-			return;
-		usb_bus_reset();
-	}
-
-	/* If we've not been reset, only reset is of interest */
-	if (g_usb.state < USB_DS_DEFAULT)
-		return;
-
-	/* Supspend handling */
-	if (csr & USB_CSR_BUS_SUSPEND) {
-		if (!(g_usb.state & USB_DS_SUSPENDED)) {
-			usb_set_state(USB_DS_SUSPENDED);
-		}
-		return;
-	} else if (g_usb.state & USB_DS_SUSPENDED) {
-		usb_set_state(USB_DS_RESUME);
-	}
-
-	/* SOF Tick */
-	if (csr & USB_CSR_SOF_PENDING) {
-		g_usb.tick++;
-		usb_regs->ar = USB_AR_SOF_CLEAR;
-		usb_dispatch_sof();
-	}
-
-	/* Check for activity */
-	if (!(csr & USB_CSR_EVT_PENDING))
-		return;
-	csr = usb_regs->evt;
-
-	/* Poll EP0 (control) */
-	usb_ep0_poll();
-}
-
-void
-usb_set_state(enum usb_dev_state new_state)
-{
-	/* Handle resume/suspend 'markers' */
-	if (new_state == USB_DS_RESUME)
-		new_state = g_usb.state & ~USB_DS_SUSPENDED;
-	else if (new_state == USB_DS_SUSPENDED)
-		new_state = g_usb.state | USB_DS_SUSPENDED;
-
-	/* If state is new, update */
-	if (g_usb.state != new_state) {
-		g_usb.state = new_state;
-		usb_dispatch_state_chg(usb_get_state());
-	}
-}
-
-enum usb_dev_state
-usb_get_state(void)
-{
-	return (g_usb.state & USB_DS_SUSPENDED) ? USB_DS_SUSPENDED : g_usb.state;
-}
-
-uint32_t
-usb_get_tick(void)
-{
-	return g_usb.tick;
-}
-
-void
-usb_connect(void)
-{
-	/* Sanity check */
-	if (g_usb.state != USB_DS_DISCONNECTED)
-		return;
-
-	/* Turn-off pull-up */
-	usb_regs->csr |= USB_CSR_PU_ENA;
-
-	/* Stack update */
-	usb_set_state(USB_DS_CONNECTED);
-}
-
-void
-usb_disconnect(void)
-{
-	/* Sanity check */
-	if (g_usb.state < USB_DS_CONNECTED)
-		return;
-
-	/* Turn-off pull-up */
-	usb_regs->csr &= ~USB_CSR_PU_ENA;
-
-	/* Stack state */
-	usb_set_state(USB_DS_DISCONNECTED);
-}
-
-
-void
-usb_set_address(uint8_t addr)
-{
-	usb_regs->csr = USB_CSR_PU_ENA | USB_CSR_CEL_ENA | USB_CSR_ADDR_MATCH | USB_CSR_ADDR(addr);
-}
-
-
-void
-usb_register_function_driver(struct usb_fn_drv *drv)
-{
-	drv->next = g_usb.fnd;
-	g_usb.fnd = drv;
-}
-
-void
-usb_unregister_function_driver(struct usb_fn_drv *drv)
-{
-	struct usb_fn_drv **p = &g_usb.fnd;
-	while (*p) {
-		if (*p == drv) {
-			*p = drv->next;
-			drv->next = NULL;
-			break;
-		}
-		p = &(*p)->next->next;
-	}
-}
-
-
-static volatile struct usb_ep *
-_get_ep_regs(uint8_t ep)
-{
-	return (ep & 0x80) ?
-		&usb_ep_regs[ep & 0xf].in :
-		&usb_ep_regs[ep & 0xf].out;
-}
-
-bool
-usb_ep_is_configured(uint8_t ep)
-{
-	volatile struct usb_ep *epr = _get_ep_regs(ep);
-	uint32_t s = epr->status;
-	return USB_EP_TYPE(s) != USB_EP_TYPE_NONE;
-}
-
-bool
-usb_ep_is_halted(uint8_t ep)
-{
-	volatile struct usb_ep *epr = _get_ep_regs(ep);
-	uint32_t s = epr->status;
-	return USB_EP_TYPE_IS_BCI(s) && (s & USB_EP_TYPE_HALTED);
-}
-
-bool
-usb_ep_halt(uint8_t ep)
-{
-	volatile struct usb_ep *epr = _get_ep_regs(ep);
-	uint32_t s = epr->status;
-	if (!USB_EP_TYPE_IS_BCI(s))
-		return false;
-	epr->status = s | USB_EP_TYPE_HALTED;
-	return true;
-}
-
-bool
-usb_ep_resume(uint8_t ep)
-{
-	volatile struct usb_ep *epr = _get_ep_regs(ep);
-	uint32_t s = epr->status;
-	if (!USB_EP_TYPE_IS_BCI(s))
-		return false;
-	epr->status = s & ~(USB_EP_TYPE_HALTED | USB_EP_DT_BIT); /* DT bit clear needed by CLEAR_FEATURE */
-	return true;
-}
-
-
-
-static uint32_t
-_usb_alloc_buf(unsigned int size, bool in)
-{
-	uint32_t v = g_usb.ep_cfg.mem[in];
-	g_usb.ep_cfg.mem[in] += size;
-	return v;
-}
-
-static bool
-_usb_ep_conf(uint8_t ep_addr, const struct usb_ep_desc *ep)
-{
-	volatile struct usb_ep *ep_regs;
-	uint32_t csr, ml;
-
-	ep_regs = _usb_hw_get_ep(ep_addr);
-
-	csr = ep_regs->status;
-	csr &= USB_EP_BD_DUAL;
-
-	ml = 0;
-
-	if (ep) {
-		const uint8_t types[4] = {
-			USB_EP_TYPE_CTRL,
-			USB_EP_TYPE_ISOC,
-			USB_EP_TYPE_BULK,
-			USB_EP_TYPE_INT,
-		};
-		csr |= types[ep->bmAttributes & 3];
-		ml   = ep->wMaxPacketSize;
-	}
-
-	ep_regs->status = csr;
-	ep_regs->_rsvd[3] = ml;
-	ep_regs->bd[0].csr = 0;
-	ep_regs->bd[1].csr = 0;
-
-	return true;
-}
-
-bool
-usb_ep_reconf(const struct usb_intf_desc *intf, uint8_t ep_addr)
-{
-	const struct usb_conf_desc *conf = g_usb.conf;
-	const struct usb_ep_desc *ep;
-	const void *eod;
-
-	eod = ((uint8_t*)intf) + conf->wTotalLength;
-	ep = (void*) intf;
-
-	for (int i=0; i<intf->bNumEndpoints; i++) {
-		ep = usb_desc_find(usb_desc_next(ep), eod, USB_DT_EP);
-		if (ep->bEndpointAddress == ep_addr)
-			return _usb_ep_conf(ep_addr, ep);
-	}
-
-	return false;
-}
-
-bool
-usb_ep_boot(const struct usb_intf_desc *intf, uint8_t ep_addr, bool dual_bd)
-{
-	const struct usb_conf_desc *conf = g_usb.conf;
-	const struct usb_intf_desc *intf_alt;
-	const struct usb_ep_desc *ep, *ep_def = NULL;
-	const void *eod;
-	volatile struct usb_ep *ep_regs;
-	uint16_t wMaxPacketSize = 0;
-
-	/* Scan all alt config to find the max packet size for that EP */
-	eod = ((uint8_t*)intf) + conf->wTotalLength;
-
-	for (intf_alt=intf;
-		(intf_alt != NULL) && (intf_alt->bInterfaceNumber == intf->bInterfaceNumber);
-		intf_alt = usb_desc_find(usb_desc_next(intf_alt), eod, USB_DT_INTF))
-	{
-		ep = (void*) intf_alt;
-		for (int i=0; i<intf_alt->bNumEndpoints; i++) {
-			ep = usb_desc_find(usb_desc_next(ep), eod, USB_DT_EP);
-			if (ep->bEndpointAddress != ep_addr)
-				continue;
-			if (ep->wMaxPacketSize > wMaxPacketSize)
-				wMaxPacketSize = ep->wMaxPacketSize;
-			if (intf_alt->bAlternateSetting == 0)
-				ep_def = ep;
-			break;
-		}
-	}
-
-	if (!wMaxPacketSize)
-		return false;
-
-	/* Allocate and setup BDs */
-	ep_regs = _usb_hw_get_ep(ep_addr);
-
-	ep_regs->status = dual_bd ? USB_EP_BD_DUAL : 0;
-	ep_regs->_rsvd[2] = wMaxPacketSize;
-
-	for (int i=0; i<(dual_bd?2:1); i++) {
-		ep_regs->bd[i].csr = 0x0000;
-		ep_regs->bd[i].ptr = _usb_alloc_buf(wMaxPacketSize, (ep_addr & 0x80) ? true : false);
-		printf("%02x %d %x\n",ep_addr, i, ep_regs->bd[i].ptr);
-	}
-
-	/* Configure with the altsetting 0 config */
-	return _usb_ep_conf(ep_addr, ep_def);
-}

+ 0 - 389
cores/usb/fw/v0/src/usb_ctrl_ep0.c

@@ -1,389 +0,0 @@
-/*
- * usb_ctrl_ep0.c
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <no2usb/usb_hw.h>
-#include <no2usb/usb_priv.h>
-
-#include "console.h"
-
-#define EP0_PKT_LEN	64
-
-/* Helpers to manipulate BDs */
-
-	/* IN */
-static inline uint32_t
-usb_ep0_in_peek(void)
-{
-	return usb_ep_regs[0].in.bd[0].csr;
-}
-
-static inline void
-usb_ep0_in_clear(void)
-{
-	usb_ep_regs[0].in.bd[0].csr = 0;
-}
-
-static inline void
-usb_ep0_in_queue_data(unsigned int len)
-{
-	usb_ep_regs[0].in.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(len);
-}
-
-static inline void
-usb_ep0_in_queue_stall(void)
-{
-	usb_ep_regs[0].in.bd[0].csr = USB_BD_STATE_RDY_STALL;
-}
-
-	/* OUT */
-static inline uint32_t
-usb_ep0_out_peek(void)
-{
-	return usb_ep_regs[0].out.bd[0].csr;
-}
-
-static inline void
-usb_ep0_out_clear(void)
-{
-	usb_ep_regs[0].out.bd[0].csr = 0;
-}
-
-static inline void
-usb_ep0_out_queue_data(void)
-{
-	usb_ep_regs[0].out.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(EP0_PKT_LEN);
-}
-
-static inline void
-usb_ep0_out_queue_stall(void)
-{
-	usb_ep_regs[0].out.bd[0].csr = USB_BD_STATE_RDY_STALL;
-}
-
-	/* SETUP */
-static inline uint32_t
-usb_ep0_setup_peek(void)
-{
-	return usb_ep_regs[0].out.bd[1].csr;
-}
-
-static inline void
-usb_ep0_setup_clear(void)
-{
-	usb_ep_regs[0].out.bd[1].csr = 0;
-}
-
-static inline void
-usb_ep0_setup_queue_data(void)
-{
-	usb_ep_regs[0].out.bd[1].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(EP0_PKT_LEN);
-}
-
-
-/* Handle control transfers */
-
-static void
-usb_handle_control_data()
-{
-	/* Handle read requests */
-	if (g_usb.ctrl.state == DATA_IN) {
-		/* How much left to do ? */
-		int xflen = g_usb.ctrl.xfer.len - g_usb.ctrl.xfer.ofs;
-		if (xflen > EP0_PKT_LEN)
-			xflen = EP0_PKT_LEN;
-
-		/* Setup descriptor for output */
-		if (xflen)
-			usb_data_write(0, &g_usb.ctrl.xfer.data[g_usb.ctrl.xfer.ofs], xflen);
-		usb_ep0_in_queue_data(xflen);
-
-		/* Move on */
-		g_usb.ctrl.xfer.ofs += xflen;
-
-		/* If we're done, setup the OUT ack */
-		if (xflen < EP0_PKT_LEN) {
-			usb_ep0_out_queue_data();
-			g_usb.ctrl.state = STATUS_DONE_OUT;
-		}
-	}
-
-	/* Handle write requests */
-	if (g_usb.ctrl.state == DATA_OUT) {
-		/* Read off any data we got */
-		uint32_t bds_out = usb_ep0_out_peek();
-
-		if ((bds_out & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK)
-		{
-			/* Read data from USB buffer */
-			int xflen = (bds_out & USB_BD_LEN_MSK) - 2;
-			usb_data_read(&g_usb.ctrl.xfer.data[g_usb.ctrl.xfer.ofs], 0, xflen);
-
-			/* Move on */
-			g_usb.ctrl.xfer.ofs += xflen;
-
-			/* Done with that buffer */
-			usb_ep0_out_clear();
-		}
-
-		/* Next ? */
-		if (g_usb.ctrl.xfer.ofs == g_usb.ctrl.xfer.len)
-		{
-			/* Done, ACK with a ZLP */
-			usb_ep0_in_queue_data(0);
-			g_usb.ctrl.state = STATUS_DONE_IN;
-		}
-		else if ((bds_out & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
-		{
-			/* Submit next BD to fill */
-			usb_ep0_out_queue_data();
-		}
-	}
-}
-
-static void
-usb_handle_control_request(struct usb_ctrl_req *req)
-{
-	enum usb_fnd_resp rv = USB_FND_CONTINUE;
-
-	/* Defaults */
-	g_usb.ctrl.xfer.data = g_usb.ctrl.buf;
-	g_usb.ctrl.xfer.len  = sizeof(g_usb.ctrl.buf);
-	g_usb.ctrl.xfer.ofs     = 0;
-	g_usb.ctrl.xfer.cb_data = NULL;
-	g_usb.ctrl.xfer.cb_done = NULL;
-	g_usb.ctrl.xfer.cb_ctx  = NULL;
-
-	/* Dipatch to all handlers */
-	rv = usb_dispatch_ctrl_req(req, &g_usb.ctrl.xfer);
-
-	/* If the request isn't handled, answer with STALL */
-	if (rv != USB_FND_SUCCESS)
-		goto error;
-
-	/* Buffer size vs request size checks */
-	if (req->wLength > g_usb.ctrl.xfer.len) {
-		if (!USB_REQ_IS_READ(req)) {
-			/* If this is a OUT treansaction and no suitable buffer was
-			 * provided, there isn't much we can do ... */
-			USB_LOG_ERR("[!] Control request handler failed to provide enough buffer space");
-			goto error;
-		}
-	} else {
-		g_usb.ctrl.xfer.len = req->wLength;
-	}
-
-	/* Handle the 'data' stage now */
-	g_usb.ctrl.state = USB_REQ_IS_READ(req) ? DATA_IN : DATA_OUT;
-	usb_handle_control_data();
-
-	return;
-
-	/* Error path */
-error:
-	g_usb.ctrl.state = STALL;
-	usb_ep0_in_queue_stall();
-	usb_ep0_out_queue_stall();
-	return;
-}
-
-
-/* Internally exposed "API" */
-
-void
-usb_ep0_reset(void)
-{
-	/* Reset internal state */
-	g_usb.ctrl.state = IDLE;
-
-	/* Configure EP0 */
-	usb_ep_regs[0].out.status = USB_EP_TYPE_CTRL | USB_EP_BD_CTRL; /* Type=Control, control mode buffered */
-	usb_ep_regs[0].in.status  = USB_EP_TYPE_CTRL | USB_EP_DT_BIT;  /* Type=Control, single buffered, DT=1 */
-
-	/* Setup the BD pointers */
-	usb_ep_regs[0].in.bd[0].ptr  = 0;
-	usb_ep_regs[0].out.bd[0].ptr = 0;
-	usb_ep_regs[0].out.bd[1].ptr = EP0_PKT_LEN;
-
-	/* Clear BD for IN/OUT */
-	usb_ep0_in_clear();
-	usb_ep0_out_clear();
-
-	/* Queue one buffer for SETUP */
-	usb_ep0_setup_queue_data();
-}
-
-void
-usb_ep0_poll(void)
-{
-	uint32_t bds_setup, bds_out, bds_in;
-	bool acted;
-
-	do {
-		/* Not done anything yet */
-		acted = false;
-
-		/* Grab current EP status */
-		bds_setup = usb_ep0_setup_peek();
-		bds_out   = usb_ep0_out_peek();
-		bds_in    = usb_ep0_in_peek();
-
-		/* Check for status IN stage finishing */
-		if (g_usb.ctrl.state == STATUS_DONE_IN) {
-			if ((bds_in & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
-				/* Return to IDLE */
-				g_usb.ctrl.state = IDLE;
-				usb_ep0_in_clear();
-
-				/* Completion Callback */
-				if (g_usb.ctrl.xfer.cb_done)
-					g_usb.ctrl.xfer.cb_done(&g_usb.ctrl.xfer);
-
-				/* Next event */
-				acted = true;
-			}
-		}
-
-		/* Check for status OUT stage finishing */
-		else if (g_usb.ctrl.state == STATUS_DONE_OUT) {
-			if ((bds_in & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
-				/* Done with the last IN BD of this transfer */
-				usb_ep0_in_clear();
-
-				/* Next event */
-				acted = true;
-			}
-			if ((bds_out & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
-				/* Sanity check */
-				if ((bds_out & USB_BD_LEN_MSK) != 2)
-					USB_LOG_ERR("[!] Got a non ZLP as a status stage packet ?!?\n");
-
-				/* Return to IDLE */
-				g_usb.ctrl.state = IDLE;
-				usb_ep0_out_clear();
-
-				/* Completion Callback */
-				if (g_usb.ctrl.xfer.cb_done)
-					g_usb.ctrl.xfer.cb_done(&g_usb.ctrl.xfer);
-
-				/* Next event */
-				acted = true;
-			}
-		}
-
-		/* Check for STALL needing a refresh */
-		else if (g_usb.ctrl.state == STALL) {
-			if ((bds_in & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_STALL) {
-				usb_ep0_in_queue_stall();
-				acted = true;
-			}
-			if ((bds_out & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_STALL) {
-				usb_ep0_out_queue_stall();
-				acted = true;
-			}
-		}
-
-		/* If any of the above was acted upon, we need a refresh */
-		if (acted)
-			continue;
-
-		/* Retry any RX error on both setup and data buffers */
-		if ((bds_setup & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR) {
-			USB_LOG_ERR("[!] Retry SETUP error\n");
-			usb_ep0_setup_queue_data();
-			acted = true;
-			continue;
-		}
-
-		if ((bds_out & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR) {
-			USB_LOG_ERR("[!] Retry OUT error\n");
-			usb_ep0_out_queue_data();
-			acted = true;
-			continue;
-		}
-
-		/* Check for SETUP */
-		if ((bds_setup & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
-			/* Really setup ? */
-			if (!(bds_setup & USB_BD_IS_SETUP)) {
-				USB_LOG_ERR("[!] Got non-SETUP in the SETUP BD !?!\n");
-			}
-
-			/* Were we waiting for this ? */
-			if ((g_usb.ctrl.state != IDLE) && (g_usb.ctrl.state != STALL)) {
-				USB_LOG_ERR("[!] Got SETUP while busy !??\n");
-			}
-
-			/* Clear descriptors */
-			usb_ep0_out_clear();
-			usb_ep0_in_clear();
-
-			/* Make sure DT=1 for IN endpoint after a SETUP */
-			usb_ep_regs[0].in.status = USB_EP_TYPE_CTRL | USB_EP_DT_BIT;  /* Type=Control, single buffered, DT=1 */
-
-			/* We acked it, need to handle it */
-			usb_data_read(&g_usb.ctrl.req, EP0_PKT_LEN, sizeof(struct usb_ctrl_req));
-			usb_handle_control_request(&g_usb.ctrl.req);
-
-			/* Release the lockout and allow new SETUP */
-			usb_regs->ar = USB_AR_CEL_RELEASE;
-			usb_ep0_setup_queue_data();
-
-			return;
-		}
-
-		/* Process data stage */
-		if (((bds_out & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK)) {
-			/* Sanity check */
-			if (g_usb.ctrl.state != DATA_OUT) {
-				USB_LOG_ERR("[!] Got unexpected DATA !?!\n");
-				usb_ep0_out_clear();
-			} else {
-				/* Process data */
-				usb_handle_control_data();
-			}
-
-			/* Next event */
-			acted = true;
-			continue;
-		}
-
-		if ((bds_in & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_OK) {
-			/* Sanity check */
-			if (g_usb.ctrl.state != DATA_IN) {
-				USB_LOG_ERR("[!] Got ack for DATA we didn't send !?!\n");
-				usb_ep0_in_clear();
-			} else {
-				/* Process data */
-				usb_handle_control_data();
-			}
-
-			/* Next event */
-			acted = true;
-			continue;
-		}
-	} while (acted);
-}

+ 0 - 361
cores/usb/fw/v0/src/usb_ctrl_std.c

@@ -1,361 +0,0 @@
-/*
- * usb_ctrl_std.c
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <no2usb/usb_hw.h>
-#include <no2usb/usb_priv.h>
-
-#include "console.h"
-
-
-	/* Control Request implementation */
-
-static bool
-_get_status_dev(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	xfer->data[0] = 0x00;	/* No remote wakeup, bus-powered */
-	xfer->data[1] = 0x00;
-	xfer->len = 2;
-	return true;
-}
-
-static bool
-_get_status_intf(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	/* Check interface exits */
-	if (usb_desc_find_intf(NULL, req->wIndex, 0, NULL))
-		return false;
-
-	/* Nothing to return really */
-	xfer->data[0] = 0x00;
-	xfer->data[1] = 0x00;
-	xfer->len = 2;
-	return true;
-}
-
-static bool
-_get_status_ep(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	uint8_t ep = req->wIndex;
-
-	if (!usb_ep_is_configured(ep))
-		return false;
-
-	xfer->data[0] = usb_ep_is_halted(ep) ? 0x01 : 0x00;
-	xfer->data[1] = 0x00;
-	xfer->len = 2;
-	return true;
-}
-
-static bool
-_clear_feature_dev(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	/* No support for any device feature */
-	return false;
-}
-
-static bool
-_clear_feature_intf(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	/* No support for any interface feature */
-	return false;
-}
-
-static bool
-_clear_feature_ep(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	uint8_t ep = req->wIndex;
-
-	/* Only support ENDPOINT_HALT feature on non-zero EP that exist
-	 * and only when in CONFIGURED state */
-	if ((usb_get_state() < USB_DS_CONFIGURED) ||
-	    (req->wValue != 0) ||	/* ENDPOINT_HALT */
-	    (ep == 0) ||
-	    (!usb_ep_is_configured(ep)))
-		return false;
-
-	/* Resume the EP */
-	return usb_ep_resume(ep);
-}
-
-static bool
-_set_feature_dev(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	/* No support for any device feature */
-	return false;
-}
-
-static bool
-_set_feature_intf(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	/* No support for any interface feature */
-	return false;
-}
-
-static bool
-_set_feature_ep(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	uint8_t ep = req->wIndex;
-
-	/* Only support ENDPOINT_HALT feature on non-zero EP that exist
-	 * and only when in CONFIGURED state */
-	if ((usb_get_state() < USB_DS_CONFIGURED) ||
-	    (req->wValue != 0) ||	/* ENDPOINT_HALT */
-	    (ep == 0) ||
-	    (!usb_ep_is_configured(ep)))
-		return false;
-
-	/* Halt the EP */
-	return usb_ep_halt(ep);
-}
-
-static bool
-_set_addr_done(struct usb_xfer *xfer)
-{
-	struct usb_ctrl_req *req = xfer->cb_ctx;
-	usb_set_address(req->wValue);
-	return true;
-}
-
-static bool
-_set_address(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	xfer->len = 0;
-	xfer->cb_done = _set_addr_done;
-	xfer->cb_ctx = req;
-	return true;
-}
-
-static bool
-_get_descriptor(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	int idx = req->wValue & 0xff;
-
-	xfer->data = NULL;
-
-	switch (req->wValue & 0xff00)
-	{
-	case 0x0100:	/* Device */
-		xfer->data = (void*)g_usb.stack_desc->dev;
-		xfer->len  = g_usb.stack_desc->dev->bLength;
-		break;
-
-	case 0x0200:	/* Configuration */
-		if (idx < g_usb.stack_desc->n_conf) {
-			xfer->data = (void*)g_usb.stack_desc->conf[idx];
-			xfer->len  = g_usb.stack_desc->conf[idx]->wTotalLength;
-		}
-		break;
-
-	case 0x0300:	/* String */
-		if (idx < g_usb.stack_desc->n_str) {
-			xfer->data = (void*)g_usb.stack_desc->str[idx];
-			xfer->len  = g_usb.stack_desc->str[idx]->bLength;
-		}
-		break;
-	}
-
-	return xfer->data != NULL;
-}
-
-static bool
-_get_configuration(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	xfer->data[0] = g_usb.conf ? g_usb.conf->bConfigurationValue : 0;
-	xfer->len = 1;
-	return true;
-}
-
-static bool
-_set_configuration(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	const struct usb_conf_desc *conf = NULL;
-	enum usb_dev_state new_state;
-
-	/* Handle the 'zero' case first */
-	if (req->wValue == 0) {
-		new_state = USB_DS_DEFAULT;
-	} else {
-		/* Find the requested config */
-		for (int i=0; i<g_usb.stack_desc->n_conf; i++)
-			if (g_usb.stack_desc->conf[i]->bConfigurationValue == req->wValue) {
-				conf = g_usb.stack_desc->conf[i];
-				break;
-			}
-
-		if (!conf)
-			return false;
-
-		new_state = USB_DS_CONFIGURED;
-	}
-
-	/* Update state */
-		/* FIXME: configure all endpoint */
-	g_usb.conf = conf;
-	g_usb.intf_alt = 0;
-	usb_set_state(new_state);
-	usb_dispatch_set_conf(g_usb.conf);
-
-	return true;
-}
-
-static bool
-_get_interface(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	const struct usb_intf_desc *intf;
-	uint8_t idx = req->wIndex;
-	uint8_t alt = req->wValue;
-	enum usb_fnd_resp rv;
-
-	/* Check interface exits */
-	if (usb_desc_find_intf(NULL, idx, 0, NULL))
-	if (intf == NULL)
-		return false;
-
-	/* Fast path */
-	if (!(g_usb.intf_alt & (1 << idx))) {
-		xfer->data[0] = 0x00;
-		xfer->len = 1;
-		return true;
-	}
-
-	/* Dispatch for an answer */
-	rv = usb_dispatch_get_intf(intf, &alt);
-	if (rv != USB_FND_SUCCESS)
-		return false;
-
-	/* Setup response */
-	xfer->data[0] = alt;
-	xfer->len = 1;
-
-	return true;
-}
-
-static bool
-_set_interface(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	const struct usb_intf_desc *intf_base, *intf_alt;
-	uint8_t idx = req->wIndex;
-	uint8_t alt = req->wValue;
-	enum usb_fnd_resp rv;
-
-	/* Check interface exits and its altsettings */
-	intf_alt = usb_desc_find_intf(NULL, req->wIndex, alt, &intf_base);
-	if (intf_alt == NULL)
-		return false;
-
-	/* Disable fast path */
-	g_usb.intf_alt |= (1 << idx);
-
-	/* Dispatch enable */
-	rv = usb_dispatch_set_intf(intf_base, intf_alt);
-	if (rv != USB_FND_SUCCESS)
-		return false;
-
-	return true;
-}
-
-
-	/* Control Request dispatch */
-
-static enum usb_fnd_resp
-usb_ctrl_std_handle(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	bool rv = false;
-
-	/* Main dispatch */
-	switch (req->wRequestAndType)
-	{
-	case USB_RT_GET_STATUS_DEV:
-		rv = _get_status_dev(req, xfer);
-		break;
-
-	case USB_RT_GET_STATUS_INTF:
-		rv = _get_status_intf(req, xfer);
-		break;
-
-	case USB_RT_GET_STATUS_EP:
-		rv = _get_status_ep(req, xfer);
-		break;
-
-	case USB_RT_CLEAR_FEATURE_DEV:
-		rv = _clear_feature_dev(req, xfer);
-		break;
-
-	case USB_RT_CLEAR_FEATURE_INTF:
-		rv = _clear_feature_intf(req, xfer);
-		break;
-
-	case USB_RT_CLEAR_FEATURE_EP:
-		rv = _clear_feature_ep(req, xfer);
-		break;
-
-	case USB_RT_SET_FEATURE_DEV:
-		rv = _set_feature_dev(req, xfer);
-		break;
-
-	case USB_RT_SET_FEATURE_INTF:
-		rv = _set_feature_intf(req, xfer);
-		break;
-
-	case USB_RT_SET_FEATURE_EP:
-		rv = _set_feature_ep(req, xfer);
-		break;
-
-	case USB_RT_SET_ADDRESS:
-		rv = _set_address(req, xfer);
-		break;
-
-	case USB_RT_GET_DESCRIPTOR:
-		rv = _get_descriptor(req, xfer);
-		break;
-
-	case USB_RT_GET_CONFIGURATION:
-		rv = _get_configuration(req, xfer);
-		break;
-
-	case USB_RT_SET_CONFIGURATION:
-		rv = _set_configuration(req, xfer);
-		break;
-
-	case USB_RT_GET_INTERFACE:
-		rv = _get_interface(req, xfer);
-		break;
-
-	case USB_RT_SET_INTERFACE:
-		rv = _set_interface(req, xfer);
-		break;
-
-	default:
-		return USB_FND_CONTINUE;
-	}
-
-	return rv ? USB_FND_SUCCESS : USB_FND_ERROR;
-}
-
-struct usb_fn_drv usb_ctrl_std_drv = {
-	.ctrl_req = usb_ctrl_std_handle,
-};

+ 0 - 395
cores/usb/fw/v0/src/usb_dfu.c

@@ -1,395 +0,0 @@
-/*
- * usb_dfu.c
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <no2usb/usb.h>
-#include <no2usb/usb_dfu.h>
-#include <no2usb/usb_dfu_proto.h>
-
-#include "spi.h"
-
-
-#define DFU_VENDOR_PROTO
-#ifdef DFU_VENDOR_PROTO
-enum usb_fnd_resp dfu_vendor_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer);
-#endif
-
-
-#define DFU_POLL_MS		250
-
-
-static const uint32_t dfu_valid_req[_DFU_MAX_STATE] = {
-	/* appIDLE */
-	(1 << USB_REQ_DFU_DETACH) |
-	(1 << USB_REQ_DFU_GETSTATUS) |
-	(1 << USB_REQ_DFU_GETSTATE) |
-	0,
-
-	/* appDETACH */
-	(1 << USB_REQ_DFU_GETSTATUS) |
-	(1 << USB_REQ_DFU_GETSTATE) |
-	0,
-
-	/* dfuIDLE */
-	(1 << USB_REQ_DFU_DETACH) |		/* Non-std */
-	(1 << USB_REQ_DFU_DNLOAD) |
-	(1 << USB_REQ_DFU_UPLOAD) |
-	(1 << USB_REQ_DFU_GETSTATUS) |
-	(1 << USB_REQ_DFU_GETSTATE) |
-	(1 << USB_REQ_DFU_ABORT) |
-	0,
-
-	/* dfuDNLOAD_SYNC */
-	(1 << USB_REQ_DFU_DNLOAD) |
-	(1 << USB_REQ_DFU_GETSTATUS) |
-	(1 << USB_REQ_DFU_GETSTATE) |
-	(1 << USB_REQ_DFU_ABORT) |
-	0,
-
-	/* dfuDNBUSY */
-	0,
-
-	/* dfuDNLOAD_IDLE */
-	(1 << USB_REQ_DFU_DNLOAD) |
-	(1 << USB_REQ_DFU_GETSTATUS) |
-	(1 << USB_REQ_DFU_GETSTATE) |
-	(1 << USB_REQ_DFU_ABORT) |
-	0,
-
-	/* dfuMANIFEST_SYNC */
-	(1 << USB_REQ_DFU_GETSTATUS) |
-	(1 << USB_REQ_DFU_GETSTATE) |
-	(1 << USB_REQ_DFU_ABORT) |
-	0,
-
-	/* dfuMANIFEST */
-	0,
-
-	/* dfuMANIFEST_WAIT_RESET */
-	0,
-
-	/* dfuUPLOAD_IDLE */
-	(1 << USB_REQ_DFU_UPLOAD) |
-	(1 << USB_REQ_DFU_GETSTATUS) |
-	(1 << USB_REQ_DFU_GETSTATE) |
-	(1 << USB_REQ_DFU_ABORT) |
-	0,
-
-	/* dfuERROR */
-	(1 << USB_REQ_DFU_GETSTATUS) |
-	(1 << USB_REQ_DFU_CLRSTATUS) |
-	(1 << USB_REQ_DFU_GETSTATE) |
-	0,
-};
-
-static struct {
-	enum dfu_state state;
-	enum dfu_status status;
-
-	uint8_t tick;
-	uint8_t intf;	// Selected interface number
-	uint8_t alt;	// Selected alt settings
-
-	uint8_t buf[4096] __attribute__((aligned(4)));
-
-	struct {
-		uint32_t addr_prog;
-		uint32_t addr_erase;
-		uint32_t addr_end;
-
-		int op_ofs;
-		int op_len;
-
-		enum {
-			FL_IDLE = 0,
-			FL_ERASE,
-			FL_PROGRAM,
-		} op;
-	} flash;
-} g_dfu;
-
-static const struct {
-	uint32_t start;
-	uint32_t end;
-} dfu_zones[2] = {
-	{ 0x00080000, 0x000a0000 },	/* iCE40 bitstream */
-	{ 0x000a0000, 0x000c0000 },	/* RISC-V firmware */
-};
-
-
-static void
-_dfu_tick(void)
-{
-	/* Rate limit to once every 10 ms */
-	if (g_dfu.tick++ < 10)
-		return;
-
-	g_dfu.tick = 0;
-
-	/* Anything to do ? Is flash ready ? */
-	if ((g_dfu.flash.op == FL_IDLE) || (flash_read_sr() & 1))
-		return;
-
-	/* Erase */
-	if (g_dfu.flash.op == FL_ERASE) {
-		/* Done ? */
-		if (g_dfu.flash.addr_erase >= (g_dfu.flash.addr_prog + g_dfu.flash.op_len)) {
-			/* Yes, move to programming */
-			g_dfu.flash.op = FL_PROGRAM;
-		} else{
-			/* No, issue the next command */
-			flash_write_enable();
-			flash_sector_erase(g_dfu.flash.addr_erase);
-			g_dfu.flash.addr_erase += 4096;
-		}
-	}
-
-	/* Programming */
-	if ((g_dfu.flash.op == FL_PROGRAM) && (g_dfu.state == dfuDNLOAD_SYNC)) {
-		/* Done ? */
-		if (g_dfu.flash.op_ofs == g_dfu.flash.op_len) {
-			/* Yes ! */
-			g_dfu.flash.op = FL_IDLE;
-			g_dfu.state = dfuDNLOAD_IDLE;
-			g_dfu.flash.addr_prog += g_dfu.flash.op_len;
-		} else {
-			/* Max len */
-			unsigned l = g_dfu.flash.op_len - g_dfu.flash.op_ofs;
-			unsigned pl = 256 - ((g_dfu.flash.addr_prog + g_dfu.flash.op_ofs) & 0xff);
-			if (l > pl)
-				l = pl;
-
-			/* Write page */
-			flash_write_enable();
-			flash_page_program(&g_dfu.buf[g_dfu.flash.op_ofs], g_dfu.flash.addr_prog + g_dfu.flash.op_ofs, l);
-
-			/* Next page */
-			g_dfu.flash.op_ofs += l;
-		}
-	}
-}
-
-static void
-_dfu_bus_reset(void)
-{
-	if (g_dfu.state != appDETACH)
-		usb_dfu_cb_reboot();
-}
-
-static void
-_dfu_state_chg(enum usb_dev_state state)
-{
-	if (state == USB_DS_CONFIGURED)
-		g_dfu.state = dfuIDLE;
-}
-
-static bool
-_dfu_detach_done_cb(struct usb_xfer *xfer)
-{
-	usb_dfu_cb_reboot();
-	return true;
-}
-
-static bool
-_dfu_dnload_done_cb(struct usb_xfer *xfer)
-{
-	/* State update */
-	g_dfu.state = dfuDNLOAD_SYNC;
-
-	return true;
-}
-
-static enum usb_fnd_resp
-_dfu_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	uint8_t state;
-
-	/* If this a class or vendor request for DFU interface ? */
-	if (req->wIndex != g_dfu.intf)
-		return USB_FND_CONTINUE;
-
-#ifdef DFU_VENDOR_PROTO
-	if ((USB_REQ_TYPE(req) | USB_REQ_RCPT(req)) == (USB_REQ_TYPE_VENDOR | USB_REQ_RCPT_INTF)) {
-		/* Let vendor code use our large buffer */
-		xfer->data = g_dfu.buf;
-		xfer->len  = sizeof(g_dfu.buf);
-
-		/* Call vendor code */
-		return dfu_vendor_ctrl_req(req, xfer);
-	}
-#endif
-
-	if ((USB_REQ_TYPE(req) | USB_REQ_RCPT(req)) != (USB_REQ_TYPE_CLASS | USB_REQ_RCPT_INTF))
-		return USB_FND_CONTINUE;
-
-	/* Check if this request is allowed in this state */
-	if ((dfu_valid_req[g_dfu.state] & (1 << req->bRequest)) == 0)
-		goto error;
-
-	/* Handle request */
-	switch (req->wRequestAndType)
-	{
-	case USB_RT_DFU_DETACH:
-		/* In theory this should be in runtime mode only but we support
-		 * it as a request to reboot to user mode when in DFU mode */
-		xfer->cb_done = _dfu_detach_done_cb;
-		break;
-
-	case USB_RT_DFU_DNLOAD:
-		/* Check for last block */
-		if (req->wLength) {
-			/* Check length doesn't overflow */
-			if ((g_dfu.flash.addr_erase + req->wLength) > g_dfu.flash.addr_end)
-				goto error;
-
-			/* Setup buffer for data */
-			xfer->len     = req->wLength;
-			xfer->data    = g_dfu.buf;
-			xfer->cb_done = _dfu_dnload_done_cb;
-
-			/* Prepare flash */
-			g_dfu.flash.op_ofs = 0;
-			g_dfu.flash.op_len = req->wLength;
-			g_dfu.flash.op     = FL_ERASE;
-		} else {
-			/* Last xfer */
-			g_dfu.state = dfuIDLE;
-		}
-		break;
-
-	case USB_RT_DFU_UPLOAD:
-		/* Not supported */
-		goto error;
-
-	case USB_RT_DFU_GETSTATUS:
-		/* Update state */
-		if (g_dfu.state == dfuDNLOAD_SYNC) {
-			if (g_dfu.flash.op == FL_IDLE) {
-				g_dfu.state = state = dfuDNLOAD_IDLE;
-			} else {
-				state = dfuDNBUSY;
-			}
-		} else if (g_dfu.state == dfuMANIFEST_SYNC) {
-			g_dfu.state = state = dfuIDLE;
-		} else {
-			state = g_dfu.state;
-		}
-
-		/* Return data */
-		xfer->data[0] = g_dfu.status;
-		xfer->data[1] = (DFU_POLL_MS >>  0) & 0xff;
-		xfer->data[2] = (DFU_POLL_MS >>  8) & 0xff;
-		xfer->data[3] = (DFU_POLL_MS >> 16) & 0xff;
-		xfer->data[4] = state;
-		xfer->data[5] = 0;
-		break;
-
-	case USB_RT_DFU_CLRSTATUS:
-		/* Clear error */
-		g_dfu.state = dfuIDLE;
-		g_dfu.status = OK;
-		break;
-
-	case USB_RT_DFU_GETSTATE:
-		/* Return state */
-		xfer->data[0] = g_dfu.state;
-		break;
-
-	case USB_RT_DFU_ABORT:
-		/* Go to IDLE */
-		g_dfu.state = dfuIDLE;
-		break;
-
-	default:
-		goto error;
-	}
-
-	return USB_FND_SUCCESS;
-
-error:
-	g_dfu.state  = dfuERROR;
-	g_dfu.status = errUNKNOWN;
-	return USB_FND_ERROR;
-}
-
-static enum usb_fnd_resp
-_dfu_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
-{
-	if ((sel->bInterfaceClass != 0xfe) ||
-	    (sel->bInterfaceSubClass != 0x01) ||
-	    (sel->bInterfaceProtocol != 0x02))
-		return USB_FND_CONTINUE;
-
-	g_dfu.state = dfuIDLE;
-	g_dfu.intf  = sel->bInterfaceNumber;
-	g_dfu.alt   = sel->bAlternateSetting;
-
-	g_dfu.flash.addr_prog  = dfu_zones[g_dfu.alt].start;
-	g_dfu.flash.addr_erase = dfu_zones[g_dfu.alt].start;
-	g_dfu.flash.addr_end   = dfu_zones[g_dfu.alt].end;
-
-	return USB_FND_SUCCESS;
-}
-
-static enum usb_fnd_resp
-_dfu_get_intf(const struct usb_intf_desc *base, uint8_t *alt)
-{
-	if ((base->bInterfaceClass != 0xfe) ||
-	    (base->bInterfaceSubClass != 0x01) ||
-	    (base->bInterfaceProtocol != 0x02))
-		return USB_FND_CONTINUE;
-
-	*alt = g_dfu.alt;
-
-	return USB_FND_SUCCESS;
-}
-
-
-static struct usb_fn_drv _dfu_drv = {
-	.sof		= _dfu_tick,
-	.bus_reset      = _dfu_bus_reset,
-	.state_chg	= _dfu_state_chg,
-	.ctrl_req	= _dfu_ctrl_req,
-	.set_intf	= _dfu_set_intf,
-	.get_intf	= _dfu_get_intf,
-};
-
-
-void __attribute__((weak))
-usb_dfu_cb_reboot(void)
-{
-	/* Nothing */
-}
-
-void
-usb_dfu_init(void)
-{
-	memset(&g_dfu, 0x00, sizeof(g_dfu));
-
-	g_dfu.state = appDETACH;
-
-	usb_register_function_driver(&_dfu_drv);
-}

+ 0 - 114
cores/usb/fw/v0/src/usb_dfu_rt.c

@@ -1,114 +0,0 @@
-/*
- * usb_dfu_rt.c
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <no2usb/usb.h>
-#include <no2usb/usb_dfu_rt.h>
-#include <no2usb/usb_dfu_proto.h>
-
-
-#define DFU_POLL_MS		250
-
-static int g_dfu_rt_intf;
-
-static bool
-_dfu_detach_done_cb(struct usb_xfer *xfer)
-{
-        usb_dfu_rt_cb_reboot();
-        return true;
-}
-
-static enum usb_fnd_resp
-_dfu_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	/* If this a class request for DFU interface ? */
-	if ((USB_REQ_TYPE(req) | USB_REQ_RCPT(req)) != (USB_REQ_TYPE_CLASS | USB_REQ_RCPT_INTF))
-		return USB_FND_CONTINUE;
-
-	if (req->wIndex != g_dfu_rt_intf)
-		return USB_FND_CONTINUE;
-
-	/* Handle request */
-	switch (req->wRequestAndType)
-	{
-	case USB_RT_DFU_DETACH:
-		xfer->cb_done = _dfu_detach_done_cb;
-		break;
-
-	case USB_RT_DFU_GETSTATUS:
-		/* Return data */
-		xfer->data[0] = OK;
-		xfer->data[1] = (DFU_POLL_MS >>  0) & 0xff;
-		xfer->data[2] = (DFU_POLL_MS >>  8) & 0xff;
-		xfer->data[3] = (DFU_POLL_MS >> 16) & 0xff;
-		xfer->data[4] = appIDLE;
-		xfer->data[5] = 0;
-		break;
-
-	case USB_RT_DFU_GETSTATE:
-		/* Return state */
-		xfer->data[0] = appIDLE;
-		break;
-
-	default:
-		return USB_FND_ERROR;
-	}
-
-	return USB_FND_SUCCESS;
-}
-
-static enum usb_fnd_resp
-_dfu_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
-{
-	if ((sel->bInterfaceClass != 0xfe) ||
-	    (sel->bInterfaceSubClass != 0x01) ||
-	    (sel->bInterfaceProtocol != 0x01))
-		return USB_FND_CONTINUE;
-
-	g_dfu_rt_intf = base->bInterfaceNumber;
-
-	return USB_FND_SUCCESS;
-}
-
-
-static struct usb_fn_drv _dfu_rt_drv = {
-	.ctrl_req	= _dfu_ctrl_req,
-	.set_intf	= _dfu_set_intf,
-};
-
-
-void __attribute__((weak))
-usb_dfu_rt_cb_reboot(void)
-{
-	/* Nothing */
-}
-
-void
-usb_dfu_rt_init(void)
-{
-	usb_register_function_driver(&_dfu_rt_drv);
-	g_dfu_rt_intf = -1;
-}

+ 0 - 73
cores/usb/fw/v0/src/usb_dfu_vendor.c

@@ -1,73 +0,0 @@
-/*
- * usb_dfu_vendor.c
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <no2usb/usb.h>
-
-#include "spi.h"
-
-
-#define USB_RT_DFU_VENDOR_VERSION	((0 << 8) | 0xc1)
-#define USB_RT_DFU_VENDOR_SPI_EXEC	((1 << 8) | 0x41)
-#define USB_RT_DFU_VENDOR_SPI_RESULT	((2 << 8) | 0xc1)
-
-
-static bool
-_dfu_vendor_spi_exec_cb(struct usb_xfer *xfer)
-{
-	struct spi_xfer_chunk sx[1] = {
-		{ .data = xfer->data, .len = xfer->len, .read = true, .write = true, },
-	};
-	spi_xfer(SPI_CS_FLASH, sx, 1);
-	return true;
-}
-
-enum usb_fnd_resp
-dfu_vendor_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
-{
-	switch (req->wRequestAndType)
-	{
-	case USB_RT_DFU_VENDOR_VERSION:
-		xfer->len  = 2;
-		xfer->data[0] = 0x01;
-		xfer->data[1] = 0x00;
-		break;
-
-	case USB_RT_DFU_VENDOR_SPI_EXEC:
-		xfer->cb_done = _dfu_vendor_spi_exec_cb;
-		break;
-
-	case USB_RT_DFU_VENDOR_SPI_RESULT:
-		/* Really nothing to do, data is already in the buffer, and we serve
-		 * whatever the host requested ... */
-		break;
-
-	default:
-		return USB_FND_ERROR;
-	}
-
-	return USB_FND_SUCCESS;
-}

+ 0 - 34
cores/usb/no2core.mk

@@ -1,34 +0,0 @@
-CORE := no2usb
-
-DEPS_no2usb := no2misc
-
-RTL_SRCS_no2usb := $(addprefix rtl/, \
-	usb.v \
-	usb_crc.v \
-	usb_ep_buf.v \
-	usb_ep_status.v \
-	usb_phy.v \
-	usb_rx_ll.v \
-	usb_rx_pkt.v \
-	usb_trans.v \
-	usb_tx_ll.v \
-	usb_tx_pkt.v \
-)
-
-PREREQ_no2usb = \
-	$(CORE_no2usb_DIR)/rtl/usb_defs.vh \
-	$(BUILD_TMP)/usb_trans_mc.hex \
-	$(BUILD_TMP)/usb_ep_status.hex
-
-TESTBENCHES_no2usb := \
-	usb_ep_buf_tb \
-	usb_tb \
-	usb_tx_tb
-
-include $(NO2BUILD_DIR)/core-magic.mk
-
-$(BUILD_TMP)/usb_trans_mc.hex: $(CORE_no2usb_DIR)/utils/microcode.py
-	$(CORE_no2usb_DIR)/utils/microcode.py > $@
-
-$(BUILD_TMP)/usb_ep_status.hex: $(CORE_no2usb_DIR)/data/usb_ep_status.hex
-	cp -a $< $@

+ 0 - 628
cores/usb/rtl/usb.v

@@ -1,628 +0,0 @@
-/*
- * usb.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb #(
-	parameter         TARGET = "ICE40",
-	parameter integer EPDW = 16,
-	parameter integer EVT_DEPTH = 0,
-
-	/* Auto-set */
-	parameter integer EPAW = 11 - $clog2(EPDW / 8)
-)(
-	// Pads
-	inout  wire pad_dp,
-	inout  wire pad_dn,
-	output reg  pad_pu,
-
-	// EP buffer interface
-	input  wire [EPAW-1:0] ep_tx_addr_0,
-	input  wire [EPDW-1:0] ep_tx_data_0,
-	input  wire ep_tx_we_0,
-
-	input  wire [EPAW-1:0] ep_rx_addr_0,
-	output wire [EPDW-1:0] ep_rx_data_1,
-	input  wire ep_rx_re_0,
-
-	input  wire ep_clk,
-
-	// Bus interface
-	input  wire [11:0] bus_addr,
-	input  wire [15:0] bus_din,
-	output wire [15:0] bus_dout,
-	input  wire bus_cyc,
-	input  wire bus_we,
-	output wire bus_ack,
-
-	// IRQ
-	output wire irq,
-
-	// SOF indication
-	output wire sof,
-
-	// Common
-	input  wire clk,
-	input  wire rst
-);
-
-	// Signals
-	// -------
-
-	// PHY
-	wire phy_rx_dp;
-	wire phy_rx_dn;
-	wire phy_rx_chg;
-
-	wire phy_tx_dp;
-	wire phy_tx_dn;
-	wire phy_tx_en;
-
-	// TX Low-Level
-	wire txll_start;
-	wire txll_bit;
-	wire txll_last;
-	wire txll_ack;
-
-	// TX Packet
-	wire txpkt_start;
-	wire txpkt_done;
-	wire [3:0] txpkt_pid;
-	wire [9:0] txpkt_len;
-	wire [7:0] txpkt_data;
-	wire txpkt_data_ack;
-
-	// RX Low-Level
-	wire [1:0] rxll_sym;
-	wire rxll_bit;
-	wire rxll_valid;
-	wire rxll_eop;
-	wire rxll_sync;
-	wire rxll_bs_skip;
-	wire rxll_bs_err;
-
-	// RX Packet
-	wire rxpkt_start;
-	wire rxpkt_done_ok;
-	wire rxpkt_done_err;
-
-	wire [ 3:0] rxpkt_pid;
-	wire rxpkt_is_sof;
-	wire rxpkt_is_token;
-	wire rxpkt_is_data;
-	wire rxpkt_is_handshake;
-
-	wire [10:0] rxpkt_frameno;
-	wire [ 6:0] rxpkt_addr;
-	wire [ 3:0] rxpkt_endp;
-
-	wire [ 7:0] rxpkt_data;
-	wire rxpkt_data_stb;
-
-	// EP Buffers
-	wire [10:0] buf_tx_addr_0;
-	wire [ 7:0] buf_tx_data_1;
-	wire buf_tx_rden_0;
-
-	wire [10:0] buf_rx_addr_0;
-	wire [ 7:0] buf_rx_data_0;
-	wire buf_rx_wren_0;
-
-	// EP Status
-	wire eps_read_0;
-	wire eps_zero_0;
-	wire eps_write_0;
-	wire [ 7:0] eps_addr_0;
-	wire [15:0] eps_wrdata_0;
-	wire [15:0] eps_rddata_3;
-
-	wire eps_bus_ready;
-	reg  eps_bus_read;
-	wire eps_bus_zero;
-	reg  eps_bus_write;
-	wire [15:0] eps_bus_dout;
-
-	// Config / Status registers
-	reg  cr_pu_ena;
-	reg  cr_cel_ena;
-	reg  cr_addr_chk;
-	reg  [ 6:0] cr_addr;
-
-	wire cel_state;
-	reg  cel_rel;
-
-	// Bus interface
-	reg  csr_bus_req;
-	wire csr_bus_clear;
-	wire csr_bus_ack;
-	reg  [15:0] csr_bus_dout;
-	wire [15:0] csr_readout;
-
-	reg  cr_bus_we;
-
-	reg  eps_bus_req;
-	wire eps_bus_clear;
-	reg  eps_bus_ack_wait;
-	wire eps_bus_req_ok;
-	reg  [2:0] eps_bus_req_ok_dly;
-
-	wire [15:0] evt_rd_data;
-	wire evt_rd_rdy;
-	reg  evt_rd_ack;
-
-	// Events
-	wire [11:0] evt_data;
-	wire evt_stb;
-
-	// Out-of-band conditions
-	wire oob_se0;
-	wire oob_sof;
-
-	reg  [19:0] timeout_suspend;	//  3 ms with no activity
-	reg  [19:0] timeout_reset;		// 10 ms SE0
-
-	wire usb_suspend;
-	wire usb_reset;
-	reg  rst_pending;
-	reg  rst_clear;
-
-	// Start-Of-Frame indication
-	reg  sof_ind;
-	reg  sof_pending;
-	reg  sof_clear;
-
-
-	// PHY
-	// ---
-
-	usb_phy #(
-		.TARGET(TARGET)
-	) phy_I (
-		.pad_dp(pad_dp),
-		.pad_dn(pad_dn),
-		.rx_dp(phy_rx_dp),
-		.rx_dn(phy_rx_dn),
-		.rx_chg(phy_rx_chg),
-		.tx_dp(phy_tx_dp),
-		.tx_dn(phy_tx_dn),
-`ifdef SIM
-		.tx_en(1'b0),
-`else
-		.tx_en(phy_tx_en),
-`endif
-		.clk(clk),
-		.rst(rst)
-	);
-
-
-	// TX
-	// --
-
-	usb_tx_ll tx_ll_I (
-		.phy_tx_dp(phy_tx_dp),
-		.phy_tx_dn(phy_tx_dn),
-		.phy_tx_en(phy_tx_en),
-		.ll_start(txll_start),
-		.ll_bit(txll_bit),
-		.ll_last(txll_last),
-		.ll_ack(txll_ack),
-		.clk(clk),
-		.rst(rst)
-	);
-
-	usb_tx_pkt tx_pkt_I (
-		.ll_start(txll_start),
-		.ll_bit(txll_bit),
-		.ll_last(txll_last),
-		.ll_ack(txll_ack),
-		.pkt_start(txpkt_start),
-		.pkt_done(txpkt_done),
-		.pkt_pid(txpkt_pid),
-		.pkt_len(txpkt_len),
-		.pkt_data(txpkt_data),
-		.pkt_data_ack(txpkt_data_ack),
-		.clk(clk),
-		.rst(rst)
-	);
-
-
-	// RX
-	// --
-
-	usb_rx_ll rx_ll_I (
-		.phy_rx_dp(phy_rx_dp),
-		.phy_rx_dn(phy_rx_dn),
-		.phy_rx_chg(phy_rx_chg),
-		.ll_sym(rxll_sym),
-		.ll_bit(rxll_bit),
-		.ll_valid(rxll_valid),
-		.ll_eop(rxll_eop),
-		.ll_sync(rxll_sync),
-		.ll_bs_skip(rxll_bs_skip),
-		.ll_bs_err(rxll_bs_err),
-		.clk(clk),
-		.rst(rst)
-	);
-
-	usb_rx_pkt rx_pkt_I (
-		.ll_sym(rxll_sym),
-		.ll_bit(rxll_bit),
-		.ll_valid(rxll_valid),
-		.ll_eop(rxll_eop),
-		.ll_sync(rxll_sync),
-		.ll_bs_skip(rxll_bs_skip),
-		.ll_bs_err(rxll_bs_err),
-		.pkt_start(rxpkt_start),
-		.pkt_done_ok(rxpkt_done_ok),
-		.pkt_done_err(rxpkt_done_err),
-		.pkt_pid(rxpkt_pid),
-		.pkt_is_sof(rxpkt_is_sof),
-		.pkt_is_token(rxpkt_is_token),
-		.pkt_is_data(rxpkt_is_data),
-		.pkt_is_handshake(rxpkt_is_handshake),
-		.pkt_frameno(rxpkt_frameno),
-		.pkt_addr(rxpkt_addr),
-		.pkt_endp(rxpkt_endp),
-		.pkt_data(rxpkt_data),
-		.pkt_data_stb(rxpkt_data_stb),
-		.inhibit(phy_tx_en),
-		.clk(clk),
-		.rst(rst)
-	);
-
-
-	// Transaction control
-	// -------------------
-
-	usb_trans trans_I (
-		.txpkt_start(txpkt_start),
-		.txpkt_done(txpkt_done),
-		.txpkt_pid(txpkt_pid),
-		.txpkt_len(txpkt_len),
-		.txpkt_data(txpkt_data),
-		.txpkt_data_ack(txpkt_data_ack),
-		.rxpkt_start(rxpkt_start),
-		.rxpkt_done_ok(rxpkt_done_ok),
-		.rxpkt_done_err(rxpkt_done_err),
-		.rxpkt_pid(rxpkt_pid),
-		.rxpkt_is_sof(rxpkt_is_sof),
-		.rxpkt_is_token(rxpkt_is_token),
-		.rxpkt_is_data(rxpkt_is_data),
-		.rxpkt_is_handshake(rxpkt_is_handshake),
-		.rxpkt_frameno(rxpkt_frameno),
-		.rxpkt_addr(rxpkt_addr),
-		.rxpkt_endp(rxpkt_endp),
-		.rxpkt_data(rxpkt_data),
-		.rxpkt_data_stb(rxpkt_data_stb),
-		.buf_tx_addr_0(buf_tx_addr_0),
-		.buf_tx_data_1(buf_tx_data_1),
-		.buf_tx_rden_0(buf_tx_rden_0),
-		.buf_rx_addr_0(buf_rx_addr_0),
-		.buf_rx_data_0(buf_rx_data_0),
-		.buf_rx_wren_0(buf_rx_wren_0),
-		.eps_read_0(eps_read_0),
-		.eps_zero_0(eps_zero_0),
-		.eps_write_0(eps_write_0),
-		.eps_addr_0(eps_addr_0),
-		.eps_wrdata_0(eps_wrdata_0),
-		.eps_rddata_3(eps_rddata_3),
-		.cr_addr_chk(cr_addr_chk),
-		.cr_addr(cr_addr),
-		.evt_data(evt_data),
-		.evt_stb(evt_stb),
-		.cel_state(cel_state),
-		.cel_rel(cel_rel),
-		.cel_ena(cr_cel_ena),
-		.clk(clk),
-		.rst(rst)
-	);
-
-
-	// EP buffers
-	// ----------
-
-	usb_ep_buf #(
-		.TARGET(TARGET),
-		.RWIDTH(8),
-		.WWIDTH(EPDW)
-	) tx_buf_I (
-		.rd_addr_0(buf_tx_addr_0),
-		.rd_data_1(buf_tx_data_1),
-		.rd_en_0(buf_tx_rden_0),
-		.rd_clk(clk),
-		.wr_addr_0(ep_tx_addr_0),
-		.wr_data_0(ep_tx_data_0),
-		.wr_en_0(ep_tx_we_0),
-		.wr_clk(ep_clk)
-	);
-
-	usb_ep_buf #(
-		.TARGET(TARGET),
-		.RWIDTH(EPDW),
-		.WWIDTH(8)
-	) rx_buf_I (
-		.rd_addr_0(ep_rx_addr_0),
-		.rd_data_1(ep_rx_data_1),
-		.rd_en_0(ep_rx_re_0),
-		.rd_clk(ep_clk),
-		.wr_addr_0(buf_rx_addr_0),
-		.wr_data_0(buf_rx_data_0),
-		.wr_en_0(buf_rx_wren_0),
-		.wr_clk(clk)
-	);
-
-
-	// EP Status / Buffer Descriptors
-	// ------------------------------
-
-	usb_ep_status ep_status_I (
-		.p_addr_0(eps_addr_0),
-		.p_read_0(eps_read_0),
-		.p_zero_0(eps_zero_0),
-		.p_write_0(eps_write_0),
-		.p_din_0(eps_wrdata_0),
-		.p_dout_3(eps_rddata_3),
-		.s_addr_0(bus_addr[7:0]),
-		.s_read_0(eps_bus_ready),
-		.s_zero_0(eps_bus_zero),
-		.s_write_0(eps_bus_write),
-		.s_din_0(bus_din),
-		.s_dout_3(eps_bus_dout),
-		.s_ready_0(eps_bus_ready),
-		.clk(clk),
-		.rst(rst)
-	);
-
-
-	// CSR & Bus Interface
-	// -------------------
-
-	// Request lines for registers and strobes for actions
-	always @(posedge clk)
-		if (csr_bus_clear) begin
-			csr_bus_req <= 1'b0;
-			cr_bus_we   <= 1'b0;
-			cel_rel     <= 1'b0;
-			rst_clear   <= 1'b0;
-			sof_clear   <= 1'b0;
-			evt_rd_ack  <= 1'b0;
-		end else begin
-			csr_bus_req <= 1'b1;
-			cr_bus_we   <= (bus_addr[1:0] == 2'b00) &  bus_we;
-			cel_rel     <= (bus_addr[1:0] == 2'b01) &  bus_we & bus_din[13];
-			rst_clear   <= (bus_addr[1:0] == 2'b01) &  bus_we & bus_din[ 9];
-			sof_clear   <= (bus_addr[1:0] == 2'b01) &  bus_we & bus_din[ 8];
-			evt_rd_ack  <= (bus_addr[1:0] == 2'b10) & ~bus_we & evt_rd_rdy;
-		end
-
-	// Read mux for CSR
-	assign csr_readout = {
-		cr_pu_ena,
-		irq,
-		cel_state,
-		cr_cel_ena,
-		usb_suspend,
-		usb_reset,
-		rst_pending,
-		sof_pending,
-		cr_addr_chk,
-		cr_addr
-	};
-
-	always @(*)
-		if (csr_bus_ack)
-			case (bus_addr[1:0])
-				2'b00:   csr_bus_dout = csr_readout;
-				2'b10:   csr_bus_dout = evt_rd_data;
-				default: csr_bus_dout = 16'h0000;
-			endcase
-		else
-			csr_bus_dout = 16'h0000;
-
-	// CSR Clear/Ack
-	assign csr_bus_ack   = csr_bus_req;
-	assign csr_bus_clear = ~bus_cyc | csr_bus_ack | bus_addr[11];
-
-	// Write regs
-	always @(posedge clk)
-		if (cr_bus_we) begin
-			cr_pu_ena  <= bus_din[15];
-			cr_cel_ena <= bus_din[12];
-			cr_addr_chk<= bus_din[7];
-			cr_addr    <= bus_din[6:0];
-		end
-
-	// Request lines for EP Status access
-	always @(posedge clk)
-		if (eps_bus_clear) begin
-			eps_bus_read  <= 1'b0;
-			eps_bus_write <= 1'b0;
-			eps_bus_req   <= 1'b0;
-		end else begin
-			eps_bus_read  <=  bus_addr[11] & ~bus_we;
-			eps_bus_write <=  bus_addr[11] &  bus_we;
-			eps_bus_req   <=  bus_addr[11];
-		end
-
-	assign eps_bus_zero = ~eps_bus_read;
-
-	// EPS Clear
-	assign eps_bus_clear = ~bus_cyc | eps_bus_ack_wait | (eps_bus_req & eps_bus_ready);
-
-	// Track when request are accepted by the RAM
-	assign eps_bus_req_ok = (eps_bus_req & eps_bus_ready);
-
-	always @(posedge clk)
-		eps_bus_req_ok_dly <= { eps_bus_req_ok_dly[1:0], eps_bus_req_ok & ~bus_we };
-
-	// ACK wait state tracking
-	always @(posedge clk or posedge rst)
-		if (rst)
-			eps_bus_ack_wait <= 1'b0;
-		else
-			eps_bus_ack_wait <= ((eps_bus_ack_wait & ~bus_we) | eps_bus_req_ok) & ~eps_bus_req_ok_dly[2];
-
-	// Bus Ack
-	assign bus_ack = csr_bus_ack | (eps_bus_ack_wait & (bus_we | eps_bus_req_ok_dly[2]));
-
-	// Output is simply the OR of all local units since we force them to zero if
-	// they're not accessed
-	assign bus_dout = csr_bus_dout | eps_bus_dout;
-
-
-	// Event handling
-	// --------------
-
-	generate
-		if (EVT_DEPTH == 0) begin
-			// We just save the # of notify since last read
-			reg [3:0] evt_cnt;
-
-			always @(posedge clk or posedge rst)
-				if (rst)
-					evt_cnt <= 4'h0;
-				else
-					evt_cnt <= evt_rd_ack ? { 3'b000, evt_stb } : (evt_cnt + evt_stb);
-
-			assign evt_rd_rdy = 1'b1;
-			assign evt_rd_data = { evt_cnt, 12'h000 };
-
-			assign irq = (evt_cnt != 4'h0);
-
-		end else if (EVT_DEPTH == 1) begin
-			// Save the latest value and # of notify since last read
-			reg [11:0] evt_last;
-			reg [ 3:0] evt_cnt;
-
-			always @(posedge clk or posedge rst)
-				if (rst)
-					evt_cnt <= 4'h0;
-				else
-					evt_cnt <= evt_rd_ack ? { 3'b000, evt_stb } : (evt_cnt + evt_stb);
-
-			always @(posedge clk)
-				if (evt_stb)
-					evt_last <= evt_data;
-
-			assign evt_rd_rdy = 1'b1;
-			assign evt_rd_data = { evt_cnt, evt_last };
-
-			assign irq = (evt_cnt != 4'h0);
-
-		end else if (EVT_DEPTH > 1) begin
-			// Small shift-reg FIFO
-			wire [11:0] ef_wdata;
-			wire [11:0] ef_rdata;
-			wire ef_wren;
-			wire ef_full;
-			wire ef_rden;
-			wire ef_empty;
-
-			reg  ef_overflow;
-
-			assign ef_wdata = evt_data;
-			assign ef_wren  = evt_stb & ~ef_full;
-
-			always @(posedge clk or posedge rst)
-				if (rst)
-					ef_overflow <= 1'b0;
-				else
-					ef_overflow <= (ef_overflow & ~evt_rd_ack) | (evt_stb & ef_full);
-
-			assign evt_rd_rdy = ~ef_empty;
-			assign evt_rd_data = { ~ef_empty, ef_overflow, 2'b00, ef_rdata };
-			assign ef_rden = evt_rd_ack;
-
-			assign irq = ~ef_rden;
-
-			fifo_sync_shift #(
-				.DEPTH(EVT_DEPTH),
-				.WIDTH(12)
-			) evt_fifo_I (
-				.wr_data(ef_wdata),
-				.wr_ena(ef_wren),
-				.wr_full(ef_full),
-				.rd_data(ef_rdata),
-				.rd_ena(ef_rden),
-				.rd_empty(ef_empty),
-				.clk(clk),
-				.rst(rst)
-			);
-
-		end
-	endgenerate
-
-
-	// USB reset/suspend
-	// -----------------
-
-	// Detect some conditions for triggers
-	assign oob_se0 = ~phy_rx_dp & ~phy_rx_dn;
-	assign oob_sof = rxpkt_start & rxpkt_is_sof;
-
-	// Suspend timeout counter
-	always @(posedge clk)
-		if (oob_sof | usb_reset)
-			timeout_suspend <= 20'hdcd80;	// 3 ms
-		else
-			timeout_suspend <= timeout_suspend + timeout_suspend[19];
-
-	assign usb_suspend = ~timeout_suspend[19];
-
-	// Reset timeout counter
-	always @(posedge clk)
-		if (~oob_se0)
-			timeout_reset <= 20'h8ad00;
-		else
-			timeout_reset <= timeout_reset + timeout_reset[19];
-
-	assign usb_reset = ~timeout_reset[19];
-
-	always @(posedge clk or posedge rst)
-		if (rst)
-			rst_pending <= 1'b1;
-		else
-			rst_pending <= (rst_pending & ~rst_clear) | usb_reset;
-
-	// Detection pin
-	always @(posedge clk)
-		if (rst)
-			pad_pu <= 1'b0;
-		else
-			pad_pu <= cr_pu_ena;
-
-
-	// Misc
-	// ----
-
-	always @(posedge clk)
-		sof_ind <= rxpkt_start & rxpkt_is_sof;
-
-	always @(posedge clk)
-		sof_pending <= (sof_pending & ~sof_clear) | (rxpkt_start & rxpkt_is_sof);
-
-	assign sof = sof_ind;
-
-endmodule // usb

+ 0 - 68
cores/usb/rtl/usb_crc.v

@@ -1,68 +0,0 @@
-/*
- * usb_crc.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb_crc #(
-	parameter integer WIDTH = 5,
-	parameter POLY  = 5'b00011,
-	parameter MATCH = 5'b00000
-)(
-	// Input
-	input  wire in_bit,
-	input  wire in_first,
-	input  wire in_valid,
-
-	// Output (updated 1 cycle after input)
-	output wire [WIDTH-1:0] crc,
-	output wire crc_match,
-
-	// Common
-	input  wire clk,
-	input  wire rst
-);
-
-	reg  [WIDTH-1:0] state;
-	wire [WIDTH-1:0] state_fb_mux;
-	wire [WIDTH-1:0] state_upd_mux;
-	wire [WIDTH-1:0] state_nxt;
-
-	assign state_fb_mux  = state & { WIDTH{~in_first} };
-	assign state_upd_mux = (state_fb_mux[WIDTH-1] == in_bit) ? POLY : 0;
-	assign state_nxt = { state_fb_mux[WIDTH-2:0], 1'b1 } ^ state_upd_mux;
-
-	always @(posedge clk)
-		if (in_valid)
-			state <= state_nxt;
-
-	assign crc_match = (state == ~MATCH);
-
-	genvar i;
-	generate
-		for (i=0; i<WIDTH; i=i+1)
-			assign crc[i] = state[WIDTH-1-i];
-	endgenerate
-
-endmodule // usb_crc

+ 0 - 44
cores/usb/rtl/usb_defs.vh

@@ -1,44 +0,0 @@
-/*
- * usb_defs.vh
- *
- * vim: ts=4 sw=4 syntax=verilog
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-localparam SYM_SE0		= 2'b00;
-localparam SYM_SE1		= 2'b11;
-localparam SYM_J		= 2'b10;
-localparam SYM_K		= 2'b01;
-
-
-localparam PID_OUT		= 4'b0001;
-localparam PID_IN		= 4'b1001;
-localparam PID_SOF		= 4'b0101;
-localparam PID_SETUP	= 4'b1101;
-
-localparam PID_DATA0	= 4'b0011;
-localparam PID_DATA1	= 4'b1011;
-
-localparam PID_ACK		= 4'b0010;
-localparam PID_NAK		= 4'b1010;
-localparam PID_STALL	= 4'b1110;
-
-localparam PID_INVAL	= 4'b0000;

+ 0 - 287
cores/usb/rtl/usb_ep_buf.v

@@ -1,287 +0,0 @@
-/*
- * usb_ep_buf.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb_ep_buf #(
-	parameter TARGET = "ICE40",
-	parameter integer RWIDTH = 8,	// 8/16/32/64
-	parameter integer WWIDTH = 8,	// 8/16/32/64
-	parameter integer AWIDTH = 11,	// Assuming 'byte' access
-
-	parameter integer ARW = AWIDTH - $clog2(RWIDTH / 8),
-	parameter integer AWW = AWIDTH - $clog2(WWIDTH / 8)
-)(
-	// Read port
-	input  wire [ARW-1:0] rd_addr_0,
-	output wire [RWIDTH-1:0] rd_data_1,
-	input  wire rd_en_0,
-	input  wire rd_clk,
-
-	// Write port
-	input  wire [AWW-1:0] wr_addr_0,
-	input  wire [WWIDTH-1:0] wr_data_0,
-	input  wire wr_en_0,
-	input  wire wr_clk
-);
-	// MODE 0:  256 x 16
-	// MODE 1:  512 x 8
-	// MODE 2: 1024 x 4
-	// MODE 3: 2048 x 2
-
-	localparam WRITE_MODE = 3 - $clog2(WWIDTH / 8);
-	localparam READ_MODE  = 3 - $clog2(RWIDTH / 8);
-
-
-	// Helpers to map to the right bits of SB_RAM40_4K
-	// -----------------------------------------------
-
-	function [7:0] ram_rd_map8 (input [15:0] rdata);
-		ram_rd_map8 = {
-			rdata[14],
-			rdata[12],
-			rdata[10],
-			rdata[ 8],
-			rdata[ 6],
-			rdata[ 4],
-			rdata[ 2],
-			rdata[ 0]
-		};
-	endfunction
-
-	function [15:0] ram_wr_map8 (input [7:0] wdata);
-		ram_wr_map8 = {
-			1'b0, wdata[7],	// 14
-			1'b0, wdata[6],	// 12
-			1'b0, wdata[5], // 10
-			1'b0, wdata[4], //  8
-			1'b0, wdata[3], //  6
-			1'b0, wdata[2], //  4
-			1'b0, wdata[1], //  2
-			1'b0, wdata[0]  //  0
-		};
-	endfunction
-
-	function [3:0] ram_rd_map4 (input [15:0] rdata);
-		ram_rd_map4 = {
-			rdata[13],
-			rdata[ 9],
-			rdata[ 5],
-			rdata[ 1]
-		};
-	endfunction
-
-	function [15:0] ram_wr_map4 (input [3:0] wdata);
-		ram_wr_map4 = {
-			2'h0, wdata[3], // 13
-			3'h0, wdata[2], //  9
-			3'h0, wdata[1], //  5
-			3'h0, wdata[0], //  1
-			1'b0
-		};
-	endfunction
-
-	function [1:0] ram_rd_map2 (input [15:0] rdata);
-		ram_rd_map2 = {
-			rdata[11],
-			rdata[ 3]
-		};
-	endfunction
-
-	function [15:0] ram_wr_map2 (input [1:0] wdata);
-		ram_wr_map2 = {
-			4'h0, wdata[1], // 11
-			7'h0, wdata[0], //  3
-			3'h0
-		};
-	endfunction
-
-
-	// Helpers to shuffle bits across blocks
-	// -------------------------------------
-
-	function [63:0] ram_rd_shuffle_64(input [63:0] src);
-		ram_rd_shuffle_64 = {
-			src[63], src[55], src[47], src[39], src[31], src[23], src[15], src[ 7],
-			src[59], src[51], src[43], src[35], src[27], src[19], src[11], src[ 3],
-			src[61], src[53], src[45], src[37], src[29], src[21], src[13], src[ 5],
-			src[57], src[49], src[41], src[33], src[25], src[17], src[ 9], src[ 1],
-			src[62], src[54], src[46], src[38], src[30], src[22], src[14], src[ 6],
-			src[58], src[50], src[42], src[34], src[26], src[18], src[10], src[ 2],
-			src[60], src[52], src[44], src[36], src[28], src[20], src[12], src[ 4],
-			src[56], src[48], src[40], src[32], src[24], src[16], src[ 8], src[ 0]
-		};
-	endfunction
-
-	function [31:0] ram_rd_shuffle_32(input [31:0] src);
-		ram_rd_shuffle_32 = {
-			src[31], src[27], src[23], src[19], src[15], src[11], src[ 7], src[ 3],
-			src[29], src[25], src[21], src[17], src[13], src[ 9], src[ 5], src[ 1],
-			src[30], src[26], src[22], src[18], src[14], src[10], src[ 6], src[ 2],
-			src[28], src[24], src[20], src[16], src[12], src[ 8], src[ 4], src[ 0]
-		};
-	endfunction
-
-	function [15:0] ram_rd_shuffle_16(input [15:0] src);
-		ram_rd_shuffle_16 = {
-			src[15], src[13], src[11], src[ 9], src[ 7], src[ 5], src[ 3], src[ 1],
-			src[14], src[12], src[10], src[ 8], src[ 6], src[ 4], src[ 2], src[ 0]
-		};
-	endfunction
-
-
-	function [63:0] ram_wr_shuffle_64(input [63:0] src);
-		ram_wr_shuffle_64 = {
-			src[63], src[31], src[47], src[15], src[55], src[23], src[39], src[ 7],
-			src[62], src[30], src[46], src[14], src[54], src[22], src[38], src[ 6],
-			src[61], src[29], src[45], src[13], src[53], src[21], src[37], src[ 5],
-			src[60], src[28], src[44], src[12], src[52], src[20], src[36], src[ 4],
-			src[59], src[27], src[43], src[11], src[51], src[19], src[35], src[ 3],
-			src[58], src[26], src[42], src[10], src[50], src[18], src[34], src[ 2],
-			src[57], src[25], src[41], src[ 9], src[49], src[17], src[33], src[ 1],
-			src[56], src[24], src[40], src[ 8], src[48], src[16], src[32], src[ 0]
-		};
-	endfunction
-
-	function [31:0] ram_wr_shuffle_32(input [31:0] src);
-		ram_wr_shuffle_32 = {
-			src[31], src[15], src[23], src[ 7], src[30], src[14], src[22], src[ 6],
-			src[29], src[13], src[21], src[ 5], src[28], src[12], src[20], src[ 4],
-			src[27], src[11], src[19], src[ 3], src[26], src[10], src[18], src[ 2],
-			src[25], src[ 9], src[17], src[ 1], src[24], src[ 8], src[16], src[ 0]
-		};
-	endfunction
-
-	function [15:0] ram_wr_shuffle_16(input [15:0] src);
-		ram_wr_shuffle_16 = {
-			src[15], src[ 7], src[14], src[ 6], src[13], src[ 5], src[12], src[ 4],
-			src[11], src[ 3], src[10], src[ 2], src[ 9], src[ 1], src[ 8], src[ 0]
-		};
-	endfunction
-
-
-	// Storage array
-	// -------------
-
-	initial begin
-		$display("READ_MODE  : %d", READ_MODE);
-		$display("WRITE_MODE : %d", WRITE_MODE);
-	end
-
-	wire [10:0] ram_raddr;
-	wire [10:0] ram_waddr;
-
-	wire [RWIDTH-1:0] rd_data_1_ram;
-	wire [WWIDTH-1:0] wr_data_0_ram;
-
-	genvar i;
-	generate
-		// Map address lines for various modes
-		assign ram_raddr[7:0] = rd_addr_0[ARW-1:ARW-8];
-		assign ram_waddr[7:0] = wr_addr_0[AWW-1:AWW-8];
-
-		if (READ_MODE == 3)
-			assign ram_raddr[10:8] = { rd_addr_0[0], rd_addr_0[1], rd_addr_0[2] };
-		else if (READ_MODE == 2)
-			assign ram_raddr[10:8] = { 1'b0, rd_addr_0[0], rd_addr_0[1] };
-		else if (READ_MODE == 1)
-			assign ram_raddr[10:8] = { 2'b00, rd_addr_0[0] };
-		else
-			assign ram_raddr[10:8] = { 3'b000 };
-
-		if (WRITE_MODE == 3)
-			assign ram_waddr[10:8] = { wr_addr_0[0], wr_addr_0[1], wr_addr_0[2] };
-		else if (WRITE_MODE == 2)
-			assign ram_waddr[10:8] = { 1'b0, wr_addr_0[0], wr_addr_0[1] };
-		else if (WRITE_MODE == 1)
-			assign ram_waddr[10:8] = { 2'b00, wr_addr_0[0] };
-		else
-			assign ram_waddr[10:8] = { 3'b000 };
-
-		// Shuffle the bits
-		if (READ_MODE == 0)
-			assign rd_data_1 = ram_rd_shuffle_64(rd_data_1_ram);
-		else if (READ_MODE == 1)
-			assign rd_data_1 = ram_rd_shuffle_32(rd_data_1_ram);
-		else if (READ_MODE == 2)
-			assign rd_data_1 = ram_rd_shuffle_16(rd_data_1_ram);
-		else
-			assign rd_data_1 = rd_data_1_ram;
-
-		if (WRITE_MODE == 0)
-			assign wr_data_0_ram = ram_wr_shuffle_64(wr_data_0);
-		else if (WRITE_MODE == 1)
-			assign wr_data_0_ram = ram_wr_shuffle_32(wr_data_0);
-		else if (WRITE_MODE == 2)
-			assign wr_data_0_ram = ram_wr_shuffle_16(wr_data_0);
-		else
-			assign wr_data_0_ram = wr_data_0;
-
-		// 4 blocks
-		for (i=0; i<4; i=i+1)
-		begin : block
-			wire [15:0] ram_rdata;
-			wire [15:0] ram_wdata;
-
-			// Block
-			SB_RAM40_4K #(
-				.WRITE_MODE(WRITE_MODE),
-				.READ_MODE(READ_MODE)
-			) ram_I (
-				.RDATA(ram_rdata),
-				.RCLK(rd_clk),
-				.RCLKE(rd_en_0),
-				.RE(1'b1),
-				.RADDR(ram_raddr),
-				.WCLK(wr_clk),
-				.WCLKE(wr_en_0),
-				.WE(1'b1),
-				.WADDR(ram_waddr),
-				.MASK(16'h0000),
-				.WDATA(ram_wdata)
-			);
-
-			// Map the right bits
-			if (READ_MODE == 3)
-				assign rd_data_1_ram[i*2+:2] = ram_rd_map2(ram_rdata);
-			else if (READ_MODE == 2)
-				assign rd_data_1_ram[i*4+:4] = ram_rd_map4(ram_rdata);
-			else if (READ_MODE == 1)
-				assign rd_data_1_ram[i*8+:8] = ram_rd_map8(ram_rdata);
-			else
-				assign rd_data_1_ram[i*16+:16] = ram_rdata;
-
-			if (WRITE_MODE == 3)
-				assign ram_wdata = ram_wr_map2(wr_data_0_ram[i*2+:2]);
-			else if (WRITE_MODE == 2)
-				assign ram_wdata = ram_wr_map4(wr_data_0_ram[i*4+:4]);
-			else if (WRITE_MODE == 1)
-				assign ram_wdata = ram_wr_map8(wr_data_0_ram[i*8+:8]);
-			else
-				assign ram_wdata = wr_data_0_ram[i*16+:16];
-		end
-	endgenerate
-
-endmodule // usb_ep_buf

+ 0 - 121
cores/usb/rtl/usb_ep_status.v

@@ -1,121 +0,0 @@
-/*
- * usb_ep_status.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb_ep_status (
-	// Priority port
-	input  wire [ 7:0] p_addr_0,
-	input  wire        p_read_0,
-	input  wire        p_zero_0,
-	input  wire        p_write_0,
-	input  wire [15:0] p_din_0,
-	output reg  [15:0] p_dout_3,
-
-	// Aux R/W port
-	input  wire [ 7:0] s_addr_0,
-	input  wire        s_read_0,
-	input  wire        s_zero_0,
-	input  wire        s_write_0,
-	input  wire [15:0] s_din_0,
-	output reg  [15:0] s_dout_3,
-	output wire        s_ready_0,
-
-	// Clock / Reset
-	input  wire clk,
-	input  wire rst
-);
-	// Signals
-	wire s_ready_0_i;
-	reg  [ 7:0] addr_1;
-	reg  [15:0] din_1;
-	reg  we_1;
-	reg  p_read_1;
-	reg  p_zero_1;
-	reg  s_read_1;
-	reg  s_zero_1;
-
-	wire [15:0] dout_2;
-	reg  p_read_2;
-	reg  p_zero_2;
-	reg  s_read_2;
-	reg  s_zero_2;
-
-	// "Arbitration"
-	assign s_ready_0_i = ~p_read_0 & ~p_write_0;
-	assign s_ready_0 = s_ready_0_i;
-
-	// Stage 1 : Address mux and Write delay
-	always @(posedge clk)
-	begin
-		addr_1   <= (p_read_0 | p_write_0) ? p_addr_0 : s_addr_0;
-		we_1     <= p_write_0 | (s_write_0 & s_ready_0_i);
-		din_1    <= p_write_0 ? p_din_0 : s_din_0;
-		p_read_1 <= p_read_0;
-		p_zero_1 <= p_zero_0;
-		s_read_1 <= s_read_0 & s_ready_0_i;
-		s_zero_1 <= s_zero_0 & s_ready_0_i;
-	end
-
-	// Stage 2 : Delays
-	always @(posedge clk)
-	begin
-		p_read_2 <= p_read_1 | p_zero_1;
-		p_zero_2 <= p_zero_1;
-		s_read_2 <= s_read_1 | s_zero_1;
-		s_zero_2 <= s_zero_1;
-	end
-
-	// Stage 3 : Output registers
-	always @(posedge clk)
-		if (p_read_2)
-			p_dout_3 <= p_zero_2 ? 16'h0000 : dout_2;
-
-	always @(posedge clk)
-		if (s_read_2)
-			s_dout_3 <= s_zero_2 ? 16'h0000 : dout_2;
-
-	// RAM element
-	SB_RAM40_4K #(
-`ifdef SIM
-		.INIT_FILE("usb_ep_status.hex"),
-`endif
-		.WRITE_MODE(0),
-		.READ_MODE(0)
-	) ebr_I (
-		.RDATA(dout_2),
-		.RADDR({3'b000, addr_1}),
-		.RCLK(clk),
-		.RCLKE(1'b1),
-		.RE(1'b1),
-		.WDATA(din_1),
-		.WADDR({3'b000, addr_1}),
-		.MASK(16'h0000),
-		.WCLK(clk),
-		.WCLKE(we_1),
-		.WE(1'b1)
-	);
-
-endmodule // usb_ep_status

+ 0 - 151
cores/usb/rtl/usb_phy.v

@@ -1,151 +0,0 @@
-/*
- * usb_phy.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb_phy #(
-	parameter TARGET = "ICE40"
-)(
-	// Pads
-	inout  wire pad_dp,
-	inout  wire pad_dn,
-
-	// RX
-	output wire rx_dp,
-	output wire rx_dn,
-	output wire rx_chg,
-
-	// TX
-	input  wire tx_dp,
-	input  wire tx_dn,
-	input  wire tx_en,
-
-	// Common
-	input  wire clk,
-	input  wire rst
-);
-
-	wire [1:0] rx_dp_i;
-	wire [1:0] rx_dn_i;
-	reg  [2:0] dp_state;
-	reg  [2:0] dn_state;
-
-	// IO buffers
-	generate
-		if (TARGET == "ICE40") begin
-
-			SB_IO #(
-				.PIN_TYPE(6'b110100),
-				.PULLUP(1'b0),
-				.NEG_TRIGGER(1'b0),
-				.IO_STANDARD("SB_LVCMOS")
-			) io_dp_I (
-				.PACKAGE_PIN(pad_dp),
-				.LATCH_INPUT_VALUE(1'b0),
-				.CLOCK_ENABLE(1'b1),
-				.INPUT_CLK(clk),
-				.OUTPUT_CLK(clk),
-				.OUTPUT_ENABLE(tx_en),
-				.D_OUT_0(tx_dp),
-				.D_OUT_1(1'b0),
-				.D_IN_0(rx_dp_i[0]),
-				.D_IN_1(rx_dp_i[1])
-			);
-
-			SB_IO #(
-				.PIN_TYPE(6'b110100),
-				.PULLUP(1'b0),
-				.NEG_TRIGGER(1'b0),
-				.IO_STANDARD("SB_LVCMOS")
-			) io_dn_I (
-				.PACKAGE_PIN(pad_dn),
-				.LATCH_INPUT_VALUE(1'b0),
-				.CLOCK_ENABLE(1'b1),
-				.INPUT_CLK(clk),
-				.OUTPUT_CLK(clk),
-				.OUTPUT_ENABLE(tx_en),
-				.D_OUT_0(tx_dn),
-				.D_OUT_1(1'b0),
-				.D_IN_0(rx_dn_i[0]),
-				.D_IN_1(rx_dn_i[1])
-			);
-
-		end
-	endgenerate
-
-	// Input sync, filter and change detect
-	always @(posedge clk or posedge rst)
-	begin
-		if (rst) begin
-			dp_state <= 3'b000;
-			dn_state <= 3'b000;
-		end else begin
-			case ({dp_state[1:0], rx_dp_i})
-				4'b0000: dp_state <= 3'b000;
-				4'b0001: dp_state <= 3'b001;
-				4'b0010: dp_state <= 3'b001;
-				4'b0011: dp_state <= 3'b001;
-				4'b0100: dp_state <= 3'b000;
-				4'b0101: dp_state <= 3'b001;
-				4'b0110: dp_state <= 3'b001;
-				4'b0111: dp_state <= 3'b111;
-				4'b1000: dp_state <= 3'b100;
-				4'b1001: dp_state <= 3'b010;
-				4'b1010: dp_state <= 3'b010;
-				4'b1011: dp_state <= 3'b011;
-				4'b1100: dp_state <= 3'b010;
-				4'b1101: dp_state <= 3'b010;
-				4'b1110: dp_state <= 3'b010;
-				4'b1111: dp_state <= 3'b011;
-				default: dp_state <= 3'bxxx;
-			endcase
-
-			case ({dn_state[1:0], rx_dn_i})
-				4'b0000: dn_state <= 3'b000;
-				4'b0001: dn_state <= 3'b001;
-				4'b0010: dn_state <= 3'b001;
-				4'b0011: dn_state <= 3'b001;
-				4'b0100: dn_state <= 3'b000;
-				4'b0101: dn_state <= 3'b001;
-				4'b0110: dn_state <= 3'b001;
-				4'b0111: dn_state <= 3'b111;
-				4'b1000: dn_state <= 3'b100;
-				4'b1001: dn_state <= 3'b010;
-				4'b1010: dn_state <= 3'b010;
-				4'b1011: dn_state <= 3'b011;
-				4'b1100: dn_state <= 3'b010;
-				4'b1101: dn_state <= 3'b010;
-				4'b1110: dn_state <= 3'b010;
-				4'b1111: dn_state <= 3'b011;
-				default: dn_state <= 3'bxxx;
-			endcase
-		end
-	end
-
-	assign rx_dp  = dp_state[1];
-	assign rx_dn  = dn_state[1];
-	assign rx_chg = dp_state[2] | dn_state[2];
-
-endmodule // usb_phy

+ 0 - 213
cores/usb/rtl/usb_rx_ll.v

@@ -1,213 +0,0 @@
-/*
- * usb_rx_ll.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb_rx_ll (
-	// PHY
-	input  wire phy_rx_dp,
-	input  wire phy_rx_dn,
-	input  wire phy_rx_chg,
-
-	// Low-Level
-	output wire [1:0] ll_sym,
-	output wire ll_bit,
-	output wire ll_valid,
-	output wire ll_eop,
-	output wire ll_sync,
-	output wire ll_bs_skip,
-	output wire ll_bs_err,
-
-	// Common
-	input  wire clk,
-	input  wire rst
-);
-
-	// Signals
-	// -------
-
-	// Sampling
-	reg        samp_active;
-	(* keep="true" *) wire samp_sync;
-	reg  [2:0] samp_cnt;
-	wire [1:0] samp_sym_0;
-	reg        samp_valid_0;
-
-	// Decoding
-	(* keep="true" *) wire dec_sym_same_0;
-	(* keep="true" *) wire dec_sym_se_0;	/* Symbol is SE0 or SE1 */
-	reg  [2:0] dec_eop_state_1;
-	reg  [3:0] dec_sync_state_1;
-	reg  [3:0] dec_rep_state_1;
-
-	reg  [1:0] dec_sym_1 = 2'b00;			/* Init is for simulation benefit only */
-	reg        dec_bit_1;
-	reg        dec_valid_1;
-	wire       dec_eop_1;
-	wire       dec_sync_1;
-	wire [2:0] dec_rep_1;
-	reg        dec_bs_skip_1;
-	wire       dec_bs_err_1;
-
-
-	// Sampling
-	// --------
-
-	// Active
-		// The EOP and Error signals are from the next stage, but the pipeline
-		// violation doesn't matter, we just want to stop before the next
-		// packet so that the resync works well at the beginning of the next
-		// packet.
-	always @(posedge clk or posedge rst)
-		if (rst)
-			samp_active <= 1'b0;
-		else
-			samp_active <= (samp_active | phy_rx_chg) & ~(dec_valid_1 & (dec_eop_1 | dec_bs_err_1));
-
-	// When to resync
-	assign samp_sync = ~samp_active | (~samp_cnt[2] && phy_rx_chg);
-
-	// Sampling phase tracking
-	always @(posedge clk)
-		if (samp_sync)
-			samp_cnt <= 3'b101;
-		else
-			/* The following case implements :
-			 * samp_cnt <= (samp_cnt - 1) & { samp_cnt[2], 2'b11 };
-			 * but in a way that synthesis understands well */
-			case (samp_cnt)
-				3'b000:  samp_cnt <= 3'b011;
-				3'b001:  samp_cnt <= 3'b000;
-				3'b010:  samp_cnt <= 3'b001;
-				3'b011:  samp_cnt <= 3'b010;
-				3'b100:  samp_cnt <= 3'b011;
-				3'b101:  samp_cnt <= 3'b100;
-				3'b110:  samp_cnt <= 3'b101;
-				3'b111:  samp_cnt <= 3'b110;
-				default: samp_cnt <= 3'bxxx;
-			endcase
-
-	// Output to next stage
-	always @(posedge clk)
-		samp_valid_0 <= samp_active & (samp_cnt[1:0] == 2'b01) & ~samp_valid_0;
-
-	assign samp_sym_0 = { phy_rx_dp, phy_rx_dn };
-
-
-	// Bit de-stuffing & NRZI
-	// ----------------------
-
-	// Compare with previous
-	assign dec_sym_same_0 = (samp_sym_0 == dec_sym_1);
-	assign dec_sym_se_0 = ~^samp_sym_0;
-
-	// Symbol and Bit-value
-	always @(posedge clk)
-		if (samp_valid_0)
-		begin
-			dec_sym_1 <= samp_sym_0;
-			dec_bit_1 <= (samp_sym_0[0]  ^ samp_sym_0[1]) &	// Symbol is J or K
-			             (dec_sym_1[0]   ^ dec_sym_1[1]) &	// Previous symbol is J or K
-			             ~(samp_sym_0[1] ^ dec_sym_1[1]);	// Same symbol
-		end
-
-	always @(posedge clk)
-		dec_valid_1 <= samp_valid_0;
-
-	// EOP detect
-	always @(posedge clk)
-		if (samp_valid_0)
-			case ({dec_eop_state_1[1:0], samp_sym_0})
-				4'b0000: dec_eop_state_1 <= 3'b001;	// SE0
-				4'b0100: dec_eop_state_1 <= 3'b010;	// SE0
-				4'b1000: dec_eop_state_1 <= 3'b010;	// We should get J but maybe we tolerate >2 SE0 ?
-				4'b1010: dec_eop_state_1 <= 3'b111; // J
-				default: dec_eop_state_1 <= 3'b000;
-			endcase
-
-	assign dec_eop_1 = dec_eop_state_1[2];
-
-	// Sync tracking
-	always @(posedge clk)
-		if (samp_valid_0)
-		begin
-			if (dec_sym_se_0)
-				dec_sync_state_1 <= 4'b0000;
-			else
-				casez ({dec_sync_state_1[2:0], samp_sym_0[1]})
-					4'b0000: dec_sync_state_1 <= 4'b0001;
-					4'b0011: dec_sync_state_1 <= 4'b0010;
-					4'b0100: dec_sync_state_1 <= 4'b0011;
-					4'b0111: dec_sync_state_1 <= 4'b0100;
-					4'b1000: dec_sync_state_1 <= 4'b0101;
-					4'b1011: dec_sync_state_1 <= 4'b0110;
-					4'b1100: dec_sync_state_1 <= 4'b0111;
-					4'b1110: dec_sync_state_1 <= 4'b1001;
-					4'b???0: dec_sync_state_1 <= 4'b0001;
-					default: dec_sync_state_1 <= 4'b0000;
-				endcase
-		end
-
-	assign dec_sync_1 = dec_sync_state_1[3];
-
-	// Repeat tracking
-	always @(posedge clk)
-		if (samp_valid_0)
-			if (dec_sym_same_0 == 1'b0)
-				dec_rep_state_1 <= 4'b0000;
-			else
-				// This is basically a saturated increment with flag for >=6
-				case (dec_rep_state_1[2:0])
-					3'b000:  dec_rep_state_1 <= 4'b0001;
-					3'b001:  dec_rep_state_1 <= 4'b0010;
-					3'b010:  dec_rep_state_1 <= 4'b0011;
-					3'b011:  dec_rep_state_1 <= 4'b0100;
-					3'b100:  dec_rep_state_1 <= 4'b0101;
-					3'b101:  dec_rep_state_1 <= 4'b0110;
-					3'b110:  dec_rep_state_1 <= 4'b1111;
-					3'b111:  dec_rep_state_1 <= 4'b1111;
-					default: dec_rep_state_1 <= 4'bxxxx;
-				endcase
-
-	assign dec_bs_err_1  = dec_rep_state_1[3];
-	assign dec_rep_1     = dec_rep_state_1[2:0];
-
-	always @(posedge clk)
-		if (samp_valid_0)
-			dec_bs_skip_1 <= (dec_rep_state_1[2:0] == 3'b110);
-
-
-	// Output
-	// ------
-
-	assign ll_sym     = dec_sym_1;
-	assign ll_bit     = dec_bit_1;
-	assign ll_valid   = dec_valid_1;
-	assign ll_eop     = dec_eop_1;
-	assign ll_sync    = dec_sync_1;
-	assign ll_bs_skip = dec_bs_skip_1;
-	assign ll_bs_err  = dec_bs_err_1;
-
-endmodule // usb_rx_ll

+ 0 - 393
cores/usb/rtl/usb_rx_pkt.v

@@ -1,393 +0,0 @@
-/*
- * usb_rx_pkt.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb_rx_pkt (
-	// Low-Level
-	input  wire [1:0] ll_sym,
-	input  wire ll_bit,
-	input  wire ll_valid,
-	input  wire ll_eop,
-	input  wire ll_sync,
-	input  wire ll_bs_skip,
-	input  wire ll_bs_err,
-
-	// Packet interface
-	output reg  pkt_start,
-	output reg  pkt_done_ok,
-	output reg  pkt_done_err,
-
-	output wire [ 3:0] pkt_pid,
-	output wire pkt_is_sof,
-	output wire pkt_is_token,
-	output wire pkt_is_data,
-	output wire pkt_is_handshake,
-
-	output wire [10:0] pkt_frameno,
-	output wire [ 6:0] pkt_addr,
-	output wire [ 3:0] pkt_endp,
-
-	output wire [ 7:0] pkt_data,
-	output reg  pkt_data_stb,
-
-	// Control
-	input  wire inhibit,
-
-	// Common
-	input  wire clk,
-	input  wire rst
-);
-
-	`include "usb_defs.vh"
-
-
-	// FSM
-	// ---
-
-	localparam
-		ST_IDLE      = 0,
-		ST_PID       = 1,
-		ST_PID_CHECK = 2,
-		ST_ERROR     = 3,
-		ST_TOKEN_1   = 4,
-		ST_TOKEN_2   = 5,
-		ST_WAIT_EOP  = 6,
-		ST_DATA      = 7;
-
-
-	// Signals
-	// -------
-
-	// FSM
-	reg  [3:0] state_nxt;
-	reg  [3:0] state;
-
-	reg state_prev_idle;
-	reg state_prev_error;
-
-	// Utils
-	wire llu_bit_stb;
-	wire llu_byte_stb;
-
-	// Data shift reg & bit counting
-	wire [7:0] data_nxt;
-	reg  [7:0] data;
-	reg  [3:0] bit_cnt;
-	reg  bit_eop_ok;
-	wire bit_last;
-
-	// CRC checking
-	wire crc_in_bit;
-	wire crc_in_valid;
-	reg  crc_in_first;
-
-	reg  crc_cap;
-
-	wire crc5_match;
-	reg  crc5_ok;
-
-	wire crc16_match;
-	reg  crc16_ok;
-
-	// PID capture and decoding
-	wire pid_cap;
-	reg  pid_cap_r;
-	reg  pid_valid;
-	reg  [3:0] pid;
-	reg  pid_is_sof;
-	reg  pid_is_token;
-	reg  pid_is_data;
-	reg  pid_is_handshake;
-
-	// TOKEN data capture
-	reg [10:0] token_data;
-
-
-	// Main FSM
-	// --------
-
-	// Next state logic
-	always @(*)
-	begin
-		// Default is to stay put
-		state_nxt = state;
-
-		// Main case
-		case (state)
-			ST_IDLE:
-				// Wait for SYNC to be detected
-				if (ll_valid && ll_sync && ~inhibit)
-					state_nxt = ST_PID;
-
-			ST_PID:
-				// Wait for PID capture
-				if (llu_byte_stb)
-					state_nxt = ST_PID_CHECK;
-
-			ST_PID_CHECK: begin
-				// Default is to error if no match
-				state_nxt = ST_ERROR;
-
-				// Select state depending on packet type
-				if (pid_valid) begin
-					if (pid_is_sof)
-						state_nxt = ST_TOKEN_1;
-					else if (pid_is_token)
-						state_nxt = ST_TOKEN_1;
-					else if (pid_is_data)
-						state_nxt = ST_DATA;
-					else if (pid_is_handshake)
-						state_nxt = ST_WAIT_EOP;
-				end
-			end
-
-			ST_ERROR:
-				// Error, wait for a possible IDLE state to resume
-				if (ll_valid && (ll_eop || (ll_bs_err && (ll_sym == SYM_J))))
-					state_nxt = ST_IDLE;
-
-			ST_TOKEN_1:
-				// First data byte
-				if (ll_valid && ll_eop)
-					state_nxt = ST_ERROR;
-				else if (llu_byte_stb)
-					state_nxt = ST_TOKEN_2;
-
-			ST_TOKEN_2:
-				// Second data byte
-				if (ll_valid && ll_eop)
-					state_nxt = ST_ERROR;
-				else if (llu_byte_stb)
-					state_nxt = ST_WAIT_EOP;
-
-			ST_WAIT_EOP:
-				// Need EOP at the right place
-				if (ll_valid && ll_eop)
-					state_nxt = (bit_eop_ok & (crc5_ok | pid_is_handshake)) ? ST_IDLE : ST_ERROR;
-				else if (llu_byte_stb)
-					state_nxt = ST_ERROR;
-
-			ST_DATA:
-				if (ll_valid) begin
-					if (ll_eop)
-						state_nxt = (bit_eop_ok & crc16_ok) ? ST_IDLE : ST_ERROR;
-					else if (ll_bs_err)
-						state_nxt = ST_ERROR;
-				end
-		endcase
-	end
-
-	// State register
-	always @(posedge clk or posedge rst)
-		if (rst)
-			state <= ST_IDLE;
-		else
-			state <= state_nxt;
-
-
-	// Utility signals
-	// ---------------
-
-	always @(posedge clk)
-	begin
-		state_prev_idle  <= (state == ST_IDLE);
-		state_prev_error <= (state == ST_ERROR);
-	end
-
-	assign llu_bit_stb  = ll_valid & ~ll_bs_skip;
-	assign llu_byte_stb = ll_valid & ~ll_bs_skip & bit_last;
-
-
-	// Data shift register and bit counter
-	// -----------------------------------
-
-	// Next word
-	assign data_nxt = { ll_bit, data[7:1] };
-
-	// Shift reg
-	always @(posedge clk)
-		if (llu_bit_stb)
-			data <= data_nxt;
-
-	// Bit counter
-	always @(posedge clk)
-		if (state == ST_IDLE)
-			bit_cnt <= 4'b0110;
-		else if (llu_bit_stb)
-			bit_cnt <= { 1'b0, bit_cnt[2:0] } - 1;
-
-	// Last bit ?
-	assign bit_last = bit_cnt[3];
-
-	// EOP OK at this position ?
-	always @(posedge clk)
-		if (state == ST_IDLE)
-			bit_eop_ok <= 1'b0;
-		else if (llu_bit_stb)
-			bit_eop_ok <= (bit_cnt[2:1] == 2'b10);
-
-
-	// CRC checks
-	// ----------
-
-	// CRC input data
-	assign crc_in_bit   = ll_bit;
-	assign crc_in_valid = llu_bit_stb;
-
-	always @(posedge clk)
-		if (state == ST_PID)
-			crc_in_first <= 1'b1;
-		else if (crc_in_valid)
-			crc_in_first <= 1'b0;
-
-	// CRC5 core
-	usb_crc #(
-		.WIDTH(5),
-		.POLY(5'b00101),
-		.MATCH(5'b01100)
-	) crc_5_I (
-		.in_bit(crc_in_bit),
-		.in_first(crc_in_first),
-		.in_valid(crc_in_valid),
-		.crc(),
-		.crc_match(crc5_match),
-		.clk(clk),
-		.rst(rst)
-	);
-
-	// CRC16 core
-	usb_crc #(
-		.WIDTH(16),
-		.POLY(16'h8005),
-		.MATCH(16'h800D)
-	) crc_16_I (
-		.in_bit(crc_in_bit),
-		.in_first(crc_in_first),
-		.in_valid(crc_in_valid),
-		.crc(),
-		.crc_match(crc16_match),
-		.clk(clk),
-		.rst(rst)
-	);
-
-	// Capture CRC status at end of each byte
-		// This will be a bit 'late' (i.e. a couple cycles after the last
-		// bit was input), but it's only used when EOP happens, which is
-		// many cycles after that, so this delay is fine
-	always @(posedge clk)
-		crc_cap <= llu_byte_stb;
-
-	always @(posedge clk)
-		if (state == ST_IDLE) begin
-			crc5_ok <= 1'b0;
-			crc16_ok <= 1'b0;
-		end else if (crc_cap) begin
-			crc5_ok  <= crc5_match;
-			crc16_ok <= crc16_match;
-		end
-
-
-	// PID capture and decoding
-	// ------------------------
-
-	// When to capture
-	assign pid_cap = (state == ST_PID) & llu_byte_stb;
-
-	// Check PID before capture
-	always @(posedge clk)
-		if (pid_cap)
-			pid_valid <= (data_nxt[3:0] == ~data_nxt[7:4]) && (
-				(data_nxt[3:0] == PID_SOF)   ||
-				(data_nxt[3:0] == PID_OUT)   ||
-				(data_nxt[3:0] == PID_IN)    ||
-				(data_nxt[3:0] == PID_SETUP) ||
-				(data_nxt[3:0] == PID_DATA0) ||
-				(data_nxt[3:0] == PID_DATA1) ||
-				(data_nxt[3:0] == PID_ACK)   ||
-				(data_nxt[3:0] == PID_NAK)   ||
-				(data_nxt[3:0] == PID_STALL)
-			);
-
-	always @(posedge clk)
-		pid_cap_r <= pid_cap;
-
-	// Capture and decode
-	always @(posedge clk)
-		if ((state == ST_PID) && llu_byte_stb)
-		begin
-			pid              <=  data_nxt;
-			pid_is_sof       <= (data_nxt[3:0] == PID_SOF);
-			pid_is_token     <= (data_nxt[3:0] == PID_OUT) || (data_nxt[3:0] == PID_IN) || (data_nxt[3:0] == PID_SETUP);
-			pid_is_data      <= (data_nxt[3:0] == PID_DATA0) || (data_nxt[3:0] == PID_DATA1);
-			pid_is_handshake <= (data_nxt[3:0] == PID_ACK) || (data_nxt[3:0] == PID_NAK) || (data_nxt[3:0] == PID_STALL);
-		end
-
-
-	// TOKEN data capture
-	// ------------------
-
-	always @(posedge clk)
-		if ((state == ST_TOKEN_1) && llu_byte_stb)
-			token_data[7:0] <= data_nxt[7:0];
-
-	always @(posedge clk)
-		if ((state == ST_TOKEN_2) && llu_byte_stb)
-			token_data[10:8] <= data_nxt[2:0];
-
-
-	// Output
-	// ------
-
-	// Generate pkt_start on PID capture
-	always @(posedge clk)
-		pkt_start <= pid_cap_r & pid_valid;
-
-	// Generate packet done signals
-	always @(posedge clk)
-	begin
-		pkt_done_ok  <= (state == ST_IDLE)  && !state_prev_idle && !state_prev_error;
-		pkt_done_err <= (state == ST_ERROR) && !state_prev_error;
-	end
-
-	// Output PID and decoded
-	assign pkt_pid          = pid;
-	assign pkt_is_sof       = pid_is_sof;
-	assign pkt_is_token     = pid_is_token;
-	assign pkt_is_data      = pid_is_data;
-	assign pkt_is_handshake = pid_is_handshake;
-
-	// Output token data
-	assign pkt_frameno = token_data;
-	assign pkt_addr    = token_data[ 6:0];
-	assign pkt_endp    = token_data[10:7];
-
-	// Data byte and associated strobe
-	assign pkt_data = data;
-
-	always @(posedge clk)
-		pkt_data_stb <= (state == ST_DATA) && llu_byte_stb;
-
-endmodule // usb_rx_pkt

+ 0 - 470
cores/usb/rtl/usb_trans.v

@@ -1,470 +0,0 @@
-/*
- * usb_trans.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb_trans #(
-	parameter integer ADDR_MATCH = 1
-)(
-	// TX Packet interface
-	output wire txpkt_start,
-	input  wire txpkt_done,
-
-	output reg  [3:0] txpkt_pid,
-	output wire [9:0] txpkt_len,
-
-	output wire [7:0] txpkt_data,
-	input  wire txpkt_data_ack,
-
-	// RX Packet interface
-	input  wire rxpkt_start,
-	input  wire rxpkt_done_ok,
-	input  wire rxpkt_done_err,
-
-	input  wire [ 3:0] rxpkt_pid,
-	input  wire rxpkt_is_sof,
-	input  wire rxpkt_is_token,
-	input  wire rxpkt_is_data,
-	input  wire rxpkt_is_handshake,
-
-	input  wire [10:0] rxpkt_frameno,
-	input  wire [ 6:0] rxpkt_addr,
-	input  wire [ 3:0] rxpkt_endp,
-
-	input  wire [ 7:0] rxpkt_data,
-	input  wire rxpkt_data_stb,
-
-	// EP Data Buffers
-	output wire [10:0] buf_tx_addr_0,
-	input  wire [ 7:0] buf_tx_data_1,
-	output wire buf_tx_rden_0,
-
-	output wire [10:0] buf_rx_addr_0,
-	output wire [ 7:0] buf_rx_data_0,
-	output wire buf_rx_wren_0,
-
-	// EP Status RAM
-	output wire eps_read_0,
-	output wire eps_zero_0,
-	output wire eps_write_0,
-	output wire [ 7:0] eps_addr_0,
-	output wire [15:0] eps_wrdata_0,
-	input  wire [15:0] eps_rddata_3,
-
-	// Config / Status
-	input  wire cr_addr_chk,
-	input  wire [ 6:0] cr_addr,
-
-	output wire [11:0] evt_data,
-	output wire evt_stb,
-
-	output wire cel_state,
-	input  wire cel_rel,
-	input  wire cel_ena,
-
-	// Common
-	input  wire clk,
-	input  wire rst
-);
-
-	`include "usb_defs.vh"
-
-	// Signals
-	// -------
-
-	// Micro-Code
-	reg  [ 3:0] mc_a_reg;
-
-	reg mc_rst_n;
-	(* keep="true" *) wire [ 3:0] mc_match_bits;
-	wire mc_match;
-	wire mc_jmp;
-
-	wire [ 7:0] mc_pc;
-	reg  [ 7:0] mc_pc_nxt;
-	wire [15:0] mc_opcode;
-
-	(* keep="true" *) wire mc_op_ld;
-	(* keep="true" *) wire mc_op_ep;
-	(* keep="true" *) wire mc_op_zlen;
-	(* keep="true" *) wire mc_op_tx;
-	(* keep="true" *) wire mc_op_notify;
-	(* keep="true" *) wire mc_op_evt_clr;
-	(* keep="true" *) wire mc_op_evt_rto;
-
-	// Events
-	wire [3:0] evt_rst;
-	wire [3:0] evt_set;
-	reg  [3:0] evt;
-
-	reg  [3:0] pkt_pid;
-
-	wire rto_now;
-	reg  [9:0] rto_cnt;
-
-	// Transaction / EndPoint / Buffer infos
-	reg        trans_is_setup;
-	reg  [3:0] trans_endp;
-	reg        trans_dir;
-	reg        trans_cel;
-
-	reg  [2:0] ep_type;
-	reg        ep_bd_dual;
-	reg        ep_bd_ctrl;
-	reg        ep_bd_idx_cur;
-	reg        ep_bd_idx_nxt;
-	reg        ep_data_toggle;
-
-	reg  [2:0] bd_state;
-
-	// EP & BD Infos fetch/writeback
-	localparam
-		EPFW_IDLE		= 4'b0000,
-		EPFW_RD_STATUS	= 4'b0100,
-		EPFW_RD_BD_W0	= 4'b0110,
-		EPFW_RD_BD_W1	= 4'b0111,
-		EPFW_WR_STATUS	= 4'b1000,
-		EPFW_WR_BD_W0	= 4'b1010;
-
-	reg  [3:0] epfw_state;
-	reg  [5:0] epfw_cap_dl;
-	reg  epfw_issue_wb;
-
-	// Control Endpoint Lockout
-	reg  cel_state_i;
-
-	// Packet TX
-	reg  txpkt_start_i;
-
-	// Address
-	reg  [10:0] addr;
-	wire addr_inc;
-	wire addr_ld;
-
-	// Length
-	reg [10:0] bd_length;
-	reg [ 9:0] xfer_length;
-	wire len_ld;
-	wire len_bd_dec;
-	wire len_xf_inc;
-
-
-	// Micro-Code execution engine
-	// ---------------------------
-
-	// Local reset to avoid being in the critical path
-	always @(posedge clk or posedge rst)
-		if (rst)
-			mc_rst_n <= 1'b0;
-		else
-			mc_rst_n <= 1'b1;
-
-	// Conditional Jump handling
-	assign mc_match_bits = (mc_a_reg[3:0] & mc_opcode[7:4]) ^ mc_opcode[3:0];
-	assign mc_match = ~|mc_match_bits;
-	assign mc_jmp = mc_opcode[15] & mc_rst_n & (mc_match ^ mc_opcode[14]);
-	assign mc_pc = mc_jmp ? {mc_opcode[13:8], 2'b00} : mc_pc_nxt;
-
-	// Program counter
-	always @(posedge clk or posedge rst)
-		if (rst)
-			mc_pc_nxt <= 8'h00;
-		else
-			mc_pc_nxt <= mc_pc + 1;
-
-	// Microcode ROM
-	SB_RAM40_4K #(
-		.INIT_FILE("usb_trans_mc.hex"),
-		.WRITE_MODE(0),
-		.READ_MODE(0)
-	) mc_rom_I (
-		.RDATA(mc_opcode),
-		.RADDR({3'b000, mc_pc}),
-		.RCLK(clk),
-		.RCLKE(1'b1),
-		.RE(1'b1),
-		.WDATA(16'h0000),
-		.WADDR(11'h000),
-		.MASK(16'h0000),
-		.WCLK(1'b0),
-		.WCLKE(1'b0),
-		.WE(1'b0)
-	);
-
-	// Decode opcodes
-	assign mc_op_ld      = mc_opcode[15:12] == 4'b0001;
-	assign mc_op_ep      = mc_opcode[15:12] == 4'b0010;
-	assign mc_op_zlen    = mc_opcode[15:12] == 4'b0011;
-	assign mc_op_tx      = mc_opcode[15:12] == 4'b0100;
-	assign mc_op_notify  = mc_opcode[15:12] == 4'b0101;
-	assign mc_op_evt_clr = mc_opcode[15:12] == 4'b0110;
-	assign mc_op_evt_rto = mc_opcode[15:12] == 4'b0111;
-
-	// A-register
-	always @(posedge clk)
-		if (mc_op_ld)
-			casez (mc_opcode[2:1])
-				2'b00:   mc_a_reg <= evt;
-				2'b01:   mc_a_reg <= pkt_pid ^ { ep_data_toggle & mc_opcode[0], 3'b000 };
-				2'b10:   mc_a_reg <= { trans_cel, ep_type };
-				2'b11:   mc_a_reg <= { 1'b0, bd_state };
-				default: mc_a_reg <= 4'hx;
-			endcase
-
-
-	// Events
-	// ------
-
-	// Latch events
-	always @(posedge clk or posedge rst)
-		if (rst)
-			evt <= 4'h0;
-		else
-			evt <= (evt & ~evt_rst) | evt_set;
-
-	assign evt_rst = {4{mc_op_evt_clr}} & mc_opcode[3:0];
-	assign evt_set = { rto_now, txpkt_done, rxpkt_done_err, rxpkt_done_ok };
-
-	// Capture Packet PID
-	if (ADDR_MATCH) begin
-		always @(posedge clk)
-			if (rxpkt_done_ok) begin
-				if (rxpkt_is_token & cr_addr_chk)
-					pkt_pid <= (rxpkt_addr == cr_addr) ? rxpkt_pid : PID_INVAL;
-				else
-					pkt_pid <= rxpkt_pid;
-			end
-	end else begin
-		always @(*)
-			pkt_pid = rxpkt_pid;
-	end
-
-	// RX Timeout counter
-	always @(posedge clk or posedge rst)
-		if (rst)
-			rto_cnt <= 0;
-		else
-			if (mc_op_evt_rto)
-				rto_cnt <= { 2'b01, mc_opcode[7:0] };
-			else
-				rto_cnt <= {
-					rto_cnt[9] & rto_cnt[8] & ~rxpkt_start,
-					rto_cnt[8:0] - rto_cnt[9]
-				};
-
-	assign rto_now = rto_cnt[9] & ~rto_cnt[8];
-
-
-	// Host NOTIFY
-	// -----------
-
-	assign evt_stb = mc_op_notify;
-	assign evt_data = {
-		mc_opcode[3:0], // [11:8] Micro-code return value
-		trans_endp,     // [ 7:4] Endpoint
-		trans_dir,      //    [3] Direction
-		trans_is_setup, //    [2] SETUP transaction
-		ep_bd_idx_cur,  //    [1] BD where it happenned
-		1'b0
-	};
-
-
-	// EP infos
-	// --------
-
-	// Capture EP#, direction and CEL status when we get a TOKEN packet
-	always @(posedge clk)
-		if (rxpkt_done_ok & rxpkt_is_token) begin
-			trans_is_setup   <= rxpkt_pid == PID_SETUP;
-			trans_endp       <= rxpkt_endp;
-			trans_dir        <= rxpkt_pid == PID_IN;
-			trans_cel        <= cel_state_i;
-		end
-
-	// EP Status Fetch/WriteBack (epfw)
-
-		// State
-	always @(posedge clk or posedge rst)
-		if (rst)
-			epfw_state <= EPFW_IDLE;
-		else
-			case (epfw_state)
-				EPFW_IDLE:
-					if (epfw_issue_wb)
-						epfw_state <= EPFW_WR_STATUS;
-					else if (rxpkt_done_ok & rxpkt_is_token)
-						epfw_state <= EPFW_RD_STATUS;
-					else if (epfw_cap_dl[1:0] == 2'b01)
-						epfw_state <= EPFW_RD_BD_W0;
-					else
-						epfw_state <= EPFW_IDLE;
-
-				EPFW_RD_STATUS:
-					epfw_state <= EPFW_IDLE;
-
-				EPFW_RD_BD_W0:
-					epfw_state <= EPFW_RD_BD_W1;
-
-				EPFW_RD_BD_W1:
-					epfw_state <= EPFW_IDLE;
-
-				EPFW_WR_STATUS:
-					epfw_state <= EPFW_WR_BD_W0;
-
-				EPFW_WR_BD_W0:
-					epfw_state <= EPFW_IDLE;
-
-				default:
-					epfw_state <= EPFW_IDLE;
-			endcase
-
-		// Issue command to RAM
-	assign eps_zero_0  = 1'b0;
-	assign eps_read_0  = epfw_state[2];
-	assign eps_write_0 = epfw_state[3];
-
-	assign eps_addr_0  = {
-		trans_endp,
-		trans_dir,
-		epfw_state[1],
-		epfw_state[1] & ep_bd_idx_cur,
-		epfw_state[0]
-	};
-
-	assign eps_wrdata_0 = epfw_state[1] ?
-		{ bd_state, trans_is_setup, 2'b00, xfer_length[9:0] } :
-		{ 8'h00, ep_data_toggle, ep_bd_idx_nxt, ep_bd_ctrl, ep_bd_dual, 1'b0, ep_type };
-
-		// Delay line for what to expect on read data
-	always @(posedge clk or posedge rst)
-		if (rst)
-			epfw_cap_dl = 6'b000000;
-		else
-			epfw_cap_dl <= {
-				epfw_state[1],
-				epfw_state[2] & ~^epfw_state[1:0],
-				epfw_cap_dl[5:2]
-			};
-
-		// Capture read data
-	always @(posedge clk)
-	begin
-		// EP Status
-		if (epfw_cap_dl[1:0] == 2'b01) begin
-			ep_type        <= eps_rddata_3[2:0];
-			ep_bd_dual     <= eps_rddata_3[4];
-			ep_bd_ctrl     <= eps_rddata_3[5];
-			ep_bd_idx_cur  <= eps_rddata_3[5] ? trans_is_setup : eps_rddata_3[6];
-			ep_bd_idx_nxt  <= eps_rddata_3[6];
-			ep_data_toggle <= eps_rddata_3[7] & ~trans_is_setup; /* For SETUP, DT == 0 */
-		end else begin
-			ep_data_toggle <= ep_data_toggle ^ (mc_op_ep & mc_opcode[0]);
-			ep_bd_idx_nxt  <= ep_bd_idx_nxt  ^ (mc_op_ep & mc_opcode[1] & ep_bd_dual );
-		end
-
-		// BD Word 0
-		if (epfw_cap_dl[1:0] == 2'b10) begin
-			bd_state <= eps_rddata_3[15:13];
-		end else begin
-			bd_state <= (mc_op_ep & mc_opcode[2]) ? mc_opcode[5:3]: bd_state;
-		end
-	end
-
-		// When do to write backs
-	always @(posedge clk)
-		epfw_issue_wb <= mc_op_ep & mc_opcode[7];
-
-
-	// Control Endpoint Lockout
-	// ------------------------
-
-	always @(posedge clk or posedge rst)
-		if (rst)
-			cel_state_i <= 1'b0;
-		else
-			cel_state_i <= cel_ena & ((cel_state_i & ~cel_rel) | (mc_op_ep & mc_opcode[8]));
-
-	assign cel_state = cel_state_i;
-
-
-	// Packet TX
-	// ---------
-
-	always @(posedge clk)
-		if (mc_op_tx)
-			txpkt_pid <= mc_opcode[3:0] ^ { mc_opcode[4] & ep_data_toggle, 3'b000 };
-
-	always @(posedge clk)
-		txpkt_start_i <= mc_op_tx;
-
-	assign txpkt_start = txpkt_start_i;
-	assign txpkt_len = bd_length[9:0];
-
-
-	// Data Address/Length shared logic
-	// --------------------------------
-
-	// Address
-	always @(posedge clk)
-		addr <= addr_ld ? eps_rddata_3[10:0] : (addr + addr_inc);
-
-	assign addr_ld  = epfw_cap_dl[1:0] == 2'b11;
-	assign addr_inc = txpkt_data_ack | txpkt_start_i | rxpkt_data_stb;
-
-	// Buffer length (decrements)
-	always @(posedge clk)
-		if (mc_op_zlen)
-			bd_length <= 0;
-		else
-			bd_length <= len_ld ? { 1'b1, eps_rddata_3[9:0] } : (bd_length -  len_bd_dec);
-
-	// Xfer length (increments)
-	always @(posedge clk)
-		xfer_length <= len_ld ? 10'h000 : (xfer_length + len_xf_inc);
-
-	// Length control
-	assign len_ld = epfw_cap_dl[1:0] == 2'b10;
-
-	assign len_bd_dec = (rxpkt_data_stb | rxpkt_start) & bd_length[10];
-	assign len_xf_inc =  rxpkt_data_stb;
-
-
-	// Data read logic
-	// ---------------
-
-	assign buf_tx_addr_0 = addr;
-	assign buf_tx_rden_0 = txpkt_data_ack | txpkt_start_i;
-
-	assign txpkt_data = buf_tx_data_1;
-
-
-	// Data write logic
-	// ----------------
-
-	assign buf_rx_addr_0 = addr;
-	assign buf_rx_data_0 = rxpkt_data;
-	assign buf_rx_wren_0 = rxpkt_data_stb & bd_length[10];
-
-endmodule // usb_trans

+ 0 - 158
cores/usb/rtl/usb_tx_ll.v

@@ -1,158 +0,0 @@
-/*
- * usb_tx_ll.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb_tx_ll (
-	// PHY
-	output wire phy_tx_dp,
-	output wire phy_tx_dn,
-	output wire phy_tx_en,
-
-	// Low-Level
-	input  wire ll_start,
-	input  wire ll_bit,
-	input  wire ll_last,
-	output reg  ll_ack,
-
-	// Common
-	input  wire clk,
-	input  wire rst
-);
-
-	`include "usb_defs.vh"
-
-	// Signals
-	// -------
-
-	// State
-	reg [2:0] state;
-	wire active;
-
-	reg  [2:0] br_cnt;
-	wire br_now;
-
-	// Bit stuffing
-	reg  [2:0] bs_cnt;
-	reg  bs_now;
-	wire bs_bit;
-
-	// NRZI
-	reg  lvl_prev;
-
-	// Output
-	reg  out_active;
-	wire [1:0] out_sym_nxt;
-	reg  [1:0] out_sym;
-
-
-	// State
-	// -----
-
-	always @(posedge clk or posedge rst)
-		if (rst)
-			state <= 3'b000;
-		else begin
-			if (ll_start)
-				state <= 3'b100;
-			else if (br_now & ~bs_now) begin
-				if (ll_last)
-					state <= 3'b101;
-				else
-					case (state[1:0])
-						2'b00:   state <= state;
-						2'b01:   state <= 3'b110;
-						2'b10:   state <= 3'b111;
-						default: state <= 3'b000;
-					endcase
-			end
-		end
-
-	assign active = state[2];
-
-	always @(posedge clk)
-		br_cnt <= { 1'b0, active ? br_cnt[1:0] : 2'b10 } + 1;
-
-	assign br_now = br_cnt[2];
-
-
-	// Bit Stuffing
-	// ------------
-
-	// Track number of 1s
-	always @(posedge clk or posedge ll_start)
-		if (ll_start) begin
-			bs_cnt <= 3'b000;
-			bs_now <= 1'b0;
-		end else if (br_now) begin
-			bs_cnt <= (ll_bit & ~bs_now) ? (bs_cnt + 1) : 3'b000;
-			bs_now <= ll_bit & (bs_cnt == 3'b101);
-		end
-
-	// Effective bit
-	assign bs_bit = ~bs_now & ll_bit;
-
-	// Track previous level
-	always @(posedge clk)
-		lvl_prev <= active ? (lvl_prev ^ (~bs_bit & br_now)) : 1'b1;
-
-
-	// Output stage
-	// ------------
-
-	// Ack input
-	always @(posedge clk)
-		ll_ack <= br_now & ~bs_now & (state[1:0] == 2'b00);
-
-	// Output symbol. Must be forced to 'J' outside of active area to
-	// be ready for the next packet start
-	assign out_sym_nxt = (bs_bit ^ lvl_prev) ? SYM_K : SYM_J;
-
-	always @(posedge clk or posedge rst)
-	begin
-		if (rst)
-			out_sym <= SYM_J;
-		else if (br_now) begin
-			case (state[1:0])
-				2'b00:   out_sym <= out_sym_nxt;
-				2'b01:   out_sym <= bs_now ? out_sym_nxt : SYM_SE0;
-				2'b10:   out_sym <= SYM_SE0;
-				2'b11:   out_sym <= SYM_J;
-				default: out_sym <= 2'bxx;
-			endcase
-		end
-	end
-
-	// The OE is a bit in advance (not aligned with br_now) on purpose
-	// so that we output a bit of 'J' at the packet beginning
-	always @(posedge clk)
-		out_active <= active;
-
-	// PHY control
-	assign phy_tx_dp = out_sym[1];
-	assign phy_tx_dn = out_sym[0];
-	assign phy_tx_en = out_active;
-
-endmodule // usb_tx_ll

+ 0 - 263
cores/usb/rtl/usb_tx_pkt.v

@@ -1,263 +0,0 @@
-/*
- * usb_tx_pkt.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-
-module usb_tx_pkt (
-	// Low-Level
-	output reg  ll_start,
-	output wire ll_bit,
-	output wire ll_last,
-	input  wire ll_ack,
-
-	// Packet interface
-	input  wire pkt_start,
-	output reg  pkt_done,
-
-	input  wire [3:0] pkt_pid,
-	input  wire [9:0] pkt_len,
-
-	input  wire [7:0] pkt_data,
-	output reg  pkt_data_ack,
-
-	// Common
-	input  wire clk,
-	input  wire rst
-);
-
-	`include "usb_defs.vh"
-
-	// FSM
-	// ---
-
-	localparam
-		ST_IDLE      = 0,
-		ST_SYNC      = 1,
-		ST_PID       = 2,
-		ST_DATA      = 3,
-		ST_CRC_LSB   = 4,
-		ST_CRC_MSB   = 5;
-
-
-	// Signals
-	// -------
-
-	// FSM
-	reg  [3:0] state_nxt;
-	reg  [3:0] state;
-
-	// Helper
-	reg  pid_is_handshake;
-	wire next;
-
-	// Shift register
-	reg  [3:0] shift_bit;
-	reg  [7:0] shift_load;
-	reg  [7:0] shift_data;
-	reg  shift_data_crc;
-	wire shift_last_bit;
-	reg  shift_last_byte;
-	wire shift_do_load;
-	wire shift_now;
-	reg  shift_new_bit;
-
-	// Packet length
-	reg [10:0] len;
-	wire len_last;
-	wire len_dec;
-
-	// CRC
-	wire crc_in_bit;
-	reg  crc_in_first;
-	wire crc_in_valid;
-	wire [15:0] crc;
-
-
-	// Main FSM
-	// --------
-
-	// Next state logic
-	always @(*)
-	begin
-		// Default is to stay put
-		state_nxt = state;
-
-		// Main case
-		case (state)
-			ST_IDLE:
-				if (pkt_start)
-					state_nxt = ST_SYNC;
-
-			ST_SYNC:
-				state_nxt = ST_PID;
-
-			ST_PID:
-				if (next)
-				begin
-					if (pid_is_handshake)
-						state_nxt = ST_IDLE;
-					else if (len_last)
-						state_nxt = ST_CRC_LSB;
-					else
-						state_nxt = ST_DATA;
-				end
-
-			ST_DATA:
-				if (next && len_last)
-					state_nxt = ST_CRC_LSB;
-
-			ST_CRC_LSB:
-				if (next)
-					state_nxt = ST_CRC_MSB;
-
-			ST_CRC_MSB:
-				if (next)
-					state_nxt = ST_IDLE;
-		endcase
-	end
-
-	// State register
-	always @(posedge clk or posedge rst)
-		if (rst)
-			state <= ST_IDLE;
-		else
-			state <= state_nxt;
-
-
-	// Helper
-	// ------
-
-	always @(posedge clk)
-		pid_is_handshake <= (pkt_pid == PID_ACK) || (pkt_pid == PID_NAK) || (pkt_pid == PID_STALL);
-
-	assign next = shift_last_bit & ll_ack;
-
-
-	// Shift register
-	// --------------
-
-	// When to load a new byte
-	assign shift_do_load = (state == ST_SYNC) | (shift_last_bit & ll_ack);
-
-	// When to shift
-	assign shift_now = (state == ST_SYNC) | ll_ack;
-
-	// Bit counter
-	always @(posedge clk)
-		if (shift_now)
-			shift_bit <= (shift_do_load ? 4'b0111 : shift_bit) - 1;
-
-	assign shift_last_bit = shift_bit[3];
-
-	// Load mux
-	always @(*)
-		case (state)
-			ST_SYNC:    shift_load <= 8'h80;
-			ST_PID:     shift_load <= { ~pkt_pid, pkt_pid };
-			ST_DATA:    shift_load <= pkt_data;
-			ST_CRC_LSB: shift_load <= crc_in_first ? 8'h00 : crc[ 7:0];
-			ST_CRC_MSB: shift_load <= crc_in_first ? 8'h00 : crc[15:8];
-			default:    shift_load <= 8'hxx;
-		endcase
-
-	// Shift data
-	always @(posedge clk)
-		if (shift_now)
-			shift_data <= shift_do_load ? shift_load : {1'b0, shift_data[7:1]};
-
-	// Some flags about the data
-	always @(posedge clk)
-		if (shift_now & shift_do_load) begin
-			shift_data_crc  <= (state == ST_DATA);
-			shift_last_byte <= (state == ST_CRC_MSB) | ((state == ST_PID) & pid_is_handshake);
-		end
-
-	// When a fresh new bit is available
-	always @(posedge clk)
-		shift_new_bit <= shift_now;
-
-
-	// Packet length
-	// -------------
-
-	assign len_dec = pkt_start || (shift_do_load && ((state == ST_DATA) || (state == ST_PID)));
-
-	always @(posedge clk)
-		if (len_dec)
-			len <= (pkt_start ? { 1'b0, pkt_len } : len) - 1;
-
-	assign len_last = len[10];
-
-
-	// CRC generation
-	// --------------
-
-	// Keep track of first bit
-	always @(posedge clk)
-		crc_in_first <= (crc_in_first & ~crc_in_valid) | (state == ST_IDLE);
-
-	// Input all bits once acked
-	assign crc_in_bit   = shift_data[0];
-	assign crc_in_valid = shift_data_crc & shift_new_bit;
-
-	// CRC16 core
-	usb_crc #(
-		.WIDTH(16),
-		.POLY(16'h8005),
-		.MATCH(16'h800D)
-	) crc_16_I (
-		.in_bit(crc_in_bit),
-		.in_first(crc_in_first),
-		.in_valid(crc_in_valid),
-		.crc(crc),
-		.crc_match(),
-		.clk(clk),
-		.rst(rst)
-	);
-
-
-	// Low-level control
-	// -----------------
-
-	// Start right after the load of SYNC
-	always @(posedge clk)
-		ll_start <= state == ST_SYNC;
-
-	// Bit
-	assign ll_bit  = shift_data[0];
-	assign ll_last = shift_last_bit & shift_last_byte;
-
-
-	// Packet interface feedback
-	// -------------------------
-
-	// We don't care about the delay, better register
-	always @(posedge clk)
-	begin
-		pkt_done <= ll_ack && ll_last;
-		pkt_data_ack <= (state == ST_DATA) && next;
-	end
-
-endmodule // usb_tx_pkt

+ 0 - 84
cores/usb/sim/usb_ep_buf_tb.v

@@ -1,84 +0,0 @@
-/*
- * usb_ep_buf_tb.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-`timescale 1ns/100ps
-
-module usb_ep_buf_tb;
-
-	localparam integer RWIDTH = 16;	// 8/16/32
-	localparam integer WWIDTH = 64;	// 8/16/32
-
-	localparam integer ARW = 11 - $clog2(RWIDTH / 8);
-	localparam integer AWW = 11 - $clog2(WWIDTH / 8);
-
-	// Signals
-	reg rst = 1;
-	reg clk  = 0;
-
-	wire [ARW-1:0] rd_addr_0;
-	wire [RWIDTH-1:0] rd_data_1;
-	wire rd_en_0;
-	wire [AWW-1:0] wr_addr_0;
-	wire [WWIDTH-1:0] wr_data_0;
-	wire wr_en_0;
-
-	// Setup recording
-	initial begin
-		$dumpfile("usb_ep_buf_tb.vcd");
-		$dumpvars(0,usb_ep_buf_tb);
-	end
-
-	// Reset pulse
-	initial begin
-		# 200 rst = 0;
-		# 1000000 $finish;
-	end
-
-	// Clocks
-	always #10 clk  = !clk;
-
-	// DUT
-	usb_ep_buf #(
-		.RWIDTH(RWIDTH),
-		.WWIDTH(WWIDTH)
-	) dut_I (
-		.rd_addr_0(rd_addr_0),
-		.rd_data_1(rd_data_1),
-		.rd_en_0(rd_en_0),
-		.rd_clk(clk),
-		.wr_addr_0(wr_addr_0),
-		.wr_data_0(wr_data_0),
-		.wr_en_0(wr_en_0),
-		.wr_clk(clk)
-	);
-
-	assign rd_en_0 = 1'b1;
-	assign wr_en_0 = 1'b1;
-	assign rd_addr_0 = 3;
-	assign wr_addr_0 = 0;
-	assign wr_data_0 = 64'hab89127bbabecafe;
-
-endmodule // usb_ep_buf_tb

+ 0 - 147
cores/usb/sim/usb_tb.v

@@ -1,147 +0,0 @@
-/*
- * usb_tb.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-`timescale 1ns/100ps
-
-module usb_tb;
-
-	// Signals
-	reg rst = 1;
-	reg clk_48m  = 0;	// USB clock
-	reg clk_samp = 0;	// Capture samplerate
-
-	reg  [7:0] in_file_data;
-	reg  in_file_valid;
-	reg  in_file_done;
-
-	wire usb_dp;
-	wire usb_dn;
-	wire usb_pu;
-
-	wire [ 8:0] ep_tx_addr_0;
-	wire [31:0] ep_tx_data_0;
-	wire ep_tx_we_0;
-	wire [ 8:0] ep_rx_addr_0;
-	wire [31:0] ep_rx_data_1;
-	wire ep_rx_re_0;
-
-	wire [11:0] bus_addr;
-	wire [15:0] bus_din;
-	wire [15:0] bus_dout;
-	wire bus_cyc;
-	wire bus_we;
-	wire bus_ack;
-
-	// Setup recording
-	initial begin
-		$dumpfile("usb_tb.vcd");
-		$dumpvars(0,usb_tb);
-	end
-
-	// Reset pulse
-	initial begin
-		# 200 rst = 0;
-		# 1000000 $finish;
-	end
-
-	// Clocks
-	always #10.416 clk_48m  = !clk_48m;
-	always #3.247  clk_samp = !clk_samp;
-
-	// DUT
-	usb #(
-		.TARGET("ICE40"),
-		.EPDW(32)
-	) dut_I (
-		.pad_dp(usb_dp),
-		.pad_dn(usb_dn),
-		.pad_pu(usb_pu),
-		.ep_tx_addr_0(ep_tx_addr_0),
-		.ep_tx_data_0(ep_tx_data_0),
-		.ep_tx_we_0(ep_tx_we_0),
-		.ep_rx_addr_0(ep_rx_addr_0),
-		.ep_rx_data_1(ep_rx_data_1),
-		.ep_rx_re_0(ep_rx_re_0),
-		.ep_clk(clk_48m),
-		.bus_addr(bus_addr),
-		.bus_din(bus_din),
-		.bus_dout(bus_dout),
-		.bus_cyc(bus_cyc),
-		.bus_we(bus_we),
-		.bus_ack(bus_ack),
-		.clk(clk_48m),
-		.rst(rst)
-	);
-
-	reg [7:0] cnt;
-
-	always @(posedge clk_48m)
-		if (bus_ack)
-			cnt <= 0;
-		else if (~cnt[7])
-			cnt <= cnt + 1;
-
-	assign bus_addr = 12'h000;
-	assign bus_din = 16'h8001;
-	assign bus_cyc = cnt[7];
-	assign bus_we = 1'b1;
-
-	assign ep_rx_addr_0 = 9'h000;
-	assign ep_rx_re_0 = 1'b1;
-	assign ep_tx_addr_0 = 9'h000;
-	assign ep_tx_data_0 = 32'h02000112;
-	assign ep_tx_we_0 = 1'b1;
-
-	// Read file
-	integer fh_in, rv;
-
-	initial
-		fh_in = $fopen("../data/capture_usb_raw_short.bin", "rb");
-
-	always @(posedge clk_samp)
-	begin
-		if (rst) begin
-			in_file_data  <= 8'h00;
-			in_file_valid <= 1'b0;
-			in_file_done  <= 1'b0;
-		end else begin
-			if (!in_file_done) begin
-				rv = $fread(in_file_data, fh_in);
-				in_file_valid <= (rv == 1);
-				in_file_done  <= (rv != 1);
-			end else begin
-				in_file_data  <= 8'h00;
-				in_file_valid <= 1'b0;
-				in_file_done  <= 1'b1;
-			end
-		end
-	end
-
-	// Input
-	assign usb_dp = in_file_data[1] & in_file_valid;
-	assign usb_dn = in_file_data[0] & in_file_valid;
-
-endmodule // usb_tb

+ 0 - 171
cores/usb/sim/usb_tx_tb.v

@@ -1,171 +0,0 @@
-/*
- * usb_tx_tb.v
- *
- * vim: ts=4 sw=4
- *
- * Copyright (C) 2019 Sylvain Munaut
- * All rights reserved.
- *
- * LGPL v3+, see LICENSE.lgpl3
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-`default_nettype none
-`timescale 1ns/100ps
-
-module usb_tx_tb;
-
-	// Signals
-	reg rst = 1;
-	reg clk_48m  = 0;	// USB clock
-
-	wire phy_tx_dp;
-	wire phy_tx_dn;
-	wire phy_tx_en;
-
-	wire ll_start;
-	wire ll_bit;
-	wire ll_last;
-	wire ll_ack;
-
-	wire pkt_start;
-	wire pkt_done;
-	wire [3:0] pkt_pid;
-	wire [9:0] pkt_len;
-	reg  [11:0] pkt_data_addr;
-	reg  [7:0] pkt_data;
-	wire pkt_data_ack;
-
-	// Setup recording
-	initial begin
-		$dumpfile("usb_tx_tb.vcd");
-		$dumpvars(0,usb_tx_tb);
-	end
-
-	// Reset pulse
-	initial begin
-		# 200 rst = 0;
-		# 400000 $finish;
-	end
-
-	// Clocks
-	always #10.416 clk_48m  = !clk_48m;
-
-	// DUT
-	usb_tx_ll tx_ll_I (
-		.phy_tx_dp(phy_tx_dp),
-		.phy_tx_dn(phy_tx_dn),
-		.phy_tx_en(phy_tx_en),
-		.ll_start(ll_start),
-		.ll_bit(ll_bit),
-		.ll_last(ll_last),
-		.ll_ack(ll_ack),
-		.clk(clk_48m),
-		.rst(rst)
-	);
-
-`ifndef NO_PKT
-	usb_tx_pkt tx_pkt_I (
-		.ll_start(ll_start),
-		.ll_bit(ll_bit),
-		.ll_last(ll_last),
-		.ll_ack(ll_ack),
-		.pkt_start(pkt_start),
-		.pkt_done(pkt_done),
-		.pkt_pid(pkt_pid),
-		.pkt_len(pkt_len),
-		.pkt_data(pkt_data),
-		.pkt_data_ack(pkt_data_ack),
-		.clk(clk_48m),
-		.rst(rst)
-	);
-
-	// Start signal
-	reg [7:0] cnt;
-	reg ready;
-
-	always @(posedge clk_48m)
-		if (rst)
-			ready <= 1'b1;
-		else
-			if (pkt_start)
-				ready <= 1'b0;
-			else if (pkt_done)
-				ready <= 1'b1;
-
-	always @(posedge clk_48m)
-		if (rst)
-			cnt <= 0;
-		else
-			cnt <= cnt + 1;
-
-	assign pkt_start = (cnt == 8'hff) & ready;
-
-	// Packet
-	assign pkt_len = 10'h100;	// 256 bytes payload
-	assign pkt_pid = 4'b0011;	// DATA0
-//	assign pkt_pid = 4'b0010;	// ACK
-
-	// Fake data source
-	always @(posedge clk_48m)
-		if (rst)
-			pkt_data_addr <= 8'h00;
-		else
-			pkt_data_addr <= pkt_data_addr + pkt_data_ack;
-
-	always @(*)
-		case (pkt_data_addr)
-			12'h000: pkt_data = 8'h8c;
-			12'h001: pkt_data = 8'h1a;
-			12'h002: pkt_data = 8'hf2;
-			12'h003: pkt_data = 8'hf0;
-
-			12'h100: pkt_data = 8'ha0;
-			12'h101: pkt_data = 8'h28;
-			12'h102: pkt_data = 8'hf2;
-			12'h103: pkt_data = 8'hf0;
-			default: pkt_data = 8'h00;
-		endcase
-`endif
-
-`ifdef NO_PKT
-	wire [31:0] bit_seq = 32'b00000001_10100101_11111111_11100000;
-	reg [7:0] cnt;
-	reg started;
-
-	always @(posedge clk_48m)
-		if (rst)
-			cnt <= 0;
-		else if (ll_ack | ~started)
-			cnt <= cnt + 1;
-
-	always @(posedge clk_48m)
-		if (rst)
-			started <= 1'b0;
-		else
-			if (ll_start)
-				started <= 1'b1;
-			else if (ll_last & ll_ack)
-				started <= 1'b0;
-
-	assign ll_start = (cnt == 8'h1f);
-	assign ll_bit   = bit_seq[31 - cnt[4:0]];
-	assign ll_last  = cnt[4:0] == 31;
-`endif
-
-	wire trig = tx_ll_I.ll_last & tx_ll_I.br_now & tx_ll_I.bs_now;
-
-endmodule // usb_tx_tb

+ 0 - 447
cores/usb/utils/microcode.py

@@ -1,447 +0,0 @@
-#!/usr/bin/env python3
-
-import sys
-import types
-
-
-#
-# OpCodes
-#
-
-def NOP():
-	return 0x0000
-
-def LD(src):
-	srcs = {
-		'evt': 0,
-		'pkt_pid': 2,
-		'pkt_pid_chk': 3,
-		'ep_type': 4,
-		'bd_state': 6,
-	}
-	return 0x1000 | srcs[src]
-
-def EP(bd_state=None, bdi_flip=False, dt_flip=False, wb=False, cel_set=False):
-	return 0x2000 | \
-		((1 << 0) if dt_flip else 0) | \
-		((1 << 1) if bdi_flip else 0) | \
-		(((bd_state << 3) | (1 << 2)) if bd_state is not None else 0) | \
-		((1 << 7) if wb else 0) | \
-		((1 << 8) if cel_set else 0)
-
-def ZL():
-	return 0x3000
-
-def TX(pid, set_dt=False):
-	return 0x4000 | pid | ((1 << 4) if set_dt else 0)
-
-def NOTIFY(code):
-	return 0x5000 | code
-
-def EVT_CLR(evts):
-	return 0x6000 | evts
-
-def EVT_RTO(timeout):
-	return 0x7000 | timeout
-
-def JMP(tgt, cond_val=None, cond_mask=0xf, cond_invert=False):
-	if isinstance(tgt, str):
-		return lambda resolve: JMP(resolve(tgt), cond_val, cond_mask, cond_invert)
-	assert tgt & 3 == 0
-	return (
-		(1 << 15) |
-		(tgt << 6) |
-		(0 if (cond_val is None) else ((cond_mask << 4) | cond_val)) |
-		((1<<14) if cond_invert else 0)
-	)
-
-def JEQ(tgt, cond_val=None, cond_mask=0xf):
-	return JMP(tgt, cond_val, cond_mask)
-
-def JNE(tgt, cond_val=None, cond_mask=0xf):
-	return JMP(tgt, cond_val, cond_mask, cond_invert=True)
-
-def L(label):
-	return label
-
-
-#
-# "Assembler"
-#
-
-def assemble(code):
-	flat_code = []
-	labels    = {}
-	for elem in code:
-		if isinstance(elem, str):
-			assert elem not in labels
-			while len(flat_code) & 3:
-				flat_code.append(JMP(elem))
-			labels[elem] = len(flat_code)
-		else:
-			flat_code.append(elem)
-	for offset, elem in enumerate(flat_code):
-		if isinstance(elem, types.LambdaType):
-			flat_code[offset] = elem(lambda label: labels[label])
-	return flat_code, labels
-
-
-#
-# Constants
-#
-
-EVT_ALL     = 0xf
-EVT_RX_OK   = (1 << 0)
-EVT_RX_ERR  = (1 << 1)
-EVT_TX_DONE = (1 << 2)
-EVT_TIMEOUT = (1 << 3)
-
-PID_OUT   = 0b0001
-PID_IN    = 0b1001
-PID_SETUP = 0b1101
-PID_DATA0 = 0b0011
-PID_DATA1 = 0b1011
-PID_ACK   = 0b0010
-PID_NAK   = 0b1010
-PID_STALL = 0b1110
-
-PID_DATA_MSK = 0b0111
-PID_DATA_VAL = 0b0011
-
-EP_TYPE_NONE  = 0b0000
-EP_TYPE_ISOC  = 0b0001
-EP_TYPE_INT   = 0b0010
-EP_TYPE_BULK  = 0b0100
-EP_TYPE_CTRL  = 0b0110
-
-EP_TYPE_MSK1  = 0b0111
-EP_TYPE_MSK2  = 0b0110
-EP_TYPE_HALT  = 0b0001
-EP_TYPE_CEL   = 0b1000
-
-BD_NONE      = 0b000
-BD_RDY_DATA  = 0b010
-BD_RDY_STALL = 0b011
-BD_RDY_MSK   = 0b110
-BD_RDY_VAL   = 0b010
-BD_DONE_OK   = 0b100
-BD_DONE_ERR  = 0b101
-
-NOTIFY_SUCCESS = 0x00
-NOTIFY_TX_FAIL = 0x08
-NOTIFY_RX_FAIL = 0x09
-
-TIMEOUT = 70	# Default timeout value for waiting for a packet from the host
-
-
-#
-# Microcode
-#
-
-
-mc = [
-	# Main loop
-	# ---------
-
-	L('IDLE'),
-		# Wait for an event we care about
-		LD('evt'),
-		JEQ('IDLE', 0),
-		EVT_CLR(EVT_ALL),
-		JEQ('IDLE', 0, EVT_RX_OK),
-
-		# Dispatch to handler
-		LD('pkt_pid'),
-		JEQ('DO_IN', PID_IN),
-		JEQ('DO_OUT', PID_OUT),
-		JEQ('DO_SETUP', PID_SETUP),
-		JMP('IDLE'),						# invalid PID / not token, ignore packet
-
-
-	# IN Transactions
-	# ---------------
-
-	L('DO_IN'),
-		# Check endpoint type
-		LD('ep_type'),
-		JEQ('DO_IN_ISOC', EP_TYPE_ISOC, EP_TYPE_MSK1),	# isochronous is special
-		JEQ('IDLE', EP_TYPE_NONE, EP_TYPE_MSK1),		# endpoint doesn't exist, ignore packet
-
-
-		# Bulk/Control/Interrupt
-		# - - - - - - - - - - - -
-
-		# Is EP halted ?
-		JEQ('TX_STALL_HALT', EP_TYPE_HALT, EP_TYPE_HALT),
-
-		# If it's a Control endpoint and Lock is active, NAK
-		JEQ('TX_NAK', EP_TYPE_CEL | EP_TYPE_CTRL, EP_TYPE_CEL | EP_TYPE_MSK2),
-
-		# Anything valid in the active BD ?
-		LD('bd_state'),
-		JEQ('TX_STALL_BD', BD_RDY_STALL),
-		JNE('TX_NAK', BD_RDY_DATA),
-
-		# TX packet from BD
-		TX(PID_DATA0, set_dt=True),
-
-		# Wait for TX to complete
-	L('_DO_IN_BCI_WAIT_TX'),
-		LD('evt'),
-		JEQ('_DO_IN_BCI_WAIT_TX', 0, EVT_TX_DONE),
-		EVT_CLR(EVT_TX_DONE),
-
-		# Wait for ACK
-		EVT_RTO(TIMEOUT),
-
-	L('_DO_IN_BCI_WAIT_ACK'),
-		LD('evt'),
-		JEQ('_DO_IN_BCI_WAIT_ACK', 0, EVT_TIMEOUT | EVT_RX_ERR | EVT_RX_OK),
-
-		# If it's not a good packet and a ACK, we failed
-		JEQ('_DO_IN_BCI_FAIL', 0, EVT_RX_OK),
-		LD('pkt_pid'),
-		JNE('_DO_IN_BCI_FAIL', PID_ACK),
-
-		# Success !
-		EP(bd_state=BD_DONE_OK, bdi_flip=True, dt_flip=True, wb=True),
-		NOTIFY(NOTIFY_SUCCESS),
-		JMP('IDLE'),
-
-		# TX Fail handler, notify the host
-	L('_DO_IN_BCI_FAIL'),
-		NOTIFY(NOTIFY_TX_FAIL),
-		JMP('IDLE'),
-
-
-		# Isochronous
-		# - - - - - -
-
-	L('DO_IN_ISOC'),
-		# Anything to TX ?
-		LD('bd_state'),
-		JNE('_DO_IN_ISOC_NO_DATA', BD_RDY_DATA),
-
-		# Transmit packet (with DATA0, always)
-		TX(PID_DATA0),
-
-		# Wait for TX to complete
-	L('_DO_IN_ISOC_WAIT_TX'),
-		LD('evt'),
-		JEQ('_DO_IN_ISOC_WAIT_TX', 0, EVT_TX_DONE),
-		EVT_CLR(EVT_TX_DONE),
-
-		# "Assume" success
-		EP(bd_state=BD_DONE_OK, bdi_flip=True, dt_flip=False, wb=True),
-		NOTIFY(NOTIFY_SUCCESS),
-		JMP('IDLE'),
-
-		# Transmit empty packet
-	L('_DO_IN_ISOC_NO_DATA'),
-		ZL(),
-		TX(PID_DATA0),
-		JMP('IDLE'),
-
-
-	# SETUP Transactions
-	# ------------------
-
-	L('DO_SETUP'),
-		# Check the endpoint is 'control' and CEL is not asserted
-		LD('ep_type'),
-		JNE('RX_DISCARD_NEXT', EP_TYPE_CTRL, EP_TYPE_MSK2 | EP_TYPE_CEL),
-
-		# For Setup, if no-space, don't NAK, just ignore
-		LD('bd_state'),
-		JNE('RX_DISCARD_NEXT', BD_RDY_DATA),
-
-		# Wait for packet
-		EVT_RTO(TIMEOUT),
-
-	L('_DO_SETUP_WAIT_DATA'),
-		LD('evt'),
-		JEQ('_DO_SETUP_WAIT_DATA', 0, EVT_TIMEOUT | EVT_RX_ERR | EVT_RX_OK),
-
-		# Did it work ?
-		JEQ('_DO_SETUP_FAIL', 0, EVT_RX_OK),
-		LD('pkt_pid'),
-		JNE('_DO_SETUP_FAIL', PID_DATA0),
-
-		# Success !
-		EP(bd_state=BD_DONE_OK, bdi_flip=True, dt_flip=True, wb=True, cel_set=True),
-		NOTIFY(NOTIFY_SUCCESS),
-		JMP('TX_ACK'),
-
-		# Setup RX handler
-	L('_DO_SETUP_FAIL'),
-		EP(bd_state=BD_DONE_ERR, bdi_flip=True, dt_flip=False, wb=True),
-		NOTIFY(NOTIFY_RX_FAIL),
-		JMP('IDLE'),
-
-
-	# OUT Transactions
-	# ----------------
-
-	L('DO_OUT'),
-		# Check endpoint type
-		LD('ep_type'),
-		JEQ('DO_OUT_ISOC', EP_TYPE_ISOC, EP_TYPE_MSK1),	# isochronous is special
-		JEQ('IDLE', EP_TYPE_NONE, EP_TYPE_MSK1),		# endpoint doesn't exist, ignore packet
-
-
-		# Bulk/Control/Interrupt
-		# - - - - - - - - - - - -
-
-		# If EP is halted, we drop the packet and respond with STALL
-		JEQ('_DO_OUT_BCI_DROP_DATA', EP_TYPE_HALT, EP_TYPE_HALT),
-
-		# If it's a Control endpoint and Lock is active, NAK
-		JEQ('_DO_OUT_BCI_DROP_DATA', EP_TYPE_CEL | EP_TYPE_CTRL, EP_TYPE_CEL | EP_TYPE_MSK2),
-
-		# Check we have space, if not prevent data writes
-		LD('bd_state'),
-		JNE('_DO_OUT_BCI_DROP_DATA', BD_RDY_DATA),
-
-		# Wait for packet
-		EVT_RTO(TIMEOUT),
-
-	L('_DO_OUT_BCI_WAIT_DATA'),
-		LD('evt'),
-		JEQ('_DO_OUT_BCI_WAIT_DATA', 0, EVT_TIMEOUT | EVT_RX_ERR | EVT_RX_OK),
-
-		# We got a packet (and possibly stored the data), now we need to respond !
-			# Not a valid packet at all, or timeout, or not DATAx -> No response
-		JEQ('_DO_OUT_BCI_FAIL', 0, EVT_RX_OK),
-		LD('pkt_pid_chk'),
-		JNE('_DO_OUT_BCI_FAIL', PID_DATA_VAL, PID_DATA_MSK),	# Accept DATA0/DATA1 only
-
-			# If EP is halted, TX STALL
-		LD('ep_type'),
-		JEQ('TX_STALL_HALT', EP_TYPE_HALT, EP_TYPE_HALT),
-
-			# If it's a Control endpoint and Lock is active, NAK
-		JEQ('TX_NAK', EP_TYPE_CEL | EP_TYPE_CTRL, EP_TYPE_CEL | EP_TYPE_MSK2),
-
-			# Wrong Data Toggle -> Ignore new data, just re-tx a ACK
-		LD('pkt_pid_chk'),
-		JEQ('TX_ACK', PID_DATA1),								# With pid_chk, DATA1 means wrong DT
-
-			# We didn't have space -> NAK
-		LD('bd_state'),
-		JNE('TX_NAK', BD_RDY_VAL, BD_RDY_MSK),
-
-			# Explicitely asked for stall ?
-		JEQ('TX_STALL_BD', BD_RDY_STALL),
-
-		# We're all good !
-		EP(bd_state=BD_DONE_OK, bdi_flip=True, dt_flip=True, wb=True),
-		NOTIFY(NOTIFY_SUCCESS),
-		JMP('TX_ACK'),
-
-		# Fail handler: Prepare to drop data
-	L('_DO_OUT_BCI_DROP_DATA'),
-		ZL(),
-		JMP('_DO_OUT_BCI_WAIT_DATA'),
-
-		# Fail hander: Packet reception failed
-	L('_DO_OUT_BCI_FAIL'),
-			# Check we actually had a BD at all
-		LD('bd_state'),
-		JNE('IDLE', BD_RDY_VAL, BD_RDY_MSK),
-
-			# We had a BD, so report the error
-		EP(bd_state=BD_DONE_ERR, bdi_flip=True, dt_flip=False, wb=True),
-		NOTIFY(NOTIFY_RX_FAIL),
-		JMP('IDLE'),
-
-
-		# Isochronous
-		# - - - - - -
-
-	L('DO_OUT_ISOC'),
-		# Do we have space to RX ?
-		LD('bd_state'),
-		JNE('_DO_OUT_ISOC_NO_SPACE', BD_RDY_DATA),
-
-		# Wait for packet RX
-		EVT_RTO(TIMEOUT),
-
-	L('_DO_OUT_ISOC_WAIT_DATA'),
-		LD('evt'),
-		JEQ('_DO_OUT_ISOC_WAIT_DATA', 0, EVT_TIMEOUT | EVT_RX_ERR | EVT_RX_OK),
-
-		# Did it work ?
-		JEQ('_DO_OUT_ISOC_FAIL', 0, EVT_RX_OK),
-		LD('pkt_pid'),
-		JNE('_DO_OUT_ISOC_FAIL', PID_DATA_VAL, PID_DATA_MSK),	# Accept DATA0/DATA1
-
-		# Success !
-		EP(bd_state=BD_DONE_OK, bdi_flip=True, dt_flip=False, wb=True),
-		NOTIFY(NOTIFY_SUCCESS),
-		JMP('IDLE'),
-
-		# RX fail handler, mark error in the BD, notify host
-	L('_DO_OUT_ISOC_FAIL'),
-		EP(bd_state=BD_DONE_ERR, bdi_flip=True, dt_flip=False, wb=True),
-		NOTIFY(NOTIFY_RX_FAIL),
-		JMP('IDLE'),
-
-		# RX no-space handler, just discard packet :(
-	L('_DO_OUT_ISOC_NO_SPACE'),
-		# Notify host ?
-		# Discard
-		JMP('RX_DISCARD_NEXT'),
-
-
-	# Common shared utility
-	# ---------------------
-
-	# Transmit STALL as asked in a Buffer Descriptor
-	L('TX_STALL_BD'),
-		EP(bd_state=BD_DONE_OK, bdi_flip=True, dt_flip=False, wb=True),
-		NOTIFY(NOTIFY_SUCCESS),
-		# fall-thru
-
-	# Transmit STALL because of halted End Point
-	L('TX_STALL_HALT'),
-		ZL(),
-		TX(PID_STALL),
-		JMP('IDLE'),
-
-	# Transmit NAK handshake
-	L('TX_NAK'),
-		ZL(),
-		TX(PID_NAK),
-		JMP('IDLE'),
-
-	# Transmit ACK handshake
-	L('TX_ACK'),
-		ZL(),
-		TX(PID_ACK),
-		JMP('IDLE'),
-
-	# Discard the next packet (if any)
-	L('RX_DISCARD_NEXT'),
-		# Zero-length to prevent store of data
-		ZL(),
-
-		# Wait for a packet
-		EVT_RTO(TIMEOUT),
-
-	L('_RX_DISCARD_WAIT'),
-		LD('evt'),
-		JEQ('_RX_DISCARD_WAIT', 0, EVT_TIMEOUT | EVT_RX_ERR | EVT_RX_OK),
-
-		# Done
-		JMP('IDLE'),
-]
-
-
-if __name__ == '__main__':
-	code, labels = assemble(mc)
-	ilabel = dict([(v,k) for k,v in labels.items()])
-	for i, v in enumerate(code):
-		if (len(sys.argv) > 1) and (sys.argv[1] == 'debug'):
-			print("%02x %04x\t%s" % (i, v,ilabel.get(i,'')))
-		else:
-			print("%04x" % (v,))