OpenCores
URL https://opencores.org/ocsvn/opb_usblite/opb_usblite/trunk

Subversion Repositories opb_usblite

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 6 to Rev 7
    Reverse comparison

Rev 6 → Rev 7

/opb_usblite/tags/R1/doc/readme.txt
0,0 → 1,27
--
-- opb_usblite - opb_uartlite replacement
--
-- opb_usblite - opb_uartlite replacement for Xilinx Microblaze processor written
-- in VHDL and Verilog. The opb_usblite is compatible with the USB CDC profile and
-- works with microsoft usbser virtual comport driver (VCD).
--
-- opb_usblite is using components by Rudolf Usselmann see
-- http://www.opencores.org/cores/usb_phy/
-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
-- MAKE SURE TO READ THEIR LICENSE TERMS BEFORE USING THIS IP-CORE
--
-- Copyright (C) 2010 Ake Rehnman
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
/opb_usblite/tags/R1/doc/README2.txt
0,0 → 1,453
-----------------------------------------
USB 1.1 / 2.0 serial data transfer core
-----------------------------------------
 
Version: 2009-10-06
Author: Joris van Rantwijk
Language: VHDL
License: GPL - GNU General Public License
Website: http://www.xs4all.nl/~rjoris/fpga/usb.html
 
 
usb_serial is a synthesizable VHDL core, implementing serial data
transfer over USB. Combined with a UTMI-compatible USB transceiver
chip, this core acts as a USB device that transfers a byte stream
in both directions over the bus.
 
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
 
-----------------------------------------
See MANUAL.pdf for detailed information.
-----------------------------------------
 
 
Files in this package
---------------------
 
COPYING Text of the GNU General Public License.
MANUAL.pdf Manual for usb_serial core.
Makefile Script to synthesizes the VHDL code for Xilinx devices.
usb_serial.vhdl Main core.
usb_control.vhdl Sub-entity handling control requests.
usb_init.vhdl Sub-entity handling device initialization.
usb_packet.vhdl Sub-entity for sending and receiving packets.
usb_transact.vhdl Sub-entity for transaction handling.
usbtest.vhdl Sample top-level design for testing.
te0146.ucf Constraints file for a TE0146 FPGA module.
testdev.py Python program running a torture test on usbtest.bit.
perftest.c C program measuring data transfer performance on Linux.
crcformula.py Python program for computing CRC update formulas.
 
----
 
The rest of this file contains some unorganized notitions.
 
 
Changes from version 2007-04-19 to 2009-10-06
---------------------------------------------
 
* usb_init:
+ Add generic HSSUPPORT
+ Rename USBRST to I_USBRST
+ Add output signal I_HIGHSPEED, active iff attached in high speed mode
+ Add output signal I_SUSPEND, active iff suspended by host
+ Add output P_CHIRPK
+ Add output PHY_XCVRSELECT
+ Add output PHY_TERMSELECT
+ Implement HS handshake / FS fallback protocol.
+ Implement suspend detection.
 
* usb_packet:
+ Add input P_CHIRPK.
+ Send continuous chirp-K when P_CHIRPK asserted.
+ Use signal s_dataout instead of variable v_dataout as register.
+ Recognize PING as a valid token packet.
+ Clear PHY_TXVALID and PHY_DATAOUT in response to RESET.
+ Pay attention to PHY_RXERROR while receiving handshake packet.
+ Eliminate ST_RFIN state and release P_RXACT one cycle earlier,
i.e. at the same time as raising P_RXFIN. (Necessary because PHY_RXACTIVE
may be low for just a single cycle between packets).
 
* usb_transact:
+ Verified that releasing P_RXACT while asserting P_RXFIN is handled fine.
+ Add generic HSSUPPORT.
+ Add output signal T_PING.
+ Add input signal T_NYET; must be valid when SEND goes down.
+ Eliminate ST_FIN so that we will always be in time to catch the rising
edge of P_RXACT even in the cycle immediately following P_RXFIN.
+ Implement PING transaction (same application timing as IN transaction).
+ Implement NYET handshake.
+ Reduce guaranteed decision time for application from 10 to 2 cycles.
+ Separate inter-packet delay and response timeout values for FS and HS;
increase FS inter-packet delay from 10 to 14 cycles.
+ Ignore our own transmitted packet while waiting for ACK.
+ Fail transaction if empty packet received while waiting for ACK or DATA.
+ Again rejected (after extensive consideration) the idea of using
PHY_LINESTATE for inter-packet delay, even though this is actually
required according to the UTMI standard. It is difficult to reliably
relate PHY_LINESTATE to logical send/receive activity. The best I can come
up with is to have an inter-packet timer which counts down iff the line
is idle as indicated by PHY_LINESTATE. But detecting line idle in FS mode
depends on the SE0-to-J transition, which makes the scheme vulnerable in
case the SE0 state is missed somehow.
So we stay with the concept of inter-packet timing based on PHY_RXACTIVE
plus a much relaxed timeout for host responses.
Note to self: please don't waste more time on this.
 
* usb_control:
+ Add generic HSSUPPORT.
+ Rename upstream interface signals to C_xxx.
+ Add input signal T_PING (ignored, therefore always ACK-ed).
+ Add output signal T_NYET (always driven to zero).
+ Redesigned descriptor ROM interface.
+ Implement ENDPOINT_HALT feature.
+ Implement self-powered bit in status word.
 
* usb_serial:
+ Changed interface to sub-entities.
+ Redesigned descriptor ROM interface.
+ Implement device_qualifier and other_speed_configuration descriptors.
+ Split single block RAM into three separate RAMs for RX buffer,
TX buffer and descriptor ROM.
+ Streamline state machine.
+ Implement PING / NYET handshake.
+ Add RXLEN / TXROOM status signals.
+ Add TXCORK control signal.
+ Add HIGHSPEED and SUSPEND signals to application interface.
+ Prepare for separate clock domains.
+ Support halting of endpoints.
 
* usb_serial_wb:
+ Removed. Wishbone is not intended for this kind of thing.
 
* usbtest:
+ Add testing of TXCORK flag.
+ Add blast mode for test of fast streaming transmission.
 
* Makefile:
+ Fix command line options for newer versions of Xilinx tools.
 
* testdev.py:
+ Testing of TXCORK feature.
+ Adapt test parameters for bigger TX/RX buffers in the device.
+ Test partial read of incoming data.
 
* perftest.c
+ Performance measurements.
 
 
Performance measurements
------------------------
 
Version 20090929:
 
Performance full speed, RX 128, TX 128, libusb-1.0 async:
RX 67108864 bytes in 61.673 s = 1088137 bytes/s
TX 64000000 bytes in 58.816 s = 1088146 bytes/s
 
Performance high speed, RX 2k, TX 1k, libusb-1.0 async:
RX 67108864 bytes in 1.490 s = 45049302 bytes/s
TX 64000000 bytes in 1.953 s = 32766457 bytes/s
 
 
Intermediate version 20090917:
( Comparing performance of normal code against error injection. )
 
Performance FS, normal:
RX 67108864 bytes in 61.674 s = 1088118 bytes/s
TX 64000000 bytes in 58.820 s = 1088073 bytes/s
 
Performance HS, normal:
RX 67108864 bytes in 1.535 s = 43727704 bytes/s
TX 64000000 bytes in 1.961 s = 32635212 bytes/s
 
Performance FS, error injection:
RX 67108864 bytes in 82.163 s = 816777 bytes/s
TX 64000000 bytes in 78.420 s = 816113 bytes/s
 
Performance HS, error injection:
RX 67108864 bytes in 1.965 s = 34144882 bytes/s
TX 64000000 bytes in 3.110 s = 20576099 bytes/s
 
 
Tested
------
 
+ Suspend/resume with SUSPEND signal used as clock gate.
+ Verified that none of the following events occur during functional test:
aborted transaction; duplicate OUT packet; OUT-NAK in high speed mode.
+ Deliberate error injection: works ok, but reduced performance as expected.
+ Tested SetFeature(ENDPOINT_HALT)
+ Functional test and performance test:
+ full speed, konijn, linux, RX 128, TX 128
+ full speed, konijn, linux, RX 128, TX 128, no_fullpacket
+ full speed, konijn, linux, RX 1k, TX 128
+ full speed, konijn, linux, RX 128, TX 1k (one time hang in perftest)
+ full speed, konijn, linux, RX 2k, TX 1k
+ high speed, konijn, linux, RX 1k, TX 1k (problems with usbserial, fixed)
+ high speed, konijn, linux, RX 2k, TX 1k
+ high speed, konijn, linux, RX 2k, TX 1k, no_fullpacket
+ high speed, konijn, linux, RX 1k, TX 2k
+ high speed, konijn, linux, RX 4k, TX 2k
+ full speed, schildpad, linux, RX 128, TX 128
+ fallback to full speed, schildpad, linux, RX 2k, TX 1k
+ full speed, sron, linux
+ high speed, sron, linux
+ Limited functional test:
+ full speed, schildpad, Win2k, RX 128, TX 128 (fails due to zero length packet)
+ full speed, schildpad, Win2k, RX 128, TX 128, no_fullpacket
+ fallback to full speed, schildpad, Win2k, RX 2k, TX 1k, no_fullpacket (failed)
+ full speed, iBook, RX 128, TX 128
+ high speed, iBook, RX 2k, TX 1k
+ full speed, sron, Windows XP
+ high speed, sron, Windows XP
+ Performance:
+ full speed, konijn, linux, RX 128, TX 128
+ high speed, konijn, linux, RX 2k, TX 1k
+ Verify descriptors, device, config, qualifier, other_speed_config, status:
+ full speed, konijn, linux
+ high speed, konijn, linux
+ Test suspend/resume:
+ full speed, konijn
+ full speed, iBook
+ high speed, konijn
+ high speed, iBook
+ Plug-in handling:
+ high speed, konijn, linux
+ fallback to full speed, schildpad, linux
+ high speed, sron, Windows XP
+ high speed, iBook
 
 
Misc issues
-----------
 
* USB 2.0 high speed requires support of SET_FEATURE(TEST_MODE).
We will not implement this.
Reason: overkill, no way to test it properly.
 
* Suspend detection is implemented.
The output signal SUSPEND from usb_serial can be used to combinatorially
drive the suspend pin on the UTMI interface. Reset of the SUSPEND signal
is asynchronous and can therefore work even when the FPGA has no clock.
 
* We will not implement detection of SOF packets.
Reason: usefulness is questionable.
 
* No separate clock domains.
Reason: difficult to implement, very hard to validate.
 
* There is a problem with empty packets under Windows 2000.
The Windows 2000 version of usbser.dll chokes on unexpected empty packets,
such as send by the device after a final full-length packet.
This has been solved in Windows XP.
 
* A babble error occurs when a device sends more bytes than expected
by the host, even if this is less than the maximum packet size.
This may happen if software submits an IN request which is not
a multiple of the maximum packet size. It may also happen if the host
sends an invalid standard device request, for example GET_STATUS with
wLength=0.
To avoid this, always submit IN requests with the transfer size set to
a multiple of the maximum packet size.
Note that babble errors can freeze the host controller; this is a known
bug of VIA UHCI controllers:
http://www.mail-archive.com/linux-usb-devel@lists.sourceforge.net/msg17019.html
 
* After plugging in, the Linux kernel log shows
"device descriptor read/64, error -62" and
"Cannot enable port 2. Maybe the USB cable is bad?".
After the errors, the kernel retries and the second attempt is successful.
It seems pretty reproducible; occurs in FS and HS mode after plugin,
but not after soft-reattach of the device.
It is worse under Win2k; the USB subsystem seems to crash after plugging in.
Theory: Initialization of the FPGA initialization takes longer than 100 ms,
causing us to miss the initial port handshake.
 
* Even 8k TX buffer is not sufficient for loss-free transmission @ 25 MB/s.
Loss rate becomes much higher under CPU load.
 
 
FPGA Resources
--------------
 
( From mapper log file; target = XC3S1000 )
 
Design: usbtest-20070419
Tools: Xilinx Webpack 7.1i
 
Number of errors: 0
Number of warnings: 2
Logic Utilization:
Number of Slice Flip Flops: 301 out of 15,360 1%
Number of 4 input LUTs: 969 out of 15,360 6%
Logic Distribution:
Number of occupied Slices: 573 out of 7,680 7%
Number of Slices containing only related logic: 573 out of 573 100%
Number of Slices containing unrelated logic: 0 out of 573 0%
*See NOTES below for an explanation of the effects of unrelated logic
Total Number 4 input LUTs: 1,034 out of 15,360 6%
Number used as logic: 969
Number used as a route-thru: 65
Number of bonded IOBs: 31 out of 173 17%
IOB Flip Flops: 27
Number of Block RAMs: 2 out of 24 8%
Number of GCLKs: 1 out of 8 12%
 
Total equivalent gate count for design: 140,539
 
----
 
Design: usbtest-20090927, full speed, RX 128, TX 128
Tools: Xilinx Webpack 7.1i
 
Number of errors: 0
Number of warnings: 2
Logic Utilization:
Number of Slice Flip Flops: 337 out of 15,360 2%
Number of 4 input LUTs: 1,151 out of 15,360 7%
Logic Distribution:
Number of occupied Slices: 671 out of 7,680 8%
Number of Slices containing only related logic: 671 out of 671 100%
Number of Slices containing unrelated logic: 0 out of 671 0%
*See NOTES below for an explanation of the effects of unrelated logic
Total Number 4 input LUTs: 1,249 out of 15,360 8%
Number used as logic: 1,151
Number used as a route-thru: 98
Number of bonded IOBs: 31 out of 173 17%
IOB Flip Flops: 31
Number of Block RAMs: 4 out of 24 16%
Number of GCLKs: 1 out of 8 12%
 
Total equivalent gate count for design: 273,110
 
----
 
Design: usbtest-20090929, high speed, RX 2k, TX 1k
Tools: Xilinx Webpack 7.1i
 
Number of errors: 0
Number of warnings: 2
Logic Utilization:
Number of Slice Flip Flops: 380 out of 15,360 2%
Number of 4 input LUTs: 1,349 out of 15,360 8%
Logic Distribution:
Number of occupied Slices: 787 out of 7,680 10%
Number of Slices containing only related logic: 787 out of 787 100%
Number of Slices containing unrelated logic: 0 out of 787 0%
*See NOTES below for an explanation of the effects of unrelated logic
Total Number 4 input LUTs: 1,465 out of 15,360 9%
Number used as logic: 1,349
Number used as a route-thru: 116
Number of bonded IOBs: 31 out of 173 17%
IOB Flip Flops: 34
Number of Block RAMs: 4 out of 24 16%
Number of GCLKs: 1 out of 8 12%
 
Total equivalent gate count for design: 274,894
 
----
 
Design: usb_serial only, 20090929, full speex RX 128, TX 128
Tools: Xilinx Webpack 7.1i
 
Number of errors: 0
Number of warnings: 2
Logic Utilization:
Number of Slice Flip Flops: 235 out of 15,360 1%
Number of 4 input LUTs: 841 out of 15,360 5%
Logic Distribution:
Number of occupied Slices: 479 out of 7,680 6%
Number of Slices containing only related logic: 479 out of 479 100%
Number of Slices containing unrelated logic: 0 out of 479 0%
*See NOTES below for an explanation of the effects of unrelated logic
Total Number 4 input LUTs: 899 out of 15,360 5%
Number used as logic: 841
Number used as a route-thru: 58
Number of bonded IOBs: 69 out of 173 39%
IOB Flip Flops: 33
Number of Block RAMs: 3 out of 24 12%
Number of GCLKs: 1 out of 8 12%
 
Total equivalent gate count for design: 204,527
 
----
 
Design: usb_serial only, 20090929, high speed, RX 2k, TX 1k
Tools: Xilinx Webpack 7.1i
 
Number of errors: 0
Number of warnings: 2
Logic Utilization:
Number of Slice Flip Flops: 285 out of 15,360 1%
Number of 4 input LUTs: 1,062 out of 15,360 6%
Logic Distribution:
Number of occupied Slices: 610 out of 7,680 7%
Number of Slices containing only related logic: 610 out of 610 100%
Number of Slices containing unrelated logic: 0 out of 610 0%
*See NOTES below for an explanation of the effects of unrelated logic
Total Number 4 input LUTs: 1,139 out of 15,360 7%
Number used as logic: 1,062
Number used as a route-thru: 77
Number of bonded IOBs: 76 out of 173 43%
IOB Flip Flops: 36
Number of Block RAMs: 3 out of 24 12%
Number of GCLKs: 1 out of 8 12%
 
Total equivalent gate count for design: 206,559
 
----
 
Design: usb_serial only, 20090929, full speed, RX 128, TX 128
Tools: Xilinx ISE 11.2
 
Number of errors: 0
Number of warnings: 1
Logic Utilization:
Number of Slice Flip Flops: 227 out of 15,360 1%
Number of 4 input LUTs: 808 out of 15,360 5%
Logic Distribution:
Number of occupied Slices: 459 out of 7,680 5%
Number of Slices containing only related logic: 459 out of 459 100%
Number of Slices containing unrelated logic: 0 out of 459 0%
*See NOTES below for an explanation of the effects of unrelated logic.
Total Number of 4 input LUTs: 835 out of 15,360 5%
Number used as logic: 808
Number used as a route-thru: 27
The Slice Logic Distribution report is not meaningful if the design is
over-mapped for a non-slice resource or if Placement fails.
Number of bonded IOBs: 69 out of 173 39%
IOB Flip Flops: 27
Number of RAMB16s: 3 out of 24 12%
Number of BUFGMUXs: 1 out of 8 12%
 
----
 
Design: usb_serial only, 20090929, high speed, RX 2k, TX 1k
Tools: Xilinx ISE 11.2
 
Number of errors: 0
Number of warnings: 2
Logic Utilization:
Number of Slice Flip Flops: 265 out of 15,360 1%
Number of 4 input LUTs: 955 out of 15,360 6%
Logic Distribution:
Number of occupied Slices: 555 out of 7,680 7%
Number of Slices containing only related logic: 555 out of 555 100%
Number of Slices containing unrelated logic: 0 out of 555 0%
*See NOTES below for an explanation of the effects of unrelated logic.
Total Number of 4 input LUTs: 1,010 out of 15,360 6%
Number used as logic: 955
Number used as a route-thru: 55
The Slice Logic Distribution report is not meaningful if the design is
over-mapped for a non-slice resource or if Placement fails.
Number of bonded IOBs: 76 out of 173 43%
IOB Flip Flops: 32
Number of RAMB16s: 3 out of 24 12%
Number of BUFGMUXs: 1 out of 8 12%
 
----
/opb_usblite/tags/R1/doc/README3.txt
0,0 → 1,99
 
USB 1.1 PHY
==========
 
Status
------
This core is done. It was tested with a USB 1.1 core I have written on
a XESS XCV800 board with a a Philips PDIUSBP11A transceiver.
I have NOT yet tested it with my USB 2.0 Function IP core.
 
Test Bench
----------
There is no test bench, period ! As I said above I have tested this core
in real hardware and it works just fine.
 
Documentation
-------------
Sorry, there is none. I just don't have the time to write it. I have tried
to follow the UTMI interface specification from USB 2.0.
'phy_mode' selects between single ended and differential tx_phy output. See
Philips ISP 1105 transceiver data sheet for an explanation of it's MODE
select pin (see Note below).
Currently this PHY only operates in Full-Speed mode. Required clock frequency
is 48MHz, from which the 12MHz USB transmit and receive clocks are derived.
 
RxError reports the following errors:
- sync errors
Could not synchronize to incoming bit stream
- Bit Stuff Error
Stuff bit had the wrong value (expected '0' got '1')
- Byte Error
Got a EOP (se0) before finished assembling a full byteAll of those errors
are or'ed together and reported via RxError.
 
Note:
1) "phy_tx_mode" selects the PHY Transmit Mode:
When phy_tx_mode is '0' the outputs are encoded as:
txdn, txdp
0 0 Differential Logic '0'
0 1 Differential Logic '1'
1 0 Single Ended '0'
1 1 Single Ended '0'
 
When phy_tx_mode is '1' the outputs are encoded as:
txdn, txdp
0 0 Single Ended '0'
0 1 Differential Logic '1'
1 0 Differential Logic '0'
1 1 Illegal State
 
See PHILIPS Transceiver Data Sheet for: ISP1105, ISP1106 and ISP1107
for more details.
 
2) "usb_rst" Indicates a USB Bus Reset (this output is also or'ed with
the reset input).
 
Misc
----
The USB 1.1 Phy Project Page is:
http://www.opencores.org/cores/usb_phy
 
To find out more about me (Rudolf Usselmann), please visit:
http://www.asics.ws
 
 
Directory Structure
-------------------
[core_root]
|
+-doc Documentation
|
+-bench--+ Test Bench
| +-verilog Verilog Sources
| +-vhdl VHDL Sources
|
+-rtl----+ Core RTL Sources
| +-verilog Verilog Sources
| +-vhdl VHDL Sources
|
+-sim----+
| +-rtl_sim---+ Functional verification Directory
| | +-bin Makefiles/Run Scripts
| | +-run Working Directory
| |
| +-gate_sim--+ Functional & Timing Gate Level
| | Verification Directory
| +-bin Makefiles/Run Scripts
| +-run Working Directory
|
+-lint--+ Lint Directory Tree
| +-bin Makefiles/Run Scripts
| +-run Working Directory
| +-log Linter log & result files
|
+-syn---+ Synthesis Directory Tree
| +-bin Synthesis Scripts
| +-run Working Directory
| +-log Synthesis log files
| +-out Synthesis Output
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/vhdl/opb_usblite_core.vhd
0,0 → 1,525
--
-- opb_usblite - opb_uartlite replacement
--
-- opb_usblite is using components from Rudolf Usselmann see
-- http://www.opencores.org/cores/usb_phy/
-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
--
-- Copyright (C) 2010 Ake Rehnman
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity OPB_USBLITE_Core is
generic (
C_PHYMODE : std_logic := '1';
C_VENDORID : std_logic_vector(15 downto 0) := X"1234";
C_PRODUCTID : std_logic_vector(15 downto 0) := X"5678";
C_VERSIONBCD : std_logic_vector(15 downto 0) := X"0200";
C_SELFPOWERED : boolean := false;
C_RXBUFSIZE_BITS: integer range 7 to 12 := 10;
C_TXBUFSIZE_BITS: integer range 7 to 12 := 10
);
port (
Clk : in std_logic;
Reset : in std_logic;
Usb_Clk : in std_logic;
-- OPB signals
OPB_CS : in std_logic;
OPB_ABus : in std_logic_vector(0 to 1);
OPB_RNW : in std_logic;
OPB_DBus : in std_logic_vector(7 downto 0);
SIn_xferAck : out std_logic;
SIn_DBus : out std_logic_vector(7 downto 0);
Interrupt : out std_logic;
-- USB signals
txdp : out std_logic;
txdn : out std_logic;
txoe : out std_logic;
rxd : in std_logic;
rxdp : in std_logic;
rxdn : in std_logic
);
end entity OPB_USBLITE_Core;
 
library unisim;
use unisim.all;
 
architecture akre of OPB_USBLITE_Core is
 
component usb_serial is
 
generic (
 
-- Vendor ID to report in device descriptor.
VENDORID : std_logic_vector(15 downto 0);
 
-- Product ID to report in device descriptor.
PRODUCTID : std_logic_vector(15 downto 0);
 
-- Product version to report in device descriptor.
VERSIONBCD : std_logic_vector(15 downto 0);
 
-- Support high speed mode.
HSSUPPORT : boolean := false;
 
-- Set to true if the device never draws power from the USB bus.
SELFPOWERED : boolean := false;
 
-- Size of receive buffer as 2-logarithm of the number of bytes.
-- Must be at least 10 (1024 bytes) for high speed support.
RXBUFSIZE_BITS: integer range 7 to 12 := 11;
 
-- Size of transmit buffer as 2-logarithm of the number of bytes.
TXBUFSIZE_BITS: integer range 7 to 12 := 10
);
port (
 
-- 60 MHz UTMI clock.
CLK : in std_logic;
 
-- Synchronous reset; clear buffers and re-attach to the bus.
RESET : in std_logic;
 
-- High for one clock when a reset signal is detected on the USB bus.
-- Note: do NOT wire this signal to RESET externally.
USBRST : out std_logic;
 
-- High when the device is operating (or suspended) in high speed mode.
HIGHSPEED : out std_logic;
 
-- High while the device is suspended.
-- Note: This signal is not synchronized to CLK.
-- It may be used to asynchronously drive the UTMI SuspendM pin.
SUSPEND : out std_logic;
 
-- High when the device is in the Configured state.
ONLINE : out std_logic;
 
-- High if a received byte is available on RXDAT.
RXVAL : out std_logic;
 
-- Received data byte, valid if RXVAL is high.
RXDAT : out std_logic_vector(7 downto 0);
 
-- High if the application is ready to receive the next byte.
RXRDY : in std_logic;
 
-- Number of bytes currently available in receive buffer.
RXLEN : out std_logic_vector((RXBUFSIZE_BITS-1) downto 0);
 
-- High if the application has data to send.
TXVAL : in std_logic;
 
-- Data byte to send, must be valid if TXVAL is high.
TXDAT : in std_logic_vector(7 downto 0);
 
-- High if the entity is ready to accept the next byte.
TXRDY : out std_logic;
 
-- Number of free byte positions currently available in transmit buffer.
TXROOM : out std_logic_vector((TXBUFSIZE_BITS-1) downto 0);
 
-- Temporarily suppress transmissions at the outgoing endpoint.
-- This gives the application an oppertunity to fill the transmit
-- buffer in order to blast data efficiently in big chunks.
TXCORK : in std_logic;
 
PHY_DATAIN : in std_logic_vector(7 downto 0);
PHY_DATAOUT : out std_logic_vector(7 downto 0);
PHY_TXVALID : out std_logic;
PHY_TXREADY : in std_logic;
PHY_RXACTIVE : in std_logic;
PHY_RXVALID : in std_logic;
PHY_RXERROR : in std_logic;
PHY_LINESTATE : in std_logic_vector(1 downto 0);
PHY_OPMODE : out std_logic_vector(1 downto 0);
PHY_XCVRSELECT: out std_logic;
PHY_TERMSELECT: out std_logic;
PHY_RESET : out std_logic
);
end component usb_serial;
 
component usb_phy is
port (
clk : in std_logic;
rst : in std_logic;
phy_tx_mode : in std_logic;
usb_rst : out std_logic;
-- Transciever Interface
txdp : out std_logic;
txdn : out std_logic;
txoe : out std_logic;
rxd : in std_logic;
rxdp : in std_logic;
rxdn : in std_logic;
 
-- UTMI Interface
DataOut_i : in std_logic_vector (7 downto 0);
TxValid_i : in std_logic;
TxReady_o : out std_logic;
RxValid_o : out std_logic;
RxActive_o : out std_logic;
RxError_o : out std_logic;
DataIn_o : out std_logic_vector (7 downto 0);
LineState_o : out std_logic_vector (1 downto 0)
);
end component usb_phy;
constant RX_FIFO_ADR : std_logic_vector(0 to 1) := "00";
constant TX_FIFO_ADR : std_logic_vector(0 to 1) := "01";
constant STATUS_REG_ADR : std_logic_vector(0 to 1) := "10";
constant CTRL_REG_ADR : std_logic_vector(0 to 1) := "11";
-- ADDRESS MAP
-- ===========
-- RX FIFO base + $0
-- TX FIFO base + $4
-- CONTROL REG base + $8
-- STATUS REG base + $C
 
 
-- Read Only
signal status_Reg : std_logic_vector(7 downto 0);
-- bit 0 rx_Data_Present
-- bit 1 rx_Buffer_Full
-- bit 2 tx_Buffer_Empty
-- bit 3 tx_Buffer_Full
-- bit 4 interrupt flag
-- bit 5 not used
-- bit 6 online flag
-- bit 7 suspend flag
-- Write Only
-- bit 0 Reset_TX_FIFO -- not used
-- bit 1 Reset_RX_FIFO -- not used
-- bit 2-3 Dont'Care
-- bit 4 enable_rxinterrupts
-- bit 5 Dont'Care
-- bit 6 enable_txinterrupts
-- bit 7 tx_enable -- not used
signal enable_txinterrupts : std_logic;
signal enable_rxinterrupts : std_logic;
signal read_RX_FIFO : std_logic;
signal reset_RX_FIFO : std_logic;
signal TX_EN : std_logic;
signal write_TX_FIFO : std_logic;
signal reset_TX_FIFO : std_logic;
signal tx_BUFFER_FULL : std_logic;
signal tx_Buffer_Empty : std_logic;
signal rx_Data_Present : std_logic;
signal rx_BUFFER_FULL : std_logic;
 
signal xfer_Ack : std_logic;
signal xfer_Ack1 : std_logic;
signal xfer_Ack2 : std_logic;
signal Interrupt_r : std_logic;
signal read_rx_fifo_r : std_logic;
signal read_rx_fifo_rr : std_logic;
signal read_rx_fifo_rrr : std_logic;
signal write_tx_fifo_r : std_logic;
signal write_tx_fifo_rr : std_logic;
signal write_tx_fifo_rrr : std_logic;
 
signal usbrst : std_logic;
signal rxval : std_logic;
signal rxdat : std_logic_vector (7 downto 0);
signal rxrdy : std_logic;
signal txval : std_logic;
signal txempty : std_logic;
signal txfull : std_logic;
signal rxfull : std_logic;
signal txdat : std_logic_vector (7 downto 0);
signal txrdy : std_logic;
signal phy_datain : std_logic_vector (7 downto 0);
signal phy_dataout : std_logic_vector (7 downto 0);
signal phy_txvalid : std_logic;
signal phy_txready : std_logic;
signal phy_rxactive : std_logic;
signal phy_rxvalid : std_logic;
signal phy_rxerror : std_logic;
signal phy_linestate : std_logic_vector (1 downto 0);
signal phy_reset : std_logic;
signal phy_resetn : std_logic;
signal phy_usb_rst : std_logic;
signal highspeed : std_logic;
signal suspend : std_logic;
signal online : std_logic;
signal rxlen : std_logic_vector((C_RXBUFSIZE_BITS-1) downto 0);
signal txroom : std_logic_vector((C_TXBUFSIZE_BITS-1) downto 0);
attribute TIG : string;
attribute TIG of Reset : signal is "yes";
attribute TIG of write_TX_FIFO : signal is "yes";
attribute TIG of read_RX_FIFO : signal is "yes";
attribute TIG of rxdat : signal is "yes";
attribute TIG of txdat : signal is "yes";
attribute TIG of rxval : signal is "yes";
attribute TIG of txrdy : signal is "yes";
attribute TIG of txempty : signal is "yes";
attribute TIG of txfull : signal is "yes";
attribute TIG of rxfull : signal is "yes";
attribute TIG of online : signal is "yes";
attribute TIG of suspend : signal is "yes";
constant C_TXFULL : std_logic_vector((C_TXBUFSIZE_BITS-1) downto 0) := (others=>'0');
constant C_TXEMPTY : std_logic_vector((C_TXBUFSIZE_BITS-1) downto 0) := (others=>'1');
constant C_RXFULL : std_logic_vector((C_RXBUFSIZE_BITS-1) downto 0) := (others=>'1');
constant C_RXEMPTY : std_logic_vector((C_RXBUFSIZE_BITS-1) downto 0) := (others=>'0');
begin -- architecture akre
 
-----------------------------------------------------------------------------
-- Instanciating Components
-----------------------------------------------------------------------------
usb_serial_inst : usb_serial
generic map (
VENDORID => C_VENDORID,
PRODUCTID => C_PRODUCTID,
VERSIONBCD => C_VERSIONBCD,
HSSUPPORT => false,
SELFPOWERED => C_SELFPOWERED,
RXBUFSIZE_BITS => C_RXBUFSIZE_BITS,
TXBUFSIZE_BITS => C_TXBUFSIZE_BITS
)
port map (
CLK => usb_clk, --in
RESET => reset, --in
USBRST => usbrst, --out
HIGHSPEED => highspeed, --out
SUSPEND => suspend, --out
ONLINE => online, --out
RXVAL => rxval, --out
RXDAT => rxdat, --out
RXRDY => rxrdy, --in
RXLEN => rxlen, --out
TXVAL => txval, --in
TXDAT => txdat, --in
TXRDY => txrdy, --out
TXROOM => txroom, --out
TXCORK => '0', --in
PHY_DATAIN => phy_datain, --in
PHY_DATAOUT => phy_dataout, --out
PHY_TXVALID => phy_txvalid, --out
PHY_TXREADY => phy_txready, --in
PHY_RXACTIVE => phy_rxactive, --in
PHY_RXVALID => phy_rxvalid, --in
PHY_RXERROR => phy_rxerror, --in
PHY_LINESTATE => phy_linestate, --in
PHY_OPMODE => open, --out
PHY_XCVRSELECT => open, --out
PHY_TERMSELECT => open, --out
PHY_RESET => phy_reset --out
);
 
phy_resetn <= not(phy_reset);
 
