Browse Source

WIP: restructure USB using interfaces to be able to create more endpoints

This seems to work in the USB core, but something seems to not be
quite hooked up right in the CDC core module.
H. Peter Anvin 3 years ago
parent
commit
a99616cbc5

+ 2 - 2
fpga/ip/int_osc.qsys

@@ -6,7 +6,7 @@
    version="1.0"
    description=""
    tags="INTERNAL_COMPONENT=true"
-   categories="" />
+   categories="System" />
  <parameter name="bonusData"><![CDATA[bonusData 
 {
    element int_osc_0
@@ -47,7 +47,7 @@
  <module
    name="int_osc_0"
    kind="altera_int_osc"
-   version="20.1"
+   version="21.1"
    enabled="1"
    autoexport="1">
   <parameter name="CBX_AUTO_BLACKBOX" value="ALL" />

+ 10 - 10
fpga/ip/int_osc.sopcinfo

@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <EnsembleReport name="int_osc" kind="int_osc" version="1.0" fabric="QSYS">
- <!-- Format version 20.1 720 (Future versions may contain additional information.) -->
- <!-- 2021.12.01.09:19:29 -->
+ <!-- Format version 21.1 842 (Future versions may contain additional information.) -->
+ <!-- 2021.12.09.22:00:36 -->
  <!-- A collection of modules and connections -->
  <parameter name="AUTO_GENERATION_ID">
   <type>java.lang.Integer</type>
-  <value>1638379169</value>
+  <value>1639116036</value>
   <derived>false</derived>
   <enabled>true</enabled>
   <visible>false</visible>
@@ -68,7 +68,7 @@
  <module
    name="int_osc_0"
    kind="altera_int_osc"
-   version="20.1"
+   version="21.1"
    path="int_osc_0">
   <!-- Describes a single module. Module parameters are
 the requested settings for a module instance. -->
@@ -154,7 +154,7 @@ the requested settings for a module instance. -->
    <visible>true</visible>
    <valid>true</valid>
   </parameter>
-  <interface name="oscena" kind="conduit_end" version="20.1">
+  <interface name="oscena" kind="conduit_end" version="21.1">
    <!-- The connection points exposed by a module instance for the
 particular module parameters. Connection points and their
 parameters are a RESULT of the module parameters. -->
@@ -203,7 +203,7 @@ parameters are a RESULT of the module parameters. -->
     <role>oscena</role>
    </port>
   </interface>
-  <interface name="clkout" kind="clock_source" version="20.1">
+  <interface name="clkout" kind="clock_source" version="21.1">
    <!-- The connection points exposed by a module instance for the
 particular module parameters. Connection points and their
 parameters are a RESULT of the module parameters. -->
@@ -283,7 +283,7 @@ parameters are a RESULT of the module parameters. -->
   <type>com.altera.entityinterfaces.IElementClass</type>
   <subtype>com.altera.entityinterfaces.IModule</subtype>
   <displayName>Internal Oscillator</displayName>
-  <version>20.1</version>
+  <version>21.1</version>
  </plugin>
  <plugin>
   <instanceCount>1</instanceCount>
@@ -291,7 +291,7 @@ parameters are a RESULT of the module parameters. -->
   <type>com.altera.entityinterfaces.IElementClass</type>
   <subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype>
   <displayName>Conduit</displayName>
-  <version>20.1</version>
+  <version>21.1</version>
  </plugin>
  <plugin>
   <instanceCount>1</instanceCount>
@@ -299,8 +299,8 @@ parameters are a RESULT of the module parameters. -->
   <type>com.altera.entityinterfaces.IElementClass</type>
   <subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype>
   <displayName>Clock Output</displayName>
-  <version>20.1</version>
+  <version>21.1</version>
  </plugin>
- <reportVersion>20.1 720</reportVersion>
+ <reportVersion>21.1 842</reportVersion>
  <uniqueIdentifier></uniqueIdentifier>
 </EnsembleReport>

+ 3 - 3
fpga/ip/int_osc/int_osc.csv

@@ -1,12 +1,12 @@
-# system info int_osc on 2021.12.01.09:19:28
+# system info int_osc on 2021.12.09.22:00:35
 system_info:
 name,value
 DEVICE,EP4CE15F17C8
 DEVICE_FAMILY,Cyclone IV E
-GENERATION_ID,1638379168
+GENERATION_ID,1639116035
 #
 #
-# Files generated for int_osc on 2021.12.01.09:19:28
+# Files generated for int_osc on 2021.12.09.22:00:35
 files:
 filepath,kind,attributes,module,is_top
 simulation/int_osc.v,VERILOG,,int_osc,true

+ 2 - 2
fpga/ip/int_osc/int_osc.html

@@ -67,7 +67,7 @@ div.greydiv { vertical-align:top ; text-align:center ; background:#eeeeee ; bord
   </table>
   <table class="blueBar">
    <tr>
-    <td class="l">2021.12.01.09:19:29</td>
+    <td class="l">2021.12.09.22:00:36</td>
     <td class="r">Datasheet</td>
    </tr>
   </table>
@@ -95,7 +95,7 @@ div.greydiv { vertical-align:top ; text-align:center ; background:#eeeeee ; bord
   <a name="module_int_osc_0"> </a>
   <div>
    <hr/>
-   <h2>int_osc_0</h2>altera_int_osc v20.1
+   <h2>int_osc_0</h2>altera_int_osc v21.1
    <br/>
    <br/>
    <br/>

+ 7 - 7
fpga/ip/int_osc/int_osc.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <deploy
- date="2021.12.01.09:19:29"
+ date="2021.12.09.22:00:36"
  outputDirectory="/home/hpa/abc80/max80/fw/fpga/ip/int_osc/">
  <perimeter>
   <parameter
@@ -49,12 +49,12 @@
  </perimeter>
  <entity
    path=""
-   parameterizationKey="int_osc:1.0:AUTO_DEVICE=EP4CE15F17C8,AUTO_DEVICE_FAMILY=Cyclone IV E,AUTO_DEVICE_SPEEDGRADE=8,AUTO_GENERATION_ID=1638379169,AUTO_UNIQUE_ID=(altera_int_osc:20.1:CBX_AUTO_BLACKBOX=ALL,CLOCK_FREQUENCY=UNKNOWN,CLOCK_FREQUENCY_1=116,CLOCK_FREQUENCY_2=77,DEVICE_FAMILY=Cyclone IV E,DEVICE_ID=UNKNOWN,INFORMATION=The maximum output frequency is 80MHz,PART_NAME=EP4CE15F17C8)"
+   parameterizationKey="int_osc:1.0:AUTO_DEVICE=EP4CE15F17C8,AUTO_DEVICE_FAMILY=Cyclone IV E,AUTO_DEVICE_SPEEDGRADE=8,AUTO_GENERATION_ID=1639116036,AUTO_UNIQUE_ID=(altera_int_osc:21.1:CBX_AUTO_BLACKBOX=ALL,CLOCK_FREQUENCY=UNKNOWN,CLOCK_FREQUENCY_1=116,CLOCK_FREQUENCY_2=77,DEVICE_FAMILY=Cyclone IV E,DEVICE_ID=UNKNOWN,INFORMATION=The maximum output frequency is 80MHz,PART_NAME=EP4CE15F17C8)"
    instancePathKey="int_osc"
    kind="int_osc"
    version="1.0"
    name="int_osc">
-  <parameter name="AUTO_GENERATION_ID" value="1638379169" />
+  <parameter name="AUTO_GENERATION_ID" value="1639116036" />
   <parameter name="AUTO_DEVICE" value="EP4CE15F17C8" />
   <parameter name="AUTO_DEVICE_FAMILY" value="Cyclone IV E" />
   <parameter name="AUTO_UNIQUE_ID" value="" />
@@ -75,7 +75,7 @@
   </sourceFiles>
   <childSourceFiles>
    <file
-       path="/opt/altera/20.1/ip/altera/altera_int_osc/altera_int_osc_hw.tcl" />
+       path="/opt/altera/21.1/ip/altera/altera_int_osc/altera_int_osc_hw.tcl" />
   </childSourceFiles>
   <messages>
    <message level="Debug" culprit="int_osc">queue size: 0 starting:int_osc "int_osc"</message>
@@ -99,10 +99,10 @@
  </entity>
  <entity
    path="submodules/"
-   parameterizationKey="altera_int_osc:20.1:CBX_AUTO_BLACKBOX=ALL,CLOCK_FREQUENCY=UNKNOWN,CLOCK_FREQUENCY_1=116,CLOCK_FREQUENCY_2=77,DEVICE_FAMILY=Cyclone IV E,DEVICE_ID=UNKNOWN,INFORMATION=The maximum output frequency is 80MHz,PART_NAME=EP4CE15F17C8"
+   parameterizationKey="altera_int_osc:21.1:CBX_AUTO_BLACKBOX=ALL,CLOCK_FREQUENCY=UNKNOWN,CLOCK_FREQUENCY_1=116,CLOCK_FREQUENCY_2=77,DEVICE_FAMILY=Cyclone IV E,DEVICE_ID=UNKNOWN,INFORMATION=The maximum output frequency is 80MHz,PART_NAME=EP4CE15F17C8"
    instancePathKey="int_osc:.:int_osc_0"
    kind="altera_int_osc"
-   version="20.1"
+   version="21.1"
    name="altera_int_osc">
   <parameter name="CLOCK_FREQUENCY_2" value="77" />
   <parameter name="CLOCK_FREQUENCY_1" value="116" />
@@ -121,7 +121,7 @@
   <childGeneratedFiles/>
   <sourceFiles>
    <file
-       path="/opt/altera/20.1/ip/altera/altera_int_osc/altera_int_osc_hw.tcl" />
+       path="/opt/altera/21.1/ip/altera/altera_int_osc/altera_int_osc_hw.tcl" />
   </sourceFiles>
   <childSourceFiles/>
   <instantiator instantiator="int_osc" as="int_osc_0" />

+ 2 - 2
fpga/ip/int_osc/simulation/aldec/rivierapro_setup.tcl

@@ -12,7 +12,7 @@
 # or its authorized distributors. Please refer to the applicable 
 # agreement for further details.
 
-# ACDS 20.1 720 linux 2021.12.01.09:19:29
+# ACDS 21.1 842 linux 2021.12.09.22:00:36
 # ----------------------------------------
 # Auto-generated simulation script rivierapro_setup.tcl
 # ----------------------------------------
@@ -113,7 +113,7 @@ if ![info exists QSYS_SIMDIR] {
 }
 
 if ![info exists QUARTUS_INSTALL_DIR] { 
-  set QUARTUS_INSTALL_DIR "/opt/altera/20.1/quartus/"
+  set QUARTUS_INSTALL_DIR "/opt/altera/21.1/quartus/"
 }
 
 if ![info exists USER_DEFINED_COMPILE_OPTIONS] { 

+ 3 - 3
fpga/ip/int_osc/simulation/cadence/ncsim_setup.sh

@@ -12,7 +12,7 @@
 # or its authorized distributors. Please refer to the applicable 
 # agreement for further details.
 
-# ACDS 20.1 720 linux 2021.12.01.09:19:29
+# ACDS 21.1 842 linux 2021.12.09.22:00:36
 
 # ----------------------------------------
 # ncsim - auto-generated simulation script
@@ -106,12 +106,12 @@
 # within the Quartus project, and generate a unified
 # script which supports all the Altera IP within the design.
 # ----------------------------------------
-# ACDS 20.1 720 linux 2021.12.01.09:19:29
+# ACDS 21.1 842 linux 2021.12.09.22:00:36
 # ----------------------------------------
 # initialize variables
 TOP_LEVEL_NAME="int_osc"
 QSYS_SIMDIR="./../"
-QUARTUS_INSTALL_DIR="/opt/altera/20.1/quartus/"
+QUARTUS_INSTALL_DIR="/opt/altera/21.1/quartus/"
 SKIP_FILE_COPY=0
 SKIP_DEV_COM=0
 SKIP_COM=0

+ 1 - 1
fpga/ip/int_osc/simulation/int_osc.sip

@@ -1,5 +1,5 @@
 set_global_assignment -entity "int_osc" -library "lib_int_osc" -name IP_TOOL_NAME "Qsys"
-set_global_assignment -entity "int_osc" -library "lib_int_osc" -name IP_TOOL_VERSION "20.1"
+set_global_assignment -entity "int_osc" -library "lib_int_osc" -name IP_TOOL_VERSION "21.1"
 set_global_assignment -entity "int_osc" -library "lib_int_osc" -name IP_TOOL_ENV "Qsys"
 set_global_assignment -library "lib_int_osc" -name SPD_FILE [file join $::quartus(sip_path) "../int_osc.spd"]
 set_global_assignment -library "lib_int_osc" -name MISC_FILE [file join $::quartus(sip_path) "../../int_osc.qsys"]

+ 1 - 1
fpga/ip/int_osc/simulation/int_osc.v

@@ -1,6 +1,6 @@
 // int_osc.v
 
-// Generated using ACDS version 20.1 720
+// Generated using ACDS version 21.1 842
 
 `timescale 1 ps / 1 ps
 module int_osc (

+ 4 - 4
fpga/ip/int_osc/simulation/mentor/msim_setup.tcl

@@ -94,7 +94,7 @@
 # within the Quartus project, and generate a unified
 # script which supports all the Altera IP within the design.
 # ----------------------------------------
-# ACDS 20.1 720 linux 2021.12.01.09:19:29
+# ACDS 21.1 842 linux 2021.12.09.22:00:35
 
 # ----------------------------------------
 # Initialize variables
@@ -113,7 +113,7 @@ if ![info exists QSYS_SIMDIR] {
 }
 
 if ![info exists QUARTUS_INSTALL_DIR] { 
-  set QUARTUS_INSTALL_DIR "/opt/altera/20.1/quartus/"
+  set QUARTUS_INSTALL_DIR "/opt/altera/21.1/quartus/"
 }
 
 if ![info exists USER_DEFINED_COMPILE_OPTIONS] { 
@@ -150,7 +150,7 @@ ensure_lib          ./libraries/
 ensure_lib          ./libraries/work/
 vmap       work     ./libraries/work/
 vmap       work_lib ./libraries/work/
-if ![ string match "*ModelSim ALTERA*" [ vsim -version ] ] {
+if ![ string match "*Intel*FPGA*" [ vsim -version ] ] {
   ensure_lib                  ./libraries/altera_ver/      
   vmap       altera_ver       ./libraries/altera_ver/      
   ensure_lib                  ./libraries/lpm_ver/         
@@ -171,7 +171,7 @@ vmap       int_osc_0 ./libraries/int_osc_0/
 # Compile device library files
 alias dev_com {
   echo "\[exec\] dev_com"
-  if ![ string match "*ModelSim ALTERA*" [ vsim -version ] ] {
+  if ![ string match "*Intel*FPGA*" [ vsim -version ] ] {
     eval  vlog $USER_DEFINED_VERILOG_COMPILE_OPTIONS $USER_DEFINED_COMPILE_OPTIONS     "$QUARTUS_INSTALL_DIR/eda/sim_lib/altera_primitives.v" -work altera_ver      
     eval  vlog $USER_DEFINED_VERILOG_COMPILE_OPTIONS $USER_DEFINED_COMPILE_OPTIONS     "$QUARTUS_INSTALL_DIR/eda/sim_lib/220model.v"          -work lpm_ver         
     eval  vlog $USER_DEFINED_VERILOG_COMPILE_OPTIONS $USER_DEFINED_COMPILE_OPTIONS     "$QUARTUS_INSTALL_DIR/eda/sim_lib/sgate.v"             -work sgate_ver       

+ 2 - 2
fpga/ip/int_osc/simulation/submodules/altera_int_osc.v

@@ -1,11 +1,11 @@
 //altint_osc CBX_AUTO_BLACKBOX="ALL" CBX_SINGLE_OUTPUT_FILE="ON" DEVICE_FAMILY="Cyclone IV E" clkout oscena
-//VERSION_BEGIN 20.1 cbx_altint_osc 2020:11:11:17:03:37:SJ cbx_arriav 2020:11:11:17:03:36:SJ cbx_cycloneii 2020:11:11:17:03:37:SJ cbx_lpm_add_sub 2020:11:11:17:03:37:SJ cbx_lpm_compare 2020:11:11:17:03:37:SJ cbx_lpm_counter 2020:11:11:17:03:37:SJ cbx_lpm_decode 2020:11:11:17:03:37:SJ cbx_mgl 2020:11:11:17:50:46:SJ cbx_nadder 2020:11:11:17:03:37:SJ cbx_nightfury 2020:11:11:17:03:37:SJ cbx_stratix 2020:11:11:17:03:37:SJ cbx_stratixii 2020:11:11:17:03:37:SJ cbx_stratixiii 2020:11:11:17:03:37:SJ cbx_stratixv 2020:11:11:17:03:37:SJ cbx_tgx 2020:11:11:17:03:37:SJ cbx_zippleback 2020:11:11:17:03:37:SJ  VERSION_END
+//VERSION_BEGIN 21.1 cbx_altint_osc 2021:10:21:11:02:24:SJ cbx_arriav 2021:10:21:11:02:24:SJ cbx_cycloneii 2021:10:21:11:02:24:SJ cbx_lpm_add_sub 2021:10:21:11:02:24:SJ cbx_lpm_compare 2021:10:21:11:02:24:SJ cbx_lpm_counter 2021:10:21:11:02:24:SJ cbx_lpm_decode 2021:10:21:11:02:24:SJ cbx_mgl 2021:10:21:11:11:47:SJ cbx_nadder 2021:10:21:11:02:24:SJ cbx_nightfury 2021:10:21:11:02:24:SJ cbx_stratix 2021:10:21:11:02:24:SJ cbx_stratixii 2021:10:21:11:02:24:SJ cbx_stratixiii 2021:10:21:11:02:24:SJ cbx_stratixv 2021:10:21:11:02:24:SJ cbx_tgx 2021:10:21:11:02:24:SJ cbx_zippleback 2021:10:21:11:02:24:SJ  VERSION_END
 // synthesis VERILOG_INPUT_VERSION VERILOG_2001
 // altera message_off 10463
 
 
 
-// Copyright (C) 2020  Intel Corporation. All rights reserved.
+// Copyright (C) 2021  Intel Corporation. All rights reserved.
 //  Your use of Intel Corporation's design tools, logic functions 
 //  and other software and tools, and any partner logic 
 //  functions, and any output files from any of the foregoing 

+ 3 - 3
fpga/ip/int_osc/simulation/synopsys/vcs/vcs_setup.sh

@@ -12,7 +12,7 @@
 # or its authorized distributors. Please refer to the applicable 
 # agreement for further details.
 
-# ACDS 20.1 720 linux 2021.12.01.09:19:29
+# ACDS 21.1 842 linux 2021.12.09.22:00:36
 
 # ----------------------------------------
 # vcs - auto-generated simulation script
@@ -94,12 +94,12 @@
 # within the Quartus project, and generate a unified
 # script which supports all the Altera IP within the design.
 # ----------------------------------------
-# ACDS 20.1 720 linux 2021.12.01.09:19:29
+# ACDS 21.1 842 linux 2021.12.09.22:00:36
 # ----------------------------------------
 # initialize variables
 TOP_LEVEL_NAME="int_osc"
 QSYS_SIMDIR="./../../"
-QUARTUS_INSTALL_DIR="/opt/altera/20.1/quartus/"
+QUARTUS_INSTALL_DIR="/opt/altera/21.1/quartus/"
 SKIP_FILE_COPY=0
 SKIP_SIM=0
 USER_DEFINED_ELAB_OPTIONS=""

+ 3 - 3
fpga/ip/int_osc/simulation/synopsys/vcsmx/vcsmx_setup.sh

@@ -12,7 +12,7 @@
 # or its authorized distributors. Please refer to the applicable 
 # agreement for further details.
 
-# ACDS 20.1 720 linux 2021.12.01.09:19:29
+# ACDS 21.1 842 linux 2021.12.09.22:00:36
 
 # ----------------------------------------
 # vcsmx - auto-generated simulation script
@@ -107,12 +107,12 @@
 # within the Quartus project, and generate a unified
 # script which supports all the Altera IP within the design.
 # ----------------------------------------
-# ACDS 20.1 720 linux 2021.12.01.09:19:29
+# ACDS 21.1 842 linux 2021.12.09.22:00:36
 # ----------------------------------------
 # initialize variables
 TOP_LEVEL_NAME="int_osc"
 QSYS_SIMDIR="./../../"
-QUARTUS_INSTALL_DIR="/opt/altera/20.1/quartus/"
+QUARTUS_INSTALL_DIR="/opt/altera/21.1/quartus/"
 SKIP_FILE_COPY=0
 SKIP_DEV_COM=0
 SKIP_COM=0

+ 12 - 12
fpga/ip/int_osc/synthesis/int_osc.debuginfo

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<EnsembleReport name="int_osc" kind="system" version="20.1" fabric="QSYS">
- <!-- Format version 20.1 720 (Future versions may contain additional information.) -->
- <!-- 2021.12.01.09:19:29 -->
+<EnsembleReport name="int_osc" kind="system" version="21.1" fabric="QSYS">
+ <!-- Format version 21.1 842 (Future versions may contain additional information.) -->
+ <!-- 2021.12.09.22:00:36 -->
  <!-- A collection of modules and connections -->
  <parameter name="clockCrossingAdapter">
   <type>com.altera.sopcmodel.ensemble.EClockAdapter</type>
@@ -53,7 +53,7 @@
  </parameter>
  <parameter name="generationId">
   <type>int</type>
-  <value>1638379169</value>
+  <value>1639116036</value>
   <derived>false</derived>
   <enabled>true</enabled>
   <visible>true</visible>
@@ -150,7 +150,7 @@
  <module
    name="int_osc_0"
    kind="altera_int_osc"
-   version="20.1"
+   version="21.1"
    path="int_osc_0">
   <!-- Describes a single module. Module parameters are
 the requested settings for a module instance. -->
@@ -236,7 +236,7 @@ the requested settings for a module instance. -->
    <visible>true</visible>
    <valid>true</valid>
   </parameter>
-  <interface name="oscena" kind="conduit_end" version="20.1">
+  <interface name="oscena" kind="conduit_end" version="21.1">
    <!-- The connection points exposed by a module instance for the
 particular module parameters. Connection points and their
 parameters are a RESULT of the module parameters. -->
@@ -285,7 +285,7 @@ parameters are a RESULT of the module parameters. -->
     <role>oscena</role>
    </port>
   </interface>
-  <interface name="clkout" kind="clock_source" version="20.1">
+  <interface name="clkout" kind="clock_source" version="21.1">
    <!-- The connection points exposed by a module instance for the
 particular module parameters. Connection points and their
 parameters are a RESULT of the module parameters. -->
@@ -365,7 +365,7 @@ parameters are a RESULT of the module parameters. -->
   <type>com.altera.entityinterfaces.IElementClass</type>
   <subtype>com.altera.entityinterfaces.IModule</subtype>
   <displayName>Internal Oscillator</displayName>
-  <version>20.1</version>
+  <version>21.1</version>
  </plugin>
  <plugin>
   <instanceCount>1</instanceCount>
@@ -373,7 +373,7 @@ parameters are a RESULT of the module parameters. -->
   <type>com.altera.entityinterfaces.IElementClass</type>
   <subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype>
   <displayName>Conduit</displayName>
-  <version>20.1</version>
+  <version>21.1</version>
  </plugin>
  <plugin>
   <instanceCount>1</instanceCount>
@@ -381,8 +381,8 @@ parameters are a RESULT of the module parameters. -->
   <type>com.altera.entityinterfaces.IElementClass</type>
   <subtype>com.altera.entityinterfaces.IMutableConnectionPoint</subtype>
   <displayName>Clock Output</displayName>
-  <version>20.1</version>
+  <version>21.1</version>
  </plugin>
- <reportVersion>20.1 720</reportVersion>
- <uniqueIdentifier>5254001B7C8D0000017D7702274A</uniqueIdentifier>
+ <reportVersion>21.1 842</reportVersion>
+ <uniqueIdentifier>5254001B7C8D0000017DA2EDD937</uniqueIdentifier>
 </EnsembleReport>

+ 5 - 5
fpga/ip/int_osc/synthesis/int_osc.qip

@@ -1,8 +1,8 @@
 set_global_assignment -entity "int_osc" -library "int_osc" -name IP_TOOL_NAME "Qsys"
-set_global_assignment -entity "int_osc" -library "int_osc" -name IP_TOOL_VERSION "20.1"
+set_global_assignment -entity "int_osc" -library "int_osc" -name IP_TOOL_VERSION "21.1"
 set_global_assignment -entity "int_osc" -library "int_osc" -name IP_TOOL_ENV "Qsys"
 set_global_assignment -library "int_osc" -name SOPCINFO_FILE [file join $::quartus(qip_path) "../../int_osc.sopcinfo"]
-set_global_assignment -entity "int_osc" -library "int_osc" -name SLD_INFO "QSYS_NAME int_osc HAS_SOPCINFO 1 GENERATION_ID 1638379169"
+set_global_assignment -entity "int_osc" -library "int_osc" -name SLD_INFO "QSYS_NAME int_osc HAS_SOPCINFO 1 GENERATION_ID 1639116036"
 set_global_assignment -library "int_osc" -name MISC_FILE [file join $::quartus(qip_path) "../int_osc.cmp"]
 set_global_assignment -library "int_osc" -name SLD_FILE [file join $::quartus(qip_path) "int_osc.debuginfo"]
 set_global_assignment -entity "int_osc" -library "int_osc" -name IP_TARGETED_DEVICE_FAMILY "Cyclone IV E"
@@ -15,7 +15,7 @@ set_global_assignment -entity "int_osc" -library "int_osc" -name IP_COMPONENT_DI
 set_global_assignment -entity "int_osc" -library "int_osc" -name IP_COMPONENT_REPORT_HIERARCHY "On"
 set_global_assignment -entity "int_osc" -library "int_osc" -name IP_COMPONENT_INTERNAL "Off"
 set_global_assignment -entity "int_osc" -library "int_osc" -name IP_COMPONENT_VERSION "MS4w"
-set_global_assignment -entity "int_osc" -library "int_osc" -name IP_COMPONENT_PARAMETER "QVVUT19HRU5FUkFUSU9OX0lE::MTYzODM3OTE2OQ==::QXV0byBHRU5FUkFUSU9OX0lE"
+set_global_assignment -entity "int_osc" -library "int_osc" -name IP_COMPONENT_PARAMETER "QVVUT19HRU5FUkFUSU9OX0lE::MTYzOTExNjAzNg==::QXV0byBHRU5FUkFUSU9OX0lE"
 set_global_assignment -entity "int_osc" -library "int_osc" -name IP_COMPONENT_PARAMETER "QVVUT19ERVZJQ0VfRkFNSUxZ::Q3ljbG9uZSBJViBF::QXV0byBERVZJQ0VfRkFNSUxZ"
 set_global_assignment -entity "int_osc" -library "int_osc" -name IP_COMPONENT_PARAMETER "QVVUT19ERVZJQ0U=::RVA0Q0UxNUYxN0M4::QXV0byBERVZJQ0U="
 set_global_assignment -entity "int_osc" -library "int_osc" -name IP_COMPONENT_PARAMETER "QVVUT19ERVZJQ0VfU1BFRURHUkFERQ==::OA==::QXV0byBERVZJQ0VfU1BFRURHUkFERQ=="
@@ -24,7 +24,7 @@ set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_COMPO
 set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_COMPONENT_REPORT_HIERARCHY "Off"
 set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_COMPONENT_INTERNAL "Off"
 set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u"
-set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_COMPONENT_VERSION "MjAuMQ=="
+set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_COMPONENT_VERSION "MjEuMQ=="
 set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_COMPONENT_DESCRIPTION "SW50ZXJuYWwgT3NjaWxsYXRvciBwcm92aWRlcyBpbnRlcm5hbCBjbG9jayBzb3VyY2UgZm9yIGRlYnVnZ2luZyBwdXJwb3NlLg=="
 set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_COMPONENT_PARAMETER "SU5GT1JNQVRJT04=::VGhlIG1heGltdW0gb3V0cHV0IGZyZXF1ZW5jeSBpcyA4ME1Ieg==::SU5GT1JNQVRJT04="
 set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_COMPONENT_PARAMETER "REVWSUNFX0ZBTUlMWQ==::Q3ljbG9uZSBJViBF::RGV2aWNlIGZhbWlseQ=="
@@ -37,5 +37,5 @@ set_global_assignment -library "int_osc" -name VERILOG_FILE [file join $::quartu
 set_global_assignment -library "int_osc" -name VERILOG_FILE [file join $::quartus(qip_path) "submodules/altera_int_osc.v"]
 
 set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_TOOL_NAME "altera_int_osc"
-set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_TOOL_VERSION "20.1"
+set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_TOOL_VERSION "21.1"
 set_global_assignment -entity "altera_int_osc" -library "int_osc" -name IP_TOOL_ENV "Qsys"

+ 1 - 1
fpga/ip/int_osc/synthesis/int_osc.v

@@ -1,6 +1,6 @@
 // int_osc.v
 
-// Generated using ACDS version 20.1 720
+// Generated using ACDS version 21.1 842
 
 `timescale 1 ps / 1 ps
 module int_osc (

+ 2 - 2
fpga/ip/int_osc/synthesis/submodules/altera_int_osc.v

@@ -1,11 +1,11 @@
 //altint_osc CBX_AUTO_BLACKBOX="ALL" CBX_SINGLE_OUTPUT_FILE="ON" DEVICE_FAMILY="Cyclone IV E" clkout oscena
-//VERSION_BEGIN 20.1 cbx_altint_osc 2020:11:11:17:03:37:SJ cbx_arriav 2020:11:11:17:03:36:SJ cbx_cycloneii 2020:11:11:17:03:37:SJ cbx_lpm_add_sub 2020:11:11:17:03:37:SJ cbx_lpm_compare 2020:11:11:17:03:37:SJ cbx_lpm_counter 2020:11:11:17:03:37:SJ cbx_lpm_decode 2020:11:11:17:03:37:SJ cbx_mgl 2020:11:11:17:50:46:SJ cbx_nadder 2020:11:11:17:03:37:SJ cbx_nightfury 2020:11:11:17:03:37:SJ cbx_stratix 2020:11:11:17:03:37:SJ cbx_stratixii 2020:11:11:17:03:37:SJ cbx_stratixiii 2020:11:11:17:03:37:SJ cbx_stratixv 2020:11:11:17:03:37:SJ cbx_tgx 2020:11:11:17:03:37:SJ cbx_zippleback 2020:11:11:17:03:37:SJ  VERSION_END
+//VERSION_BEGIN 21.1 cbx_altint_osc 2021:10:21:11:02:24:SJ cbx_arriav 2021:10:21:11:02:24:SJ cbx_cycloneii 2021:10:21:11:02:24:SJ cbx_lpm_add_sub 2021:10:21:11:02:24:SJ cbx_lpm_compare 2021:10:21:11:02:24:SJ cbx_lpm_counter 2021:10:21:11:02:24:SJ cbx_lpm_decode 2021:10:21:11:02:24:SJ cbx_mgl 2021:10:21:11:11:47:SJ cbx_nadder 2021:10:21:11:02:24:SJ cbx_nightfury 2021:10:21:11:02:24:SJ cbx_stratix 2021:10:21:11:02:24:SJ cbx_stratixii 2021:10:21:11:02:24:SJ cbx_stratixiii 2021:10:21:11:02:24:SJ cbx_stratixv 2021:10:21:11:02:24:SJ cbx_tgx 2021:10:21:11:02:24:SJ cbx_zippleback 2021:10:21:11:02:24:SJ  VERSION_END
 // synthesis VERILOG_INPUT_VERSION VERILOG_2001
 // altera message_off 10463
 
 
 
-// Copyright (C) 2020  Intel Corporation. All rights reserved.
+// Copyright (C) 2021  Intel Corporation. All rights reserved.
 //  Your use of Intel Corporation's design tools, logic functions 
 //  and other software and tools, and any partner logic 
 //  functions, and any output files from any of the foregoing 

+ 11 - 12
fpga/max80.qsf

@@ -42,7 +42,7 @@ set_global_assignment -name DEVICE EP4CE15F17C8
 set_global_assignment -name TOP_LEVEL_ENTITY max80
 set_global_assignment -name ORIGINAL_QUARTUS_VERSION 18.1.1
 set_global_assignment -name PROJECT_CREATION_TIME_DATE "13:01:33  FEBRUARY 22, 2021"
-set_global_assignment -name LAST_QUARTUS_VERSION "20.1.1 Lite Edition"
+set_global_assignment -name LAST_QUARTUS_VERSION "21.1.0 Lite Edition"
 set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
 set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
 set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
@@ -50,9 +50,9 @@ set_global_assignment -name DEVICE_FILTER_PACKAGE EQFP
 set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144
 set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
 set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256
-set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (Verilog)"
-set_global_assignment -name EDA_TIME_SCALE "100 ps" -section_id eda_simulation
-set_global_assignment -name EDA_OUTPUT_DATA_FORMAT "VERILOG HDL" -section_id eda_simulation
+set_global_assignment -name EDA_SIMULATION_TOOL "Questa Intel FPGA (SystemVerilog)"
+set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation
+set_global_assignment -name EDA_OUTPUT_DATA_FORMAT "SYSTEMVERILOG HDL" -section_id eda_simulation
 set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_timing
 set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_symbol
 set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_signal_integrity
@@ -64,8 +64,8 @@ set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
 set_global_assignment -name VCCA_USER_VOLTAGE 2.5V
 set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
 set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
-set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
-set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE 12.5%
+set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER OFF
+set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE "12.5 %"
 set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008
 set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
 set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
@@ -124,7 +124,7 @@ set_instance_assignment -name IO_STANDARD "2.5 V" -to clock_48
 
 
 set_global_assignment -name EDA_MAP_ILLEGAL_CHARACTERS ON -section_id eda_simulation
-set_global_assignment -name EDA_ENABLE_GLITCH_FILTERING ON -section_id eda_simulation
+set_global_assignment -name EDA_ENABLE_GLITCH_FILTERING OFF -section_id eda_simulation
 set_global_assignment -name EDA_WRITE_NODES_FOR_POWER_ESTIMATION ALL_NODES -section_id eda_simulation
 set_global_assignment -name EDA_TEST_BENCH_DESIGN_INSTANCE_NAME max80 -section_id eda_simulation
 set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to led[1]
@@ -247,22 +247,22 @@ set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to rngio[0]
 set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to rngio[1]
 set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to rngio[2]
 
+
+set_global_assignment -name MUX_RESTRUCTURE AUTO
+set_global_assignment -name SYSTEMVERILOG_FILE usb/usb_serial/src_v/usb_cdc_core.sv
+set_global_assignment -name SYSTEMVERILOG_FILE usb/usb_serial/src_v/usbf_device_core.sv
 set_global_assignment -name SYSTEMVERILOG_FILE rng.sv
-set_global_assignment -name VERILOG_FILE ip/int_osc/synthesis/int_osc.v
 set_global_assignment -name QIP_FILE ip/int_osc/synthesis/int_osc.qip
-set_global_assignment -name VERILOG_FILE ip/int_osc/synthesis/submodules/altera_int_osc.v
 set_global_assignment -name VERILOG_FILE ip/pll4.v
 set_global_assignment -name VERILOG_FILE ip/pll3.v
 set_global_assignment -name VERILOG_FILE ip/pll2.v
 set_global_assignment -name VERILOG_FILE usb/usb_fs_phy/src_v/usb_fs_phy.v
 set_global_assignment -name VERILOG_FILE usb/usb_serial/src_v/usbf_sie_tx.v
 set_global_assignment -name VERILOG_FILE usb/usb_serial/src_v/usbf_sie_rx.v
-set_global_assignment -name VERILOG_FILE usb/usb_serial/src_v/usbf_device_core.v
 set_global_assignment -name VERILOG_FILE usb/usb_serial/src_v/usbf_defs.v
 set_global_assignment -name VERILOG_FILE usb/usb_serial/src_v/usbf_crc16.v
 set_global_assignment -name VERILOG_FILE usb/usb_serial/src_v/usb_desc_rom.v
 set_global_assignment -name VERILOG_FILE usb/usb_serial/src_v/usb_cdc_top.v
-set_global_assignment -name VERILOG_FILE usb/usb_serial/src_v/usb_cdc_core.v
 set_global_assignment -name SYSTEMVERILOG_FILE usb/usb.sv
 set_global_assignment -name VERILOG_FILE ip/statusram.v
 set_global_assignment -name VERILOG_INCLUDE_FILE iodevs.vh
@@ -294,5 +294,4 @@ set_global_assignment -name SOURCE_FILE max80.pins
 set_global_assignment -name SOURCE_TCL_SCRIPT_FILE scripts/pins.tcl
 set_global_assignment -name VERILOG_FILE ip/fifo.v
 set_global_assignment -name VERILOG_FILE ip/ddufifo.v
-
 set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

BIN
fpga/output_files/max80.jbc


+ 2 - 2
fpga/output_files/max80.jdi

@@ -1,6 +1,6 @@
 <sld_project_info>
   <project>
-    <hash md5_digest_80b="37b389424706a6c44117"/>
+    <hash md5_digest_80b="abf5fd392e1a6e33688a"/>
   </project>
   <file_info>
     <file device="EP4CE15F17C8" path="max80.sof" usercode="0xFFFFFFFF"/>
@@ -8,7 +8,7 @@
   <sld_infos>
     <sld_info hpath="rng:rng|int_osc:int_osc" name="int_osc">
       <assignment_values>
-        <assignment_value text="QSYS_NAME int_osc HAS_SOPCINFO 1 GENERATION_ID 1638379169"/>
+        <assignment_value text="QSYS_NAME int_osc HAS_SOPCINFO 1 GENERATION_ID 1639116036"/>
       </assignment_values>
       <parameters/>
     </sld_info>

BIN
fpga/output_files/max80.jic


+ 2 - 2
fpga/output_files/max80.pin

@@ -1,4 +1,4 @@
- -- Copyright (C) 2020  Intel Corporation. All rights reserved.
+ -- Copyright (C) 2021  Intel Corporation. All rights reserved.
  -- Your use of Intel Corporation's design tools, logic functions 
  -- and other software and tools, and any partner logic 
  -- functions, and any output files from any of the foregoing 
@@ -64,7 +64,7 @@
  -- Pin directions (input, output or bidir) are based on device operating in user mode.
  ---------------------------------------------------------------------------------
 
-Quartus Prime Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
+Quartus Prime Version 21.1.0 Build 842 10/21/2021 SJ Lite Edition
 CHIP  "max80"  ASSIGNED TO AN: EP4CE15F17C8
 
 Pin Name/Usage               : Location  : Dir.   : I/O Standard      : Voltage : I/O Bank  : User Assignment

BIN
fpga/output_files/max80.pof


+ 1 - 1
fpga/output_files/max80.sld

@@ -2,7 +2,7 @@
   <sld_infos>
     <sld_info hpath="rng:rng|int_osc:int_osc" name="int_osc">
       <assignment_values>
-        <assignment_value text="QSYS_NAME int_osc HAS_SOPCINFO 1 GENERATION_ID 1638379169"/>
+        <assignment_value text="QSYS_NAME int_osc HAS_SOPCINFO 1 GENERATION_ID 1639116036"/>
       </assignment_values>
     </sld_info>
   </sld_infos>

BIN
fpga/output_files/max80.sof


+ 6 - 6
fpga/sdram.sv

@@ -140,7 +140,7 @@ module dram_port
 	  else if (bus.start)
 	    begin
 	       started <= 1'b1;
-	       ready   <= |bus.wstrb; // All write data latched
+	       ready   <= bus.wrack;
 	    end
 	  else if (started & ~ready)
 	    begin
@@ -191,9 +191,9 @@ module dram_arbiter
 			     (ustr[i].prio >= rfsh_prio);
 
 	   assign ustr[i].start = grant[i] & dstr.start;
-	   assign dstr.addr     = grant[i] ? ustr[i].addr  : 'z;
-	   assign dstr.wd       = grant[i] ? ustr[i].wd    : 'z;
-	   assign dstr.wstrb    = grant[i] ? ustr[i].wstrb : 'z;
+	   assign dstr.addr     = grant[i] ? ustr[i].addr  : 'bz;
+	   assign dstr.wd       = grant[i] ? ustr[i].wd    : 'bz;
+	   assign dstr.wstrb    = grant[i] ? ustr[i].wstrb : 'bz;
 	end // block: u
    endgenerate
 
@@ -257,8 +257,8 @@ module sdram
 	      output [12:0] sr_a, // SDRAM address bus
 	      inout [15:0]  sr_dq, // SDRAM data bus
 
-			    // Port 1
-			    dram_bus.ustr port1 [1:port1_count],
+	      // Port 1
+	      dram_bus.ustr port1 [1:port1_count],
 
 	      // Port 2
 	      input [24:1]  a2,

+ 0 - 3
fpga/usb/usb_fs_phy/src_v/usb_fs_phy.v

@@ -75,9 +75,6 @@ module usb_fs_phy
 //-----------------------------------------------------------------
 reg         rx_en_q;
 
-// Xilinx placement pragmas:
-//synthesis attribute IOB of out_dp_q is "TRUE"
-//synthesis attribute IOB of out_dn_q is "TRUE"
 reg         out_dp_q;
 reg         out_dn_q;
 

+ 991 - 0
fpga/usb/usb_serial/src_v/usb_cdc_core.sv

@@ -0,0 +1,991 @@
+//-----------------------------------------------------------------
+//                       USB Serial Port
+//                            V0.1
+//                     Ultra-Embedded.com
+//                       Copyright 2020
+//
+//                 Email: admin@ultra-embedded.com
+//
+//                         License: LGPL
+//-----------------------------------------------------------------
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file 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 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source 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 source; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA  02111-1307  USA
+//-----------------------------------------------------------------
+
+module usb_cdc_core
+  (
+   // Inputs
+   input clk_i
+   ,input rst_i
+   ,input enable_i
+   ,input [ 7:0] utmi_data_in_i
+   ,input utmi_txready_i
+   ,input utmi_rxvalid_i
+   ,input utmi_rxactive_i
+   ,input utmi_rxerror_i
+   ,input [ 1:0] utmi_linestate_i
+   ,input inport_valid_i
+   ,input [ 7:0] inport_data_i
+   ,input outport_accept_i
+     
+   // Outputs
+   ,output [ 7:0] utmi_data_out_o
+   ,output utmi_txvalid_o
+   ,output [ 1:0] utmi_op_mode_o
+   ,output [ 1:0] utmi_xcvrselect_o
+   ,output utmi_termselect_o
+   ,output utmi_dppulldown_o
+   ,output utmi_dmpulldown_o
+   ,output inport_accept_o
+   ,output outport_valid_o
+   ,output [ 7:0] outport_data_o
+   ,output outport_break_o
+   );
+
+   parameter USB_SPEED_HS = "False"; // True or False
+
+   //-----------------------------------------------------------------
+   // Defines
+   //-----------------------------------------------------------------
+   // Device class
+`define DEV_CLASS_RESERVED              8'h00
+`define DEV_CLASS_AUDIO                 8'h01
+`define DEV_CLASS_COMMS                 8'h02
+`define DEV_CLASS_HID                   8'h03
+`define DEV_CLASS_MONITOR               8'h04
+`define DEV_CLASS_PHY_IF                8'h05
+`define DEV_CLASS_POWER                 8'h06
+`define DEV_CLASS_PRINTER               8'h07
+`define DEV_CLASS_STORAGE               8'h08
+`define DEV_CLASS_HUB                   8'h09
+`define DEV_CLASS_TMC                   8'hFE
+`define DEV_CLASS_VENDOR_CUSTOM         8'hFF
+
+   // Standard requests (via SETUP packets)
+`define REQ_GET_STATUS                  8'h00
+`define REQ_CLEAR_FEATURE               8'h01
+`define REQ_SET_FEATURE                 8'h03
+`define REQ_SET_ADDRESS                 8'h05
+`define REQ_GET_DESCRIPTOR              8'h06
+`define REQ_SET_DESCRIPTOR              8'h07
+`define REQ_GET_CONFIGURATION           8'h08
+`define REQ_SET_CONFIGURATION           8'h09
+`define REQ_GET_INTERFACE               8'h0A
+`define REQ_SET_INTERFACE               8'h0B
+`define REQ_SYNC_FRAME                  8'h0C
+
+   // Descriptor types
+`define DESC_DEVICE                     8'h01
+`define DESC_CONFIGURATION              8'h02
+`define DESC_STRING                     8'h03
+`define DESC_INTERFACE                  8'h04
+`define DESC_ENDPOINT                   8'h05
+`define DESC_DEV_QUALIFIER              8'h06
+`define DESC_OTHER_SPEED_CONF           8'h07
+`define DESC_IF_POWER                   8'h08
+
+   // Endpoints
+`define ENDPOINT_DIR_MASK               8'h80
+`define ENDPOINT_DIR_R                  7
+`define ENDPOINT_DIR_IN                 1'b1
+`define ENDPOINT_DIR_OUT                1'b0
+`define ENDPOINT_ADDR_MASK              8'h7F
+`define ENDPOINT_TYPE_MASK              8'h3
+`define ENDPOINT_TYPE_CONTROL           0
+`define ENDPOINT_TYPE_ISO               1
+`define ENDPOINT_TYPE_BULK              2
+`define ENDPOINT_TYPE_INTERRUPT         3
+
+   // Device Requests (bmRequestType)
+`define USB_RECIPIENT_MASK              8'h1F
+`define USB_RECIPIENT_DEVICE            8'h00
+`define USB_RECIPIENT_INTERFACE         8'h01
+`define USB_RECIPIENT_ENDPOINT          8'h02
+`define USB_REQUEST_TYPE_MASK           8'h60
+`define USB_STANDARD_REQUEST            8'h00
+`define USB_CLASS_REQUEST               8'h20
+`define USB_VENDOR_REQUEST              8'h40
+
+   // USB device addresses are 7-bits
+`define USB_ADDRESS_MASK                8'h7F
+
+   // USB Feature Selectors
+`define USB_FEATURE_ENDPOINT_STATE      16'h0000
+`define USB_FEATURE_REMOTE_WAKEUP       16'h0001
+`define USB_FEATURE_TEST_MODE           16'h0002
+
+   // String Descriptors
+`define UNICODE_LANGUAGE_STR_ID         8'd0
+`define MANUFACTURER_STR_ID             8'd1
+`define PRODUCT_NAME_STR_ID             8'd2
+`define SERIAL_NUM_STR_ID               8'd3
+
+`define CDC_ENDPOINT_BULK_OUT           1
+`define CDC_ENDPOINT_BULK_IN            2
+`define CDC_ENDPOINT_INTR_IN            3
+
+`define CDC_SEND_ENCAPSULATED_COMMAND   8'h00
+`define CDC_GET_ENCAPSULATED_RESPONSE   8'h01
+`define CDC_GET_LINE_CODING             8'h21
+`define CDC_SET_LINE_CODING             8'h20
+`define CDC_SET_CONTROL_LINE_STATE      8'h22
+`define CDC_SEND_BREAK                  8'h23
+
+   // Descriptor ROM offsets / sizes
+`define ROM_DESC_DEVICE_ADDR            8'd0
+`define ROM_DESC_DEVICE_SIZE            16'd18
+`define ROM_DESC_CONF_ADDR              8'd18
+`define ROM_DESC_CONF_SIZE              16'd67
+`define ROM_DESC_STR_LANG_ADDR          8'd85
+`define ROM_DESC_STR_LANG_SIZE          16'd4
+`define ROM_DESC_STR_MAN_ADDR           8'd89
+`define ROM_DESC_STR_MAN_SIZE           16'd30
+`define ROM_DESC_STR_PROD_ADDR          8'd119
+`define ROM_DESC_STR_PROD_SIZE          16'd30
+`define ROM_DESC_STR_SERIAL_ADDR        8'd149
+`define ROM_DESC_STR_SERIAL_SIZE        16'd14
+`define ROM_CDC_LINE_CODING_ADDR        8'd163
+`define ROM_CDC_LINE_CODING_SIZE        16'd7
+
+   //-----------------------------------------------------------------
+   // Wires
+   //-----------------------------------------------------------------
+
+   wire  usb_reset_w;
+   reg [6:0] device_addr_q;
+
+   localparam endpoints = 4;
+   usb_endpoint usb_ep [0:endpoints-1] ();
+   
+   wire       utmi_chirp_en_w;
+   wire       usb_hs_w;
+
+   //-----------------------------------------------------------------
+   // Transceiver Control (high speed)
+   //-----------------------------------------------------------------
+   generate
+      if (USB_SPEED_HS == "True")
+	begin
+
+	   localparam STATE_W                       = 3;
+	   localparam STATE_IDLE                    = 3'd0;
+	   localparam STATE_WAIT_RST                = 3'd1;
+	   localparam STATE_SEND_CHIRP_K            = 3'd2;
+	   localparam STATE_WAIT_CHIRP_JK           = 3'd3;
+	   localparam STATE_FULLSPEED               = 3'd4;
+	   localparam STATE_HIGHSPEED               = 3'd5;
+	   reg [STATE_W-1:0] state_q;
+	   reg [STATE_W-1:0] next_state_r;
+
+	   // 60MHz clock rate
+`define USB_RST_W  20
+	   reg [`USB_RST_W-1:0] usb_rst_time_q;
+	   reg [7:0] 		chirp_count_q;
+	   reg [1:0] 		last_linestate_q;
+
+	   localparam DETACH_TIME    = 20'd60000;  // 1ms -> T0
+	   localparam ATTACH_FS_TIME = 20'd180000; // T0 + 3ms = T1
+	   localparam CHIRPK_TIME    = 20'd246000; // T1 + ~1ms
+	   localparam HS_RESET_TIME  = 20'd600000; // T0 + 10ms = T9
+	   localparam HS_CHIRP_COUNT = 8'd5;
+
+	   reg [  1:0] 		utmi_op_mode_r;
+	   reg [  1:0] 		utmi_xcvrselect_r;
+	   reg 			utmi_termselect_r;
+	   reg 			utmi_dppulldown_r;
+	   reg 			utmi_dmpulldown_r;
+
+	   always @ *
+	     begin
+		next_state_r = state_q;
+
+		// Default - disconnect
+		utmi_op_mode_r    = 2'd1;
+		utmi_xcvrselect_r = 2'd0;
+		utmi_termselect_r = 1'b0;
+		utmi_dppulldown_r = 1'b0;
+		utmi_dmpulldown_r = 1'b0;
+
+		case (state_q)
+		  STATE_IDLE:
+		    begin
+		       // Detached
+		       if (enable_i && usb_rst_time_q >= DETACH_TIME)
+			 next_state_r = STATE_WAIT_RST;
+		    end
+		  STATE_WAIT_RST:
+		    begin
+		       // Assert FS mode, check for SE0 (T0)
+		       utmi_op_mode_r    = 2'd0;
+		       utmi_xcvrselect_r = 2'd1;
+		       utmi_termselect_r = 1'b1;
+		       utmi_dppulldown_r = 1'b0;
+		       utmi_dmpulldown_r = 1'b0;
+
+		       // Wait for SE0 (T1), send device chirp K
+		       if (usb_rst_time_q >= ATTACH_FS_TIME)
+			 next_state_r = STATE_SEND_CHIRP_K;
+		    end
+		  STATE_SEND_CHIRP_K:
+		    begin
+		       // Send chirp K
+		       utmi_op_mode_r    = 2'd2;
+		       utmi_xcvrselect_r = 2'd0;
+		       utmi_termselect_r = 1'b1;
+		       utmi_dppulldown_r = 1'b0;
+		       utmi_dmpulldown_r = 1'b0;
+
+		       // End of device chirp K (T2)
+		       if (usb_rst_time_q >= CHIRPK_TIME)
+			 next_state_r = STATE_WAIT_CHIRP_JK;
+		    end
+		  STATE_WAIT_CHIRP_JK:
+		    begin
+		       // Stop sending chirp K and wait for downstream port chirps
+		       utmi_op_mode_r    = 2'd2;
+		       utmi_xcvrselect_r = 2'd0;
+		       utmi_termselect_r = 1'b1;
+		       utmi_dppulldown_r = 1'b0;
+		       utmi_dmpulldown_r = 1'b0;
+
+		       // Required number of chirps detected, move to HS mode (T7)
+		       if (chirp_count_q >= HS_CHIRP_COUNT)
+			 next_state_r = STATE_HIGHSPEED;
+		       // Time out waiting for chirps, fallback to FS mode
+		       else if (usb_rst_time_q >= HS_RESET_TIME)
+			 next_state_r = STATE_FULLSPEED;
+		    end
+		  STATE_FULLSPEED:
+		    begin
+		       utmi_op_mode_r    = 2'd0;
+		       utmi_xcvrselect_r = 2'd1;
+		       utmi_termselect_r = 1'b1;
+		       utmi_dppulldown_r = 1'b0;
+		       utmi_dmpulldown_r = 1'b0;
+
+		       // USB reset detected...
+		       if (usb_rst_time_q >= HS_RESET_TIME && usb_reset_w)
+			 next_state_r = STATE_WAIT_RST;
+		    end
+		  STATE_HIGHSPEED:
+		    begin
+		       // Enter HS mode
+		       utmi_op_mode_r    = 2'd0;
+		       utmi_xcvrselect_r = 2'd0;
+		       utmi_termselect_r = 1'b0;
+		       utmi_dppulldown_r = 1'b0;
+		       utmi_dmpulldown_r = 1'b0;
+
+		       // Long SE0 - could be reset or suspend
+		       // TODO: Should revert to FS mode and check...
+		       if (usb_rst_time_q >= HS_RESET_TIME && usb_reset_w)
+			 next_state_r = STATE_WAIT_RST;
+		    end
+		  default:
+		    ;
+		endcase
+	     end
+
+	   // Update state
+	   always @ (posedge clk_i or posedge rst_i)
+	     if (rst_i)
+	       state_q   <= STATE_IDLE;
+	     else
+	       state_q   <= next_state_r;
+
+	   // Time since T0 (start of HS reset)
+	   always @ (posedge clk_i or posedge rst_i)
+	     if (rst_i)
+	       usb_rst_time_q <= `USB_RST_W'b0;
+	   // Entering wait for reset state
+	     else if (next_state_r == STATE_WAIT_RST && state_q != STATE_WAIT_RST)
+	       usb_rst_time_q <=  `USB_RST_W'b0;
+	   // Waiting for reset, reset count on line state toggle
+	     else if (state_q == STATE_WAIT_RST && (utmi_linestate_i != 2'b00))
+	       usb_rst_time_q <=  `USB_RST_W'b0;
+	     else if (usb_rst_time_q != {(`USB_RST_W){1'b1}})
+	       usb_rst_time_q <= usb_rst_time_q + `USB_RST_W'd1;
+
+	   always @ (posedge clk_i or posedge rst_i)
+	     if (rst_i)
+	       last_linestate_q   <= 2'b0;
+	     else
+	       last_linestate_q   <= utmi_linestate_i;
+
+	   // Chirp counter
+	   always @ (posedge clk_i or posedge rst_i)
+	     if (rst_i)
+	       chirp_count_q   <= 8'b0;
+	     else if (state_q == STATE_SEND_CHIRP_K)
+	       chirp_count_q   <= 8'b0;
+	     else if (state_q == STATE_WAIT_CHIRP_JK && (last_linestate_q != utmi_linestate_i) && chirp_count_q != 8'hFF)
+	       chirp_count_q   <= chirp_count_q + 8'd1;
+
+	   assign utmi_op_mode_o    = utmi_op_mode_r;
+	   assign utmi_xcvrselect_o = utmi_xcvrselect_r;
+	   assign utmi_termselect_o = utmi_termselect_r;
+	   assign utmi_dppulldown_o = utmi_dppulldown_r;
+	   assign utmi_dmpulldown_o = utmi_dmpulldown_r;
+
+	   assign utmi_chirp_en_w   = (state_q == STATE_SEND_CHIRP_K);
+	   assign usb_hs_w          = (state_q == STATE_HIGHSPEED);
+
+	end
+      else
+	begin
+	   //-----------------------------------------------------------------
+	   // Transceiver Control
+	   //-----------------------------------------------------------------
+	   reg [  1:0]  utmi_op_mode_r;
+	   reg [  1:0] 	utmi_xcvrselect_r;
+	   reg          utmi_termselect_r;
+	   reg          utmi_dppulldown_r;
+	   reg          utmi_dmpulldown_r;
+
+	   always @ *
+	     begin
+		if (enable_i)
+		  begin
+		     utmi_op_mode_r    = 2'd0;
+		     utmi_xcvrselect_r = 2'd1;
+		     utmi_termselect_r = 1'b1;
+		     utmi_dppulldown_r = 1'b0;
+		     utmi_dmpulldown_r = 1'b0;
+		  end
+		else
+		  begin
+		     utmi_op_mode_r    = 2'd1;
+		     utmi_xcvrselect_r = 2'd0;
+		     utmi_termselect_r = 1'b0;
+		     utmi_dppulldown_r = 1'b0;
+		     utmi_dmpulldown_r = 1'b0;
+		  end
+	     end
+
+	   assign utmi_op_mode_o    = utmi_op_mode_r;
+	   assign utmi_xcvrselect_o = utmi_xcvrselect_r;
+	   assign utmi_termselect_o = utmi_termselect_r;
+	   assign utmi_dppulldown_o = utmi_dppulldown_r;
+	   assign utmi_dmpulldown_o = utmi_dmpulldown_r;
+
+	   assign utmi_chirp_en_w   = 1'b0;
+	   assign usb_hs_w          = 1'b0;
+
+	end
+   endgenerate
+
+   //-----------------------------------------------------------------
+   // Core
+   //-----------------------------------------------------------------
+   usbf_device_core #(.endpoints(endpoints))
+     u_core
+       (
+	.clk_i(clk_i),
+	.rst_i(rst_i),
+
+	.intr_o(),
+
+	// UTMI interface
+	.utmi_data_o(utmi_data_out_o),
+	.utmi_data_i(utmi_data_in_i),
+	.utmi_txvalid_o(utmi_txvalid_o),
+	.utmi_txready_i(utmi_txready_i),
+	.utmi_rxvalid_i(utmi_rxvalid_i),
+	.utmi_rxactive_i(utmi_rxactive_i),
+	.utmi_rxerror_i(utmi_rxerror_i),
+	.utmi_linestate_i(utmi_linestate_i),
+
+	.reg_chirp_en_i(utmi_chirp_en_w),
+	.reg_int_en_sof_i(1'b0),
+
+	.reg_dev_addr_i(device_addr_q),
+
+	// Endpoint interfaces array
+	.ep (usb_ep),
+
+	// Status
+	.reg_sts_rst_clr_i(1'b1),
+	.reg_sts_rst_o(usb_reset_w),
+	.reg_sts_frame_num_o()
+	);
+
+   // USB: Setup packet capture (limited to 8 bytes for USB-FS)
+   //-----------------------------------------------------------------
+   reg [7:0] setup_packet_q[0:7];
+   reg [2:0] setup_wr_idx_q;
+   reg       setup_frame_q;
+   reg       setup_valid_q;
+   reg       setup_data_q;
+   reg       status_ready_q; // STATUS response received
+
+   assign usb_ep[0].d.rx_space = 1'b1;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       begin
+	  setup_packet_q[0]  <= 8'b0;
+	  setup_packet_q[1]  <= 8'b0;
+	  setup_packet_q[2]  <= 8'b0;
+	  setup_packet_q[3]  <= 8'b0;
+	  setup_packet_q[4]  <= 8'b0;
+	  setup_packet_q[5]  <= 8'b0;
+	  setup_packet_q[6]  <= 8'b0;
+	  setup_packet_q[7]  <= 8'b0;
+	  setup_wr_idx_q     <= 3'b0;
+	  setup_valid_q      <= 1'b0;
+	  setup_frame_q      <= 1'b0;
+	  setup_data_q       <= 1'b0;
+	  status_ready_q     <= 1'b0;
+       end
+   // SETUP token received
+     else if (usb_ep[0].uc.rx_setup)
+       begin
+	  setup_packet_q[0]  <= 8'b0;
+	  setup_packet_q[1]  <= 8'b0;
+	  setup_packet_q[2]  <= 8'b0;
+	  setup_packet_q[3]  <= 8'b0;
+	  setup_packet_q[4]  <= 8'b0;
+	  setup_packet_q[5]  <= 8'b0;
+	  setup_packet_q[6]  <= 8'b0;
+	  setup_packet_q[7]  <= 8'b0;
+	  setup_wr_idx_q     <= 3'b0;
+	  setup_valid_q      <= 1'b0;
+	  setup_frame_q      <= 1'b1;
+	  setup_data_q       <= 1'b0;
+	  status_ready_q     <= 1'b0;
+       end
+   // Valid DATA for setup frame
+     else if (usb_ep[0].u.rx_valid && usb_ep[0].uc.rx_strb)
+       begin
+	  setup_packet_q[setup_wr_idx_q] <= usb_ep[0].uc.rx_data;
+	  setup_wr_idx_q      <= setup_wr_idx_q + 3'd1;
+	  setup_valid_q       <=  setup_frame_q && usb_ep[0].uc.rx_last;
+	  setup_data_q        <= !setup_frame_q && usb_ep[0].uc.rx_last;
+	  if (usb_ep[0].uc.rx_last)
+            setup_frame_q   <= 1'b0;
+       end
+   // Detect STATUS stage (ACK for SETUP GET requests)
+   // TODO: Not quite correct ....
+     else if (usb_ep[0].u.rx_valid && !usb_ep[0].uc.rx_strb &&
+	      usb_ep[0].uc.rx_last)
+       begin
+	  setup_valid_q       <= 1'b0;
+	  status_ready_q      <= 1'b1;
+       end
+     else
+       setup_valid_q       <= 1'b0;
+
+   //-----------------------------------------------------------------
+   // SETUP request decode
+   //-----------------------------------------------------------------
+   wire [7:0]  bmRequestType_w = setup_packet_q[0];
+   wire [7:0]  bRequest_w      = setup_packet_q[1];
+   wire [15:0] wValue_w        = {setup_packet_q[3], setup_packet_q[2]};
+   wire [15:0] wIndex_w        = {setup_packet_q[5], setup_packet_q[4]};
+   wire [15:0] wLength         = {setup_packet_q[7], setup_packet_q[6]};
+
+   wire        setup_get_w            = setup_valid_q && (bmRequestType_w[`ENDPOINT_DIR_R] == `ENDPOINT_DIR_IN);
+   wire        setup_set_w            = setup_valid_q && (bmRequestType_w[`ENDPOINT_DIR_R] == `ENDPOINT_DIR_OUT);
+   wire        setup_no_data_w        = setup_set_w && (wLength == 16'b0);
+
+   // For REQ_GET_DESCRIPTOR
+   wire [7:0]  bDescriptorType_w  = setup_packet_q[3];
+   wire [7:0]  bDescriptorIndex_w = setup_packet_q[2];
+
+   //-----------------------------------------------------------------
+   // Process setup request
+   //-----------------------------------------------------------------
+   reg 	       ctrl_stall_r; // Send STALL
+   reg 	       ctrl_ack_r;   // Send STATUS (ZLP)
+   reg [15:0]  ctrl_get_len_r;
+
+   reg [7:0]   desc_addr_r;
+
+   reg 	       rx_break_q;
+   reg 	       rx_break_r;
+
+   reg 	       addressed_q;
+   reg 	       addressed_r;
+   reg [6:0]   device_addr_r;
+
+   reg 	       configured_q;
+   reg 	       configured_r;
+
+   reg 	       set_with_data_q;
+   reg 	       set_with_data_r;
+   wire        data_status_zlp_w;
+
+   always @ *
+     begin
+	ctrl_stall_r    = 1'b0;
+	ctrl_get_len_r  = 16'b0;
+	ctrl_ack_r      = 1'b0;
+	desc_addr_r     = 8'b0;
+	device_addr_r   = device_addr_q;
+	addressed_r     = addressed_q;
+	configured_r    = configured_q;
+	set_with_data_r = set_with_data_q;
+	rx_break_r      = 1'b0;
+
+	if (setup_valid_q)
+	  begin
+             set_with_data_r = 1'b0;
+
+             case (bmRequestType_w & `USB_REQUEST_TYPE_MASK)
+               `USB_STANDARD_REQUEST:
+		 begin
+		    case (bRequest_w)
+		      `REQ_GET_STATUS:
+			begin
+			   $display("GET_STATUS");
+			end
+		      `REQ_CLEAR_FEATURE:
+			begin
+			   $display("CLEAR_FEATURE");
+			   ctrl_ack_r = setup_set_w && setup_no_data_w;
+			end
+		      `REQ_SET_FEATURE:
+			begin
+			   $display("SET_FEATURE");
+			   ctrl_ack_r = setup_set_w && setup_no_data_w;
+			end
+		      `REQ_SET_ADDRESS:
+			begin
+			   $display("SET_ADDRESS: Set device address %d", wValue_w[6:0]);
+			   ctrl_ack_r    = setup_set_w && setup_no_data_w;
+			   device_addr_r = wValue_w[6:0];
+			   addressed_r   = 1'b1;
+			end
+		      `REQ_GET_DESCRIPTOR:
+			begin
+			   $display("GET_DESCRIPTOR: Type %d", bDescriptorType_w);
+
+			   case (bDescriptorType_w)
+			     `DESC_DEVICE:
+			       begin
+				  desc_addr_r    = `ROM_DESC_DEVICE_ADDR;
+				  ctrl_get_len_r = `ROM_DESC_DEVICE_SIZE;
+			       end
+			     `DESC_CONFIGURATION:
+			       begin
+				  desc_addr_r    = `ROM_DESC_CONF_ADDR;
+				  ctrl_get_len_r = `ROM_DESC_CONF_SIZE;
+			       end
+			     `DESC_STRING:
+			       begin
+				  case (bDescriptorIndex_w)
+				    `UNICODE_LANGUAGE_STR_ID:
+				      begin
+					 desc_addr_r    = `ROM_DESC_STR_LANG_ADDR;
+					 ctrl_get_len_r = `ROM_DESC_STR_LANG_SIZE;
+				      end
+				    `MANUFACTURER_STR_ID:
+				      begin
+					 desc_addr_r    = `ROM_DESC_STR_MAN_ADDR;
+					 ctrl_get_len_r = `ROM_DESC_STR_MAN_SIZE;
+				      end
+				    `PRODUCT_NAME_STR_ID:
+				      begin
+					 desc_addr_r    = `ROM_DESC_STR_PROD_ADDR;
+					 ctrl_get_len_r = `ROM_DESC_STR_PROD_SIZE;
+				      end
+				    `SERIAL_NUM_STR_ID:
+				      begin
+					 desc_addr_r    = `ROM_DESC_STR_SERIAL_ADDR;
+					 ctrl_get_len_r = `ROM_DESC_STR_SERIAL_SIZE;
+				      end
+				    default:
+				      ;
+				  endcase
+			       end
+			     default:
+			       ;
+			   endcase
+			end
+		      `REQ_GET_CONFIGURATION:
+			begin
+			   $display("GET_CONF");
+			end
+		      `REQ_SET_CONFIGURATION:
+			begin
+			   $display("SET_CONF: Configuration %x", wValue_w);
+
+			   if (wValue_w == 16'd0)
+			     begin
+				configured_r = 1'b0;
+				ctrl_ack_r   = setup_set_w && setup_no_data_w;
+			     end
+			   // Only support one configuration for now
+			   else if (wValue_w == 16'd1)
+			     begin
+				configured_r = 1'b1;
+				ctrl_ack_r   = setup_set_w && setup_no_data_w;
+			     end
+			   else
+			     ctrl_stall_r = 1'b1;
+			end
+		      `REQ_GET_INTERFACE:
+			begin
+			   $display("GET_INTERFACE");
+			   ctrl_stall_r = 1'b1;
+			end
+		      `REQ_SET_INTERFACE:
+			begin
+			   $display("SET_INTERFACE: %x %x", wValue_w, wIndex_w);
+			   if (wValue_w == 16'd0 && wIndex_w == 16'd0)
+			     ctrl_ack_r   = setup_set_w && setup_no_data_w;
+			   else
+			     ctrl_stall_r = 1'b1;
+			end
+		      default:
+			begin
+			   ctrl_stall_r = 1'b1;
+			end
+		    endcase
+		 end
+               `USB_VENDOR_REQUEST:
+		 begin
+		    // None supported
+		    ctrl_stall_r = 1'b1;
+		 end
+               `USB_CLASS_REQUEST:
+		 begin
+		    ctrl_ack_r      = setup_set_w && setup_no_data_w;
+		    set_with_data_r = setup_set_w && !setup_no_data_w;
+
+		    case (bRequest_w)
+		      `CDC_GET_LINE_CODING:
+			begin
+			   $display("CDC_GET_LINE_CODING");
+			   desc_addr_r    = `ROM_CDC_LINE_CODING_ADDR;
+			   ctrl_get_len_r = `ROM_CDC_LINE_CODING_SIZE;
+			end
+		      `CDC_SEND_BREAK:
+			begin
+			   rx_break_r    = (wValue_w != 16'd0);
+			end
+		      default:
+			begin
+			   // Do nothing
+			end
+		    endcase
+		 end
+               default:
+		 begin
+		    ctrl_stall_r = 1'b1;
+		 end
+             endcase
+	  end
+	else if (data_status_zlp_w)
+          set_with_data_r = 1'b0;
+     end
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       begin
+	  device_addr_q   <= 7'b0;
+	  addressed_q     <= 1'b0;
+	  configured_q    <= 1'b0;
+	  set_with_data_q <= 1'b0;
+	  rx_break_q      <= 1'b0;
+       end
+     else if (usb_reset_w)
+       begin
+	  device_addr_q   <= 7'b0;
+	  addressed_q     <= 1'b0;
+	  configured_q    <= 1'b0;
+	  set_with_data_q <= 1'b0;
+	  rx_break_q      <= 1'b0;
+       end
+     else
+       begin
+	  device_addr_q   <= device_addr_r;
+	  addressed_q     <= addressed_r;
+	  configured_q    <= configured_r;
+	  set_with_data_q <= set_with_data_r;
+	  rx_break_q      <= rx_break_r;
+       end
+
+   //-----------------------------------------------------------------
+   // SETUP response
+   //-----------------------------------------------------------------
+   reg        ctrl_sending_q;
+   reg [15:0] ctrl_send_idx_q;
+   reg [15:0] ctrl_send_len_q;
+   wire       ctrl_send_zlp_w = ctrl_sending_q && (ctrl_send_len_q != wLength);
+
+   reg        ctrl_sending_r;
+   reg [15:0] ctrl_send_idx_r;
+   reg [15:0] ctrl_send_len_r;
+
+   reg        ctrl_txvalid_q;
+   reg [7:0]  ctrl_txdata_q;
+   reg        ctrl_txstrb_q;
+   reg        ctrl_txlast_q;
+   reg        ctrl_txstall_q;
+
+   reg        ctrl_txvalid_r;
+   reg [7:0]  ctrl_txdata_r;
+   reg        ctrl_txstrb_r;
+   reg        ctrl_txlast_r;
+   reg        ctrl_txstall_r;
+
+   wire       ctrl_send_accept_w = usb_ep[0].u.tx_data_accept || !usb_ep[0].d.tx_data_valid;
+
+   reg [7:0]  desc_addr_q;
+   wire [7:0] desc_data_w;
+
+   always @ *
+     begin
+	ctrl_sending_r  = ctrl_sending_q;
+	ctrl_send_idx_r = ctrl_send_idx_q;
+	ctrl_send_len_r = ctrl_send_len_q;
+
+	ctrl_txvalid_r  = ctrl_txvalid_q;
+	ctrl_txdata_r   = ctrl_txdata_q;
+	ctrl_txstrb_r   = ctrl_txstrb_q;
+	ctrl_txlast_r   = ctrl_txlast_q;
+	ctrl_txstall_r  = ctrl_txstall_q;
+
+	// New SETUP request
+	if (setup_valid_q)
+	  begin
+             // Send STALL
+             if (ctrl_stall_r)
+               begin
+		  ctrl_txvalid_r  = 1'b1;
+		  ctrl_txstrb_r   = 1'b0;
+		  ctrl_txlast_r   = 1'b1;
+		  ctrl_txstall_r  = 1'b1;
+               end
+             // Send STATUS response (ZLP)
+             else if (ctrl_ack_r)
+               begin
+		  ctrl_txvalid_r  = 1'b1;
+		  ctrl_txstrb_r   = 1'b0;
+		  ctrl_txlast_r   = 1'b1;
+		  ctrl_txstall_r  = 1'b0;
+               end
+             else
+               begin
+		  ctrl_sending_r  = setup_get_w && !ctrl_stall_r;
+		  ctrl_send_idx_r = 16'b0;
+		  ctrl_send_len_r = ctrl_get_len_r;
+		  ctrl_txstall_r  = 1'b0;
+               end
+	  end
+	// Abort control send when STATUS received
+	else if (status_ready_q)
+	  begin
+             ctrl_sending_r  = 1'b0;
+             ctrl_send_idx_r = 16'b0;
+             ctrl_send_len_r = 16'b0;
+
+             ctrl_txvalid_r  = 1'b0;
+	  end
+	// Send STATUS response (ZLP)
+	else if (set_with_data_q && setup_data_q)
+	  begin
+             ctrl_txvalid_r  = 1'b1;
+             ctrl_txstrb_r   = 1'b0;
+             ctrl_txlast_r   = 1'b1;
+             ctrl_txstall_r  = 1'b0;
+	  end
+	else if (ctrl_sending_r && ctrl_send_accept_w)
+	  begin
+             // TODO: Send ZLP on exact multiple lengths...
+             ctrl_txvalid_r  = 1'b1;
+             ctrl_txdata_r   = desc_data_w;
+             ctrl_txstrb_r   = 1'b1;
+             ctrl_txlast_r   = usb_hs_w ? (ctrl_send_idx_r[5:0] == 6'b111111) : (ctrl_send_idx_r[2:0] == 3'b111);
+
+             // Increment send index
+             ctrl_send_idx_r = ctrl_send_idx_r + 16'd1;
+
+             // TODO: Detect need for ZLP
+             if (ctrl_send_idx_r == wLength)
+               begin
+		  ctrl_sending_r = 1'b0;
+		  ctrl_txlast_r  = 1'b1;
+               end
+	  end
+	else if (ctrl_send_accept_w)
+          ctrl_txvalid_r  = 1'b0;
+     end
+
+   assign data_status_zlp_w = set_with_data_q && setup_data_q && ctrl_send_accept_w;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       begin
+	  ctrl_sending_q  <= 1'b0;
+	  ctrl_send_idx_q <= 16'b0;
+	  ctrl_send_len_q <= 16'b0;
+	  ctrl_txvalid_q  <= 1'b0;
+	  ctrl_txdata_q   <= 8'b0;
+	  ctrl_txstrb_q   <= 1'b0;
+	  ctrl_txlast_q   <= 1'b0;
+	  ctrl_txstall_q  <= 1'b0;
+	  desc_addr_q     <= 8'b0;
+       end
+     else if (usb_reset_w)
+       begin
+	  ctrl_sending_q  <= 1'b0;
+	  ctrl_send_idx_q <= 16'b0;
+	  ctrl_send_len_q <= 16'b0;
+	  ctrl_txvalid_q  <= 1'b0;
+	  ctrl_txdata_q   <= 8'b0;
+	  ctrl_txstrb_q   <= 1'b0;
+	  ctrl_txlast_q   <= 1'b0;
+	  ctrl_txstall_q  <= 1'b0;
+	  desc_addr_q     <= 8'b0;
+       end
+     else
+       begin
+	  ctrl_sending_q  <= ctrl_sending_r;
+	  ctrl_send_idx_q <= ctrl_send_idx_r;
+	  ctrl_send_len_q <= ctrl_send_len_r;
+	  ctrl_txvalid_q  <= ctrl_txvalid_r;
+	  ctrl_txdata_q   <= ctrl_txdata_r;
+	  ctrl_txstrb_q   <= ctrl_txstrb_r;
+	  ctrl_txlast_q   <= ctrl_txlast_r;
+	  ctrl_txstall_q  <= ctrl_txstall_r;
+
+	  if (setup_valid_q)
+            desc_addr_q     <= desc_addr_r;
+	  else if (ctrl_sending_r && ctrl_send_accept_w)
+            desc_addr_q     <= desc_addr_q + 8'd1;
+       end
+
+   assign usb_ep[0].d.tx_ready      = ctrl_txvalid_q;
+   assign usb_ep[0].d.tx_data_valid = ctrl_txvalid_q;
+   assign usb_ep[0].d.tx_data_strb  = ctrl_txstrb_q;
+   assign usb_ep[0].d.tx_data       = ctrl_txdata_q;
+   assign usb_ep[0].d.tx_data_last  = ctrl_txlast_q;
+   assign usb_ep[0].d.ep_stall      = ctrl_txstall_q;
+
+   //-----------------------------------------------------------------
+   // Descriptor ROM
+   //-----------------------------------------------------------------
+   usb_desc_rom
+     u_rom
+       (
+	.hs_i(usb_hs_w),
+	.addr_i(desc_addr_q),
+	.data_o(desc_data_w)
+	);
+
+   //-----------------------------------------------------------------
+   // Unused Endpoint Downstream Signals
+   //-----------------------------------------------------------------
+
+   assign usb_ep[0].d.ep_iso        = 1'b0;
+   assign usb_ep[0].d.cfg_int_rx    = 1'b0;
+   assign usb_ep[0].d.cfg_int_tx    = 1'b0;
+
+   // EP1: data input
+   assign usb_ep[1].d.ep_iso        = 1'b0;
+   assign usb_ep[1].d.cfg_int_rx    = 1'b0;
+   assign usb_ep[1].d.cfg_int_tx    = 1'b0;
+   assign usb_ep[1].d.ep_stall      = 1'b0;
+   assign usb_ep[1].d.tx_ready      = 1'b0;
+   assign usb_ep[1].d.tx_data_valid = 1'b0;
+   assign usb_ep[1].d.tx_data_strb  = 1'b0;
+   assign usb_ep[1].d.tx_data       = 8'bx;
+   assign usb_ep[1].d.tx_data_last  = 1'b0;
+
+   // EP2: data output
+   assign usb_ep[2].d.ep_iso        = 1'b0;
+   assign usb_ep[2].d.cfg_int_rx    = 1'b0;
+   assign usb_ep[2].d.cfg_int_tx    = 1'b0;
+   assign usb_ep[2].d.ep_stall      = 1'b0;
+   assign usb_ep[2].d.rx_space      = 1'b0;
+
+   // EP3: notification output
+   assign usb_ep[3].d.ep_iso        = 1'b0;
+   assign usb_ep[3].d.cfg_int_rx    = 1'b0;
+   assign usb_ep[3].d.cfg_int_tx    = 1'b0;
+   assign usb_ep[3].d.ep_stall      = 1'b0;
+   assign usb_ep[3].d.tx_ready      = 1'b0;
+   assign usb_ep[3].d.tx_data_valid = 1'b0;
+   assign usb_ep[3].d.tx_data_strb  = 1'b0;
+   assign usb_ep[3].d.tx_data       = 8'bx;
+   assign usb_ep[3].d.tx_data_last  = 1'b0;
+   assign usb_ep[3].d.rx_space      = 1'b0;
+   
+   //-----------------------------------------------------------------
+   // Stream I/O
+   //-----------------------------------------------------------------
+   reg        inport_valid_q;
+   reg [7:0]  inport_data_q;
+   reg [10:0] inport_cnt_q;
+   reg 	      outport_break_q;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       begin
+	  inport_valid_q  <= 1'b0;
+	  inport_data_q   <= 8'b0;
+       end
+     else if (inport_accept_o)
+       begin
+	  inport_valid_q <= inport_valid_i;
+	  inport_data_q  <= inport_data_i;
+       end
+
+   wire [10:0] max_packet_w   = usb_hs_w ? 11'd511 : 11'd63;
+   wire        inport_last_w  = !inport_valid_i || (inport_cnt_q == max_packet_w);
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       inport_cnt_q  <= 11'b0;
+     else if (inport_last_w && usb_ep[2].u.tx_data_accept)
+       inport_cnt_q  <= 11'b0;
+     else if (inport_valid_q && usb_ep[2].u.tx_data_accept)
+       inport_cnt_q  <= inport_cnt_q + 11'd1;
+
+   assign usb_ep[2].d.tx_data_valid = inport_valid_q;
+   assign usb_ep[2].d.tx_ready      = inport_valid_q;
+   assign usb_ep[2].d.tx_data_strb  = inport_valid_q;
+   assign usb_ep[2].d.tx_data       = inport_data_q;
+   assign usb_ep[2].d.tx_data_last  = inport_last_w;
+
+   assign inport_accept_o     = !inport_valid_q | usb_ep[2].u.tx_data_accept;
+
+   assign outport_valid_o     = usb_ep[1].u.rx_valid && usb_ep[1].uc.rx_strb;
+   assign outport_data_o      = usb_ep[1].uc.rx_data;
+   assign usb_ep[1].d.rx_space      = outport_accept_i;
+
+   always @(posedge clk_i or posedge rst_i)
+     if (rst_i)
+       outport_break_q <= 1'b0;
+     else
+       outport_break_q <= rx_break_q |
+			  (outport_break_q &
+			   ~setup_set_w &
+			   ~outport_valid_o &
+			   ~(inport_valid_q & usb_ep[2].u.tx_data_accept));
+
+   assign outport_break_o  = outport_break_q;
+
+endmodule

+ 0 - 1141
fpga/usb/usb_serial/src_v/usb_cdc_core.v

@@ -1,1141 +0,0 @@
-//-----------------------------------------------------------------
-//                       USB Serial Port
-//                            V0.1
-//                     Ultra-Embedded.com
-//                       Copyright 2020
-//
-//                 Email: admin@ultra-embedded.com
-//
-//                         License: LGPL
-//-----------------------------------------------------------------
-//
-// This source file may be used and distributed without
-// restriction provided that this copyright statement is not
-// removed from the file and that any derivative work contains
-// the original copyright notice and the associated disclaimer.
-//
-// This source file 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 2.1 of the License, or (at your option) any
-// later version.
-//
-// This source 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 source; if not, write to the
-// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
-// Boston, MA  02111-1307  USA
-//-----------------------------------------------------------------
-
-//-----------------------------------------------------------------
-//                          Generated File
-//-----------------------------------------------------------------
-
-module usb_cdc_core
-(
-    // Inputs
-     input           clk_i
-    ,input           rst_i
-    ,input           enable_i
-    ,input  [  7:0]  utmi_data_in_i
-    ,input           utmi_txready_i
-    ,input           utmi_rxvalid_i
-    ,input           utmi_rxactive_i
-    ,input           utmi_rxerror_i
-    ,input  [  1:0]  utmi_linestate_i
-    ,input           inport_valid_i
-    ,input  [  7:0]  inport_data_i
-    ,input           outport_accept_i
-
-    // Outputs
-    ,output [  7:0]  utmi_data_out_o
-    ,output          utmi_txvalid_o
-    ,output [  1:0]  utmi_op_mode_o
-    ,output [  1:0]  utmi_xcvrselect_o
-    ,output          utmi_termselect_o
-    ,output          utmi_dppulldown_o
-    ,output          utmi_dmpulldown_o
-    ,output          inport_accept_o
-    ,output          outport_valid_o
-    ,output [  7:0]  outport_data_o
-    ,output          outport_break_o
-);
-
-
-
-
-parameter USB_SPEED_HS = "False"; // True or False
-
-//-----------------------------------------------------------------
-// Defines
-//-----------------------------------------------------------------
-// Device class
-`define DEV_CLASS_RESERVED              8'h00
-`define DEV_CLASS_AUDIO                 8'h01
-`define DEV_CLASS_COMMS                 8'h02
-`define DEV_CLASS_HID                   8'h03
-`define DEV_CLASS_MONITOR               8'h04
-`define DEV_CLASS_PHY_IF                8'h05
-`define DEV_CLASS_POWER                 8'h06
-`define DEV_CLASS_PRINTER               8'h07
-`define DEV_CLASS_STORAGE               8'h08
-`define DEV_CLASS_HUB                   8'h09
-`define DEV_CLASS_TMC                   8'hFE
-`define DEV_CLASS_VENDOR_CUSTOM         8'hFF
-
-// Standard requests (via SETUP packets)
-`define REQ_GET_STATUS                  8'h00
-`define REQ_CLEAR_FEATURE               8'h01
-`define REQ_SET_FEATURE                 8'h03
-`define REQ_SET_ADDRESS                 8'h05
-`define REQ_GET_DESCRIPTOR              8'h06
-`define REQ_SET_DESCRIPTOR              8'h07
-`define REQ_GET_CONFIGURATION           8'h08
-`define REQ_SET_CONFIGURATION           8'h09
-`define REQ_GET_INTERFACE               8'h0A
-`define REQ_SET_INTERFACE               8'h0B
-`define REQ_SYNC_FRAME                  8'h0C
-
-// Descriptor types
-`define DESC_DEVICE                     8'h01
-`define DESC_CONFIGURATION              8'h02
-`define DESC_STRING                     8'h03
-`define DESC_INTERFACE                  8'h04
-`define DESC_ENDPOINT                   8'h05
-`define DESC_DEV_QUALIFIER              8'h06
-`define DESC_OTHER_SPEED_CONF           8'h07
-`define DESC_IF_POWER                   8'h08
-
-// Endpoints
-`define ENDPOINT_DIR_MASK               8'h80
-`define ENDPOINT_DIR_R                  7
-`define ENDPOINT_DIR_IN                 1'b1
-`define ENDPOINT_DIR_OUT                1'b0
-`define ENDPOINT_ADDR_MASK              8'h7F
-`define ENDPOINT_TYPE_MASK              8'h3
-`define ENDPOINT_TYPE_CONTROL           0
-`define ENDPOINT_TYPE_ISO               1
-`define ENDPOINT_TYPE_BULK              2
-`define ENDPOINT_TYPE_INTERRUPT         3
-
-// Device Requests (bmRequestType)
-`define USB_RECIPIENT_MASK              8'h1F
-`define USB_RECIPIENT_DEVICE            8'h00
-`define USB_RECIPIENT_INTERFACE         8'h01
-`define USB_RECIPIENT_ENDPOINT          8'h02
-`define USB_REQUEST_TYPE_MASK           8'h60
-`define USB_STANDARD_REQUEST            8'h00
-`define USB_CLASS_REQUEST               8'h20
-`define USB_VENDOR_REQUEST              8'h40
-
-// USB device addresses are 7-bits
-`define USB_ADDRESS_MASK                8'h7F
-
-// USB Feature Selectors
-`define USB_FEATURE_ENDPOINT_STATE      16'h0000
-`define USB_FEATURE_REMOTE_WAKEUP       16'h0001
-`define USB_FEATURE_TEST_MODE           16'h0002
-
-// String Descriptors
-`define UNICODE_LANGUAGE_STR_ID         8'd0
-`define MANUFACTURER_STR_ID             8'd1
-`define PRODUCT_NAME_STR_ID             8'd2
-`define SERIAL_NUM_STR_ID               8'd3
-
-`define CDC_ENDPOINT_BULK_OUT           1
-`define CDC_ENDPOINT_BULK_IN            2
-`define CDC_ENDPOINT_INTR_IN            3
-
-`define CDC_SEND_ENCAPSULATED_COMMAND   8'h00
-`define CDC_GET_ENCAPSULATED_RESPONSE   8'h01
-`define CDC_GET_LINE_CODING             8'h21
-`define CDC_SET_LINE_CODING             8'h20
-`define CDC_SET_CONTROL_LINE_STATE      8'h22
-`define CDC_SEND_BREAK                  8'h23
-
-// Descriptor ROM offsets / sizes
-`define ROM_DESC_DEVICE_ADDR            8'd0
-`define ROM_DESC_DEVICE_SIZE            16'd18
-`define ROM_DESC_CONF_ADDR              8'd18
-`define ROM_DESC_CONF_SIZE              16'd67
-`define ROM_DESC_STR_LANG_ADDR          8'd85
-`define ROM_DESC_STR_LANG_SIZE          16'd4
-`define ROM_DESC_STR_MAN_ADDR           8'd89
-`define ROM_DESC_STR_MAN_SIZE           16'd30
-`define ROM_DESC_STR_PROD_ADDR          8'd119
-`define ROM_DESC_STR_PROD_SIZE          16'd30
-`define ROM_DESC_STR_SERIAL_ADDR        8'd149
-`define ROM_DESC_STR_SERIAL_SIZE        16'd14
-`define ROM_CDC_LINE_CODING_ADDR        8'd163
-`define ROM_CDC_LINE_CODING_SIZE        16'd7
-
-//-----------------------------------------------------------------
-// Wires
-//-----------------------------------------------------------------
-wire         usb_reset_w;
-reg  [6:0]   device_addr_q;
-
-wire         usb_ep0_tx_rd_w;
-wire [7:0]   usb_ep0_tx_data_w;
-wire         usb_ep0_tx_empty_w;
-
-wire         usb_ep0_rx_wr_w;
-wire [7:0]   usb_ep0_rx_data_w;
-wire         usb_ep0_rx_full_w;
-wire         usb_ep1_tx_rd_w;
-wire [7:0]   usb_ep1_tx_data_w;
-wire         usb_ep1_tx_empty_w;
-
-wire         usb_ep1_rx_wr_w;
-wire [7:0]   usb_ep1_rx_data_w;
-wire         usb_ep1_rx_full_w;
-wire         usb_ep2_tx_rd_w;
-wire [7:0]   usb_ep2_tx_data_w;
-wire         usb_ep2_tx_empty_w;
-
-wire         usb_ep2_rx_wr_w;
-wire [7:0]   usb_ep2_rx_data_w;
-wire         usb_ep2_rx_full_w;
-wire         usb_ep3_tx_rd_w;
-wire [7:0]   usb_ep3_tx_data_w;
-wire         usb_ep3_tx_empty_w;
-
-wire         usb_ep3_rx_wr_w;
-wire [7:0]   usb_ep3_rx_data_w;
-wire         usb_ep3_rx_full_w;
-
-// Rx SIE Interface (shared)
-wire        rx_strb_w;
-wire [7:0]  rx_data_w;
-wire        rx_last_w;
-wire        rx_crc_err_w;
-
-// EP0 Rx SIE Interface
-wire        ep0_rx_space_w;
-wire        ep0_rx_valid_w;
-wire        ep0_rx_setup_w;
-
-// EP0 Tx SIE Interface
-wire        ep0_tx_ready_w;
-wire        ep0_tx_data_valid_w;
-wire        ep0_tx_data_strb_w;
-wire [7:0]  ep0_tx_data_w;
-wire        ep0_tx_data_last_w;
-wire        ep0_tx_data_accept_w;
-wire        ep0_tx_stall_w;
-// EP1 Rx SIE Interface
-wire        ep1_rx_space_w;
-wire        ep1_rx_valid_w;
-wire        ep1_rx_setup_w;
-
-// EP1 Tx SIE Interface
-wire        ep1_tx_ready_w;
-wire        ep1_tx_data_valid_w;
-wire        ep1_tx_data_strb_w;
-wire [7:0]  ep1_tx_data_w;
-wire        ep1_tx_data_last_w;
-wire        ep1_tx_data_accept_w;
-wire        ep1_tx_stall_w;
-// EP2 Rx SIE Interface
-wire        ep2_rx_space_w;
-wire        ep2_rx_valid_w;
-wire        ep2_rx_setup_w;
-
-// EP2 Tx SIE Interface
-wire        ep2_tx_ready_w;
-wire        ep2_tx_data_valid_w;
-wire        ep2_tx_data_strb_w;
-wire [7:0]  ep2_tx_data_w;
-wire        ep2_tx_data_last_w;
-wire        ep2_tx_data_accept_w;
-wire        ep2_tx_stall_w;
-// EP3 Rx SIE Interface
-wire        ep3_rx_space_w;
-wire        ep3_rx_valid_w;
-wire        ep3_rx_setup_w;
-
-// EP3 Tx SIE Interface
-wire        ep3_tx_ready_w;
-wire        ep3_tx_data_valid_w;
-wire        ep3_tx_data_strb_w;
-wire [7:0]  ep3_tx_data_w;
-wire        ep3_tx_data_last_w;
-wire        ep3_tx_data_accept_w;
-wire        ep3_tx_stall_w;
-
-wire utmi_chirp_en_w;
-wire usb_hs_w;
-
-//-----------------------------------------------------------------
-// Transceiver Control (high speed)
-//-----------------------------------------------------------------
-generate
-if (USB_SPEED_HS == "True")
-begin
-
-localparam STATE_W                       = 3;
-localparam STATE_IDLE                    = 3'd0;
-localparam STATE_WAIT_RST                = 3'd1;
-localparam STATE_SEND_CHIRP_K            = 3'd2;
-localparam STATE_WAIT_CHIRP_JK           = 3'd3;
-localparam STATE_FULLSPEED               = 3'd4;
-localparam STATE_HIGHSPEED               = 3'd5;
-reg [STATE_W-1:0] state_q;
-reg [STATE_W-1:0] next_state_r;
-
-// 60MHz clock rate
-`define USB_RST_W  20
-reg [`USB_RST_W-1:0] usb_rst_time_q;
-reg [7:0]            chirp_count_q;
-reg [1:0]            last_linestate_q;
-
-localparam DETACH_TIME    = 20'd60000;  // 1ms -> T0
-localparam ATTACH_FS_TIME = 20'd180000; // T0 + 3ms = T1
-localparam CHIRPK_TIME    = 20'd246000; // T1 + ~1ms
-localparam HS_RESET_TIME  = 20'd600000; // T0 + 10ms = T9
-localparam HS_CHIRP_COUNT = 8'd5;
-
-reg [  1:0]  utmi_op_mode_r;
-reg [  1:0]  utmi_xcvrselect_r;
-reg          utmi_termselect_r;
-reg          utmi_dppulldown_r;
-reg          utmi_dmpulldown_r;
-
-always @ *
-begin
-    next_state_r = state_q;
-
-    // Default - disconnect
-    utmi_op_mode_r    = 2'd1;
-    utmi_xcvrselect_r = 2'd0;
-    utmi_termselect_r = 1'b0;
-    utmi_dppulldown_r = 1'b0;
-    utmi_dmpulldown_r = 1'b0;
-
-    case (state_q)
-    STATE_IDLE:
-    begin
-        // Detached
-        if (enable_i && usb_rst_time_q >= DETACH_TIME)
-            next_state_r = STATE_WAIT_RST;
-    end
-    STATE_WAIT_RST:
-    begin
-        // Assert FS mode, check for SE0 (T0)
-        utmi_op_mode_r    = 2'd0;
-        utmi_xcvrselect_r = 2'd1;
-        utmi_termselect_r = 1'b1;
-        utmi_dppulldown_r = 1'b0;
-        utmi_dmpulldown_r = 1'b0;
-
-        // Wait for SE0 (T1), send device chirp K
-        if (usb_rst_time_q >= ATTACH_FS_TIME)
-            next_state_r = STATE_SEND_CHIRP_K;
-    end
-    STATE_SEND_CHIRP_K:
-    begin
-        // Send chirp K
-        utmi_op_mode_r    = 2'd2;
-        utmi_xcvrselect_r = 2'd0;
-        utmi_termselect_r = 1'b1;
-        utmi_dppulldown_r = 1'b0;
-        utmi_dmpulldown_r = 1'b0;
-
-        // End of device chirp K (T2)
-        if (usb_rst_time_q >= CHIRPK_TIME)
-            next_state_r = STATE_WAIT_CHIRP_JK;
-    end
-    STATE_WAIT_CHIRP_JK:
-    begin
-        // Stop sending chirp K and wait for downstream port chirps
-        utmi_op_mode_r    = 2'd2;
-        utmi_xcvrselect_r = 2'd0;
-        utmi_termselect_r = 1'b1;
-        utmi_dppulldown_r = 1'b0;
-        utmi_dmpulldown_r = 1'b0;
-
-        // Required number of chirps detected, move to HS mode (T7)
-        if (chirp_count_q >= HS_CHIRP_COUNT)
-            next_state_r = STATE_HIGHSPEED;
-        // Time out waiting for chirps, fallback to FS mode
-        else if (usb_rst_time_q >= HS_RESET_TIME)
-            next_state_r = STATE_FULLSPEED;
-    end
-    STATE_FULLSPEED:
-    begin
-        utmi_op_mode_r    = 2'd0;
-        utmi_xcvrselect_r = 2'd1;
-        utmi_termselect_r = 1'b1;
-        utmi_dppulldown_r = 1'b0;
-        utmi_dmpulldown_r = 1'b0;
-
-        // USB reset detected...
-        if (usb_rst_time_q >= HS_RESET_TIME && usb_reset_w)
-            next_state_r = STATE_WAIT_RST;
-    end
-    STATE_HIGHSPEED:
-    begin
-        // Enter HS mode
-        utmi_op_mode_r    = 2'd0;
-        utmi_xcvrselect_r = 2'd0;
-        utmi_termselect_r = 1'b0;
-        utmi_dppulldown_r = 1'b0;
-        utmi_dmpulldown_r = 1'b0;
-
-        // Long SE0 - could be reset or suspend
-        // TODO: Should revert to FS mode and check...
-        if (usb_rst_time_q >= HS_RESET_TIME && usb_reset_w)
-            next_state_r = STATE_WAIT_RST;
-    end
-    default:
-        ;
-    endcase
-end
-
-// Update state
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    state_q   <= STATE_IDLE;
-else
-    state_q   <= next_state_r;
-
-// Time since T0 (start of HS reset)
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    usb_rst_time_q <= `USB_RST_W'b0;
-// Entering wait for reset state
-else if (next_state_r == STATE_WAIT_RST && state_q != STATE_WAIT_RST)
-    usb_rst_time_q <=  `USB_RST_W'b0;
-// Waiting for reset, reset count on line state toggle
-else if (state_q == STATE_WAIT_RST && (utmi_linestate_i != 2'b00))
-    usb_rst_time_q <=  `USB_RST_W'b0;
-else if (usb_rst_time_q != {(`USB_RST_W){1'b1}})
-    usb_rst_time_q <= usb_rst_time_q + `USB_RST_W'd1;
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    last_linestate_q   <= 2'b0;
-else
-    last_linestate_q   <= utmi_linestate_i;
-
-// Chirp counter
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    chirp_count_q   <= 8'b0;
-else if (state_q == STATE_SEND_CHIRP_K)
-    chirp_count_q   <= 8'b0;
-else if (state_q == STATE_WAIT_CHIRP_JK && (last_linestate_q != utmi_linestate_i) && chirp_count_q != 8'hFF)
-    chirp_count_q   <= chirp_count_q + 8'd1;
-
-assign utmi_op_mode_o    = utmi_op_mode_r;
-assign utmi_xcvrselect_o = utmi_xcvrselect_r;
-assign utmi_termselect_o = utmi_termselect_r;
-assign utmi_dppulldown_o = utmi_dppulldown_r;
-assign utmi_dmpulldown_o = utmi_dmpulldown_r;
-
-assign utmi_chirp_en_w   = (state_q == STATE_SEND_CHIRP_K);
-assign usb_hs_w          = (state_q == STATE_HIGHSPEED);
-
-end
-else
-begin
-//-----------------------------------------------------------------
-// Transceiver Control
-//-----------------------------------------------------------------
-reg [  1:0]  utmi_op_mode_r;
-reg [  1:0]  utmi_xcvrselect_r;
-reg          utmi_termselect_r;
-reg          utmi_dppulldown_r;
-reg          utmi_dmpulldown_r;
-
-always @ *
-begin
-    if (enable_i)
-    begin
-        utmi_op_mode_r    = 2'd0;
-        utmi_xcvrselect_r = 2'd1;
-        utmi_termselect_r = 1'b1;
-        utmi_dppulldown_r = 1'b0;
-        utmi_dmpulldown_r = 1'b0;
-    end
-    else
-    begin
-        utmi_op_mode_r    = 2'd1;
-        utmi_xcvrselect_r = 2'd0;
-        utmi_termselect_r = 1'b0;
-        utmi_dppulldown_r = 1'b0;
-        utmi_dmpulldown_r = 1'b0;
-    end
-end
-
-assign utmi_op_mode_o    = utmi_op_mode_r;
-assign utmi_xcvrselect_o = utmi_xcvrselect_r;
-assign utmi_termselect_o = utmi_termselect_r;
-assign utmi_dppulldown_o = utmi_dppulldown_r;
-assign utmi_dmpulldown_o = utmi_dmpulldown_r;
-
-assign utmi_chirp_en_w   = 1'b0;
-assign usb_hs_w          = 1'b0;
-
-end
-endgenerate
-
-//-----------------------------------------------------------------
-// Core
-//-----------------------------------------------------------------
-usbf_device_core
-u_core
-(
-    .clk_i(clk_i),
-    .rst_i(rst_i),
-
-    .intr_o(),
-
-    // UTMI interface
-    .utmi_data_o(utmi_data_out_o),
-    .utmi_data_i(utmi_data_in_i),
-    .utmi_txvalid_o(utmi_txvalid_o),
-    .utmi_txready_i(utmi_txready_i),
-    .utmi_rxvalid_i(utmi_rxvalid_i),
-    .utmi_rxactive_i(utmi_rxactive_i),
-    .utmi_rxerror_i(utmi_rxerror_i),
-    .utmi_linestate_i(utmi_linestate_i),
-
-    .reg_chirp_en_i(utmi_chirp_en_w),
-    .reg_int_en_sof_i(1'b0),
-
-    .reg_dev_addr_i(device_addr_q),
-
-    // Rx SIE Interface (shared)
-    .rx_strb_o(rx_strb_w),
-    .rx_data_o(rx_data_w),
-    .rx_last_o(rx_last_w),
-    .rx_crc_err_o(rx_crc_err_w),
-
-    // EP0 Config
-    .ep0_iso_i(1'b0),
-    .ep0_stall_i(ep0_tx_stall_w),
-    .ep0_cfg_int_rx_i(1'b0),
-    .ep0_cfg_int_tx_i(1'b0),
-
-    // EP0 Rx SIE Interface
-    .ep0_rx_setup_o(ep0_rx_setup_w),
-    .ep0_rx_valid_o(ep0_rx_valid_w),
-    .ep0_rx_space_i(ep0_rx_space_w),
-
-    // EP0 Tx SIE Interface
-    .ep0_tx_ready_i(ep0_tx_ready_w),
-    .ep0_tx_data_valid_i(ep0_tx_data_valid_w),
-    .ep0_tx_data_strb_i(ep0_tx_data_strb_w),
-    .ep0_tx_data_i(ep0_tx_data_w),
-    .ep0_tx_data_last_i(ep0_tx_data_last_w),
-    .ep0_tx_data_accept_o(ep0_tx_data_accept_w),
-
-    // EP1 Config
-    .ep1_iso_i(1'b0),
-    .ep1_stall_i(ep1_tx_stall_w),
-    .ep1_cfg_int_rx_i(1'b0),
-    .ep1_cfg_int_tx_i(1'b0),
-
-    // EP1 Rx SIE Interface
-    .ep1_rx_setup_o(ep1_rx_setup_w),
-    .ep1_rx_valid_o(ep1_rx_valid_w),
-    .ep1_rx_space_i(ep1_rx_space_w),
-
-    // EP1 Tx SIE Interface
-    .ep1_tx_ready_i(ep1_tx_ready_w),
-    .ep1_tx_data_valid_i(ep1_tx_data_valid_w),
-    .ep1_tx_data_strb_i(ep1_tx_data_strb_w),
-    .ep1_tx_data_i(ep1_tx_data_w),
-    .ep1_tx_data_last_i(ep1_tx_data_last_w),
-    .ep1_tx_data_accept_o(ep1_tx_data_accept_w),
-
-    // EP2 Config
-    .ep2_iso_i(1'b0),
-    .ep2_stall_i(ep2_tx_stall_w),
-    .ep2_cfg_int_rx_i(1'b0),
-    .ep2_cfg_int_tx_i(1'b0),
-
-    // EP2 Rx SIE Interface
-    .ep2_rx_setup_o(ep2_rx_setup_w),
-    .ep2_rx_valid_o(ep2_rx_valid_w),
-    .ep2_rx_space_i(ep2_rx_space_w),
-
-    // EP2 Tx SIE Interface
-    .ep2_tx_ready_i(ep2_tx_ready_w),
-    .ep2_tx_data_valid_i(ep2_tx_data_valid_w),
-    .ep2_tx_data_strb_i(ep2_tx_data_strb_w),
-    .ep2_tx_data_i(ep2_tx_data_w),
-    .ep2_tx_data_last_i(ep2_tx_data_last_w),
-    .ep2_tx_data_accept_o(ep2_tx_data_accept_w),
-
-    // EP3 Config
-    .ep3_iso_i(1'b0),
-    .ep3_stall_i(ep3_tx_stall_w),
-    .ep3_cfg_int_rx_i(1'b0),
-    .ep3_cfg_int_tx_i(1'b0),
-
-    // EP3 Rx SIE Interface
-    .ep3_rx_setup_o(ep3_rx_setup_w),
-    .ep3_rx_valid_o(ep3_rx_valid_w),
-    .ep3_rx_space_i(ep3_rx_space_w),
-
-    // EP3 Tx SIE Interface
-    .ep3_tx_ready_i(ep3_tx_ready_w),
-    .ep3_tx_data_valid_i(ep3_tx_data_valid_w),
-    .ep3_tx_data_strb_i(ep3_tx_data_strb_w),
-    .ep3_tx_data_i(ep3_tx_data_w),
-    .ep3_tx_data_last_i(ep3_tx_data_last_w),
-    .ep3_tx_data_accept_o(ep3_tx_data_accept_w),
-
-    // Status
-    .reg_sts_rst_clr_i(1'b1),
-    .reg_sts_rst_o(usb_reset_w),
-    .reg_sts_frame_num_o()
-);
-
-assign ep0_rx_space_w = 1'b1;
-
-//-----------------------------------------------------------------
-// USB: Setup packet capture (limited to 8 bytes for USB-FS)
-//-----------------------------------------------------------------
-reg [7:0] setup_packet_q[0:7];
-reg [2:0] setup_wr_idx_q;
-reg       setup_frame_q;
-reg       setup_valid_q;
-reg       setup_data_q;
-reg       status_ready_q; // STATUS response received
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-begin
-    setup_packet_q[0]  <= 8'b0;
-    setup_packet_q[1]  <= 8'b0;
-    setup_packet_q[2]  <= 8'b0;
-    setup_packet_q[3]  <= 8'b0;
-    setup_packet_q[4]  <= 8'b0;
-    setup_packet_q[5]  <= 8'b0;
-    setup_packet_q[6]  <= 8'b0;
-    setup_packet_q[7]  <= 8'b0;
-    setup_wr_idx_q     <= 3'b0;
-    setup_valid_q      <= 1'b0;
-    setup_frame_q      <= 1'b0;
-    setup_data_q       <= 1'b0;
-    status_ready_q     <= 1'b0;
-end
-// SETUP token received
-else if (ep0_rx_setup_w)
-begin
-    setup_packet_q[0]  <= 8'b0;
-    setup_packet_q[1]  <= 8'b0;
-    setup_packet_q[2]  <= 8'b0;
-    setup_packet_q[3]  <= 8'b0;
-    setup_packet_q[4]  <= 8'b0;
-    setup_packet_q[5]  <= 8'b0;
-    setup_packet_q[6]  <= 8'b0;
-    setup_packet_q[7]  <= 8'b0;
-    setup_wr_idx_q     <= 3'b0;
-    setup_valid_q      <= 1'b0;
-    setup_frame_q      <= 1'b1;
-    setup_data_q       <= 1'b0;
-    status_ready_q     <= 1'b0;
-end
-// Valid DATA for setup frame
-else if (ep0_rx_valid_w && rx_strb_w)
-begin
-    setup_packet_q[setup_wr_idx_q] <= rx_data_w;
-    setup_wr_idx_q      <= setup_wr_idx_q + 3'd1;
-    setup_valid_q       <= setup_frame_q && rx_last_w;
-    setup_data_q        <= !setup_frame_q && rx_last_w;
-    if (rx_last_w)
-        setup_frame_q   <= 1'b0;
-end
-// Detect STATUS stage (ACK for SETUP GET requests)
-// TODO: Not quite correct ....
-else if (ep0_rx_valid_w && !rx_strb_w && rx_last_w)
-begin
-    setup_valid_q       <= 1'b0;
-    status_ready_q      <= 1'b1;
-end
-else
-    setup_valid_q       <= 1'b0;
-
-//-----------------------------------------------------------------
-// SETUP request decode
-//-----------------------------------------------------------------
-wire [7:0]  bmRequestType_w = setup_packet_q[0];
-wire [7:0]  bRequest_w      = setup_packet_q[1];
-wire [15:0] wValue_w        = {setup_packet_q[3], setup_packet_q[2]};
-wire [15:0] wIndex_w        = {setup_packet_q[5], setup_packet_q[4]};
-wire [15:0] wLength         = {setup_packet_q[7], setup_packet_q[6]};
-
-wire setup_get_w            = setup_valid_q && (bmRequestType_w[`ENDPOINT_DIR_R] == `ENDPOINT_DIR_IN);
-wire setup_set_w            = setup_valid_q && (bmRequestType_w[`ENDPOINT_DIR_R] == `ENDPOINT_DIR_OUT);
-wire setup_no_data_w        = setup_set_w && (wLength == 16'b0);
-
-// For REQ_GET_DESCRIPTOR
-wire [7:0]  bDescriptorType_w  = setup_packet_q[3];
-wire [7:0]  bDescriptorIndex_w = setup_packet_q[2];
-
-//-----------------------------------------------------------------
-// Process setup request
-//-----------------------------------------------------------------
-reg        ctrl_stall_r; // Send STALL
-reg        ctrl_ack_r;   // Send STATUS (ZLP)
-reg [15:0] ctrl_get_len_r;
-
-reg [7:0]  desc_addr_r;
-
-reg	   rx_break_q;
-reg	   rx_break_r;
-
-reg        addressed_q;
-reg        addressed_r;
-reg [6:0]  device_addr_r;
-
-reg        configured_q;
-reg        configured_r;
-
-reg        set_with_data_q;
-reg        set_with_data_r;
-wire       data_status_zlp_w;
-
-always @ *
-begin
-    ctrl_stall_r    = 1'b0;
-    ctrl_get_len_r  = 16'b0;
-    ctrl_ack_r      = 1'b0;
-    desc_addr_r     = 8'b0;
-    device_addr_r   = device_addr_q;
-    addressed_r     = addressed_q;
-    configured_r    = configured_q;
-    set_with_data_r = set_with_data_q;
-    rx_break_r      = 1'b0;
-
-    if (setup_valid_q)
-    begin
-        set_with_data_r = 1'b0;
-
-        case (bmRequestType_w & `USB_REQUEST_TYPE_MASK)
-        `USB_STANDARD_REQUEST:
-        begin
-            case (bRequest_w)
-            `REQ_GET_STATUS:
-            begin
-                $display("GET_STATUS");
-            end
-            `REQ_CLEAR_FEATURE:
-            begin
-                $display("CLEAR_FEATURE");
-                ctrl_ack_r = setup_set_w && setup_no_data_w;
-            end
-            `REQ_SET_FEATURE:
-            begin
-                $display("SET_FEATURE");
-                ctrl_ack_r = setup_set_w && setup_no_data_w;
-            end
-            `REQ_SET_ADDRESS:
-            begin
-                $display("SET_ADDRESS: Set device address %d", wValue_w[6:0]);
-                ctrl_ack_r    = setup_set_w && setup_no_data_w;
-                device_addr_r = wValue_w[6:0];
-                addressed_r   = 1'b1;
-            end
-            `REQ_GET_DESCRIPTOR:
-            begin
-                $display("GET_DESCRIPTOR: Type %d", bDescriptorType_w);
-
-                case (bDescriptorType_w)
-                `DESC_DEVICE:
-                begin
-                    desc_addr_r    = `ROM_DESC_DEVICE_ADDR;
-                    ctrl_get_len_r = `ROM_DESC_DEVICE_SIZE;
-                end
-                `DESC_CONFIGURATION:
-                begin
-                    desc_addr_r    = `ROM_DESC_CONF_ADDR;
-                    ctrl_get_len_r = `ROM_DESC_CONF_SIZE;
-                end
-                `DESC_STRING:
-                begin
-                    case (bDescriptorIndex_w)
-                    `UNICODE_LANGUAGE_STR_ID:
-                    begin
-                        desc_addr_r    = `ROM_DESC_STR_LANG_ADDR;
-                        ctrl_get_len_r = `ROM_DESC_STR_LANG_SIZE;
-                    end
-                    `MANUFACTURER_STR_ID:
-                    begin
-                        desc_addr_r    = `ROM_DESC_STR_MAN_ADDR;
-                        ctrl_get_len_r = `ROM_DESC_STR_MAN_SIZE;
-                    end
-                    `PRODUCT_NAME_STR_ID:
-                    begin
-                        desc_addr_r    = `ROM_DESC_STR_PROD_ADDR;
-                        ctrl_get_len_r = `ROM_DESC_STR_PROD_SIZE;
-                    end
-                    `SERIAL_NUM_STR_ID:
-                    begin
-                        desc_addr_r    = `ROM_DESC_STR_SERIAL_ADDR;
-                        ctrl_get_len_r = `ROM_DESC_STR_SERIAL_SIZE;
-                    end
-                    default:
-                        ;
-                    endcase
-                end
-                default:
-                    ;
-                endcase
-            end
-            `REQ_GET_CONFIGURATION:
-            begin
-                $display("GET_CONF");
-            end
-            `REQ_SET_CONFIGURATION:
-            begin
-                $display("SET_CONF: Configuration %x", wValue_w);
-
-                if (wValue_w == 16'd0)
-                begin
-                    configured_r = 1'b0;
-                    ctrl_ack_r   = setup_set_w && setup_no_data_w;
-                end
-                // Only support one configuration for now
-                else if (wValue_w == 16'd1)
-                begin
-                    configured_r = 1'b1;
-                    ctrl_ack_r   = setup_set_w && setup_no_data_w;
-                end
-                else
-                    ctrl_stall_r = 1'b1;
-            end
-            `REQ_GET_INTERFACE:
-            begin
-                $display("GET_INTERFACE");
-                ctrl_stall_r = 1'b1;
-            end
-            `REQ_SET_INTERFACE:
-            begin
-                $display("SET_INTERFACE: %x %x", wValue_w, wIndex_w);
-                if (wValue_w == 16'd0 && wIndex_w == 16'd0)
-                    ctrl_ack_r   = setup_set_w && setup_no_data_w;
-                else
-                    ctrl_stall_r = 1'b1;
-            end
-            default:
-            begin
-                ctrl_stall_r = 1'b1;
-            end
-            endcase
-        end
-        `USB_VENDOR_REQUEST:
-        begin
-            // None supported
-            ctrl_stall_r = 1'b1;
-        end
-        `USB_CLASS_REQUEST:
-        begin
-            ctrl_ack_r      = setup_set_w && setup_no_data_w;
-            set_with_data_r = setup_set_w && !setup_no_data_w;
-
-            case (bRequest_w)
-            `CDC_GET_LINE_CODING:
-            begin
-                $display("CDC_GET_LINE_CODING");
-                desc_addr_r    = `ROM_CDC_LINE_CODING_ADDR;
-                ctrl_get_len_r = `ROM_CDC_LINE_CODING_SIZE;
-            end
-	    `CDC_SEND_BREAK:
-	      begin
-		 rx_break_r    = (wValue_w != 16'd0);
-	      end
-            default:
-              begin
-		 // Do nothing
-              end
-            endcase
-        end
-        default:
-        begin
-            ctrl_stall_r = 1'b1;
-        end
-        endcase
-    end
-    else if (data_status_zlp_w)
-        set_with_data_r = 1'b0;
-end
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-begin
-    device_addr_q   <= 7'b0;
-    addressed_q     <= 1'b0;
-    configured_q    <= 1'b0;
-    set_with_data_q <= 1'b0;
-    rx_break_q      <= 1'b0;
-end
-else if (usb_reset_w)
-begin
-    device_addr_q   <= 7'b0;
-    addressed_q     <= 1'b0;
-    configured_q    <= 1'b0;
-    set_with_data_q <= 1'b0;
-    rx_break_q      <= 1'b0;
-end
-else
-begin
-    device_addr_q   <= device_addr_r;
-    addressed_q     <= addressed_r;
-    configured_q    <= configured_r;
-    set_with_data_q <= set_with_data_r;
-    rx_break_q      <= rx_break_r;
-end
-
-//-----------------------------------------------------------------
-// SETUP response
-//-----------------------------------------------------------------
-reg        ctrl_sending_q;
-reg [15:0] ctrl_send_idx_q;
-reg [15:0] ctrl_send_len_q;
-wire       ctrl_send_zlp_w = ctrl_sending_q && (ctrl_send_len_q != wLength);
-
-reg        ctrl_sending_r;
-reg [15:0] ctrl_send_idx_r;
-reg [15:0] ctrl_send_len_r;
-
-reg        ctrl_txvalid_q;
-reg [7:0]  ctrl_txdata_q;
-reg        ctrl_txstrb_q;
-reg        ctrl_txlast_q;
-reg        ctrl_txstall_q;
-
-reg        ctrl_txvalid_r;
-reg [7:0]  ctrl_txdata_r;
-reg        ctrl_txstrb_r;
-reg        ctrl_txlast_r;
-reg        ctrl_txstall_r;
-
-wire       ctrl_send_accept_w = ep0_tx_data_accept_w || !ep0_tx_data_valid_w;
-
-reg [7:0]  desc_addr_q;
-wire[7:0]  desc_data_w;
-
-always @ *
-begin
-    ctrl_sending_r  = ctrl_sending_q;
-    ctrl_send_idx_r = ctrl_send_idx_q;
-    ctrl_send_len_r = ctrl_send_len_q;
-
-    ctrl_txvalid_r  = ctrl_txvalid_q;
-    ctrl_txdata_r   = ctrl_txdata_q;
-    ctrl_txstrb_r   = ctrl_txstrb_q;
-    ctrl_txlast_r   = ctrl_txlast_q;
-    ctrl_txstall_r  = ctrl_txstall_q;
-
-    // New SETUP request
-    if (setup_valid_q)
-    begin
-        // Send STALL
-        if (ctrl_stall_r)
-        begin
-            ctrl_txvalid_r  = 1'b1;
-            ctrl_txstrb_r   = 1'b0;
-            ctrl_txlast_r   = 1'b1;
-            ctrl_txstall_r  = 1'b1;
-        end
-        // Send STATUS response (ZLP)
-        else if (ctrl_ack_r)
-        begin
-            ctrl_txvalid_r  = 1'b1;
-            ctrl_txstrb_r   = 1'b0;
-            ctrl_txlast_r   = 1'b1;
-            ctrl_txstall_r  = 1'b0;
-        end
-        else
-        begin
-            ctrl_sending_r  = setup_get_w && !ctrl_stall_r;
-            ctrl_send_idx_r = 16'b0;
-            ctrl_send_len_r = ctrl_get_len_r;
-            ctrl_txstall_r  = 1'b0;
-        end
-    end
-    // Abort control send when STATUS received
-    else if (status_ready_q)
-    begin
-        ctrl_sending_r  = 1'b0;
-        ctrl_send_idx_r = 16'b0;
-        ctrl_send_len_r = 16'b0;
-
-        ctrl_txvalid_r  = 1'b0;
-    end
-    // Send STATUS response (ZLP)
-    else if (set_with_data_q && setup_data_q)
-    begin
-        ctrl_txvalid_r  = 1'b1;
-        ctrl_txstrb_r   = 1'b0;
-        ctrl_txlast_r   = 1'b1;
-        ctrl_txstall_r  = 1'b0;
-    end
-    else if (ctrl_sending_r && ctrl_send_accept_w)
-    begin
-        // TODO: Send ZLP on exact multiple lengths...
-        ctrl_txvalid_r  = 1'b1;
-        ctrl_txdata_r   = desc_data_w;
-        ctrl_txstrb_r   = 1'b1;
-        ctrl_txlast_r   = usb_hs_w ? (ctrl_send_idx_r[5:0] == 6'b111111) : (ctrl_send_idx_r[2:0] == 3'b111);
-
-        // Increment send index
-        ctrl_send_idx_r = ctrl_send_idx_r + 16'd1;
-
-        // TODO: Detect need for ZLP
-        if (ctrl_send_idx_r == wLength)
-        begin
-            ctrl_sending_r = 1'b0;
-            ctrl_txlast_r  = 1'b1;
-        end
-    end
-    else if (ctrl_send_accept_w)
-        ctrl_txvalid_r  = 1'b0;
-end
-
-assign data_status_zlp_w = set_with_data_q && setup_data_q && ctrl_send_accept_w;
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-begin
-    ctrl_sending_q  <= 1'b0;
-    ctrl_send_idx_q <= 16'b0;
-    ctrl_send_len_q <= 16'b0;
-    ctrl_txvalid_q  <= 1'b0;
-    ctrl_txdata_q   <= 8'b0;
-    ctrl_txstrb_q   <= 1'b0;
-    ctrl_txlast_q   <= 1'b0;
-    ctrl_txstall_q  <= 1'b0;
-    desc_addr_q     <= 8'b0;
-end
-else if (usb_reset_w)
-begin
-    ctrl_sending_q  <= 1'b0;
-    ctrl_send_idx_q <= 16'b0;
-    ctrl_send_len_q <= 16'b0;
-    ctrl_txvalid_q  <= 1'b0;
-    ctrl_txdata_q   <= 8'b0;
-    ctrl_txstrb_q   <= 1'b0;
-    ctrl_txlast_q   <= 1'b0;
-    ctrl_txstall_q  <= 1'b0;
-    desc_addr_q     <= 8'b0;
-end
-else
-begin
-    ctrl_sending_q  <= ctrl_sending_r;
-    ctrl_send_idx_q <= ctrl_send_idx_r;
-    ctrl_send_len_q <= ctrl_send_len_r;
-    ctrl_txvalid_q  <= ctrl_txvalid_r;
-    ctrl_txdata_q   <= ctrl_txdata_r;
-    ctrl_txstrb_q   <= ctrl_txstrb_r;
-    ctrl_txlast_q   <= ctrl_txlast_r;
-    ctrl_txstall_q  <= ctrl_txstall_r;
-
-    if (setup_valid_q)
-        desc_addr_q     <= desc_addr_r;
-    else if (ctrl_sending_r && ctrl_send_accept_w)
-        desc_addr_q     <= desc_addr_q + 8'd1;
-end
-
-assign ep0_tx_ready_w      = ctrl_txvalid_q;
-assign ep0_tx_data_valid_w = ctrl_txvalid_q;
-assign ep0_tx_data_strb_w  = ctrl_txstrb_q;
-assign ep0_tx_data_w       = ctrl_txdata_q;
-assign ep0_tx_data_last_w  = ctrl_txlast_q;
-assign ep0_tx_stall_w      = ctrl_txstall_q;
-
-//-----------------------------------------------------------------
-// Descriptor ROM
-//-----------------------------------------------------------------
-usb_desc_rom
-u_rom
-(
-    .hs_i(usb_hs_w),
-    .addr_i(desc_addr_q),
-    .data_o(desc_data_w)
-);
-
-//-----------------------------------------------------------------
-// Unused Endpoints
-//-----------------------------------------------------------------
-assign ep1_tx_ready_w      = 1'b0;
-assign ep1_tx_data_valid_w = 1'b0;
-assign ep1_tx_data_strb_w  = 1'b0;
-assign ep1_tx_data_w       = 8'b0;
-assign ep1_tx_data_last_w  = 1'b0;
-assign ep1_tx_stall_w      = 1'b0;
-assign ep3_tx_ready_w      = 1'b0;
-assign ep3_tx_data_valid_w = 1'b0;
-assign ep3_tx_data_strb_w  = 1'b0;
-assign ep3_tx_data_w       = 8'b0;
-assign ep3_tx_data_last_w  = 1'b0;
-assign ep3_tx_stall_w      = 1'b0;
-
-assign ep2_rx_space_w      = 1'b0;
-assign ep3_rx_space_w      = 1'b0;
-
-//-----------------------------------------------------------------
-// Stream I/O
-//-----------------------------------------------------------------
-reg        inport_valid_q;
-reg [7:0]  inport_data_q;
-reg [10:0] inport_cnt_q;
-reg	   outport_break_q;
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-begin
-    inport_valid_q  <= 1'b0;
-    inport_data_q   <= 8'b0;
-end
-else if (inport_accept_o)
-begin
-    inport_valid_q <= inport_valid_i;
-    inport_data_q  <= inport_data_i;
-end
-
-wire [10:0] max_packet_w   = usb_hs_w ? 11'd511 : 11'd63;
-wire        inport_last_w  = !inport_valid_i || (inport_cnt_q == max_packet_w);
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    inport_cnt_q  <= 11'b0;
-else if (inport_last_w && ep2_tx_data_accept_w)
-    inport_cnt_q  <= 11'b0;
-else if (inport_valid_q && ep2_tx_data_accept_w)
-    inport_cnt_q  <= inport_cnt_q + 11'd1;
-
-assign ep2_tx_data_valid_w = inport_valid_q;
-assign ep2_tx_data_w       = inport_data_q;
-assign ep2_tx_ready_w      = ep2_tx_data_valid_w;
-assign ep2_tx_data_strb_w  = ep2_tx_data_valid_w;
-assign ep2_tx_data_last_w  = inport_last_w;
-assign inport_accept_o     = !inport_valid_q | ep2_tx_data_accept_w;
-
-assign outport_valid_o  = ep1_rx_valid_w && rx_strb_w;
-assign outport_data_o   = rx_data_w;
-assign ep1_rx_space_w   = outport_accept_i;
-
-always @(posedge clk_i or posedge rst_i)
-  if (rst_i)
-    outport_break_q <= 1'b0;
-  else
-    outport_break_q <= rx_break_q |
-		       (outport_break_q &
-			~setup_set_w &
-			~outport_valid_o &
-			~(inport_valid_q & ep2_tx_data_accept_w));
-
-assign outport_break_o  = outport_break_q;
-
-endmodule

+ 959 - 0
fpga/usb/usb_serial/src_v/usbf_device_core.sv

@@ -0,0 +1,959 @@
+//-----------------------------------------------------------------
+//                       USB Serial Port
+//                            V0.1
+//                     Ultra-Embedded.com
+//                       Copyright 2020
+//
+//                 Email: admin@ultra-embedded.com
+//
+//                         License: LGPL
+//-----------------------------------------------------------------
+//
+// This source file may be used and distributed without         
+// restriction provided that this copyright statement is not    
+// removed from the file and that any derivative work contains  
+// the original copyright notice and the associated disclaimer. 
+//
+// This source file 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 2.1 of the License, or (at your option) any   
+// later version.
+//
+// This source 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 source; if not, write to the 
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
+// Boston, MA  02111-1307  USA
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+//                          Generated File
+//-----------------------------------------------------------------
+
+package usb_endpoint_types;
+   // Downstream data
+   typedef struct {
+      logic       ep_stall;
+      logic       ep_iso;
+      logic       cfg_int_rx;
+      logic       cfg_int_tx;
+      logic       rx_space;
+      logic       tx_ready;
+      logic       tx_data_valid;
+      logic       tx_data_strb;
+      logic [7:0] tx_data;
+      logic       tx_data_last;
+   } d_t;
+
+   // Per-endpoint upstream data
+   typedef struct {
+      logic       rx_valid;
+      logic       tx_data_accept;
+   } u_t;
+   // Upstream data, shared between all endpoints; included here
+   // to make the interface complete. If suitable for the upstream
+   // device core, however, they do not need to be multiplexed.
+   typedef struct {
+      logic       rx_setup;
+      logic [7:0] rx_data;
+      logic       rx_strb;
+      logic       rx_last;
+      logic       rx_crc_err;
+   } uc_t;
+endpackage
+
+interface usb_endpoint;
+   import usb_endpoint_types::*;
+   
+   d_t d;
+   u_t u;
+   uc_t uc;
+
+   // Upstream interface (toward application)
+   modport ustr (
+		 input 	      d,
+		 output       u,
+		 output       uc
+		 );
+
+   // Downstream interface (toward PHY)
+   modport dstr (
+		 output       d,
+		 input 	      u,
+		 input 	      uc
+		 );
+endinterface // usb_endpoint
+
+module usbf_endpoint_mux
+  #(parameter endpoints = 4, epbits = 4)
+   (
+    input 	       valid_i,
+    input [epbits-1:0] ep_select_i,
+    usb_endpoint.ustr  ep_u [0:endpoints-1],
+    usb_endpoint.dstr  ep_d
+    );
+
+   import usb_endpoint_types::*;
+
+   wire [endpoints-1:0] selected = valid_i << ep_select_i;
+
+   // Quartus seems to need these intermediate variables
+   // to be able to use structures here.
+   d_t   u_d [0:endpoints-1];
+   u_t   ep_d_u;
+   uc_t  ep_d_uc;
+
+   always_comb
+     begin
+	ep_d_u  = ep_d.u;
+	ep_d_uc = ep_d.uc;
+	
+	ep_d.d = '{ default:'b0 };
+	for (int j = 0; j < endpoints; j++)
+	  if (selected[j])
+	    ep_d.d = u_d[j];
+     end
+   
+   generate
+      genvar 	i;
+      for (i = 0; i < endpoints; i++)
+	begin : mux
+	   always_comb
+	     begin
+		ep_u[i].uc = ep_d_uc;
+		if (selected[i])
+		  ep_u[i].u = ep_d_u;
+		else
+		  ep_u[i].u = '{ default:'b0 };
+
+		u_d[i] = ep_u[i].d;
+	     end
+	end
+   endgenerate
+endmodule
+
+module usbf_device_core
+  #(parameter endpoints = 4)
+  (
+   // Inputs
+   input clk_i
+   ,input rst_i
+
+   ,input [ 7:0] utmi_data_i
+   ,input utmi_txready_i
+   ,input utmi_rxvalid_i
+   ,input utmi_rxactive_i
+   ,input utmi_rxerror_i
+   ,input [ 1:0] utmi_linestate_i
+   ,input reg_chirp_en_i
+   ,input reg_int_en_sof_i
+   ,input reg_sts_rst_clr_i
+   ,input [ 6:0] reg_dev_addr_i
+     
+   // Outputs
+   ,output intr_o
+   ,output [ 7:0] utmi_data_o
+   ,output utmi_txvalid_o
+   ,output reg_sts_rst_o
+   ,output [ 10:0] reg_sts_frame_num_o
+
+   // Endpoint interfaces
+   ,usb_endpoint.ustr ep[0:endpoints-1]
+   );
+
+   genvar e;
+   
+   //-----------------------------------------------------------------
+   // Defines:
+   //-----------------------------------------------------------------
+`include "usbf_defs.v"
+
+`define USB_RESET_CNT_W     15
+
+   localparam STATE_W                       = 3;
+   localparam STATE_RX_IDLE                 = 3'd0;
+   localparam STATE_RX_DATA                 = 3'd1;
+   localparam STATE_RX_DATA_READY           = 3'd2;
+   localparam STATE_RX_DATA_IGNORE          = 3'd3;
+   localparam STATE_TX_DATA                 = 3'd4;
+   localparam STATE_TX_DATA_COMPLETE        = 3'd5;
+   localparam STATE_TX_HANDSHAKE            = 3'd6;
+   localparam STATE_TX_CHIRP                = 3'd7;
+   reg [STATE_W-1:0] state_q;
+
+   //-----------------------------------------------------------------
+   // Reset detection
+   //-----------------------------------------------------------------
+   reg [`USB_RESET_CNT_W-1:0] se0_cnt_q;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       se0_cnt_q <= `USB_RESET_CNT_W'b0;
+     else if (utmi_linestate_i == 2'b0)
+       begin
+	  if (!se0_cnt_q[`USB_RESET_CNT_W-1])
+            se0_cnt_q <= se0_cnt_q + `USB_RESET_CNT_W'd1;
+       end    
+     else
+       se0_cnt_q <= `USB_RESET_CNT_W'b0;
+
+   wire usb_rst_w = se0_cnt_q[`USB_RESET_CNT_W-1];
+
+   //-----------------------------------------------------------------
+   // Wire / Regs
+   //-----------------------------------------------------------------
+`define USB_FRAME_W    11
+   wire [`USB_FRAME_W-1:0] frame_num_w;
+
+   wire                    frame_valid_w;
+
+`define USB_DEV_W      7
+   localparam usb_dev_max = (1 << `USB_DEV_W)-1;
+   wire [`USB_DEV_W-1:0]   token_dev_w;
+
+`define USB_EP_W       4
+   localparam usb_ep_max = (1 << `USB_EP_W)-1;
+   wire [`USB_EP_W-1:0]    token_ep_w;
+
+`define USB_PID_W      8
+   localparam usb_pid_max = (1 << `USB_PID_W)-1;
+   wire [`USB_PID_W-1:0]   token_pid_w;
+
+   wire                    token_valid_w;
+
+   wire                    rx_data_valid_w;
+   wire                    rx_data_complete_w;
+
+   wire                    rx_handshake_w;
+
+   reg                     tx_data_valid_r;
+   reg                     tx_data_strb_r;
+   reg [7:0] 		   tx_data_r;
+   reg 			   tx_data_last_r;
+   wire                    tx_data_accept_w;
+   
+   wire [7:0] 		   rx_data_w;
+   wire 		   rx_strb_w;
+   wire 		   rx_last_w;
+   wire			   rx_crc_err_w;
+
+   reg 			   tx_valid_q;
+   reg [7:0] 		   tx_pid_q;
+   wire                    tx_accept_w;
+
+   reg                     rx_space_q;
+   reg                     rx_space_r;
+   reg                     tx_ready_r;
+   reg                     out_data_bit_r;
+   reg                     in_data_bit_r;
+
+   reg                     ep_stall_r;
+   reg                     ep_iso_r;
+
+   reg                     rx_enable_q;
+   reg                     rx_setup_q;
+
+   // Note: these registers are forced to zero for invalid endpoints
+   reg [usb_ep_max:0] 	   out_data_bit_q;
+   reg [usb_ep_max:0] 	   in_data_bit_q;
+
+   reg [`USB_DEV_W-1:0]    current_addr_q;
+
+   //-----------------------------------------------------------------
+   // Endpoint MUX
+   //-----------------------------------------------------------------
+   usb_endpoint ept ();		// Endpoint selected by token
+
+   usbf_endpoint_mux #(.endpoints(endpoints), .epbits(`USB_EP_W))
+   u_endpoint_mux
+     (
+      .valid_i     ( ~rst_i & ~usb_rst_w ),
+      .ep_select_i ( token_ep_w ),
+      .ep_u        ( ep ),
+      .ep_d        ( ept.dstr )
+      );
+
+   assign ep_stall_r = ept.d.ep_stall;
+   assign ep_iso_r   = ept.d.ep_iso;
+   
+//-----------------------------------------------------------------
+// SIE - TX
+//-----------------------------------------------------------------
+   usbf_sie_tx
+     u_sie_tx
+       (
+	.clk_i(clk_i),
+	.rst_i(rst_i),
+	
+	.enable_i(~usb_rst_w),
+	.chirp_i(reg_chirp_en_i),
+	
+	// UTMI Interface
+	.utmi_data_o(utmi_data_o),
+	.utmi_txvalid_o(utmi_txvalid_o),
+	.utmi_txready_i(utmi_txready_i),
+	
+	// Request
+	.tx_valid_i(tx_valid_q),
+	.tx_pid_i(tx_pid_q),
+	.tx_accept_o(tx_accept_w),
+	
+	// Data
+	.data_valid_i(tx_data_valid_r),
+	.data_strb_i(tx_data_strb_r),
+	.data_i(tx_data_r),
+	.data_last_i(tx_data_last_r),
+	.data_accept_o(tx_data_accept_w)
+	);
+
+   assign tx_ready_r           = ept.d.tx_ready;
+   assign tx_data_valid_r      = ept.d.tx_data_valid;
+   assign tx_data_r            = ept.d.tx_data;
+   assign tx_data_last_r       = ept.d.tx_data_last;
+
+   assign ept.u.tx_data_accept = tx_data_accept_w;
+
+   //-----------------------------------------------------------------
+   // SIE - RX
+   //-----------------------------------------------------------------
+   usbf_sie_rx
+     u_sie_rx
+       (
+	.clk_i(clk_i),
+	.rst_i(rst_i),
+	
+	.enable_i(~usb_rst_w && ~reg_chirp_en_i),
+	
+	// UTMI Interface
+	.utmi_data_i(utmi_data_i),
+	.utmi_rxvalid_i(utmi_rxvalid_i),
+	.utmi_rxactive_i(utmi_rxactive_i),
+	
+	.current_addr_i(current_addr_q),
+	
+	.pid_o(token_pid_w),
+	
+	.frame_valid_o(frame_valid_w),
+	.frame_number_o(reg_sts_frame_num_o),
+	
+	.token_valid_o(token_valid_w),
+	.token_addr_o(token_dev_w),
+	.token_ep_o(token_ep_w),
+	.token_crc_err_o(),
+	
+	.handshake_valid_o(rx_handshake_w),
+	
+	.data_valid_o(rx_data_valid_w),
+	.data_strb_o(rx_strb_w),
+	.data_o(rx_data_w),
+	.data_last_o(rx_last_w),
+	
+	.data_complete_o(rx_data_complete_w),
+	.data_crc_err_o(rx_crc_err_w)
+	);
+
+   assign rx_space_r = ept.d.rx_space;
+
+   always @(posedge clk_i or posedge rst_i)
+     if (rst_i)
+       rx_space_q <= 1'b0;
+     else if (state_q == STATE_RX_IDLE)
+       rx_space_q <= rx_space_r;
+
+   assign ept.u.rx_valid    = rx_enable_q & rx_data_valid_w;
+
+   assign ept.uc.rx_setup   = rx_setup_q & (token_ep_w == 4'd0);
+   assign ept.uc.rx_data    = rx_data_w;
+   assign ept.uc.rx_strb    = rx_strb_w;
+   assign ept.uc.rx_last    = rx_last_w;
+   assign ept.uc.rx_crc_err = rx_crc_err_w;
+   
+   //-----------------------------------------------------------------
+   // Next state
+   //-----------------------------------------------------------------
+   reg [STATE_W-1:0] next_state_r;
+
+   always @ *
+     begin
+	next_state_r = state_q;
+
+	//-----------------------------------------
+	// State Machine
+	//-----------------------------------------
+	case (state_q)
+
+	  //-----------------------------------------
+	  // IDLE
+	  //-----------------------------------------
+	  STATE_RX_IDLE :
+	    begin
+               // Token received (OUT, IN, SETUP, PING)
+               if (token_valid_w)
+		 begin
+		    //-------------------------------
+		    // IN transfer (device -> host)
+		    //-------------------------------
+		    if (token_pid_w == `PID_IN)
+		      begin
+			 // Stalled endpoint?
+			 if (ep_stall_r)
+			   next_state_r  = STATE_TX_HANDSHAKE;
+			 // Some data to TX?
+			 else if (tx_ready_r)
+			   next_state_r  = STATE_TX_DATA;
+			 // No data to TX
+			 else
+			   next_state_r  = STATE_TX_HANDSHAKE;
+		      end
+		    //-------------------------------
+		    // PING transfer (device -> host)
+		    //-------------------------------
+		    else if (token_pid_w == `PID_PING)
+		      begin
+			 next_state_r  = STATE_TX_HANDSHAKE;
+		      end
+		    //-------------------------------
+		    // OUT transfer (host -> device)
+		    //-------------------------------
+		    else if (token_pid_w == `PID_OUT)
+		      begin
+			 // Stalled endpoint?
+			 if (ep_stall_r)
+			   next_state_r  = STATE_RX_DATA_IGNORE;
+			 // Some space to rx
+			 else if (rx_space_r)
+			   next_state_r  = STATE_RX_DATA;
+			 // No rx space, ignore receive
+			 else
+			   next_state_r  = STATE_RX_DATA_IGNORE;
+		      end
+		    //-------------------------------
+		    // SETUP transfer (host -> device)
+		    //-------------------------------
+		    else if (token_pid_w == `PID_SETUP)
+		      begin
+			 // Some space to rx
+			 if (rx_space_r)
+			   next_state_r  = STATE_RX_DATA;
+			 // No rx space, ignore receive
+			 else
+			   next_state_r  = STATE_RX_DATA_IGNORE;
+		      end
+		 end
+               else if (reg_chirp_en_i)
+		 next_state_r  = STATE_TX_CHIRP;
+	    end
+
+	  //-----------------------------------------
+	  // RX_DATA
+	  //-----------------------------------------
+	  STATE_RX_DATA :
+	    begin
+               // TODO: Exit data state handling?
+
+               // TODO: Sort out ISO data bit handling
+               // Check for expected DATAx PID
+               if ((token_pid_w == `PID_DATA0 &&  out_data_bit_r && !ep_iso_r) ||
+		   (token_pid_w == `PID_DATA1 && !out_data_bit_r && !ep_iso_r))
+		 next_state_r  = STATE_RX_DATA_IGNORE;
+               // Receive complete
+               else if (rx_data_valid_w && rx_last_w)
+		 next_state_r  = STATE_RX_DATA_READY;
+	    end
+	  //-----------------------------------------
+	  // RX_DATA_IGNORE
+	  //-----------------------------------------
+	  STATE_RX_DATA_IGNORE :
+	    begin
+               // Receive complete
+               if (rx_data_valid_w && rx_last_w)
+		 next_state_r  = STATE_RX_DATA_READY;
+	    end
+	  //-----------------------------------------
+	  // RX_DATA_READY
+	  //-----------------------------------------
+	  STATE_RX_DATA_READY :
+	    begin
+               if (rx_data_complete_w)
+		 begin
+		    // No response on CRC16 error
+		    if (rx_crc_err_w)
+                      next_state_r  = STATE_RX_IDLE;
+		    // ISO endpoint, no response?
+		    else if (ep_iso_r)
+                      next_state_r  = STATE_RX_IDLE;
+		    else
+                      next_state_r  = STATE_TX_HANDSHAKE;
+		 end
+	    end
+	  //-----------------------------------------
+	  // TX_DATA
+	  //-----------------------------------------
+	  STATE_TX_DATA :
+	    begin
+               if (!tx_valid_q || tx_accept_w)
+		 if (tx_data_valid_r && tx_data_last_r && tx_data_accept_w)
+                   next_state_r  = STATE_TX_DATA_COMPLETE;
+	    end
+	  //-----------------------------------------
+	  // TX_HANDSHAKE
+	  //-----------------------------------------
+	  STATE_TX_DATA_COMPLETE :
+	    begin
+               next_state_r  = STATE_RX_IDLE;
+	    end
+	  //-----------------------------------------
+	  // TX_HANDSHAKE
+	  //-----------------------------------------
+	  STATE_TX_HANDSHAKE :
+	    begin
+               if (tx_accept_w)
+		 next_state_r  = STATE_RX_IDLE;
+	    end
+	  //-----------------------------------------
+	  // TX_CHIRP
+	  //-----------------------------------------
+	  STATE_TX_CHIRP :
+	    begin
+               if (!reg_chirp_en_i)
+		 next_state_r  = STATE_RX_IDLE;
+	    end
+
+	  default :
+	    ;
+
+	endcase
+
+	//-----------------------------------------
+	// USB Bus Reset (HOST->DEVICE)
+	//----------------------------------------- 
+	if (usb_rst_w && !reg_chirp_en_i)
+          next_state_r  = STATE_RX_IDLE;
+     end
+
+   // Update state
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       state_q   <= STATE_RX_IDLE;
+     else
+       state_q   <= next_state_r;
+
+   //-----------------------------------------------------------------
+   // Response
+   //-----------------------------------------------------------------
+   reg         tx_valid_r;
+   reg [7:0]   tx_pid_r;
+
+   always @ *
+     begin
+	tx_valid_r = 1'b0;
+	tx_pid_r   = 8'b0;
+
+	case (state_q)
+	  //-----------------------------------------
+	  // IDLE
+	  //-----------------------------------------
+	  STATE_RX_IDLE :
+	    begin
+               // Token received (OUT, IN, SETUP, PING)
+               if (token_valid_w)
+		 begin
+		    //-------------------------------
+		    // IN transfer (device -> host)
+		    //-------------------------------
+		    if (token_pid_w == `PID_IN)
+		      begin
+			 // Stalled endpoint?
+			 if (ep_stall_r)
+			   begin
+			      tx_valid_r = 1'b1;
+			      tx_pid_r   = `PID_STALL;
+			   end
+			 // Some data to TX?
+			 else if (tx_ready_r)
+			   begin
+			      tx_valid_r = 1'b1;
+			      // TODO: Handle MDATA for ISOs
+			      tx_pid_r   = in_data_bit_r ? `PID_DATA1 : `PID_DATA0;
+			   end
+			 // No data to TX
+			 else
+			   begin
+			      tx_valid_r = 1'b1;
+			      tx_pid_r   = `PID_NAK;
+			   end
+		      end
+		    //-------------------------------
+		    // PING transfer (device -> host)
+		    //-------------------------------
+		    else if (token_pid_w == `PID_PING)
+		      begin
+			 // Stalled endpoint?
+			 if (ep_stall_r)
+			   begin
+			      tx_valid_r = 1'b1;
+			      tx_pid_r   = `PID_STALL;
+			   end
+			 // Data ready to RX
+			 else if (rx_space_r)
+			   begin
+			      tx_valid_r = 1'b1;
+			      tx_pid_r   = `PID_ACK;
+			   end
+			 // No data to TX
+			 else
+			   begin
+			      tx_valid_r = 1'b1;
+			      tx_pid_r   = `PID_NAK;
+			   end
+		      end
+		 end
+	    end
+
+	  //-----------------------------------------
+	  // RX_DATA_READY
+	  //-----------------------------------------
+	  STATE_RX_DATA_READY :
+	    begin
+	       // Receive complete
+	       if (rx_data_complete_w)
+		 begin
+		    // No response on CRC16 error
+		    if (rx_crc_err_w)
+                      ;
+		    // ISO endpoint, no response?
+		    else if (ep_iso_r)
+                      ;
+		    // Send STALL?
+		    else if (ep_stall_r)
+		      begin
+			 tx_valid_r = 1'b1;
+			 tx_pid_r   = `PID_STALL;
+		      end
+		    // DATAx bit mismatch
+		    else if ( (token_pid_w == `PID_DATA0 && out_data_bit_r) ||
+			      (token_pid_w == `PID_DATA1 && !out_data_bit_r) )
+		      begin
+			 // Ack transfer to resync
+			 tx_valid_r = 1'b1;
+			 tx_pid_r   = `PID_ACK;
+		      end
+		    // Send NAK
+		    else if (!rx_space_q)
+		      begin
+			 tx_valid_r = 1'b1;
+			 tx_pid_r   = `PID_NAK;
+		      end
+		    // TODO: USB 2.0, no more buffer space, return NYET
+		    else
+		      begin
+			 tx_valid_r = 1'b1;
+			 tx_pid_r   = `PID_ACK;
+		      end
+		 end
+	    end
+
+	  //-----------------------------------------
+	  // TX_CHIRP
+	  //-----------------------------------------
+	  STATE_TX_CHIRP :
+	    begin
+               tx_valid_r = 1'b1;
+               tx_pid_r   = 8'b0;
+	    end
+
+	  default :
+	    ;
+
+	endcase
+     end
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       tx_valid_q <= 1'b0;
+     else if (!tx_valid_q || tx_accept_w)
+       tx_valid_q <= tx_valid_r;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       tx_pid_q <= 8'b0;
+     else if (!tx_valid_q || tx_accept_w)
+       tx_pid_q <= tx_pid_r;
+
+   //-----------------------------------------------------------------
+   // Receive enable
+   //-----------------------------------------------------------------
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       rx_enable_q <= 1'b0;
+     else if (usb_rst_w ||reg_chirp_en_i)
+       rx_enable_q <= 1'b0;
+     else
+       rx_enable_q <= (state_q == STATE_RX_DATA);
+
+   //-----------------------------------------------------------------
+   // Receive SETUP: Pulse on SETUP packet receive
+   //-----------------------------------------------------------------
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       rx_setup_q <= 1'b0;
+     else if (usb_rst_w ||reg_chirp_en_i)
+       rx_setup_q <= 1'b0;
+     else if ((state_q == STATE_RX_IDLE) && token_valid_w && (token_pid_w == `PID_SETUP) && (token_ep_w == 4'd0))
+       rx_setup_q <= 1'b1;
+     else
+       rx_setup_q <= 1'b0;
+
+   //-----------------------------------------------------------------
+   // Set Address
+   //-----------------------------------------------------------------
+   reg addr_update_pending_q;
+
+   wire ep0_tx_zlp_w = ep[0].d.tx_data_valid & ~ep[0].d.tx_data_strb &
+	ep[0].d.tx_data_last & ep[0].u.tx_data_accept;
+
+   reg 	sent_status_zlp_q;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       sent_status_zlp_q   <= 1'b0;
+     else if (usb_rst_w)
+       sent_status_zlp_q   <= 1'b0;
+     else if (ep0_tx_zlp_w)
+       sent_status_zlp_q   <= 1'b1;
+     else if (rx_handshake_w)
+       sent_status_zlp_q   <= 1'b0;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       addr_update_pending_q   <= 1'b0;
+     else if ((sent_status_zlp_q && addr_update_pending_q && rx_handshake_w && token_pid_w == `PID_ACK) || usb_rst_w)
+       addr_update_pending_q   <= 1'b0;
+   // TODO: Use write strobe
+     else if (reg_dev_addr_i != current_addr_q)
+       addr_update_pending_q   <= 1'b1;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       current_addr_q  <= 'b0;
+     else if (usb_rst_w)
+       current_addr_q  <= 'b0;
+     else if (sent_status_zlp_q && addr_update_pending_q && rx_handshake_w && token_pid_w == `PID_ACK)
+       current_addr_q  <= reg_dev_addr_i;
+
+   //-----------------------------------------------------------------
+   // Endpoint data bit toggle
+   //-----------------------------------------------------------------
+   reg 	new_out_bit_r;
+   reg 	new_in_bit_r;
+
+   always @ *
+     begin
+	new_out_bit_r = out_data_bit_r;
+	new_in_bit_r  = in_data_bit_r;
+
+	case (state_q)
+	  //-----------------------------------------
+	  // RX_DATA_READY
+	  //-----------------------------------------
+	  STATE_RX_DATA_READY :
+	    begin
+	       // Receive complete
+	       if (rx_data_complete_w)
+		 begin
+		    // No toggle on CRC16 error
+		    if (rx_crc_err_w)
+                      ;
+		    // ISO endpoint, no response?
+		    else if (ep_iso_r)
+                      ; // TODO: HS handling
+		    // STALL?
+		    else if (ep_stall_r)
+                      ;
+		    // DATAx bit mismatch
+		    else if ( (token_pid_w == `PID_DATA0 && out_data_bit_r) ||
+			      (token_pid_w == `PID_DATA1 && !out_data_bit_r) )
+                      ;
+		    // NAKd
+		    else if (!rx_space_q)
+                      ;
+		    // Data accepted - toggle data bit
+		    else
+                      new_out_bit_r = !out_data_bit_r;
+		 end
+	    end
+	  //-----------------------------------------
+	  // RX_IDLE
+	  //-----------------------------------------
+	  STATE_RX_IDLE :
+	    begin
+               // Token received (OUT, IN, SETUP, PING)
+               if (token_valid_w)
+		 begin
+		    // SETUP packets always start with DATA0
+		    if (token_pid_w == `PID_SETUP)
+		      begin
+			 new_out_bit_r = 1'b0;
+			 new_in_bit_r  = 1'b1;
+		      end
+		 end
+               // ACK received
+               else if (rx_handshake_w && token_pid_w == `PID_ACK)
+		 begin
+		    new_in_bit_r = !in_data_bit_r;
+		 end
+	    end
+	  default:
+            ;
+	endcase
+     end
+
+   always @(posedge clk_i or posedge rst_i)
+     if (rst_i)
+       begin
+	  out_data_bit_q <= 'b0;
+	  in_data_bit_q  <= 'b0;
+       end
+     else
+       begin
+	  out_data_bit_q <= 'b0;
+	  in_data_bit_q  <= 'b0;
+	  if ((token_ep_w < endpoints) && ~usb_rst_w)
+	    begin
+	       out_data_bit_q[token_ep_w] <= new_out_bit_r;
+	       in_data_bit_q [token_ep_w] <= new_in_bit_r;
+	    end
+       end // else: !if(rst_i)
+
+   assign out_data_bit_r = out_data_bit_q[token_ep_w];
+   assign in_data_bit_r  = in_data_bit_q [token_ep_w];
+
+   //-----------------------------------------------------------------
+   // Reset event
+   //-----------------------------------------------------------------
+   reg rst_event_q;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       rst_event_q <= 1'b0;
+     else if (usb_rst_w)
+       rst_event_q <= 1'b1;
+     else if (reg_sts_rst_clr_i)
+       rst_event_q <= 1'b0;
+
+   assign reg_sts_rst_o = rst_event_q;
+
+   //-----------------------------------------------------------------
+   // Interrupts
+   //-----------------------------------------------------------------
+   reg intr_q;
+
+   wire cfg_int_rx_r = ept.d.cfg_int_rx;
+   wire cfg_int_tx_r = ept.d.cfg_int_tx;
+
+   always @ (posedge clk_i or posedge rst_i)
+     if (rst_i)
+       intr_q <= 1'b0;
+   // SOF
+     else if (frame_valid_w && reg_int_en_sof_i)
+       intr_q <= 1'b1;
+   // Reset event
+     else if (!rst_event_q && usb_rst_w)
+       intr_q <= 1'b1;
+   // Rx ready
+     else if (state_q == STATE_RX_DATA_READY && rx_space_q && cfg_int_rx_r)
+       intr_q <= 1'b1;
+   // Tx complete
+     else if (state_q == STATE_TX_DATA_COMPLETE && cfg_int_tx_r)
+       intr_q <= 1'b1;    
+     else
+       intr_q <= 1'b0;
+
+   assign intr_o = intr_q;
+
+   //-------------------------------------------------------------------
+   // Debug
+   //-------------------------------------------------------------------
+`ifdef verilator
+   /* verilator lint_off WIDTH */
+   reg [79:0] dbg_state;
+
+   always @ *
+     begin
+	dbg_state = "-";
+
+	case (state_q)
+	  STATE_RX_IDLE: dbg_state = "IDLE";
+	  STATE_RX_DATA: dbg_state = "RX_DATA";
+	  STATE_RX_DATA_READY: dbg_state = "RX_DATA_READY";
+	  STATE_RX_DATA_IGNORE: dbg_state = "RX_IGNORE";
+	  STATE_TX_DATA: dbg_state = "TX_DATA";
+	  STATE_TX_DATA_COMPLETE: dbg_state = "TX_DATA_COMPLETE";
+	  STATE_TX_HANDSHAKE: dbg_state = "TX_HANDSHAKE";
+	  STATE_TX_CHIRP: dbg_state = "CHIRP";
+	endcase
+     end
+
+   reg [79:0] dbg_pid;
+   reg [7:0]  dbg_pid_r;
+   always @ *
+     begin
+	dbg_pid = "-";
+
+	if (tx_valid_q && tx_accept_w)
+          dbg_pid_r = tx_pid_q;
+	else if (token_valid_w || rx_handshake_w || rx_data_valid_w)
+          dbg_pid_r = token_pid_w;
+	else
+          dbg_pid_r = 8'b0;
+
+	case (dbg_pid_r)
+	  // Token
+	  `PID_OUT:
+            dbg_pid = "OUT";
+	  `PID_IN:
+            dbg_pid = "IN";
+	  `PID_SOF:
+            dbg_pid = "SOF";
+	  `PID_SETUP:
+            dbg_pid = "SETUP";
+	  `PID_PING:
+            dbg_pid = "PING";
+	  // Data
+	  `PID_DATA0:
+            dbg_pid = "DATA0";
+	  `PID_DATA1:
+            dbg_pid = "DATA1";
+	  `PID_DATA2:
+            dbg_pid = "DATA2";
+	  `PID_MDATA:
+            dbg_pid = "MDATA";
+	  // Handshake
+	  `PID_ACK:
+            dbg_pid = "ACK";
+	  `PID_NAK:
+            dbg_pid = "NAK";
+	  `PID_STALL:
+            dbg_pid = "STALL";
+	  `PID_NYET:
+            dbg_pid = "NYET";
+	  // Special
+	  `PID_PRE:
+            dbg_pid = "PRE/ERR";
+	  `PID_SPLIT:
+            dbg_pid = "SPLIT";
+	  default:
+            ;
+	endcase
+     end
+   /* verilator lint_on WIDTH */
+`endif
+
+
+endmodule

+ 0 - 1054
fpga/usb/usb_serial/src_v/usbf_device_core.v

@@ -1,1054 +0,0 @@
-//-----------------------------------------------------------------
-//                       USB Serial Port
-//                            V0.1
-//                     Ultra-Embedded.com
-//                       Copyright 2020
-//
-//                 Email: admin@ultra-embedded.com
-//
-//                         License: LGPL
-//-----------------------------------------------------------------
-//
-// This source file may be used and distributed without         
-// restriction provided that this copyright statement is not    
-// removed from the file and that any derivative work contains  
-// the original copyright notice and the associated disclaimer. 
-//
-// This source file 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 2.1 of the License, or (at your option) any   
-// later version.
-//
-// This source 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 source; if not, write to the 
-// Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
-// Boston, MA  02111-1307  USA
-//-----------------------------------------------------------------
-
-//-----------------------------------------------------------------
-//                          Generated File
-//-----------------------------------------------------------------
-
-module usbf_device_core
-(
-    // Inputs
-     input           clk_i
-    ,input           rst_i
-    ,input  [  7:0]  utmi_data_i
-    ,input           utmi_txready_i
-    ,input           utmi_rxvalid_i
-    ,input           utmi_rxactive_i
-    ,input           utmi_rxerror_i
-    ,input  [  1:0]  utmi_linestate_i
-    ,input           ep0_stall_i
-    ,input           ep0_iso_i
-    ,input           ep0_cfg_int_rx_i
-    ,input           ep0_cfg_int_tx_i
-    ,input           ep0_rx_space_i
-    ,input           ep0_tx_ready_i
-    ,input           ep0_tx_data_valid_i
-    ,input           ep0_tx_data_strb_i
-    ,input  [  7:0]  ep0_tx_data_i
-    ,input           ep0_tx_data_last_i
-    ,input           ep1_stall_i
-    ,input           ep1_iso_i
-    ,input           ep1_cfg_int_rx_i
-    ,input           ep1_cfg_int_tx_i
-    ,input           ep1_rx_space_i
-    ,input           ep1_tx_ready_i
-    ,input           ep1_tx_data_valid_i
-    ,input           ep1_tx_data_strb_i
-    ,input  [  7:0]  ep1_tx_data_i
-    ,input           ep1_tx_data_last_i
-    ,input           ep2_stall_i
-    ,input           ep2_iso_i
-    ,input           ep2_cfg_int_rx_i
-    ,input           ep2_cfg_int_tx_i
-    ,input           ep2_rx_space_i
-    ,input           ep2_tx_ready_i
-    ,input           ep2_tx_data_valid_i
-    ,input           ep2_tx_data_strb_i
-    ,input  [  7:0]  ep2_tx_data_i
-    ,input           ep2_tx_data_last_i
-    ,input           ep3_stall_i
-    ,input           ep3_iso_i
-    ,input           ep3_cfg_int_rx_i
-    ,input           ep3_cfg_int_tx_i
-    ,input           ep3_rx_space_i
-    ,input           ep3_tx_ready_i
-    ,input           ep3_tx_data_valid_i
-    ,input           ep3_tx_data_strb_i
-    ,input  [  7:0]  ep3_tx_data_i
-    ,input           ep3_tx_data_last_i
-    ,input           reg_chirp_en_i
-    ,input           reg_int_en_sof_i
-    ,input           reg_sts_rst_clr_i
-    ,input  [  6:0]  reg_dev_addr_i
-
-    // Outputs
-    ,output          intr_o
-    ,output [  7:0]  utmi_data_o
-    ,output          utmi_txvalid_o
-    ,output          rx_strb_o
-    ,output [  7:0]  rx_data_o
-    ,output          rx_last_o
-    ,output          rx_crc_err_o
-    ,output          ep0_rx_setup_o
-    ,output          ep0_rx_valid_o
-    ,output          ep0_tx_data_accept_o
-    ,output          ep1_rx_setup_o
-    ,output          ep1_rx_valid_o
-    ,output          ep1_tx_data_accept_o
-    ,output          ep2_rx_setup_o
-    ,output          ep2_rx_valid_o
-    ,output          ep2_tx_data_accept_o
-    ,output          ep3_rx_setup_o
-    ,output          ep3_rx_valid_o
-    ,output          ep3_tx_data_accept_o
-    ,output          reg_sts_rst_o
-    ,output [ 10:0]  reg_sts_frame_num_o
-);
-
-
-
-//-----------------------------------------------------------------
-// Defines:
-//-----------------------------------------------------------------
-`include "usbf_defs.v"
-
-`define USB_RESET_CNT_W     15
-
-localparam STATE_W                       = 3;
-localparam STATE_RX_IDLE                 = 3'd0;
-localparam STATE_RX_DATA                 = 3'd1;
-localparam STATE_RX_DATA_READY           = 3'd2;
-localparam STATE_RX_DATA_IGNORE          = 3'd3;
-localparam STATE_TX_DATA                 = 3'd4;
-localparam STATE_TX_DATA_COMPLETE        = 3'd5;
-localparam STATE_TX_HANDSHAKE            = 3'd6;
-localparam STATE_TX_CHIRP                = 3'd7;
-reg [STATE_W-1:0] state_q;
-
-//-----------------------------------------------------------------
-// Reset detection
-//-----------------------------------------------------------------
-reg [`USB_RESET_CNT_W-1:0] se0_cnt_q;
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    se0_cnt_q <= `USB_RESET_CNT_W'b0;
-else if (utmi_linestate_i == 2'b0)
-begin
-    if (!se0_cnt_q[`USB_RESET_CNT_W-1])
-        se0_cnt_q <= se0_cnt_q + `USB_RESET_CNT_W'd1;
-end    
-else
-    se0_cnt_q <= `USB_RESET_CNT_W'b0;
-
-wire usb_rst_w = se0_cnt_q[`USB_RESET_CNT_W-1];
-
-//-----------------------------------------------------------------
-// Wire / Regs
-//-----------------------------------------------------------------
-`define USB_FRAME_W    11
-wire [`USB_FRAME_W-1:0] frame_num_w;
-
-wire                    frame_valid_w;
-
-`define USB_DEV_W      7
-wire [`USB_DEV_W-1:0]   token_dev_w;
-
-`define USB_EP_W       4
-wire [`USB_EP_W-1:0]    token_ep_w;
-
-`define USB_PID_W      8
-wire [`USB_PID_W-1:0]   token_pid_w;
-
-wire                    token_valid_w;
-
-wire                    rx_data_valid_w;
-wire                    rx_data_complete_w;
-
-wire                    rx_handshake_w;
-
-reg                     tx_data_valid_r;
-reg                     tx_data_strb_r;
-reg  [7:0]              tx_data_r;
-reg                     tx_data_last_r;
-wire                    tx_data_accept_w;
-
-reg                     tx_valid_q;
-reg [7:0]               tx_pid_q;
-wire                    tx_accept_w;
-
-reg                     rx_space_q;
-reg                     rx_space_r;
-reg                     tx_ready_r;
-reg                     out_data_bit_r;
-reg                     in_data_bit_r;
-
-reg                     ep_stall_r;
-reg                     ep_iso_r;
-
-reg                     rx_enable_q;
-reg                     rx_setup_q;
-
-reg                     ep0_out_data_bit_q;
-reg                     ep0_in_data_bit_q;
-reg                     ep1_out_data_bit_q;
-reg                     ep1_in_data_bit_q;
-reg                     ep2_out_data_bit_q;
-reg                     ep2_in_data_bit_q;
-reg                     ep3_out_data_bit_q;
-reg                     ep3_in_data_bit_q;
-
-reg [`USB_DEV_W-1:0]    current_addr_q;
-
-//-----------------------------------------------------------------
-// SIE - TX
-//-----------------------------------------------------------------
-usbf_sie_tx
-u_sie_tx
-(
-    .clk_i(clk_i),
-    .rst_i(rst_i),
-    
-    .enable_i(~usb_rst_w),
-    .chirp_i(reg_chirp_en_i),
-
-    // UTMI Interface
-    .utmi_data_o(utmi_data_o),
-    .utmi_txvalid_o(utmi_txvalid_o),
-    .utmi_txready_i(utmi_txready_i),
-
-    // Request
-    .tx_valid_i(tx_valid_q),
-    .tx_pid_i(tx_pid_q),
-    .tx_accept_o(tx_accept_w),
-
-    // Data
-    .data_valid_i(tx_data_valid_r),
-    .data_strb_i(tx_data_strb_r),
-    .data_i(tx_data_r),
-    .data_last_i(tx_data_last_r),
-    .data_accept_o(tx_data_accept_w)
-);
-
-always @ *
-begin
-    tx_data_valid_r = 1'b0;
-    tx_data_strb_r  = 1'b0;
-    tx_data_r       = 8'b0;
-    tx_data_last_r  = 1'b0;
-
-    case (token_ep_w)
-    4'd0:
-    begin
-        tx_data_valid_r = ep0_tx_data_valid_i;
-        tx_data_strb_r  = ep0_tx_data_strb_i;
-        tx_data_r       = ep0_tx_data_i;
-        tx_data_last_r  = ep0_tx_data_last_i;
-    end
-    4'd1:
-    begin
-        tx_data_valid_r = ep1_tx_data_valid_i;
-        tx_data_strb_r  = ep1_tx_data_strb_i;
-        tx_data_r       = ep1_tx_data_i;
-        tx_data_last_r  = ep1_tx_data_last_i;
-    end
-    4'd2:
-    begin
-        tx_data_valid_r = ep2_tx_data_valid_i;
-        tx_data_strb_r  = ep2_tx_data_strb_i;
-        tx_data_r       = ep2_tx_data_i;
-        tx_data_last_r  = ep2_tx_data_last_i;
-    end
-    4'd3:
-    begin
-        tx_data_valid_r = ep3_tx_data_valid_i;
-        tx_data_strb_r  = ep3_tx_data_strb_i;
-        tx_data_r       = ep3_tx_data_i;
-        tx_data_last_r  = ep3_tx_data_last_i;
-    end
-    default:
-        ;
-    endcase    
-end
-
-assign ep0_tx_data_accept_o = tx_data_accept_w & (token_ep_w == 4'd0);
-assign ep1_tx_data_accept_o = tx_data_accept_w & (token_ep_w == 4'd1);
-assign ep2_tx_data_accept_o = tx_data_accept_w & (token_ep_w == 4'd2);
-assign ep3_tx_data_accept_o = tx_data_accept_w & (token_ep_w == 4'd3);
-
-always @ *
-begin
-    rx_space_r     = 1'b0;
-    tx_ready_r     = 1'b0;
-    out_data_bit_r = 1'b0;
-    in_data_bit_r  = 1'b0;
-
-    ep_stall_r = 1'b0;
-    ep_iso_r   = 1'b0;
-
-    case (token_ep_w)
-    4'd0:
-    begin
-        rx_space_r    = ep0_rx_space_i;
-        tx_ready_r    = ep0_tx_ready_i;
-        out_data_bit_r= ep0_out_data_bit_q;
-        in_data_bit_r = ep0_in_data_bit_q;
-        ep_stall_r    = ep0_stall_i;
-        ep_iso_r      = ep0_iso_i;
-    end
-    4'd1:
-    begin
-        rx_space_r    = ep1_rx_space_i;
-        tx_ready_r    = ep1_tx_ready_i;
-        out_data_bit_r= ep1_out_data_bit_q;
-        in_data_bit_r = ep1_in_data_bit_q;
-        ep_stall_r    = ep1_stall_i;
-        ep_iso_r      = ep1_iso_i;
-    end
-    4'd2:
-    begin
-        rx_space_r    = ep2_rx_space_i;
-        tx_ready_r    = ep2_tx_ready_i;
-        out_data_bit_r= ep2_out_data_bit_q;
-        in_data_bit_r = ep2_in_data_bit_q;
-        ep_stall_r    = ep2_stall_i;
-        ep_iso_r      = ep2_iso_i;
-    end
-    4'd3:
-    begin
-        rx_space_r    = ep3_rx_space_i;
-        tx_ready_r    = ep3_tx_ready_i;
-        out_data_bit_r= ep3_out_data_bit_q;
-        in_data_bit_r = ep3_in_data_bit_q;
-        ep_stall_r    = ep3_stall_i;
-        ep_iso_r      = ep3_iso_i;
-    end
-    default:
-        ;
-    endcase
-end
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    rx_space_q <= 1'b0;
-else if (state_q == STATE_RX_IDLE)
-    rx_space_q <= rx_space_r;
-
-//-----------------------------------------------------------------
-// SIE - RX
-//-----------------------------------------------------------------
-usbf_sie_rx
-u_sie_rx
-(
-    .clk_i(clk_i),
-    .rst_i(rst_i),
-    
-    .enable_i(~usb_rst_w && ~reg_chirp_en_i),
-
-    // UTMI Interface
-    .utmi_data_i(utmi_data_i),
-    .utmi_rxvalid_i(utmi_rxvalid_i),
-    .utmi_rxactive_i(utmi_rxactive_i),
-
-    .current_addr_i(current_addr_q),
-
-    .pid_o(token_pid_w),
-
-    .frame_valid_o(frame_valid_w),
-    .frame_number_o(reg_sts_frame_num_o),
-
-    .token_valid_o(token_valid_w),
-    .token_addr_o(token_dev_w),
-    .token_ep_o(token_ep_w),
-    .token_crc_err_o(),
-
-    .handshake_valid_o(rx_handshake_w),
-
-    .data_valid_o(rx_data_valid_w),
-    .data_strb_o(rx_strb_o),
-    .data_o(rx_data_o),
-    .data_last_o(rx_last_o),
-
-    .data_complete_o(rx_data_complete_w),
-    .data_crc_err_o(rx_crc_err_o)
-);
-
-assign ep0_rx_valid_o = rx_enable_q & rx_data_valid_w & (token_ep_w == 4'd0);
-assign ep0_rx_setup_o = rx_setup_q & (token_ep_w == 4'd0);
-assign ep1_rx_valid_o = rx_enable_q & rx_data_valid_w & (token_ep_w == 4'd1);
-assign ep1_rx_setup_o = rx_setup_q & (token_ep_w == 4'd0);
-assign ep2_rx_valid_o = rx_enable_q & rx_data_valid_w & (token_ep_w == 4'd2);
-assign ep2_rx_setup_o = rx_setup_q & (token_ep_w == 4'd0);
-assign ep3_rx_valid_o = rx_enable_q & rx_data_valid_w & (token_ep_w == 4'd3);
-assign ep3_rx_setup_o = rx_setup_q & (token_ep_w == 4'd0);
-
-//-----------------------------------------------------------------
-// Next state
-//-----------------------------------------------------------------
-reg [STATE_W-1:0] next_state_r;
-
-always @ *
-begin
-    next_state_r = state_q;
-
-    //-----------------------------------------
-    // State Machine
-    //-----------------------------------------
-    case (state_q)
-
-    //-----------------------------------------
-    // IDLE
-    //-----------------------------------------
-    STATE_RX_IDLE :
-    begin
-        // Token received (OUT, IN, SETUP, PING)
-        if (token_valid_w)
-        begin
-            //-------------------------------
-            // IN transfer (device -> host)
-            //-------------------------------
-            if (token_pid_w == `PID_IN)
-            begin
-                // Stalled endpoint?
-                if (ep_stall_r)
-                    next_state_r  = STATE_TX_HANDSHAKE;
-                // Some data to TX?
-                else if (tx_ready_r)
-                    next_state_r  = STATE_TX_DATA;
-                // No data to TX
-                else
-                    next_state_r  = STATE_TX_HANDSHAKE;
-            end
-            //-------------------------------
-            // PING transfer (device -> host)
-            //-------------------------------
-            else if (token_pid_w == `PID_PING)
-            begin
-                next_state_r  = STATE_TX_HANDSHAKE;
-            end
-            //-------------------------------
-            // OUT transfer (host -> device)
-            //-------------------------------
-            else if (token_pid_w == `PID_OUT)
-            begin
-                // Stalled endpoint?
-                if (ep_stall_r)
-                    next_state_r  = STATE_RX_DATA_IGNORE;
-                // Some space to rx
-                else if (rx_space_r)
-                    next_state_r  = STATE_RX_DATA;
-                // No rx space, ignore receive
-                else
-                    next_state_r  = STATE_RX_DATA_IGNORE;
-            end
-            //-------------------------------
-            // SETUP transfer (host -> device)
-            //-------------------------------
-            else if (token_pid_w == `PID_SETUP)
-            begin
-                // Some space to rx
-                if (rx_space_r)
-                    next_state_r  = STATE_RX_DATA;
-                // No rx space, ignore receive
-                else
-                    next_state_r  = STATE_RX_DATA_IGNORE;
-            end
-        end
-        else if (reg_chirp_en_i)
-            next_state_r  = STATE_TX_CHIRP;
-    end
-
-    //-----------------------------------------
-    // RX_DATA
-    //-----------------------------------------
-    STATE_RX_DATA :
-    begin
-        // TODO: Exit data state handling?
-
-        // TODO: Sort out ISO data bit handling
-        // Check for expected DATAx PID
-        if ((token_pid_w == `PID_DATA0 &&  out_data_bit_r && !ep_iso_r) ||
-            (token_pid_w == `PID_DATA1 && !out_data_bit_r && !ep_iso_r))
-            next_state_r  = STATE_RX_DATA_IGNORE;
-        // Receive complete
-        else if (rx_data_valid_w && rx_last_o)
-            next_state_r  = STATE_RX_DATA_READY;
-    end
-    //-----------------------------------------
-    // RX_DATA_IGNORE
-    //-----------------------------------------
-    STATE_RX_DATA_IGNORE :
-    begin
-        // Receive complete
-        if (rx_data_valid_w && rx_last_o)
-            next_state_r  = STATE_RX_DATA_READY;
-    end
-    //-----------------------------------------
-    // RX_DATA_READY
-    //-----------------------------------------
-    STATE_RX_DATA_READY :
-    begin
-        if (rx_data_complete_w)
-        begin
-            // No response on CRC16 error
-            if (rx_crc_err_o)
-                next_state_r  = STATE_RX_IDLE;
-            // ISO endpoint, no response?
-            else if (ep_iso_r)
-                next_state_r  = STATE_RX_IDLE;
-            else
-                next_state_r  = STATE_TX_HANDSHAKE;
-        end
-    end
-    //-----------------------------------------
-    // TX_DATA
-    //-----------------------------------------
-    STATE_TX_DATA :
-    begin
-        if (!tx_valid_q || tx_accept_w)
-            if (tx_data_valid_r && tx_data_last_r && tx_data_accept_w)
-                next_state_r  = STATE_TX_DATA_COMPLETE;
-    end
-    //-----------------------------------------
-    // TX_HANDSHAKE
-    //-----------------------------------------
-    STATE_TX_DATA_COMPLETE :
-    begin
-        next_state_r  = STATE_RX_IDLE;
-    end
-    //-----------------------------------------
-    // TX_HANDSHAKE
-    //-----------------------------------------
-    STATE_TX_HANDSHAKE :
-    begin
-        if (tx_accept_w)
-            next_state_r  = STATE_RX_IDLE;
-    end
-    //-----------------------------------------
-    // TX_CHIRP
-    //-----------------------------------------
-    STATE_TX_CHIRP :
-    begin
-        if (!reg_chirp_en_i)
-            next_state_r  = STATE_RX_IDLE;
-    end
-
-    default :
-       ;
-
-    endcase
-
-    //-----------------------------------------
-    // USB Bus Reset (HOST->DEVICE)
-    //----------------------------------------- 
-    if (usb_rst_w && !reg_chirp_en_i)
-        next_state_r  = STATE_RX_IDLE;
-end
-
-// Update state
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    state_q   <= STATE_RX_IDLE;
-else
-    state_q   <= next_state_r;
-
-//-----------------------------------------------------------------
-// Response
-//-----------------------------------------------------------------
-reg         tx_valid_r;
-reg [7:0]   tx_pid_r;
-
-always @ *
-begin
-    tx_valid_r = 1'b0;
-    tx_pid_r   = 8'b0;
-
-    case (state_q)
-    //-----------------------------------------
-    // IDLE
-    //-----------------------------------------
-    STATE_RX_IDLE :
-    begin
-        // Token received (OUT, IN, SETUP, PING)
-        if (token_valid_w)
-        begin
-            //-------------------------------
-            // IN transfer (device -> host)
-            //-------------------------------
-            if (token_pid_w == `PID_IN)
-            begin
-                // Stalled endpoint?
-                if (ep_stall_r)
-                begin
-                    tx_valid_r = 1'b1;
-                    tx_pid_r   = `PID_STALL;
-                end
-                // Some data to TX?
-                else if (tx_ready_r)
-                begin
-                    tx_valid_r = 1'b1;
-                    // TODO: Handle MDATA for ISOs
-                    tx_pid_r   = in_data_bit_r ? `PID_DATA1 : `PID_DATA0;
-                end
-                // No data to TX
-                else
-                begin
-                    tx_valid_r = 1'b1;
-                    tx_pid_r   = `PID_NAK;
-                end
-            end
-            //-------------------------------
-            // PING transfer (device -> host)
-            //-------------------------------
-            else if (token_pid_w == `PID_PING)
-            begin
-                // Stalled endpoint?
-                if (ep_stall_r)
-                begin
-                    tx_valid_r = 1'b1;
-                    tx_pid_r   = `PID_STALL;
-                end
-                // Data ready to RX
-                else if (rx_space_r)
-                begin
-                    tx_valid_r = 1'b1;
-                    tx_pid_r   = `PID_ACK;
-                end
-                // No data to TX
-                else
-                begin
-                    tx_valid_r = 1'b1;
-                    tx_pid_r   = `PID_NAK;
-                end
-            end
-        end
-    end
-
-    //-----------------------------------------
-    // RX_DATA_READY
-    //-----------------------------------------
-    STATE_RX_DATA_READY :
-    begin
-       // Receive complete
-       if (rx_data_complete_w)
-       begin
-            // No response on CRC16 error
-            if (rx_crc_err_o)
-                ;
-            // ISO endpoint, no response?
-            else if (ep_iso_r)
-                ;
-            // Send STALL?
-            else if (ep_stall_r)
-            begin
-                tx_valid_r = 1'b1;
-                tx_pid_r   = `PID_STALL;
-            end
-            // DATAx bit mismatch
-            else if ( (token_pid_w == `PID_DATA0 && out_data_bit_r) ||
-                      (token_pid_w == `PID_DATA1 && !out_data_bit_r) )
-            begin
-                // Ack transfer to resync
-                tx_valid_r = 1'b1;
-                tx_pid_r   = `PID_ACK;
-            end
-            // Send NAK
-            else if (!rx_space_q)
-            begin
-                tx_valid_r = 1'b1;
-                tx_pid_r   = `PID_NAK;
-            end
-            // TODO: USB 2.0, no more buffer space, return NYET
-            else
-            begin
-                tx_valid_r = 1'b1;
-                tx_pid_r   = `PID_ACK;
-            end
-       end
-    end
-
-    //-----------------------------------------
-    // TX_CHIRP
-    //-----------------------------------------
-    STATE_TX_CHIRP :
-    begin
-        tx_valid_r = 1'b1;
-        tx_pid_r   = 8'b0;
-    end
-
-    default :
-       ;
-
-    endcase
-end
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    tx_valid_q <= 1'b0;
-else if (!tx_valid_q || tx_accept_w)
-    tx_valid_q <= tx_valid_r;
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    tx_pid_q <= 8'b0;
-else if (!tx_valid_q || tx_accept_w)
-    tx_pid_q <= tx_pid_r;
-
-//-----------------------------------------------------------------
-// Receive enable
-//-----------------------------------------------------------------
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    rx_enable_q <= 1'b0;
-else if (usb_rst_w ||reg_chirp_en_i)
-    rx_enable_q <= 1'b0;
-else
-    rx_enable_q <= (state_q == STATE_RX_DATA);
-
-//-----------------------------------------------------------------
-// Receive SETUP: Pulse on SETUP packet receive
-//-----------------------------------------------------------------
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    rx_setup_q <= 1'b0;
-else if (usb_rst_w ||reg_chirp_en_i)
-    rx_setup_q <= 1'b0;
-else if ((state_q == STATE_RX_IDLE) && token_valid_w && (token_pid_w == `PID_SETUP) && (token_ep_w == 4'd0))
-    rx_setup_q <= 1'b1;
-else
-    rx_setup_q <= 1'b0;
-
-//-----------------------------------------------------------------
-// Set Address
-//-----------------------------------------------------------------
-reg addr_update_pending_q;
-
-wire ep0_tx_zlp_w = ep0_tx_data_valid_i && (ep0_tx_data_strb_i == 1'b0) && 
-                    ep0_tx_data_last_i && ep0_tx_data_accept_o;
-
-reg sent_status_zlp_q;
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    sent_status_zlp_q   <= 1'b0;
-else if (usb_rst_w)
-    sent_status_zlp_q   <= 1'b0;
-else if (ep0_tx_zlp_w)
-    sent_status_zlp_q   <= 1'b1;
-else if (rx_handshake_w)
-    sent_status_zlp_q   <= 1'b0;
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    addr_update_pending_q   <= 1'b0;
-else if ((sent_status_zlp_q && addr_update_pending_q && rx_handshake_w && token_pid_w == `PID_ACK) || usb_rst_w)
-    addr_update_pending_q   <= 1'b0;
-// TODO: Use write strobe
-else if (reg_dev_addr_i != current_addr_q)
-    addr_update_pending_q   <= 1'b1;
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    current_addr_q  <= `USB_DEV_W'b0;
-else if (usb_rst_w)
-    current_addr_q  <= `USB_DEV_W'b0;
-else if (sent_status_zlp_q && addr_update_pending_q && rx_handshake_w && token_pid_w == `PID_ACK)
-    current_addr_q  <= reg_dev_addr_i;
-
-//-----------------------------------------------------------------
-// Endpoint data bit toggle
-//-----------------------------------------------------------------
-reg new_out_bit_r;
-reg new_in_bit_r;
-
-always @ *
-begin
-    new_out_bit_r = out_data_bit_r;
-    new_in_bit_r  = in_data_bit_r;
-
-    case (state_q)
-    //-----------------------------------------
-    // RX_DATA_READY
-    //-----------------------------------------
-    STATE_RX_DATA_READY :
-    begin
-       // Receive complete
-       if (rx_data_complete_w)
-       begin
-            // No toggle on CRC16 error
-            if (rx_crc_err_o)
-                ;
-            // ISO endpoint, no response?
-            else if (ep_iso_r)
-                ; // TODO: HS handling
-            // STALL?
-            else if (ep_stall_r)
-                ;
-            // DATAx bit mismatch
-            else if ( (token_pid_w == `PID_DATA0 && out_data_bit_r) ||
-                      (token_pid_w == `PID_DATA1 && !out_data_bit_r) )
-                ;
-            // NAKd
-            else if (!rx_space_q)
-                ;
-            // Data accepted - toggle data bit
-            else
-                new_out_bit_r = !out_data_bit_r;
-       end
-    end
-    //-----------------------------------------
-    // RX_IDLE
-    //-----------------------------------------
-    STATE_RX_IDLE :
-    begin
-        // Token received (OUT, IN, SETUP, PING)
-        if (token_valid_w)
-        begin
-            // SETUP packets always start with DATA0
-            if (token_pid_w == `PID_SETUP)
-            begin
-                new_out_bit_r = 1'b0;
-                new_in_bit_r  = 1'b1;
-            end
-        end
-        // ACK received
-        else if (rx_handshake_w && token_pid_w == `PID_ACK)
-        begin
-            new_in_bit_r = !in_data_bit_r;
-        end
-    end
-    default:
-        ;
-    endcase
-end
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-begin
-    ep0_out_data_bit_q <= 1'b0;
-    ep0_in_data_bit_q  <= 1'b0;
-end
-else if (usb_rst_w)
-begin
-    ep0_out_data_bit_q <= 1'b0;
-    ep0_in_data_bit_q  <= 1'b0;
-end
-else if (token_ep_w == 4'd0)
-begin
-    ep0_out_data_bit_q <= new_out_bit_r;
-    ep0_in_data_bit_q  <= new_in_bit_r;
-end
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-begin
-    ep1_out_data_bit_q <= 1'b0;
-    ep1_in_data_bit_q  <= 1'b0;
-end
-else if (usb_rst_w)
-begin
-    ep1_out_data_bit_q <= 1'b0;
-    ep1_in_data_bit_q  <= 1'b0;
-end
-else if (token_ep_w == 4'd1)
-begin
-    ep1_out_data_bit_q <= new_out_bit_r;
-    ep1_in_data_bit_q  <= new_in_bit_r;
-end
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-begin
-    ep2_out_data_bit_q <= 1'b0;
-    ep2_in_data_bit_q  <= 1'b0;
-end
-else if (usb_rst_w)
-begin
-    ep2_out_data_bit_q <= 1'b0;
-    ep2_in_data_bit_q  <= 1'b0;
-end
-else if (token_ep_w == 4'd2)
-begin
-    ep2_out_data_bit_q <= new_out_bit_r;
-    ep2_in_data_bit_q  <= new_in_bit_r;
-end
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-begin
-    ep3_out_data_bit_q <= 1'b0;
-    ep3_in_data_bit_q  <= 1'b0;
-end
-else if (usb_rst_w)
-begin
-    ep3_out_data_bit_q <= 1'b0;
-    ep3_in_data_bit_q  <= 1'b0;
-end
-else if (token_ep_w == 4'd3)
-begin
-    ep3_out_data_bit_q <= new_out_bit_r;
-    ep3_in_data_bit_q  <= new_in_bit_r;
-end
-
-//-----------------------------------------------------------------
-// Reset event
-//-----------------------------------------------------------------
-reg rst_event_q;
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    rst_event_q <= 1'b0;
-else if (usb_rst_w)
-    rst_event_q <= 1'b1;
-else if (reg_sts_rst_clr_i)
-    rst_event_q <= 1'b0;
-
-assign reg_sts_rst_o = rst_event_q;
-
-//-----------------------------------------------------------------
-// Interrupts
-//-----------------------------------------------------------------
-reg intr_q;
-
-reg cfg_int_rx_r;
-reg cfg_int_tx_r;
-
-always @ *
-begin
-    cfg_int_rx_r = 1'b0;
-    cfg_int_tx_r = 1'b0;
-
-    case (token_ep_w)
-    4'd0:
-    begin
-        cfg_int_rx_r = ep0_cfg_int_rx_i;
-        cfg_int_tx_r = ep0_cfg_int_tx_i;
-    end
-    4'd1:
-    begin
-        cfg_int_rx_r = ep1_cfg_int_rx_i;
-        cfg_int_tx_r = ep1_cfg_int_tx_i;
-    end
-    4'd2:
-    begin
-        cfg_int_rx_r = ep2_cfg_int_rx_i;
-        cfg_int_tx_r = ep2_cfg_int_tx_i;
-    end
-    4'd3:
-    begin
-        cfg_int_rx_r = ep3_cfg_int_rx_i;
-        cfg_int_tx_r = ep3_cfg_int_tx_i;
-    end
-    default:
-        ;
-    endcase
-end
-
-always @ (posedge clk_i or posedge rst_i)
-if (rst_i)
-    intr_q <= 1'b0;
-// SOF
-else if (frame_valid_w && reg_int_en_sof_i)
-    intr_q <= 1'b1;
-// Reset event
-else if (!rst_event_q && usb_rst_w)
-    intr_q <= 1'b1;
-// Rx ready
-else if (state_q == STATE_RX_DATA_READY && rx_space_q && cfg_int_rx_r)
-    intr_q <= 1'b1;
-// Tx complete
-else if (state_q == STATE_TX_DATA_COMPLETE && cfg_int_tx_r)
-    intr_q <= 1'b1;    
-else
-    intr_q <= 1'b0;
-
-assign intr_o = intr_q;
-
-//-------------------------------------------------------------------
-// Debug
-//-------------------------------------------------------------------
-`ifdef verilator
-/* verilator lint_off WIDTH */
-reg [79:0] dbg_state;
-
-always @ *
-begin
-    dbg_state = "-";
-
-    case (state_q)
-    STATE_RX_IDLE: dbg_state = "IDLE";
-    STATE_RX_DATA: dbg_state = "RX_DATA";
-    STATE_RX_DATA_READY: dbg_state = "RX_DATA_READY";
-    STATE_RX_DATA_IGNORE: dbg_state = "RX_IGNORE";
-    STATE_TX_DATA: dbg_state = "TX_DATA";
-    STATE_TX_DATA_COMPLETE: dbg_state = "TX_DATA_COMPLETE";
-    STATE_TX_HANDSHAKE: dbg_state = "TX_HANDSHAKE";
-    STATE_TX_CHIRP: dbg_state = "CHIRP";
-    endcase
-end
-
-reg [79:0] dbg_pid;
-reg [7:0]  dbg_pid_r;
-always @ *
-begin
-    dbg_pid = "-";
-
-    if (tx_valid_q && tx_accept_w)
-        dbg_pid_r = tx_pid_q;
-    else if (token_valid_w || rx_handshake_w || rx_data_valid_w)
-        dbg_pid_r = token_pid_w;
-    else
-        dbg_pid_r = 8'b0;
-
-    case (dbg_pid_r)
-    // Token
-    `PID_OUT:
-        dbg_pid = "OUT";
-    `PID_IN:
-        dbg_pid = "IN";
-    `PID_SOF:
-        dbg_pid = "SOF";
-    `PID_SETUP:
-        dbg_pid = "SETUP";
-    `PID_PING:
-        dbg_pid = "PING";
-    // Data
-    `PID_DATA0:
-        dbg_pid = "DATA0";
-    `PID_DATA1:
-        dbg_pid = "DATA1";
-    `PID_DATA2:
-        dbg_pid = "DATA2";
-    `PID_MDATA:
-        dbg_pid = "MDATA";
-    // Handshake
-    `PID_ACK:
-        dbg_pid = "ACK";
-    `PID_NAK:
-        dbg_pid = "NAK";
-    `PID_STALL:
-        dbg_pid = "STALL";
-    `PID_NYET:
-        dbg_pid = "NYET";
-    // Special
-    `PID_PRE:
-        dbg_pid = "PRE/ERR";
-    `PID_SPLIT:
-        dbg_pid = "SPLIT";
-    default:
-        ;
-    endcase
-end
-/* verilator lint_on WIDTH */
-`endif
-
-
-endmodule

File diff suppressed because it is too large
+ 7079 - 7079
rv32/boot.mif


+ 1 - 1
rv32/system.c

@@ -73,7 +73,7 @@ void init(void)
     wait_romcopy_done();
     set_leds(5);
 
-#if DEBUG
+#if 1 // DEBUG
     con_puts("Waiting 5 s for testing...");
     udelay(5000000);
     con_putc('\n');

Some files were not shown because too many files changed in this diff