Phase II – Bus and USB Snooping
In order to decipher how this monstrosity operated, we used the original software to perform various actions while snooping USB and monitoring the internal bus. We already knew what pins we wanted to drive high/low in order to apply signal X to ZIF pin Y. The object of the next phase was to determine how the USB commands were interpreted by the 8051 in order to tell the CPLD/FPGA what to do.
In the pic below, the logic analyzer port A is watching the 8 data lines of the bus, and port B is monitoring the ALE, nCS, nINT, nRD, nWR lines of the bus. The white wire is tapping the 24MHz system clock for most efficient use of the logic analyzer’s memory. Otherwise, we’d have to clock the LA at 50MHz or more likely, 100MHz internally and we’d get much shallower data storage. Use EXTCLK when you can!
Fig 3 – Top2005 during takeover
Bus Control. The 8051 is the master, and all the other IC’s report to it. The PDI can trigger an interrupt when it gets data from the PC, but the CPLD/FPGA are written/read on demand when the 8051 wants to change things. We’ll take a moment to describe the internal bus in a little greater detail.
- DATA[7:0] – 8-bit Address/Data bus.
- ALE – Address Latch Enable. A nice throwback to the old-school, this signal tells the bus what address (what peripheral) is being written/read. To do that, the 8051 puts the desired address on the bus and toggles ALE. On the falling edge of ALE, things like the FPGA latch this address and use it to determine if the next write/read is meant for them. This board is a little weird in that it is CONSTANTLY toggling ALE, when we would expect it only in the case of a MOVX instruction. So the FPGA and CPLD have to deal with a lot of junk ALE latches. No biggie as long as you don’t respond to anybody else’s address space, but the frantic ALE sure looks stupid when viewed on the logic analyzer.
- nCE – Chip Enable (active low). When low, the bus data is meant for the PDIUSB. When high, the data is meant for the FPGA or CPLD.
- nRD – Read Data (active low). When the 8051 wants data, it first tristates it’s own bus drivers. Then, it drives nRD low to allow one of the other chips to drive the bus during the low time of nRD. When nRD goes high again, that other driver must go tristate.
- nWR – Write Data (active low). Used to latch data into one of the PDIUSB, CPLD, or FPGA.
Top2005 USB Commands
While this is certainly not an exhaustive list of the USB commands, it is a list of the commands that are most useful for IC testing. All writes are bulk writes to endpoint $02, and all reads are bulk reads from endpoint $82. The PDIUSB treats bulk and interrupt transfers the same way, so there is no use to interrupt transfers and you can just do it all with bulk transfers.
We’ll begin with the “0E Series”, which control most of the major pin/voltage defintions. Each 0E command is 4 bytes long, consisting of $0E, a command code, a pin/value code, and terminated with $00. Yes, the $00 is needed or the 8051 will get tangled up over time and begin spewing junk. One exception is the bitstream load command which is 64 bytes long, containing the 4-byte 0E command and 60 bytes of bitstream. On to the commands, my friends!
0E 12 XX 00 – Set VPP Level. XX is the hex code for the desired voltage. From what we can tell, the hex code is intended to be a user-readable voltage value. Because the VPP is not terribly accurate, and we didn’t know the codes ahead of time, we just programmed it to each of the 255 different codes and recorded the first value when the VPP changed.
This gives us a list that sometimes does not match voltage to hex code, but we blame the 8051 programming – should have just let us write the resistor code directly! Again, the accuracy is terrible so here we’ve recorded the ACTUAL voltage measured on our device. 9.95v instead of 10v, for example. It would probably be a good idea to try to use the actual intended code, but we’ll leave that as an exercise for the reader.
- 00 – Boost off. Voltage will be around 4.6v because the boost has a schottky diode from 5v to VPP. Can never truly go to 0v.
- 33 – 9.37v. Probably code $5E for 9.4v, but anything from $33 to $5E is interpreted as 9.4v.
- 5F – 9.95v
- 64 – 10.44v
- 69 – 11.03v
- 78 – 12.00v
- 7D – 12.61v
- 82 – 13.10v
- 87 – 13.70v
- 91 – 14.79v
- 9B – 16.36v
- D2 – 21.11v
- FA – 25.59v
There’s a few traps in there, such as $6E and $AA that both give 9.4v. So either use our code or the actual code, and try to avoid “in-between” stuff.
0E 13 XX 00 – Set VCCx Level. XX is the hex code for VCCx voltage, and the Top2005 only has 3 choices. These were easy to decipher, so the ideal value is listed here. Actual 3.3v is more like 3.6v, for example.
- 19 – 2.5v
- 21 – 3.3v
- 32 – 5.0v
0E 14 XX 00 – Apply VPP to Pin. XX is the hex code for the ZIF pin number. Available codes are: 0 (clear all pins), 1 ($01), 5 ($05), 7 ($07), 9 ($09), 10 ($0a), 11 ($0B), 12 ($0C), 14 ($0E), 15 ($0F), 20 ($14), 26 ($1A), 28 ($1C), 29 ($1D), 30 ($1E), 31 ($1F), 34 ($22), 35 ($23), and 40 ($28). Note that these are additive. Latching pin 1 to VPP followed by pin 5 means they will BOTH be connected. Writing 0E 14 00 00 clears all VPP connections.
0E 15 XX 00 – Apply VCCx to Pin. XX is again the hex code for the ZIF pin. Available codes are: 0 (clear all pins), 8 ($08), 13 ($0D), 17 ($11), 24 ($18), 25 ($19), 26 ($1A), 27 ($1B), 28 ($1C), 30 ($1E), 32 ($20), 34 ($22), 36 ($24), 40 ($28). Again, the latching action is additive and you must write 00 to clear all.
0E 16 XX 00 – Apply GND to Pin. XX is again the hex code for the ZIF pin. Available codes are: 0 (clear all), 10 ($0A), 14 ($0E), 16 ($10), 20 ($14), 25 ($19), 31 ($1F). Again, the latching action is additive and you must write 00 to clear all.
0E 2x – Bitsream Commands
A special subset of the 0E commands are the $21, $22, and $23 bitstream commands. Pretty much essential for booting the FPGA and changing bitstreams. Yes, all your FPGA registers are cleared to 00′s when you reload a bistream. Just a piece of trivia that you may use to aid in debugging. Or at least to know how to handle the startup.
0E 21 XX 00 – Start Bitstream Upload. Internally, this makes the 8051 assert the FPGA INIT pin and wait for PROG. Fire it once when you want to start uploading a bitstream.
0E 22 00 00 DATA – Bitstream Data Packet. This 64-byte command consists of the header 0E 22 00 00 and 60 bytes of bitstream data. These packets are used to stream the bistream into the FPGA. Start at the beginning of the bitstream data (skip header!) and churn out packets until you reach the end. Any short packets at the end should be buffered with 00′s out to 60 data bytes.
0E 23 00 00 – End Bitstream Upload. Deassert INIT and the FPGA is up and running. This is usually followed up by a $07 “read” command of 64 bytes. It’s all junk except for the first byte, which indicates the success of the upload. You want an $01 here and not a $00, or you must re-upload. Failed configuration is rare, and usually only happens if your FPGA code is so fux0r’d that it pulls down a data bus pin by accident. That requires a power cycle to fix.
Continue to Next Page