usb_phy_inst : usb_phy
port map(
clk => Usb_Clk, --in 48MHz
rst => phy_resetn, --in
phy_tx_mode => C_PHYMODE, --in
usb_rst => phy_usb_rst, --out
txdp => txdp, --out
txdn => txdn, --out
txoe => txoe, --out
rxd => rxd, --in
rxdp => rxdp, --in
rxdn => rxdn, --in
DataOut_i => phy_dataout, --in
TxValid_i => phy_txvalid, --in
TxReady_o => phy_txready, --out
RxValid_o => phy_rxvalid, --out
RxActive_o => phy_rxactive, --out
RxError_o => phy_rxerror, --out
DataIn_o => phy_datain, --out
LineState_o => phy_linestate --out
);
-----------------------------------------------------------------------------
-- Status register / Control register
-----------------------------------------------------------------------------
status_Reg(0) <= rx_Data_Present;
status_Reg(1) <= rx_BUFFER_FULL;
status_Reg(2) <= tx_Buffer_Empty;
status_Reg(3) <= tx_BUFFER_FULL;
status_Reg(4) <= Interrupt_r;
status_Reg(5) <= '0';
status_Reg(6) <= online;
status_Reg(7) <= suspend;
 
-----------------------------------------------------------------------------
-- Control / Status Register Handling
-----------------------------------------------------------------------------
 
