Why "drive USB pull-up resistor to '0' to disable USB"?


Hi there. I’m fairly new to FPGA, and I find the following lines in the template code is a little confusing.

// drive USB pull-up resistor to '0' to disable USB
assign USBPU = 0;

Why do we need to explicitly disable USB? I mean, if we don’t need USB connectivity, we can simply ignore it, right?

In addition, I would appreciate it if somebody can explain to me how does driving a pull-up resistor to ‘0’ disable USB. Thanks in advance!


UPDATE: See the end for WHY you disable USB.

Here’s the HOW:

For what that USB_PU line does, let’s take a look at the schematic:


We see the USB D+ line is connected via a 1.5K resistor to USB_PU. Per the USB spec (as described in the Speed Identification section here), if you pull the D+ line to 3.3V (in this case by setting USB_PU to ‘1’), you’re telling the USB host that there’s a USB device present (thus enabling all the handshaking and enumeration that follows).

If you pull D+ low by setting USB_PU to ‘0’ (or ground), you’re signaling there is no (longer) a USB device connected.

(Edit upon edits later…) And if you pore over the page linked above, you’ll see mention of how D- can be used to identify a low speed device. But since D- doesn’t have a pull-up resistor, you don’t have to worry about pulling that line low at all - only the D+ line matters here since the TinyFPGA only identifies as high-speed.

Now for WHY:

If you don’t disable USB (either by omitting the USB_PU setting code or setting it to ‘1’ instead of ‘0’) the device/computer the TinyFPGA is connected to will identify it as a high speed USB device and will try to enumerate it. This will fail unless you’ve got some logic coded in that communicates properly over USB_P and USB_N. In the blinky example, you clearly don’t, so the enumeration will fail. In Windows, if you look in the Device Manager, you’ll see a new “Unknown USB Device (Device Descriptor Request Failed)”… which isn’t the end of the world, but it’s kinda sloppy nonetheless.

Bottom line: it’s better to disable USB by pulling USB_PU low if you’re not actually going to communicate via the USB port.

But how does any of this work to load the firmware over USB? Because there’s the default TinyFPGA bootloader that loads up when you hit the reset button, which contains the USB logic to enumerate as USB. If your code contained similar logic, you too could use the USB port (e.g., as a serial device).

I hope this helps!


Thanks for the information, Marty. That’s really helpful!

USB communication on FPGAs sounds cool but also complicated. Can you tell me more about it? I’m aware of the “USB in a NutShell” series, but they are a little too long for me to digest. (Well, they are not that long, but such specification is too dry for a beginner like me.)

To be more specific, I just want to get started to make “something” with the on-board USB port, like a Space Invaders emulator. To begin with, this repo enables me to emulate a serial terminal that simply echoes the characters back, but I don’t really get what data , valid , and ready of its “streaming pipeline interface” stand for. Are they part of the USB protocol or from the serial protocol? Shouldn’t I just need to deal with TX and RX?

I would appreciate it if you could point me to some beginner-friendly materials!


Ironically, I was about to follow up with a link to that very repo! I don’t know a lot about USB at this level, so I’m learning too.

I’m curious - what OS are you using, exactly, that you got that code working in? It’s (sadly) a pain in Windows via the recommended make + icestorm method as not everything you need (e.g., nextpnr) is even available. (I also have iCEcube2 at my disposal.)


I’m (also sadly) on macOS Mojave. There are some Altera boards at my desk, but Quartus only supports Windows and Linux, and setting up a VM seems to cause some performance penalty, so they are basically unusable for me at the moment. Thanks to Project IceStorm, I can at least play with LATTICE boards on my MacBook Pro. By the way, if you happen to own a macOS device, it’s necessary to apply this pull request to use tinyfpga_bx_usbserial.

Speaking of Windows, there is something called Windows Subsystem for Linux. Would that help?


I don’t use WSL as it makes it impossible to use VMWare player / VirtualBox / etc.

I’m gonna try setting up in an Ubuntu VM tomorrow and see how it goes.


Good luck! I’ll post update if I find something interesting.


I end up with the same problem this user is having:

As usual, this is pretty frustrating.


That sucks! You can try the firmware built on macOS if you want (remember to remove the tailing .hex), but I suspect the error has something to do with the device driver.

usbserial_tbx.asc.hex (1.6 MB)
usbserial_tbx.bin.hex (131.9 KB)


While your bin file differs somewhat from mine, I don’t think it’s functionally different. Flashing it ends up with the same problem in terms of the serial connection on Windows.


I’m starting to think it may be a deeper problem in terms of timing…


I’ve taken my question here: USB Communication

I’m hoping someone has an insight - I think it’s a timing thing but the fact that I can’t get any of them to work makes me wonder if it’s just Windows.

I take it these USB serial examples are working find for you though, right (on OS X)?


Yes, but not out-of-the-box. I need to manually apply this pull request. Otherwise, I can flash successfully but no device will show up in /dev/*.


I’m not aware of any fix for Windows… It usually just works for serial.