Car World JTAG UART

A UART (Universally Asynchronous Receiver-Transmitter) core, to allow for communication between the Car World game and the DE2 Board via a JTAG UART.

DeviceCar World JTAG UART
Input/OutputBoth
Address Base0x10001020
Address Map
AddressR/WDescription
baseR/WData Register
31:16 - Number of bytes available to read (after this read - see Notes)
15 - read data is valid
7:0 - the data itself
base+4R/WControl Register
31:16 - Spaces available for writing
10 - AC (has value of 1 if JTAG UART has been accessed by host, cleared by writing 1 to it)
9 - Write interrupt is pending
8 - Read interrupt is pending
1 - Enable write interrupts
0 - Enable read interrupts
InitializationNone
Interrupts
TriggeredOn data-received or able to send (see below)
IRQ Line13
EnableSet bit 1 and/or 0 in the Control Register for write and read interrupts respectively.
AcknowledgeRead (write) interrupts acknowledged by reading (writing) to the Data Register
Software Setup This core communicates with the JTAG UART Data Transceiver program running on the host computer.
The JTAG UART Data Transceiver program is bundled with the Car World program and can downloaded here.
To start the program, navigate to the jtag_transceiver folder and run transcerver_setup.bat.

Notes

The Data Register is used for both sending and receiving through the JTAG - the type of instruction executed (stw or ldw) determines whether you send or receive. Every time you read from this register an 8-bit data word is ejected from the receive FIFO, and everytime you write to it you insert a byte to the send FIFO. Note that you can not read the "Number of Bytes available" in bits 31:16 of this register without reading the data in bits 7:0, and hence ejecting another byte. The "Number of Bytes available" does not include the byte you just ejected - but make sure you extract this byte from the 32-bit result (if it is valid).

If you try to send a byte when the write FIFO is full, the byte will not be sent, and will be lost.

Assembly Example: Sending the character '0' through the JTAG

  movia r7, 0x10001020 /* r7 now contains the base address */
WRITE_POLL:
  ldwio r3, 4(r7) /* Load from the JTAG */
  srli  r3, r3, 16 /* Check only the write available bits */
  beq   r3, r0, WRITE_POLL /* If this is 0 (branch true), data cannot be sent */
  movui r2, 0x30 /* ASCII code for 0 */
  stwio r2, 0(r7) /* Write the byte to the JTAG */

Assembly Example: Polling the JTAG until valid data has been received

  movia r7, 0x10001020 /* r7 now contains the base address */
READ_POLL:
  ldwio r2, 0(r7) /* Load from the JTAG */
  andi  r3, r2, 0x8000 /* Mask other bits */
  beq   r3, r0, READ_POLL /* If this is 0 (branch true), data is not valid */
  andi  r3, r2, 0x00FF /* Data read is now in r3 */

C Example: Sending "Hello World" through the UART

#define JTAG_UART_DATA ((volatile int*) 0x10001020)
#define JTAG_UART_CONTROL ((volatile int*) (0x10001020+4))

int main()
{
    unsigned char hwld[] = {'H','e','l','l','o',' ','W','o','r','l','d','\0'};
    unsigned char *pOutput;

    pOutput = hwld;
    while(*pOutput) //strings in C are zero terminated
    {
         //if room in output buffer
         if((*JTAG_UART_CONTROL)&0xffff0000  ) 
         {
            //then write the next byte
            *JTAG_UART_DATA = (*pOutput++); 
         }
     }
}