Dear Miss Jan Axelson,
I’m very happy to find your website and this forum. Thank you helping developers making sense of the harder stuff to get their USB projects done. I hope you like my question. I try to be as clear and non-annoying as possible ;-). Also I would be prepared to buy a book if you can tell it serves my goals.
My goal is to design a full speed USB device for an FPGA written in VHDL. I know this is a big project but I’ve got some functionality running fine in the logic simulator like the rx data sampler, CRC5, CRC16 and a major part of the protocol layer state machine (SIE). The chapter 9 state machine I still need to do (you know with states like attached, powered, addressed and configured).
I’m reading through fragments of multiple chapters to get an idea about the complete required functionally needed for a USB device. It’s easy to make a narrow minded solution to get some chapter 8 stuff working that will backfire when I am implementing chapter 9 stuff.
So, right now I’m thinking about the storage stuff. With that I mean the endpoint buffers and the descriptors (device, configuration, interface, endpoint and string)
As this design is for an FPGA I can make it parameterizable. The function side could define the number of endpoints it wishes to use as well as the sizes of the buffers. I plan to use dual-port memory to implement this. The dual-port memory is a dedicated part inside the FPGA (Xilinx block RAM). Depending on what is requested on the client/function side I can define 1 or more of the 18kb block RAM components. As you might know in contrast to run-time, what is compile time to software is elaboration to HDLs. So during elaboration all the constant parameters should be evaluated to compute the total size of the required memory and then I can decide how much block RAMs I need to use as well as defining the initial contents.
Still I’ve a hard time figuring out what I actually need to store. To start simple I think I’m going for a single configuration, single interface USB device with a configurable set of endpoints. Is there hierarchy in storage? For example do all descriptors belong to endpoint zero? Should all control transfers go to the default control pipe of endpoint zero?
Apart from that I would like to store strings for stuff like manufacturer and product identification. Am I right I can implement it like this: A single area of memory that starts with that String Descriptor Zero. I only want to support US English so the String Descriptor Zero is just 4 bytes. Then on offset 4 I can start the first UNICODE String Descriptor. Let say it is the iManufacturer string of the device descriptor, the first string index I can use is 1 because 0 is when I don’t support strings. So I think I also need to maintain a lookup table to translate between the string index to the offset into the string memory area where the UNICODE String Descriptor begins. That way I can store up to 255 strings correct? Immediately after the first UNICODE String Descriptor I can have the next one right?
In general I think my previous questions demonstrate my perspective (and frustrations ;-) to actually implement a really good USB device. I would be really grateful if you can provide me some good resources how I actually can build all that functionality especially about the storage of endpoint buffers and the descriptor stuff.
Resources I already know of are:
- USB Made Simple (website)
- USB in a nutshell
- USB 2.0 official specification
- An introduction to USB development, by Jack Ganssle
- CYCLIC REDUNDANCY CHECKS IN USB
- DESIGNING A ROBUST USB SERIAL INTERFACE ENGINE(SIE)
- Some various USB Peripheral Controller device datasheets (no major secrets revealed
)
I would be super XL ultra grateful for your attention and time if you’re willing to provide me some valuable answers on this post.
Best regards,
Maarten Verhage