-
Notifications
You must be signed in to change notification settings - Fork 175
Description
Tang primer 20k has a working example of the usb3317 being used (https://github.com/sipeed/TangPrimer-20K-example/tree/main/USB).
This example has been generated via https://luna.readthedocs.io/en/latest/. Unfortunately the author did not include the original .py files that generated the verilog.
I have been trying to reconstruct for two weeks what the original file might have been, but no luck (since I do not want a serial device but a simple custom device for bulk transfers).
I generated a file that fails at the descriptor stage as far as I can tell from Windows (although the connection sound does play. In other words, the device does appear in the device manager.
I suspect there might be an issue with my customization (i.e., disabling submodules.car and platform.request and using a Record instead):
#!/usr/bin/env python3
#
# This file is part of LUNA.
#
# Copyright (c) 2020 Great Scott Gadgets <[email protected]>
# SPDX-License-Identifier: BSD-3-Clause
import os
from amaranth import Elaboratable, Module
from usb_protocol.emitters import DeviceDescriptorCollection
from luna import top_level_cli
from luna.gateware.platform import NullPin
from luna.gateware.usb.usb2.device import USBDevice
from amaranth import Elaboratable, Module
from amaranth.hdl.rec import Record, DIR_FANIN, DIR_FANOUT, DIR_NONE
from amaranth.back import verilog
from luna import top_level_cli
class USBDeviceExample(Elaboratable):
""" Simple example of a USB device using the LUNA framework. """
def __init__(self):
self.ulpi = Record([
('data', [('i', 8, DIR_FANIN),
('o', 8, DIR_FANOUT), ('oe', 1, DIR_FANOUT)]),
('clk', [('i', 8, DIR_FANIN)]),
('nxt', [('i', 8, DIR_FANIN)]),
('stp', [('o', 8, DIR_FANOUT)]),
('dir', [('i', 1, DIR_FANIN)]),
('rst', [('o', 8, DIR_FANOUT)])
])
def create_descriptors(self):
""" Create the descriptors we want to use for our device. """
descriptors = DeviceDescriptorCollection()
#
# We'll add the major components of the descriptors we we want.
# The collection we build here will be necessary to create a standard endpoint.
#
# We'll need a device descriptor...
with descriptors.DeviceDescriptor() as d:
d.idVendor = 0x16d0
d.idProduct = 0xf3b
d.iManufacturer = "LUNA"
d.iProduct = "Test Device"
d.iSerialNumber = "1234"
d.bNumConfigurations = 1
# ... and a description of the USB configuration we'll provide.
with descriptors.ConfigurationDescriptor() as c:
with c.InterfaceDescriptor() as i:
i.bInterfaceNumber = 0
with i.EndpointDescriptor() as e:
e.bEndpointAddress = 0x01
e.wMaxPacketSize = 64
with i.EndpointDescriptor() as e:
e.bEndpointAddress = 0x81
e.wMaxPacketSize = 64
return descriptors
def elaborate(self, platform):
m = Module()
# Generate our domain clocks/resets.
# m.submodules.car = platform.clock_domain_generator()
# Create our USB device interface...
# bus = platform.request(platform.default_usb_connection)
m.submodules.usb = usb = USBDevice(bus=bus)
# Add our standard control endpoint to the device.
descriptors = self.create_descriptors()
usb.add_standard_control_endpoint(descriptors)
# Connect our device as a high speed device by default.
m.d.comb += [
usb.connect .eq(1),
usb.full_speed_only .eq(1 if os.getenv('LUNA_FULL_ONLY') else 0),
]
# ... and for now, attach our LEDs to our most recent control request.
m.d.comb += [
platform.request_optional(
'led', 0, default=NullPin()).o .eq(usb.tx_activity_led),
platform.request_optional(
'led', 1, default=NullPin()).o .eq(usb.rx_activity_led),
platform.request_optional(
'led', 2, default=NullPin()).o .eq(usb.suspended),
]
return m
def ports(self):
return [
self.ulpi.data.o,
self.ulpi.data.oe,
self.ulpi.data.i,
self.ulpi.clk.i,
self.ulpi.nxt.i,
self.ulpi.stp.o,
self.ulpi.dir.i,
self.ulpi.rst.o
]
if __name__ == "__main__":
top_level_cli(USBDeviceExample)
The .car submodule seems to be addressed(?) in the Gowin project as follows (I assume):
assign ulpi_rst = 1'b1;
assign ulpi_data = ulpi_data_oe ? ulpi_data_o : 8'hz;
wire int_clk = ~ulpi_clk;
reg [4:0] rst_cnt;
always @(posedge int_clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
rst_cnt <=5'd0;
end else begin
if (rst_cnt[4] == 1'b0) rst_cnt <= rst_cnt + 5'd1;
end
end
What am I overlooking here? Did I do something counter to the Luna framework?