Author Topic: Actual USB device design in VHDL for FPGA  (Read 5431 times)

Maarten Verhage

  • Member
  • ***
  • Posts: 2
Actual USB device design in VHDL for FPGA
« on: March 25, 2016, 06:15:13 pm »
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
« Last Edit: April 01, 2016, 03:09:37 pm by Maarten Verhage »

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Actual USB device design in VHDL for FPGA
« Reply #1 on: March 26, 2016, 11:05:57 am »
Yes, the host requests descriptors by sending Get Descriptor requests to control endpoint zero. The USB specs don't forbid multiple control endpoints but there is no benefit to them, and I've never seen one implemented.

I see nothing wrong with your plan to store strings in memory and access them using a lookup table.

I wrote USB Complete Fifth Edition to serve as a bridge between the USB specifications, which are detailed but don't go into real-world development issues, and brief introductory material like the sources you mention. More information is here:

http://janaxelson.com/usbc.htm

Good luck with your project. Feel free to return here if you have more questions.




Maarten Verhage

  • Member
  • ***
  • Posts: 2
Re: Actual USB device design in VHDL for FPGA
« Reply #2 on: March 26, 2016, 02:01:42 pm »
Hi Jan & other readers,

Great thanks a lot! I'm sure I will only support the control endpoint for endpoint zero.

So for my understanding: All of the functionality in chapter 9, like device requests and descriptors belong to the default control pipe, which is just one level higher in the stack to endpoint zero.

Sorry I failed to get a picture attached to this post, therefore please take a look on page 11 of the USB in a Nutshell article.

I think the block diagram is a bit simplified as the storage of the descriptors isn't shown. I'm wondering if I actually need to expose endpoint zero to the function side. I think I can implement the majority of the default control pipe functionality in the lower side (where the SIE resides). This also make sense if I receive Set Feature with a request to output some Test_SE0_NAK because that is a low level hardware thing. Maybe I can use the idea of an USB peripheral controller to see what is actually communicated to the function side of endpoint zero (like a microcontroller). Sure I would need to inform them when my state machine reached the configured state.

Thanks for confirming on my string storage idea. For the configuration, interfaces and endpoint descriptors I think it is a bit easier to store because when I receive Get Descriptor I need to provide everything at once as described in spec 9.4.3:

"A request for a configuration descriptor returns the configuration descriptor, all interface descriptors, and endpoint descriptors for all of the interfaces in a single request. The first interface descriptor follows the configuration descriptor. The endpoint descriptors for the first interface follow the first interface descriptor. If there are additional interfaces, their interface descriptor and endpoint descriptors follow the first interface’s endpoint
descriptors."

So I think I just need to remember the offset and length of the memory area that contains the whole configuration stuff. Read that and provide it to the SIE transmitter to have it sent to the host, right?

About your book USB complete. Look, I think I'm a bit of a atypical guy here on this forum as I actually are aiming to make a digital design for a USB device. And I think it's save to say the majority of people here including you would be buying a peripheral controller part to get that functionality to your design. So, I would like to ask you how much can I benefit from your book to make the translation from all the required behavior to an actual design? Also have you ever came across an elaborate USB device block diagram or perhaps double buffering schemes that would be more or less beneficial to me?

Ok, thanks anyway and happy easter!!
Maarten
« Last Edit: March 27, 2016, 05:22:46 pm by Maarten Verhage »

Jan Axelson

  • Administrator
  • Frequent Contributor
  • *****
  • Posts: 3033
    • Lakeview Research
Re: Actual USB device design in VHDL for FPGA
« Reply #3 on: March 27, 2016, 09:50:33 am »
You can structure your device any way you want as long as it meets the relevant specifications and performs any other communications you require.

Yes, a request for a configuration descriptor returns the configuration descriptor and all subordinate descriptors. The host will not ask for the subordinate descriptors individually.

USB Complete 5th Edition does not explain how to design a peripheral in VHDL. It does, however, describe USB communication protocols and requirements including things like how to perform successful enumeration, how to manage the stages of control transfers, how to decide what transfer types to support, tools and tips for debugging, managing power, and more. A complete Table of Contents and more are here:

http://janaxelson.com/usbc.htm