Thursday, May 27, 2021

VIO GPIO Test IP Core and Design


A simple and frequent task, how to set and read some random FPGA pin for test purposes? Sure this can be done over JTAG. Even the free JTAG BUZZ can do this. Well if you manage to get it up and running of course. My own ToolZ can readout in standard version, and theoretically could force pin state too, but well this function is currently not exposed. So there is an option to create a VIO core and connect it to the pin(s) of interest. This is always doable and works, but you are pretty much bound to make a new project every time and need to recompile new bitstream what takes its time.

OK amazingly JTAG BUZZ worked on brief testing, it allows single pin monitoring and continuity testing. There seems to be no function to set a single pin to static value.

But we wanted something for FPGA, the idea is that we can create a ready made bitstreams that implement some sort of generic VIO to GPIO gateway that connects at once to all available FPGA IO pins. Done, the IP Core includes about 10 lines of significant source code total.

Startup provides the FPGA internal free running clock so we do not depend on any external clocks being present. VIO_GPIO provides read-back of all connected IO pin simultaneously, selecting one pin by its index. The selected pin can be made output and its value can be forced to 0 or 1. At the same time this one pin is read back, and also connected to frequency meter IP Core. So if there are external clocks connected to the FPGA then we can measure their frequency (using internal clock a reference). 

Does it work? First try out and indeed all works as intended!

Here out1 is value to be written to the indexed pin, out2 is direction control (1 is output), out0 is pin index. The frequency meter also works, if we change the indexed pin output with mouse very quickly, then the frequency meter can show 1 Hz of detected frequency.

This design would work on all Xilinx 7 series FPGA and SoC or newer devices. Pretty much anything that can be programmed with Vivado can be used.

The first design was created for Zynq 7014 CLG484 package, it would without modifications also work for CLG400 package. For 7020 the same design should be one time recompiled.

For the XDC file I used the boundary scan order for the pins, so it is possible to look up the PAD number from Xilinx BSDL file, and convert to the "index" in the design. It is also possible to get the index from the XDC file. If we use package different from that in the original design then only the BSDL flow works to determine the ball-index mapping.















Monday, May 10, 2021

Scriptable UART/I2C Terminal

The need for this tool did come from the test requirement for the CR00040 I2C module, there are four I2C devices onboard and all of them should be checked during factory testing.

A simple test terminal application was used as a starting point, the edit box for the transmit string was changed to a memo to enter "test script". All lines from the memo are sent to the serial port, one line at a time. Two special cases added, when the first char on line is "=" then UART is read and compared to a string with display output on mismatch. On mismatch global RESULT variable is set to false. First char "!" is interpreted as a request for a timed delay in milliseconds.

Adding and testing those new features did take about half a day. While most of the time was spent troubleshooting a really silly bug (wrong string length on transmit).

This is an example output of the scripting terminal. All four I2C devices on CR00040 are tested. The CO2 sensor factory test is initiated, and the result is read back after 10 seconds delay needed by the sensor.

After starting the test a result will be displayed depending on the results of the read string comparisons, if all matched, then OKAY is displayed (or FAILED if at least one comparison failed).

Please note that while this tool was developed for I2C testing using the UHSA USB-I2C adapter, the tool could be used for more generic UART testing. It basically sends and receives UART strings having zero knowledge about I2C coded in.