
As the name "Universal Latch-based Shift Register" implies, it's a shift register based on individual latches. The first advantage of this asynchronous method is the need of only two input signals.
All the operations, like shifting one bit, require non-overlapping, alternating pulses on SD and SC. This takes care of any transient condition and glitches. Capture and Update require slightly more complicated sequences but still use only SD and SC. The only exception is RESET, which is performed with an overlapping sequence.
I have no idea, it's all asynchronous magic. Short chains should reach 10 or 20MHz easily but since it's meant to be driven from some Arduino-style MCU through USB or a serial port, raw speed is not critical. The focus is on minimising any impact on the target circuit (surface, routing, power,...).
Below is an abridged diagram showing only 4 in and 4 out pins. Source : DTAP2-ULSR on Hackaday.io where transparent latches are replaced by back-fed MUX2 for simulation sake. There are 3 main stages :
The actual implementation has 12 bits of depth, with the 4 middle ones being both inputs and outputs.

The input, output and inout stages are made from 2 or 3 latches, made from standard A21OI and A221OI cells. They are smaller than a DFF.

For 8 inputs and 8 outputs (including 4 combined in and out)
a22oi a221oi a21oi : 66 (including one for the full adder, the rest for the bulk of the scan chain) buf : 35 (I never asked for them) inv : 4 (including one for the full adder) dfrbp : 4 (for the decoders/counters) xor2 : 2 (Full adder) and2 : 1 capture decoder.Result:

Conclusion :
112 total cells (excluding fill and tap cells)
And it's still bloated by the toolchain with
But can you do something this compact with the JTAG standard? And since each bit/stage does not require absolute synchronism or a tight timing, the clock network is relaxed and each register uses less space than a standard DFF.
Asynchronous circuits are frowned upon and notoriously prone to weird errors. After all, synchronous designs are much easier to analyse and get right. However the latter relies on the asumption of a magically simultaneous clock pulse that arrives everywhere at the same time. The ULSR does not assume this, in particular to make implementation more convenient: no clock tree synthesis, saving power and area. The ULSR runs slower the JTAG and requires more timing margin, but that's only a fair compromise.
One consequence is that a clock signal can drive only one of the synchronous gates like DFF, which must be chained, like below. This lets the Place&Route tools optimise for density without consideration for timing. Since only one DFF gets a clock signal, the setup & hold only depends on the host toggling the SD and SC pins slow enough, though there is ample margin at 1Mbps.

You can find these operations in the test/test.py script.
A more elaborate protocol can be designed on top of this, for example: addressing specific registers by counting the number of bits injected. Let your imagination go wild!
Use some Arduino for example, and play with the SD/SC signals. About 1us between each bit toggle is a good ballpark. An Arduino sketch will be provided someday, transcribing the code in test/test.py
5 leftover pins are connected to a Full Adder that you can test it with the scan chain through external wires. Have fun injecting errors to see if the scan chain can detect them!
| # | Input | Output | Bidirectional |
|---|---|---|---|
| 0 | I0 | O0 | SD |
| 1 | I1 | O1 | SC |
| 2 | I2 | O2 | DO |
| 3 | I3 | O3 | FA1 |
| 4 | I4 | O4 | FA2 |
| 5 | I5 | O5 | FA3 |
| 6 | I6 | O6 | FAS |
| 7 | I7 | O7 | FAC |