├── bench └── verilog │ ├── timescale.v │ ├── tests_lib.v │ ├── test_bench_top.v │ └── tests.v ├── rtl └── verilog │ ├── timescale.v │ ├── usb1_crc5.v │ ├── usb1_fifo2.v │ ├── usb1_crc16.v │ ├── usb1_utmi_if.v │ ├── usb1_defines.v │ ├── usb1_pa.v │ ├── usb1_rom1.v │ ├── usb1_idma.v │ ├── usb1_pl.v │ ├── usb1_pd.v │ ├── usb1_core.v │ ├── usb1_ctrl.v │ └── usb1_pe.v ├── doc ├── success_story.txt └── README.txt ├── README.md ├── LICENSE └── sim └── rtl_sim ├── bin └── Makefile └── run ├── Makefile └── waves └── waves.do /bench/verilog/timescale.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 10ps 2 | -------------------------------------------------------------------------------- /rtl/verilog/timescale.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 10ps 2 | -------------------------------------------------------------------------------- /doc/success_story.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/www-asics-ws/usb1_device/HEAD/doc/success_story.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # usb1_device 2 | USB 1.1 Device IP Core 3 | 4 | Description 5 | 6 | USB 1.1 slave/device IP core. Default configuration is 6 endpoints: 7 | 1 Control, 1 Isochronous IN, 1, Isochronous Out, 1 Bulk IN, 1 Bulk 8 | Out, 1 Interrupt IN. Includes control engine, providing full enumeration 9 | process in hardware - no external micro-controller necessary. 10 | Derived from my USB 2.0 Function IP core, except all the high speed 11 | support logic has been ripped out and the interface was changed from 12 | shared memory to FIFO based. 13 | 14 | A basic test bench is now included as well. It should be viewed 15 | as a starting point to write a more comprehensive and complete 16 | test bench. 17 | 18 | I expect the users of this core to have some fundamental USB knowledge 19 | and be familiar with the UTMI specification and with the general USB 20 | transceivers (e.g. from philips). If you are not familiar with these two 21 | you should check out www.usb.org and read up on this subject ... 22 | 23 | Features 24 | 25 | - USB 1.1 Compliant Function 26 | - Hardware enumeration support 27 | - No micro controller/CPU required 28 | - FIFO based interface 29 | - Written In Verilog 30 | - Fully Synthesisable 31 | - Tested in Hardware 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2000-2017, ASICs World Services, LTD. 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source, netlist, binary and silicon forms, with 6 | or without modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of ASICS World Services, the Authors and/or the names of 17 | its contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 | IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 28 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 29 | OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /sim/rtl_sim/bin/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: sim 3 | SHELL = /bin/sh 4 | #MS=-s 5 | 6 | ########################################################################## 7 | # 8 | # DUT Sources 9 | # 10 | ########################################################################## 11 | DUT_SRC_DIR=../../../rtl/verilog 12 | PHY_SRC_DIR=../../../../usb_phy/rtl/verilog 13 | FIFO_SRC_DIR=../../../../generic_fifos/rtl/verilog 14 | GMEM_SRC_DIR=../../../../generic_memories/rtl/verilog 15 | 16 | #_TARGETS_= $(DUT_SRC_DIR)/usb1_top.v 17 | 18 | _TARGETS_= $(DUT_SRC_DIR)/usb1_utmi_if.v \ 19 | $(DUT_SRC_DIR)/usb1_pl.v \ 20 | $(DUT_SRC_DIR)/usb1_pd.v \ 21 | $(DUT_SRC_DIR)/usb1_pa.v \ 22 | $(DUT_SRC_DIR)/usb1_pe.v \ 23 | $(DUT_SRC_DIR)/usb1_idma.v \ 24 | $(DUT_SRC_DIR)/usb1_crc5.v \ 25 | $(DUT_SRC_DIR)/usb1_crc16.v \ 26 | $(DUT_SRC_DIR)/usb1_fifo2.v \ 27 | $(DUT_SRC_DIR)/usb1_ctrl.v \ 28 | $(DUT_SRC_DIR)/usb1_rom1.v \ 29 | $(DUT_SRC_DIR)/usb1_core.v \ 30 | \ 31 | $(PHY_SRC_DIR)/usb_tx_phy.v \ 32 | $(PHY_SRC_DIR)/usb_rx_phy.v \ 33 | $(PHY_SRC_DIR)/usb_phy.v \ 34 | \ 35 | $(FIFO_SRC_DIR)/generic_fifo_sc_a.v \ 36 | \ 37 | $(GMEM_SRC_DIR)/generic_dpram.v \ 38 | \ 39 | 40 | 41 | 42 | 43 | ########################################################################## 44 | # 45 | # Test Bench Sources 46 | # 47 | ########################################################################## 48 | _TOP_=test 49 | TB_SRC_DIR=../../../bench/verilog 50 | _TB_= $(TB_SRC_DIR)/test_bench_top.v \ 51 | 52 | 53 | ########################################################################## 54 | # 55 | # Misc Variables 56 | # 57 | ########################################################################## 58 | 59 | INCDIR=+incdir+./$(DUT_SRC_DIR)/ +incdir+./$(TB_SRC_DIR)/ 60 | LOGF=-l .nclog 61 | 62 | ########################################################################## 63 | # 64 | # Make Targets 65 | # 66 | ########################################################################## 67 | 68 | simw_old: 69 | @$(MAKE) $(MS) sim ACCESS="-ACCESS +r " WAVES="-DEFINE WAVES" 70 | 71 | ss: 72 | signalscan -do waves/waves.do -waves waves/waves.trn & 73 | 74 | 75 | simw: 76 | $(MAKE) $(MS) sim ACCESS="+access+r " WAVES="+define+WAVES" 77 | 78 | sim: 79 | ncverilog -q +define+RUDIS_TB $(_TARGETS_) $(_TB_) \ 80 | $(INCDIR) $(WAVES) $(ACCESS) $(LOGF) +ncstatus \ 81 | +ncuid+`hostname` 82 | 83 | gatew: 84 | @$(MAKE) -s gate ACCESS="+access+r" WAVES="+define+WAVES" 85 | 86 | gate: 87 | ncverilog -q +define+RUDIS_TB $(_TB_) $(UMC_LIB) \ 88 | $(GATE_NETLIST) $(INCDIR) $(WAVES) $(ACCESS) \ 89 | $(LOGF) +ncstatus +ncuid+`hostname` 90 | 91 | simxl: 92 | verilog +incdir+$(DUT_SRC_DIR) +incdir+$(TB_SRC_DIR) \ 93 | +access+r +define+WAVES $(_TARGETS_) $(_TB_) 94 | 95 | clean: 96 | rm -rf ./waves/*.dsn ./waves/*.trn \ 97 | INCA_libs ncverilog.key \ 98 | ./verilog.* .nclog hal.log 99 | 100 | -------------------------------------------------------------------------------- /sim/rtl_sim/run/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: sim 3 | SHELL = /bin/sh 4 | #MS=-s 5 | 6 | ########################################################################## 7 | # 8 | # DUT Sources 9 | # 10 | ########################################################################## 11 | DUT_SRC_DIR=../../../rtl/verilog 12 | PHY_SRC_DIR=../../../../usb_phy/rtl/verilog 13 | FIFO_SRC_DIR=../../../../generic_fifos/rtl/verilog 14 | GMEM_SRC_DIR=../../../../generic_memories/rtl/verilog 15 | 16 | #_TARGETS_= $(DUT_SRC_DIR)/usb1_top.v 17 | 18 | _TARGETS_= $(DUT_SRC_DIR)/usb1_utmi_if.v \ 19 | $(DUT_SRC_DIR)/usb1_pl.v \ 20 | $(DUT_SRC_DIR)/usb1_pd.v \ 21 | $(DUT_SRC_DIR)/usb1_pa.v \ 22 | $(DUT_SRC_DIR)/usb1_pe.v \ 23 | $(DUT_SRC_DIR)/usb1_idma.v \ 24 | $(DUT_SRC_DIR)/usb1_crc5.v \ 25 | $(DUT_SRC_DIR)/usb1_crc16.v \ 26 | $(DUT_SRC_DIR)/usb1_fifo2.v \ 27 | $(DUT_SRC_DIR)/usb1_ctrl.v \ 28 | $(DUT_SRC_DIR)/usb1_rom1.v \ 29 | $(DUT_SRC_DIR)/usb1_core.v \ 30 | \ 31 | $(PHY_SRC_DIR)/usb_tx_phy.v \ 32 | $(PHY_SRC_DIR)/usb_rx_phy.v \ 33 | $(PHY_SRC_DIR)/usb_phy.v \ 34 | \ 35 | $(FIFO_SRC_DIR)/generic_fifo_sc_a.v \ 36 | \ 37 | $(GMEM_SRC_DIR)/generic_dpram.v \ 38 | \ 39 | 40 | 41 | 42 | 43 | ########################################################################## 44 | # 45 | # Test Bench Sources 46 | # 47 | ########################################################################## 48 | _TOP_=test 49 | TB_SRC_DIR=../../../bench/verilog 50 | _TB_= $(TB_SRC_DIR)/test_bench_top.v \ 51 | 52 | 53 | ########################################################################## 54 | # 55 | # Misc Variables 56 | # 57 | ########################################################################## 58 | 59 | INCDIR=+incdir+./$(DUT_SRC_DIR)/ +incdir+./$(TB_SRC_DIR)/ 60 | LOGF=-l .nclog 61 | 62 | ########################################################################## 63 | # 64 | # Make Targets 65 | # 66 | ########################################################################## 67 | 68 | simw_old: 69 | @$(MAKE) $(MS) sim ACCESS="-ACCESS +r " WAVES="-DEFINE WAVES" 70 | 71 | ss: 72 | signalscan -do waves/waves.do -waves waves/waves.trn & 73 | 74 | 75 | simw: 76 | $(MAKE) $(MS) sim ACCESS="+access+r " WAVES="+define+WAVES" 77 | 78 | sim: 79 | ncverilog -q +define+RUDIS_TB $(_TARGETS_) $(_TB_) \ 80 | $(INCDIR) $(WAVES) $(ACCESS) $(LOGF) +ncstatus \ 81 | +ncuid+`hostname` 82 | 83 | gatew: 84 | @$(MAKE) -s gate ACCESS="+access+r" WAVES="+define+WAVES" 85 | 86 | gate: 87 | ncverilog -q +define+RUDIS_TB $(_TB_) $(UMC_LIB) \ 88 | $(GATE_NETLIST) $(INCDIR) $(WAVES) $(ACCESS) \ 89 | $(LOGF) +ncstatus +ncuid+`hostname` 90 | 91 | simxl: 92 | verilog +incdir+$(DUT_SRC_DIR) +incdir+$(TB_SRC_DIR) \ 93 | +access+r +define+WAVES $(_TARGETS_) $(_TB_) 94 | 95 | clean: 96 | rm -rf ./waves/*.dsn ./waves/*.trn \ 97 | INCA_libs ncverilog.key \ 98 | ./verilog.* .nclog hal.log 99 | 100 | -------------------------------------------------------------------------------- /rtl/verilog/usb1_crc5.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// USB CRC5 Modules //// 4 | //// //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: usb1_crc5.v,v 1.1.1.1 2002-09-19 12:07:05 rudi Exp $ 42 | // 43 | // $Date: 2002-09-19 12:07:05 $ 44 | // $Revision: 1.1.1.1 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // 52 | // 53 | // 54 | // 55 | // 56 | // 57 | // 58 | 59 | `include "usb1_defines.v" 60 | 61 | /////////////////////////////////////////////////////////////////// 62 | // 63 | // CRC5 64 | // 65 | /////////////////////////////////////////////////////////////////// 66 | 67 | module usb1_crc5(crc_in, din, crc_out); 68 | input [4:0] crc_in; 69 | input [10:0] din; 70 | output [4:0] crc_out; 71 | 72 | assign crc_out[0] = din[10] ^ din[9] ^ din[6] ^ din[5] ^ din[3] ^ 73 | din[0] ^ crc_in[0] ^ crc_in[3] ^ crc_in[4]; 74 | 75 | assign crc_out[1] = din[10] ^ din[7] ^ din[6] ^ din[4] ^ din[1] ^ 76 | crc_in[0] ^ crc_in[1] ^ crc_in[4]; 77 | 78 | assign crc_out[2] = din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[6] ^ 79 | din[3] ^ din[2] ^ din[0] ^ crc_in[0] ^ crc_in[1] ^ 80 | crc_in[2] ^ crc_in[3] ^ crc_in[4]; 81 | 82 | assign crc_out[3] = din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[4] ^ din[3] ^ 83 | din[1] ^ crc_in[1] ^ crc_in[2] ^ crc_in[3] ^ crc_in[4]; 84 | 85 | assign crc_out[4] = din[10] ^ din[9] ^ din[8] ^ din[5] ^ din[4] ^ din[2] ^ 86 | crc_in[2] ^ crc_in[3] ^ crc_in[4]; 87 | 88 | endmodule 89 | 90 | -------------------------------------------------------------------------------- /rtl/verilog/usb1_fifo2.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// Fast FIFO 2 entries deep //// 4 | //// //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: usb1_fifo2.v,v 1.1.1.1 2002-09-19 12:07:31 rudi Exp $ 42 | // 43 | // $Date: 2002-09-19 12:07:31 $ 44 | // $Revision: 1.1.1.1 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // 52 | // 53 | // 54 | // 55 | // 56 | 57 | `include "timescale.v" 58 | 59 | module usb1_fifo2(clk, rst, clr, din, we, dout, re); 60 | 61 | input clk, rst; 62 | input clr; 63 | input [7:0] din; 64 | input we; 65 | output [7:0] dout; 66 | input re; 67 | 68 | 69 | //////////////////////////////////////////////////////////////////// 70 | // 71 | // Local Wires 72 | // 73 | 74 | reg [7:0] mem[0:1]; 75 | reg wp; 76 | reg rp; 77 | 78 | //////////////////////////////////////////////////////////////////// 79 | // 80 | // Misc Logic 81 | // 82 | 83 | always @(posedge clk or negedge rst) 84 | if(!rst) wp <= #1 1'h0; 85 | else 86 | if(clr) wp <= #1 1'h0; 87 | else 88 | if(we) wp <= #1 ~wp; 89 | 90 | always @(posedge clk or negedge rst) 91 | if(!rst) rp <= #1 1'h0; 92 | else 93 | if(clr) rp <= #1 1'h0; 94 | else 95 | if(re) rp <= #1 ~rp; 96 | 97 | // Fifo Output 98 | assign dout = mem[ rp ]; 99 | 100 | // Fifo Input 101 | always @(posedge clk) 102 | if(we) mem[ wp ] <= #1 din; 103 | 104 | endmodule 105 | 106 | -------------------------------------------------------------------------------- /sim/rtl_sim/run/waves/waves.do: -------------------------------------------------------------------------------- 1 | // Signalscan Version 6.8b1 2 | 3 | 4 | define noactivityindicator 5 | define analog waveform lines 6 | define add variable default overlay off 7 | define waveform window analogheight 1 8 | define terminal automatic 9 | define buttons control \ 10 | 1 opensimmulationfile \ 11 | 2 executedofile \ 12 | 3 designbrowser \ 13 | 4 waveform \ 14 | 5 source \ 15 | 6 breakpoints \ 16 | 7 definesourcessearchpath \ 17 | 8 exit \ 18 | 9 createbreakpoint \ 19 | 10 creategroup \ 20 | 11 createmarker \ 21 | 12 closesimmulationfile \ 22 | 13 renamesimmulationfile \ 23 | 14 replacesimulationfiledata \ 24 | 15 listopensimmulationfiles \ 25 | 16 savedofile 26 | define buttons waveform \ 27 | 1 replacesimulationfiledata \ 28 | 2 cut \ 29 | 3 copy \ 30 | 4 paste \ 31 | 5 delete \ 32 | 6 zoomin \ 33 | 7 zoomout \ 34 | 8 zoomoutfull \ 35 | 9 expand \ 36 | 10 createmarker \ 37 | 11 designbrowser:1 \ 38 | 12 savedofile \ 39 | 13 variableradixoctal \ 40 | 14 variableradixdecimal \ 41 | 15 variableradixhexadecimal \ 42 | 16 variableradixascii 43 | define buttons designbrowser \ 44 | 1 undo \ 45 | 2 cut \ 46 | 3 copy \ 47 | 4 paste \ 48 | 5 delete \ 49 | 6 cdupscope \ 50 | 7 getallvariables \ 51 | 8 getdeepallvariables \ 52 | 9 addvariables \ 53 | 10 addvarsandclosewindow \ 54 | 11 closewindow \ 55 | 12 scopefiltermodule \ 56 | 13 scopefiltertask \ 57 | 14 scopefilterfunction \ 58 | 15 scopefilterblock \ 59 | 16 scopefilterprimitive 60 | define buttons event \ 61 | 1 undo \ 62 | 2 cut \ 63 | 3 copy \ 64 | 4 paste \ 65 | 5 delete \ 66 | 6 move \ 67 | 7 closewindow \ 68 | 8 duplicate \ 69 | 9 defineasrisingedge \ 70 | 10 defineasfallingedge \ 71 | 11 defineasanyedge \ 72 | 12 variableradixbinary \ 73 | 13 variableradixoctal \ 74 | 14 variableradixdecimal \ 75 | 15 variableradixhexadecimal \ 76 | 16 variableradixascii 77 | define buttons source \ 78 | 1 undo \ 79 | 2 cut \ 80 | 3 copy \ 81 | 4 paste \ 82 | 5 delete \ 83 | 6 createbreakpoint \ 84 | 7 creategroup \ 85 | 8 createmarker \ 86 | 9 createevent \ 87 | 10 createregisterpage \ 88 | 11 closewindow \ 89 | 12 opensimmulationfile \ 90 | 13 closesimmulationfile \ 91 | 14 renamesimmulationfile \ 92 | 15 replacesimulationfiledata \ 93 | 16 listopensimmulationfiles 94 | define buttons register \ 95 | 1 undo \ 96 | 2 cut \ 97 | 3 copy \ 98 | 4 paste \ 99 | 5 delete \ 100 | 6 createregisterpage \ 101 | 7 closewindow \ 102 | 8 continuefor \ 103 | 9 continueuntil \ 104 | 10 continueforever \ 105 | 11 stop \ 106 | 12 previous \ 107 | 13 next \ 108 | 14 variableradixbinary \ 109 | 15 variableradixhexadecimal \ 110 | 16 variableradixascii 111 | define show related transactions 112 | define exit noprompt 113 | define event search direction forward 114 | define variable fullhierarchy 115 | define variable nofilenames 116 | define variable nofullpathfilenames 117 | include bookmark with filenames 118 | include scope history without filenames 119 | define waveform window listpane 8.94 120 | define waveform window namepane 15.97 121 | define multivalueindication 122 | define pattern curpos dot 123 | define pattern cursor1 dot 124 | define pattern cursor2 dot 125 | define pattern marker dot 126 | define print designer "Rudolf Usselmann" 127 | define print border 128 | define print color blackonwhite 129 | define print command "/usr/bin/lpr -P%P" 130 | define print printer lp 131 | define print size A4 132 | define print range visible 133 | define print variable visible 134 | define rise fall time low threshold percentage 10 135 | define rise fall time high threshold percentage 90 136 | define rise fall time low value 0 137 | define rise fall time high value 3.3 138 | define sendmail command "/usr/lib/sendmail" 139 | define sequence time width 30.00 140 | define snap 141 | 142 | define source noprompt 143 | define time units default 144 | define userdefinedbussymbol 145 | define user guide directory "/usr/local/designacc/signalscan-6.5s2/doc/html" 146 | define waveform window grid off 147 | define waveform window waveheight 14 148 | define waveform window wavespace 6 149 | define web browser command netscape 150 | define zoom outfull on initial add off 151 | add group \ 152 | A \ 153 | test.rst \ 154 | test.clk \ 155 | 156 | add group \ 157 | USB \ 158 | test.tx_dn1 \ 159 | test.tx_dp1 \ 160 | test.rx_dp1 \ 161 | test.rx_dn1 \ 162 | 163 | 164 | deselect all 165 | create marker Marker1 0ns 166 | open window designbrowser 1 geometry 450 268 1020 752 167 | open window waveform 1 geometry 52 97 1540 1023 168 | zoom at 0(0)ns 0.00004911 0.00000000 169 | -------------------------------------------------------------------------------- /doc/README.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | The USB 1.1 Function IP Core 4 | ============================================ 5 | 6 | Status 7 | ------ 8 | This core is done. It was tested on a XESS XCV800 board with 9 | a Philips USB transceiver. 10 | 11 | Test Bench 12 | ---------- 13 | I have uploaded a very basic test bench. It should be viewed 14 | as a starting point to write a more comprehensive and complete 15 | test bench. 16 | 17 | Documentation 18 | ------------- 19 | Sorry, there is none. I just don't have the time to write it (yet). 20 | 21 | However, since this core is derived from my USB 2.0 Function 22 | IP core, you might find something useful in there. Main 23 | difference is that all the high speed support features have 24 | been ripped out, and the interface was changed from a shared 25 | memory model to a FIFO based model. Further there is no need 26 | for a micro-controller interface and/or register file. 27 | 28 | 29 | Here is the quick info: 30 | 31 | The core will perform all USB enumeration in hardware. Meaning 32 | it will automatically respond to the hosts SETUP packets and 33 | send back appropriate information (which you must enter in to 34 | the ROM). The enumeration process is usually very simple. The 35 | host first requests a device Descriptor, which tells the host 36 | some basic information about the device. Then it gets the 37 | configuration descriptor, which descries the entire configuration 38 | including all interfaces and endpoints. In this implementation 39 | no descriptor may be larger than 64 bytes. 40 | 41 | I have created anew top level since last check-in. Here is the 42 | hierarchical view of the USB core: 43 | 44 | usb1_core 45 | | 46 | +-- usb_phy 47 | | | 48 | | +-- usb_tx_phy 49 | | | 50 | | +-- usb_rx_phy 51 | | 52 | +-- usb1_utmi_if 53 | | 54 | +-- usb1_pl 55 | | | 56 | | +-- usb1_pd 57 | | | 58 | | +-- usb1_pa 59 | | | 60 | | +-- usb1_idma 61 | | | 62 | | +-- usb1_pe 63 | | 64 | +-- usb1_ctrl 65 | | 66 | +-- usb1_rom1 67 | | 68 | +-- 2x generic_fifo_sc_a 69 | | 70 | +-- generic_dpram 71 | 72 | The following files have been removed and are no longer needed: 73 | usb1_top.v 74 | usb1_ep_in.v 75 | usb1_ep_out.v 76 | usb1_ep.v 77 | usb1_fifo.v 78 | 79 | This new release is a more generic and user friendly version of the 80 | first release. You can now easy configure the endpoints and other 81 | features. FIFOs are external to the core, you can chose the fifo 82 | that best fits you from the "generfic_fifos" projects at OpenCores. 83 | This includes choosing a dual clock fifo if you need to. 84 | 85 | The new top level (usb1_core.v) has now a brief description of the 86 | IO signals. Hopefully that description and the test bench will be 87 | sufficient to get you started. 88 | 89 | Also remember that you MUST edit the ROM to properly configure the 90 | settings for your implementation and enter proper vendor IDs, etc. 91 | 92 | I will try to write a more complete documentation as I get the time. 93 | 94 | Misc 95 | ---- 96 | The USB 1.1 Function Project Page is: 97 | http://www.opencores.org/cores/usb1_funct/ 98 | 99 | To find out more about me (Rudolf Usselmann), please visit: 100 | http://www.asics.ws 101 | 102 | Directory Structure 103 | ------------------- 104 | [core_root] 105 | | 106 | +-doc Documentation 107 | | 108 | +-bench--+ Test Bench 109 | | +-verilog Verilog Sources 110 | | +-vhdl VHDL Sources 111 | | 112 | +-rtl----+ Core RTL Sources 113 | | +-verilog Verilog Sources 114 | | +-vhdl VHDL Sources 115 | | 116 | +-sim----+ 117 | | +-rtl_sim---+ Functional verification Directory 118 | | | +-bin Makefiles/Run Scripts 119 | | | +-run Working Directory 120 | | | 121 | | +-gate_sim--+ Functional & Timing Gate Level 122 | | | Verification Directory 123 | | +-bin Makefiles/Run Scripts 124 | | +-run Working Directory 125 | | 126 | +-lint--+ Lint Directory Tree 127 | | +-bin Makefiles/Run Scripts 128 | | +-run Working Directory 129 | | +-log Linter log & result files 130 | | 131 | +-syn---+ Synthesis Directory Tree 132 | | +-bin Synthesis Scripts 133 | | +-run Working Directory 134 | | +-log Synthesis log files 135 | | +-out Synthesis Output 136 | -------------------------------------------------------------------------------- /rtl/verilog/usb1_crc16.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// USB CRC16 Modules //// 4 | //// //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: usb1_crc16.v,v 1.1.1.1 2002-09-19 12:07:39 rudi Exp $ 42 | // 43 | // $Date: 2002-09-19 12:07:39 $ 44 | // $Revision: 1.1.1.1 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // 52 | // 53 | // 54 | // 55 | // 56 | // 57 | // 58 | 59 | `include "usb1_defines.v" 60 | 61 | /////////////////////////////////////////////////////////////////// 62 | // 63 | // CRC16 64 | // 65 | /////////////////////////////////////////////////////////////////// 66 | 67 | module usb1_crc16(crc_in, din, crc_out); 68 | input [15:0] crc_in; 69 | input [7:0] din; 70 | output [15:0] crc_out; 71 | 72 | assign crc_out[0] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ 73 | din[2] ^ din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9] ^ 74 | crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^ 75 | crc_in[14] ^ crc_in[15]; 76 | assign crc_out[1] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^ 77 | din[1] ^ crc_in[9] ^ crc_in[10] ^ crc_in[11] ^ 78 | crc_in[12] ^ crc_in[13] ^ crc_in[14] ^ crc_in[15]; 79 | assign crc_out[2] = din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9]; 80 | assign crc_out[3] = din[2] ^ din[1] ^ crc_in[9] ^ crc_in[10]; 81 | assign crc_out[4] = din[3] ^ din[2] ^ crc_in[10] ^ crc_in[11]; 82 | assign crc_out[5] = din[4] ^ din[3] ^ crc_in[11] ^ crc_in[12]; 83 | assign crc_out[6] = din[5] ^ din[4] ^ crc_in[12] ^ crc_in[13]; 84 | assign crc_out[7] = din[6] ^ din[5] ^ crc_in[13] ^ crc_in[14]; 85 | assign crc_out[8] = din[7] ^ din[6] ^ crc_in[0] ^ crc_in[14] ^ crc_in[15]; 86 | assign crc_out[9] = din[7] ^ crc_in[1] ^ crc_in[15]; 87 | assign crc_out[10] = crc_in[2]; 88 | assign crc_out[11] = crc_in[3]; 89 | assign crc_out[12] = crc_in[4]; 90 | assign crc_out[13] = crc_in[5]; 91 | assign crc_out[14] = crc_in[6]; 92 | assign crc_out[15] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^ 93 | din[1] ^ din[0] ^ crc_in[7] ^ crc_in[8] ^ crc_in[9] ^ 94 | crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^ 95 | crc_in[14] ^ crc_in[15]; 96 | 97 | endmodule 98 | 99 | -------------------------------------------------------------------------------- /rtl/verilog/usb1_utmi_if.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// UTMI Interface //// 4 | //// //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: usb1_utmi_if.v,v 1.1.1.1 2002-09-19 12:07:14 rudi Exp $ 42 | // 43 | // $Date: 2002-09-19 12:07:14 $ 44 | // $Revision: 1.1.1.1 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // 52 | // 53 | // 54 | // 55 | // 56 | // 57 | // 58 | 59 | `include "usb1_defines.v" 60 | 61 | module usb1_utmi_if( // UTMI Interface (EXTERNAL) 62 | phy_clk, rst, 63 | DataOut, TxValid, TxReady, 64 | RxValid, RxActive, RxError, DataIn, 65 | 66 | // Internal Interface 67 | rx_data, rx_valid, rx_active, rx_err, 68 | tx_data, tx_valid, tx_valid_last, tx_ready, 69 | tx_first 70 | 71 | ); 72 | 73 | input phy_clk; 74 | input rst; 75 | 76 | output [7:0] DataOut; 77 | output TxValid; 78 | input TxReady; 79 | 80 | input [7:0] DataIn; 81 | input RxValid; 82 | input RxActive; 83 | input RxError; 84 | 85 | 86 | output [7:0] rx_data; 87 | output rx_valid, rx_active, rx_err; 88 | input [7:0] tx_data; 89 | input tx_valid; 90 | input tx_valid_last; 91 | output tx_ready; 92 | input tx_first; 93 | 94 | /////////////////////////////////////////////////////////////////// 95 | // 96 | // Local Wires and Registers 97 | // 98 | reg [7:0] rx_data; 99 | reg rx_valid, rx_active, rx_err; 100 | reg [7:0] DataOut; 101 | reg tx_ready; 102 | reg TxValid; 103 | 104 | /////////////////////////////////////////////////////////////////// 105 | // 106 | // Misc Logic 107 | // 108 | 109 | 110 | /////////////////////////////////////////////////////////////////// 111 | // 112 | // RX Interface Input registers 113 | // 114 | 115 | always @(posedge phy_clk or negedge rst) 116 | if(!rst) rx_valid <= #1 1'b0; 117 | else rx_valid <= #1 RxValid; 118 | 119 | always @(posedge phy_clk or negedge rst) 120 | if(!rst) rx_active <= #1 1'b0; 121 | else rx_active <= #1 RxActive; 122 | 123 | always @(posedge phy_clk or negedge rst) 124 | if(!rst) rx_err <= #1 1'b0; 125 | else rx_err <= #1 RxError; 126 | 127 | always @(posedge phy_clk) 128 | rx_data <= #1 DataIn; 129 | 130 | /////////////////////////////////////////////////////////////////// 131 | // 132 | // TX Interface Output/Input registers 133 | // 134 | 135 | always @(posedge phy_clk) 136 | if(TxReady | tx_first) DataOut <= #1 tx_data; 137 | 138 | always @(posedge phy_clk) 139 | tx_ready <= #1 TxReady; 140 | 141 | always @(posedge phy_clk or negedge rst) 142 | if(!rst) TxValid <= #1 1'b0; 143 | else 144 | TxValid <= #1 tx_valid | tx_valid_last | (TxValid & !TxReady); 145 | 146 | endmodule 147 | 148 | -------------------------------------------------------------------------------- /rtl/verilog/usb1_defines.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// USB 1.1 function defines file //// 4 | //// //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: usb1_defines.v,v 1.3 2002-09-25 06:06:49 rudi Exp $ 42 | // 43 | // $Date: 2002-09-25 06:06:49 $ 44 | // $Revision: 1.3 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // Revision 1.2 2002/09/20 11:46:54 rudi 52 | // fixed a type 'define' was missing ... 53 | // 54 | // Revision 1.1.1.1 2002/09/19 12:07:40 rudi 55 | // Initial Checkin 56 | // 57 | // 58 | // 59 | // 60 | // 61 | // 62 | // 63 | // 64 | 65 | `include "timescale.v" 66 | 67 | //`define USBF_DEBUG 68 | //`define USBF_VERBOSE_DEBUG 69 | 70 | // Enable or disable Block Frames 71 | //`define USB1_BF_ENABLE 72 | 73 | ///////////////////////////////////////////////////////////////////// 74 | // 75 | // Items below this point should NOT be modified by the end user 76 | // UNLESS you know exactly what you are doing ! 77 | // Modify at you own risk !!! 78 | // 79 | ///////////////////////////////////////////////////////////////////// 80 | 81 | `define ROM_SIZE0 7'd018 // Device Descriptor Length 82 | `define ROM_SIZE1 7'd053 // Configuration Descriptor Length 83 | `define ROM_SIZE2A 7'd004 // Language ID Descriptor Start Length 84 | `define ROM_SIZE2B 7'd010 // String Descriptor Length 85 | `define ROM_SIZE2C 7'd010 // for future use 86 | `define ROM_SIZE2D 7'd010 // for future use 87 | 88 | `define ROM_START0 7'h00 // Device Descriptor Start Address 89 | `define ROM_START1 7'h12 // Configuration Descriptor Start Address 90 | `define ROM_START2A 7'h47 // Language ID Descriptor Start Address 91 | `define ROM_START2B 7'h50 // String Descriptor Start Address 92 | `define ROM_START2C 7'h60 // for future use 93 | `define ROM_START2D 7'h70 // for future use 94 | 95 | // Endpoint Configuration Constants 96 | `define IN 14'b00_001_000000000 97 | `define OUT 14'b00_010_000000000 98 | `define CTRL 14'b10_100_000000000 99 | `define ISO 14'b01_000_000000000 100 | `define BULK 14'b10_000_000000000 101 | `define INT 14'b00_000_000000000 102 | 103 | // PID Encodings 104 | `define USBF_T_PID_OUT 4'b0001 105 | `define USBF_T_PID_IN 4'b1001 106 | `define USBF_T_PID_SOF 4'b0101 107 | `define USBF_T_PID_SETUP 4'b1101 108 | `define USBF_T_PID_DATA0 4'b0011 109 | `define USBF_T_PID_DATA1 4'b1011 110 | `define USBF_T_PID_DATA2 4'b0111 111 | `define USBF_T_PID_MDATA 4'b1111 112 | `define USBF_T_PID_ACK 4'b0010 113 | `define USBF_T_PID_NACK 4'b1010 114 | `define USBF_T_PID_STALL 4'b1110 115 | `define USBF_T_PID_NYET 4'b0110 116 | `define USBF_T_PID_PRE 4'b1100 117 | `define USBF_T_PID_ERR 4'b1100 118 | `define USBF_T_PID_SPLIT 4'b1000 119 | `define USBF_T_PID_PING 4'b0100 120 | `define USBF_T_PID_RES 4'b0000 121 | 122 | // The HMS_DEL is a constant for the "Half Micro Second" 123 | // Clock pulse generator. This constant specifies how many 124 | // Phy clocks there are between two hms_clock pulses. This 125 | // constant plus 2 represents the actual delay. 126 | // Example: For a 60 Mhz (16.667 nS period) Phy Clock, the 127 | // delay must be 30 phy clock: 500ns / 16.667nS = 30 clocks 128 | `define USBF_HMS_DEL 5'h16 129 | 130 | // After sending Data in response to an IN token from host, the 131 | // host must reply with an ack. The host has 622nS in Full Speed 132 | // mode and 400nS in High Speed mode to reply. RX_ACK_TO_VAL_FS 133 | // and RX_ACK_TO_VAL_HS are the numbers of UTMI clock cycles 134 | // minus 2 for Full and High Speed modes. 135 | //`define USBF_RX_ACK_TO_VAL_FS 8'd36 136 | `define USBF_RX_ACK_TO_VAL_FS 8'd200 137 | 138 | // After sending a OUT token the host must send a data packet. 139 | // The host has 622nS in Full Speed mode and 400nS in High Speed 140 | // mode to send the data packet. 141 | // TX_DATA_TO_VAL_FS and TX_DATA_TO_VAL_HS are is the numbers of 142 | // UTMI clock cycles minus 2. 143 | //`define USBF_TX_DATA_TO_VAL_FS 8'd36 144 | `define USBF_TX_DATA_TO_VAL_FS 8'd200 145 | -------------------------------------------------------------------------------- /rtl/verilog/usb1_pa.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// Packet Assembler //// 4 | //// Assembles Token and Data USB packets //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: usb1_pa.v,v 1.1.1.1 2002-09-19 12:07:13 rudi Exp $ 42 | // 43 | // $Date: 2002-09-19 12:07:13 $ 44 | // $Revision: 1.1.1.1 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // 52 | // 53 | // 54 | // 55 | // 56 | // 57 | 58 | `include "usb1_defines.v" 59 | 60 | module usb1_pa( clk, rst, 61 | 62 | // UTMI TX I/F 63 | tx_data, tx_valid, tx_valid_last, tx_ready, 64 | tx_first, 65 | 66 | // Protocol Engine Interface 67 | send_token, token_pid_sel, 68 | send_data, data_pid_sel, 69 | 70 | // IDMA Interface 71 | tx_data_st, rd_next, 72 | 73 | ep_empty 74 | ); 75 | 76 | input clk, rst; 77 | 78 | // UTMI TX Interface 79 | output [7:0] tx_data; 80 | output tx_valid; 81 | output tx_valid_last; 82 | input tx_ready; 83 | output tx_first; 84 | 85 | // Protocol Engine Interface 86 | input send_token; 87 | input [1:0] token_pid_sel; 88 | input send_data; 89 | input [1:0] data_pid_sel; 90 | 91 | // IDMA Interface 92 | input [7:0] tx_data_st; 93 | output rd_next; 94 | 95 | input ep_empty; 96 | 97 | /////////////////////////////////////////////////////////////////// 98 | // 99 | // Local Wires and Registers 100 | // 101 | 102 | parameter [3:0] // synopsys enum state 103 | IDLE = 4'b0001, 104 | DATA = 4'b0010, 105 | CRC1 = 4'b0100, 106 | CRC2 = 4'b1000; 107 | 108 | reg [3:0] /* synopsys enum state */ state, next_state; 109 | // synopsys state_vector state 110 | 111 | reg last; 112 | reg rd_next; 113 | 114 | reg [7:0] token_pid, data_pid; // PIDs from selectors 115 | reg [7:0] tx_data_d; 116 | reg [7:0] tx_data_data; 117 | reg dsel; 118 | reg tx_valid_d; 119 | reg send_token_r; 120 | reg [7:0] tx_spec_data; 121 | reg crc_sel1, crc_sel2; 122 | reg tx_first_r; 123 | reg send_data_r; 124 | wire crc16_clr; 125 | reg [15:0] crc16; 126 | wire [15:0] crc16_next; 127 | wire [15:0] crc16_rev; 128 | reg crc16_add; 129 | reg send_data_r2; 130 | reg tx_valid_r; 131 | reg tx_valid_r1; 132 | 133 | wire zero_length; 134 | 135 | /////////////////////////////////////////////////////////////////// 136 | // 137 | // Misc Logic 138 | // 139 | reg zero_length_r; 140 | assign zero_length = ep_empty; 141 | 142 | always @(posedge clk or negedge rst) 143 | if(!rst) zero_length_r <= #1 1'b0; 144 | else 145 | if(last) zero_length_r <= #1 1'b0; 146 | else 147 | if(crc16_clr) zero_length_r <= #1 zero_length; 148 | 149 | always @(posedge clk) 150 | tx_valid_r1 <= #1 tx_valid; 151 | 152 | always @(posedge clk) 153 | tx_valid_r <= #1 tx_valid_r1; 154 | 155 | always @(posedge clk or negedge rst) 156 | if(!rst) send_token_r <= #1 1'b0; 157 | else 158 | if(send_token) send_token_r <= #1 1'b1; 159 | else 160 | if(tx_ready) send_token_r <= #1 1'b0; 161 | 162 | // PID Select 163 | always @(token_pid_sel) 164 | case(token_pid_sel) // synopsys full_case parallel_case 165 | 2'd0: token_pid = { ~`USBF_T_PID_ACK, `USBF_T_PID_ACK}; 166 | 2'd1: token_pid = { ~`USBF_T_PID_NACK, `USBF_T_PID_NACK}; 167 | 2'd2: token_pid = {~`USBF_T_PID_STALL, `USBF_T_PID_STALL}; 168 | 2'd3: token_pid = { ~`USBF_T_PID_NYET, `USBF_T_PID_NYET}; 169 | endcase 170 | 171 | always @(data_pid_sel) 172 | case(data_pid_sel) // synopsys full_case parallel_case 173 | 2'd0: data_pid = { ~`USBF_T_PID_DATA0, `USBF_T_PID_DATA0}; 174 | 2'd1: data_pid = { ~`USBF_T_PID_DATA1, `USBF_T_PID_DATA1}; 175 | 2'd2: data_pid = { ~`USBF_T_PID_DATA2, `USBF_T_PID_DATA2}; 176 | 2'd3: data_pid = { ~`USBF_T_PID_MDATA, `USBF_T_PID_MDATA}; 177 | endcase 178 | 179 | // Data path Muxes 180 | 181 | always @(send_token or send_token_r or token_pid or tx_data_data) 182 | if(send_token | send_token_r) tx_data_d = token_pid; 183 | else tx_data_d = tx_data_data; 184 | 185 | always @(dsel or tx_data_st or tx_spec_data) 186 | if(dsel) tx_data_data = tx_spec_data; 187 | else tx_data_data = tx_data_st; 188 | 189 | always @(crc_sel1 or crc_sel2 or data_pid or crc16_rev) 190 | if(!crc_sel1 & !crc_sel2) tx_spec_data = data_pid; 191 | else 192 | if(crc_sel1) tx_spec_data = crc16_rev[15:8]; // CRC 1 193 | else tx_spec_data = crc16_rev[7:0]; // CRC 2 194 | 195 | assign tx_data = tx_data_d; 196 | 197 | // TX Valid assignment 198 | assign tx_valid_last = send_token | last; 199 | assign tx_valid = tx_valid_d; 200 | 201 | always @(posedge clk) 202 | tx_first_r <= #1 send_token | send_data; 203 | 204 | assign tx_first = (send_token | send_data) & ! tx_first_r; 205 | 206 | // CRC Logic 207 | always @(posedge clk) 208 | send_data_r <= #1 send_data; 209 | 210 | always @(posedge clk) 211 | send_data_r2 <= #1 send_data_r; 212 | 213 | assign crc16_clr = send_data & !send_data_r; 214 | 215 | always @(posedge clk) 216 | crc16_add <= #1 !zero_length_r & 217 | ((send_data_r & !send_data_r2) | (rd_next & !crc_sel1)); 218 | 219 | always @(posedge clk) 220 | if(crc16_clr) crc16 <= #1 16'hffff; 221 | else 222 | if(crc16_add) crc16 <= #1 crc16_next; 223 | 224 | usb1_crc16 u1( 225 | .crc_in( crc16 ), 226 | .din( {tx_data_st[0], tx_data_st[1], 227 | tx_data_st[2], tx_data_st[3], 228 | tx_data_st[4], tx_data_st[5], 229 | tx_data_st[6], tx_data_st[7]} ), 230 | .crc_out( crc16_next ) ); 231 | 232 | assign crc16_rev[15] = ~crc16[8]; 233 | assign crc16_rev[14] = ~crc16[9]; 234 | assign crc16_rev[13] = ~crc16[10]; 235 | assign crc16_rev[12] = ~crc16[11]; 236 | assign crc16_rev[11] = ~crc16[12]; 237 | assign crc16_rev[10] = ~crc16[13]; 238 | assign crc16_rev[9] = ~crc16[14]; 239 | assign crc16_rev[8] = ~crc16[15]; 240 | assign crc16_rev[7] = ~crc16[0]; 241 | assign crc16_rev[6] = ~crc16[1]; 242 | assign crc16_rev[5] = ~crc16[2]; 243 | assign crc16_rev[4] = ~crc16[3]; 244 | assign crc16_rev[3] = ~crc16[4]; 245 | assign crc16_rev[2] = ~crc16[5]; 246 | assign crc16_rev[1] = ~crc16[6]; 247 | assign crc16_rev[0] = ~crc16[7]; 248 | 249 | /////////////////////////////////////////////////////////////////// 250 | // 251 | // Transmit/Encode state machine 252 | // 253 | 254 | always @(posedge clk or negedge rst) 255 | if(!rst) state <= #1 IDLE; 256 | else state <= #1 next_state; 257 | 258 | always @(state or send_data or tx_ready or tx_valid_r or zero_length) 259 | begin 260 | next_state = state; // Default don't change current state 261 | tx_valid_d = 1'b0; 262 | dsel = 1'b0; 263 | rd_next = 1'b0; 264 | last = 1'b0; 265 | crc_sel1 = 1'b0; 266 | crc_sel2 = 1'b0; 267 | case(state) // synopsys full_case parallel_case 268 | IDLE: 269 | begin 270 | if(zero_length & send_data) 271 | begin 272 | tx_valid_d = 1'b1; 273 | dsel = 1'b1; 274 | next_state = CRC1; 275 | end 276 | else 277 | if(send_data) // Send DATA packet 278 | begin 279 | tx_valid_d = 1'b1; 280 | dsel = 1'b1; 281 | next_state = DATA; 282 | end 283 | end 284 | DATA: 285 | begin 286 | if(tx_ready & tx_valid_r) 287 | rd_next = 1'b1; 288 | 289 | tx_valid_d = 1'b1; 290 | if(!send_data & tx_ready & tx_valid_r) 291 | begin 292 | dsel = 1'b1; 293 | crc_sel1 = 1'b1; 294 | next_state = CRC1; 295 | end 296 | end 297 | CRC1: 298 | begin 299 | dsel = 1'b1; 300 | tx_valid_d = 1'b1; 301 | if(tx_ready) 302 | begin 303 | last = 1'b1; 304 | crc_sel2 = 1'b1; 305 | next_state = CRC2; 306 | end 307 | else 308 | begin 309 | tx_valid_d = 1'b1; 310 | crc_sel1 = 1'b1; 311 | end 312 | 313 | end 314 | CRC2: 315 | begin 316 | dsel = 1'b1; 317 | crc_sel2 = 1'b1; 318 | if(tx_ready) 319 | begin 320 | next_state = IDLE; 321 | end 322 | else 323 | begin 324 | last = 1'b1; 325 | end 326 | 327 | end 328 | endcase 329 | end 330 | 331 | endmodule 332 | 333 | -------------------------------------------------------------------------------- /bench/verilog/tests_lib.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// Test Bench Library //// 4 | //// //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: tests_lib.v,v 1.1 2002-09-25 06:10:10 rudi Exp $ 42 | // 43 | // $Date: 2002-09-25 06:10:10 $ 44 | // $Revision: 1.1 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // 52 | // 53 | // 54 | // 55 | // 56 | // 57 | 58 | 59 | task show_errors; 60 | 61 | begin 62 | 63 | $display("\n"); 64 | $display(" +--------------------+"); 65 | $display(" | Total ERRORS: %0d |", error_cnt); 66 | $display(" +--------------------+"); 67 | 68 | end 69 | endtask 70 | 71 | task recv_packet; 72 | output [3:0] pid; 73 | output size; 74 | 75 | integer del, size,n; 76 | reg [15:0] crc16r; 77 | reg [7:0] x,y; 78 | 79 | begin 80 | crc16r = 16'hffff; 81 | utmi_recv_pack(size); 82 | for(n=1;n5000) 186 | begin 187 | $display("\n\n*************************************\n"); 188 | $display("ERROR: Watch Dog Counter Expired\n"); 189 | $display("*************************************\n\n\n"); 190 | $finish; 191 | end 192 | 193 | /////////////////////////////////////////////////////////////////// 194 | // 195 | // Clock generation 196 | // 197 | 198 | always #10.42 clk = ~clk; 199 | always #10.42 clk2 = ~clk2; 200 | 201 | /////////////////////////////////////////////////////////////////// 202 | // 203 | // Module Instantiations 204 | // 205 | 206 | usb_phy tb_phy(.clk( clk ), 207 | .rst( rst ), 208 | 209 | .phy_tx_mode( 1'b1 ), 210 | .usb_rst( ), 211 | 212 | .rxd( rx_dp1 ), 213 | .rxdp( rx_dp1 ), 214 | .rxdn( rx_dn1 ), 215 | 216 | .txdp( tx_dp1 ), 217 | .txdn( tx_dn1 ), 218 | .txoe( ), 219 | 220 | .DataIn_o( tb_rxdata ), 221 | .RxValid_o( tb_rx_valid ), 222 | .RxActive_o( tb_rx_active ), 223 | .RxError_o( tb_rx_error ), 224 | 225 | .DataOut_i( tb_txdata ), 226 | .TxValid_i( tb_tx_valid ), 227 | .TxReady_o( tb_tx_ready ), 228 | .LineState_o( ) 229 | ); 230 | 231 | parameter LD = 40; 232 | 233 | assign #(LD) rx_dp1 = !usb_reset & tx_dp2; 234 | assign #(LD) rx_dn1 = !usb_reset & tx_dn2; 235 | 236 | assign #(LD) rx_dp2 = !usb_reset & tx_dp1; 237 | assign #(LD) rx_dn2 = !usb_reset & tx_dn1; 238 | 239 | usb1_core u0( .clk_i( clk2 ), 240 | .rst_i( rst ), 241 | 242 | // USB Misc 243 | .phy_tx_mode( 1'b1 ), 244 | .usb_rst( ), 245 | // USB Status 246 | .usb_busy( ), 247 | .ep_sel( ), 248 | 249 | // Interrupts 250 | .dropped_frame( ), 251 | .misaligned_frame( ), 252 | .crc16_err( ), 253 | 254 | // Vendor Features 255 | .v_set_int( ), 256 | .v_set_feature( ), 257 | .wValue( ), 258 | .wIndex( ), 259 | .vendor_data( ), 260 | 261 | // USB PHY Interface 262 | .tx_dp( tx_dp2 ), 263 | .tx_dn( tx_dn2 ), 264 | .tx_oe( ), 265 | 266 | .rx_d( rx_dp2 ), 267 | .rx_dp( rx_dp2 ), 268 | .rx_dn( rx_dn2 ), 269 | 270 | // End point 1 configuration 271 | .ep1_cfg( `ISO | `IN | 14'd0256 ), 272 | // End point 1 'OUT' FIFO i/f 273 | .ep1_dout( ), 274 | .ep1_we( ), 275 | .ep1_full( 1'b0 ), 276 | // End point 1 'IN' FIFO i/f 277 | .ep1_din( ep1_us_din ), 278 | .ep1_re( ep1_us_re ), 279 | .ep1_empty( ep1_us_empty ), 280 | .ep1_bf_en( 1'b0 ), 281 | .ep1_bf_size( 7'h0 ), 282 | 283 | // End point 2 configuration 284 | .ep2_cfg( `ISO | `OUT | 14'd0256 ), 285 | // End point 2 'OUT' FIFO i/f 286 | .ep2_dout( ep2_us_dout ), 287 | .ep2_we( ep2_us_we ), 288 | .ep2_full( ep2_us_full ), 289 | // End point 2 'IN' FIFO i/f 290 | .ep2_din( 8'h0 ), 291 | .ep2_re( ), 292 | .ep2_empty( 1'b0 ), 293 | .ep2_bf_en( 1'b0 ), 294 | .ep2_bf_size( 7'h0 ), 295 | 296 | // End point 3 configuration 297 | .ep3_cfg( `BULK | `IN | 14'd064 ), 298 | // End point 3 'OUT' FIFO i/f 299 | .ep3_dout( ), 300 | .ep3_we( ), 301 | .ep3_full( 1'b0 ), 302 | // End point 3 'IN' FIFO i/f 303 | .ep3_din( ep3_us_din ), 304 | .ep3_re( ep3_us_re ), 305 | .ep3_empty( ep3_us_empty ), 306 | .ep3_bf_en( 1'b0 ), 307 | .ep3_bf_size( 7'h0 ), 308 | 309 | // End point 4 configuration 310 | .ep4_cfg( `BULK | `OUT | 14'd064 ), 311 | // End point 4 'OUT' FIFO i/f 312 | .ep4_dout( ep4_us_dout ), 313 | .ep4_we( ep4_us_we ), 314 | .ep4_full( ep4_us_full ), 315 | // End point 4 'IN' FIFO i/f 316 | .ep4_din( 8'h0 ), 317 | .ep4_re( ), 318 | .ep4_empty( 1'b0 ), 319 | .ep4_bf_en( 1'b0 ), 320 | .ep4_bf_size( 7'h0 ), 321 | 322 | // End point 5 configuration 323 | .ep5_cfg( `INT | `IN | 14'd064 ), 324 | // End point 5 'OUT' FIFO i/f 325 | .ep5_dout( ), 326 | .ep5_we( ), 327 | .ep5_full( 1'b0 ), 328 | // End point 5 'IN' FIFO i/f 329 | .ep5_din( ep5_us_din ), 330 | .ep5_re( ep5_us_re ), 331 | .ep5_empty( ep5_us_empty ), 332 | .ep5_bf_en( 1'b0 ), 333 | .ep5_bf_size( 7'h0 ), 334 | 335 | // End point 6 configuration 336 | .ep6_cfg( 14'h00 ), 337 | // End point 6 'OUT' FIFO i/f 338 | .ep6_dout( ), 339 | .ep6_we( ), 340 | .ep6_full( 1'b0 ), 341 | // End point 6 'IN' FIFO i/f 342 | .ep6_din( 8'h0 ), 343 | .ep6_re( ), 344 | .ep6_empty( 1'b0 ), 345 | .ep6_bf_en( 1'b0 ), 346 | .ep6_bf_size( 7'h0 ), 347 | 348 | // End point 7 configuration 349 | .ep7_cfg( 14'h00 ), 350 | // End point 7 'OUT' FIFO i/f 351 | .ep7_dout( ), 352 | .ep7_we( ), 353 | .ep7_full( 1'b0 ), 354 | // End point 7 'IN' FIFO i/f 355 | .ep7_din( 8'h0 ), 356 | .ep7_re( ), 357 | .ep7_empty( 1'b0 ), 358 | .ep7_bf_en( 1'b0 ), 359 | .ep7_bf_size( 7'h0 ) 360 | ); 361 | 362 | // EP 1 FIFO 363 | generic_fifo_sc_a #(8,9,0) 364 | f0( 365 | .clk( clk2 ), 366 | .rst( rst ), 367 | .clr( 1'b0 ), 368 | .din( ep1_f_din ), 369 | .we( ep1_f_we ), 370 | .dout( ep1_us_din ), 371 | .re( ep1_us_re ), 372 | .full( ), 373 | .empty( ), 374 | .full_r( ep1_f_full ), 375 | .empty_r( ep1_us_empty ), 376 | .full_n( ), 377 | .empty_n( ), 378 | .full_n_r( ), 379 | .empty_n_r( ), 380 | .level( ) 381 | ); 382 | 383 | // EP 2 FIFO 384 | generic_fifo_sc_a #(8,9,0) 385 | f1( 386 | .clk( clk2 ), 387 | .rst( rst ), 388 | .clr( 1'b0 ), 389 | .din( ep2_us_dout ), 390 | .we( ep2_us_we ), 391 | .dout( ep2_f_dout ), 392 | .re( ep2_f_re ), 393 | .full( ), 394 | .empty( ), 395 | .full_r( ep2_us_full ), 396 | .empty_r( ep2_f_empty ), 397 | .full_n( ), 398 | .empty_n( ), 399 | .full_n_r( ), 400 | .empty_n_r( ), 401 | .level( ) 402 | ); 403 | 404 | // EP 3 FIFO 405 | generic_fifo_sc_a #(8,9,0) 406 | f2( 407 | .clk( clk2 ), 408 | .rst( rst ), 409 | .clr( 1'b0 ), 410 | .din( ep3_f_din ), 411 | .we( ep3_f_we ), 412 | .dout( ep3_us_din ), 413 | .re( ep3_us_re ), 414 | .full( ), 415 | .empty( ), 416 | .full_r( ep3_f_full ), 417 | .empty_r( ep3_us_empty ), 418 | .full_n( ), 419 | .empty_n( ), 420 | .full_n_r( ), 421 | .empty_n_r( ), 422 | .level( ) 423 | ); 424 | 425 | // EP 4 FIFO 426 | generic_fifo_sc_a #(8,9,0) 427 | f3( 428 | .clk( clk2 ), 429 | .rst( rst ), 430 | .clr( 1'b0 ), 431 | .din( ep4_us_dout ), 432 | .we( ep4_us_we ), 433 | .dout( ep4_f_dout ), 434 | .re( ep4_f_re ), 435 | .full( ), 436 | .empty( ), 437 | .full_r( ep4_us_full ), 438 | .empty_r( ep4_f_empty ), 439 | .full_n( ), 440 | .empty_n( ), 441 | .full_n_r( ), 442 | .empty_n_r( ), 443 | .level( ) 444 | ); 445 | 446 | // EP 5 FIFO 447 | generic_fifo_sc_a #(8,6,0) 448 | f4( 449 | .clk( clk2 ), 450 | .rst( rst ), 451 | .clr( 1'b0 ), 452 | .din( ep5_f_din ), 453 | .we( ep5_f_we ), 454 | .dout( ep5_us_din ), 455 | .re( ep5_us_re ), 456 | .full( ), 457 | .empty( ), 458 | .full_r( ep5_f_full ), 459 | .empty_r( ep5_us_empty ), 460 | .full_n( ), 461 | .empty_n( ), 462 | .full_n_r( ), 463 | .empty_n_r( ), 464 | .level( ) 465 | ); 466 | 467 | /////////////////////////////////////////////////////////////////// 468 | // 469 | // Test and test lib Includes 470 | // 471 | `include "tests_lib.v" 472 | `include "tests.v" 473 | 474 | endmodule 475 | 476 | -------------------------------------------------------------------------------- /rtl/verilog/usb1_pd.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// Packet Disassembler //// 4 | //// Disassembles Token and Data USB packets //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: usb1_pd.v,v 1.2 2002-09-25 06:06:49 rudi Exp $ 42 | // 43 | // $Date: 2002-09-25 06:06:49 $ 44 | // $Revision: 1.2 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // Revision 1.1.1.1 2002/09/19 12:07:17 rudi 52 | // Initial Checkin 53 | // 54 | // 55 | // 56 | // 57 | // 58 | // 59 | // 60 | // 61 | 62 | `include "usb1_defines.v" 63 | 64 | module usb1_pd( clk, rst, 65 | 66 | // UTMI RX I/F 67 | rx_data, rx_valid, rx_active, rx_err, 68 | 69 | // PID Information 70 | pid_OUT, pid_IN, pid_SOF, pid_SETUP, 71 | pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA, 72 | pid_ACK, pid_NACK, pid_STALL, pid_NYET, 73 | pid_PRE, pid_ERR, pid_SPLIT, pid_PING, 74 | pid_cks_err, 75 | 76 | // Token Information 77 | token_fadr, token_endp, token_valid, crc5_err, 78 | frame_no, 79 | 80 | // Receive Data Output 81 | rx_data_st, rx_data_valid, rx_data_done, crc16_err, 82 | 83 | // Misc. 84 | seq_err, rx_busy 85 | ); 86 | 87 | input clk, rst; 88 | 89 | //UTMI RX Interface 90 | input [7:0] rx_data; 91 | input rx_valid, rx_active, rx_err; 92 | 93 | // Decoded PIDs (used when token_valid is asserted) 94 | output pid_OUT, pid_IN, pid_SOF, pid_SETUP; 95 | output pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; 96 | output pid_ACK, pid_NACK, pid_STALL, pid_NYET; 97 | output pid_PRE, pid_ERR, pid_SPLIT, pid_PING; 98 | output pid_cks_err; // Indicates a PID checksum error 99 | 100 | 101 | output [6:0] token_fadr; // Function address from token 102 | output [3:0] token_endp; // Endpoint number from token 103 | output token_valid; // Token is valid 104 | output crc5_err; // Token crc5 error 105 | output [10:0] frame_no; // Frame number for SOF tokens 106 | 107 | output [7:0] rx_data_st; // Data to memory store unit 108 | output rx_data_valid; // Data on rx_data_st is valid 109 | output rx_data_done; // Indicates end of a transfer 110 | output crc16_err; // Data packet CRC 16 error 111 | 112 | output seq_err; // State Machine Sequence Error 113 | output rx_busy; // Receivig Data Packet 114 | 115 | /////////////////////////////////////////////////////////////////// 116 | // 117 | // Local Wires and Registers 118 | // 119 | 120 | parameter [3:0] // synopsys enum state 121 | IDLE = 4'b0001, 122 | ACTIVE = 4'b0010, 123 | TOKEN = 4'b0100, 124 | DATA = 4'b1000; 125 | 126 | reg [3:0] /* synopsys enum state */ state, next_state; 127 | // synopsys state_vector state 128 | 129 | reg [7:0] pid; // Packet PDI 130 | reg pid_le_sm; // PID Load enable from State Machine 131 | wire pid_ld_en; // Enable loading of PID (all conditions) 132 | wire pid_cks_err; // Indicates a pid checksum err 133 | 134 | // Decoded PID values 135 | wire pid_OUT, pid_IN, pid_SOF, pid_SETUP; 136 | wire pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; 137 | wire pid_ACK, pid_NACK, pid_STALL, pid_NYET; 138 | wire pid_PRE, pid_ERR, pid_SPLIT, pid_PING, pid_RES; 139 | wire pid_TOKEN; // All TOKEN packet that we recognize 140 | wire pid_DATA; // All DATA packets that we recognize 141 | 142 | reg [7:0] token0, token1; // Token Registers 143 | reg token_le_1, token_le_2; // Latch enables for token storage registers 144 | wire [4:0] token_crc5; 145 | 146 | reg [7:0] d0, d1, d2; // Data path delay line (used to filter out crcs) 147 | reg data_valid_d; // Data Valid output from State Machine 148 | reg data_done; // Data cycle complete output from State Machine 149 | reg data_valid0; // Data valid delay line 150 | reg rxv1; 151 | reg rxv2; 152 | 153 | reg seq_err; // State machine sequence error 154 | 155 | reg pid_ack; 156 | 157 | reg token_valid_r1; 158 | reg token_valid_str1, token_valid_str2; 159 | 160 | reg rx_active_r; 161 | 162 | wire [4:0] crc5_out; 163 | wire [4:0] crc5_out2; 164 | wire crc16_clr; 165 | reg [15:0] crc16_sum; 166 | wire [15:0] crc16_out; 167 | 168 | /////////////////////////////////////////////////////////////////// 169 | // 170 | // Misc Logic 171 | // 172 | 173 | reg rx_busy, rx_busy_d; 174 | 175 | always @(posedge clk or negedge rst) 176 | if(!rst) rx_busy_d <= #1 1'b0; 177 | else 178 | if(rx_valid & (state == DATA)) rx_busy_d <= #1 1'b1; 179 | else 180 | if(state != DATA) rx_busy_d <= #1 1'b0; 181 | 182 | always @(posedge clk) 183 | rx_busy <= #1 rx_busy_d; 184 | 185 | // PID Decoding Logic 186 | assign pid_ld_en = pid_le_sm & rx_active & rx_valid; 187 | 188 | always @(posedge clk or negedge rst) 189 | if(!rst) pid <= #1 8'hf0; 190 | else 191 | if(pid_ld_en) pid <= #1 rx_data; 192 | 193 | assign pid_cks_err = (pid[3:0] != ~pid[7:4]); 194 | 195 | assign pid_OUT = pid[3:0] == `USBF_T_PID_OUT; 196 | assign pid_IN = pid[3:0] == `USBF_T_PID_IN; 197 | assign pid_SOF = pid[3:0] == `USBF_T_PID_SOF; 198 | assign pid_SETUP = pid[3:0] == `USBF_T_PID_SETUP; 199 | assign pid_DATA0 = pid[3:0] == `USBF_T_PID_DATA0; 200 | assign pid_DATA1 = pid[3:0] == `USBF_T_PID_DATA1; 201 | assign pid_DATA2 = pid[3:0] == `USBF_T_PID_DATA2; 202 | assign pid_MDATA = pid[3:0] == `USBF_T_PID_MDATA; 203 | assign pid_ACK = pid[3:0] == `USBF_T_PID_ACK; 204 | assign pid_NACK = pid[3:0] == `USBF_T_PID_NACK; 205 | assign pid_STALL = pid[3:0] == `USBF_T_PID_STALL; 206 | assign pid_NYET = pid[3:0] == `USBF_T_PID_NYET; 207 | assign pid_PRE = pid[3:0] == `USBF_T_PID_PRE; 208 | assign pid_ERR = pid[3:0] == `USBF_T_PID_ERR; 209 | assign pid_SPLIT = pid[3:0] == `USBF_T_PID_SPLIT; 210 | assign pid_PING = pid[3:0] == `USBF_T_PID_PING; 211 | assign pid_RES = pid[3:0] == `USBF_T_PID_RES; 212 | 213 | assign pid_TOKEN = pid_OUT | pid_IN | pid_SOF | pid_SETUP | pid_PING; 214 | assign pid_DATA = pid_DATA0 | pid_DATA1 | pid_DATA2 | pid_MDATA; 215 | 216 | // Token Decoding LOGIC 217 | always @(posedge clk) 218 | if(token_le_1) token0 <= #1 rx_data; 219 | 220 | always @(posedge clk) 221 | if(token_le_2) token1 <= #1 rx_data; 222 | 223 | always @(posedge clk) 224 | token_valid_r1 <= #1 token_le_2; 225 | 226 | always @(posedge clk) 227 | token_valid_str1 <= #1 token_valid_r1 | pid_ack; 228 | 229 | always @(posedge clk) 230 | token_valid_str2 <= #1 token_valid_str1; 231 | 232 | assign token_valid = token_valid_str1; 233 | 234 | // CRC 5 should perform the check in one cycle (flow through logic) 235 | // 11 bits and crc5 input, 1 bit output 236 | assign crc5_err = token_valid & (crc5_out2 != token_crc5); 237 | 238 | usb1_crc5 u0( 239 | .crc_in( 5'h1f ), 240 | .din( { token_fadr[0], 241 | token_fadr[1], 242 | token_fadr[2], 243 | token_fadr[3], 244 | token_fadr[4], 245 | token_fadr[5], 246 | token_fadr[6], 247 | token_endp[0], 248 | token_endp[1], 249 | token_endp[2], 250 | token_endp[3] } ), 251 | .crc_out( crc5_out ) ); 252 | 253 | // Invert and reverse result bits 254 | assign crc5_out2 = ~{crc5_out[0], crc5_out[1], crc5_out[2], crc5_out[3], 255 | crc5_out[4]}; 256 | 257 | assign frame_no = { token1[2:0], token0}; 258 | assign token_fadr = token0[6:0]; 259 | assign token_endp = {token1[2:0], token0[7]}; 260 | assign token_crc5 = token1[7:3]; 261 | 262 | // Data receiving logic 263 | // build a delay line and stop when we are about to get crc 264 | always @(posedge clk or negedge rst) 265 | if(!rst) rxv1 <= #1 1'b0; 266 | else 267 | if(data_valid_d) rxv1 <= #1 1'b1; 268 | else 269 | if(data_done) rxv1 <= #1 1'b0; 270 | 271 | always @(posedge clk or negedge rst) 272 | if(!rst) rxv2 <= #1 1'b0; 273 | else 274 | if(rxv1 & data_valid_d) rxv2 <= #1 1'b1; 275 | else 276 | if(data_done) rxv2 <= #1 1'b0; 277 | 278 | always @(posedge clk) 279 | data_valid0 <= #1 rxv2 & data_valid_d; 280 | 281 | always @(posedge clk) 282 | begin 283 | if(data_valid_d) d0 <= #1 rx_data; 284 | if(data_valid_d) d1 <= #1 d0; 285 | if(data_valid_d) d2 <= #1 d1; 286 | end 287 | 288 | assign rx_data_st = d2; 289 | assign rx_data_valid = data_valid0; 290 | assign rx_data_done = data_done; 291 | 292 | // crc16 accumulates rx_data as long as data_valid_d is asserted. 293 | // when data_done is asserted, crc16 reports status, and resets itself 294 | // next cycle. 295 | always @(posedge clk) 296 | rx_active_r <= #1 rx_active; 297 | 298 | assign crc16_clr = rx_active & !rx_active_r; 299 | 300 | always @(posedge clk) 301 | if(crc16_clr) crc16_sum <= #1 16'hffff; 302 | else 303 | if(data_valid_d) crc16_sum <= #1 crc16_out; 304 | 305 | usb1_crc16 u1( 306 | .crc_in( crc16_sum ), 307 | .din( {rx_data[0], rx_data[1], rx_data[2], rx_data[3], 308 | rx_data[4], rx_data[5], rx_data[6], rx_data[7]} ), 309 | .crc_out( crc16_out ) ); 310 | 311 | // Verify against polynomial 312 | assign crc16_err = data_done & (crc16_sum != 16'h800d); 313 | 314 | /////////////////////////////////////////////////////////////////// 315 | // 316 | // Receive/Decode State machine 317 | // 318 | 319 | always @(posedge clk or negedge rst) 320 | if(!rst) state <= #1 IDLE; 321 | else state <= #1 next_state; 322 | 323 | always @(state or rx_valid or rx_active or rx_err or pid_ACK or pid_TOKEN 324 | or pid_DATA) 325 | begin 326 | next_state = state; // Default don't change current state 327 | pid_le_sm = 1'b0; 328 | token_le_1 = 1'b0; 329 | token_le_2 = 1'b0; 330 | data_valid_d = 1'b0; 331 | data_done = 1'b0; 332 | seq_err = 1'b0; 333 | pid_ack = 1'b0; 334 | case(state) // synopsys full_case parallel_case 335 | IDLE: 336 | begin 337 | pid_le_sm = 1'b1; 338 | if(rx_valid & rx_active) next_state = ACTIVE; 339 | end 340 | ACTIVE: 341 | begin 342 | // Received a ACK from Host 343 | if(pid_ACK & !rx_err) 344 | begin 345 | pid_ack = 1'b1; 346 | if(!rx_active) next_state = IDLE; 347 | end 348 | else 349 | // Receiving a TOKEN 350 | if(pid_TOKEN & rx_valid & rx_active & !rx_err) 351 | begin 352 | token_le_1 = 1'b1; 353 | next_state = TOKEN; 354 | end 355 | else 356 | // Receiving DATA 357 | if(pid_DATA & rx_valid & rx_active & !rx_err) 358 | begin 359 | data_valid_d = 1'b1; 360 | next_state = DATA; 361 | end 362 | else 363 | if( !rx_active | rx_err | 364 | (rx_valid & !(pid_TOKEN | pid_DATA)) ) // ERROR 365 | begin 366 | seq_err = !rx_err; 367 | if(!rx_active) next_state = IDLE; 368 | end 369 | end 370 | TOKEN: 371 | begin 372 | if(rx_valid & rx_active & !rx_err) 373 | begin 374 | token_le_2 = 1'b1; 375 | next_state = IDLE; 376 | end 377 | else 378 | if(!rx_active | rx_err) // ERROR 379 | begin 380 | seq_err = !rx_err; 381 | if(!rx_active) next_state = IDLE; 382 | end 383 | end 384 | DATA: 385 | begin 386 | if(rx_valid & rx_active & !rx_err) data_valid_d = 1'b1; 387 | if(!rx_active | rx_err) 388 | begin 389 | data_done = 1'b1; 390 | if(!rx_active) next_state = IDLE; 391 | end 392 | end 393 | 394 | endcase 395 | end 396 | 397 | endmodule 398 | 399 | -------------------------------------------------------------------------------- /bench/verilog/tests.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// Test Case Collection //// 4 | //// //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: tests.v,v 1.1 2002-09-25 06:10:10 rudi Exp $ 42 | // 43 | // $Date: 2002-09-25 06:10:10 $ 44 | // $Revision: 1.1 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // 52 | // 53 | // 54 | // 55 | // 56 | // 57 | 58 | 59 | task send_setup; 60 | input [7:0] fa; 61 | input [7:0] req_type; 62 | input [7:0] request; 63 | input [15:0] wValue; 64 | input [15:0] wIndex; 65 | input [15:0] wLength; 66 | 67 | integer len; 68 | begin 69 | 70 | buffer1[0] = req_type; 71 | buffer1[1] = request; 72 | buffer1[3] = wValue[15:8]; 73 | buffer1[2] = wValue[7:0]; 74 | buffer1[5] = wIndex[15:8]; 75 | buffer1[4] = wIndex[7:0]; 76 | buffer1[7] = wLength[15:8]; 77 | buffer1[6] = wLength[7:0]; 78 | 79 | buffer1_last = 0; 80 | send_token( fa, // Function Address 81 | 0, // Logical Endpoint Number 82 | `USBF_T_PID_SETUP // PID 83 | ); 84 | 85 | repeat(1) @(posedge clk); 86 | 87 | send_data(`USBF_T_PID_DATA0, 8, 1); 88 | 89 | // Wait for ACK 90 | utmi_recv_pack(len); 91 | 92 | if(8'hd2 !== txmem[0]) 93 | begin 94 | $display("ERROR: SETUP: ACK mismatch. Expected: %h, Got: %h (%t)", 95 | 8'hd2, txmem[0], $time); 96 | error_cnt = error_cnt + 1; 97 | end 98 | 99 | if(len !== 1) 100 | begin 101 | $display("ERROR: SETUP: Length mismatch. Expected: %h, Got: %h (%t)", 102 | 8'h1, len, $time); 103 | error_cnt = error_cnt + 1; 104 | end 105 | 106 | repeat(1) @(posedge clk); 107 | setup_pid = 1; 108 | repeat(1) @(posedge clk); 109 | end 110 | 111 | endtask 112 | 113 | 114 | 115 | task data_in; 116 | input [7:0] fa; 117 | input [7:0] pl_size; 118 | 119 | integer rlen; 120 | reg [3:0] pid, expect_pid; 121 | begin 122 | 123 | buffer1_last = 0; 124 | repeat(5) @(posedge clk); 125 | send_token( fa, // Function Address 126 | 0, // Logical Endpoint Number 127 | `USBF_T_PID_IN // PID 128 | ); 129 | 130 | recv_packet(pid,rlen); 131 | if(setup_pid) expect_pid = 4'hb; // DATA 1 132 | else expect_pid = 4'h3; // DATA 0 133 | 134 | if(pid !== expect_pid) 135 | begin 136 | $display("ERROR: Data IN PID mismatch. Expected: %h, Got: %h (%t)", 137 | expect_pid, pid, $time); 138 | error_cnt = error_cnt + 1; 139 | end 140 | 141 | setup_pid = ~setup_pid; 142 | if(rlen != pl_size) 143 | begin 144 | $display("ERROR: Data IN Size mismatch. Expected: %d, Got: %d (%t)", 145 | pl_size, rlen, $time); 146 | error_cnt = error_cnt + 1; 147 | end 148 | 149 | for(n=0;n wLength[6:0]) ? wLength[6:0] : rom_size_dd; 254 | 255 | always @(posedge clk) 256 | rom_sel_r <= #1 rom_sel; 257 | 258 | always @(posedge clk) 259 | if(!rst) rom_adr <= #1 7'h0; 260 | else 261 | if(rom_sel & !rom_sel_r) rom_adr <= #1 rom_start_d; 262 | else 263 | if(rom_sel & !fifo_full) rom_adr <= #1 rom_adr + 7'h1; 264 | 265 | always @(posedge clk) 266 | if(!rst) rom_size <= #1 7'h0; 267 | else 268 | if(rom_sel & !rom_sel_r) rom_size <= #1 rom_size_d; 269 | else 270 | if(rom_sel & !fifo_full) rom_size <= #1 rom_size - 7'h01; 271 | 272 | always @(posedge clk) 273 | fifo_we_rom_r <= #1 rom_sel; 274 | 275 | always @(posedge clk) 276 | fifo_we_rom_r2 <= #1 fifo_we_rom_r; 277 | 278 | assign fifo_we_rom = rom_sel & fifo_we_rom_r2; 279 | 280 | assign rom_done = (rom_size == 7'h0) & !(rom_sel & !rom_sel_r); 281 | 282 | /////////////////////////////////////////////////////////////////// 283 | // 284 | // Get Header 285 | // 286 | 287 | assign fifo_re1 = get_hdr & !fifo_empty; 288 | 289 | always @(posedge clk) 290 | adv <= #1 get_hdr & !fifo_empty & !adv; 291 | 292 | always @(posedge clk) 293 | if(!rst) le <= #1 8'h0; 294 | else 295 | if(!get_hdr) le <= #1 8'h0; 296 | else 297 | if(!(|le)) le <= #1 8'h1; 298 | else 299 | if(adv) le <= #1 {le[6:0], 1'b0}; 300 | 301 | always @(posedge clk) 302 | if(le[0]) hdr0 <= #1 ep0_din; 303 | 304 | always @(posedge clk) 305 | if(le[1]) hdr1 <= #1 ep0_din; 306 | 307 | always @(posedge clk) 308 | if(le[2]) hdr2 <= #1 ep0_din; 309 | 310 | always @(posedge clk) 311 | if(le[3]) hdr3 <= #1 ep0_din; 312 | 313 | always @(posedge clk) 314 | if(le[4]) hdr4 <= #1 ep0_din; 315 | 316 | always @(posedge clk) 317 | if(le[5]) hdr5 <= #1 ep0_din; 318 | 319 | always @(posedge clk) 320 | if(le[6]) hdr6 <= #1 ep0_din; 321 | 322 | always @(posedge clk) 323 | if(le[7]) hdr7 <= #1 ep0_din; 324 | 325 | assign hdr_done = le[7] & adv; 326 | 327 | /////////////////////////////////////////////////////////////////// 328 | // 329 | // Send Data to Host 330 | // 331 | parameter ZERO_DATA = 5'b00001, 332 | ZERO_ONE_DATA = 5'b00010, 333 | CONFIG_DATA = 5'b00100, 334 | SYNC_FRAME_DATA = 5'b01000, 335 | VEND_DATA = 5'b10000; 336 | 337 | assign high_sel = write_done_r; 338 | 339 | always @(posedge clk) 340 | case(data_sel) // synopsys full_case parallel_case 341 | ZERO_DATA: ep0_dout <= #1 rom_sel ? rom_data : 8'h0; 342 | ZERO_ONE_DATA: ep0_dout <= #1 high_sel ? 8'h1 : 8'h0; 343 | CONFIG_DATA: ep0_dout <= #1 {7'h0, configured}; // return configuration 344 | SYNC_FRAME_DATA: ep0_dout <= #1 high_sel ? {5'h0, frame_no[10:8]} : frame_no[7:0]; 345 | VEND_DATA: ep0_dout <= #1 high_sel ? vendor_data[15:8] : vendor_data[7:0]; 346 | endcase 347 | 348 | always @(posedge clk) 349 | ep0_we <= #1 fifo_we_d | fifo_we_rom; 350 | 351 | always @(posedge clk) 352 | if(in_size_0) ep0_size <= #1 8'h0; 353 | else 354 | if(in_size_1) ep0_size <= #1 8'h1; 355 | else 356 | if(in_size_2) ep0_size <= #1 8'h2; 357 | else 358 | if(rom_sel) ep0_size <= #1 {1'b0, rom_size_d}; 359 | 360 | 361 | always @(posedge clk) 362 | write_done_r <= #1 in_size_2 & !fifo_full & fifo_we_d & 363 | !write_done_r & !write_done; 364 | 365 | always @(posedge clk) 366 | write_done <= #1 in_size_2 & !fifo_full & fifo_we_d & 367 | write_done_r & !write_done; 368 | 369 | /////////////////////////////////////////////////////////////////// 370 | // 371 | // Decode Header 372 | // 373 | 374 | // Valid bRequest Codes 375 | parameter GET_STATUS = 8'h00, 376 | CLEAR_FEATURE = 8'h01, 377 | SET_FEATURE = 8'h03, 378 | SET_ADDRESS = 8'h05, 379 | GET_DESCRIPTOR = 8'h06, 380 | SET_DESCRIPTOR = 8'h07, 381 | GET_CONFIG = 8'h08, 382 | SET_CONFIG = 8'h09, 383 | GET_INTERFACE = 8'h0a, 384 | SET_INTERFACE = 8'h0b, 385 | SYNCH_FRAME = 8'h0c; 386 | 387 | parameter V_SET_INT = 8'h0f; 388 | 389 | 390 | assign bmReqType = hdr0; 391 | assign bm_req_dir = bmReqType[7]; // 0-Host to device; 1-device to host 392 | assign bm_req_type = bmReqType[6:5]; // 0-standard; 1-class; 2-vendor; 3-RESERVED 393 | assign bm_req_recp = bmReqType[4:0]; // 0-device; 1-interface; 2-endpoint; 3-other 394 | // 4..31-reserved 395 | assign bRequest = hdr1; 396 | assign wValue = {hdr3, hdr2}; 397 | assign wIndex = {hdr5, hdr4}; 398 | assign wLength = {hdr7, hdr6}; 399 | 400 | always @(posedge clk) 401 | hdr_done_r <= #1 hdr_done; 402 | 403 | // Standard commands that MUST support 404 | always @(posedge clk) 405 | get_status <= #1 hdr_done & (bRequest == GET_STATUS) & 406 | (bm_req_type==2'h0); 407 | 408 | always @(posedge clk) 409 | clear_feature <= #1 hdr_done & (bRequest == CLEAR_FEATURE) & 410 | (bm_req_type==2'h0); 411 | 412 | always @(posedge clk) 413 | set_feature <= #1 hdr_done & (bRequest == SET_FEATURE) & 414 | (bm_req_type==2'h0); 415 | 416 | always @(posedge clk) 417 | set_address <= #1 hdr_done & (bRequest == SET_ADDRESS) & 418 | (bm_req_type==2'h0); 419 | 420 | always @(posedge clk) 421 | get_descriptor <= #1 hdr_done & (bRequest == GET_DESCRIPTOR) & 422 | (bm_req_type==2'h0); 423 | 424 | always @(posedge clk) 425 | set_descriptor <= #1 hdr_done & (bRequest == SET_DESCRIPTOR) & 426 | (bm_req_type==2'h0); 427 | 428 | always @(posedge clk) 429 | get_config <= #1 hdr_done & (bRequest == GET_CONFIG) & 430 | (bm_req_type==2'h0); 431 | 432 | always @(posedge clk) 433 | set_config <= #1 hdr_done & (bRequest == SET_CONFIG) & 434 | (bm_req_type==2'h0); 435 | 436 | always @(posedge clk) 437 | get_interface <= #1 hdr_done & (bRequest == GET_INTERFACE) & 438 | (bm_req_type==2'h0); 439 | 440 | always @(posedge clk) 441 | set_interface <= #1 hdr_done & (bRequest == SET_INTERFACE) & 442 | (bm_req_type==2'h0); 443 | 444 | always @(posedge clk) 445 | synch_frame <= #1 hdr_done & (bRequest == SYNCH_FRAME) & 446 | (bm_req_type==2'h0); 447 | 448 | always @(posedge clk) 449 | v_set_int <= #1 hdr_done & (bRequest == V_SET_INT) & 450 | (bm_req_type==2'h2); 451 | 452 | always @(posedge clk) 453 | v_set_feature <= #1 hdr_done & (bRequest == SET_FEATURE) & 454 | (bm_req_type==2'h2); 455 | 456 | always @(posedge clk) 457 | v_get_status <= #1 hdr_done & (bRequest == GET_STATUS) & 458 | (bm_req_type==2'h2); 459 | 460 | // A config err must cause the device to send a STALL for an ACK 461 | always @(posedge clk) 462 | config_err <= #1 hdr_done_r & !(get_status | clear_feature | 463 | set_feature | set_address | get_descriptor | 464 | set_descriptor | get_config | set_config | 465 | get_interface | set_interface | synch_frame | 466 | v_set_int | v_set_feature | v_get_status); 467 | 468 | always @(posedge clk) 469 | send_stall <= #1 config_err; 470 | 471 | /////////////////////////////////////////////////////////////////// 472 | // 473 | // Set address 474 | // 475 | 476 | always @(posedge clk) 477 | if(!rst) set_adr_pending <= #1 1'b0; 478 | else 479 | if(ctrl_in | ctrl_out | ctrl_setup) set_adr_pending <= #1 1'b0; 480 | else 481 | if(set_address) set_adr_pending <= #1 1'b1; 482 | 483 | always @(posedge clk) 484 | if(!rst) funct_adr_tmp <= #1 7'h0; 485 | else 486 | if(set_address) funct_adr_tmp <= #1 wValue[6:0]; 487 | 488 | always @(posedge clk) 489 | if(!rst) funct_adr <= #1 7'h0; 490 | else 491 | if(set_adr_pending & ctrl_in) funct_adr <= #1 funct_adr_tmp; 492 | 493 | /////////////////////////////////////////////////////////////////// 494 | // 495 | // Main FSM 496 | // 497 | 498 | always @(posedge clk) 499 | if(!rst) state <= #1 IDLE; 500 | else state <= next_state; 501 | 502 | always @(state or ctrl_setup or ctrl_in or ctrl_out or hdr_done or 503 | fifo_full or rom_done or write_done_r or wValue or bm_req_recp or 504 | get_status or clear_feature or set_feature or set_address or 505 | get_descriptor or set_descriptor or get_config or set_config or 506 | get_interface or set_interface or synch_frame or v_set_int or 507 | v_set_feature or v_get_status 508 | ) 509 | begin 510 | next_state = state; 511 | get_hdr = 1'b0; 512 | data_sel = ZERO_DATA; 513 | fifo_we_d = 1'b0; 514 | in_size_0 = 1'b0; 515 | in_size_1 = 1'b0; 516 | in_size_2 = 1'b0; 517 | rom_sel = 1'b0; 518 | 519 | case(state) // synopsys full_case parallel_case 520 | 521 | // Wait for Setup token 522 | IDLE: 523 | begin 524 | if(ctrl_setup) next_state = GET_HDR; 525 | if(get_status) next_state = GET_STATUS_S; 526 | if(clear_feature) next_state = CLEAR_FEATURE_S; 527 | if(set_feature) next_state = SET_FEATURE_S; 528 | if(set_address) next_state = SET_ADDRESS_S; 529 | if(get_descriptor) next_state = GET_DESCRIPTOR_S; 530 | if(set_descriptor) next_state = SET_DESCRIPTOR_S; 531 | if(get_config) next_state = GET_CONFIG_S; 532 | if(set_config) next_state = SET_CONFIG_S; 533 | if(get_interface) next_state = GET_INTERFACE_S; 534 | if(set_interface) next_state = SET_INTERFACE_S; 535 | if(synch_frame) next_state = SYNCH_FRAME_S; 536 | if(v_set_int) next_state = V_SET_INT_S; 537 | if(v_set_feature) next_state = V_SET_INT_S; 538 | if(v_get_status) next_state = V_GET_STATUS_S; 539 | end 540 | 541 | // Retrieve Setup Header 542 | GET_HDR: 543 | begin 544 | get_hdr = 1'b1; 545 | if(hdr_done) next_state = IDLE; 546 | end 547 | 548 | 549 | // Actions for supported commands 550 | GET_STATUS_S: 551 | begin 552 | // Returns to host 553 | // 16'h0001 for device 554 | // 16'h0000 for interface 555 | // 16'h0000 for endpoint 556 | if(bm_req_recp == 5'h00) data_sel = ZERO_ONE_DATA; 557 | else data_sel = ZERO_DATA; 558 | 559 | in_size_2 = 1'b1; 560 | if(!fifo_full) 561 | begin 562 | fifo_we_d = 1'b1; 563 | if(write_done_r) next_state = WAIT_IN_DATA; 564 | end 565 | 566 | end 567 | V_GET_STATUS_S: 568 | begin 569 | data_sel = VEND_DATA; 570 | in_size_2 = 1'b1; 571 | if(!fifo_full) 572 | begin 573 | fifo_we_d = 1'b1; 574 | if(write_done_r) next_state = WAIT_IN_DATA; 575 | end 576 | end 577 | 578 | CLEAR_FEATURE_S: 579 | begin 580 | // just ignore this for now 581 | next_state = STATUS_IN; 582 | end 583 | 584 | SET_FEATURE_S: 585 | begin 586 | // just ignore this for now 587 | next_state = STATUS_IN; 588 | end 589 | 590 | SET_ADDRESS_S: 591 | begin 592 | // done elsewhere .... 593 | next_state = STATUS_IN; 594 | end 595 | 596 | GET_DESCRIPTOR_S: 597 | begin 598 | if( wValue[15:8] == 8'h01 | 599 | wValue[15:8] == 8'h02 | 600 | wValue[15:8] == 8'h03 ) 601 | rom_sel = 1'b1; 602 | else 603 | next_state = IDLE; 604 | 605 | if(rom_done) 606 | next_state = IDLE; 607 | end 608 | 609 | SET_DESCRIPTOR_S: 610 | begin 611 | // This doesn't do anything since we do not support 612 | // setting the descriptor 613 | next_state = IDLE; 614 | end 615 | 616 | GET_CONFIG_S: 617 | begin 618 | // Send one byte back that indicates current status 619 | in_size_1 = 1'b1; 620 | data_sel = CONFIG_DATA; 621 | if(!fifo_full) 622 | begin 623 | fifo_we_d = 1'b1; 624 | next_state = WAIT_IN_DATA; 625 | end 626 | end 627 | 628 | SET_CONFIG_S: 629 | begin 630 | // done elsewhere .... 631 | next_state = STATUS_IN; 632 | end 633 | 634 | GET_INTERFACE_S: 635 | begin 636 | // Return interface '0' 637 | in_size_1 = 1'b1; 638 | if(!fifo_full) 639 | begin 640 | fifo_we_d = 1'b1; 641 | next_state = WAIT_IN_DATA; 642 | end 643 | end 644 | 645 | SET_INTERFACE_S: 646 | begin 647 | // just ignore this for now 648 | next_state = STATUS_IN; 649 | end 650 | 651 | SYNCH_FRAME_S: 652 | begin 653 | // Return Frame current frame number 654 | data_sel = SYNC_FRAME_DATA; 655 | in_size_2 = 1'b1; 656 | if(!fifo_full) 657 | begin 658 | fifo_we_d = 1'b1; 659 | if(write_done_r) next_state = WAIT_IN_DATA; 660 | end 661 | end 662 | 663 | V_SET_INT_S: 664 | begin 665 | // done elsewhere .... 666 | next_state = STATUS_IN; 667 | end 668 | 669 | WAIT_IN_DATA: 670 | begin 671 | if(ctrl_in) next_state = STATUS_OUT; 672 | end 673 | 674 | STATUS_IN: 675 | begin 676 | in_size_0 = 1'b1; 677 | if(ctrl_in) next_state = IDLE; 678 | end 679 | 680 | STATUS_OUT: 681 | begin 682 | if(ctrl_out) next_state = IDLE; 683 | end 684 | endcase 685 | end 686 | 687 | endmodule 688 | 689 | -------------------------------------------------------------------------------- /rtl/verilog/usb1_pe.v: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | //// //// 3 | //// Protocol Engine //// 4 | //// Performs automatic protocol functions //// 5 | //// //// 6 | //// Author: Rudolf Usselmann //// 7 | //// rudi@asics.ws //// 8 | //// //// 9 | //// //// 10 | //// Downloaded from: http://www.opencores.org/cores/usb1_funct///// 11 | //// //// 12 | ///////////////////////////////////////////////////////////////////// 13 | //// //// 14 | //// Copyright (C) 2000-2002 Rudolf Usselmann //// 15 | //// www.asics.ws //// 16 | //// rudi@asics.ws //// 17 | //// //// 18 | //// This source file may be used and distributed without //// 19 | //// restriction provided that this copyright statement is not //// 20 | //// removed from the file and that any derivative work contains //// 21 | //// the original copyright notice and the associated disclaimer.//// 22 | //// //// 23 | //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 24 | //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 25 | //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 26 | //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 27 | //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 28 | //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 29 | //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 30 | //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 31 | //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 32 | //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 33 | //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 34 | //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 35 | //// POSSIBILITY OF SUCH DAMAGE. //// 36 | //// //// 37 | ///////////////////////////////////////////////////////////////////// 38 | 39 | // CVS Log 40 | // 41 | // $Id: usb1_pe.v,v 1.1.1.1 2002-09-19 12:07:24 rudi Exp $ 42 | // 43 | // $Date: 2002-09-19 12:07:24 $ 44 | // $Revision: 1.1.1.1 $ 45 | // $Author: rudi $ 46 | // $Locker: $ 47 | // $State: Exp $ 48 | // 49 | // Change History: 50 | // $Log: not supported by cvs2svn $ 51 | // 52 | // 53 | // 54 | // 55 | // 56 | // 57 | 58 | `include "usb1_defines.v" 59 | 60 | module usb1_pe( clk, rst, 61 | 62 | // UTMI Interfaces 63 | tx_valid, rx_active, 64 | 65 | // PID Information 66 | pid_OUT, pid_IN, pid_SOF, pid_SETUP, 67 | pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA, 68 | pid_ACK, pid_PING, 69 | 70 | // Token Information 71 | token_valid, 72 | 73 | // Receive Data Output 74 | rx_data_done, crc16_err, 75 | 76 | // Packet Assembler Interface 77 | send_token, token_pid_sel, 78 | data_pid_sel, 79 | 80 | // IDMA Interface 81 | rx_dma_en, tx_dma_en, 82 | abort, 83 | idma_done, 84 | 85 | // Register File Interface 86 | 87 | fsel, 88 | ep_sel, match, nse_err, 89 | ep_full, ep_empty, 90 | 91 | int_upid_set, int_crc16_set, int_to_set, int_seqerr_set, 92 | csr, 93 | send_stall 94 | 95 | ); 96 | 97 | input clk, rst; 98 | input tx_valid, rx_active; 99 | 100 | // Packet Disassembler Interface 101 | // Decoded PIDs (used when token_valid is asserted) 102 | input pid_OUT, pid_IN, pid_SOF, pid_SETUP; 103 | input pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA; 104 | input pid_ACK, pid_PING; 105 | 106 | input token_valid; // Token is valid 107 | 108 | input rx_data_done; // Indicates end of a transfer 109 | input crc16_err; // Data packet CRC 16 error 110 | 111 | // Packet Assembler Interface 112 | output send_token; 113 | output [1:0] token_pid_sel; 114 | output [1:0] data_pid_sel; 115 | 116 | // IDMA Interface 117 | output rx_dma_en; // Allows the data to be stored 118 | output tx_dma_en; // Allows for data to be retrieved 119 | output abort; // Abort Transfer (time_out, crc_err or rx_error) 120 | input idma_done; // DMA is done indicator 121 | 122 | input ep_full; // Indicates the endpoints fifo is full 123 | input ep_empty; // Indicates the endpoints fifo is empty 124 | 125 | // Register File interface 126 | input fsel; // This function is selected 127 | input [3:0] ep_sel; // Endpoint Number Input 128 | input match; // Endpoint Matched 129 | output nse_err; // no such endpoint error 130 | 131 | output int_upid_set; // Set unsupported PID interrupt 132 | output int_crc16_set; // Set CRC16 error interrupt 133 | output int_to_set; // Set time out interrupt 134 | output int_seqerr_set; // Set PID sequence error interrupt 135 | 136 | input [13:0] csr; // Internal CSR Output 137 | 138 | input send_stall; // Force sending a STALL during setup 139 | 140 | 141 | /////////////////////////////////////////////////////////////////// 142 | // 143 | // Local Wires and Registers 144 | // 145 | 146 | // tx token decoding 147 | parameter ACK = 0, 148 | NACK = 1, 149 | STALL = 2, 150 | NYET = 3; 151 | 152 | // State decoding 153 | parameter [9:0] // synopsys enum state 154 | IDLE = 10'b000000_0001, 155 | TOKEN = 10'b000000_0010, 156 | IN = 10'b000000_0100, 157 | IN2 = 10'b000000_1000, 158 | OUT = 10'b000001_0000, 159 | OUT2A = 10'b000010_0000, 160 | OUT2B = 10'b000100_0000, 161 | UPDATEW = 10'b001000_0000, 162 | UPDATE = 10'b010000_0000, 163 | UPDATE2 = 10'b100000_0000; 164 | 165 | reg [1:0] token_pid_sel; 166 | reg [1:0] token_pid_sel_d; 167 | reg send_token; 168 | reg send_token_d; 169 | reg rx_dma_en, tx_dma_en; 170 | reg int_seqerr_set_d; 171 | reg int_seqerr_set; 172 | reg int_upid_set; 173 | 174 | reg match_r; 175 | 176 | // Endpoint Decoding 177 | wire IN_ep, OUT_ep, CTRL_ep; // Endpoint Types 178 | wire txfr_iso, txfr_bulk, txfr_int; // Transfer Types 179 | 180 | reg [1:0] uc_dpd; 181 | 182 | // Buffer checks 183 | reg [9:0] /* synopsys enum state */ state, next_state; 184 | // synopsys state_vector state 185 | 186 | // PID next and current decoders 187 | reg [1:0] next_dpid; 188 | reg [1:0] this_dpid; 189 | reg pid_seq_err; 190 | wire [1:0] tr_fr_d; 191 | 192 | wire [13:0] size_next; 193 | wire buf_smaller; 194 | 195 | // After sending Data in response to an IN token from host, the 196 | // host must reply with an ack. The host has XXXnS to reply. 197 | // "rx_ack_to" indicates when this time has expired. 198 | // rx_ack_to_clr, clears the timer 199 | reg rx_ack_to_clr; 200 | reg rx_ack_to_clr_d; 201 | reg rx_ack_to; 202 | reg [7:0] rx_ack_to_cnt; 203 | 204 | // After sending a OUT token the host must send a data packet. 205 | // The host has XX nS to send the packet. "tx_data_to" indicates 206 | // when this time has expired. 207 | // tx_data_to_clr, clears the timer 208 | wire tx_data_to_clr; 209 | reg tx_data_to; 210 | reg [7:0] tx_data_to_cnt; 211 | 212 | wire [7:0] rx_ack_to_val, tx_data_to_val; 213 | 214 | 215 | wire [1:0] next_bsel; 216 | reg uc_stat_set_d; 217 | reg uc_dpd_set; 218 | 219 | reg in_token; 220 | reg out_token; 221 | reg setup_token; 222 | 223 | wire in_op, out_op; // Indicate a IN or OUT operation 224 | 225 | reg [1:0] allow_pid; 226 | 227 | reg nse_err; 228 | reg abort; 229 | 230 | wire [1:0] ep_type, txfr_type; 231 | 232 | /////////////////////////////////////////////////////////////////// 233 | // 234 | // Misc Logic 235 | // 236 | 237 | // Endpoint/CSR Decoding 238 | assign IN_ep = csr[9]; 239 | assign OUT_ep = csr[10]; 240 | assign CTRL_ep = csr[11]; 241 | 242 | assign txfr_iso = csr[12]; 243 | assign txfr_bulk = csr[13]; 244 | assign txfr_int = !csr[12] & !csr[13]; 245 | 246 | assign ep_type = csr[10:9]; 247 | assign txfr_type = csr[13:12]; 248 | 249 | always @(posedge clk) 250 | match_r <= #1 match & fsel; 251 | 252 | // No Such Endpoint Indicator 253 | always @(posedge clk) 254 | nse_err <= #1 token_valid & (pid_OUT | pid_IN | pid_SETUP) & !match; 255 | 256 | always @(posedge clk) 257 | send_token <= #1 send_token_d; 258 | 259 | always @(posedge clk) 260 | token_pid_sel <= #1 token_pid_sel_d; 261 | 262 | /////////////////////////////////////////////////////////////////// 263 | // 264 | // Data Pid Storage 265 | // 266 | 267 | reg [1:0] ep0_dpid, ep1_dpid, ep2_dpid, ep3_dpid; 268 | reg [1:0] ep4_dpid, ep5_dpid, ep6_dpid, ep7_dpid; 269 | 270 | always @(posedge clk or negedge rst) 271 | if(!rst) ep0_dpid <= 2'b00; 272 | else 273 | if(uc_dpd_set & (ep_sel == 4'h0)) ep0_dpid <= next_dpid; 274 | 275 | always @(posedge clk or negedge rst) 276 | if(!rst) ep1_dpid <= 2'b00; 277 | else 278 | if(uc_dpd_set & (ep_sel == 4'h1)) ep1_dpid <= next_dpid; 279 | 280 | always @(posedge clk or negedge rst) 281 | if(!rst) ep2_dpid <= 2'b00; 282 | else 283 | if(uc_dpd_set & (ep_sel == 4'h2)) ep2_dpid <= next_dpid; 284 | 285 | always @(posedge clk or negedge rst) 286 | if(!rst) ep3_dpid <= 2'b00; 287 | else 288 | if(uc_dpd_set & (ep_sel == 4'h3)) ep3_dpid <= next_dpid; 289 | 290 | always @(posedge clk or negedge rst) 291 | if(!rst) ep4_dpid <= 2'b00; 292 | else 293 | if(uc_dpd_set & (ep_sel == 4'h4)) ep4_dpid <= next_dpid; 294 | 295 | always @(posedge clk or negedge rst) 296 | if(!rst) ep5_dpid <= 2'b00; 297 | else 298 | if(uc_dpd_set & (ep_sel == 4'h5)) ep5_dpid <= next_dpid; 299 | 300 | always @(posedge clk or negedge rst) 301 | if(!rst) ep6_dpid <= 2'b00; 302 | else 303 | if(uc_dpd_set & (ep_sel == 4'h6)) ep6_dpid <= next_dpid; 304 | 305 | always @(posedge clk or negedge rst) 306 | if(!rst) ep7_dpid <= 2'b00; 307 | else 308 | if(uc_dpd_set & (ep_sel == 4'h7)) ep7_dpid <= next_dpid; 309 | 310 | always @(posedge clk) 311 | case(ep_sel) 312 | 4'h0: uc_dpd <= ep0_dpid; 313 | 4'h1: uc_dpd <= ep1_dpid; 314 | 4'h2: uc_dpd <= ep2_dpid; 315 | 4'h3: uc_dpd <= ep3_dpid; 316 | 4'h4: uc_dpd <= ep4_dpid; 317 | 4'h5: uc_dpd <= ep5_dpid; 318 | 4'h6: uc_dpd <= ep6_dpid; 319 | 4'h7: uc_dpd <= ep7_dpid; 320 | endcase 321 | 322 | /////////////////////////////////////////////////////////////////// 323 | // 324 | // Data Pid Sequencer 325 | // 326 | 327 | assign tr_fr_d = 2'h0; 328 | 329 | always @(posedge clk) // tr/mf:ep/type:tr/type:last dpd 330 | casex({tr_fr_d,ep_type,txfr_type,uc_dpd}) // synopsys full_case parallel_case 331 | 8'b0?_01_01_??: next_dpid <= #1 2'b00; // ISO txfr. IN, 1 tr/mf 332 | 333 | 8'b10_01_01_?0: next_dpid <= #1 2'b01; // ISO txfr. IN, 2 tr/mf 334 | 8'b10_01_01_?1: next_dpid <= #1 2'b00; // ISO txfr. IN, 2 tr/mf 335 | 336 | 8'b11_01_01_00: next_dpid <= #1 2'b01; // ISO txfr. IN, 3 tr/mf 337 | 8'b11_01_01_01: next_dpid <= #1 2'b10; // ISO txfr. IN, 3 tr/mf 338 | 8'b11_01_01_10: next_dpid <= #1 2'b00; // ISO txfr. IN, 3 tr/mf 339 | 340 | 8'b0?_10_01_??: next_dpid <= #1 2'b00; // ISO txfr. OUT, 1 tr/mf 341 | 342 | 8'b10_10_01_??: // ISO txfr. OUT, 2 tr/mf 343 | begin // Resynchronize in case of PID error 344 | case({pid_MDATA, pid_DATA1}) // synopsys full_case parallel_case 345 | 2'b10: next_dpid <= #1 2'b01; 346 | 2'b01: next_dpid <= #1 2'b00; 347 | endcase 348 | end 349 | 350 | 8'b11_10_01_00: // ISO txfr. OUT, 3 tr/mf 351 | begin // Resynchronize in case of PID error 352 | case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case 353 | 2'b10: next_dpid <= #1 2'b01; 354 | 2'b01: next_dpid <= #1 2'b00; 355 | endcase 356 | end 357 | 8'b11_10_01_01: // ISO txfr. OUT, 3 tr/mf 358 | begin // Resynchronize in case of PID error 359 | case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case 360 | 2'b10: next_dpid <= #1 2'b10; 361 | 2'b01: next_dpid <= #1 2'b00; 362 | endcase 363 | end 364 | 8'b11_10_01_10: // ISO txfr. OUT, 3 tr/mf 365 | begin // Resynchronize in case of PID error 366 | case({pid_MDATA, pid_DATA2}) // synopsys full_case parallel_case 367 | 2'b10: next_dpid <= #1 2'b01; 368 | 2'b01: next_dpid <= #1 2'b00; 369 | endcase 370 | end 371 | 372 | 8'b??_01_00_?0, // IN/OUT endpoint only 373 | 8'b??_10_00_?0: next_dpid <= #1 2'b01; // INT transfers 374 | 375 | 8'b??_01_00_?1, // IN/OUT endpoint only 376 | 8'b??_10_00_?1: next_dpid <= #1 2'b00; // INT transfers 377 | 378 | 8'b??_01_10_?0, // IN/OUT endpoint only 379 | 8'b??_10_10_?0: next_dpid <= #1 2'b01; // BULK transfers 380 | 381 | 8'b??_01_10_?1, // IN/OUT endpoint only 382 | 8'b??_10_10_?1: next_dpid <= #1 2'b00; // BULK transfers 383 | 384 | 8'b??_00_??_??: // CTRL Endpoint 385 | casex({setup_token, in_op, out_op, uc_dpd}) // synopsys full_case parallel_case 386 | 5'b1_??_??: next_dpid <= #1 2'b11; // SETUP operation 387 | 5'b0_10_0?: next_dpid <= #1 2'b11; // IN operation 388 | 5'b0_10_1?: next_dpid <= #1 2'b01; // IN operation 389 | 5'b0_01_?0: next_dpid <= #1 2'b11; // OUT operation 390 | 5'b0_01_?1: next_dpid <= #1 2'b10; // OUT operation 391 | endcase 392 | 393 | endcase 394 | 395 | // Current PID decoder 396 | 397 | // Allow any PID for ISO. transfers when mode full speed or tr_fr is zero 398 | always @(pid_DATA0 or pid_DATA1 or pid_DATA2 or pid_MDATA) 399 | case({pid_DATA0, pid_DATA1, pid_DATA2, pid_MDATA} ) // synopsys full_case parallel_case 400 | 4'b1000: allow_pid = 2'b00; 401 | 4'b0100: allow_pid = 2'b01; 402 | 4'b0010: allow_pid = 2'b10; 403 | 4'b0001: allow_pid = 2'b11; 404 | endcase 405 | 406 | always @(posedge clk) // tf/mf:ep/type:tr/type:last dpd 407 | casex({tr_fr_d,ep_type,txfr_type,uc_dpd}) // synopsys full_case parallel_case 408 | 8'b0?_01_01_??: this_dpid <= #1 2'b00; // ISO txfr. IN, 1 tr/mf 409 | 410 | 8'b10_01_01_?0: this_dpid <= #1 2'b01; // ISO txfr. IN, 2 tr/mf 411 | 8'b10_01_01_?1: this_dpid <= #1 2'b00; // ISO txfr. IN, 2 tr/mf 412 | 413 | 8'b11_01_01_00: this_dpid <= #1 2'b10; // ISO txfr. IN, 3 tr/mf 414 | 8'b11_01_01_01: this_dpid <= #1 2'b01; // ISO txfr. IN, 3 tr/mf 415 | 8'b11_01_01_10: this_dpid <= #1 2'b00; // ISO txfr. IN, 3 tr/mf 416 | 417 | 8'b00_10_01_??: this_dpid <= #1 allow_pid; // ISO txfr. OUT, 0 tr/mf 418 | 8'b01_10_01_??: this_dpid <= #1 2'b00; // ISO txfr. OUT, 1 tr/mf 419 | 420 | 8'b10_10_01_?0: this_dpid <= #1 2'b11; // ISO txfr. OUT, 2 tr/mf 421 | 8'b10_10_01_?1: this_dpid <= #1 2'b01; // ISO txfr. OUT, 2 tr/mf 422 | 423 | 8'b11_10_01_00: this_dpid <= #1 2'b11; // ISO txfr. OUT, 3 tr/mf 424 | 8'b11_10_01_01: this_dpid <= #1 2'b11; // ISO txfr. OUT, 3 tr/mf 425 | 8'b11_10_01_10: this_dpid <= #1 2'b10; // ISO txfr. OUT, 3 tr/mf 426 | 427 | 8'b??_01_00_?0, // IN/OUT endpoint only 428 | 8'b??_10_00_?0: this_dpid <= #1 2'b00; // INT transfers 429 | 8'b??_01_00_?1, // IN/OUT endpoint only 430 | 8'b??_10_00_?1: this_dpid <= #1 2'b01; // INT transfers 431 | 432 | 8'b??_01_10_?0, // IN/OUT endpoint only 433 | 8'b??_10_10_?0: this_dpid <= #1 2'b00; // BULK transfers 434 | 8'b??_01_10_?1, // IN/OUT endpoint only 435 | 8'b??_10_10_?1: this_dpid <= #1 2'b01; // BULK transfers 436 | 437 | 8'b??_00_??_??: // CTRL Endpoint 438 | casex({setup_token,in_op, out_op, uc_dpd}) // synopsys full_case parallel_case 439 | 5'b1_??_??: this_dpid <= #1 2'b00; // SETUP operation 440 | 5'b0_10_0?: this_dpid <= #1 2'b00; // IN operation 441 | 5'b0_10_1?: this_dpid <= #1 2'b01; // IN operation 442 | 5'b0_01_?0: this_dpid <= #1 2'b00; // OUT operation 443 | 5'b0_01_?1: this_dpid <= #1 2'b01; // OUT operation 444 | endcase 445 | endcase 446 | 447 | // Assign PID for outgoing packets 448 | assign data_pid_sel = this_dpid; 449 | 450 | // Verify PID for incoming data packets 451 | always @(posedge clk) 452 | pid_seq_err <= #1 !( (this_dpid==2'b00 & pid_DATA0) | 453 | (this_dpid==2'b01 & pid_DATA1) | 454 | (this_dpid==2'b10 & pid_DATA2) | 455 | (this_dpid==2'b11 & pid_MDATA) ); 456 | 457 | /////////////////////////////////////////////////////////////////// 458 | // 459 | // IDMA Setup & src/dst buffer select 460 | // 461 | 462 | // For Control endpoints things are different: 463 | // buffer0 is used for OUT (incoming) data packets 464 | // buffer1 is used for IN (outgoing) data packets 465 | 466 | // Keep track of last token for control endpoints 467 | always @(posedge clk or negedge rst) 468 | if(!rst) in_token <= #1 1'b0; 469 | else 470 | if(pid_IN) in_token <= #1 1'b1; 471 | else 472 | if(pid_OUT | pid_SETUP) in_token <= #1 1'b0; 473 | 474 | always @(posedge clk or negedge rst) 475 | if(!rst) out_token <= #1 1'b0; 476 | else 477 | if(pid_OUT | pid_SETUP) out_token <= #1 1'b1; 478 | else 479 | if(pid_IN) out_token <= #1 1'b0; 480 | 481 | always @(posedge clk or negedge rst) 482 | if(!rst) setup_token <= #1 1'b0; 483 | else 484 | if(pid_SETUP) setup_token <= #1 1'b1; 485 | else 486 | if(pid_OUT | pid_IN) setup_token <= #1 1'b0; 487 | 488 | // Indicates if we are performing an IN operation 489 | assign in_op = IN_ep | (CTRL_ep & in_token); 490 | 491 | // Indicates if we are performing an OUT operation 492 | assign out_op = OUT_ep | (CTRL_ep & out_token); 493 | 494 | 495 | /////////////////////////////////////////////////////////////////// 496 | // 497 | // Determine if packet is to small or to large 498 | // This is used to NACK and ignore packet for OUT endpoints 499 | // 500 | 501 | 502 | /////////////////////////////////////////////////////////////////// 503 | // 504 | // Register File Update Logic 505 | // 506 | 507 | always @(posedge clk) 508 | uc_dpd_set <= #1 uc_stat_set_d; 509 | 510 | // Abort signal 511 | always @(posedge clk) 512 | abort <= #1 match & fsel & (state != IDLE); 513 | 514 | /////////////////////////////////////////////////////////////////// 515 | // 516 | // TIME OUT TIMERS 517 | // 518 | 519 | // After sending Data in response to an IN token from host, the 520 | // host must reply with an ack. The host has 622nS in Full Speed 521 | // mode and 400nS in High Speed mode to reply. 522 | // "rx_ack_to" indicates when this time has expired. 523 | // rx_ack_to_clr, clears the timer 524 | 525 | always @(posedge clk) 526 | rx_ack_to_clr <= #1 tx_valid | rx_ack_to_clr_d; 527 | 528 | always @(posedge clk) 529 | if(rx_ack_to_clr) rx_ack_to_cnt <= #1 8'h0; 530 | else rx_ack_to_cnt <= #1 rx_ack_to_cnt + 8'h1; 531 | 532 | always @(posedge clk) 533 | rx_ack_to <= #1 (rx_ack_to_cnt == rx_ack_to_val); 534 | 535 | assign rx_ack_to_val = `USBF_RX_ACK_TO_VAL_FS; 536 | 537 | // After sending a OUT token the host must send a data packet. 538 | // The host has 622nS in Full Speed mode and 400nS in High Speed 539 | // mode to send the data packet. 540 | // "tx_data_to" indicates when this time has expired. 541 | // "tx_data_to_clr" clears the timer 542 | 543 | assign tx_data_to_clr = rx_active; 544 | 545 | always @(posedge clk) 546 | if(tx_data_to_clr) tx_data_to_cnt <= #1 8'h0; 547 | else tx_data_to_cnt <= #1 tx_data_to_cnt + 8'h1; 548 | 549 | always @(posedge clk) 550 | tx_data_to <= #1 (tx_data_to_cnt == tx_data_to_val); 551 | 552 | assign tx_data_to_val = `USBF_TX_DATA_TO_VAL_FS; 553 | 554 | /////////////////////////////////////////////////////////////////// 555 | // 556 | // Interrupts 557 | // 558 | reg pid_OUT_r, pid_IN_r, pid_PING_r, pid_SETUP_r; 559 | 560 | always @(posedge clk) 561 | pid_OUT_r <= #1 pid_OUT; 562 | 563 | always @(posedge clk) 564 | pid_IN_r <= #1 pid_IN; 565 | 566 | always @(posedge clk) 567 | pid_PING_r <= #1 pid_PING; 568 | 569 | always @(posedge clk) 570 | pid_SETUP_r <= #1 pid_SETUP; 571 | 572 | always @(posedge clk) 573 | int_upid_set <= #1 match_r & !pid_SOF & ( 574 | ( OUT_ep & !(pid_OUT_r | pid_PING_r)) | 575 | ( IN_ep & !pid_IN_r) | 576 | (CTRL_ep & !(pid_IN_r | pid_OUT_r | pid_PING_r | pid_SETUP_r)) 577 | ); 578 | 579 | 580 | assign int_to_set = ((state == IN2) & rx_ack_to) | ((state == OUT) & tx_data_to); 581 | 582 | assign int_crc16_set = rx_data_done & crc16_err; 583 | 584 | always @(posedge clk) 585 | int_seqerr_set <= #1 int_seqerr_set_d; 586 | 587 | reg send_stall_r; 588 | 589 | always @(posedge clk or negedge rst) 590 | if(!rst) send_stall_r <= #1 1'b0; 591 | else 592 | if(send_stall) send_stall_r <= #1 1'b1; 593 | else 594 | if(send_token) send_stall_r <= #1 1'b0; 595 | 596 | /////////////////////////////////////////////////////////////////// 597 | // 598 | // Main Protocol State Machine 599 | // 600 | 601 | always @(posedge clk or negedge rst) 602 | if(!rst) state <= #1 IDLE; 603 | else 604 | if(match) state <= #1 IDLE; 605 | else state <= #1 next_state; 606 | 607 | always @(state or 608 | pid_seq_err or idma_done or ep_full or ep_empty or 609 | token_valid or pid_ACK or rx_data_done or 610 | tx_data_to or crc16_err or 611 | rx_ack_to or pid_PING or txfr_iso or txfr_int or 612 | CTRL_ep or pid_IN or pid_OUT or IN_ep or OUT_ep or pid_SETUP or pid_SOF 613 | or match_r or abort or send_stall_r 614 | ) 615 | begin 616 | next_state = state; 617 | token_pid_sel_d = ACK; 618 | send_token_d = 1'b0; 619 | rx_dma_en = 1'b0; 620 | tx_dma_en = 1'b0; 621 | uc_stat_set_d = 1'b0; 622 | rx_ack_to_clr_d = 1'b1; 623 | int_seqerr_set_d = 1'b0; 624 | 625 | case(state) // synopsys full_case parallel_case 626 | IDLE: 627 | begin 628 | // synopsys translate_off 629 | `ifdef USBF_VERBOSE_DEBUG 630 | $display("PE: Entered state IDLE (%t)", $time); 631 | `endif 632 | `ifdef USBF_DEBUG 633 | if(rst & match_r & !pid_SOF) 634 | begin 635 | if(match_r === 1'bx) $display("ERROR: IDLE: match_r is unknown. (%t)", $time); 636 | if(pid_SOF === 1'bx) $display("ERROR: IDLE: pid_SOF is unknown. (%t)", $time); 637 | if(CTRL_ep === 1'bx) $display("ERROR: IDLE: CTRL_ep is unknown. (%t)", $time); 638 | if(pid_IN === 1'bx) $display("ERROR: IDLE: pid_IN is unknown. (%t)", $time); 639 | if(pid_OUT === 1'bx) $display("ERROR: IDLE: pid_OUT is unknown. (%t)", $time); 640 | if(pid_SETUP === 1'bx) $display("ERROR: IDLE: pid_SETUP is unknown. (%t)", $time); 641 | if(pid_PING === 1'bx) $display("ERROR: IDLE: pid_PING is unknown. (%t)", $time); 642 | if(IN_ep === 1'bx) $display("ERROR: IDLE: IN_ep is unknown. (%t)", $time); 643 | if(OUT_ep === 1'bx) $display("ERROR: IDLE: OUT_ep is unknown. (%t)", $time); 644 | end 645 | `endif 646 | // synopsys translate_on 647 | 648 | if(match_r & !pid_SOF) 649 | begin 650 | /* 651 | if(ep_stall) // Halt Forced send STALL 652 | begin 653 | token_pid_sel_d = STALL; 654 | send_token_d = 1'b1; 655 | next_state = TOKEN; 656 | end 657 | else 658 | */ 659 | if(IN_ep | (CTRL_ep & pid_IN)) 660 | begin 661 | if(txfr_int & ep_empty) 662 | begin 663 | token_pid_sel_d = NACK; 664 | send_token_d = 1'b1; 665 | next_state = TOKEN; 666 | end 667 | else 668 | begin 669 | tx_dma_en = 1'b1; 670 | next_state = IN; 671 | end 672 | end 673 | else 674 | if(OUT_ep | (CTRL_ep & (pid_OUT | pid_SETUP))) 675 | begin 676 | rx_dma_en = 1'b1; 677 | next_state = OUT; 678 | end 679 | end 680 | end 681 | 682 | TOKEN: 683 | begin 684 | // synopsys translate_off 685 | `ifdef USBF_VERBOSE_DEBUG 686 | $display("PE: Entered state TOKEN (%t)", $time); 687 | `endif 688 | // synopsys translate_on 689 | next_state = IDLE; 690 | end 691 | 692 | IN: 693 | begin 694 | // synopsys translate_off 695 | `ifdef USBF_VERBOSE_DEBUG 696 | $display("PE: Entered state IN (%t)", $time); 697 | `endif 698 | `ifdef USBF_DEBUG 699 | if(idma_done === 1'bx) $display("ERROR: IN: idma_done is unknown. (%t)", $time); 700 | if(txfr_iso === 1'bx) $display("ERROR: IN: txfr_iso is unknown. (%t)", $time); 701 | `endif 702 | // synopsys translate_on 703 | rx_ack_to_clr_d = 1'b0; 704 | if(idma_done) 705 | begin 706 | if(txfr_iso) next_state = UPDATE; 707 | else next_state = IN2; 708 | end 709 | 710 | end 711 | IN2: 712 | begin 713 | // synopsys translate_off 714 | `ifdef USBF_VERBOSE_DEBUG 715 | $display("PE: Entered state IN2 (%t)", $time); 716 | `endif 717 | `ifdef USBF_DEBUG 718 | if(rx_ack_to === 1'bx) $display("ERROR: IN2: rx_ack_to is unknown. (%t)", $time); 719 | if(token_valid === 1'bx)$display("ERROR: IN2: token_valid is unknown. (%t)", $time); 720 | if(pid_ACK === 1'bx) $display("ERROR: IN2: pid_ACK is unknown. (%t)", $time); 721 | `endif 722 | // synopsys translate_on 723 | rx_ack_to_clr_d = 1'b0; 724 | // Wait for ACK from HOST or Timeout 725 | if(rx_ack_to) next_state = IDLE; 726 | else 727 | if(token_valid & pid_ACK) 728 | begin 729 | next_state = UPDATE; 730 | end 731 | end 732 | 733 | OUT: 734 | begin 735 | // synopsys translate_off 736 | `ifdef USBF_VERBOSE_DEBUG 737 | $display("PE: Entered state OUT (%t)", $time); 738 | `endif 739 | `ifdef USBF_DEBUG 740 | if(tx_data_to === 1'bx) $display("ERROR: OUT: tx_data_to is unknown. (%t)", $time); 741 | if(crc16_err === 1'bx) $display("ERROR: OUT: crc16_err is unknown. (%t)", $time); 742 | if(abort === 1'bx) $display("ERROR: OUT: abort is unknown. (%t)", $time); 743 | if(rx_data_done === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); 744 | if(txfr_iso === 1'bx) $display("ERROR: OUT: txfr_iso is unknown. (%t)", $time); 745 | if(pid_seq_err === 1'bx)$display("ERROR: OUT: rx_data_done is unknown. (%t)", $time); 746 | `endif 747 | // synopsys translate_on 748 | if(tx_data_to | crc16_err | abort ) 749 | next_state = IDLE; 750 | else 751 | if(rx_data_done) 752 | begin // Send Ack 753 | if(txfr_iso) 754 | begin 755 | if(pid_seq_err) int_seqerr_set_d = 1'b1; 756 | next_state = UPDATEW; 757 | end 758 | else next_state = OUT2A; 759 | end 760 | end 761 | 762 | OUT2B: 763 | begin // This is a delay State to NACK to small or to 764 | // large packets. this state could be skipped 765 | // synopsys translate_off 766 | `ifdef USBF_VERBOSE_DEBUG 767 | $display("PE: Entered state OUT2B (%t)", $time); 768 | `endif 769 | `ifdef USBF_DEBUG 770 | if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time); 771 | `endif 772 | // synopsys translate_on 773 | if(abort) next_state = IDLE; 774 | else next_state = OUT2B; 775 | end 776 | OUT2A: 777 | begin // Send ACK/NACK/NYET 778 | // synopsys translate_off 779 | `ifdef USBF_VERBOSE_DEBUG 780 | $display("PE: Entered state OUT2A (%t)", $time); 781 | `endif 782 | `ifdef USBF_DEBUG 783 | if(abort === 1'bx) $display("ERROR: OUT2A: abort is unknown. (%t)", $time); 784 | if(pid_seq_err === 1'bx)$display("ERROR: OUT2A: rx_data_done is unknown. (%t)", $time); 785 | `endif 786 | // synopsys translate_on 787 | if(abort) next_state = IDLE; 788 | else 789 | 790 | if(send_stall_r) 791 | begin 792 | token_pid_sel_d = STALL; 793 | send_token_d = 1'b1; 794 | next_state = IDLE; 795 | end 796 | else 797 | if(ep_full) 798 | begin 799 | token_pid_sel_d = NACK; 800 | send_token_d = 1'b1; 801 | next_state = IDLE; 802 | end 803 | else 804 | begin 805 | token_pid_sel_d = ACK; 806 | send_token_d = 1'b1; 807 | if(pid_seq_err) next_state = IDLE; 808 | else next_state = UPDATE; 809 | end 810 | end 811 | 812 | UPDATEW: 813 | begin 814 | // synopsys translate_off 815 | `ifdef USBF_VERBOSE_DEBUG 816 | $display("PE: Entered state UPDATEW (%t)", $time); 817 | `endif 818 | // synopsys translate_on 819 | next_state = UPDATE; 820 | end 821 | 822 | UPDATE: 823 | begin 824 | // synopsys translate_off 825 | `ifdef USBF_VERBOSE_DEBUG 826 | $display("PE: Entered state UPDATE (%t)", $time); 827 | `endif 828 | // synopsys translate_on 829 | uc_stat_set_d = 1'b1; 830 | next_state = IDLE; 831 | end 832 | endcase 833 | end 834 | 835 | endmodule 836 | 837 | --------------------------------------------------------------------------------