diff --git a/luna/gateware/usb/usb2/host/__init__.py b/luna/gateware/usb/usb2/host/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/luna/gateware/usb/usb2/host/packet.py b/luna/gateware/usb/usb2/host/packet.py new file mode 100644 index 000000000..c669a8127 --- /dev/null +++ b/luna/gateware/usb/usb2/host/packet.py @@ -0,0 +1,125 @@ +# +# This file is part of usb2-highspeed-core +# +# Copyright (c) 2021 Hans Baier +# SPDX-License-Identifier: BSD-3-Clause + +""" Contains the gatware module necessary to interpret and generate low-level USB host packets. """ + + +import operator +import unittest +import functools + +from nmigen import Signal, Module, Elaboratable, Cat, Array, Const +from nmigen.build import Platform +from nmigen.hdl.rec import Record, DIR_FANIN, DIR_FANOUT + + +from .. import USBSpeed, USBPacketID +from ...stream import USBInStreamInterface, USBOutStreamInterface +from ....interface.utmi import UTMITransmitInterface +from ....test import LunaGatewareTestCase, usb_domain_test_case + +from ..packet import USBTokenDetector + + + +class TokenGeneratorInterface(Record): + """ Record providing an interface to a USB token generator. + + Attributes + ---------- + pid: Signal(4), input + The Packet ID of the token. + payload: Signal(11), input + The payload of the token. + + new_token: Signal(), input + Strobe asserted for a single cycle when a new token packet should be sent. + """ + + def __init__(self): + super().__init__([ + ('pid', 4, DIR_FANIN), + ('payload', 11, DIR_FANIN), + ('new_token', 1, DIR_FANIN), + ]) + +class USBTokenGenerator(Elaboratable): + """ Gateware that generates token packets, including SOF + + Attributes + ---------- + interface: TokenGeneratorInterface + The interface that specifies the Token to be constructed + speed: Signal(2), input + Carries a ``USBSpeed`` constant identifying the device's current operating speed. + + Parameters + ---------- + utmi: UTMIInterface + The UTMI bus to transmit on. + """ + + def __init__(self, *, utmi, domain_clock=60e6): + self.utmi = utmi + self._domain_clock = domain_clock + + # + # I/O port + # + self.interface = TokenGeneratorInterface() + self.speed = Signal(2) + + def elaborate(self, platform: Platform) -> Module: + m = Module() + interface = self.interface + utmi = self.utmi + + token_data = Signal(24) + token_crc = Signal(5) + + m.d.comb += token_crc.eq(USBTokenDetector.generate_crc_for_token(interface.payload)) + + m.d.usb += [ + token_data.eq( + Cat( + interface.pid, + ~interface.pid, + interface.payload, + token_crc)) + ] + + with m.FSM(domain="usb"): + + # waiting for a new packet to be sent + with m.State("IDLE"): + with m.If(utmi.tx_ready & interface.new_token): + m.next = "PID" + + with m.State("PID"): + with m.If(utmi.tx_ready): + m.d.comb += [ + utmi.tx_data.eq(token_data[0:8]), + utmi.tx_valid.eq(1), + ] + m.next = "PAYLOAD0" + + with m.State("PAYLOAD0"): + with m.If(utmi.tx_ready): + m.d.comb += [ + utmi.tx_data.eq(token_data[8:16]), + utmi.tx_valid.eq(1), + ] + m.next = "PAYLOAD1" + + with m.State("PAYLOAD1"): + with m.If(utmi.tx_ready): + m.d.comb += [ + utmi.tx_data.eq(token_data[16:24]), + utmi.tx_valid.eq(1), + ] + m.next = "IDLE" + + return m \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 06ba0cfd0..18d3d2c1e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ pyusb -e git://github.com/hansfbaier/nmigen-library.git#egg=nmigen_library -e git://github.com/lambdaconcept/minerva.git#egg=minerva -e git://github.com/lambdaconcept/lambdasoc.git#egg=lambdasoc --e git://github.com/usb-tools/python-usb-protocol.git#egg=usb_protocol +-e git://github.com/hansfbaier/python-usb-descriptors.git#egg=usb_descriptors -e git://github.com/greatscottgadgets/apollo.git#egg=apollo pyvcd pyserial~=3.4