Accelerating JTAG chain accesses

The typical SET statement used to write to and read from a JTAG chain in XJEase is as follows:

// Write to ADDRESS and read from DATA
SET ADDRESS := 0, value := DATA;

When a SET instruction with a read in it is executed, the JTAG chain is scanned out into the hardware and the results are read back before the next instruction can be executed. This has a major problem: if the JTAG chain TCK frequency is low, the execution of the code is slow, as we cannot begin executing the next instruction until the current instruction has finished.

In the figure above, A shows the system waiting for each JTAG chain to execute and finish before proceeding with the next XJEase instruction, whereas B indicates the speed-up that could be obtained if the system did not have to wait for one scan to finish before the next is started.

This can only happen if the SET statements being executed only write and do not read, unlike the example above. When there are only writes then XJEase execution can continue concurrently with the data being sent to and from the XJLink, resulting in a large speed-up.

If data is being read as well as written, then each scan that reads data back must complete before the next can be sent, and so the latency of the USB connection to the XJLink becomes dominant in the maximum throughput that can be obtained.

Designing around JTAG chain latency

If a number of JTAG scans are written (with no reading of data back), then XJTAG will group those scans together and send them all at once, making better use of the available bandwidth. Therefore, multiple writes should be put together as much as possible.

Example

// Change this ...
FOR i := 0 FOR BUS_WIDTH
  WriteCycle(1 << i, 0xaa);
  ReadCycle(1 << i)(result);
  CheckResult(result);
END;

// ... to this.
FOR i := 0 FOR BUS_WIDTH
  WriteCycle(1 << i, 0xaa);
END;
FOR i := 0 FOR BUS_WIDTH
  ReadCycle(1 << i)(result);
  CheckResult(result);
END;

The above example shows how the user can improve the speed by putting the write accesses together. However, XJTAG will still combine the scans together and send them whenever it is convenient, which may result in the scans being sent in batches. To guarantee that a sequence of write scans is sent as efficiently as possible, a HOLDOFF block can be used.

Example

// To group all the writes together:
HOLDOFF
  FOR i := 0 FOR BUS_WIDTH
    WriteCycle(1 << i, 0xaa);
  END;
END;
FOR i := 0 FOR BUS_WIDTH
  ReadCycle(1 << i)(result);
  CheckResult(result);
END;

Problems associated with queued JTAG writes

There are two problems associated with queueing JTAG writes:

Speed
The JTAG scans are being sent back to back, so the time between a JTAG write and a subsequent read is only 5 TCK cycles. If the TCK frequency is 33 MHz, the time between writing to the net and reading back could only be 150 ns. This could be a problem if the net has some capacitance or if there is a large feedback path that the signal must travel along. One example is a serial loopback through a level converter: the level converter rise time is very much longer than 150 ns!
Timing
The user may want to send chain 1, wait for 10 ms, then send chain 2. But the system would combine these two chains and send them together.

In these situations, a FLUSH operation can be included to make sure that any outstanding accesses are flushed out to the hardware.

Example

// A loopback test from TX to RX through the RS232 level converters
LoopbackTest()(INT result)
  INT val;

  SET TX := 0;
  FLUSH;

  SET val := RX;

  IF val != 0 THEN
    PRINT("Unable to loopback TX to RX\n");
    result := 1;
    RETURN;
  END;

  result := 0;
END;