process (clk, reset) is
begin
if (reset = '1') then -- asynchronous reset (active high)
reset_TX_FIFO <= '1';
reset_RX_FIFO <= '1';
enable_rxinterrupts <= '0';
enable_txinterrupts <= '0';
TX_EN <= '0';
xfer_Ack2 <= '0';
elsif (clk'event and clk = '1') then -- rising clock edge
reset_TX_FIFO <= '0';
reset_RX_FIFO <= '0';
xfer_Ack2 <= '0';
if (OPB_CS = '1') and (OPB_RNW = '0') and (OPB_ABus = CTRL_REG_ADR) then
reset_TX_FIFO <= OPB_DBus(0);
reset_RX_FIFO <= OPB_DBus(1);
enable_rxinterrupts <= OPB_DBus(4);
enable_txinterrupts <= OPB_DBus(6);
TX_EN <= OPB_DBus(7);
xfer_Ack2 <= '1';
end if;
if (OPB_CS = '1') and (OPB_RNW = '1') and (OPB_ABus = STATUS_REG_ADR) then
xfer_Ack2 <= '1';
end if;
end if;
end process;
 
-----------------------------------------------------------------------------
-- Interrupt handling
-----------------------------------------------------------------------------
process (clk, reset)
begin
if reset = '1' then -- asynchronous reset (active high)
Interrupt_r <= '0';
elsif clk'event and clk = '1' then -- rising clock edge
Interrupt_r <= (enable_rxinterrupts and rx_Data_Present) or
(enable_txinterrupts and tx_Buffer_Empty);
end if;
end process;
Interrupt <= Interrupt_r;
-----------------------------------------------------------------------------
-- Handling the OPB bus interface
-----------------------------------------------------------------------------
process (clk, OPB_CS) is
begin
if (OPB_CS='0') then
xfer_Ack <= '0';
SIn_DBus <= (others => '0');
elsif (clk'event and clk='1') then
xfer_Ack <= xfer_Ack1 or xfer_Ack2;
SIn_DBus <= (others => '0');
if (OPB_RNW='1') then
if (OPB_ABus = STATUS_REG_ADR) then
SIn_DBus(7 downto 0) <= status_reg;
else
SIn_DBus(7 downto 0) <= rxdat;
end if;
end if;
end if;
end process;
SIn_xferAck <= xfer_Ack;
 
-----------------------------------------------------------------------------
-- Generating read and write pulses to the FIFOs
-----------------------------------------------------------------------------
process(clk,reset)
begin
if (reset='1') then
read_RX_FIFO <= '0';
write_TX_FIFO <= '0';
xfer_Ack1 <= '0';
elsif (clk'event and clk='1') then
tx_BUFFER_EMPTY <= txempty;
tx_BUFFER_FULL <= txfull;
rx_Data_Present <= rxval;
rx_Buffer_Full <= rxfull;
write_TX_FIFO <= '0';
read_RX_FIFO <= '0';
xfer_Ack1 <= '0';
if (OPB_CS='1' and OPB_RNW='0' and OPB_ABus=TX_FIFO_ADR) then
txdat <= OPB_DBus(7 downto 0);
write_TX_FIFO <= '1';
xfer_Ack1 <= '1';
end if;
if (OPB_CS='1' and OPB_RNW='1' and OPB_ABus=RX_FIFO_ADR) then
read_RX_FIFO <= '1';
xfer_Ack1 <= '1';
end if;
end if;
end process;
-----------------------------------------------------------------------------
-- Synchronization logic across clock domains
-----------------------------------------------------------------------------
process(usb_clk, reset)
begin
if (reset='1') then
read_RX_FIFO_r <= '0';
read_RX_FIFO_rr <= '0';
read_RX_FIFO_rrr <= '0';
write_TX_FIFO_r <= '0';
write_TX_FIFO_rr <= '0';
write_TX_FIFO_rrr <= '0';
elsif (usb_clk'event and usb_clk='1') then
rxrdy <= '0';
txval <= '0';
txfull <= '0';
rxfull <= '0';
txfull <= '0';
txempty <= '0';
if (rxlen = C_RXFULL) then
rxfull <= '1';
end if;
if (txroom = C_TXFULL) then
-- txfull <= '1';
txfull <= online and not(suspend);
end if;
if (txroom = C_TXEMPTY) then
txempty <= '1';
end if;
write_TX_FIFO_r <= write_TX_FIFO;
write_TX_FIFO_rr <= write_TX_FIFO_r;
write_TX_FIFO_rrr <= write_TX_FIFO_rr;
read_RX_FIFO_r <= read_RX_FIFO;
read_RX_FIFO_rr <= read_RX_FIFO_r;
read_RX_FIFO_rrr <= read_RX_FIFO_rr;
if (read_RX_FIFO_rrr='1' and read_RX_FIFO_rr='0') then
rxrdy <= '1';
end if;
if (write_TX_FIFO_rrr='1' and write_TX_FIFO_rr='0') then
txval <= '1';
end if;
end if;
end process;
end architecture akre;
 
 
 
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/vhdl/tb_USBLITE_Core.vhd
0,0 → 1,948
--
-- opb_usblite - opb_uartlite replacement
--
-- opb_usblite is using components from Rudolf Usselmann see
-- http://www.opencores.org/cores/usb_phy/
-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
--
-- Copyright (C) 2010 Ake Rehnman
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use STD.TEXTIO.all;
use IEEE.STD_LOGIC_TEXTIO.all;
 
 
entity tb_USBLITE_Core is
end entity tb_USBLITE_Core;
 
library unisim;
use unisim.all;
 
architecture akre of tb_USBLITE_Core is
 
component usb_phy is
port (
clk : in std_logic;
rst : in std_logic;
phy_tx_mode : in std_logic;
usb_rst : out std_logic;
-- Transciever Interface
txdp : out std_logic;
txdn : out std_logic;
txoe : out std_logic;
rxd : in std_logic;
rxdp : in std_logic;
rxdn : in std_logic;
 
-- UTMI Interface
DataOut_i : in std_logic_vector (7 downto 0);
TxValid_i : in std_logic;
TxReady_o : out std_logic;
RxValid_o : out std_logic;
RxActive_o : out std_logic;
RxError_o : out std_logic;
DataIn_o : out std_logic_vector (7 downto 0);
LineState_o : out std_logic_vector (1 downto 0)
);
end component usb_phy;
component OPB_USBLITE_Core is
generic (
C_PHYMODE : std_logic := '1';
C_VENDORID : std_logic_vector(15 downto 0) := X"1234";
C_PRODUCTID : std_logic_vector(15 downto 0) := X"5678";
C_VERSIONBCD : std_logic_vector(15 downto 0) := X"0200";
C_SELFPOWERED : boolean := false;
C_RXBUFSIZE_BITS: integer range 7 to 12 := 10;
C_TXBUFSIZE_BITS: integer range 7 to 12 := 10
);
port (
Clk : in std_logic;
Reset : in std_logic;
Usb_Clk : in std_logic;
-- OPB signals
OPB_CS : in std_logic;
OPB_ABus : in std_logic_vector(0 to 1);
OPB_RNW : in std_logic;
OPB_DBus : in std_logic_vector(7 downto 0);
SIn_xferAck : out std_logic;
SIn_DBus : out std_logic_vector(7 downto 0);
Interrupt : out std_logic;
-- USB signals
txdp : out std_logic;
txdn : out std_logic;
txoe : out std_logic;
rxd : in std_logic;
rxdp : in std_logic;
rxdn : in std_logic
);
end component OPB_USBLITE_Core;
signal clk : std_logic;
signal usbclk : std_logic;
signal reset : std_logic;
signal rxdp : std_logic;
signal rxdn : std_logic;
signal rxd : std_logic;
signal txdp : std_logic;
signal txdn : std_logic;
signal txoe : std_logic;
 
signal usbtxdata : std_logic_vector (7 downto 0);
signal usbtxvalid : std_logic;
signal usbtxready : std_logic;
signal usbrxvalid : std_logic;
signal usbrxactive : std_logic;
signal usbrxerror : std_logic;
signal usbrxdata : std_logic_vector (7 downto 0);
signal usblinestate : std_logic_vector (1 downto 0);
signal Bus2IP_CS : std_logic := '0';
signal Bus2IP_CE : std_logic := '0';
signal Bus2IP_Addr : std_logic_vector(0 to 31) := X"00000000";
signal Bus2IP_RNW : std_logic := '0';
signal Bus2IP_Data : std_logic_vector(0 to 31);
signal Bus2IP_BE : std_logic_vector(3 downto 0) := "0000";
signal IP2Bus_Ack : std_logic := '0';
signal IP2Bus_Data : std_logic_vector(0 to 31) := X"00000000";
signal Interrupt : std_logic := '0';
signal resetn : std_logic;
signal usbrxdata_r : std_logic_vector(7 downto 0);
-- type txmemarray is array (0 to 2048) of std_logic_vector(7 downto 0);
type txmemarray is array (0 to 255) of std_logic_vector(7 downto 0);
shared variable txmem : txmemarray;
-- type bufferarray is array (0 to 16384) of std_logic_vector(7 downto 0);
type bufferarray is array (0 to 255) of std_logic_vector(7 downto 0);
shared variable buffer1 : bufferarray;
shared variable buffer0 : bufferarray;
shared variable buffer1_last : integer;
shared variable len : integer;
shared variable setup_pid : std_logic;
shared variable error_cnt : integer;
 
constant USBF_T_PID_OUT : std_logic_vector(3 downto 0):="0001";
constant USBF_T_PID_IN : std_logic_vector(3 downto 0):="1001";
constant USBF_T_PID_SOF : std_logic_vector(3 downto 0):="0101";
constant USBF_T_PID_SETUP : std_logic_vector(3 downto 0):="1101";
constant USBF_T_PID_DATA0 : std_logic_vector(3 downto 0):="0011";
constant USBF_T_PID_DATA1 : std_logic_vector(3 downto 0):="1011";
constant USBF_T_PID_DATA2 : std_logic_vector(3 downto 0):="0111";
constant USBF_T_PID_MDATA : std_logic_vector(3 downto 0):="1111";
constant USBF_T_PID_ACK : std_logic_vector(3 downto 0):="0010";
constant USBF_T_PID_NACK : std_logic_vector(3 downto 0):="1010";
constant USBF_T_PID_STALL : std_logic_vector(3 downto 0):="1110";
constant USBF_T_PID_NYET : std_logic_vector(3 downto 0):="0110";
constant USBF_T_PID_PRE : std_logic_vector(3 downto 0):="1100";
constant USBF_T_PID_ERR : std_logic_vector(3 downto 0):="1100";
constant USBF_T_PID_SPLIT : std_logic_vector(3 downto 0):="1000";
constant USBF_T_PID_PING : std_logic_vector(3 downto 0):="0100";
constant USBF_T_PID_RES : std_logic_vector(3 downto 0):="0000";
constant GET_STATUS : std_logic_vector(7 downto 0) := X"00";
constant CLEAR_FEATURE : std_logic_vector(7 downto 0) := X"01";
constant SET_FEATURE : std_logic_vector(7 downto 0) := X"03";
constant SET_ADDRESS : std_logic_vector(7 downto 0) := X"05";
constant GET_DESCRIPTOR : std_logic_vector(7 downto 0) := X"06";
constant SET_DESCRIPTOR : std_logic_vector(7 downto 0) := X"07";
constant GET_CONFIG : std_logic_vector(7 downto 0) := X"08";
constant SET_CONFIG : std_logic_vector(7 downto 0) := X"09";
constant GET_INTERFACE : std_logic_vector(7 downto 0) := X"0a";
constant SET_INTERFACE : std_logic_vector(7 downto 0) := X"0b";
constant SYNCH_FRAME : std_logic_vector(7 downto 0) := X"0c";
procedure utmi_recv_pack (variable size : inout integer) is
begin
size := 0;
while (usbrxactive /= '1') loop
wait until rising_edge(usbclk);
end loop;
while (usbrxactive= '1') loop
while (usbrxvalid /= '1' and usbrxactive = '1') loop
wait until rising_edge(usbclk);
end loop;
if (usbrxvalid = '1' and usbrxactive = '1') then
txmem(size) := usbrxdata;
size := size + 1;
end if;
wait until rising_edge(usbclk);
end loop;
end procedure utmi_recv_pack;
procedure utmi_send_pack (constant size : integer; signal usbtxdata: out std_logic_vector; signal usbtxvalid: out std_logic) is
variable n : integer;
begin
for n in 0 to size-1 loop
wait until rising_edge(usbclk);
usbtxvalid <= '1';
usbtxdata <= txmem(n);
while (usbtxready/='1') loop
wait until rising_edge(usbclk);
end loop;
end loop;
wait until rising_edge(usbclk);
usbtxvalid <= '0';
end procedure utmi_send_pack;
function crc5 (crc_in:std_logic_vector; din:std_logic_vector) return std_logic_vector is
variable crc5x : std_logic_vector (4 downto 0);
begin
crc5x(0) := din(10) xor din(9) xor din(6) xor din(5) xor din(3) xor din(0) xor crc_in(0) xor crc_in(3) xor crc_in(4);
crc5x(1) := din(10) xor din(7) xor din(6) xor din(4) xor din(1) xor crc_in(0) xor crc_in(1) xor crc_in(4);
crc5x(2) := din(10) xor din(9) xor din(8) xor din(7) xor din(6) xor din(3) xor din(2) xor din(0) xor crc_in(0) xor crc_in(1) xor crc_in(2) xor crc_in(3) xor crc_in(4);
crc5x(3) := din(10) xor din(9) xor din(8) xor din(7) xor din(4) xor din(3) xor din(1) xor crc_in(1) xor crc_in(2) xor crc_in(3) xor crc_in(4);
crc5x(4) := din(10) xor din(9) xor din(8) xor din(5) xor din(4) xor din(2) xor crc_in(2) xor crc_in(3) xor crc_in(4);
return crc5x;
end function crc5;
function crc16 (crc_in: std_logic_vector; din:std_logic_vector) return std_logic_vector is
variable crc_out : std_logic_vector (15 downto 0);
begin
crc_out(0) := din(7) xor din(6) xor din(5) xor din(4) xor din(3) xor
din(2) xor din(1) xor din(0) xor crc_in(8) xor crc_in(9) xor
crc_in(10) xor crc_in(11) xor crc_in(12) xor crc_in(13) xor
crc_in(14) xor crc_in(15);
crc_out(1) := din(7) xor din(6) xor din(5) xor din(4) xor din(3) xor din(2) xor
din(1) xor crc_in(9) xor crc_in(10) xor crc_in(11) xor
crc_in(12) xor crc_in(13) xor crc_in(14) xor crc_in(15);
crc_out(2) := din(1) xor din(0) xor crc_in(8) xor crc_in(9);
crc_out(3) := din(2) xor din(1) xor crc_in(9) xor crc_in(10);
crc_out(4) := din(3) xor din(2) xor crc_in(10) xor crc_in(11);
crc_out(5) := din(4) xor din(3) xor crc_in(11) xor crc_in(12);
crc_out(6) := din(5) xor din(4) xor crc_in(12) xor crc_in(13);
crc_out(7) := din(6) xor din(5) xor crc_in(13) xor crc_in(14);
crc_out(8) := din(7) xor din(6) xor crc_in(0) xor crc_in(14) xor crc_in(15);
crc_out(9) := din(7) xor crc_in(1) xor crc_in(15);
crc_out(10) := crc_in(2);
crc_out(11) := crc_in(3);
crc_out(12) := crc_in(4);
crc_out(13) := crc_in(5);
crc_out(14) := crc_in(6);
crc_out(15) := din(7) xor din(6) xor din(5) xor din(4) xor din(3) xor din(2) xor
din(1) xor din(0) xor crc_in(7) xor crc_in(8) xor crc_in(9) xor
crc_in(10) xor crc_in(11) xor crc_in(12) xor crc_in(13) xor
crc_in(14) xor crc_in(15);
return crc_out;
end function crc16;
 
procedure recv_packet(variable pid: inout std_logic_vector(3 downto 0); variable size: inout integer) is
variable del,n : integer;
variable crc16r : std_logic_vector(15 downto 0);
variable x,y : std_logic_vector(7 downto 0);
variable s : LINE;
begin
crc16r := X"ffff";
utmi_recv_pack(size);
for n in 1 to size-3 loop
y := txmem(n);
x(7) := y(0);
x(6) := y(1);
x(5) := y(2);
x(4) := y(3);
x(3) := y(4);
x(2) := y(5);
x(1) := y(6);
x(0) := y(7);
crc16r := crc16(crc16r, x);
end loop;
n := size-2;
 
y := crc16r(15 downto 8);
x(7) := y(0);
x(6) := y(1);
x(5) := y(2);
x(4) := y(3);
x(3) := y(4);
x(2) := y(5);
x(1) := y(6);
x(0) := y(7);
crc16r(15 downto 8) := not(x);
 
y := crc16r(7 downto 0);
x(7) := y(0);
x(6) := y(1);
x(5) := y(2);
x(4) := y(3);
x(3) := y(4);
x(2) := y(5);
x(1) := y(6);
x(0) := y(7);
crc16r(7 downto 0) := not(x);
 
if (crc16r /= txmem(n)&txmem(n+1)) then
--$display("ERROR: CRC Mismatch: Expected: %h, Got: %h%h (%t)",crc16r, txmem[n], txmem[n+1], $time);
WRITE(s,string'("ERROR: CRC Mismatch got:"));
HWRITE(s,crc16r);
WRITE(s,string'(" expected:"));
HWRITE(s,txmem(n)&txmem(n+1));
report s.all;
end if;
 
for n in 0 to size-3 loop
buffer1(buffer1_last+n) := txmem(n+1);
end loop;
n := size-3;
 
buffer1_last := buffer1_last+n;
 
-- Check PID
x := txmem(0);
 
if (x(7 downto 4) /= not(x(3 downto 0))) then
--$display("ERROR: Pid Checksum mismatch: Top: %h Bottom: %h (%t)",x[7:4], x[3:0], $time);
WRITE(s,string'("ERROR: Pid Checksum mismatch: Top: "));
HWRITE(s,x(7 downto 4));
WRITE(s,string'(" Bottom:"));
HWRITE(s,x(3 downto 0));
report s.all;
end if;
 
pid := x(3 downto 0);
size:= size-3;
 
end procedure recv_packet;
procedure send_token (constant fa:std_logic_vector(7 downto 0); constant ep:std_logic_vector(3 downto 0); constant pid:std_logic_vector(3 downto 0)) is
variable tmp_data:std_logic_vector(15 downto 0);
variable x,y:std_logic_vector(10 downto 0);
variable len:integer;
begin
tmp_data := fa(6 downto 0)&ep&"00000";
if (pid=USBF_T_PID_ACK) then
len := 1;
else
len := 3;
end if;
y := fa(6 downto 0)&ep;
x(10) := y(4);
x(9) := y(5);
x(8) := y(6);
x(7) := y(7);
x(6) := y(8);
x(5) := y(9);
x(4) := y(10);
x(3) := y(0);
x(2) := y(1);
x(1) := y(2);
x(0) := y(3);
y(4 downto 0) := crc5("11111", x);
tmp_data(4 downto 0) := not(y(4 downto 0));
tmp_data(15 downto 5) := x;
txmem(0) := (not(pid)&pid); -- PID
txmem(1) := ( tmp_data(8)&tmp_data(9)&tmp_data(10)&tmp_data(11)&tmp_data(12)&tmp_data(13)&tmp_data(14)&tmp_data(15));
txmem(2) := ( tmp_data(0)&tmp_data(1)&tmp_data(2)&tmp_data(3)&tmp_data(4)&tmp_data(5)&tmp_data(6)&tmp_data(7));
utmi_send_pack(len,usbtxdata,usbtxvalid);
end procedure send_token;
 
procedure send_data (constant pid:std_logic_vector(3 downto 0); constant len:integer; constant mode:integer) is
variable n : integer;
variable crc16r : std_logic_vector(15 downto 0);
variable x,y : std_logic_vector(7 downto 0);
begin
txmem(0) := not(pid)&pid; -- PID
crc16r := X"ffff";
for n in 0 to len-1 loop
if(mode=1) then
y := buffer1(buffer1_last+n);
else
y := std_logic_vector(to_unsigned(n,8));
end if;
-- x(7 downto 0) := y(0 to 7);
x(7) := y(0);
x(6) := y(1);
x(5) := y(2);
x(4) := y(3);
x(3) := y(4);
x(2) := y(5);
x(1) := y(6);
x(0) := y(7);
txmem(n+1) := y;
crc16r := crc16(crc16r, x);
end loop;
buffer1_last := buffer1_last + len - 1;
y := crc16r(15 downto 8);
-- x(7 downto 0) := y(0 to 7);
x(7) := y(0);
x(6) := y(1);
x(5) := y(2);
x(4) := y(3);
x(3) := y(4);
x(2) := y(5);
x(1) := y(6);
x(0) := y(7);
txmem(len+1) := not(x);
 
y := crc16r(7 downto 0);
-- x(7 downto 0) := y(0 to 7);
x(7) := y(0);
x(6) := y(1);
x(5) := y(2);
x(4) := y(3);
x(3) := y(4);
x(2) := y(5);
x(1) := y(6);
x(0) := y(7);
txmem(len+2) := not(x);
 
utmi_send_pack(len+3,usbtxdata,usbtxvalid);
end procedure send_data;
 
procedure data_in (constant fa:std_logic_vector(7 downto 0); constant pl_size:integer) is
variable rlen : integer;
variable pid : std_logic_vector(3 downto 0);
variable expected_pid : std_logic_vector(3 downto 0);
variable s : LINE;
begin
buffer1_last := 0;
send_token( fa, -- Function Address
X"00", -- Logical Endpoint Number
USBF_T_PID_IN -- PID
);
recv_packet(pid,rlen);
if (setup_pid='1') then
expected_pid := X"b"; -- DATA 1
else
expected_pid := X"3"; -- DATA 0
end if;
if (pid /= expected_pid) then
--$display("ERROR: Data IN PID mismatch. Expected: %h, Got: %h (%t)", expect_pid, pid, $time);
report "ERROR: Data IN PID mismatch.";
error_cnt := error_cnt + 1;
end if;
 
setup_pid := not(setup_pid);
if (rlen /= pl_size) then
report "ERROR: Data IN Size mismatch.";
--$display("ERROR: Data IN Size mismatch. Expected: %d, Got: %d (%t)", pl_size, rlen, $time);
error_cnt := error_cnt + 1;
end if;
 
DEALLOCATE(s);
WRITE(s,string'("RCV bytes: "));
WRITE(s,rlen);
report s.all;
for n in 0 to rlen-1 loop
-- $display("RCV Data[%0d]: %h",n,buffer1[n]);
DEALLOCATE(s);
WRITE(s,string'("RCV Data["));
WRITE(s,n);
WRITE(s,string'("]="));
HWRITE(s,buffer1(n));
report s.all;
end loop;
-- repeat(5) @(posedge clk);
wait for 1 us;
 
send_token( fa, -- Function Address
X"00", -- Logical Endpoint Number
USBF_T_PID_ACK -- PID
);
 
-- repeat(5) @(posedge clk);
wait for 1 us;
end procedure data_in;
procedure data_out(fa:std_logic_vector(7 downto 0); pl_size:integer) is
variable len : integer;
begin
send_token( fa, -- Function Address
X"00", -- Logical Endpoint Number
USBF_T_PID_OUT -- PID
);
wait until rising_edge(usbclk);
 
if (setup_pid='0') then
send_data(USBF_T_PID_DATA0, pl_size, 1);
else
send_data(USBF_T_PID_DATA1, pl_size, 1);
end if;
setup_pid := not(setup_pid);
 
-- Wait for ACK
utmi_recv_pack(len);
 
if(txmem(0) /= X"d2") then
--$display("ERROR: ACK mismatch. Expected: %h, Got: %h (%t)",8'hd2, txmem[0], $time);
report "ERROR: SETUP: ACK mismatch";
error_cnt := error_cnt + 1;
end if;
 
if(len /= 1) then
--$display("ERROR: SETUP: Length mismatch. Expected: %h, Got: %h (%t)",8'h1, len, $time);
report "ERROR: SETUP: Length mismatch";
error_cnt := error_cnt + 1;
end if;
-- repeat(5) @(posedge clk);
wait for 1 us;
end procedure data_out;
 
procedure send_setup (constant fa:std_logic_vector(7 downto 0);
constant req_type:std_logic_vector(7 downto 0);
constant request:std_logic_vector(7 downto 0);
constant wValue:std_logic_vector(15 downto 0);
constant wIndex:std_logic_vector(15 downto 0);
constant wLength:std_logic_vector(15 downto 0)) is
begin
send_token(fa,X"0",USBF_T_PID_SETUP);
wait for 1 us;
buffer1(0) := req_type;
buffer1(1) := request;
buffer1(3) := wValue(15 downto 8);
buffer1(2) := wValue(7 downto 0);
buffer1(5) := wIndex(15 downto 8);
buffer1(4) := wIndex(7 downto 0);
buffer1(7) := wLength(15 downto 8);
buffer1(6) := wLength(7 downto 0);
buffer1_last := 0;
send_data(USBF_T_PID_DATA0, 8, 1);
utmi_recv_pack(len);
if (txmem(0) /= x"d2") then
--$display("ERROR: SETUP: ACK mismatch. Expected: %h, Got: %h (%t)", 8'hd2, txmem[0], $time);
report "ERROR: SETUP: ACK mismatch";
error_cnt := error_cnt + 1;
end if;
if (len /= 1) then
--$display("ERROR: SETUP: Length mismatch. Expected: %h, Got: %h (%t)", 8'h1, len, $time);
report "ERROR: SETUP: Length mismatch. len="&integer'image(len);
error_cnt := error_cnt + 1;
end if;
wait until rising_edge(usbclk);
setup_pid := '1';
wait until rising_edge(usbclk);
end procedure send_setup;
procedure send_sof(constant frmn:integer) is
variable frmnv : std_logic_vector(10 downto 0);
variable tmp_data : std_logic_vector(15 downto 0);
variable x,y : std_logic_vector(10 downto 0);
begin
frmnv := std_logic_vector(to_unsigned(frmn,11));
y := frmnv;
x(10) := y(0);
x(9) := y(1);
x(8) := y(2);
x(7) := y(3);
x(6) := y(4);
x(5) := y(5);
x(4) := y(6);
x(3) := y(7);
x(2) := y(8);
x(1) := y(9);
x(0) := y(10);
 
tmp_data(15 downto 5) := x;
y(4 downto 0) := crc5( X"1F", x );
tmp_data(4 downto 0) := not(y(4 downto 0));
txmem(0) := not(USBF_T_PID_SOF)&USBF_T_PID_SOF; -- PID
txmem(1) := tmp_data(8)&tmp_data(9)&tmp_data(10)&tmp_data(11)&
tmp_data(12)&tmp_data(13)&tmp_data(14)&tmp_data(15);
txmem(2) := tmp_data(0)&tmp_data(1)&tmp_data(2)&tmp_data(3)&
tmp_data(4)&tmp_data(5)&tmp_data(6)&tmp_data(7);
txmem(1) := frmnv(7 downto 0);
txmem(2) := tmp_data(0)&tmp_data(1)&tmp_data(2)&tmp_data(3)&
tmp_data(4)& frmnv(10 downto 8);
utmi_send_pack(3,usbtxdata,usbtxvalid);
end procedure send_sof;
 
procedure buswrite(constant adr : in std_logic_vector(31 downto 0);
constant data : in std_logic_vector(31 downto 0);
signal Bus2IP_Clk : in std_logic;
signal Bus2IP_Addr : out std_logic_vector(0 to 31);
signal Bus2IP_Data : out std_logic_vector(0 to 31);
signal Bus2IP_BE : out std_logic_vector(0 to 3);
signal Bus2IP_CS : out std_logic;
signal Bus2IP_CE : out std_logic;
signal Bus2IP_RNW : out std_logic;
signal IP2Bus_Data : in std_logic_vector(0 to 31);
signal IP2Bus_Ack : in std_logic) is
begin
wait until (Bus2IP_Clk='1' and Bus2IP_Clk'event);
wait for 1 ns;
Bus2IP_Addr <= adr;
Bus2IP_Data <= data;
Bus2IP_RNW <= '0';
Bus2IP_CE <= '1';
Bus2IP_CS <= '1';
Bus2IP_BE <= "1111";
wait until (Bus2IP_Clk'event and Bus2IP_Clk='1' and IP2Bus_Ack='1');
wait for 1 ns;
Bus2IP_Addr <= (others=>'0');
Bus2IP_Data <= (others=>'0');
Bus2IP_RNW <= '0';
Bus2IP_CE <= '0';
Bus2IP_CS <= '0';
Bus2IP_BE <= "0000";
end buswrite;
 
procedure busread (constant adr : in std_logic_vector(31 downto 0);
variable data : out std_logic_vector(31 downto 0);
signal Bus2IP_Clk : in std_logic;
signal Bus2IP_Addr : out std_logic_vector(0 to 31);
signal Bus2IP_Data : out std_logic_vector(0 to 31);
signal Bus2IP_BE : out std_logic_vector(0 to 3);
signal Bus2IP_CS : out std_logic;
signal Bus2IP_CE : out std_logic;
signal Bus2IP_RNW : out std_logic;
signal IP2Bus_Data : in std_logic_vector(0 to 31);
signal IP2Bus_Ack : in std_logic) is
begin
wait until (Bus2IP_Clk='1' and Bus2IP_Clk'event);
wait for 1 ns;
Bus2IP_Addr <= adr;
Bus2IP_Data <= (others=>'0');
Bus2IP_RNW <= '1';
Bus2IP_CS <= '1';
Bus2IP_CE <= '1';
Bus2IP_BE <= "1111";
wait until (Bus2IP_Clk'event and Bus2IP_Clk='1' and IP2Bus_Ack='1');
data := IP2Bus_Data;
wait for 1 ns;
Bus2IP_Addr <= (others=>'0');
Bus2IP_Data <= (others=>'0');
Bus2IP_RNW <= '0';
Bus2IP_CS <= '0';
Bus2IP_CE <= '0';
Bus2IP_BE <= "0000";
end busread;
procedure uartread (variable d : out std_logic_vector (7 downto 0)) is
variable tmp : std_logic_vector(31 downto 0);
-- variable ss : LINE;
begin
loop
busread(X"00000002", tmp, clk, Bus2IP_Addr, Bus2IP_Data, Bus2IP_BE, Bus2IP_CS, Bus2IP_CE, Bus2IP_RNW, IP2Bus_Data, IP2Bus_Ack);
exit when ((tmp and X"00000001") /= X"00000000");
end loop;
-- DEALLOCATE(ss);
-- WRITE(ss,string'("uartstatus="));
-- HWRITE(ss,tmp);
-- report ss.all;
busread(X"00000000", tmp, clk, Bus2IP_Addr, Bus2IP_Data, Bus2IP_BE, Bus2IP_CS, Bus2IP_CE, Bus2IP_RNW, IP2Bus_Data, IP2Bus_Ack);
d := tmp(7 downto 0);
end procedure uartread;
procedure uartwrite (variable d : std_logic_vector (7 downto 0)) is
variable tmp : std_logic_vector(31 downto 0);
begin
loop
busread(X"00000002", tmp, clk, Bus2IP_Addr, Bus2IP_Data, Bus2IP_BE, Bus2IP_CS, Bus2IP_CE, Bus2IP_RNW, IP2Bus_Data, IP2Bus_Ack);
exit when ((tmp and X"00000004") /= X"00000000");
end loop;
tmp := X"00000000";
tmp(7 downto 0) := d;
buswrite(X"00000001", tmp, clk, Bus2IP_Addr, Bus2IP_Data, Bus2IP_BE, Bus2IP_CS, Bus2IP_CE, Bus2IP_RNW, IP2Bus_Data, IP2Bus_Ack);
end procedure uartwrite;
 
shared variable nn : integer;
shared variable pid : std_logic_vector(3 downto 0);
shared variable ss : LINE;
shared variable dd : std_logic_vector(7 downto 0);
shared variable rlen : integer;
begin
 
resetn <= not(reset);
rxd <= rxdp;
 
usb_phy_inst : usb_phy
port map (
clk => usbclk,
rst => resetn,
phy_tx_mode => '1',
usb_rst => open,
txdp => rxdp,
txdn => rxdn,
txoe => open,
rxd => txdp,
rxdp => txdp,
rxdn => txdn,
 
-- UTMI Interface
DataOut_i => usbtxdata,
TxValid_i => usbtxvalid,
TxReady_o => usbtxready,
RxValid_o => usbrxvalid,
RxActive_o => usbrxactive,
RxError_o => usbrxerror,
DataIn_o => usbrxdata,
LineState_o => usblinestate
);
 
 
OPB_USBLITE_Core_inst : OPB_USBLITE_Core
port map (
Clk => clk,
Reset => reset,
Usb_Clk => usbclk,
OPB_CS => Bus2IP_CS,
OPB_ABus => Bus2IP_Addr(30 to 31),
OPB_RNW => Bus2IP_RNW,
OPB_DBus => Bus2IP_Data(24 to 31),
SIn_xferAck => IP2Bus_Ack,
SIn_DBus => IP2Bus_Data(24 to 31),
Interrupt => Interrupt,
txdp => txdp,
txdn => txdn,
txoe => txoe,
rxd => rxd,
rxdp => rxdp,
rxdn => rxdn
);
 
process
begin
clk <= '0';
wait for 6.66666ns;
clk <= '1';
wait for 6.66666ns;
end process;
 
process
begin
usbclk <= '0';
wait for 10.41666ns;
usbclk <= '1';
wait for 10.41666ns;
end process;
process(usbclk)
begin
if (usbclk'event and usbclk='1') then
if (usbrxvalid='1') then
usbrxdata_r <= usbrxdata;
end if;
end if;
end process;
process
begin
wait for 100ns;
reset <= '1';
wait for 100ns;
reset <= '0';
wait for 100 us;
 
report "Setting Address ...";
wait for 1 us;
send_setup( X"00", -- Function Address
X"00", -- Request Type
SET_ADDRESS, -- Request
X"0012", -- wValue
X"0000", -- wIndex
X"0000" -- wLength
);
 
-- Status OK
data_in( X"00", -- Function Address
0 -- Expected payload size
);
 
report("Getting DEVICE descriptor ...");
send_setup( X"12", -- Function Address
X"80", -- Request Type
GET_DESCRIPTOR, -- Request
X"0100", -- wValue
X"0000", -- wIndex
X"0008" -- wLength
);
 
data_in( X"12", -- Function Address
8 -- Expected payload size
);
 
-- Status OK
data_out( X"12", -- Function Address
0 -- Expected payload size
);
 
report("Getting whole DEVICE descriptor ...");
send_setup( X"12", -- Function Address
X"80", -- Request Type
GET_DESCRIPTOR, -- Request
X"0100", -- wValue
X"0000", -- wIndex
X"0012" -- wLength
);
 
data_in( X"12", -- Function Address
18 -- Expected payload size
);
 
-- Status OK
data_out( X"12", -- Function Address
0 -- Expected payload size
);
 
report "Getting CONFIGURATION descriptor ...";
send_setup( X"12", -- Function Address
X"80", -- Request Type
GET_DESCRIPTOR, -- Request
X"0200", -- wValue
X"0000", -- wIndex
X"0008" -- wLength
);
 
data_in( X"12", -- Function Address
8 -- Expected payload size
);
 
-- Status OK
data_out( X"12", -- Function Address
0 -- Expected payload size
);
 
report "Getting whole CONFIGURATION descriptor ...";
send_setup( X"12", -- Function Address
X"80", -- Request Type
GET_DESCRIPTOR, -- Request
X"0200", -- wValue
X"0000", -- wIndex
X"0043" -- wLength
);
 
data_in( X"12", -- Function Address
64 -- Expected payload size
);
 
-- Status OK
data_out( X"12", -- Function Address
0 -- Expected payload size
);
 
data_in( X"12", -- Function Address
3 -- Expected payload size
);
 
-- Status OK
data_out( X"12", -- Function Address
0 -- Expected payload size
);
report "Set configuration 1...";
send_setup( X"12", -- Function Address
X"00", -- Request Type
SET_CONFIG, -- Request
X"0001", -- wValue
X"0000", -- wIndex
X"0000" -- wLength
);
 
data_in( X"12", -- Function Address
0 -- Expected payload size
);
wait for 1 us;
report "EP1 OUT...";
for nn in 0 to 63 loop
buffer1(nn) := std_logic_vector(to_unsigned(nn+32,8));
end loop;
buffer1_last := 0;
pid := "0000";
send_sof(0); -- Send SOF
wait until rising_edge(usbclk);
 
send_token( X"12", -- Function Address
X"1", -- Logical Endpoint Number
USBF_T_PID_OUT -- PID
);
 
wait until rising_edge(usbclk);
 
if (pid="0000") then
send_data(USBF_T_PID_DATA0, 64, 1);
else
send_data(USBF_T_PID_DATA1, 64, 1);
end if;
 
pid := not(pid);
 
-- Wait for ACK
utmi_recv_pack(len);
for nn in 0 to 63 loop
uartread(dd);
DEALLOCATE(ss);
WRITE(ss,string'("uartread="));
HWRITE(ss,dd);
report ss.all;
end loop;
 
wait for 1 us;
 
report "EP1 IN...";
for nn in 0 to 63 loop
dd := std_logic_vector(to_unsigned(nn,8));
DEALLOCATE(ss);
WRITE(ss,string'("uartwrite="));
HWRITE(ss,dd);
report ss.all;
uartwrite(dd);
end loop;
 
-- Send Data
send_sof(1); -- Send SOF
send_token( X"12", -- Function Address
X"1", -- Logical Endpoint Number
USBF_T_PID_IN -- PID
);
 
recv_packet(pid,rlen);
for nn in 0 to 63 loop
dd := txmem(nn+1);
DEALLOCATE(ss);
WRITE(ss,string'("usb recv="));
HWRITE(ss,dd);
report ss.all;
end loop;
send_token( X"12", -- Function Address
X"1", -- Logical Endpoint Number
USBF_T_PID_ACK -- PID
);
wait for 10us;
reset <= '1';
wait for 1us;
reset <= '0';
wait;
end process;
end architecture akre;
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/vhdl/opb_usblite.vhd
0,0 → 1,204
--
-- opb_usblite - opb_uartlite replacement
--
-- opb_usblite is using components from Rudolf Usselmann see
-- http://www.opencores.org/cores/usb_phy/
-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
--
-- Copyright (C) 2010 Ake Rehnman
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
library IEEE;
use IEEE.std_logic_1164.all;
 
entity OPB_USBLITE is
generic (
C_OPB_AWIDTH : integer := 32;
C_OPB_DWIDTH : integer := 32;
C_BASEADDR : std_logic_vector(0 to 31) := X"FFFF_0000";
C_HIGHADDR : std_logic_vector := X"FFFF_00FF";
C_SYSRST : std_logic := '1'; -- enable external reset
C_PHYMODE : std_logic := '1'; -- phy mode
C_VENDORID : std_logic_vector(15 downto 0) := X"1234"; -- VID
C_PRODUCTID : std_logic_vector(15 downto 0) := X"5678"; -- PID
C_VERSIONBCD : std_logic_vector(15 downto 0) := X"0200"; -- device version
C_SELFPOWERED : boolean := false; -- self or bus powered
C_RXBUFSIZE_BITS: integer range 7 to 12 := 10; -- size of rx buf (2^10 = 1024 bytes)
C_TXBUFSIZE_BITS: integer range 7 to 12 := 10 -- size of tx buf (2^10 = 1024 bytes)
);
port (
-- Global signals
OPB_Clk : in std_logic;
OPB_Rst : in std_logic;
SYS_Rst : in std_logic;
USB_Clk : in std_logic;
-- OPB signals
OPB_ABus : in std_logic_vector(0 to 31);
OPB_BE : in std_logic_vector(0 to 3);
OPB_RNW : in std_logic;
OPB_select : in std_logic;
OPB_seqAddr : in std_logic;
OPB_DBus : in std_logic_vector(0 to 31);
Sl_DBus : out std_logic_vector(0 to 31);
Sl_errAck : out std_logic;
Sl_retry : out std_logic;
Sl_toutSup : out std_logic;
Sl_xferAck : out std_logic;
 
-- Interrupt
Interrupt : out std_logic;
 
-- USB signals
txdp : out std_logic; -- connect to VPO
txdn : out std_logic; -- connect to VMO/FSEO
txoe : out std_logic; -- connect to OE
rxd : in std_logic; -- connect to RCV
rxdp : in std_logic; -- connect to VP
rxdn : in std_logic -- connect to VM
);
 
end entity OPB_USBLITE;
 
library Common_v1_00_a;
use Common_v1_00_a.pselect;
 
library unisim;
use unisim.all;
 
library opb_usblite_v1_00_a;
use opb_usblite_v1_00_a.opb_usblite_core;
 
architecture akre of OPB_USBLITE is
 
component pselect is
generic (
C_AB : integer;
C_AW : integer;
C_BAR : std_logic_vector);
port (
A : in std_logic_vector(0 to C_AW-1);
AValid : in std_logic;
ps : out std_logic);
end component pselect;
 
component OPB_USBLITE_Core is
generic (
C_PHYMODE : std_logic := '1';
C_VENDORID : std_logic_vector(15 downto 0) := X"1234";
C_PRODUCTID : std_logic_vector(15 downto 0) := X"5678";
C_VERSIONBCD : std_logic_vector(15 downto 0) := X"0200";
C_SELFPOWERED : boolean := false;
C_RXBUFSIZE_BITS: integer range 7 to 12 := 10;
C_TXBUFSIZE_BITS: integer range 7 to 12 := 10
);
port (
Clk : in std_logic;
Reset : in std_logic;
Usb_Clk : in std_logic;
-- OPB signals
OPB_CS : in std_logic;
OPB_ABus : in std_logic_vector(0 to 1);
OPB_RNW : in std_logic;
OPB_DBus : in std_logic_vector(7 downto 0);
SIn_xferAck : out std_logic;
SIn_DBus : out std_logic_vector(7 downto 0);
Interrupt : out std_logic;
-- USB signals
txdp : out std_logic;
txdn : out std_logic;
txoe : out std_logic;
rxd : in std_logic;
rxdp : in std_logic;
rxdn : in std_logic
);
end component OPB_USBLITE_Core;
 
function nbits (x, y : std_logic_vector(0 to C_OPB_AWIDTH-1)) return integer is
begin
for i in 0 to C_OPB_AWIDTH-1 loop
if x(i) /= y(i) then
return i;
end if;
end loop;
return(C_OPB_AWIDTH);
end function nbits;
 
constant C_NBITS : integer := nbits(C_HIGHADDR, C_BASEADDR);
 
signal OPB_CS : std_logic;
signal core_rst : std_logic;
begin -- architecture akre
 
 
-----------------------------------------------------------------------------
-- OPB bus interface
-----------------------------------------------------------------------------
 
-- Do the OPB address decoding
pselect_I : pselect
generic map (
C_AB => C_NBITS,
C_AW => C_OPB_AWIDTH,
C_BAR => C_BASEADDR)
port map (
A => OPB_ABus,
AValid => OPB_select,
ps => OPB_CS);
 
 
Sl_errAck <= '0';
Sl_retry <= '0';
Sl_toutSup <= '0';
Sl_DBus(0 to 23) <= (others=>'0');
 
-----------------------------------------------------------------------------
-- Instanciating the USB core
-----------------------------------------------------------------------------
core_rst <= SYS_Rst when C_SYSRST='1' else OPB_Rst;
OPB_USBLITE_Core_inst : OPB_USBLITE_Core
generic map (
C_PHYMODE => C_PHYMODE,
C_VENDORID => C_VENDORID,
C_PRODUCTID => C_PRODUCTID,
C_VERSIONBCD => C_VERSIONBCD,
C_SELFPOWERED => C_SELFPOWERED,
C_RXBUFSIZE_BITS => C_RXBUFSIZE_BITS,
C_TXBUFSIZE_BITS => C_TXBUFSIZE_BITS
)
port map (
Clk => OPB_Clk,
Reset => core_rst,
Usb_Clk => USB_Clk,
-- OPB signals
OPB_CS => OPB_CS,
OPB_ABus => OPB_ABus(28 to 29),
OPB_RNW => OPB_RNW,
OPB_DBus => OPB_DBus(24 to 31),
SIn_xferAck => Sl_xferAck,
SIn_DBus => Sl_DBus(24 to 31),
Interrupt => Interrupt,
-- USB signals
txdp => txdp,
txdn => txdn,
txoe => txoe,
rxd => rxd,
rxdp => rxdp,
rxdn => rxdn
);
 
end architecture akre;
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/vhdl/usb_serial.vhdl
0,0 → 1,1061
--
-- USB 2.0 Serial data transfer entity
--
-- This entity implements a USB 2.0 device that carries a bidirectional
-- byte stream over the bus. It communicates with the host according to
-- the USB Communication Device Class, specifically the ACM (Abstract
-- Control Model) variant.
--
-- The low-level interface signals are labeled PHY_xxx and can be connected
-- to an UTMI-compliant PHY component. The PHY should be configured in 8-bit
-- mode.
--
-- The application interface supports simple byte-at-a-time sending and
-- receiving. Three block RAMs are used to implement a receive buffer,
-- a transmission buffer and descriptor ROM.
--
-- The CLK input must be the 60 MHz clock generated by the UTMI transceiver.
-- All application interface signals and PHY interface signals are
-- synchronized to the rising edge of CLK, except for SUSPEND which has
-- an asynchronous reset.
--
-- Transmission:
-- * The entity asserts TXRDY when it is ready to send data.
-- * The application puts data on TXDAT and asserts TXVAL when it is
-- ready to send data.
-- * In each clock cycle in which TXRDY and TXVAL are both asserted,
-- the entity takes a byte from TXDAT and queues it for transmission.
--
-- Receiving:
-- * The application asserts RXRDY when it is ready to receive data.
-- * The entity puts data on RXDAT and asserts RXVAL when it has
-- data available. It will only do this in response to RXRDY.
-- * When RXVAL is high, the application must either accept a byte
-- from RXDAT and be ready for the next byte in the following cycle,
-- or it must deassert RXRDY to pause the receive queue.
--
-- At power on, and after RESET, the device waits for 16 ms before
-- attaching to the USB bus. A high signal on ONLINE indicates that
-- the device has been fully configured by the host.
--
-- Bugs and limitations:
-- * The TEST_MODE feature (mandatory for high speed devices) is
-- not implemented and returns an error condition to the host.
-- * The SEND_ENCAPSULATED_COMMAND and GET_ENCAPSULATED_RESPONSE commands
-- (mandatory CDC-ACM requests) are not supported but will return a
-- success condition to the host.
-- * The default control pipe does not verify requests from the host
-- as strictly as required by the standard. As a result, invalid
-- requests from the host may sometimes appear to succeed when
-- they should have returned an error condition.
--
-- Implementation note:
-- At some point it may become useful to implement separate clock domains
-- for the application resp. PHY side of this entity, using the FIFO buffers
-- for clock domain crossing. As a first step, a distinction has been made
-- between application-side signals (prefixed with q_) and PHY-side signals
-- (prefixed with s_). Currently the corresponding signals from both sides
-- are simply wired together with asynchronous assignments. By replacing
-- these hardwired connections with carefully designed synchronization logic,
-- a separation of clock domains could be realized.
--
 
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
use work.usb_pkg.all;
 
entity usb_serial is
 
generic (
 
-- Vendor ID to report in device descriptor.
VENDORID : std_logic_vector(15 downto 0);
 
-- Product ID to report in device descriptor.
PRODUCTID : std_logic_vector(15 downto 0);
 
-- Product version to report in device descriptor.
VERSIONBCD : std_logic_vector(15 downto 0);
 
-- Support high speed mode.
HSSUPPORT : boolean := false;
 
-- Set to true if the device never draws power from the USB bus.
SELFPOWERED : boolean := false;
 
-- Size of receive buffer as 2-logarithm of the number of bytes.
-- Must be at least 10 (1024 bytes) for high speed support.
RXBUFSIZE_BITS: integer range 7 to 12 := 11;
 
-- Size of transmit buffer as 2-logarithm of the number of bytes.
TXBUFSIZE_BITS: integer range 7 to 12 := 10 );
 
port (
 
-- 60 MHz UTMI clock.
CLK : in std_logic;
 
-- Synchronous reset; clear buffers and re-attach to the bus.
RESET : in std_logic;
 
-- High for one clock when a reset signal is detected on the USB bus.
-- Note: do NOT wire this signal to RESET externally.
USBRST : out std_logic;
 
-- High when the device is operating (or suspended) in high speed mode.
HIGHSPEED : out std_logic;
 
-- High while the device is suspended.
-- Note: This signal is not synchronized to CLK.
-- It may be used to asynchronously drive the UTMI SuspendM pin.
SUSPEND : out std_logic;
 
-- High when the device is in the Configured state.
ONLINE : out std_logic;
 
-- High if a received byte is available on RXDAT.
RXVAL : out std_logic;
 
-- Received data byte, valid if RXVAL is high.
RXDAT : out std_logic_vector(7 downto 0);
 
-- High if the application is ready to receive the next byte.
RXRDY : in std_logic;
 
-- Number of bytes currently available in receive buffer.
RXLEN : out std_logic_vector((RXBUFSIZE_BITS-1) downto 0);
 
-- High if the application has data to send.
TXVAL : in std_logic;
 
-- Data byte to send, must be valid if TXVAL is high.
TXDAT : in std_logic_vector(7 downto 0);
 
-- High if the entity is ready to accept the next byte.
TXRDY : out std_logic;
 
-- Number of free byte positions currently available in transmit buffer.
TXROOM : out std_logic_vector((TXBUFSIZE_BITS-1) downto 0);
 
-- Temporarily suppress transmissions at the outgoing endpoint.
-- This gives the application an oppertunity to fill the transmit
-- buffer in order to blast data efficiently in big chunks.
TXCORK : in std_logic;
 
PHY_DATAIN : in std_logic_vector(7 downto 0);
PHY_DATAOUT : out std_logic_vector(7 downto 0);
PHY_TXVALID : out std_logic;
PHY_TXREADY : in std_logic;
PHY_RXACTIVE : in std_logic;
PHY_RXVALID : in std_logic;
PHY_RXERROR : in std_logic;
PHY_LINESTATE : in std_logic_vector(1 downto 0);
PHY_OPMODE : out std_logic_vector(1 downto 0);
PHY_XCVRSELECT: out std_logic;
PHY_TERMSELECT: out std_logic;
PHY_RESET : out std_logic );
end entity usb_serial;
 
architecture usb_serial_arch of usb_serial is
 
-- Byte array type
type t_byte_array is array(natural range <>) of std_logic_vector(7 downto 0);
 
-- Conditional expression.
function choose_int(z: boolean; a, b: integer)
return integer is
begin
if z then return a; else return b; end if;
end function;
 
-- Conditional expression.
function choose_byte(z: boolean; a, b: std_logic_vector)
return std_logic_vector is
begin
if z then return a; else return b; end if;
end function;
 
-- Maximum packet size according to protocol.
constant MAX_FSPACKET_SIZE: integer := 64;
constant MAX_HSPACKET_SIZE: integer := 512;
 
-- Width required for a pointer that can cover either RX or TX buffer.
constant BUFPTR_SIZE : integer := choose_int(RXBUFSIZE_BITS > TXBUFSIZE_BITS, RXBUFSIZE_BITS, TXBUFSIZE_BITS);
 
-- Data endpoint number.
constant data_endpt : std_logic_vector(3 downto 0) := "0001";
constant notify_endpt : std_logic_vector(3 downto 0) := "0010";
 
-- Descriptor ROM
-- addr 0 .. 17 : device descriptor
-- addr 20 .. 29 : device qualifier
-- addr 32 .. 98 : full speed configuration descriptor
-- addr 112 .. 178 : high speed configuration descriptor
-- addr 179 : other_speed_configuration hack
constant DESC_DEV_ADDR : integer := 0;
constant DESC_DEV_LEN : integer := 18;
constant DESC_QUAL_ADDR : integer := 20;
constant DESC_QUAL_LEN : integer := 10;
constant DESC_FSCFG_ADDR : integer := 32;
constant DESC_FSCFG_LEN : integer := 67;
constant DESC_HSCFG_ADDR : integer := 112;
constant DESC_HSCFG_LEN : integer := 67;
constant DESC_OTHERSPEED_ADDR : integer := 179;
 
constant descrom_pre: t_byte_array(0 to 191) :=
-- 18 bytes device descriptor
( X"12", -- bLength = 18 bytes
X"01", -- bDescriptorType = device descriptor
choose_byte(HSSUPPORT, X"00", X"10"), -- bcdUSB = 1.10 or 2.00
choose_byte(HSSUPPORT, X"02", X"01"),
X"02", -- bDeviceClass = Communication Device Class
X"00", -- bDeviceSubClass = none
X"00", -- bDeviceProtocol = none
X"40", -- bMaxPacketSize0 = 64 bytes
VENDORID(7 downto 0), -- idVendor
VENDORID(15 downto 8),
PRODUCTID(7 downto 0), -- idProduct
PRODUCTID(15 downto 8),
VERSIONBCD(7 downto 0), -- bcdDevice
VERSIONBCD(15 downto 8),
X"00", -- iManufacturer
X"00", -- iProduct
X"00", -- iSerialNumber
X"01", -- bNumConfigurations = 1
-- 2 bytes padding
X"00", X"00",
-- 10 bytes device qualifier
X"0a", -- bLength = 10 bytes
X"06", -- bDescriptorType = device qualifier
X"00", X"02", -- bcdUSB = 2.0
X"02", -- bDeviceClass = Communication Device Class
X"00", -- bDeviceSubClass = none
X"00", -- bDeviceProtocol = none
X"40", -- bMaxPacketSize0 = 64 bytes
X"01", -- bNumConfigurations = 1
X"00", -- bReserved
-- 2 bytes padding
X"00", X"00",
-- 67 bytes full-speed configuration descriptor
-- 9 bytes configuration header
X"09", -- bLength = 9 bytes
X"02", -- bDescriptorType = configuration descriptor
X"43", X"00", -- wTotalLength = 67 bytes
X"02", -- bNumInterfaces = 2
X"01", -- bConfigurationValue = 1
X"00", -- iConfiguration = none
choose_byte(SELFPOWERED, X"c0", X"80"), -- bmAttributes
X"fa", -- bMaxPower = 500 mA
-- 9 bytes interface descriptor (communication control class)
X"09", -- bLength = 9 bytes
X"04", -- bDescriptorType = interface descriptor
X"00", -- bInterfaceNumber = 0
X"00", -- bAlternateSetting = 0
X"01", -- bNumEndpoints = 1
X"02", -- bInterfaceClass = Communication Interface
X"02", -- bInterfaceSubClass = Abstract Control Model
X"01", -- bInterfaceProtocol = V.25ter (required for Linux CDC-ACM driver)
X"00", -- iInterface = none
-- 5 bytes functional descriptor (header)
X"05", -- bLength = 5 bytes
X"24", -- bDescriptorType = CS_INTERFACE
X"00", -- bDescriptorSubtype = header
X"10", X"01", -- bcdCDC = 1.10
-- 4 bytes functional descriptor (abstract control management)
X"04", -- bLength = 4 bytes
X"24", -- bDescriptorType = CS_INTERFACE
X"02", -- bDescriptorSubtype = Abstract Control Mgmnt
X"00", -- bmCapabilities = none
-- 5 bytes functional descriptor (union)
X"05", -- bLength = 5 bytes
X"24", -- bDescriptorType = CS_INTERFACE
X"06", -- bDescriptorSubtype = union
X"00", -- bMasterInterface = 0
X"01", -- bSlaveInterface0 = 1
-- 5 bytes functional descriptor (call management)
X"05", -- bLength = 5 bytes
X"24", -- bDescriptorType = CS_INTERFACE
X"01", -- bDescriptorSubType = Call Management
X"00", -- bmCapabilities = no call mgmnt
X"01", -- bDataInterface = 1
-- 7 bytes endpoint descriptor (notify IN)
X"07", -- bLength = 7 bytes
X"05", -- bDescriptorType = endpoint descriptor
X"82", -- bEndpointAddress = IN 2
X"03", -- bmAttributes = interrupt data
X"08", X"00", -- wMaxPacketSize = 8 bytes
X"ff", -- bInterval = 255 frames
-- 9 bytes interface descriptor (data class)
X"09", -- bLength = 9 bytes
X"04", -- bDescriptorType = interface descriptor
X"01", -- bInterfaceNumber = 1
X"00", -- bAlternateSetting = 0
X"02", -- bNumEndpoints = 2
X"0a", -- bInterfaceClass = Data Interface
X"00", -- bInterfaceSubClass = none
X"00", -- bInterafceProtocol = none
X"00", -- iInterface = none
-- 7 bytes endpoint descriptor (data IN)
X"07", -- bLength = 7 bytes
X"05", -- bDescriptorType = endpoint descriptor
X"81", -- bEndpointAddress = IN 1
X"02", -- bmAttributes = bulk data
X"40", X"00", -- wMaxPacketSize = 64 bytes
X"00", -- bInterval
-- 7 bytes endpoint descriptor (data OUT)
X"07", -- bLength = 7 bytes
X"05", -- bDescriptorType = endpoint descriptor
X"01", -- bEndpointAddress = OUT 1
X"02", -- bmAttributes = bulk data
X"40", X"00", -- wMaxPacketSize = 64 bytes
X"00", -- bInterval
-- 13 bytes padding
X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
X"00", X"00", X"00", X"00", X"00",
-- 67 bytes high-speed configuration descriptor
-- 9 bytes configuration header
X"09", -- bLength = 9 bytes
X"02", -- bDescriptorType = configuration descriptor
X"43", X"00", -- wTotalLength = 67 bytes
X"02", -- bNumInterfaces = 2
X"01", -- bConfigurationValue = 1
X"00", -- iConfiguration = none
choose_byte(SELFPOWERED, X"c0", X"80" ), -- bmAttributes = self-powered
X"fa", -- bMaxPower = 500 mA
-- 9 bytes interface descriptor (communication control class)
X"09", -- bLength = 9 bytes
X"04", -- bDescriptorType = interface descriptor
X"00", -- bInterfaceNumber = 0
X"00", -- bAlternateSetting = 0
X"01", -- bNumEndpoints = 1
X"02", -- bInterfaceClass = Communication Interface
X"02", -- bInterfaceSubClass = Abstract Control Model
X"01", -- bInterfaceProtocol = V.25ter (required for Linux CDC-ACM driver)
X"00", -- iInterface = none
-- 5 bytes functional descriptor (header)
X"05", -- bLength = 5 bytes
X"24", -- bDescriptorType = CS_INTERFACE
X"00", -- bDescriptorSubtype = header
X"10", X"01", -- bcdCDC = 1.10
-- 4 bytes functional descriptor (abstract control management)
X"04", -- bLength = 4 bytes
X"24", -- bDescriptorType = CS_INTERFACE
X"02", -- bDescriptorSubtype = Abstract Control Mgmnt
X"00", -- bmCapabilities = none
-- 5 bytes functional descriptor (union)
X"05", -- bLength = 5 bytes
X"24", -- bDescriptorType = CS_INTERFACE
X"06", -- bDescriptorSubtype = union
X"00", -- bMasterInterface = 0
X"01", -- bSlaveInterface0 = 1
-- 5 bytes functional descriptor (call management)
X"05", -- bLength = 5 bytes
X"24", -- bDescriptorType = CS_INTERFACE
X"01", -- bDescriptorSubType = Call Management
X"00", -- bmCapabilities = no call mgmnt
X"01", -- bDataInterface = 1
-- 7 bytes endpoint descriptor (notify IN)
X"07", -- bLength = 7 bytes
X"05", -- bDescriptorType = endpoint descriptor
X"82", -- bEndpointAddress = IN 2
X"03", -- bmAttributes = interrupt data
X"08", X"00", -- wMaxPacketSize = 8 bytes
X"0f", -- bInterval = 2**14 frames
-- 9 bytes interface descriptor (data class)
X"09", -- bLength = 9 bytes
X"04", -- bDescriptorType = interface descriptor
X"01", -- bInterfaceNumber = 1
X"00", -- bAlternateSetting = 0
X"02", -- bNumEndpoints = 2
X"0a", -- bInterfaceClass = Data Interface
X"00", -- bInterfaceSubClass = none
X"00", -- bInterafceProtocol = none
X"00", -- iInterface = none
-- 7 bytes endpoint descriptor (data IN)
X"07", -- bLength = 7 bytes
X"05", -- bDescriptorType = endpoint descriptor
X"81", -- bEndpointAddress = IN 1
X"02", -- bmAttributes = bulk data
X"00", X"02", -- wMaxPacketSize = 512 bytes
X"00", -- bInterval
-- 7 bytes endpoint descriptor (data OUT)
X"07", -- bLength = 7 bytes
X"05", -- bDescriptorType = endpoint descriptor
X"01", -- bEndpointAddress = OUT 1
X"02", -- bmAttributes = bulk data
X"00", X"02", -- wMaxPacketSize = 512 bytes
X"00", -- bInterval = never NAK
-- other_speed_configuration hack
X"07",
-- 12 bytes padding
X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00",
X"00", X"00", X"00", X"00" );
 
constant descrom: t_byte_array(0 to (choose_int(HSSUPPORT, 191, 111))) :=
descrom_pre(0 to choose_int(HSSUPPORT, 191, 111));
signal descrom_start: unsigned(choose_int(HSSUPPORT, 7, 6) downto 0);
signal descrom_raddr: unsigned(choose_int(HSSUPPORT, 7, 6) downto 0);
signal descrom_rdat: std_logic_vector(7 downto 0);
 
-- RX buffer
signal rxbuf: t_byte_array(0 to (2**RXBUFSIZE_BITS-1));
signal rxbuf_rdat: std_logic_vector(7 downto 0);
 
-- TX buffer
signal txbuf: t_byte_array(0 to (2**TXBUFSIZE_BITS-1));
signal txbuf_rdat: std_logic_vector(7 downto 0);
 
-- Interface to usb_init
signal usbi_usbrst : std_logic;
signal usbi_highspeed : std_logic;
signal usbi_suspend : std_logic;
 
-- Interface to usb_packet
signal usbp_chirpk : std_logic;
signal usbp_rxact : std_logic;
signal usbp_rxrdy : std_logic;
signal usbp_rxfin : std_logic;
signal usbp_rxdat : std_logic_vector(7 downto 0);
signal usbp_txact : std_logic;
signal usbp_txrdy : std_logic;
signal usbp_txdat : std_logic_vector(7 downto 0);
 
-- Interface to usb_transact
signal usbt_in : std_logic;
signal usbt_out : std_logic;
signal usbt_setup : std_logic;
signal usbt_ping : std_logic;
signal usbt_fin : std_logic;
signal usbt_endpt : std_logic_vector(3 downto 0);
signal usbt_nak : std_logic;
signal usbt_stall : std_logic;
signal usbt_nyet : std_logic;
signal usbt_send : std_logic;
signal usbt_isync : std_logic;
signal usbt_osync : std_logic;
signal usbt_rxrdy : std_logic;
signal usbt_rxdat : std_logic_vector(7 downto 0);
signal usbt_txrdy : std_logic;
signal usbt_txdat : std_logic_vector(7 downto 0);
 
-- Interface to usb_control
signal usbc_addr : std_logic_vector(6 downto 0);
signal usbc_confd : std_logic;
signal usbc_clr_in : std_logic_vector(1 to 2);
signal usbc_clr_out : std_logic_vector(1 to 2);
signal usbc_sethlt_in : std_logic_vector(1 to 2);
signal usbc_sethlt_out: std_logic_vector(1 to 2);
signal usbc_dscbusy : std_logic;
signal usbc_dscrd : std_logic;
signal usbc_dsctyp : std_logic_vector(2 downto 0);
signal usbc_dscinx : std_logic_vector(7 downto 0);
signal usbc_dscoff : std_logic_vector(7 downto 0);
signal usbc_dsclen : std_logic_vector(7 downto 0);
signal usbc_selfpowered : std_logic;
signal usbc_in : std_logic;
signal usbc_out : std_logic;
signal usbc_setup : std_logic;
signal usbc_ping : std_logic;
signal usbc_nak : std_logic;
signal usbc_stall : std_logic;
signal usbc_nyet : std_logic;
signal usbc_send : std_logic;
signal usbc_isync : std_logic;
signal usbc_txdat : std_logic_vector(7 downto 0);
 
-- State machine
type t_state is (
ST_IDLE, ST_STALL, ST_NAK,
ST_INSTART, ST_INSEND, ST_INDONE, ST_OUTRECV, ST_OUTNAK );
signal s_state : t_state := ST_IDLE;
 
-- Endpoint administration (PHY side).
signal s_rxbuf_head : unsigned(RXBUFSIZE_BITS-1 downto 0) := to_unsigned(0, RXBUFSIZE_BITS);
signal s_rxbuf_tail : unsigned(RXBUFSIZE_BITS-1 downto 0);
signal s_txbuf_head : unsigned(TXBUFSIZE_BITS-1 downto 0);
signal s_txbuf_tail : unsigned(TXBUFSIZE_BITS-1 downto 0) := to_unsigned(0, TXBUFSIZE_BITS);
signal s_txbuf_stop : unsigned(TXBUFSIZE_BITS-1 downto 0);
signal s_bufptr : unsigned(BUFPTR_SIZE-1 downto 0);
signal s_txprev_full : std_logic := '0'; -- Last transmitted packet was full-size
signal s_txprev_acked : std_logic := '1'; -- Last trantsmitted packet was ack-ed.
signal s_isync : std_logic := '0';
signal s_osync : std_logic := '0';
signal s_halt_in : std_logic_vector(1 to 2) := "00";
signal s_halt_out : std_logic_vector(1 to 2) := "00";
signal s_nyet : std_logic := '0';
 
-- Buffer state (application side).
signal q_rxbuf_head : unsigned(RXBUFSIZE_BITS-1 downto 0);
signal q_rxbuf_tail : unsigned(RXBUFSIZE_BITS-1 downto 0) := to_unsigned(0, RXBUFSIZE_BITS);
signal q_txbuf_head : unsigned(TXBUFSIZE_BITS-1 downto 0) := to_unsigned(0, TXBUFSIZE_BITS);
signal q_txbuf_tail : unsigned(TXBUFSIZE_BITS-1 downto 0);
 
-- Control signals (PHY side).
signal s_reset : std_logic;
signal s_txcork : std_logic;
 
-- Status signals (application side).
signal q_usbrst : std_logic;
signal q_online : std_logic;
signal q_highspeed : std_logic;
 
-- Receive buffer logic (application side).
signal q_rxval : std_logic := '0';
signal q_rxbuf_read : std_logic;
signal q_txbuf_rdy : std_logic;
 
begin
 
-- Check buffer size.
assert ((not HSSUPPORT) or (RXBUFSIZE_BITS >= 10))
report "High-speed device needs at least 1024 bytes RX buffer";
 
-- Bus reset logic
usb_init_inst : usb_init
generic map (
HSSUPPORT => HSSUPPORT )
port map (
CLK => CLK,
RESET => s_reset,
I_USBRST => usbi_usbrst,
I_HIGHSPEED => usbi_highspeed,
I_SUSPEND => usbi_suspend,
P_CHIRPK => usbp_chirpk,
PHY_RESET => PHY_RESET,
PHY_LINESTATE => PHY_LINESTATE,
PHY_OPMODE => PHY_OPMODE,
PHY_XCVRSELECT => PHY_XCVRSELECT,
PHY_TERMSELECT => PHY_TERMSELECT );
 
-- Packet level logic
usb_packet_inst : usb_packet
port map (
CLK => CLK,
RESET => usbi_usbrst,
P_CHIRPK => usbp_chirpk,
P_RXACT => usbp_rxact,
P_RXRDY => usbp_rxrdy,
P_RXFIN => usbp_rxfin,
P_RXDAT => usbp_rxdat,
P_TXACT => usbp_txact,
P_TXRDY => usbp_txrdy,
P_TXDAT => usbp_txdat,
PHY_DATAIN => PHY_DATAIN,
PHY_DATAOUT => PHY_DATAOUT,
PHY_TXVALID => PHY_TXVALID,
PHY_TXREADY => PHY_TXREADY,
PHY_RXACTIVE => PHY_RXACTIVE,
PHY_RXVALID => PHY_RXVALID,
PHY_RXERROR => PHY_RXERROR );
 
-- Transaction level logic
usb_transact_inst : usb_transact
generic map (
HSSUPPORT => HSSUPPORT )
port map (
CLK => CLK,
RESET => usbi_usbrst,
T_IN => usbt_in,
T_OUT => usbt_out,
T_SETUP => usbt_setup,
T_PING => usbt_ping,
T_FIN => usbt_fin,
T_ADDR => usbc_addr,
T_ENDPT => usbt_endpt,
T_NAK => usbt_nak,
T_STALL => usbt_stall,
T_NYET => usbt_nyet,
T_SEND => usbt_send,
T_ISYNC => usbt_isync,
T_OSYNC => usbt_osync,
T_RXRDY => usbt_rxrdy,
T_RXDAT => usbt_rxdat,
T_TXRDY => usbt_txrdy,
T_TXDAT => usbt_txdat,
I_HIGHSPEED => usbi_highspeed,
P_RXACT => usbp_rxact,
P_RXRDY => usbp_rxrdy,
P_RXFIN => usbp_rxfin,
P_RXDAT => usbp_rxdat,
P_TXACT => usbp_txact,
P_TXRDY => usbp_txrdy,
P_TXDAT => usbp_txdat );
 
-- Default control endpoint
usb_control_inst : usb_control
generic map (
NENDPT => 2 )
port map (
CLK => CLK,
RESET => usbi_usbrst,
C_ADDR => usbc_addr,
C_CONFD => usbc_confd,
C_CLRIN => usbc_clr_in,
C_CLROUT => usbc_clr_out,
C_HLTIN => s_halt_in,
C_HLTOUT => s_halt_out,
C_SHLTIN => usbc_sethlt_in,
C_SHLTOUT => usbc_sethlt_out,
C_DSCBUSY => usbc_dscbusy,
C_DSCRD => usbc_dscrd,
C_DSCTYP => usbc_dsctyp,
C_DSCINX => usbc_dscinx,
C_DSCOFF => usbc_dscoff,
C_DSCLEN => usbc_dsclen,
C_SELFPOWERED => usbc_selfpowered,
T_IN => usbc_in,
T_OUT => usbc_out,
T_SETUP => usbc_setup,
T_PING => usbc_ping,
T_FIN => usbt_fin,
T_NAK => usbc_nak,
T_STALL => usbc_stall,
T_NYET => usbc_nyet,
T_SEND => usbc_send,
T_ISYNC => usbc_isync,
T_OSYNC => usbt_osync,
T_RXRDY => usbt_rxrdy,
T_RXDAT => usbt_rxdat,
T_TXRDY => usbt_txrdy,
T_TXDAT => usbc_txdat );
 
-- Assign usb_serial output signals.
USBRST <= q_usbrst;
HIGHSPEED <= q_highspeed;
SUSPEND <= usbi_suspend;
ONLINE <= q_online;
RXVAL <= q_rxval;
RXDAT <= rxbuf_rdat;
RXLEN <= std_logic_vector(q_rxbuf_head - q_rxbuf_tail);
TXRDY <= q_txbuf_rdy;
TXROOM <= std_logic_vector(q_txbuf_tail - q_txbuf_head - 1);
 
-- Assign usb_control input signals
usbc_in <= usbt_in when (usbt_endpt = "0000") else '0';
usbc_out <= usbt_out when (usbt_endpt = "0000") else '0';
usbc_setup <= usbt_setup when (usbt_endpt = "0000") else '0';
usbc_ping <= usbt_ping when (usbt_endpt = "0000") else '0';
usbc_selfpowered <= '1' when SELFPOWERED else '0';
 
-- Assign usb_transact input lines
usbt_nak <= usbc_nak when (usbt_endpt = "0000") else
'1' when (s_state = ST_NAK) else
'0';
usbt_stall <= usbc_stall when (usbt_endpt = "0000") else
'1' when (s_state = ST_STALL) else
'0';
usbt_nyet <= usbc_nyet when (usbt_endpt = "0000") else
s_nyet;
usbt_send <= usbc_send when (usbt_endpt = "0000") else
'1' when (s_state = ST_INSEND) else
'0';
usbt_isync <= usbc_isync when (usbt_endpt = "0000") else
s_isync;
usbt_txdat <= usbc_txdat when (usbt_endpt = "0000" and usbc_dscbusy = '0') else
descrom_rdat when (usbt_endpt = "0000") else
txbuf_rdat;
 
-- Buffer logic.
q_rxbuf_read <= (RXRDY or (not q_rxval)) when (q_rxbuf_tail /= q_rxbuf_head) else '0';
q_txbuf_rdy <= '1' when (q_txbuf_head + 1 /= q_txbuf_tail) else '0';
 
-- Connection between PHY-side and application-side signals.
-- This could be a good place to insert clock domain crossing.
q_rxbuf_head <= s_rxbuf_head;
s_rxbuf_tail <= q_rxbuf_tail;
s_txbuf_head <= q_txbuf_head;
q_txbuf_tail <= s_txbuf_tail;
s_txcork <= TXCORK;
s_reset <= RESET;
q_online <= usbc_confd;
q_usbrst <= usbi_usbrst;
q_highspeed <= usbi_highspeed;
 
-- Lookup address/length of the selected descriptor (combinatorial).
process (usbc_dsctyp, usbc_dscinx, usbi_highspeed)
constant slen: integer := descrom_start'length;
constant nlen: integer := USBC_DSCLEN'length;
variable s: unsigned((slen-1) downto 0);
variable n: unsigned((nlen-1) downto 0);
begin
s := to_unsigned(0, slen);
n := to_unsigned(0, nlen);
case usbc_dsctyp is
when "001" => -- device descriptor
s := to_unsigned(DESC_DEV_ADDR, slen);
n := to_unsigned(DESC_DEV_LEN, nlen);
when "010" => -- configuration descriptor
if usbc_dscinx = X"00" then
if HSSUPPORT and (usbi_highspeed = '1') then
s := to_unsigned(DESC_HSCFG_ADDR, slen);
n := to_unsigned(DESC_HSCFG_LEN, nlen);
else
s := to_unsigned(DESC_FSCFG_ADDR, slen);
n := to_unsigned(DESC_FSCFG_LEN, nlen);
end if;
end if;
when "110" => -- device qualifier
if HSSUPPORT then
s := to_unsigned(DESC_QUAL_ADDR, slen);
n := to_unsigned(DESC_QUAL_LEN, nlen);
end if;
when "111" => -- other speed configuration
if HSSUPPORT and (usbc_dscinx = X"00") then
if usbi_highspeed = '1' then
s := to_unsigned(DESC_FSCFG_ADDR, slen);
n := to_unsigned(DESC_FSCFG_LEN, nlen);
else
s := to_unsigned(DESC_HSCFG_ADDR, slen);
n := to_unsigned(DESC_HSCFG_LEN, nlen);
end if;
end if;
when others =>
-- unsupported descriptor type
end case;
descrom_start <= s;
usbc_dsclen <= std_logic_vector(n);
end process;
 
-- Main application-side synchronous process.
process is
begin
wait until rising_edge(CLK);
 
if RESET = '1' then
 
-- Reset this entity.
q_rxbuf_tail <= to_unsigned(0, RXBUFSIZE_BITS);
q_txbuf_head <= to_unsigned(0, TXBUFSIZE_BITS);
q_rxval <= '0';
 
else
 
-- Read data from the RX buffer.
if q_rxbuf_read = '1' then
-- The RAM buffer reads a byte in this cycle.
q_rxbuf_tail <= q_rxbuf_tail + 1;
q_rxval <= '1';
elsif RXRDY = '1' then
-- Byte consumed by application; no new data yet.
q_rxval <= '0';
end if;
 
-- Write data to the TX buffer.
if (TXVAL = '1') and (q_txbuf_rdy = '1') then
-- The RAM buffer writes a byte in this cycle.
q_txbuf_head <= q_txbuf_head + 1;
end if;
 
end if;
 
end process;
 
-- Main PHY-side synchronous process.
process is
variable v_max_txsize : unsigned(TXBUFSIZE_BITS-1 downto 0);
variable v_rxbuf_len_lim : unsigned(RXBUFSIZE_BITS-1 downto 0);
variable v_rxbuf_tmp_head : unsigned(RXBUFSIZE_BITS-1 downto 0);
variable v_rxbuf_pktroom : std_logic;
begin
wait until rising_edge(CLK);
 
-- Determine the maximum packet size we can transmit.
if HSSUPPORT and usbi_highspeed = '1' then
v_max_txsize := to_unsigned(MAX_HSPACKET_SIZE, TXBUFSIZE_BITS);
else
v_max_txsize := to_unsigned(MAX_FSPACKET_SIZE, TXBUFSIZE_BITS);
end if;
 
-- Determine if there is room for another packet in the RX buffer.
-- We need room for the largest possible incoming packet, plus
-- two CRC bytes.
if HSSUPPORT then
v_rxbuf_len_lim := to_unsigned(2**RXBUFSIZE_BITS - MAX_HSPACKET_SIZE - 2, RXBUFSIZE_BITS);
else
v_rxbuf_len_lim := to_unsigned(2**RXBUFSIZE_BITS - MAX_FSPACKET_SIZE - 2, RXBUFSIZE_BITS);
end if;
if HSSUPPORT and s_state = ST_OUTRECV then
-- Currently receiving a packet; compare against the temporary
-- tail pointer to decide NYET vs ACK.
v_rxbuf_tmp_head := resize(s_bufptr, RXBUFSIZE_BITS);
else
-- Not receiving a packet (or NYET not supported);
-- compare against the tail pointer to decide NAK vs ACK.
v_rxbuf_tmp_head := s_rxbuf_head;
end if;
if v_rxbuf_tmp_head - s_rxbuf_tail < v_rxbuf_len_lim then
v_rxbuf_pktroom := '1';
else
v_rxbuf_pktroom := '0';
end if;
 
-- State machine
if s_reset = '1' then
 
-- Reset this entity.
s_state <= ST_IDLE;
s_rxbuf_head <= to_unsigned(0, RXBUFSIZE_BITS);
s_txbuf_tail <= to_unsigned(0, TXBUFSIZE_BITS);
s_txprev_full <= '0';
s_txprev_acked <= '1';
s_isync <= '0';
s_osync <= '0';
s_halt_in <= "00";
s_halt_out <= "00";
 
elsif usbi_usbrst = '1' then
 
-- Reset protocol state.
s_state <= ST_IDLE;
s_txprev_full <= '0';
s_txprev_acked <= '1';
s_isync <= '0';
s_osync <= '0';
s_halt_in <= "00";
s_halt_out <= "00";
 
else
 
case s_state is
 
when ST_IDLE =>
-- Idle; wait for a transaction
s_nyet <= '0';
if (usbt_endpt = data_endpt) and (usbt_in = '1') then
-- Start of IN transaction
if s_halt_in(1) = '1' then
-- Endpoint halted
s_state <= ST_STALL;
elsif (s_txbuf_tail /= s_txbuf_head and s_txcork = '0') or s_txprev_full = '1' then
-- Prepare to send data
s_bufptr <= resize(s_txbuf_tail, s_bufptr'length);
s_state <= ST_INSTART;
else
-- We have no data to send
s_state <= ST_NAK;
end if;
elsif (usbt_endpt = data_endpt) and (usbt_out = '1') then
-- Start of OUT transaction
if s_halt_out(1) = '1' then
-- Endpoint halted
s_state <= ST_STALL;
elsif v_rxbuf_pktroom = '1' then
-- Prepare to receive data
s_bufptr <= resize(s_rxbuf_head, s_bufptr'length);
s_state <= ST_OUTRECV;
else
-- We have no room to store a new packet
s_state <= ST_OUTNAK;
end if;
elsif HSSUPPORT and (usbt_endpt = data_endpt) and (usbt_ping = '1') then
-- Start of PING transaction
if v_rxbuf_pktroom = '1' then
-- There is room in the RX buffer for another packet; do nothing (ACK).
s_state <= ST_IDLE;
else
-- There is no room in the RX buffer; respond with NAK.
s_state <= ST_NAK;
end if;
elsif (usbt_endpt = notify_endpt) and (usbt_in = '1') then
-- The notify endpoint simply NAK's all IN transactions
if s_halt_in(2) = '1' then
-- Endpoint halted
s_state <= ST_STALL;
else
s_state <= ST_NAK;
end if;
end if;
 
-- Reset sync bits when the control endpoint tells us.
s_isync <= s_isync and (not usbc_clr_in(1));
s_osync <= s_osync and (not usbc_clr_out(1));
 
-- Set/reset halt bits when the control endpoint tells us.
s_halt_in(1) <= (s_halt_in(1) or usbc_sethlt_in(1)) and (not usbc_clr_in(1));
s_halt_in(2) <= (s_halt_in(2) or usbc_sethlt_in(2)) and (not usbc_clr_in(2));
s_halt_out(1) <= (s_halt_out(1) or usbc_sethlt_out(1)) and (not usbc_clr_out(1));
 
when ST_STALL =>
-- Wait for end of transaction
if (usbt_in = '0') and (usbt_out = '0') and (usbt_ping = '0') then
s_state <= ST_IDLE;
end if;
 
when ST_NAK =>
-- Wait for end of transaction
if (usbt_in = '0') and (usbt_out = '0') and (usbt_ping = '0') then
s_state <= ST_IDLE;
end if;
 
when ST_INSTART =>
-- Prepare to send data; read first byte from memory.
if usbt_in = '0' then
-- Transaction canceled.
s_state <= ST_IDLE;
elsif (s_txbuf_tail = s_txbuf_head) or
(s_txprev_acked = '0' and resize(s_bufptr, TXBUFSIZE_BITS) = s_txbuf_stop) or
(s_txprev_acked = '1' and s_txcork = '1') then
-- The TX buffer is empty, or a previous empty packet
-- is unacknowledged, or the TX buffer is corked;
-- must send an empty packet.
s_state <= ST_INDONE;
else
-- Send a non-empty packet.
if s_txprev_acked = '1' then
-- Set up a size limit for this packet.
s_txbuf_stop <= s_txbuf_tail + v_max_txsize;
end if;
s_bufptr <= s_bufptr + 1;
s_state <= ST_INSEND;
end if;
 
when ST_INSEND =>
-- Sending data
if usbt_in = '0' then
-- Transaction canceled.
s_state <= ST_IDLE;
elsif usbt_txrdy = '1' then
-- Need to provide the next data byte;
-- stop when we reach the end of the TX buffer;
-- stop when we reach the packet size limit.
if (resize(s_bufptr, TXBUFSIZE_BITS) = s_txbuf_head) or
(resize(s_bufptr, TXBUFSIZE_BITS) = s_txbuf_stop) then
-- No more bytes
s_state <= ST_INDONE;
else
s_bufptr <= s_bufptr + 1;
end if;
end if;
 
when ST_INDONE =>
-- Done sending packet; wait for ACK.
if usbt_in = '0' then
-- No acknowledgement
s_txprev_acked <= '0';
-- Set limit for next packet to the same point
s_txbuf_stop <= resize(s_bufptr, TXBUFSIZE_BITS);
-- Done
s_state <= ST_IDLE;
elsif usbt_fin = '1' then
-- Got acknowledgement
s_txprev_acked <= '1';
-- Update buffer tail
s_txbuf_tail <= resize(s_bufptr, TXBUFSIZE_BITS);
-- Flip sync bit
s_isync <= not s_isync;
-- Remember if this was a full-sized packet.
if s_txbuf_tail + v_max_txsize = resize(s_bufptr, TXBUFSIZE_BITS) then
s_txprev_full <= '1';
else
s_txprev_full <= '0';
end if;
-- Done
s_state <= ST_IDLE;
end if;
 
when ST_OUTRECV =>
-- Receiving data
if usbt_out = '0' then
-- Transaction ended.
-- If the transaction was succesful, usbt_fin has been
-- asserted in the previous cycle and has triggered
-- an update of s_rxbuf_head.
s_state <= ST_IDLE;
elsif (usbt_fin = '1') and (usbt_osync = s_osync) then
-- Good packet received; discard CRC bytes
s_rxbuf_head <= resize(s_bufptr, RXBUFSIZE_BITS) - 2;
s_osync <= not s_osync;
elsif usbt_rxrdy = '1' then
-- Got data byte
s_bufptr <= s_bufptr + 1;
if HSSUPPORT then
-- Set NYET if there is no room to receive
-- another packet after this one.
s_nyet <= not v_rxbuf_pktroom;
end if;
end if;
 
when ST_OUTNAK =>
-- Receiving data while we don't have room to store it
if usbt_out = '0' then
-- End of transaction
s_state <= ST_IDLE;
elsif (usbt_rxrdy = '1') and (usbt_osync = s_osync) then
-- This is a new (non-duplicate) packet, but we can
-- not store it; so respond with NAK.
s_state <= ST_NAK;
end if;
 
end case;
 
end if;
end process;
 
-- It is always a fight to get the synthesizer to infer block RAM.
-- The problem is we need dual port RAM with read-enable signals.
-- The recommended coding style, with registered read addresses,
-- does not work in this case.
-- The code below generates three RAM blocks on the Xilinx Spartan-3,
-- but it is doubtful whether it will work on other FPGA families.
 
-- Write to RX buffer.
process (CLK) is
begin
if rising_edge(CLK) then
if s_state = ST_OUTRECV and usbt_rxrdy = '1' then
rxbuf(to_integer(resize(s_bufptr, RXBUFSIZE_BITS))) <= usbt_rxdat;
end if;
end if;
end process;
 
-- Read from RX buffer.
process (CLK) is
begin
if rising_edge(CLK) then
if q_rxbuf_read = '1' then
rxbuf_rdat <= rxbuf(to_integer(q_rxbuf_tail));
end if;
end if;
end process;
 
-- Write to TX buffer.
process (CLK) is
begin
if rising_edge(CLK) then
if TXVAL = '1' then
txbuf(to_integer(q_txbuf_head)) <= TXDAT;
end if;
end if;
end process;
 
-- Read from TX buffer.
process (CLK) is
begin
if rising_edge(CLK) then
if (usbt_txrdy = '1') or (s_state = ST_INSTART) then
txbuf_rdat <= txbuf(to_integer(resize(s_bufptr, TXBUFSIZE_BITS)));
end if;
end if;
end process;
 
-- Read from descriptor memory.
process (CLK) is
begin
if rising_edge(CLK) then
if usbc_dscrd = '1' then
if HSSUPPORT and unsigned(usbc_dscoff) = 1 and usbc_dsctyp = "111" then
-- Disguise the configuration descriptor as an
-- other_speed_configuration descriptor.
descrom_raddr <= to_unsigned(DESC_OTHERSPEED_ADDR, descrom_raddr'length);
else
descrom_raddr <= descrom_start + resize(unsigned(usbc_dscoff), descrom_raddr'length);
end if;
end if;
end if;
end process;
assert to_integer(descrom_raddr) < descrom_rdat'length;
descrom_rdat <= descrom(to_integer(descrom_raddr));
 
end architecture usb_serial_arch;
 
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/vhdl/usb_transact.vhdl
0,0 → 1,628
--
-- USB 2.0 Transaction-level logic
--
-- This entity deals with transactions. A transaction consists of up to
-- three packets: token, data, handshake. This component supports four
-- transaction types:
-- * IN (device-to-host bulk/interrupt/control transfer)
-- * OUT (host-to-device bulk/interrupt/control transfer)
-- * SETUP (host-to-device control operation)
-- * PING (flow control for host-to-device bulk/control transfer, HS only)
-- Isochronous transactions are not supported.
--
-- The low-level interface signals are named P_xxx and connect to
-- the usb_packet component.
--
-- The application interface signals are named T_xxx and operate as
-- follows:
--
-- * At the start of a transaction, either T_IN, T_OUT, T_SETUP or T_PING
-- rises to 1, indicating the transaction type. At the same time,
-- T_ENDPT is set to the endpoint number for this transaction.
-- These signals are held for the duration of the transaction.
--
-- OUT and SETUP transactions:
-- * Each incoming byte is put on RXDAT and announced by asserting RXRDY.
-- These signals are valid for only one clock cycle.
-- * OSYNC is set to the transmitter's sync bit and held until the end
-- of the transaction.
-- * The last two bytes are CRC bytes; these should be ignored.
-- * Successfull completion is indicated by asserting T_FIN for one cycle.
-- * Receive errors are indicated by deasserting T_OUT/T_SETUP without
-- ever asserting T_FIN. In this case, the application must discard any
-- data already accepted during this transaction.
-- * It is probably safe to assume that the first assertion of T_RXRDY
-- does not immediately coincide with the rising T_OUT/T_SETUP signal.
-- The implementation of usb_control and usb_serial depend on this
-- assumption. The assumption may be false if PHY_RXACTIVE is low for
-- only one clock between token and data, and re-assertion of PHY_RXACTIVE
-- coincides with assertion of PHY_RXVALID. This is not explicitly
-- prohibited in the UTMI spec, but it just seems extremely unlikely.
--
-- OUT transactions:
-- * If the application is not ready to accept data, it should assert
-- either NAK or STALL. These signals must be set up as soon as the last
-- byte of the packet has been received, and kept stable until the end
-- of the transaction.
-- * If the application is ready to accept this OUT packet, but not ready
-- to accept a subsequent OUT packet, it may assert T_NYET. This signal
-- must be set up as soon as the last byte of the packet has been received
-- and kept stable until the end of the transaction. NYET is only valid
-- in high speed mode; in full speed mode, this entity will ignore the
-- NYET signal and send ACK instead.
-- * Note: NAK/STALL/NYET must not be used during SETUP transactions;
-- the standard specifies that SETUP transactions must always be ACK-ed
-- and errors reported during the subsequent data transaction.
--
-- IN transactions:
-- * The application should assert SEND, put the sync bit on ISYNC
-- and put the first byte on TXDAT. The component will assert TXRDY
-- to acknowledge each byte; in the following cycle, the application
-- must either provide the next data byte or release SEND to indicate
-- the end of the packet.
-- After T_IN rises, the application must respond within 2 clock cycles.
-- * The application must not include CRC bytes.
-- * If the application is not ready to send data, it should assert
-- either NAK or STALL and keep it asserted until the end of the
-- transaction.
-- * An empty packet can be sent by keeping SEND, NAK and STALL
-- deasserted; the component will interpret this as a zero-length SEND.
-- * Successfull completion of an IN transaction is indicated by
-- asserting FIN for one cycle.
-- * Timeout is indicated by deasserting T_IN without ever asserting FIN.
-- In this case, the application must assume that the IN transaction
-- failed.
--
-- PING transactions:
-- * In high speed mode only, the host may send a PING transaction to which
-- the application must respond with either ACK or NAK to indicate whether
-- it is willing to receive a full sized OUT transaction.
-- * When a PING is received, T_PING is raised and at the same time T_ENDPT
-- becomes valid. The application must respond within 2 clock cycles.
-- * If the application is not ready to received data, it should assert T_NAK
-- and keep it asserted until the end of the transaction. If the application
-- does not assert either T_NAK or T_STALL, an ACK response will be sent.
--
 
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
 
entity usb_transact is
 
generic (
 
-- Support high speed mode.
HSSUPPORT : boolean := false );
 
port (
 
-- 60 MHz UTMI clock.
CLK : in std_logic;
 
-- Synchronous reset of this entity.
RESET : in std_logic;
 
-- High during IN transactions.
T_IN : out std_logic;
 
-- High during OUT transactions.
T_OUT : out std_logic;
 
-- High during SETUP transactions.
T_SETUP : out std_logic;
 
-- High during PING transactions.
T_PING : out std_logic;
 
-- Indicates successfull completion of a transaction.
T_FIN : out std_logic;
 
-- Device address.
T_ADDR : in std_logic_vector(6 downto 0);
 
-- Endpoint number for current transaction.
T_ENDPT : out std_logic_vector(3 downto 0);
 
-- Triggers a NAK response to IN/OUT/PING.
T_NAK : in std_logic;
 
-- Triggers a STALL response to IN/OUT.
T_STALL : in std_logic;
 
-- Triggers a NYET response to OUT.
T_NYET : in std_logic;
 
-- High while application has data to send (in response to OUT).
T_SEND : in std_logic;
 
-- Sync bit to use for IN transactions.
T_ISYNC : in std_logic;
 
-- Sync bit used for the current OUT transaction.
T_OSYNC : out std_logic;
 
-- Indicates next byte received.
T_RXRDY : out std_logic;
 
-- Received data; valid when T_RXRDY = '1'.
T_RXDAT : out std_logic_vector(7 downto 0);
 
-- Requests next byte to transmit; application must update T_TXDAT or T_SEND in next cycle.
T_TXRDY : out std_logic;
 
-- Data byte to transmit; must be valid when T_SEND = '1'.
T_TXDAT : in std_logic_vector(7 downto 0);
 
-- Connect to I_HIGHSPEED from usb_init.
I_HIGHSPEED : in std_logic;
 
-- Connect to P_RXACT from usb_packet.
P_RXACT : in std_logic;
 
-- Connect to P_RXRDY from usb_packet.
P_RXRDY : in std_logic;
 
-- Connect to P_RXFIN from usb_packet.
P_RXFIN : in std_logic;
 
-- Connect to P_RXDAT from usb_packet.
P_RXDAT : in std_logic_vector(7 downto 0);
 
-- Connect to P_TXACT towards usb_packet.
P_TXACT : out std_logic;
 
-- Connect to P_TXRDY from usb_packet.
P_TXRDY : in std_logic;
 
-- Connect to P_TXDAT towards usb_packet.
P_TXDAT : out std_logic_vector(7 downto 0) );
 
end entity usb_transact;
 
architecture usb_transact_arch of usb_transact is
 
-- PID constants
constant pid_out : std_logic_vector(3 downto 0) := "0001";
constant pid_in : std_logic_vector(3 downto 0) := "1001";
constant pid_setup: std_logic_vector(3 downto 0) := "1101";
constant pid_ack : std_logic_vector(3 downto 0) := "0010";
constant pid_nak : std_logic_vector(3 downto 0) := "1010";
constant pid_stall: std_logic_vector(3 downto 0) := "1110";
constant pid_nyet : std_logic_vector(3 downto 0) := "0110";
constant pid_ping : std_logic_vector(3 downto 0) := "0100";
constant pid_data : std_logic_vector(2 downto 0) := "011";
 
function pid_mirror(v: std_logic_vector) return std_logic_vector
is begin
return (not v) & v;
end function;
 
-- State machine
type t_state is (
ST_IDLE, ST_SKIP,
ST_GETTOKEN1, ST_GETTOKEN2, ST_GETTOKEN3, ST_GOTTOKEN,
ST_SENDSHAKE,
ST_GETDATA, ST_GOTDATA,
ST_SENDDATA, ST_SENDING,
ST_WAITACK, ST_WAITSKIP, ST_GETACK );
signal s_state : t_state := ST_IDLE;
signal s_active : std_logic;
 
-- Transaction state
signal s_in : std_logic := '0';
signal s_out : std_logic := '0';
signal s_setup : std_logic := '0';
signal s_ping : std_logic := '0';
signal s_finished : std_logic := '0';
 
-- Previous value of P_RXACT; needed to detect bad packet while waiting for host.
signal s_prevrxact : std_logic;
 
-- PID byte to use for outgoing packet (ST_SENDSHAKE or ST_SENDDATA)
signal s_sendpid : std_logic_vector(3 downto 0);
 
-- Registered output signals
signal s_endpt : std_logic_vector(3 downto 0) := "0000";
signal s_osync : std_logic := '0';
 
-- In full speed mode, we must time out an expected host response after
-- 16 to 18 bit periods. In high speed mode, we must time out after
-- 736 to 816 bit periods. We can not get accurate timing because we don't
-- know the delay due to CRC, EOP, SYNC and UTMI pipeline. (We should use
-- PHY_LINESTATE for timing, but we don't.) So we just use a much longer
-- timeout; wait_timeout_fs = 511 cycles = 102 bit periods;
-- wait_timeout_hs = 127 cycles = 1020 bit periods.
constant wait_timeout_fs : unsigned(8 downto 0) := "111111111";
constant wait_timeout_hs : unsigned(8 downto 0) := "001111111";
 
-- In full speed mode, we must wait at least 2 and at most 6.5 bit periods
-- before responding to the host. We have wait_send_fs = 14 cycles from
-- rising T_IN/OUT/SETUP until valid T_NAK; equals 16 cycles from rising
-- P_RXFIN until rising P_TXACT; equals 18 cycles from falling PHY_RXACTIVE
-- until rising PHY_TXVALID. Including pipeline delay in the UTMI, we end
-- up with 2 to 5 bit periods from SE0-to-J until SYNC.
constant wait_send_fs : unsigned(8 downto 0) := "000001110";
 
-- In high speed mode, we must wait at least 8 and at most 192 bit periods
-- before responding to the host. We give the application wait_send_hs = 2
-- cycles to get its act together; i.e. from rising T_IN/OUT/SETUP/PING
-- until valid T_NAK/STALL/NYET/SEND. This corresponds to 4 cycles from
-- P_RXFIN until P_TXACT; equals 6 cycles from falling PHY_RXACTIVE until
-- rising PHY_TXVALID. Including pipeline delay in the UTMI, we end up
-- with 78 to 127 bit periods between packets.
constant wait_send_hs : unsigned(8 downto 0) := "000000010";
 
-- Count down timer.
signal wait_count : unsigned(8 downto 0);
 
begin
 
-- Assign control signals
s_active <=
'1' when (s_state = ST_IDLE or s_state = ST_GOTTOKEN or
s_state = ST_SENDSHAKE or
s_state = ST_GETDATA or s_state = ST_GOTDATA or
s_state = ST_SENDDATA or s_state = ST_SENDING or
s_state = ST_WAITACK or s_state = ST_WAITSKIP or s_state = ST_GETACK)
else '0';
T_IN <= s_in and s_active;
T_OUT <= s_out and s_active;
T_SETUP <= s_setup and s_active;
T_PING <= s_ping and s_active;
T_FIN <= s_finished; -- Note: T_FIN only occurs when s_state = ST_IDLE
T_ENDPT <= s_endpt;
T_OSYNC <= s_osync;
 
-- Received bytes
T_RXRDY <= P_RXRDY when (s_state = ST_GETDATA) else '0';
T_RXDAT <= P_RXDAT;
 
-- Byte to transmit: handshake PID, data PID or data byte
T_TXRDY <= P_TXRDY when (s_state = ST_SENDING) else '0';
P_TXACT <= '1' when (s_state = ST_SENDSHAKE or s_state = ST_SENDDATA or
(s_state = ST_SENDING and T_SEND = '1'))
else '0';
P_TXDAT <= pid_mirror(s_sendpid) when (s_state = ST_SENDSHAKE or s_state = ST_SENDDATA)
else T_TXDAT;
 
 
-- On every rising clock edge
process is
begin
wait until rising_edge(CLK);
 
s_prevrxact <= P_RXACT;
 
if RESET = '1' then
 
-- Reset this component
s_state <= ST_IDLE;
s_in <= '0';
s_out <= '0';
s_setup <= '0';
s_ping <= '0';
s_finished <= '0';
 
else
 
case s_state is
 
when ST_IDLE =>
-- Idle; wait for incoming packet
s_in <= '0';
s_out <= '0';
s_setup <= '0';
s_ping <= '0';
s_finished <= '0';
if P_RXRDY = '1' then
case P_RXDAT(3 downto 0) is
when pid_out =>
-- OUT token
s_out <= '1';
s_state <= ST_GETTOKEN1;
when pid_in =>
-- IN token
s_in <= '1';
s_state <= ST_GETTOKEN1;
when pid_setup =>
-- SETUP token
s_setup <= '1';
s_state <= ST_GETTOKEN1;
when pid_ping =>
-- PING token
if HSSUPPORT then
s_ping <= '1';
s_state <= ST_GETTOKEN1;
else
-- no PINGing for full speed devices
s_state <= ST_SKIP;
end if;
when others =>
-- unexpected packet
s_state <= ST_SKIP;
end case;
end if;
 
when ST_SKIP =>
-- Skip incoming packet and go back to IDLE
if P_RXACT = '0' then
s_state <= ST_IDLE;
end if;
 
when ST_GETTOKEN1 =>
-- Receive and check 2nd byte of a token packet
if P_RXACT = '0' then
-- Bad packet
s_state <= ST_IDLE;
elsif P_RXRDY = '1' then
-- Store endpoint number
s_endpt(0) <= P_RXDAT(7);
-- Check address
if P_RXDAT(6 downto 0) = T_ADDR then
-- Packet is addressed to us
s_state <= ST_GETTOKEN2;
else
-- Packet not addressed to us
s_state <= ST_SKIP;
end if;
end if;
 
when ST_GETTOKEN2 =>
-- Receive 3rd byte of token packet
if P_RXACT = '0' then
-- Bad packet
s_state <= ST_IDLE;
elsif P_RXRDY = '1' then
-- Store endpoint number
s_endpt(3 downto 1) <= P_RXDAT(2 downto 0);
s_state <= ST_GETTOKEN3;
end if;
 
when ST_GETTOKEN3 =>
-- Wait for end of incoming token packet
if P_RXFIN = '1' then
-- Token was ok
s_state <= ST_GOTTOKEN;
elsif P_RXACT = '0' then
-- Token was bad
s_state <= ST_IDLE;
end if;
if (s_in = '1') or (HSSUPPORT and (s_ping = '1')) then
if HSSUPPORT and (I_HIGHSPEED = '1') then
wait_count <= wait_send_hs;
else
wait_count <= wait_send_fs;
end if;
else
if HSSUPPORT and (I_HIGHSPEED = '1') then
wait_count <= wait_timeout_hs;
else
wait_count <= wait_timeout_fs;
end if;
end if;
 
when ST_GOTTOKEN =>
-- Wait for data packet or wait for our turn to respond
if P_RXACT = '1' then
if P_RXRDY = '1' then
-- Got PID byte
if ((s_out = '1') or (s_setup = '1')) and
(P_RXDAT(2 downto 0) = pid_data) then
-- This is the DATA packet we were waiting for
s_osync <= P_RXDAT(3);
s_state <= ST_GETDATA;
else
-- Got unexpected packet
s_in <= '0';
s_out <= '0';
s_setup <= '0';
s_ping <= '0';
case P_RXDAT(3 downto 0) is
when pid_out =>
-- unexpected OUT token
s_out <= '1';
s_state <= ST_GETTOKEN1;
when pid_in =>
-- unexpected IN token
s_in <= '1';
s_state <= ST_GETTOKEN1;
when pid_setup =>
-- unexpected SETUP token
s_setup <= '1';
s_state <= ST_GETTOKEN1;
when pid_ping =>
-- unexpected PING token
if HSSUPPORT then
s_ping <= '1';
s_state <= ST_GETTOKEN1;
else
-- no PINGing for full speed devices
s_state <= ST_SKIP;
end if;
when others =>
-- unexpected packet
s_state <= ST_SKIP;
end case;
end if;
end if;
elsif s_prevrxact = '1' then
-- got bad packet
s_state <= ST_IDLE;
elsif wait_count = 0 then
-- timer reached zero
if s_in = '1' then
-- IN transaction: send response
if T_STALL = '1' then
s_state <= ST_SENDSHAKE;
s_sendpid <= pid_stall;
elsif T_NAK = '1' then
s_state <= ST_SENDSHAKE;
s_sendpid <= pid_nak;
else
s_state <= ST_SENDDATA;
s_sendpid <= T_ISYNC & pid_data;
end if;
elsif HSSUPPORT and (s_ping = '1') then
-- PING transaction: send handshake
s_state <= ST_SENDSHAKE;
if T_STALL = '1' then
s_sendpid <= pid_stall;
elsif T_NAK = '1' then
s_sendpid <= pid_nak;
else
s_sendpid <= pid_ack;
end if;
else
-- OUT/SETUP transaction:
-- timeout while waiting for DATA packet
s_state <= ST_IDLE;
end if;
end if;
-- count down timer
wait_count <= wait_count - 1;
 
when ST_SENDSHAKE =>
-- Send handshake packet
if P_TXRDY = '1' then
-- Handshake done, transaction completed
s_finished <= '1';
s_state <= ST_IDLE;
end if;
 
when ST_GETDATA =>
-- Wait for end of incoming data packet
if P_RXFIN = '1' then
-- Data packet was good, respond with handshake
s_state <= ST_GOTDATA;
elsif P_RXACT = '0' then
-- Data packet was bad, ignore it
s_state <= ST_IDLE;
end if;
if HSSUPPORT and (I_HIGHSPEED = '1') then
wait_count <= wait_send_hs;
else
wait_count <= wait_send_fs;
end if;
 
when ST_GOTDATA =>
-- Wait for inter-packet delay before responding
if wait_count = 0 then
-- Move to response state
s_state <= ST_SENDSHAKE;
if T_STALL = '1' then
s_sendpid <= pid_stall;
elsif T_NAK = '1' then
s_sendpid <= pid_nak;
elsif HSSUPPORT and (I_HIGHSPEED = '1') and (T_NYET = '1') then
s_sendpid <= pid_nyet;
else
s_sendpid <= pid_ack;
end if;
end if;
wait_count <= wait_count - 1;
 
when ST_SENDDATA =>
-- Start sending a data packet
if P_TXRDY = '1' then
-- Sent PID byte, need first data byte
s_state <= ST_SENDING;
end if;
 
when ST_SENDING =>
-- Send payload of data packet
if T_SEND = '0' then
-- End of data packet
s_state <= ST_WAITACK;
end if;
if HSSUPPORT and (I_HIGHSPEED = '1') then
wait_count <= wait_timeout_hs;
else
wait_count <= wait_timeout_fs;
end if;
 
when ST_WAITACK =>
-- Wait for ACK handshake
if P_RXACT = '1' then
if P_RXRDY = '1' then
-- Got PID byte
case P_RXDAT(3 downto 0) is
when pid_ack =>
-- ACK handshake
s_state <= ST_GETACK;
when pid_out =>
-- unexpected OUT token
s_in <= '0';
s_out <= '1';
s_state <= ST_GETTOKEN1;
when pid_in =>
-- unexpected IN token
s_in <= '1';
s_state <= ST_GETTOKEN1;
when pid_setup =>
-- unexpected SETUP token
s_in <= '0';
s_setup <= '1';
s_state <= ST_GETTOKEN1;
when pid_ping =>
-- unexpected PING token
if HSSUPPORT then
s_in <= '0';
s_ping <= '1';
s_state <= ST_GETTOKEN1;
else
-- no PINGing for full speed devices
s_state <= ST_SKIP;
end if;
when ("0" & pid_data) | ("1" & pid_data) =>
-- unexpected DATA packet
-- This could be our own transmitted packet
-- (if it was very short), so skip this.
s_state <= ST_WAITSKIP;
when others =>
-- unexpected packet
s_state <= ST_SKIP;
end case;
end if;
elsif s_prevrxact = '1' then
-- got bad packet
s_state <= ST_IDLE;
elsif wait_count = 0 then
-- timeout while waiting for ACK
s_state <= ST_IDLE;
end if;
-- count down timer
wait_count <= wait_count - 1;
 
when ST_WAITSKIP =>
-- Skip the echo of our own transmitted packet
if wait_count = 0 then
-- timeout
s_state <= ST_SKIP;
elsif P_RXFIN = '1' then
-- end of packet
s_state <= ST_WAITACK;
elsif P_RXACT = '0' then
-- bad packet
s_state <= ST_IDLE;
end if;
-- count down timer
wait_count <= wait_count - 1;
 
when ST_GETACK =>
-- Wait for end of incoming ACK packet
if P_RXFIN = '1' then
-- ACK handshake was good
s_finished <= '1';
s_state <= ST_IDLE;
elsif P_RXACT = '0' then
-- ACK handshake was bad
s_state <= ST_IDLE;
end if;
 
end case;
 
end if;
 
end process;
 
end architecture usb_transact_arch;
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/vhdl/usb_control.vhdl
0,0 → 1,623
--
-- USB 2.0 Default control endpoint
--
-- This entity implements the minimal required functionality of
-- the default control endpoint.
--
-- The low-level interface signals are named T_xxx and should be conditionally
-- connected to the usb_transact interface in the following way:
-- * Always connect output signal C_ADDR to T_ADDR;
-- * Always connect input signals T_FIN, T_OSYNC, T_RXRDY, T_RXDAT, T_TXRDY;
-- * If T_ENDPT = 0, connect input signals T_IN, T_OUT, T_SETUP, T_PING;
-- otherwise pull these inputs to zero.
-- * If T_ENDPT = 0, connect output signals T_NAK, T_STALL, T_NYET, T_SEND,
-- T_ISYNC, T_TXDAT; otherwise another endpoint should drive these.
-- * If T_ENDPT = 0 and C_DSCBUSY = 0, connect output signal T_TXDAT;
-- otherwise if T_ENDPT = 0 and C_DSCBUSY = 1, drive T_TXDAT
-- from descriptor memory;
-- otherwise another endpoint drives T_TXDAT.
--
-- A device descriptor and a configuration descriptor must be provided
-- in external memory. If high speed mode is supported, an other-speed
-- device qualifier and other-speed configuration descriptor must also
-- be provided. In addition, string descriptors may optionally be provided.
-- Each descriptor may be at most 255 bytes long.
-- A maximum packet size of 64 bytes is assumed for control transfers.
--
-- This entity uses the following protocol to access descriptor data:
-- * When C_DSCBUSY is high, the entity is accessing descriptor data.
-- A descriptor is selected by signals C_DSCTYP and C_DSCINX;
-- a byte within this descriptor is selected by signal C_DSCOFF.
-- * Based on C_DSCTYP and C_DSCINX, the application must assign
-- the length of the selected descriptor to C_DSCLEN. If the selected
-- descriptor does not exist, the application must set C_DSCLEN to zero.
-- C_DSCLEN must be valid one clock after rising C_DSCBUSY and must
-- remain stable as long as C_DSCBUSY, C_DSCTYP and C_DSCINX remain
-- unchanged.
-- * When C_DSCRD is asserted, the application must put the selected
-- byte from the selected descriptor on T_TXDAT towards usb_transact.
-- The application must respond in the first clock cycle following
-- assertion of C_DSCRD.
-- * When C_DSCRD is not asserted, but C_DSCBUSY is still high,
-- the application must keep T_TXDAT unchanged. Changes to C_DSCOFF
-- must not affect T_TXDAT while C_DSCRD is low.
--
-- The standard device requests are handled as follows:
--
-- Clear Feature:
-- When clearing the ENDPOINT_HALT feature, reset the endpoint's
-- sync bits (as required by spec). Otherwise ignore but report
-- success status.
-- BAD: should return STALL when referring to invalid endpoint/interface.
--
-- Get Configuration:
-- Return 1 if configured, 0 if not configured.
--
-- Get Descriptor:
-- Handled by application through descriptor data interface as
-- described above.
--
-- Get Interface:
-- Always return zero byte.
-- BAD: should return STALL when referring to invalid endpoint/interface.
--
-- Get Status:
-- Return device status / endpoint status / zero.
-- BAD: should return STALL when referring to invalid endpoint/interface.
--
-- Set Address:
-- Store new address.
--
-- Set Configuration:
-- Switch between Configured and Address states; clear all endpoint
-- sync bits (as required by spec). Accepts only configuration values
-- 0 and 1.
--
-- Set Descriptor:
-- Not implemented; returns STALL. (Correct; request is optional.)
--
-- Set Feature:
-- Only ENDPOINT_HALT feature implemented; otherwise returns STALL.
-- BAD: every high speed device must support TEST_MODE.
--
-- Set Interface:
-- Not implemented; returns STALL.
-- (Correct; request is optional if no interfaces have alternate settings.)
--
-- Synch Frame:
-- Not implemented; returns STALL.
-- (Correct, assuming no isosynchronous endpoints.)
--
-- Non-standard requests are silently ignored but return success status.
-- This is incorrect, but necessary to get host software to accept usb_serial
-- as CDC-ACM device.
--
 
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
 
entity usb_control is
 
generic (
 
-- Highest endpoint number in use.
NENDPT : integer range 1 to 15 );
 
port (
 
-- 60 MHz UTMI clock.
CLK : in std_logic;
 
-- Synchronous reset of this entity.
RESET : in std_logic;
 
-- Current device address.
C_ADDR : out std_logic_vector(6 downto 0);
 
-- High when in Configured state.
C_CONFD : out std_logic;
 
-- Trigger clearing of sync/halt bits for IN endpoint.
C_CLRIN : out std_logic_vector(1 to NENDPT);
 
-- Trigger clearing of sync/halt bits for OUT endpoint.
C_CLROUT : out std_logic_vector(1 to NENDPT);
 
-- Current status of halt bit for IN endpoints.
C_HLTIN : in std_logic_vector(1 to NENDPT);
 
-- Current status of halt bit for IN endpoints.
C_HLTOUT : in std_logic_vector(1 to NENDPT);
 
-- Trigger setting of halt bit for IN endpoints.
C_SHLTIN : out std_logic_vector(1 to NENDPT);
 
-- Trigger setting of halt bit for OUT endpoints.
C_SHLTOUT : out std_logic_vector(1 to NENDPT);
 
-- High when accessing descriptor memory.
-- Note that C_DSCBUSY may go low in between packets of a single descriptor.
C_DSCBUSY : out std_logic;
 
-- Descriptor read enable. Asserted to request a descriptor byte;
-- in the next clock cycle, the application must update T_TXDAT.
C_DSCRD : out std_logic;
 
-- LSB bits of the requested descriptor type. Valid when C_DSCBUSY is high.
C_DSCTYP : out std_logic_vector(2 downto 0);
 
-- Requested descriptor index. Valid when C_DSCBUSY is high.
C_DSCINX : out std_logic_vector(7 downto 0);
 
-- Offset within requested descriptor. Valid when C_DSCBUSY and C_DSCRD are high.
C_DSCOFF : out std_logic_vector(7 downto 0);
 
-- Set to length of current descriptor by application.
C_DSCLEN : in std_logic_vector(7 downto 0);
 
-- High if the device is not drawing bus power.
C_SELFPOWERED : in std_logic;
 
-- Connect to T_IN from usb_transact when T_ENDPT = 0, otherwise pull to 0.
T_IN : in std_logic;
 
-- Connect to T_OUT from usb_transact when T_ENDPT = 0, otherwise pull to 0.
T_OUT : in std_logic;
 
-- Connect to T_SETUP from usb_transact when T_ENDPT = 0, otherwise pull to 0.
T_SETUP : in std_logic;
 
-- Connect to T_PING from usb_transact when T_ENDPT = 0, otherwise pull to 0.
T_PING : in std_logic;
 
-- Connect to T_FIN from ubs_transact.
T_FIN : in std_logic;
 
-- Connect to T_NAK towards usb_transact when T_ENDPT = 0.
T_NAK : out std_logic;
 
-- Connect to T_STALL towards usb_transact when T_ENDPT = 0.
T_STALL : out std_logic;
 
-- Connect to T_NYET towards usb_transact when T_ENDPT = 0.
T_NYET : out std_logic;
 
-- Connect to T_SEND towards usb_transact when T_ENDPT = 0.
T_SEND : out std_logic;
 
-- Connect to T_ISYNC towards usb_transact when T_ENDPT = 0.
T_ISYNC : out std_logic;
 
-- Connect to T_OSYNC from usb_transact.
T_OSYNC : in std_logic;
 
-- Connect to T_RXRDY from usb_transact.
T_RXRDY : in std_logic;
 
-- Connect to T_RXDAT from usb_transact.
T_RXDAT : in std_logic_vector(7 downto 0);
 
-- Connect to T_TXRDY from usb_transact.
T_TXRDY : in std_logic;
 
-- Connect to T_TXDAT towards usb_transact when T_ENDPT = 0 and C_DSCBUSY = '0'.
T_TXDAT : out std_logic_vector(7 downto 0) );
 
end entity usb_control;
 
architecture usb_control_arch of usb_control is
 
-- Constants for control request
constant req_getstatus : std_logic_vector(3 downto 0) := "0000";
constant req_clearfeature : std_logic_vector(3 downto 0) := "0001";
constant req_setfeature : std_logic_vector(3 downto 0) := "0011";
constant req_setaddress : std_logic_vector(3 downto 0) := "0101";
constant req_getdesc : std_logic_vector(3 downto 0) := "0110";
constant req_getconf : std_logic_vector(3 downto 0) := "1000";
constant req_setconf : std_logic_vector(3 downto 0) := "1001";
constant req_getiface : std_logic_vector(3 downto 0) := "1010";
 
-- State machine
type t_state is (
ST_IDLE, ST_STALL,
ST_SETUP, ST_SETUPERR, ST_NONSTANDARD, ST_ENDSETUP, ST_WAITIN,
ST_SENDRESP, ST_STARTDESC, ST_SENDDESC, ST_DONESEND );
signal s_state : t_state := ST_IDLE;
 
-- Current control request
signal s_ctlrequest : std_logic_vector(3 downto 0);
signal s_ctlparam : std_logic_vector(7 downto 0);
signal s_desctyp : std_logic_vector(2 downto 0);
signal s_answerlen : unsigned(7 downto 0);
signal s_sendbyte : std_logic_vector(7 downto 0) := "00000000";
 
-- Device state
signal s_addr : std_logic_vector(6 downto 0) := "0000000";
signal s_confd : std_logic := '0';
 
-- Counters
signal s_setupptr : unsigned(2 downto 0);
signal s_answerptr : unsigned(7 downto 0);
 
begin
 
-- Status signals
C_ADDR <= s_addr;
C_CONFD <= s_confd;
 
-- Memory interface
C_DSCBUSY <= T_IN when (s_state = ST_WAITIN) else
'1' when (s_state = ST_STARTDESC or s_state = ST_SENDDESC) else
'0';
C_DSCRD <= '1' when (s_state = ST_STARTDESC) else T_TXRDY;
C_DSCTYP <= s_desctyp;
C_DSCINX <= s_ctlparam;
C_DSCOFF <= std_logic_vector(s_answerptr);
 
-- Transaction interface
T_NAK <= '0';
T_STALL <= '1' when (s_state = ST_STALL) else '0';
T_NYET <= '0';
T_SEND <= '1' when ((s_state = ST_SENDRESP) or (s_state = ST_SENDDESC))
else '0';
T_ISYNC <= not std_logic(s_answerptr(6));
T_TXDAT <= s_sendbyte;
 
-- On every rising clock edge
process is
begin
wait until rising_edge(CLK);
 
-- Set endpoint reset/halt lines to zero by default
C_CLRIN <= (others => '0');
C_CLROUT <= (others => '0');
C_SHLTIN <= (others => '0');
C_SHLTOUT <= (others => '0');
 
-- State machine
if RESET = '1' then
 
-- Reset this entity
s_state <= ST_IDLE;
s_addr <= "0000000";
s_confd <= '0';
 
-- Trigger endpoint reset lines
C_CLRIN <= (others => '1');
C_CLROUT <= (others => '1');
 
else
 
case s_state is
 
when ST_IDLE =>
-- Idle; wait for SETUP transaction;
-- OUT transactions are ignored but acknowledged;
-- IN transactions send an empty packet.
s_answerptr <= to_unsigned(0, s_answerptr'length);
if T_SETUP = '1' then
-- Start of SETUP transaction
s_state <= ST_SETUP;
s_setupptr <= to_unsigned(0, s_setupptr'length);
end if;
 
when ST_STALL =>
-- Stalled; wait for next SETUP transaction;
-- respond to IN/OUT transactions with a STALL handshake.
if T_SETUP = '1' then
-- Start of SETUP transaction
s_state <= ST_SETUP;
s_setupptr <= to_unsigned(0, s_setupptr'length);
end if;
 
when ST_SETUP =>
-- In SETUP transaction; parse request structure.
s_answerptr <= to_unsigned(0, s_answerptr'length);
if T_RXRDY = '1' then
-- Process next request byte
case s_setupptr is
when "000" =>
-- bmRequestType
s_ctlparam <= T_RXDAT;
if T_RXDAT(6 downto 5) /= "00" then
-- non-standard device request
s_state <= ST_NONSTANDARD;
end if;
when "001" =>
-- bRequest
s_ctlrequest <= T_RXDAT(3 downto 0);
if T_RXDAT(7 downto 4) /= "0000" then
-- Unknown request
s_state <= ST_SETUPERR;
end if;
when "010" =>
-- wValue lsb
if s_ctlrequest /= req_getstatus then
s_ctlparam <= T_RXDAT;
end if;
when "011" =>
-- wValue msb
if s_ctlrequest = req_getdesc then
if T_RXDAT(7 downto 3) /= "00000" then
-- Unsupported descriptor type
s_state <= ST_SETUPERR;
end if;
end if;
-- Store descriptor type (assuming GET_DESCRIPTOR request)
s_desctyp <= T_RXDAT(2 downto 0);
when "100" =>
-- wIndex lsb
case s_ctlrequest is
when req_clearfeature =>
if s_ctlparam = "00000000" then
-- Clear ENDPOINT_HALT feature;
-- store endpoint selector
s_ctlparam <= T_RXDAT;
else
-- Unknown clear feature request
s_ctlparam <= "00000000";
end if;
when req_setfeature =>
if s_ctlparam = "00000000" then
-- Set ENDPOINT_HALT feature;
-- store endpoint selector
s_ctlparam <= T_RXDAT;
else
-- Unsupported set feature request
s_state <= ST_SETUPERR;
end if;
when req_getstatus =>
if s_ctlparam(1 downto 0) = "00" then
-- Get device status
s_sendbyte <= "0000000" & C_SELFPOWERED;
s_ctlparam <= "00000000";
elsif s_ctlparam(1 downto 0) = "10" then
-- Get endpoint status
s_sendbyte <= "00000000";
s_ctlparam <= T_RXDAT;
else
-- Probably get interface status
s_sendbyte <= "00000000";
s_ctlparam <= "00000000";
end if;
when others =>
-- Don't care about index.
end case;
when "101" =>
-- wIndex msb; don't care
when "110" =>
-- wLength lsb
s_answerlen <= unsigned(T_RXDAT);
when "111" =>
-- wLength msb
if T_RXDAT /= "00000000" then
s_answerlen <= "11111111";
end if;
s_state <= ST_ENDSETUP;
when others =>
-- Impossible
end case;
-- Increment position within SETUP packet
s_setupptr <= s_setupptr + 1;
elsif T_FIN = '1' then
-- Got short SETUP packet; answer with STALL status.
s_state <= ST_STALL;
elsif T_SETUP = '0' then
-- Got corrupt SETUP packet; ignore.
s_state <= ST_IDLE;
end if;
 
when ST_SETUPERR =>
-- In SETUP transaction; got request error
if T_FIN = '1' then
-- Got good SETUP packet that causes request error
s_state <= ST_STALL;
elsif T_SETUP = '0' then
-- Got corrupt SETUP packet; ignore
s_state <= ST_IDLE;
end if;
 
when ST_NONSTANDARD =>
-- Ignore non-standard requests
if T_SETUP = '0' then
s_state <= ST_IDLE;
end if;
 
when ST_ENDSETUP =>
-- Parsed request packet; wait for end of SETUP transaction
if T_FIN = '1' then
-- Got complet SETUP packet; handle it
case s_ctlrequest is
when req_getstatus =>
-- Prepare status byte and move to data stage
-- If s_ctlparam = 0, the status byte has already
-- been prepared in state S_SETUP.
for i in 1 to NENDPT loop
if unsigned(s_ctlparam(3 downto 0)) = i then
if s_ctlparam(7) = '1' then
s_sendbyte <= "0000000" & C_HLTIN(i);
else
s_sendbyte <= "0000000" & C_HLTOUT(i);
end if;
end if;
end loop;
s_state <= ST_WAITIN;
when req_clearfeature =>
-- Reset endpoint
for i in 1 to NENDPT loop
if unsigned(s_ctlparam(3 downto 0)) = i then
if s_ctlparam(7) = '1' then
C_CLRIN(i) <= '1';
else
C_CLROUT(i) <= '1';
end if;
end if;
end loop;
s_state <= ST_IDLE;
when req_setfeature =>
-- Set endpoint HALT
for i in 1 to NENDPT loop
if unsigned(s_ctlparam(3 downto 0)) = i then
if s_ctlparam(7) = '1' then
C_SHLTIN(i) <= '1';
else
C_SHLTOUT(i) <= '1';
end if;
end if;
end loop;
s_state <= ST_IDLE;
when req_setaddress =>
-- Move to status stage
s_state <= ST_WAITIN;
when req_getdesc =>
-- Move to data stage
s_state <= ST_WAITIN;
when req_getconf =>
-- Move to data stage
s_state <= ST_WAITIN;
when req_setconf =>
-- Set device configuration
if s_ctlparam(7 downto 1) = "0000000" then
s_confd <= s_ctlparam(0);
s_state <= ST_IDLE;
C_CLRIN <= (others => '1');
C_CLROUT <= (others => '1');
else
-- Unknown configuration number
s_state <= ST_STALL;
end if;
when req_getiface =>
-- Move to data stage
s_state <= ST_WAITIN;
when others =>
-- Unsupported request
s_state <= ST_STALL;
end case;
elsif T_SETUP = '0' then
-- Got corrupt SETUP packet; ignore
s_state <= ST_IDLE;
end if;
 
when ST_WAITIN =>
-- Got valid SETUP packet; waiting for IN transaction.
s_answerptr(5 downto 0) <= "000000";
if T_SETUP = '1' then
-- Start of next SETUP transaction
s_state <= ST_SETUP;
s_setupptr <= to_unsigned(0, s_setupptr'length);
elsif T_IN = '1' then
-- Start of IN transaction; respond to the request
case s_ctlrequest is
when req_getstatus =>
-- Respond with status byte, followed by zero byte.
s_state <= ST_SENDRESP;
when req_setaddress =>
-- Effectuate change of device address
s_addr <= s_ctlparam(6 downto 0);
s_state <= ST_IDLE;
when req_getdesc =>
-- Respond with descriptor
s_state <= ST_STARTDESC;
when req_getconf =>
-- Respond with current configuration
s_sendbyte <= "0000000" & s_confd;
s_state <= ST_SENDRESP;
when req_getiface =>
-- Respond with zero byte
s_sendbyte <= "00000000";
s_state <= ST_SENDRESP;
when others =>
-- Impossible
end case;
end if;
 
when ST_SENDRESP =>
-- Respond to IN with a preset byte,
-- followed by zero or more nul byte(s)
if T_IN = '0' then
-- Aborted IN transaction; wait for retry
s_state <= ST_WAITIN;
elsif T_TXRDY = '1' then
-- Need next data byte
s_sendbyte <= "00000000";
if (s_answerptr(0) = '1') or (s_answerlen(0) = '1') then
-- Reached end of transfer.
-- Note that we only ever send 1 or 2 byte answers.
s_state <= ST_DONESEND;
end if;
s_answerptr(5 downto 0) <= s_answerptr(5 downto 0) + 1;
end if;
 
when ST_STARTDESC =>
-- Fetching first byte of packet.
if T_IN = '0' then
-- Aborted IN transaction; wait for retry
s_state <= ST_WAITIN;
elsif unsigned(C_DSCLEN) = 0 then
-- Invalid descriptor.
s_state <= ST_STALL;
elsif (s_answerptr = unsigned(C_DSCLEN)) or
(s_answerptr = s_answerlen) then
-- Send an empty packet to complete the transfer.
s_state <= ST_DONESEND;
else
-- Send a normal descriptor packet.
s_state <= ST_SENDDESC;
end if;
s_answerptr(5 downto 0) <= s_answerptr(5 downto 0) + 1;
 
when ST_SENDDESC =>
-- Respond to IN with descriptor
if T_IN = '0' then
-- Aborted IN transaction; wait for retry
s_state <= ST_WAITIN;
elsif T_TXRDY = '1' then
-- Need next data byte
if (s_answerptr(5 downto 0) = 0) or
(s_answerptr = unsigned(C_DSCLEN)) or
(s_answerptr = s_answerlen) then
-- Just sent the last byte of the packet
s_state <= ST_DONESEND;
else
s_answerptr(5 downto 0) <= s_answerptr(5 downto 0) + 1;
end if;
end if;
 
when ST_DONESEND =>
-- Done sending packet; wait until IN transaction completes.
-- Note: s_answerptr contains the number of bytes sent so-far,
-- unless this is a multiple of 64, in which case s_answerptr
-- contains 64 less than the number of bytes sent; and unless
-- the last packet sent was an empty end-of-transfer packet,
-- in which case s_answerptr contains 1 more than the number
-- of bytes sent.
if T_FIN = '1' then
-- Host acknowledged transaction.
if s_answerptr(5 downto 0) = 0 then
-- The last sent packet was a full sized packet.
-- If s_answerptr + 64 = s_answerlen, the transfer
-- is now complete; otherwise the host will expect
-- more data. In either case, we go back to WAITIN.
-- This can't go wrong because WAITIN also listens
-- for the next SETUP and handles it properly.
s_state <= ST_WAITIN;
else
-- The last sent packet was not full sized;
-- it was either empty or reached the end of
-- the descriptor. In either case, the transfer
-- is now complete.
s_state <= ST_IDLE;
end if;
s_answerptr <= s_answerptr + 64;
elsif T_IN = '0' then
-- Transaction failed; wait for retry.
s_state <= ST_WAITIN;
end if;
 
end case;
 
end if;
 
end process;
 
end architecture usb_control_arch;
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/vhdl/usb_pkg.vhdl
0,0 → 1,163
--
-- USB 2.0 VHDL package
--
 
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
 
package usb_pkg is
 
-- Initialization, handshake, reset.
component usb_init is
generic (
HSSUPPORT : boolean := false ); -- Support high speed mode
port (
CLK : in std_logic; -- 60 MHz UTMI clock
RESET : in std_logic; -- Synchronous reset
I_USBRST : out std_logic; -- High when bus reset signal detected
I_HIGHSPEED : out std_logic; -- High when attached at high speed
I_SUSPEND : out std_logic; -- High when suspended
P_CHIRPK : out std_logic;
PHY_RESET : out std_logic;
PHY_LINESTATE : in std_logic_vector(1 downto 0);
PHY_OPMODE : out std_logic_vector(1 downto 0);
PHY_XCVRSELECT : out std_logic;
PHY_TERMSELECT : out std_logic );
end component usb_init;
 
-- Packet-level logic and CRC handling.
component usb_packet is
port (
CLK : in std_logic; -- 60 MHz UTMI clock
RESET : in std_logic; -- Synchronous reset of this entity
P_CHIRPK : in std_logic; -- High to force chirp K transmission
P_RXACT : out std_logic; -- High while receiving a packet
P_RXRDY : out std_logic; -- Indicates arrival of a byte
P_RXFIN : out std_logic; -- Indicates successfull completion
P_RXDAT : out std_logic_vector(7 downto 0); -- Received byte value
P_TXACT : in std_logic; -- High while transmitting a packet
P_TXRDY : out std_logic; -- Request for next data byte
P_TXDAT : in std_logic_vector(7 downto 0); -- Data byte to transmit
PHY_DATAIN : in std_logic_vector(7 downto 0);
PHY_DATAOUT : out std_logic_vector(7 downto 0);
PHY_TXVALID : out std_logic;
PHY_TXREADY : in std_logic;
PHY_RXACTIVE : in std_logic;
PHY_RXVALID : in std_logic;
PHY_RXERROR : in std_logic );
end component usb_packet;
 
-- Transaction-level logic.
component usb_transact is
generic (
HSSUPPORT : boolean := false ); -- Support high speed mode
port (
CLK : in std_logic; -- 60 MHz UTMI clock
RESET : in std_logic; -- Synchronous reset of this entity
T_IN : out std_logic; -- High during IN transactions
T_OUT : out std_logic; -- High during OUT transactions
T_SETUP : out std_logic; -- High during SETUP transactions
T_PING : out std_logic; -- High during PING transactions
T_FIN : out std_logic; -- Indicates successfull completion
T_ADDR : in std_logic_vector(6 downto 0); -- Device address
T_ENDPT : out std_logic_vector(3 downto 0); -- Endpoint number
T_NAK : in std_logic; -- Triggers a NAK response to IN/OUT
T_STALL : in std_logic; -- Triggers a STALL response to IN/OUT
T_NYET : in std_logic; -- Triggers a NYET response to OUT
T_SEND : in std_logic; -- High while application has data to send
T_ISYNC : in std_logic; -- Sync bit to use for IN transactions
T_OSYNC : out std_logic; -- Sync bit used in the OUT transaction
T_RXRDY : out std_logic; -- Indicates arrival of received byte
T_RXDAT : out std_logic_vector(7 downto 0); -- Received data
T_TXRDY : out std_logic; -- Requests next data byte to transmit
T_TXDAT : in std_logic_vector(7 downto 0); -- Data to transmit
I_HIGHSPEED : in std_logic;
P_RXACT : in std_logic;
P_RXRDY : in std_logic;
P_RXFIN : in std_logic;
P_RXDAT : in std_logic_vector(7 downto 0);
P_TXACT : out std_logic;
P_TXRDY : in std_logic;
P_TXDAT : out std_logic_vector(7 downto 0) );
end component usb_transact;
 
-- Default control endpoint.
component usb_control is
generic (
NENDPT : integer range 1 to 15 ); -- Highest endpoint number in use
port (
CLK : in std_logic; -- 60 MHz UTMI clock
RESET : in std_logic; -- Synchronous reset of this entity
C_ADDR : out std_logic_vector(6 downto 0); -- Current device address
C_CONFD : out std_logic; -- High when in Configured state
C_CLRIN : out std_logic_vector(1 to NENDPT); -- Trigger clearing of sync bit for IN endpoint
C_CLROUT : out std_logic_vector(1 to NENDPT); -- Trigger clearing of sync bit for OUT endpoint
C_HLTIN : in std_logic_vector(1 to NENDPT); -- Current status of halt bit for IN endpoint
C_HLTOUT : in std_logic_vector(1 to NENDPT); -- Current status of halt bit for OUT endpoint
C_SHLTIN : out std_logic_vector(1 to NENDPT); -- Trigger setting of halt bit for IN endpoint
C_SHLTOUT : out std_logic_vector(1 to NENDPT); -- Trigger setting of halt bit for OUT endpoint
C_DSCBUSY : out std_logic; -- High when accessing descriptor memory
C_DSCRD : out std_logic; -- Descriptor read enable
C_DSCTYP : out std_logic_vector(2 downto 0); -- Requested descriptor type
C_DSCINX : out std_logic_vector(7 downto 0); -- Requested descriptor index
C_DSCOFF : out std_logic_vector(7 downto 0); -- Offset within requested descriptor
C_DSCLEN : in std_logic_vector(7 downto 0); -- Length of selected descriptor
C_SELFPOWERED : in std_logic; -- High if the device is not drawing bus power
T_IN : in std_logic;
T_OUT : in std_logic;
T_SETUP : in std_logic;
T_PING : in std_logic;
T_FIN : in std_logic;
T_NAK : out std_logic;
T_STALL : out std_logic;
T_NYET : out std_logic;
T_SEND : out std_logic;
T_ISYNC : out std_logic;
T_OSYNC : in std_logic;
T_RXRDY : in std_logic;
T_RXDAT : in std_logic_vector(7 downto 0);
T_TXRDY : in std_logic;
T_TXDAT : out std_logic_vector(7 downto 0) );
end component usb_control;
 
-- Serial data transfer core.
component usb_serial is
generic (
VENDORID : std_logic_vector(15 downto 0); -- Vendor ID
PRODUCTID : std_logic_vector(15 downto 0); -- Product ID
VERSIONBCD : std_logic_vector(15 downto 0); -- Product version
HSSUPPORT : boolean := false; -- Support high speed mode
SELFPOWERED : boolean := false; -- Device does not use bus power
RXBUFSIZE_BITS: integer range 7 to 12 := 11; -- Size of receive buffer
TXBUFSIZE_BITS: integer range 7 to 12 := 10 ); -- Size of transmit buffer
port (
CLK : in std_logic; -- 60 MHz UTMI clock
RESET : in std_logic; -- Synchronous reset
USBRST : out std_logic; -- Reset signal detected on bus
HIGHSPEED : out std_logic; -- Device operating in high speed mode
SUSPEND : out std_logic; -- Device is suspended
ONLINE : out std_logic; -- Device is in Configured state
RXVAL : out std_logic; -- Received byte available on RXDAT
RXDAT : out std_logic_vector(7 downto 0);
RXRDY : in std_logic; -- Application ready for next byte
RXLEN : out std_logic_vector(RXBUFSIZE_BITS-1 downto 0);
TXVAL : in std_logic; -- Application has data to send
TXDAT : in std_logic_vector(7 downto 0);
TXRDY : out std_logic; -- Entity ready to accept next byte
TXROOM : out std_logic_vector(TXBUFSIZE_BITS-1 downto 0);
TXCORK : in std_logic; -- Suppress data transmission
PHY_DATAIN : in std_logic_vector(7 downto 0);
PHY_DATAOUT : out std_logic_vector(7 downto 0);
PHY_TXVALID : out std_logic;
PHY_TXREADY : in std_logic;
PHY_RXACTIVE : in std_logic;
PHY_RXVALID : in std_logic;
PHY_RXERROR : in std_logic;
PHY_LINESTATE : in std_logic_vector(1 downto 0);
PHY_OPMODE : out std_logic_vector(1 downto 0);
PHY_XCVRSELECT: out std_logic;
PHY_TERMSELECT: out std_logic;
PHY_RESET : out std_logic );
end component usb_serial;
 
end package usb_pkg;
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/vhdl/usb_init.vhdl
0,0 → 1,386
--
-- USB 2.0 Initialization, handshake and reset detection.
--
-- This entity provides the following functions:
--
-- * USB bus attachment: At powerup and after a RESET signal, switch to
-- non-driving mode, wait for 17 ms, then attach to the USB bus. This
-- should ensure that the host notices our reattachment and initiates
-- a reset procedure.
--
-- * High speed handshake (if HSSUPPORT enabled): attempt to enter
-- high speed mode after a bus reset.
--
-- * Monitor the linestate for reset and/or suspend signalling.
--
-- The low-level interface connects to an UTMI compliant USB PHY such as
-- the SMSC GT3200. The UTMI interface must be configured for 60 MHz operation
-- with an 8-bit data bus.
--
 
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
 
entity usb_init is
 
generic (
 
-- Support high speed mode.
HSSUPPORT : boolean := false );
 
port (
 
-- 60 MHz UTMI clock.
CLK : in std_logic;
 
-- Synchronous reset; triggers detach and reattach to the USB bus.
RESET : in std_logic;
 
-- High for one clock if a reset signal is detected on the USB bus.
I_USBRST : out std_logic;
 
-- High when attached to the host in high speed mode.
I_HIGHSPEED : out std_logic;
 
-- High when suspended.
-- Reset of this signal is asynchronous.
-- This signal may be used to drive (inverted) the UTMI SuspendM pin.
I_SUSPEND : out std_logic;
 
-- High to tell usb_packet that it must drive a continuous K state.
P_CHIRPK : out std_logic;
 
-- Connect to the UTMI Reset signal.
PHY_RESET : out std_logic;
 
-- Connect to the UTMI LineState signal.
PHY_LINESTATE : in std_logic_vector(1 downto 0);
 
-- Cconnect to the UTMI OpMode signal.
PHY_OPMODE : out std_logic_vector(1 downto 0);
 
-- Connect to the UTMI XcvrSelect signal (0 = high speed, 1 = full speed).
PHY_XCVRSELECT : out std_logic;
 
-- Connect to the UTMI TermSelect signal (0 = high speed, 1 = full speed).
PHY_TERMSELECT : out std_logic );
 
end entity usb_init;
 
architecture usb_init_arch of usb_init is
 
-- Time from bus idle until device suspend (3 ms).
constant TIME_SUSPEND : unsigned(19 downto 0) := to_unsigned(180000, 20);
 
-- Time from start of SE0 until detection of reset signal (2.5 us + 10%).
constant TIME_RESET : unsigned(7 downto 0) := to_unsigned(165, 8);
 
-- Time to wait for good SE0 when waking up from suspend (6 ms).
constant TIME_SUSPRST: unsigned(19 downto 0) := to_unsigned(360000, 20);
 
-- Duration of chirp K from device during high speed detection (1 ms + 10%).
constant TIME_CHIRPK : unsigned(19 downto 0) := to_unsigned(66000, 20);
 
-- Minimum duration of chirp J/K during high speed detection (2.5 us + 10%).
constant TIME_FILT : unsigned(7 downto 0) := to_unsigned(165, 8);
 
-- Time to wait for chirp until giving up (1.1 ms).
constant TIME_WTFS : unsigned(19 downto 0) := to_unsigned(66000, 20);
 
-- Time to wait after reverting to full-speed before sampling the bus (100 us).
constant TIME_WTRSTHS : unsigned(19 downto 0) := to_unsigned(6000, 20);
 
-- State machine
type t_state is (
ST_INIT, ST_FSRESET, ST_FULLSPEED, ST_SUSPEND, ST_SUSPRESET,
ST_SENDCHIRP, ST_RECVCHIRP, ST_HIGHSPEED, ST_HSREVERT );
signal s_state : t_state := ST_INIT;
 
-- Timers.
signal s_timer1 : unsigned(7 downto 0);
signal s_timer2 : unsigned(19 downto 0) := to_unsigned(0, 20);
 
-- Count J/K chirps.
signal s_chirpcnt : unsigned(2 downto 0);
 
-- High if the device is operating in high speed (or suspended from high speed).
signal s_highspeed : std_logic := '0';
 
-- High if the device is currently suspended.
-- Reset of this signal is asynchronous.
signal s_suspend : std_logic := '0';
 
-- Input registers.
signal s_linestate : std_logic_vector(1 downto 0);
 
-- Output registers.
signal s_reset : std_logic := '1';
signal s_opmode : std_logic_vector(1 downto 0) := "01";
signal s_xcvrselect : std_logic := '1';
signal s_termselect : std_logic := '1';
signal s_chirpk : std_logic := '0';
 
begin
 
I_USBRST <= s_reset;
I_HIGHSPEED <= s_highspeed;
I_SUSPEND <= s_suspend;
P_CHIRPK <= s_chirpk;
PHY_RESET <= s_reset;
PHY_OPMODE <= s_opmode;
PHY_XCVRSELECT <= s_xcvrselect;
PHY_TERMSELECT <= s_termselect;
 
-- Synchronous process.
process is
variable v_clrtimer1 : std_logic;
variable v_clrtimer2 : std_logic;
begin
wait until rising_edge(CLK);
 
-- By default, do not clear the timers.
v_clrtimer1 := '0';
v_clrtimer2 := '0';
 
-- Register linestate input.
s_linestate <= PHY_LINESTATE;
 
-- Default assignments to registers.
s_reset <= '0';
s_chirpk <= '0';
 
if RESET = '1' then
 
-- Reset PHY.
s_reset <= '1';
s_opmode <= "01";
s_xcvrselect <= '1';
s_termselect <= '1';
 
-- Go to ST_INIT state and wait until bus attachment.
v_clrtimer1 := '1';
v_clrtimer2 := '1';
s_highspeed <= '0';
s_state <= ST_INIT;
 
else
 
case s_state is
 
when ST_INIT =>
-- Wait before attaching to bus.
s_opmode <= "01"; -- non-driving
s_xcvrselect <= '1'; -- full speed
s_termselect <= '1'; -- full speed
v_clrtimer1 := '1';
if s_timer2 = to_unsigned(0, s_timer2'length) - 1 then
-- Timer2 overflows after ~ 17 ms; attach to bus.
v_clrtimer2 := '1';
s_state <= ST_FULLSPEED;
end if;
 
when ST_FSRESET =>
-- Waiting for end of reset before full speed operation.
s_highspeed <= '0';
s_opmode <= "00"; -- normal
s_xcvrselect <= '1'; -- full speed
s_termselect <= '1'; -- full speed
v_clrtimer1 := '1';
v_clrtimer2 := '1';
if s_linestate /= "00" then
-- Reset signal ended.
s_state <= ST_FULLSPEED;
end if;
 
when ST_FULLSPEED =>
-- Operating in full speed.
s_highspeed <= '0';
s_opmode <= "00"; -- normal
s_xcvrselect <= '1'; -- full speed
s_termselect <= '1'; -- full speed
if s_linestate /= "00" then
-- Bus not in SE0 state; clear reset timer.
v_clrtimer1 := '1';
end if;
if s_linestate /= "01" then
-- Bus not in J state; clear suspend timer.
v_clrtimer2 := '1';
end if;
if s_timer1 = TIME_RESET then
-- Bus has been in SE0 state for TIME_RESET;
-- this is a reset signal.
s_reset <= '1';
if HSSUPPORT then
s_state <= ST_SENDCHIRP;
else
s_state <= ST_FSRESET;
end if;
elsif s_timer2 = TIME_SUSPEND then
-- Bus has been idle for TIME_SUSPEND;
-- go to suspend state.
s_state <= ST_SUSPEND;
end if;
 
when ST_SUSPEND =>
-- Suspended; waiting for resume signal.
-- Possibly our clock will be disabled; wake up
-- is initiated by the asynchronous reset of s_suspend.
s_opmode <= "00"; -- normal
s_xcvrselect <= '1'; -- full speed
s_termselect <= '1'; -- full speed
v_clrtimer1 := '1';
v_clrtimer2 := '1';
if s_linestate /= "01" then
-- Bus not in J state; resume.
if HSSUPPORT and s_highspeed = '1' then
-- High speed resume protocol.
if s_linestate = "10" then
-- Bus in K state; resume to high speed.
s_state <= ST_HIGHSPEED;
elsif s_linestate = "00" then
-- Bus in SE0 state; start reset detection.
s_state <= ST_SUSPRESET;
end if;
else
-- Resume to full speed.
s_state <= ST_FULLSPEED;
end if;
end if;
 
when ST_SUSPRESET =>
-- Wake up in SE0 state; wait for proper reset signal.
s_opmode <= "00"; -- normal
s_xcvrselect <= '1'; -- full speed
s_termselect <= '1'; -- full speed
if s_linestate /= "00" then
-- Bus not in SE0 state; clear reset timer.
v_clrtimer1 := '1';
end if;
if s_timer1 = TIME_RESET then
-- Bus has been in SE0 state for TIME_RESET;
-- this is a reset signal.
s_reset <= '1';
v_clrtimer2 := '1';
s_state <= ST_SENDCHIRP;
end if;
if s_timer2 = TIME_SUSPRST then
-- Still no proper reset signal; go back to sleep.
s_state <= ST_SUSPEND;
end if;
 
when ST_SENDCHIRP =>
-- Sending chirp K for a duration of TIME_CHIRPK.
s_highspeed <= '0';
s_opmode <= "10"; -- disable bit stuffing
s_xcvrselect <= '0'; -- high speed
s_termselect <= '1'; -- full speed
s_chirpk <= '1'; -- send chirp K
v_clrtimer1 := '1';
if s_timer2 = TIME_CHIRPK then
-- end of chirp K
v_clrtimer2 := '1';
s_chirpcnt <= "000";
s_state <= ST_RECVCHIRP;
end if;
 
when ST_RECVCHIRP =>
-- Waiting for K-J-K-J-K-J chirps.
-- Note: DO NOT switch Opmode to normal yet; there
-- may be pending bits in the transmission buffer.
s_opmode <= "10"; -- disable bit stuffing
s_xcvrselect <= '0'; -- high speed
s_termselect <= '1'; -- full speed
if ( s_chirpcnt(0) = '0' and s_linestate /= "10" ) or
( s_chirpcnt(0) = '1' and s_linestate /= "01" ) then
-- Not the linestate we want.
v_clrtimer1 := '1';
end if;
if s_timer2 = TIME_WTFS then
-- High speed detection failed; go to full speed.
v_clrtimer1 := '1';
v_clrtimer2 := '1';
s_state <= ST_FSRESET;
elsif s_timer1 = TIME_FILT then
-- We got the chirp we wanted.
if s_chirpcnt = 5 then
-- This was the last chirp;
-- we got a successful high speed handshake.
v_clrtimer2 := '1';
s_state <= ST_HIGHSPEED;
end if;
s_chirpcnt <= s_chirpcnt + 1;
v_clrtimer1 := '1';
end if;
 
when ST_HIGHSPEED =>
-- Operating in high speed.
s_highspeed <= '1';
s_opmode <= "00"; -- normal
s_xcvrselect <= '0'; -- high speed
s_termselect <= '0'; -- high speed
if s_linestate /= "00" then
-- Bus not idle; clear revert timer.
v_clrtimer2 := '1';
end if;
if s_timer2 = TIME_SUSPEND then
-- Bus has been idle for TIME_SUSPEND;
-- revert to full speed.
v_clrtimer2 := '1';
s_state <= ST_HSREVERT;
end if;
 
when ST_HSREVERT =>
-- Revert to full speed and wait for 100 us.
s_opmode <= "00"; -- normal
s_xcvrselect <= '1'; -- full speed
s_termselect <= '1'; -- full speed
if s_timer2 = TIME_WTRSTHS then
v_clrtimer2 := '1';
if s_linestate = "00" then
-- Reset from high speed.
s_reset <= '1';
s_state <= ST_SENDCHIRP;
else
-- Suspend from high speed.
s_state <= ST_SUSPEND;
end if;
end if;
 
end case;
 
end if;
 
-- Increment or clear timer1.
if v_clrtimer1 = '1' then
s_timer1 <= to_unsigned(0, s_timer1'length);
else
s_timer1 <= s_timer1 + 1;
end if;
 
-- Increment or clear timer2.
if v_clrtimer2 = '1' then
s_timer2 <= to_unsigned(0, s_timer2'length);
else
s_timer2 <= s_timer2 + 1;
end if;
 
end process;
 
-- Drive the s_suspend flipflop (synchronous set, asynchronous reset).
process (CLK, PHY_LINESTATE) is
begin
if PHY_LINESTATE /= "01" then
-- The bus is not in full speed idle state;
-- reset the s_suspend flipflop.
s_suspend <= '0';
elsif rising_edge(CLK) then
if s_state = ST_SUSPEND then
-- Bus is idle and FSM is in suspend state;
-- enable the s_suspend flipflop.
s_suspend <= '1';
end if;
end if;
end process;
 
end architecture usb_init_arch;
 
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/vhdl/usb_packet.vhdl
0,0 → 1,460
--
-- USB 2.0 Packet-level logic.
--
-- This entity hides the details of the UTMI interface and handles
-- computation and verificaton of CRCs.
--
-- The low-level interface signals are named PHY_xxx and may be
-- connected to an UTMI compliant USB PHY, such as the SMSC GT3200.
--
-- The application interface signals are named P_xxx.
-- The receiving side of the interface operates as follows:
-- * At the start of an incoming packet, RXACT is set high.
-- * When a new byte arrives, RXRDY is asserted and the byte is put
-- on RXDAT. These signals are valid for only one clock cycle; the
-- application must accept them immediately.
-- * The first byte of a packet is the PID. Subsequent bytes contain
-- data and CRC. This entity verifies the CRC, but does not
-- discard it from the data stream.
-- * Some time after correctly receiving the last byte of a packet,
-- RXACT is deasserted; at the same time RXFIN is asserted for one cycle
-- to confirm the packet.
-- * If a corrupt packet is received, RXACT is deasserted without
-- asserting RXFIN.
--
-- The transmission side of the interface operates as follows:
-- * The application starts transmission by setting TXACT to 1 and setting
-- TXDAT to the PID value (with correctly mirrored high order bits).
-- * The entity asserts TXRDY when it needs the next payload byte.
-- On the following clock cycle, the application must then provide the
-- next payload byte on TXDAT, or deassert TXACT to indicate the end of
-- the packet. The signal on TXDAT must be held stable until the next
-- assertion of TXRDY.
-- * CRC bytes should not be included in the payload; the entity will
-- add them automatically.
-- * As part of the high speed handshake, the application may request
-- transmission of a continuous chirp K state by asserting CHIRPK.
--
-- Implementation note:
-- Transmission timing is a bit tricky due to the following issues:
-- * After the PHY asserts PHY_TXREADY, we must immediately provide
-- new data or deassert PHY_TXVALID on the next clock cycle.
-- * The PHY may assert PHY_TXREADY during subsequent clock cycles,
-- even though the average byte period is more than 40 cycles.
-- * We want to register PHY inputs and outputs to ensure valid timing.
--
-- To satisfy these requirements, we make the application run one byte
-- ahead. While keeping the current byte in the output register PHY_DATAOUT,
-- the application already provides the following data byte. That way, we
-- can respond to PHY_TXREADY immediately in the next cycle, with the
-- application following up in the clock cycle after that.
--
 
library ieee;
use ieee.std_logic_1164.all, ieee.numeric_std.all;
 
entity usb_packet is
 
port (
 
-- 60 MHz UTMI clock.
CLK : in std_logic;
 
-- Synchronous reset of this entity.
RESET : in std_logic;
 
-- High to force chirp K transmission.
P_CHIRPK : in std_logic;
 
-- High while receiving a packet.
P_RXACT : out std_logic;
 
-- Indicates next byte received; data must be read from RXDAT immediately.
P_RXRDY : out std_logic;
 
-- High for one cycle to indicate successful completion of packet.
P_RXFIN : out std_logic;
 
-- Received byte value. Valid if RXRDY is high.
P_RXDAT : out std_logic_vector(7 downto 0);
 
-- High while transmitting a packet.
P_TXACT : in std_logic;
 
-- Request for next data byte; application must change TXDAT on the next clock cycle.
P_TXRDY : out std_logic;
 
-- Data byte to transmit. Hold stable until next assertion of TXRDY.
P_TXDAT : in std_logic_vector(7 downto 0);
 
-- Connect to UTMI DataIn signal.
PHY_DATAIN : in std_logic_vector(7 downto 0);
 
-- Connect to UTMI DataOut signal.
PHY_DATAOUT : out std_logic_vector(7 downto 0);
 
-- Connect to UTMI TxValid signal.
PHY_TXVALID : out std_logic;
 
-- Connect to UTMI TxReady signal.
PHY_TXREADY : in std_logic;
 
-- Connect to UTMI RxActive signal.
PHY_RXACTIVE : in std_logic;
 
-- Connect to UTMI RxValid signal.
PHY_RXVALID : in std_logic;
 
-- Connect to UTMI RxError signal.
PHY_RXERROR : in std_logic );
 
end entity usb_packet;
 
architecture usb_packet_arch of usb_packet is
 
-- State machine
type t_state is (
ST_NONE, ST_CHIRPK,
ST_RWAIT, ST_RTOKEN, ST_RDATA, ST_RSHAKE,
ST_TSTART, ST_TDATA, ST_TCRC1, ST_TCRC2 );
signal s_state : t_state := ST_NONE;
signal s_txfirst : std_logic := '0';
 
-- Registered inputs
signal s_rxactive : std_logic;
signal s_rxvalid : std_logic;
signal s_rxerror : std_logic;
signal s_datain : std_logic_vector(7 downto 0);
signal s_txready : std_logic;
 
-- Byte pending for transmission
signal s_dataout : std_logic_vector(7 downto 0);
 
-- True if an incoming packet would be valid if it ended now.
signal s_rxgoodpacket : std_logic;
 
-- CRC computation
constant crc5_gen : std_logic_vector(4 downto 0) := "00101";
constant crc5_res : std_logic_vector(4 downto 0) := "01100";
constant crc16_gen : std_logic_vector(15 downto 0) := "1000000000000101";
constant crc16_res : std_logic_vector(15 downto 0) := "1000000000001101";
signal crc5_buf : std_logic_vector(4 downto 0);
signal crc16_buf : std_logic_vector(15 downto 0);
 
-- Update CRC 5 to account for a new byte
function crc5_upd(
c : in std_logic_vector(4 downto 0);
b : in std_logic_vector(7 downto 0) )
return std_logic_vector
is
variable t : std_logic_vector(4 downto 0);
variable y : std_logic_vector(4 downto 0);
begin
t := (
b(0) xor c(4),
b(1) xor c(3),
b(2) xor c(2),
b(3) xor c(1),
b(4) xor c(0) );
y := (
b(5) xor t(1) xor t(2),
b(6) xor t(0) xor t(1) xor t(4),
b(5) xor b(7) xor t(0) xor t(3) xor t(4),
b(6) xor t(1) xor t(3) xor t(4),
b(7) xor t(0) xor t(2) xor t(3) );
return y;
end function;
 
-- Update CRC-16 to account for new byte
function crc16_upd(
c : in std_logic_vector(15 downto 0);
b : in std_logic_vector(7 downto 0) )
return std_logic_vector
is
variable t : std_logic_vector(7 downto 0);
variable y : std_logic_vector(15 downto 0);
begin
t := (
b(0) xor c(15),
b(1) xor c(14),
b(2) xor c(13),
b(3) xor c(12),
b(4) xor c(11),
b(5) xor c(10),
b(6) xor c(9),
b(7) xor c(8) );
y := (
c(7) xor t(0) xor t(1) xor t(2) xor t(3) xor t(4) xor t(5) xor t(6) xor t(7),
c(6), c(5), c(4), c(3), c(2),
c(1) xor t(7),
c(0) xor t(6) xor t(7),
t(5) xor t(6),
t(4) xor t(5),
t(3) xor t(4),
t(2) xor t(3),
t(1) xor t(2),
t(0) xor t(1),
t(1) xor t(2) xor t(3) xor t(4) xor t(5) xor t(6) xor t(7),
t(0) xor t(1) xor t(2) xor t(3) xor t(4) xor t(5) xor t(6) xor t(7) );
return y;
end function;
 
begin
 
-- Assign output signals
P_RXACT <= s_rxactive;
P_RXFIN <= (not s_rxactive) and (not s_rxerror) and s_rxgoodpacket;
P_RXRDY <= s_rxactive and s_rxvalid;
P_RXDAT <= s_datain;
 
-- Assert P_TXRDY during ST_TSTART to acknowledge the PID byte,
-- during the first cycle of ST_TDATA to acknowledge the first
-- data byte, and whenever we need a new data byte during ST_TDATA.
P_TXRDY <= '1' when (s_state = ST_TSTART)
else (s_txfirst or s_txready) when (s_state = ST_TDATA)
else '0';
 
-- On every rising clock edge
process is
variable v_dataout : std_logic_vector(7 downto 0);
variable v_txvalid : std_logic;
variable v_crc_upd : std_logic;
variable v_crc_data : std_logic_vector(7 downto 0);
variable v_crc5_new : std_logic_vector(4 downto 0);
variable v_crc16_new : std_logic_vector(15 downto 0);
begin
wait until rising_edge(CLK);
 
-- Default assignment to temporary variables
v_dataout := s_dataout;
v_txvalid := '0';
v_crc_upd := '0';
v_crc_data := "00000000";
v_crc5_new := "00000";
v_crc16_new := "0000000000000000";
 
-- Default assignment to s_txfirst
s_txfirst <= '0';
 
-- Register inputs
s_rxactive <= PHY_RXACTIVE;
s_rxvalid <= PHY_RXVALID;
s_rxerror <= PHY_RXERROR;
s_datain <= PHY_DATAIN;
s_txready <= PHY_TXREADY;
 
-- State machine
if RESET = '1' then
 
-- Reset entity
s_state <= ST_NONE;
s_rxgoodpacket <= '0';
 
else
 
case s_state is
when ST_NONE =>
-- Waiting for incoming or outgoing packet
 
-- Initialize CRC buffers
crc5_buf <= "11111";
crc16_buf <= "1111111111111111";
s_rxgoodpacket <= '0';
 
if P_CHIRPK = '1' then
-- Send continuous chirp K.
s_state <= ST_CHIRPK;
 
elsif s_rxactive = '1' then
-- Receiver starting
 
if s_rxerror = '1' then
-- Receive error at PHY level
s_state <= ST_RWAIT;
elsif s_rxvalid = '1' then
-- Got PID byte
if s_datain(3 downto 0) = not s_datain(7 downto 4) then
case s_datain(1 downto 0) is
when "01" => -- token packet
s_state <= ST_RTOKEN;
when "11" => -- data packet
s_state <= ST_RDATA;
when "10" => -- handshake packet
s_state <= ST_RSHAKE;
s_rxgoodpacket <= '1';
when others => -- PING token or special packet
-- If this is a PING token, it will work out fine;
-- otherwise it will be flagged as a bad packet
-- either here or in usb_transact.
s_state <= ST_RTOKEN;
end case;
else
-- Corrupt PID byte
s_state <= ST_RWAIT;
end if;
end if;
 
elsif P_TXACT = '1' then
-- Transmission starting; put data in output buffer
v_txvalid := '1';
v_dataout := P_TXDAT;
s_state <= ST_TSTART;
end if;
 
when ST_CHIRPK =>
-- Sending continuous chirp K.
if P_CHIRPK = '0' then
s_state <= ST_NONE;
end if;
 
when ST_RTOKEN =>
-- Receiving a token packet
if s_rxactive = '0' then
-- End of packet
s_rxgoodpacket <= '0';
s_state <= ST_NONE;
elsif s_rxerror = '1' then
-- Error at PHY level
s_rxgoodpacket <= '0';
s_state <= ST_RWAIT;
elsif s_rxvalid = '1' then
-- Just received a byte; update CRC
v_crc5_new := crc5_upd(crc5_buf, s_datain);
crc5_buf <= v_crc5_new;
if v_crc5_new = crc5_res then
s_rxgoodpacket <= '1';
else
s_rxgoodpacket <= '0';
end if;
end if;
 
when ST_RDATA =>
-- Receiving a data packet
if s_rxactive = '0' then
-- End of packet
s_rxgoodpacket <= '0';
s_state <= ST_NONE;
elsif s_rxerror = '1' then
-- Error at PHY level
s_rxgoodpacket <= '0';
s_state <= ST_RWAIT;
elsif s_rxvalid = '1' then
-- Just received a byte; update CRC
v_crc_upd := '1';
v_crc_data := s_datain;
end if;
 
when ST_RWAIT =>
-- Wait until the end of the current packet
if s_rxactive = '0' then
s_state <= ST_NONE;
end if;
 
when ST_RSHAKE =>
-- Receiving a handshake packet
if s_rxactive = '0' then
-- Got good handshake
s_rxgoodpacket <= '0';
s_state <= ST_NONE;
elsif s_rxerror = '1' or s_rxvalid = '1' then
-- Error or unexpected data byte in handshake packet
s_rxgoodpacket <= '0';
s_state <= ST_RWAIT;
end if;
 
when ST_TSTART =>
-- Transmission starting;
-- PHY module sees our PHY_TXVALID signal;
-- PHY_TXREADY is undefined;
-- we assert P_TXRDY to acknowledge the PID byte
v_txvalid := '1';
-- Check packet type
case P_TXDAT(1 downto 0) is
when "11" => -- data packet
s_state <= ST_TDATA;
s_txfirst <= '1';
when "10" => -- handshake packet
s_state <= ST_RWAIT;
when others => -- should not happen
end case;
 
when ST_TDATA =>
-- Sending a data packet
v_txvalid := '1';
if (s_txready = '1') or (s_txfirst = '1') then
-- Need next byte
if P_TXACT = '0' then
-- No more data; send first CRC byte
for i in 0 to 7 loop
v_dataout(i) := not crc16_buf(15-i);
end loop;
s_state <= ST_TCRC1;
else
-- Put next byte in output buffer
v_dataout := P_TXDAT;
-- And update the CRC
v_crc_upd := '1';
v_crc_data := P_TXDAT;
end if;
end if;
 
when ST_TCRC1 =>
-- Sending the first CRC byte of a data packet
v_txvalid := '1';
if s_txready = '1' then
-- Just queued the first CRC byte; move to 2nd byte
for i in 0 to 7 loop
v_dataout(i) := not crc16_buf(7-i);
end loop;
s_state <= ST_TCRC2;
end if;
 
when ST_TCRC2 =>
-- Sending the second CRC byte of a data packet
if s_txready = '1' then
-- Just sent the 2nd CRC byte; end packet
s_state <= ST_RWAIT;
else
-- Last byte is still pending
v_txvalid := '1';
end if;
 
end case;
 
end if;
 
-- CRC-16 update
if v_crc_upd = '1' then
v_crc16_new := crc16_upd(crc16_buf, v_crc_data);
crc16_buf <= v_crc16_new;
if s_state = ST_RDATA and v_crc16_new = crc16_res then
-- If this is the last byte of the packet, it is a valid packet.
s_rxgoodpacket <= '1';
else
s_rxgoodpacket <= '0';
end if;
end if;
 
-- Drive data output to PHY
if RESET = '1' then
-- Reset.
PHY_TXVALID <= '0';
PHY_DATAOUT <= "00000000";
elsif s_state = ST_CHIRPK then
-- Continuous chirp-K.
PHY_TXVALID <= P_CHIRPK;
PHY_DATAOUT <= "00000000";
elsif (PHY_TXREADY = '1') or (s_state = ST_NONE and P_TXACT = '1') then
-- Move a data byte from the buffer to the output lines when the PHY
-- accepts the previous byte, and also at the start of a new packet.
PHY_TXVALID <= v_txvalid;
PHY_DATAOUT <= v_dataout;
end if;
 
-- Keep pending output byte in register.
s_dataout <= v_dataout;
 
end process;
 
end architecture usb_packet_arch;
 
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/verilog/usb_rx_phy.v
0,0 → 1,452
/////////////////////////////////////////////////////////////////////
//// ////
//// USB 1.1 PHY ////
//// RX & DPLL ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/usb_phy/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
//// www.asics.ws ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: usb_rx_phy.v,v 1.5 2004/10/19 09:29:07 rudi Exp $
//
// $Date: 2004/10/19 09:29:07 $
// $Revision: 1.5 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: usb_rx_phy.v,v $
// Revision 1.5 2004/10/19 09:29:07 rudi
// Fixed DPLL alignment in the rx_phy and bit stuffing errors in the tx_phy (if last bit bit was a stuff bit in a packet it was omitted).
//
// Revision 1.4 2003/12/02 04:56:00 rudi
// Fixed a bug reported by Karl C. Posch from Graz University of Technology. Thanks Karl !
//
// Revision 1.3 2003/10/19 18:07:45 rudi
// - Fixed Sync Error to be only checked/generated during the sync phase
//
// Revision 1.2 2003/10/19 17:40:13 rudi
// - Made core more robust against line noise
// - Added Error Checking and Reporting
// (See README.txt for more info)
//
// Revision 1.1.1.1 2002/09/16 14:27:01 rudi
// Created Directory Structure
//
//
//
//
//
//
//
//
 
`include "timescale.v"
 
module usb_rx_phy( clk, rst, fs_ce,
// Transciever Interface
rxd, rxdp, rxdn,
 
// UTMI Interface
RxValid_o, RxActive_o, RxError_o, DataIn_o,
RxEn_i, LineState);
 
input clk;
input rst;
output fs_ce;
input rxd, rxdp, rxdn;
output [7:0] DataIn_o;
output RxValid_o;
output RxActive_o;
output RxError_o;
input RxEn_i;
output [1:0] LineState;
 
///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//
 
reg rxd_s0, rxd_s1, rxd_s;
reg rxdp_s0, rxdp_s1, rxdp_s, rxdp_s_r;
reg rxdn_s0, rxdn_s1, rxdn_s, rxdn_s_r;
reg synced_d;
wire k, j, se0;
reg rxd_r;
reg rx_en;
reg rx_active;
reg [2:0] bit_cnt;
reg rx_valid1, rx_valid;
reg shift_en;
reg sd_r;
reg sd_nrzi;
reg [7:0] hold_reg;
wire drop_bit; // Indicates a stuffed bit
reg [2:0] one_cnt;
 
reg [1:0] dpll_state, dpll_next_state;
reg fs_ce_d;
reg fs_ce;
wire change;
wire lock_en;
reg [2:0] fs_state, fs_next_state;
reg rx_valid_r;
reg sync_err_d, sync_err;
reg bit_stuff_err;
reg se0_r, byte_err;
reg se0_s;
 
///////////////////////////////////////////////////////////////////
//
// Misc Logic
//
 
assign RxActive_o = rx_active;
assign RxValid_o = rx_valid;
assign RxError_o = sync_err | bit_stuff_err | byte_err;
assign DataIn_o = hold_reg;
assign LineState = {rxdn_s1, rxdp_s1};
 
always @(posedge clk) rx_en <= RxEn_i;
always @(posedge clk) sync_err <= !rx_active & sync_err_d;
 
///////////////////////////////////////////////////////////////////
//
// Synchronize Inputs
//
 
// First synchronize to the local system clock to
// avoid metastability outside the sync block (*_s0).
// Then make sure we see the signal for at least two
// clock cycles stable to avoid glitches and noise
 
always @(posedge clk) rxd_s0 <= rxd;
always @(posedge clk) rxd_s1 <= rxd_s0;
always @(posedge clk) // Avoid detecting Line Glitches and noise
if(rxd_s0 && rxd_s1) rxd_s <= 1'b1;
else
if(!rxd_s0 && !rxd_s1) rxd_s <= 1'b0;
 
always @(posedge clk) rxdp_s0 <= rxdp;
always @(posedge clk) rxdp_s1 <= rxdp_s0;
always @(posedge clk) rxdp_s_r <= rxdp_s0 & rxdp_s1;
always @(posedge clk) rxdp_s <= (rxdp_s0 & rxdp_s1) | rxdp_s_r; // Avoid detecting Line Glitches and noise
 
always @(posedge clk) rxdn_s0 <= rxdn;
always @(posedge clk) rxdn_s1 <= rxdn_s0;
always @(posedge clk) rxdn_s_r <= rxdn_s0 & rxdn_s1;
always @(posedge clk) rxdn_s <= (rxdn_s0 & rxdn_s1) | rxdn_s_r; // Avoid detecting Line Glitches and noise
 
assign k = !rxdp_s & rxdn_s;
assign j = rxdp_s & !rxdn_s;
assign se0 = !rxdp_s & !rxdn_s;
 
always @(posedge clk) if(fs_ce) se0_s <= se0;
 
///////////////////////////////////////////////////////////////////
//
// DPLL
//
 
// This design uses a clock enable to do 12Mhz timing and not a
// real 12Mhz clock. Everything always runs at 48Mhz. We want to
// make sure however, that the clock enable is always exactly in
// the middle between two virtual 12Mhz rising edges.
// We monitor rxdp and rxdn for any changes and do the appropiate
// adjustments.
// In addition to the locking done in the dpll FSM, we adjust the
// final latch enable to compensate for various sync registers ...
 
// Allow lockinf only when we are receiving
assign lock_en = rx_en;
 
always @(posedge clk) rxd_r <= rxd_s;
 
// Edge detector
assign change = rxd_r != rxd_s;
 
// DPLL FSM
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) dpll_state <= 2'h1;
else dpll_state <= dpll_next_state;
 
always @(dpll_state or lock_en or change)
begin
fs_ce_d = 1'b0;
case(dpll_state) // synopsys full_case parallel_case
2'h0:
if(lock_en && change) dpll_next_state = 2'h0;
else dpll_next_state = 2'h1;
2'h1:begin
fs_ce_d = 1'b1;
if(lock_en && change) dpll_next_state = 2'h3;
else dpll_next_state = 2'h2;
end
2'h2:
if(lock_en && change) dpll_next_state = 2'h0;
else dpll_next_state = 2'h3;
2'h3:
if(lock_en && change) dpll_next_state = 2'h0;
else dpll_next_state = 2'h0;
endcase
end
 
// Compensate for sync registers at the input - allign full speed
// clock enable to be in the middle between two bit changes ...
reg fs_ce_r1, fs_ce_r2;
 
always @(posedge clk) fs_ce_r1 <= fs_ce_d;
always @(posedge clk) fs_ce_r2 <= fs_ce_r1;
always @(posedge clk) fs_ce <= fs_ce_r2;
 
 
///////////////////////////////////////////////////////////////////
//
// Find Sync Pattern FSM
//
 
parameter FS_IDLE = 3'h0,
K1 = 3'h1,
J1 = 3'h2,
K2 = 3'h3,
J2 = 3'h4,
K3 = 3'h5,
J3 = 3'h6,
K4 = 3'h7;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) fs_state <= FS_IDLE;
else fs_state <= fs_next_state;
 
always @(fs_state or fs_ce or k or j or rx_en or rx_active or se0 or se0_s)
begin
synced_d = 1'b0;
sync_err_d = 1'b0;
fs_next_state = fs_state;
if(fs_ce && !rx_active && !se0 && !se0_s)
case(fs_state) // synopsys full_case parallel_case
FS_IDLE:
begin
if(k && rx_en) fs_next_state = K1;
end
K1:
begin
if(j && rx_en) fs_next_state = J1;
else
begin
sync_err_d = 1'b1;
fs_next_state = FS_IDLE;
end
end
J1:
begin
if(k && rx_en) fs_next_state = K2;
else
begin
sync_err_d = 1'b1;
fs_next_state = FS_IDLE;
end
end
K2:
begin
if(j && rx_en) fs_next_state = J2;
else
begin
sync_err_d = 1'b1;
fs_next_state = FS_IDLE;
end
end
J2:
begin
if(k && rx_en) fs_next_state = K3;
else
begin
sync_err_d = 1'b1;
fs_next_state = FS_IDLE;
end
end
K3:
begin
if(j && rx_en) fs_next_state = J3;
else
if(k && rx_en)
begin
fs_next_state = FS_IDLE; // Allow missing first K-J
synced_d = 1'b1;
end
else
begin
sync_err_d = 1'b1;
fs_next_state = FS_IDLE;
end
end
J3:
begin
if(k && rx_en) fs_next_state = K4;
else
begin
sync_err_d = 1'b1;
fs_next_state = FS_IDLE;
end
end
K4:
begin
if(k) synced_d = 1'b1;
fs_next_state = FS_IDLE;
end
endcase
end
 
///////////////////////////////////////////////////////////////////
//
// Generate RxActive
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) rx_active <= 1'b0;
else
if(synced_d && rx_en) rx_active <= 1'b1;
else
if(se0 && rx_valid_r) rx_active <= 1'b0;
 
always @(posedge clk)
if(rx_valid) rx_valid_r <= 1'b1;
else
if(fs_ce) rx_valid_r <= 1'b0;
 
///////////////////////////////////////////////////////////////////
//
// NRZI Decoder
//
 
always @(posedge clk)
if(fs_ce) sd_r <= rxd_s;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) sd_nrzi <= 1'b0;
else
if(!rx_active) sd_nrzi <= 1'b1;
else
if(rx_active && fs_ce) sd_nrzi <= !(rxd_s ^ sd_r);
 
///////////////////////////////////////////////////////////////////
//
// Bit Stuff Detect
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) one_cnt <= 3'h0;
else
if(!shift_en) one_cnt <= 3'h0;
else
if(fs_ce)
begin
if(!sd_nrzi || drop_bit) one_cnt <= 3'h0;
else one_cnt <= one_cnt + 3'h1;
end
 
assign drop_bit = (one_cnt==3'h6);
 
always @(posedge clk) bit_stuff_err <= drop_bit & sd_nrzi & fs_ce & !se0 & rx_active; // Bit Stuff Error
 
///////////////////////////////////////////////////////////////////
//
// Serial => Parallel converter
//
 
always @(posedge clk)
if(fs_ce) shift_en <= synced_d | rx_active;
 
always @(posedge clk)
if(fs_ce && shift_en && !drop_bit)
hold_reg <= {sd_nrzi, hold_reg[7:1]};
 
///////////////////////////////////////////////////////////////////
//
// Generate RxValid
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) bit_cnt <= 3'b0;
else
if(!shift_en) bit_cnt <= 3'h0;
else
if(fs_ce && !drop_bit) bit_cnt <= bit_cnt + 3'h1;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) rx_valid1 <= 1'b0;
else
if(fs_ce && !drop_bit && (bit_cnt==3'h7)) rx_valid1 <= 1'b1;
else
if(rx_valid1 && fs_ce && !drop_bit) rx_valid1 <= 1'b0;
 
always @(posedge clk) rx_valid <= !drop_bit & rx_valid1 & fs_ce;
 
always @(posedge clk) se0_r <= se0;
 
always @(posedge clk) byte_err <= se0 & !se0_r & (|bit_cnt[2:1]) & rx_active;
 
endmodule
 
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/verilog/usb_tx_phy.v
0,0 → 1,465
/////////////////////////////////////////////////////////////////////
//// ////
//// USB 1.1 PHY ////
//// TX ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/usb_phy/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
//// www.asics.ws ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: usb_tx_phy.v,v 1.4 2004/10/19 09:29:07 rudi Exp $
//
// $Date: 2004/10/19 09:29:07 $
// $Revision: 1.4 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: usb_tx_phy.v,v $
// Revision 1.4 2004/10/19 09:29:07 rudi
// Fixed DPLL alignment in the rx_phy and bit stuffing errors in the tx_phy (if last bit bit was a stuff bit in a packet it was omitted).
//
// Revision 1.3 2003/10/21 05:58:41 rudi
// usb_rst is no longer or'ed with the incomming reset internally.
// Now usb_rst is simply an output, the application can decide how
// to utilize it.
//
// Revision 1.2 2003/10/19 17:40:13 rudi
// - Made core more robust against line noise
// - Added Error Checking and Reporting
// (See README.txt for more info)
//
// Revision 1.1.1.1 2002/09/16 14:27:02 rudi
// Created Directory Structure
//
//
//
//
//
//
//
 
`include "timescale.v"
 
module usb_tx_phy(
clk, rst, fs_ce, phy_mode,
// Transciever Interface
txdp, txdn, txoe,
 
// UTMI Interface
DataOut_i, TxValid_i, TxReady_o
);
 
input clk;
input rst;
input fs_ce;
input phy_mode;
output txdp, txdn, txoe;
input [7:0] DataOut_i;
input TxValid_i;
output TxReady_o;
 
///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//
 
parameter IDLE = 3'd0,
SOP = 3'h1,
DATA = 3'h2,
EOP1 = 3'h3,
EOP2 = 3'h4,
WAIT = 3'h5;
 
reg TxReady_o;
reg [2:0] state, next_state;
reg tx_ready_d;
reg ld_sop_d;
reg ld_data_d;
reg ld_eop_d;
reg tx_ip;
reg tx_ip_sync;
reg [2:0] bit_cnt;
reg [7:0] hold_reg;
reg [7:0] hold_reg_d;
 
reg sd_raw_o;
wire hold;
reg data_done;
reg sft_done;
reg sft_done_r;
wire sft_done_e;
reg ld_data;
wire eop_done;
reg [2:0] one_cnt;
wire stuff;
reg sd_bs_o;
reg sd_nrzi_o;
reg append_eop;
reg append_eop_sync1;
reg append_eop_sync2;
reg append_eop_sync3;
reg append_eop_sync4;
reg txdp, txdn;
reg txoe_r1, txoe_r2;
reg txoe;
 
///////////////////////////////////////////////////////////////////
//
// Misc Logic
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) TxReady_o <= 1'b0;
else TxReady_o <= tx_ready_d & TxValid_i;
 
always @(posedge clk) ld_data <= ld_data_d;
 
///////////////////////////////////////////////////////////////////
//
// Transmit in progress indicator
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) tx_ip <= 1'b0;
else
if(ld_sop_d) tx_ip <= 1'b1;
else
if(eop_done) tx_ip <= 1'b0;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) tx_ip_sync <= 1'b0;
else
if(fs_ce) tx_ip_sync <= tx_ip;
 
// data_done helps us to catch cases where TxValid drops due to
// packet end and then gets re-asserted as a new packet starts.
// We might not see this because we are still transmitting.
// data_done should solve those cases ...
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) data_done <= 1'b0;
else
if(TxValid_i && ! tx_ip) data_done <= 1'b1;
else
if(!TxValid_i) data_done <= 1'b0;
 
///////////////////////////////////////////////////////////////////
//
// Shift Register
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) bit_cnt <= 3'h0;
else
if(!tx_ip_sync) bit_cnt <= 3'h0;
else
if(fs_ce && !hold) bit_cnt <= bit_cnt + 3'h1;
 
assign hold = stuff;
 
always @(posedge clk)
if(!tx_ip_sync) sd_raw_o <= 1'b0;
else
case(bit_cnt) // synopsys full_case parallel_case
3'h0: sd_raw_o <= hold_reg_d[0];
3'h1: sd_raw_o <= hold_reg_d[1];
3'h2: sd_raw_o <= hold_reg_d[2];
3'h3: sd_raw_o <= hold_reg_d[3];
3'h4: sd_raw_o <= hold_reg_d[4];
3'h5: sd_raw_o <= hold_reg_d[5];
3'h6: sd_raw_o <= hold_reg_d[6];
3'h7: sd_raw_o <= hold_reg_d[7];
endcase
 
always @(posedge clk)
sft_done <= !hold & (bit_cnt == 3'h7);
 
always @(posedge clk)
sft_done_r <= sft_done;
 
assign sft_done_e = sft_done & !sft_done_r;
 
// Out Data Hold Register
always @(posedge clk)
if(ld_sop_d) hold_reg <= 8'h80;
else
if(ld_data) hold_reg <= DataOut_i;
 
always @(posedge clk) hold_reg_d <= hold_reg;
 
///////////////////////////////////////////////////////////////////
//
// Bit Stuffer
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) one_cnt <= 3'h0;
else
if(!tx_ip_sync) one_cnt <= 3'h0;
else
if(fs_ce)
begin
if(!sd_raw_o || stuff) one_cnt <= 3'h0;
else one_cnt <= one_cnt + 3'h1;
end
 
assign stuff = (one_cnt==3'h6);
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) sd_bs_o <= 1'h0;
else
if(fs_ce) sd_bs_o <= !tx_ip_sync ? 1'b0 : (stuff ? 1'b0 : sd_raw_o);
 
///////////////////////////////////////////////////////////////////
//
// NRZI Encoder
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) sd_nrzi_o <= 1'b1;
else
if(!tx_ip_sync || !txoe_r1) sd_nrzi_o <= 1'b1;
else
if(fs_ce) sd_nrzi_o <= sd_bs_o ? sd_nrzi_o : ~sd_nrzi_o;
 
///////////////////////////////////////////////////////////////////
//
// EOP append logic
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) append_eop <= 1'b0;
else
if(ld_eop_d) append_eop <= 1'b1;
else
if(append_eop_sync2) append_eop <= 1'b0;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) append_eop_sync1 <= 1'b0;
else
if(fs_ce) append_eop_sync1 <= append_eop;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) append_eop_sync2 <= 1'b0;
else
if(fs_ce) append_eop_sync2 <= append_eop_sync1;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) append_eop_sync3 <= 1'b0;
else
if(fs_ce) append_eop_sync3 <= append_eop_sync2 |
(append_eop_sync3 & !append_eop_sync4); // Make sure always 2 bit wide
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) append_eop_sync4 <= 1'b0;
else
if(fs_ce) append_eop_sync4 <= append_eop_sync3;
 
assign eop_done = append_eop_sync3;
 
///////////////////////////////////////////////////////////////////
//
// Output Enable Logic
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txoe_r1 <= 1'b0;
else
if(fs_ce) txoe_r1 <= tx_ip_sync;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txoe_r2 <= 1'b0;
else
if(fs_ce) txoe_r2 <= txoe_r1;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txoe <= 1'b1;
else
if(fs_ce) txoe <= !(txoe_r1 | txoe_r2);
 
///////////////////////////////////////////////////////////////////
//
// Output Registers
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txdp <= 1'b1;
else
if(fs_ce) txdp <= phy_mode ?
(!append_eop_sync3 & sd_nrzi_o) :
sd_nrzi_o;
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) txdn <= 1'b0;
else
if(fs_ce) txdn <= phy_mode ?
(!append_eop_sync3 & ~sd_nrzi_o) :
append_eop_sync3;
 
///////////////////////////////////////////////////////////////////
//
// Tx Statemashine
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) state <= IDLE;
else state <= next_state;
 
always @(state or TxValid_i or data_done or sft_done_e or eop_done or fs_ce)
begin
next_state = state;
tx_ready_d = 1'b0;
 
ld_sop_d = 1'b0;
ld_data_d = 1'b0;
ld_eop_d = 1'b0;
 
case(state) // synopsys full_case parallel_case
IDLE:
if(TxValid_i)
begin
ld_sop_d = 1'b1;
next_state = SOP;
end
SOP:
if(sft_done_e)
begin
tx_ready_d = 1'b1;
ld_data_d = 1'b1;
next_state = DATA;
end
DATA:
begin
if(!data_done && sft_done_e)
begin
ld_eop_d = 1'b1;
next_state = EOP1;
end
if(data_done && sft_done_e)
begin
tx_ready_d = 1'b1;
ld_data_d = 1'b1;
end
end
EOP1:
if(eop_done) next_state = EOP2;
EOP2:
if(!eop_done && fs_ce) next_state = WAIT;
WAIT:
if(fs_ce) next_state = IDLE;
endcase
end
 
endmodule
 
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/hdl/verilog/usb_phy.v
0,0 → 1,184
/////////////////////////////////////////////////////////////////////
//// ////
//// USB 1.1 PHY ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/usb_phy/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
//// www.asics.ws ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: usb_phy.v,v 1.4 2003/10/21 05:58:40 rudi Exp $
//
// $Date: 2003/10/21 05:58:40 $
// $Revision: 1.4 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: usb_phy.v,v $
// Revision 1.4 2003/10/21 05:58:40 rudi
// usb_rst is no longer or'ed with the incomming reset internally.
// Now usb_rst is simply an output, the application can decide how
// to utilize it.
//
// Revision 1.3 2003/10/19 17:40:13 rudi
// - Made core more robust against line noise
// - Added Error Checking and Reporting
// (See README.txt for more info)
//
// Revision 1.2 2002/09/16 16:06:37 rudi
// Changed top level name to be consistent ...
//
// Revision 1.1.1.1 2002/09/16 14:26:59 rudi
// Created Directory Structure
//
//
//
//
//
//
//
//
 
`include "timescale.v"
 
module usb_phy(clk, rst, phy_tx_mode, usb_rst,
// Transciever Interface
txdp, txdn, txoe,
rxd, rxdp, rxdn,
 
// UTMI Interface
DataOut_i, TxValid_i, TxReady_o, RxValid_o,
RxActive_o, RxError_o, DataIn_o, LineState_o
);
 
input clk;
input rst;
input phy_tx_mode;
output usb_rst;
output txdp, txdn, txoe;
input rxd, rxdp, rxdn;
input [7:0] DataOut_i;
input TxValid_i;
output TxReady_o;
output [7:0] DataIn_o;
output RxValid_o;
output RxActive_o;
output RxError_o;
output [1:0] LineState_o;
 
///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//
 
reg [4:0] rst_cnt;
reg usb_rst;
wire fs_ce;
wire rst;
 
///////////////////////////////////////////////////////////////////
//
// Misc Logic
//
 
///////////////////////////////////////////////////////////////////
//
// TX Phy
//
 
usb_tx_phy i_tx_phy(
.clk( clk ),
.rst( rst ),
.fs_ce( fs_ce ),
.phy_mode( phy_tx_mode ),
 
// Transciever Interface
.txdp( txdp ),
.txdn( txdn ),
.txoe( txoe ),
 
// UTMI Interface
.DataOut_i( DataOut_i ),
.TxValid_i( TxValid_i ),
.TxReady_o( TxReady_o )
);
 
///////////////////////////////////////////////////////////////////
//
// RX Phy and DPLL
//
 
usb_rx_phy i_rx_phy(
.clk( clk ),
.rst( rst ),
.fs_ce( fs_ce ),
 
// Transciever Interface
.rxd( rxd ),
.rxdp( rxdp ),
.rxdn( rxdn ),
 
// UTMI Interface
.DataIn_o( DataIn_o ),
.RxValid_o( RxValid_o ),
.RxActive_o( RxActive_o ),
.RxError_o( RxError_o ),
.RxEn_i( txoe ),
.LineState( LineState_o )
);
 
///////////////////////////////////////////////////////////////////
//
// Generate an USB Reset is we see SE0 for at least 2.5uS
//
 
`ifdef USB_ASYNC_REST
always @(posedge clk or negedge rst)
`else
always @(posedge clk)
`endif
if(!rst) rst_cnt <= 5'h0;
else
if(LineState_o != 2'h0) rst_cnt <= 5'h0;
else
if(!usb_rst && fs_ce) rst_cnt <= rst_cnt + 5'h1;
 
always @(posedge clk)
usb_rst <= (rst_cnt == 5'h1f);
 
endmodule
 
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/data/opb_usblite_v2_1_0.pao
0,0 → 1,43
#--
#-- opb_usblite - opb_uartlite replacement
#--
#-- opb_usblite is using components from Rudolf Usselmann see
#-- http://www.opencores.org/cores/usb_phy/
#-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
#--
#-- Copyright (C) 2010 Ake Rehnman
#--
#-- This program is free software: you can redistribute it and/or modify
#-- it under the terms of the GNU Lesser General Public License as published by
#-- the Free Software Foundation, either version 3 of the License, or
#-- (at your option) any later version.
#--
#-- This program is distributed in the hope that it will be useful,
#-- but WITHOUT ANY WARRANTY; without even the implied warranty of
#-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#-- GNU Lesser General Public License for more details.
#--
#-- You should have received a copy of the GNU Lesser General Public License
#-- along with this program. If not, see <http://www.gnu.org/licenses/>.
#--
 
lib opb_usblite_v1_00_a timescale.v verilog
lib opb_usblite_v1_00_a usb_tx_phy.v verilog
lib opb_usblite_v1_00_a usb_rx_phy.v verilog
lib opb_usblite_v1_00_a usb_phy.v verilog
lib opb_usblite_v1_00_a opb_usblite vhdl
lib opb_usblite_v1_00_a opb_usblite_core vhdl
lib opb_usblite_v1_00_a usb_control.vhdl vhdl
lib opb_usblite_v1_00_a usb_init.vhdl vhdl
lib opb_usblite_v1_00_a usb_packet.vhdl vhdl
lib opb_usblite_v1_00_a usb_pkg.vhdl vhdl
lib opb_usblite_v1_00_a usb_serial.vhdl vhdl
lib opb_usblite_v1_00_a usb_transact.vhdl vhdl
lib common_v1_00_a family vhdl
lib common_v1_00_a common_types_pkg vhdl
lib common_v1_00_a pselect vhdl
lib common_v1_00_a mux_encode_sel vhdl
lib common_v1_00_a mux_onehot vhdl
lib common_v1_00_a or_bits vhdl
lib common_v1_00_a or_muxcy vhdl
lib common_v1_00_a or_gate vhdl
/opb_usblite/tags/R1/pcores/opb_usblite_v1_00_a/data/opb_usblite_v2_1_0.mpd
0,0 → 1,75
#--
#-- opb_usblite - opb_uartlite replacement
#--
#-- opb_usblite is using components from Rudolf Usselmann see
#-- http://www.opencores.org/cores/usb_phy/
#-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
#--
#-- Copyright (C) 2010 Ake Rehnman
#--
#-- This program is free software: you can redistribute it and/or modify
#-- it under the terms of the GNU Lesser General Public License as published by
#-- the Free Software Foundation, either version 3 of the License, or
#-- (at your option) any later version.
#--
#-- This program is distributed in the hope that it will be useful,
#-- but WITHOUT ANY WARRANTY; without even the implied warranty of
#-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#-- GNU Lesser General Public License for more details.
#--
#-- You should have received a copy of the GNU Lesser General Public License
#-- along with this program. If not, see <http://www.gnu.org/licenses/>.
#--
 
 
BEGIN opb_usblite
 
## Peripheral Options
OPTION IPTYPE = PERIPHERAL
OPTION IMP_NETLIST = TRUE
OPTION HDL = VHDL
OPTION IP_GROUP = MICROBLAZE:PPC:USER
 
 
## Bus Interfaces
BUS_INTERFACE BUS = SOPB, BUS_STD = OPB, BUS_TYPE = SLAVE
 
## Generics for VHDL or Parameters for Verilog
PARAMETER C_OPB_AWIDTH = 32, DT = INTEGER, BUS = SOPB
PARAMETER C_OPB_DWIDTH = 32, DT = INTEGER, BUS = SOPB
PARAMETER C_BASEADDR = 0xffff0000, DT = std_logic_vector(0 to 31), PAIR = C_HIGHADDR, ADDRESS = BASE, BUS = SOPB
PARAMETER C_HIGHADDR = 0xffff00ff, DT = std_logic_vector, PAIR = C_BASEADDR, ADDRESS = HIGH, BUS = SOPB
PARAMETER C_SYSRST = 1, DT = std_logic
PARAMETER C_PHYMODE = 1, DT = std_logic
PARAMETER C_VENDORID = 0x1234, DT = std_logic_vector(15 downto 0)
PARAMETER C_PRODUCTID = 0x5678, DT = std_logic_vector(15 downto 0)
PARAMETER C_VERSIONBCD = 0x0200, DT = std_logic_vector(15 downto 0)
PARAMETER C_SELFPOWERED = false, DT = BOOLEAN
PARAMETER C_RXBUFSIZE_BITS = 10, DT = INTEGER
PARAMETER C_TXBUFSIZE_BITS = 10, DT = INTEGER
 
## Ports
PORT OPB_Clk = "", DIR = I, SIGIS = CLK, BUS = SOPB
PORT OPB_Rst = OPB_Rst, DIR = I, SIGIS = RST, BUS = SOPB
PORT SYS_Rst = "", DIR = I, SIGIS = RST
PORT USB_Clk = "", DIR = I, SIGIS = CLK
PORT OPB_ABus = OPB_ABus, DIR = I, VEC = [0:31], BUS = SOPB
PORT OPB_BE = OPB_BE, DIR = I, VEC = [0:3], BUS = SOPB
PORT OPB_RNW = OPB_RNW, DIR = I, BUS = SOPB
PORT OPB_select = OPB_select, DIR = I, BUS = SOPB
PORT OPB_seqAddr = OPB_seqAddr, DIR = I, BUS = SOPB
PORT OPB_DBus = OPB_DBus, DIR = I, VEC = [0:31], BUS = SOPB
PORT Sl_DBus = Sl_DBus, DIR = O, VEC = [0:31], BUS = SOPB
PORT Sl_errAck = Sl_errAck, DIR = O, BUS = SOPB
PORT Sl_retry = Sl_retry, DIR = O, BUS = SOPB
PORT Sl_toutSup = Sl_toutSup, DIR = O, BUS = SOPB
PORT Sl_xferAck = Sl_xferAck, DIR = O, BUS = SOPB
PORT Interrupt = "", DIR = O, LEVEL = HIGH, SIGIS = INTERRUPT, INTERRUPT_PRIORITY = LOW
PORT txdp = "", DIR = O
PORT txdn = "", DIR = O
PORT txoe = "", DIR = O
PORT rxd = "", DIR = I
PORT rxdp = "", DIR = I
PORT rxdn = "", DIR = I
 
END
/opb_usblite/tags/R1/drivers/opb_usblite_v1_00_a/src/usblite_l.c
0,0 → 1,43
/*
--
-- opb_usblite - opb_uartlite replacement
--
-- opb_usblite is using components from Rudolf Usselmann see
-- http://www.opencores.org/cores/usb_phy/
-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
--
-- Copyright (C) 2010 Ake Rehnman
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
*/
#include "usblite_l.h"
 
/******************************************************************************/
void usblite_SendByte(unsigned int base, unsigned char data)
{
while (usblite_mIsTransmitFull(base));
 
usblite_out32(base + XUL_TX_FIFO_OFFSET, data);
}
 
 
/****************************************************************************/
unsigned char usblite_RecvByte(unsigned int base)
{
while (usblite_mIsReceiveEmpty(base));
 
return (unsigned char)usblite_in32(base + XUL_RX_FIFO_OFFSET);
}
 
/opb_usblite/tags/R1/drivers/opb_usblite_v1_00_a/src/usblite_l.h
0,0 → 1,95
/*
--
-- opb_usblite - opb_uartlite replacement
--
-- opb_usblite is using components from Rudolf Usselmann see
-- http://www.opencores.org/cores/usb_phy/
-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
--
-- Copyright (C) 2010 Ake Rehnman
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
*/
 
#ifndef USBLITE_L_H /* prevent circular inclusions */
#define USBLITE_L_H /* by using protection macros */
 
#ifdef __cplusplus
extern "C" {
#endif
 
/* register offsets */
 
#define XUL_RX_FIFO_OFFSET 0 /* receive FIFO, read only */
#define XUL_TX_FIFO_OFFSET 4 /* transmit FIFO, write only */
#define XUL_STATUS_REG_OFFSET 8 /* status register, read only */
#define XUL_CONTROL_REG_OFFSET 12 /* control register, write only */
 
/* control register bit positions */
 
#define XUL_CR_ENABLE_INTR 0x10 /* enable interrupt */
#define XUL_CR_FIFO_RX_RESET 0x02 /* reset receive FIFO */
#define XUL_CR_FIFO_TX_RESET 0x01 /* reset transmit FIFO */
 
/* status register bit positions */
 
#define XUL_SR_INTR_ENABLED 0x10 /* interrupt enabled */
#define XUL_SR_TX_FIFO_FULL 0x08 /* transmit FIFO full */
#define XUL_SR_TX_FIFO_EMPTY 0x04 /* transmit FIFO empty */
#define XUL_SR_RX_FIFO_FULL 0x02 /* receive FIFO full */
#define XUL_SR_RX_FIFO_VALID_DATA 0x01 /* data in receive FIFO */
 
/*****************************************************************************/
#define usblite_out32(addr, data) *(unsigned int*)(addr)=(unsigned int)(data)
 
#define usblite_in32(addr) *(unsigned int*)(addr)
 
#define usblite_mSetControlReg(BaseAddress, Mask) \
usblite_out32((BaseAddress) + XUL_CONTROL_REG_OFFSET, (Mask))
 
#define usblite_mGetStatusReg(BaseAddress) \
usblite_in32((BaseAddress) + XUL_STATUS_REG_OFFSET)
 
#define usblite_mIsReceiveEmpty(BaseAddress) \
((usblite_mGetStatusReg((BaseAddress)) & XUL_SR_RX_FIFO_VALID_DATA) != \
XUL_SR_RX_FIFO_VALID_DATA)
 
#define usblite_mIsTransmitFull(BaseAddress) \
((usblite_mGetStatusReg((BaseAddress)) & XUL_SR_TX_FIFO_FULL) == \
XUL_SR_TX_FIFO_FULL)
 
#define usblite_mIsIntrEnabled(BaseAddress) \
((usblite_mGetStatusReg((BaseAddress)) & XUL_SR_INTR_ENABLED) == \
XUL_SR_INTR_ENABLED)
 
#define usblite_mEnableIntr(BaseAddress) \
usblite_mSetControlReg((BaseAddress), XUL_CR_ENABLE_INTR)
 
#define usblite_mDisableIntr(BaseAddress) \
usblite_mSetControlReg((BaseAddress), 0)
 
 
/************************** Function Prototypes *****************************/
 
void usblite_SendByte(unsigned int base, unsigned char Data);
 
unsigned char usblite_RecvByte(unsigned int base);
 
#ifdef __cplusplus
}
#endif
 
#endif /* end of protection macro */
 
/opb_usblite/tags/R1/drivers/opb_usblite_v1_00_a/src/Makefile
0,0 → 1,52
#--
#-- opb_usblite - opb_uartlite replacement
#--
#-- opb_usblite is using components from Rudolf Usselmann see
#-- http://www.opencores.org/cores/usb_phy/
#-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
#--
#-- Copyright (C) 2010 Ake Rehnman
#--
#-- This program is free software: you can redistribute it and/or modify
#-- it under the terms of the GNU Lesser General Public License as published by
#-- the Free Software Foundation, either version 3 of the License, or
#-- (at your option) any later version.
#--
#-- This program is distributed in the hope that it will be useful,
#-- but WITHOUT ANY WARRANTY; without even the implied warranty of
#-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#-- GNU Lesser General Public License for more details.
#--
#-- You should have received a copy of the GNU Lesser General Public License
#-- along with this program. If not, see <http://www.gnu.org/licenses/>.
#--
 
 
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
 
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
 
INCLUDEFILES=usblite_l.h
LIBSOURCES=*.c
OUTS = *.o
 
 
libs:
echo "Compiling usblite"
$(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES)
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OUTS}
make clean
 
include:
${CP} ${INCLUDEFILES} ${INCLUDEDIR}
 
clean:
rm -rf ${OUTS}
 
/opb_usblite/tags/R1/drivers/opb_usblite_v1_00_a/data/opb_usblite_v2_1_0.mdd
0,0 → 1,71
#--
#-- opb_usblite - opb_uartlite replacement
#--
#-- opb_usblite is using components from Rudolf Usselmann see
#-- http://www.opencores.org/cores/usb_phy/
#-- and Joris van Rantwijk see http://www.xs4all.nl/~rjoris/fpga/usb.html
#--
#-- Copyright (C) 2010 Ake Rehnman
#--
#-- This program is free software: you can redistribute it and/or modify
#-- it under the terms of the GNU Lesser General Public License as published by
#-- the Free Software Foundation, either version 3 of the License, or
#-- (at your option) any later version.
#--
#-- This program is distributed in the hope that it will be useful,
#-- but WITHOUT ANY WARRANTY; without even the implied warranty of
#-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#-- GNU Lesser General Public License for more details.
#--
#-- You should have received a copy of the GNU Lesser General Public License
#-- along with this program. If not, see <http://www.gnu.org/licenses/>.
#--
 
OPTION psf_version = 2.1;
 
BEGIN driver opb_usblite
 
OPTION supported_peripherals = (opb_usblite);
OPTION driver_state = ACTIVE;
OPTION depends = (common_v1_00_a);
OPTION copyfiles = all;
 
BEGIN INTERFACE stdin
PROPERTY header = usblite_l.h;
FUNCTION name = inbyte, value = usblite_RecvByte;
END INTERFACE
 
BEGIN INTERFACE stdout
PROPERTY header = usblite_l.h;
FUNCTION name = outbyte, value = usblite_SendByte;
END INTERFACE
 
BEGIN INTERFACE stdio
PROPERTY header = usblite_l.h;
FUNCTION name = inbyte, value = usblite_RecvByte;
FUNCTION name = outbyte, value = usblite_SendByte;
END INTERFACE
 
BEGIN INTERFACE vxworks5_4
END INTERFACE
 
BEGIN INTERFACE vxworks5_5
END INTERFACE
 
BEGIN INTERFACE vxworks6_1
END INTERFACE
 
BEGIN INTERFACE vxworks6_3
END INTERFACE
 
BEGIN INTERFACE linux
END INTERFACE
 
BEGIN ARRAY interrupt_handler
PROPERTY desc = "Interrupt Handler Information";
PROPERTY size = 1, permit = none;
PARAM name = int_handler, default = XNullHandler, desc = "Name of Interrupt Handler", type = string;
PARAM name = int_port, default = Interrupt, desc = "Interrupt pin associated with the interrupt handler", permit = none;
END ARRAY
 
END driver
/opb_usblite/tags/R1/schematic/usbif.opj
0,0 → 1,78
(ExpressProject "usbif"
(ProjectVersion "19981106")
(ProjectType "PCB")
(Folder "Design Resources"
(Folder "Library")
(NoModify)
(File ".\usbif.dsn"
(Type "Schematic Design"))
(BuildFileAddedOrDeleted "x")
(CompileFileAddedOrDeleted "x")
(ANNOTATE_Scope "0")
(ANNOTATE_Mode "1")
(ANNOTATE_Action "0")
(Annotate_Page_Order "0")
(ANNOTATE_Reset_References_to_1 "FALSE")
(ANNOTATE_No_Page_Number_Change "FALSE")
(ANNOTATE_Property_Combine "{Value}{Source Package}{POWER_GROUP}")
(ANNOTATE_IncludeNonPrimitive "FALSE")
(ANNOTATE_Refdes_Control_Required "FALSE")
(Annotate_type "Default")
(width_pages "100")
(width_start "80")
(width_End "80"))
(Folder "Outputs")
(Folder "Referenced Projects")
(PartMRUSelector
(PAX_TITLEBLOCKX
(LibraryName "X:\CIS\LIBRARIES\PAX_TITLEBLOCK.OLB")
(DeviceIndex "0"))
(Resistor
(FullPartName "Resistor.Normal")
(LibraryName "X:\CIS\LIBRARIES\PE_PASSIVE.OLB")
(DeviceIndex "0"))
(Zener
(FullPartName "Zener.Normal")
(LibraryName "X:\CIS\LIBRARIES\PE_DISCRETE.OLB")
(DeviceIndex "0"))
(Capacitor
(FullPartName "Capacitor.Normal")
(LibraryName "X:\CIS\LIBRARIES\PE_PASSIVE.OLB")
(DeviceIndex "0"))
(VCC_ARROW
(LibraryName "C:\ORCAD\ORCAD_16.2\TOOLS\CAPTURE\LIBRARY\CAPSYM.OLB")
(DeviceIndex "0"))
(GND_SIGNAL
(LibraryName "C:\ORCAD\ORCAD_16.2\TOOLS\CAPTURE\LIBRARY\CAPSYM.OLB")
(DeviceIndex "0"))
("Connector 4+2GND"
(FullPartName "Connector 4+2GND.Normal")
(LibraryName "X:\CIS\LIBRARIES\PE_CONNECTOR.OLB")
(DeviceIndex "0"))
(USB1T11
(FullPartName "USB1T11.Normal")
(LibraryName "X:\CIS\LIBRARIES\AKRELIB.OLB")
(DeviceIndex "0")))
(LastUsedLibraryBrowseDirectory "X:\CIS\Libraries")
(GlobalState
(FileView
(Path "Design Resources")
(Path "Design Resources" ".\usbif.dsn")
(Path "Design Resources" ".\usbif.dsn" "Design Cache")
(Select "Design Resources" ".\usbif.dsn"))
(HierarchyView)
(Doc
(Type "COrCapturePMDoc")
(Frame
(Placement "44 0 1 -1 -1 -4 -23 0 200 0 253"))
(Tab 0))
(Doc
(Type "COrSchematicDoc")
(Frame
(Placement "44 2 3 -1 -1 -4 -23 22 1051 22 302")
(Scroll "-192 -7")
(Zoom "65")
(Occurrence "/"))
(Path "C:\AKRE\USBTEST\USBIF.DSN")
(Schematic "SCHEMATIC1")
(Page "PAGE1"))))
/opb_usblite/tags/R1/schematic/usbif.pdf
0,0 → 1,83
%PDF-1.3
 
1 0 obj
<</Type/Pages/Count 1/Kids[4 0 R]>>
endobj
2 0 obj
<</Type/Catalog/Pages 1 0 R>>
endobj
3 0 obj
<</Title (usbif.opj)/Creator (Win2PDF 3.30 http://www.win2pdf.com)/Author (arehnman)/CreationDate (D:20100606141639-22'00')/Producer (PDFlib 3.03 \(Win32\))>>
endobj
4 0 obj
<</Type/Page/Parent 1 0 R/Resources 9 0 R/MediaBox[0 0 841.88 595.27]/Contents[5 0 R]>>
endobj
5 0 obj
<</Length 4569/Filter/FlateDecode>>
stream
 
 
+\FSQI==%eCmy="W)cQz +Vh7P\ؑ\t J>,,1h&Ц +%,B -<"`\\ +pmJ2%""`^UxSm[K&:<ٚ읣r7ɞ|_ZQž'@\4bvϸlL]DaLP[р`4/_62(=At Dr +5cU} +2\̔g3SHbF?c.vX>V=?mS $tXf ",k3f6s'4IˋIc\ʬʖ!jW{ +HVD#Zb"‰UM(0d!I+ +S@R8\p1(׃iXJb0f4}[W&^y'cLߎ広St1ℓK +qUG7q:( ‰ +g]Դ׍!W) #_0ԉht7*[i;B +tR +zR=}=pOprB:cNq'~֡̓~l''NW 8:ϯהRsJ,[@\\̗j,zYԘDQ8KB\,>/.Sz'ж/A6*\\$!{bdl>]]ݜ-P.JH֕2Nf]c=Y%%秿GVJ$‚۶OcMksSSϞg7G&hSQxmGW'ϧUs|~qq=^8X\,ϧ qU`|]Â>zr +Ta:t{'+ZNig +, ch 6&tk9H[Hb*qS`bqF3>:8Sz:hj +tktozDbnfۓx)[t +Z&?W29zM#vpʔv0+@Á|4]i!a&{lW?<;zj%)t)Z9Mh˫{$3c S +ڼ'Dgvo FsxU~BJVq3#?ѓHU; iըFg>9|A +}\u3Fm9li3t%+ƭh,f]+71HzlQϋ׵1t: n1{UC3`6=k:i]h"-1,U6MN8 +D J'L:|D*m񪀷Mbr-C,eѐR+>> +endobj +8 0 obj +<> +endobj +9 0 obj +<>>> +endobj +xref +0 10 +0000000000 65535 f +0000000015 00000 n +0000000066 00000 n +0000000111 00000 n +0000000285 00000 n +0000000388 00000 n +0000000000 65535 f +0000005025 00000 n +0000005113 00000 n +0000005206 00000 n +trailer +<> +startxref +5272 +%%EOF
/opb_usblite/tags/R1/schematic/USBIF.DSN Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
opb_usblite/tags/R1/schematic/USBIF.DSN Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: opb_usblite/tags/R1/refdesign/system.mss =================================================================== --- opb_usblite/tags/R1/refdesign/system.mss (nonexistent) +++ opb_usblite/tags/R1/refdesign/system.mss (revision 7) @@ -0,0 +1,101 @@ + + PARAMETER VERSION = 2.2.0 + + +BEGIN OS + PARAMETER OS_NAME = standalone + PARAMETER OS_VER = 2.00.a + PARAMETER PROC_INSTANCE = microblaze_0 + PARAMETER STDIN = opb_usblite_0 + PARAMETER STDOUT = opb_usblite_0 +END + + +BEGIN PROCESSOR + PARAMETER DRIVER_NAME = cpu + PARAMETER DRIVER_VER = 1.12.b + PARAMETER HW_INSTANCE = microblaze_0 + PARAMETER COMPILER = mb-gcc + PARAMETER ARCHIVER = mb-ar +END + + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 1.00.a + PARAMETER HW_INSTANCE = dlmb_cntlr +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = bram + PARAMETER DRIVER_VER = 1.00.a + PARAMETER HW_INSTANCE = ilmb_cntlr +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 1.00.a + PARAMETER HW_INSTANCE = lmb_bram +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = gpio + PARAMETER DRIVER_VER = 2.13.a + PARAMETER HW_INSTANCE = LEDs_8Bit +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = gpio + PARAMETER DRIVER_VER = 2.13.a + PARAMETER HW_INSTANCE = DIP_Switches_4Bit +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = gpio + PARAMETER DRIVER_VER = 2.13.a + PARAMETER HW_INSTANCE = Buttons_4Bit +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = mpmc + PARAMETER DRIVER_VER = 3.01.a + PARAMETER HW_INSTANCE = DDR_SDRAM +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 1.00.a + PARAMETER HW_INSTANCE = clock_generator_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = uartlite + PARAMETER DRIVER_VER = 1.14.a + PARAMETER HW_INSTANCE = mdm_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 1.00.a + PARAMETER HW_INSTANCE = proc_sys_reset_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = opb_usblite + PARAMETER DRIVER_VER = 1.00.a + PARAMETER HW_INSTANCE = opb_usblite_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = opbarb + PARAMETER DRIVER_VER = 1.02.a + PARAMETER HW_INSTANCE = opb_v20_0 +END + +BEGIN DRIVER + PARAMETER DRIVER_NAME = generic + PARAMETER DRIVER_VER = 1.00.a + PARAMETER HW_INSTANCE = plbv46_opb_bridge_0 +END + + Index: opb_usblite/tags/R1/refdesign/system.xmp =================================================================== --- opb_usblite/tags/R1/refdesign/system.xmp (nonexistent) +++ opb_usblite/tags/R1/refdesign/system.xmp (revision 7) @@ -0,0 +1,29 @@ +#Please do not modify this file by hand +XmpVersion: 11.4 +VerMgmt: 11.4 +IntStyle: default +MHS File: system.mhs +MSS File: system.mss +Architecture: spartan3e +Device: xc3s500e +Package: fg320 +SpeedGrade: -4 +UserCmd1: +UserCmd1Type: 0 +UserCmd2: +UserCmd2Type: 0 +GenSimTB: 0 +SdkExportBmmBit: 1 +SdkExportDir: SDK/SDK_Export +InsertNoPads: 0 +WarnForEAArch: 1 +HdlLang: VHDL +SimModel: BEHAVIORAL +UcfFile: data/system.ucf +EnableParTimingError: 1 +ShowLicenseDialog: 1 +ICacheAddr: DDR_SDRAM, +DCacheAddr: DDR_SDRAM, +Processor: microblaze_0 +BootLoop: 1 +XmdStub: 0 Index: opb_usblite/tags/R1/refdesign/system.mhs =================================================================== --- opb_usblite/tags/R1/refdesign/system.mhs (nonexistent) +++ opb_usblite/tags/R1/refdesign/system.mhs (revision 7) @@ -0,0 +1,275 @@ + +# ############################################################################## +# Created by Base System Builder Wizard for Xilinx EDK 11.4 Build EDK_LS4.68 +# Wed Jun 02 12:30:45 2010 +# Target Board: Xilinx Spartan-3E Starter Board Rev D +# Family: spartan3e +# Device: XC3S500e +# Package: FG320 +# Speed Grade: -4 +# Processor number: 1 +# Processor 1: microblaze_0 +# System clock frequency: 50.0 +# Debug Interface: On-Chip HW Debug Module +# ############################################################################## + PARAMETER VERSION = 2.1.0 + + + PORT fpga_0_LEDs_8Bit_GPIO_IO_O_pin = fpga_0_LEDs_8Bit_GPIO_IO_O_pin, DIR = O, VEC = [0:7] + PORT fpga_0_DIP_Switches_4Bit_GPIO_IO_I_pin = fpga_0_DIP_Switches_4Bit_GPIO_IO_I_pin, DIR = I, VEC = [0:3] + PORT fpga_0_Buttons_4Bit_GPIO_IO_I_pin = fpga_0_Buttons_4Bit_GPIO_IO_I_pin, DIR = I, VEC = [0:3] + PORT fpga_0_DDR_SDRAM_DDR_Clk_pin = fpga_0_DDR_SDRAM_DDR_Clk_pin, DIR = O + PORT fpga_0_DDR_SDRAM_DDR_Clk_n_pin = fpga_0_DDR_SDRAM_DDR_Clk_n_pin, DIR = O + PORT fpga_0_DDR_SDRAM_DDR_CE_pin = fpga_0_DDR_SDRAM_DDR_CE_pin, DIR = O + PORT fpga_0_DDR_SDRAM_DDR_CS_n_pin = fpga_0_DDR_SDRAM_DDR_CS_n_pin, DIR = O + PORT fpga_0_DDR_SDRAM_DDR_RAS_n_pin = fpga_0_DDR_SDRAM_DDR_RAS_n_pin, DIR = O + PORT fpga_0_DDR_SDRAM_DDR_CAS_n_pin = fpga_0_DDR_SDRAM_DDR_CAS_n_pin, DIR = O + PORT fpga_0_DDR_SDRAM_DDR_WE_n_pin = fpga_0_DDR_SDRAM_DDR_WE_n_pin, DIR = O + PORT fpga_0_DDR_SDRAM_DDR_BankAddr_pin = fpga_0_DDR_SDRAM_DDR_BankAddr_pin, DIR = O, VEC = [1:0] + PORT fpga_0_DDR_SDRAM_DDR_Addr_pin = fpga_0_DDR_SDRAM_DDR_Addr_pin, DIR = O, VEC = [12:0] + PORT fpga_0_DDR_SDRAM_DDR_DQ_pin = fpga_0_DDR_SDRAM_DDR_DQ_pin, DIR = IO, VEC = [15:0] + PORT fpga_0_DDR_SDRAM_DDR_DM_pin = fpga_0_DDR_SDRAM_DDR_DM_pin, DIR = O, VEC = [1:0] + PORT fpga_0_DDR_SDRAM_DDR_DQS_pin = fpga_0_DDR_SDRAM_DDR_DQS_pin, DIR = IO, VEC = [1:0] + PORT fpga_0_DDR_SDRAM_ddr_dqs_div_io_pin = fpga_0_DDR_SDRAM_ddr_dqs_div_io_pin, DIR = IO + PORT fpga_0_clk_1_sys_clk_pin = dcm_clk_s, DIR = I, SIGIS = CLK, CLK_FREQ = 50000000 + PORT fpga_0_rst_1_sys_rst_pin = sys_rst_s, DIR = I, SIGIS = RST, RST_POLARITY = 1 + PORT opb_usblite_0_txdp_pin = opb_usblite_0_txdp, DIR = O + PORT opb_usblite_0_txdn_pin = opb_usblite_0_txdn, DIR = O + PORT opb_usblite_0_txdoe_pin = opb_usblite_0_txoe, DIR = O + PORT opb_usblite_0_rxd_pin = opb_usblite_0_rxd, DIR = I + PORT opb_usblite_0_rxdp_pin = opb_usblite_0_rxdp, DIR = I + PORT opb_usblite_0_rxdn_pin = opb_usblite_0_rxdn, DIR = I + + +BEGIN microblaze + PARAMETER INSTANCE = microblaze_0 + PARAMETER C_AREA_OPTIMIZED = 1 + PARAMETER C_INTERCONNECT = 1 + PARAMETER C_DEBUG_ENABLED = 1 + PARAMETER C_ICACHE_BASEADDR = 0x44000000 + PARAMETER C_ICACHE_HIGHADDR = 0x47ffffff + PARAMETER C_CACHE_BYTE_SIZE = 8192 + PARAMETER C_ICACHE_ALWAYS_USED = 1 + PARAMETER C_DCACHE_BASEADDR = 0x44000000 + PARAMETER C_DCACHE_HIGHADDR = 0x47ffffff + PARAMETER C_DCACHE_BYTE_SIZE = 8192 + PARAMETER C_DCACHE_ALWAYS_USED = 1 + PARAMETER HW_VER = 7.20.d + PARAMETER C_USE_ICACHE = 1 + PARAMETER C_USE_DCACHE = 1 + BUS_INTERFACE DPLB = mb_plb + BUS_INTERFACE IPLB = mb_plb + BUS_INTERFACE DXCL = microblaze_0_DXCL + BUS_INTERFACE IXCL = microblaze_0_IXCL + BUS_INTERFACE DEBUG = microblaze_0_mdm_bus + BUS_INTERFACE DLMB = dlmb + BUS_INTERFACE ILMB = ilmb + PORT MB_RESET = mb_reset +END + +BEGIN plb_v46 + PARAMETER INSTANCE = mb_plb + PARAMETER HW_VER = 1.04.a + PORT PLB_Clk = clk_50_0000MHz + PORT SYS_Rst = sys_bus_reset +END + +BEGIN lmb_v10 + PARAMETER INSTANCE = ilmb + PARAMETER HW_VER = 1.00.a + PORT LMB_Clk = clk_50_0000MHz + PORT SYS_Rst = sys_bus_reset +END + +BEGIN lmb_v10 + PARAMETER INSTANCE = dlmb + PARAMETER HW_VER = 1.00.a + PORT LMB_Clk = clk_50_0000MHz + PORT SYS_Rst = sys_bus_reset +END + +BEGIN lmb_bram_if_cntlr + PARAMETER INSTANCE = dlmb_cntlr + PARAMETER HW_VER = 2.10.b + PARAMETER C_BASEADDR = 0x00000000 + PARAMETER C_HIGHADDR = 0x00001fff + BUS_INTERFACE SLMB = dlmb + BUS_INTERFACE BRAM_PORT = dlmb_port +END + +BEGIN lmb_bram_if_cntlr + PARAMETER INSTANCE = ilmb_cntlr + PARAMETER HW_VER = 2.10.b + PARAMETER C_BASEADDR = 0x00000000 + PARAMETER C_HIGHADDR = 0x00001fff + BUS_INTERFACE SLMB = ilmb + BUS_INTERFACE BRAM_PORT = ilmb_port +END + +BEGIN bram_block + PARAMETER INSTANCE = lmb_bram + PARAMETER HW_VER = 1.00.a + BUS_INTERFACE PORTA = ilmb_port + BUS_INTERFACE PORTB = dlmb_port +END + +BEGIN xps_gpio + PARAMETER INSTANCE = LEDs_8Bit + PARAMETER C_ALL_INPUTS = 0 + PARAMETER C_GPIO_WIDTH = 8 + PARAMETER C_INTERRUPT_PRESENT = 0 + PARAMETER C_IS_DUAL = 0 + PARAMETER HW_VER = 2.00.a + PARAMETER C_BASEADDR = 0x81400000 + PARAMETER C_HIGHADDR = 0x8140ffff + BUS_INTERFACE SPLB = mb_plb + PORT GPIO_IO_O = fpga_0_LEDs_8Bit_GPIO_IO_O_pin +END + +BEGIN xps_gpio + PARAMETER INSTANCE = DIP_Switches_4Bit + PARAMETER C_ALL_INPUTS = 1 + PARAMETER C_GPIO_WIDTH = 4 + PARAMETER C_INTERRUPT_PRESENT = 0 + PARAMETER C_IS_DUAL = 0 + PARAMETER HW_VER = 2.00.a + PARAMETER C_BASEADDR = 0x81420000 + PARAMETER C_HIGHADDR = 0x8142ffff + BUS_INTERFACE SPLB = mb_plb + PORT GPIO_IO_I = fpga_0_DIP_Switches_4Bit_GPIO_IO_I_pin +END + +BEGIN xps_gpio + PARAMETER INSTANCE = Buttons_4Bit + PARAMETER C_ALL_INPUTS = 1 + PARAMETER C_GPIO_WIDTH = 4 + PARAMETER C_INTERRUPT_PRESENT = 0 + PARAMETER C_IS_DUAL = 0 + PARAMETER HW_VER = 2.00.a + PARAMETER C_BASEADDR = 0x81440000 + PARAMETER C_HIGHADDR = 0x8144ffff + BUS_INTERFACE SPLB = mb_plb + PORT GPIO_IO_I = fpga_0_Buttons_4Bit_GPIO_IO_I_pin +END + +BEGIN mpmc + PARAMETER INSTANCE = DDR_SDRAM + PARAMETER C_NUM_PORTS = 1 + PARAMETER C_SPECIAL_BOARD = S3E_STKIT + PARAMETER C_MEM_TYPE = DDR + PARAMETER C_MEM_PARTNO = MT46V32M16-6 + PARAMETER C_MEM_BANKADDR_WIDTH = 2 + PARAMETER C_MEM_DATA_WIDTH = 16 + PARAMETER C_MEM_DM_WIDTH = 2 + PARAMETER C_MEM_DQS_WIDTH = 2 + PARAMETER C_PIM0_BASETYPE = 1 + PARAMETER C_XCL0_B_IN_USE = 1 + PARAMETER HW_VER = 5.04.a + PARAMETER C_MPMC_BASEADDR = 0x44000000 + PARAMETER C_MPMC_HIGHADDR = 0x47ffffff + BUS_INTERFACE XCL0 = microblaze_0_IXCL + BUS_INTERFACE XCL0_B = microblaze_0_DXCL + PORT MPMC_Clk0 = clk_100_0000MHzDCM0 + PORT MPMC_Clk90 = clk_100_0000MHz90DCM0 + PORT MPMC_Rst = sys_periph_reset + PORT DDR_Clk = fpga_0_DDR_SDRAM_DDR_Clk_pin + PORT DDR_Clk_n = fpga_0_DDR_SDRAM_DDR_Clk_n_pin + PORT DDR_CE = fpga_0_DDR_SDRAM_DDR_CE_pin + PORT DDR_CS_n = fpga_0_DDR_SDRAM_DDR_CS_n_pin + PORT DDR_RAS_n = fpga_0_DDR_SDRAM_DDR_RAS_n_pin + PORT DDR_CAS_n = fpga_0_DDR_SDRAM_DDR_CAS_n_pin + PORT DDR_WE_n = fpga_0_DDR_SDRAM_DDR_WE_n_pin + PORT DDR_BankAddr = fpga_0_DDR_SDRAM_DDR_BankAddr_pin + PORT DDR_Addr = fpga_0_DDR_SDRAM_DDR_Addr_pin + PORT DDR_DQ = fpga_0_DDR_SDRAM_DDR_DQ_pin + PORT DDR_DM = fpga_0_DDR_SDRAM_DDR_DM_pin + PORT DDR_DQS = fpga_0_DDR_SDRAM_DDR_DQS_pin + PORT DDR_DQS_Div_O = fpga_0_DDR_SDRAM_ddr_dqs_div_io_pin + PORT DDR_DQS_Div_I = fpga_0_DDR_SDRAM_ddr_dqs_div_io_pin +END + +BEGIN clock_generator + PARAMETER INSTANCE = clock_generator_0 + PARAMETER C_EXT_RESET_HIGH = 1 + PARAMETER C_CLKIN_FREQ = 50000000 + PARAMETER C_CLKOUT0_FREQ = 100000000 + PARAMETER C_CLKOUT0_PHASE = 90 + PARAMETER C_CLKOUT0_GROUP = DCM0 + PARAMETER C_CLKOUT0_BUF = TRUE + PARAMETER C_CLKOUT1_FREQ = 100000000 + PARAMETER C_CLKOUT1_PHASE = 0 + PARAMETER C_CLKOUT1_GROUP = DCM0 + PARAMETER C_CLKOUT1_BUF = TRUE + PARAMETER C_CLKOUT2_FREQ = 50000000 + PARAMETER C_CLKOUT2_PHASE = 0 + PARAMETER C_CLKOUT2_GROUP = NONE + PARAMETER C_CLKOUT2_BUF = TRUE + PARAMETER HW_VER = 3.02.a + PARAMETER C_CLKOUT3_FREQ = 48000000 + PARAMETER C_CLKOUT3_PHASE = 0 + PARAMETER C_CLKOUT3_GROUP = NONE + PARAMETER C_CLKOUT3_BUF = TRUE + PORT CLKIN = dcm_clk_s + PORT CLKOUT0 = clk_100_0000MHz90DCM0 + PORT CLKOUT1 = clk_100_0000MHzDCM0 + PORT CLKOUT2 = clk_50_0000MHz + PORT RST = sys_rst_s + PORT LOCKED = Dcm_all_locked + PORT CLKOUT3 = clk_48_0000MHz +END + +BEGIN mdm + PARAMETER INSTANCE = mdm_0 + PARAMETER C_MB_DBG_PORTS = 1 + PARAMETER C_USE_UART = 1 + PARAMETER C_UART_WIDTH = 8 + PARAMETER HW_VER = 1.00.g + PARAMETER C_BASEADDR = 0x84400000 + PARAMETER C_HIGHADDR = 0x8440ffff + BUS_INTERFACE SPLB = mb_plb + BUS_INTERFACE MBDEBUG_0 = microblaze_0_mdm_bus + PORT Debug_SYS_Rst = Debug_SYS_Rst +END + +BEGIN proc_sys_reset + PARAMETER INSTANCE = proc_sys_reset_0 + PARAMETER C_EXT_RESET_HIGH = 1 + PARAMETER HW_VER = 2.00.a + PORT Slowest_sync_clk = clk_50_0000MHz + PORT Ext_Reset_In = sys_rst_s + PORT MB_Debug_Sys_Rst = Debug_SYS_Rst + PORT Dcm_locked = Dcm_all_locked + PORT MB_Reset = mb_reset + PORT Bus_Struct_Reset = sys_bus_reset + PORT Peripheral_Reset = sys_periph_reset +END + +BEGIN opb_usblite + PARAMETER INSTANCE = opb_usblite_0 + PARAMETER HW_VER = 1.00.a + BUS_INTERFACE SOPB = opb_v20_0 + PORT txdp = opb_usblite_0_txdp + PORT txdn = opb_usblite_0_txdn + PORT txoe = opb_usblite_0_txoe + PORT rxd = opb_usblite_0_rxd + PORT rxdp = opb_usblite_0_rxdp + PORT rxdn = opb_usblite_0_rxdn + PORT USB_Clk = clk_48_0000MHz +END + +BEGIN opb_v20 + PARAMETER INSTANCE = opb_v20_0 + PARAMETER HW_VER = 1.10.c + PORT OPB_Clk = clk_50_0000MHz + PORT SYS_Rst = sys_bus_reset +END + +BEGIN plbv46_opb_bridge + PARAMETER INSTANCE = plbv46_opb_bridge_0 + PARAMETER HW_VER = 1.01.a + PARAMETER C_RNG0_BASEADDR = 0xFFFF0000 + PARAMETER C_RNG0_HIGHADDR = 0xFFFF7FFF + BUS_INTERFACE SPLB = mb_plb + BUS_INTERFACE MOPB = opb_v20_0 +END + Index: opb_usblite/tags/R1/inf/fpgaser.inf =================================================================== --- opb_usblite/tags/R1/inf/fpgaser.inf (nonexistent) +++ opb_usblite/tags/R1/inf/fpgaser.inf (revision 7) @@ -0,0 +1,50 @@ +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} + +Provider=%OC% +LayoutFile=layout.inf +DriverVer=10/15/1999,5.0.2153.1 + +[Manufacturer] +%OC%=OC + +[OC] +%USBLITE%=Reader, USB\VID_1234&PID_5678 + +[Reader_Install.NTx86] +;Windows2000 + +[DestinationDirs] +DefaultDestDir=12 +Reader.NT.Copy=12 + +[Reader.NT] +CopyFiles=Reader.NT.Copy +AddReg=Reader.NT.AddReg + +[Reader.NT.Copy] +usbser.sys + +[Reader.NT.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[Reader.NT.Services] +AddService = usbser, 0x00000002, Service_Inst + +[Service_Inst] +DisplayName = %Serial.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\usbser.sys +LoadOrderGroup = Base + +[Strings] +OC = "www.opencores.org" +USBLITE = "OPB_USBLITE Serial" +Serial.SvcDesc = "OPB_USBLITE Serial emulation driver" +

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.