Protocol documentation for Digilent USB JTAG controllers.
The Digilent Adept USB protocol is found in many development boards and programming cables made by Digilent. The protocol supports SPI, JTAG, etc, and Controllers build into development boards often support additional features like reading sensor values.
Digilent's API abstracts out their controllers and allows users to transparently speak any supported protocol through their branded controllers. Adapt's goal is similar, but with many more controllers, so adding digilent support will open up many controllers.
Protocol Description:
There are two major types of USB message used in the Digilent Adept protocol: Control and Bulk. Control messages read or write information about the controller itself. Bulk messages are primarily used to instruct the controller to send data out to the connected target.
Control Messages
Messages to query or set fields in the controller. bRequestType field depends on direction (OUT=0x40; IN=0xC0). All unspecified USB message fields are 0.
Name | RQ* | Direction* | Length | Description |
---|---|---|---|---|
Product Name | E1 | IN | 28 | ASCII |
User Name | E2 | IN | 16 | ASCII |
Serial Number | E4 | IN | 12 | ASCII |
Firmware Version | E6 | IN | 2 or 4 | RAW BYTES Little Endian. |
Device Capabilities | E7 | IN | 8 | Bitflag showing features supported by the board. Its use is a bit inconsistent:
|
Set OEM Seed | E8 | OUT | 2 | Sets a seed that determines the data returned by the 0xEC request. See the Description of OEM Verify |
Product ID | E9 | IN | 4 | The product ID is not consistently handled. Sometimes a controller will always report its product id, sometimes it will only report the product id after being flashed with firmware. Sometimes the product id is used to determine what firmware to flash the controller with, if any. |
OEM ID CHECK | EC | IN | 4 | Returns a value based on the OEM SEED (0xE8) request. A check that digilent drivers do to ensure the controller is running official firmware. Unnecessary to call in open drivers. Example implementation (python):
seed = {Seed from 0xEC cmd}
See the Description of OEM Verify |
Terms:
(RQ is Request Code)USB message direction: IN=to computer; OUT=to device
Bulk Requests
Most bulk messages cause electrical activity on the controller's output pins.
Initial Request Message Format:
All bulk requests start with the same Initial Request and end with a Response Code from the device. Some requests transfer additional data in between the initial request and the response code, and are described below.
Initial Request messages are sent to USB endpoint (1). The endpoints for reading response codes and sending/receiving addtional data depends on the device, and is detailed in the Known Device Table.
AVD Response protocol:
SZ:CT:RQ:00:{Parameters to the request if any}
Where
SZ:
Length of bulk packet minus 1.
CT:
Category or request. Category 0x02 appears to be JTAG.
RQ:
Request Code
Full Message Sequence:
BULK IN (USB ENDPOINT 2) 01:XX #Status code. 1 byte long. 00 known to be 'good'. 03 is a fail of some kind (when the device is already in use).
- Initialization message (In table below).
- Status Code message (described above).
- YY* Raw bit data rounded to the byte. XX bits. USB Endpoint 3.
- YY* Raw bit data rounded to the byte. XX bits. USB Endpoint 4. Only sent if RV in init message is 1.
- 03:02:ZZ:00 to USB Endpoint 1. ZZ = 80|RQ. RQ is the RQ of the init message. Requests number of bits transferred.
- SZ:FL:(XX:XX:XX:XX)* SZ = bitcount(FL)*4 + 1. FL is a bit field for 0x80 and 0x40. 0x80 requests for the number of bits sent. 0x40 Requests for the number of bits received. For each flag there is a 4 byte number for the number of bits.
Bulk JTAG Control Request Commands:
Name | CT | RQ | Transaction Type | SZ | Parameters |
---|---|---|---|---|---|
ENABLE JTAG | 02 | 00 | Simple | 3 | None |
DISABLE JTAG | 02 | 01 | Simple | 4 | None |
PORT INFO | 02 | 02 | Simple | 4 | 1 byte detail type. 0x01: Port Count. 0x05: Port Properties. |
SET SPEED | 02 | 03 | Simple | 7 |
4 byte speed in bps Returns status 0 and the 4 byte (little endian) actual bit rate the controller selected. If JTAG is not enabled, will return status code 0x04 and no data. |
GET SPEED | 02 | 04 | Simple | 3 |
No Parameters Returns status 0 and the 4 byte (little endian) actual bit rate the controller selected. If JTAG is not enabled, will return status code 0x04 and no data. |
SET Tms Tdi Tdo | 02 | 05 | Simple | 6 | MS:DI:DO One byte each. |
GET Tms Tdi Tdo Tck | 02 | 06 | Simple | 3 | None |
Clock Tick | 02 | 07 | Special (Status, Send 02:02:87 to endpoint 1. Status) | 9 | MS:DI:XX:XX:XX:XX In this case X implies clock cycles, but bits are shifted. |
WRITE TDI BITS | 02 | 08 | ADV | 9 | RV:MS:XX:XX:XX:XX |
READ TDO BITS | 02 | 09 | ADV | 9 | MS:DI:XX:XX:XX:XX |
WRITE TMS/TDI BITS | 02 | 10 | ADV | 8 | RV:XX:XX:XX:XX |
WRITE TMS BITS | 02 | 11 | ADV | 9 | RV:DI:XX:XX:XX:XX |
(XX is the number of bits to transfer. Little Endian Number. 4 bytes.)
(MS, DI, DO, and CK are Boolean values for the state of the pins TMS, TDI, TDO, and TCK respectively. )
(RV is 1 if the values shifted out of TDO should be returned. This causes an additional packet to be sent from the device after the transfer of the provided input data.)
Known Devides:
The Endpnum column refers to which bulk endpoints are used to:
- Send initial Bulk Requests
- Receive Status Code responses
- Send additional command data (like JTAG transition data)
- Receive additional command data (like JTAG TDO states read from target)
All devices listed here have a vendorID of 0x1443.
Name | Endpnum | deviceID | FW? | ProdName | DCAP | ProdID |
Cr2s2 | 1 2 3 4 | 0007 | No | Cr2s2 | 0x15 (0)dJtg (2)dEpp (4)dSpi |
0x00900126 |
Basys2 | 1 2 3 4 | 0007 | No | Basys2 | 0x05 (0)dJtg (2)dEpp |
0x00800223 |
Nexys2 | 1 1 2 6 | 0005 | FX2FW_05_0000000D_ 00000000_030A.HEX |
PreFW: OnbUsb1 V2.0 PostFW: Onboard USB' |
0x0D (0)dJtg (2)dEpp (3)dStm |
PreFW: Unsupported PostFW: 0x00100005 |
Nexys3 | 1 1 2 6 | 0007 | FX2FW_0D_0000000D_ 00000000_030A.HEX |
Nexys3 | PreFW: 0 PostFW: 0x0D (0)dJtg (2)dEpp (3)dStm |
0x00D0010D |
Atlys | 1 1 2 6 | 0007 | FX2FW_0C_0000000D_ 00000000_030A.HEX |
Atlys | PreFW: Unsupported PostFW: 0x0D (0)dJtg (2)dEpp (3)dStm |
0x00C0010C |
Digilent Device Capabilities Enum:
VALUE | NAME | DESCRIPTION |
0x00000001 | dcapJtg | Jtag.... |
0x00000002 | dcapPio | Pin I/O |
0x00000004 | dcapEpp | Async Parallel Interface |
0x00000008 | dcapStm | Sync Parallel Interface (High Speed Stream) |
0x00000010 | dcapSpi | Serial Peripheral Interface |
0x00000020 | dcapTwi | Two Wire (Serial) Interface (i2c) |
0x00000040 | dcapAci | Async Comm Interface (UART) |
0x00000080 | dcapAio | Analog IN/OUT |
0x00000100 | dcapEmc | Electro-Mechanical Control |
0x00000200 | dcapDci | Not Documented |
0x00000400 | dcapGio | General Sensor & User I/O Libraries |
0x00000800 | dcapPti | Not Documented |
OEM Verification Procedure:
OEM Verification is an unrequired step for initialzing a digilent controller. The process it usually done once at startup, and entails setting a seed, asking the board to generate a response based off the seed, and confirming if that response is valid for the provided seed. No open drivers need to implement this.
- Set OEM Check Seed (0xE8) request. This seed is often based on time, or sometimes just '14'.
- Read OEM Check (0xEC) retuest.
- XOR the two bytes from the OEM seed
- XOR each byte returned from the OEM Check request with the value calculated in step 3.
- The resulting 4 bytes (after xoring) should equal 'Digi'. If not, the oem check fails.