The Digilent Digital I/O 5 (DIO5), referred to by Digilent as both a System Board and a Peripheral Board, functions as a rapid development board featuring a Xilinx CoolRunner XCR3128 CPLD along with various I/O including switches, LEDs, and displays. It was designed to be interfaced with other Digilent system boards (such as an FPGA board) to expand the available I/O while working seamlessly with the main design software, and with the default factory set CPLD configuration, experimentation is given a head start.
Read on to learn more about the DIO5 and my experience of using it.
You can email me at james.boshikoopa@gmail.com
I bought from eBay a kit described as 'Digilent DIO5 Xilinx Coolrunner Development System' for just under £39, that supposedly was never used (since a couple of pins were bent on the DIO5 board it looks like the previous owner inserted it into another board and removed it in such a way that the pins became bent, however). The kit is contained in a plain white box with two stickers on the top, one of them reads:
Digilent DIO5
Rapid digital circuit implementation made easy
Full-featured I/O with Xilinx CoolRunner CPLD
www.digilentinc.com
The other:
Digilab Breadboard 1
Rapid digital circuit implementation made easy
Featuring Xilinx Spartan FPGAs
www.digilentinc.com
Noe: looking online, the kit was also available with just the DIO5 - stickers were placed on top of box to indicate what was included.
In the box is the DIO5 mainboard, two 'Digilab Breadboard 1' breadboards, and 'CoolRunner-II RealDigital CPLD Design Kit Programmable Logic Guide November 2003' (I don't know if the guide was originally included and was perhaps something the seller had obtained at another date).
Before going into detail about the DIO5 I'll first talk about the other items in the kit, starting with the 'Design Kit Programmable Logic Guide November 2003'. Interestingly, ‘xc9500xl’ is written on the front cover, perhaps because the CPLD was a recent release at the time. The guide consists of 190 pages and covers the history of programmable logic, along with Xilinx solutions, design software, implementation, design reference, and glossary of terms.
This appears to be a digital copy:
http://www.bitsavers.org/components/xilinx/Programmable_Logic_Design_Quick_Start_Handbook_2003.pdf
Next, on to the breadboard, of which the package is marked as 'Digilab BB1'. The breadboard PCB has written on it:
Digilab Breadboard 1
Copyright 2001, Digilent, Inc.
WWW.DIGILENT.CC
PB200011 DPBBN-AB-1 REV B
In the corners of the PCB are metal standoffs, and the actual breadboard is in the centre with what looks to be a (small) area to write something. On the left side are four 20x2 female connectors (two upright, other two laying flat). On the right side are four 20x2 male connectors (two upright, other two laying flat). All the connections are labelled. There are also red and white wires for VDD and GND respectively, connected to the breadboard.
On the back of the PCB is a grid of solder points.
The breadboard can be plugged into the DIO5, likely the breadboard is supposed to sit between the DIO5 and the FPGA board. Possibly multiple breadboard can be connected side-by-side since the connections are the same on both sides.
Let's move on to the DIO5 now, the DIO5 package has a sticker with 'Digital I/O 5' written on it. A screw post can be found in each corner of the PCB and on the board is written:
Digilab Digital I/O 5
Copyright 2003, Digilent Inc.
www.digilentinc.com
PB200028 Rev B
There is what looks to be an area to write on.
There two 20x2 male expansion connectors, two male headers with shunts, one male header without shunt, Xilinx CoolRunner XCR3128XL CPLD, 16x2 HD44780 character LCD, PS/2 port (mouse/keyboard), VGA port, 4-digit 7-segment red LED display, eight 2-way switches, 16 push buttons, and 16 LEDs.
On the back of the PCB it has a label with ‘C037204’ printed on it.
The DIO5 product page is available at:
https://digilent.com/reference/dio5/dio5
It has links for the schematic, reference manual, and the sell sheet (which is a brochure).
A direct link to the brochure:
https://digilent.com/reference/_media/dio5/dio5-brochure.pdf
A summary of the features outlined in the brochure follows:
XCR3128 CPLD
A 16x2 character LCD
A 4-digit seven segment display
16 individual LEDs in three different colours
16 button keypad
8 slide switches
3-bit VGA port
PS/2 mouse or keyboard port
Example applications:
I/O devices can be used to create a complete computer system around MicroBlaze
Any circuit where general-purpose I/O devices are needed
Can be used with a system board to partition designs across two programmable devices
Note that MicroBlaze is a 32-bit RISC soft processor core, which you can implement on an FPGA, for example.
The brochure also reveals that the DIO5 is compatible with the D2SB and D2FT boards.
The DIO5 reference manual direct link:
https://digilent.com/reference/_media/dio5/dio5_rm.pdf
I'll recount some of the important information from the reference manual to give more of an overview of the DIO5:
JTAG, system bus and clock on connector P1. Uncommitted I/O and VGA on connector P2.
Compatible with all versions of Xilinx ISE tools.
The CPLD on the DIO5 is configured during manufacturing with the project shown in Appendix 1.
DIO5 draws power from the system board.
The DIO5 board draws power from three pins on the 40-pin connectors: pin 37 supplies 3.3V; pin 39 provides system GND, and pin 40 supplies unregulated voltage (VU). Pin 40 (VU) is connected directly to an LM1117 5VDC LDO regulator on the DIO5. 5VDC is used by the LCD display and the PS/2 interface. The 3.3V supply is used to drive the CPLD and all other I/O devices on the board. During normal operation, the DIO5 consumes 10-20mA from the 5V supply, and 50-100mA from the 3.3V supply depending on how many LEDs are illuminated.
Jumper-shunts must be loaded on pins 1 and 2 of jumper blocks JP2 and JP3 on the DIO5 to include the CPLD in the scan chain, or across pins 2 and 3 to remove the CPLD from the scan chain.
Jumper position JP1 allows the JTAG signals on the CPLD to be reclaimed if they are inadvertently programmed as user I/O’s. Since the JTAG pins on the CPLD are used only for programming, this jumper block should not normally be loaded.
Signals from all I/O devices on the DIO5 are routed through the CPLD, with the exception of the VGA port (video data is too high bandwidth to pass through the CPLD).
Appendix 1 has the default CPLD configuration, which implements a bus-oriented, register-based interface that can be used by a system board to interact with the DIO5 board.
You can find the XCR3128XL datasheet at:
https://docs.amd.com/v/u/en-US/ds012
Some basic information about the CPLD from the datasheet:
128 macrocells
3000 usable gates
128 registers
3V ISP JTAG
108 user I/Os
5V tolerant I/O pins
1,000 erase/program cycles guaranteed
Of the FPGA boards I own the Digilent Xilinx XUP VIRTEX-II PRO appears to be compatible, which I'll cover in a separate section, but I figured it would be much easier to test the main features of the DIO5 using an Arduino, before interfacing with an FPGA. Due to the factory set CPLD configuration of the DIO5 you can quite easily use it with any system board by connecting to the DIO5's expansion connectors.
The datasheet for the XCR3128XL claims 5V tolerant I/O pins so we can use a standard Arduino, of course you can use compatible boards and indeed I used an Arduino Uno clone, DCcduino Uno. Since we need to supply between 6V and 12V to the VU pin of the DIO5 it makes sense to power the Arduino from a higher voltage via the barrel jack connector and use that same supply for the DIO5 VU pin by connecting it to the Arduino’s VIN pin. We can still connect the Arduino to a computer via USB to program it as the Arduino will automatically select the power source to power itself so there is no conflict.
I'll get to the final test Arduino code I wrote shortly but just to mention that initially I made a short test sketch and after programming the Arduino I connected just the power connections - VU, GND, and VCC33 - to the DIO5. I powered the Arduino with 7V through the barrel jack connector from my variable power supply and saw that the DIO5’s 7-segment display had a lit ‘0’ on the left side and the LCD showed ‘blocks’ on the top row. I measured the 5V regulated voltage on the DIO5 as 5V, a good sign the board was connected and powered correctly.
Next, I wrote code to turn LED0 on, note that the individual LEDs are inverted in the CPLD configuration, so even though they have a 3.3V common, logic 1 turns the LED on. Note also LCLK isn't need to turn the discrete LEDs on/off.
The final Arduino sketch, DIO5_test.ino, is available for download from the bottom of the page and demonstrates most of the features of the DIO5 - it is rough code I quickly put together that I'm sure can be greatly improved. I purposely didn't write directly to the pin ports to make the code more readable and portable to other Arduino-like boards. It doesn't test the VGA and PS/2 connections, but feel free to add to the sketch while consulting the DIO5 reference manual to add support for VGA and PS/2.
The hardware connections are described toward the start of the sketch, follow carefully and double check your wiring before applying power.
In setup() we initialize the I/O and set the DIO5 control (WE, OE, CS) initial state, then we enable a 256Hz clock pulse on LCLK using the TimerOne library so we don't have to worry about producing the pulse directly ourselves. LCLK is required for the 7-segment LED display and for button debouncing. Lastly, in setup(), doDemo() is called, which shows off the DIO5 features.
The doDemo() function is broken down into doDemoLED() which manipulates the discrete LEDs, doDemo7SegLED() which displays numbers on the 7-segment LED display, and doDemoLCD() which displays information on the LCD.
Let's now look at the demo subfunctions in more detail:
doDemoLED()
Writes to the DIO5 address bus '0' to select the first eight LEDs (0-7) - see the reference manual page 2 to see the memory map on the right-hand side of the page. Even though the DIO5 has six address lines only three are needed. Function sequenceLED() is then run, which starts by calling clearData(), which ensures the DIO5 data lines are all set to LOW.
Back in sequenceLED() a loop begins which turns on each data bit in turn, causing the LEDs to switch on in turn. After setting a data line to HIGH we call doWrite() which manipulates DIO5 control signals WE and CS so that the CPLD updates its state and switches the LEDs on. After doWrite() a delay is added using delay() and passing delayLED, an int whose values you can modify to affect the timing of the LED demonstrations. Lastly, in sequenceLED() the data bits are set LOW using clearData(), so they are in the correct state for the next time sequenceLED() is called.
Returning to doDemoLED(), we set the address to '1' to select LEDs 8-F and then sequenceLED() is called again to switch the second lot of LEDs on in the same manner as the first eight, so in the end all 16 LEDs are lit.
doDemo7SegLED()
At the start of the function the DIO5 address is set to '2' to access the first two digits of the 7-segment LED display and then we call writeNybble() first passing true, second time false, to update digits one and two. In function writeNybble() a loop of 16 iterations is set up since we want to display 0-9 and A-F on the digits. The input parameter nybbleLow let's first clear the appropriate DIO5 data pins since there are two display digits in a byte. Then we can set the four data bits for the digit we're currently writing to based on the number (represented by c) that currently needs to be displayed. Once the data is set doWrite() is called to update the CPLD and delay() ensures the digits don't change too quickly.
Once we have updated the first two digits, in doDemo7SegLED() the address is set to '3' to select digits three and four, the data bits are cleared using clearData(), and the last two digits are updated using writeNybble() as before. The effect is that each digit will show an increasing hex value in turn.
doDemoLCD()
In doDemoLCD() the DIO5 address is set to '4' to write commands to it, this works because the LCD's RS (Register Select) pin is connected to ADR0. Next, the data bits are cleared using clearData(). Since the LCD is HD44780 compatible we have to send it commands which we do so by setting various data bits and then calling doWrite() so that the LCD is updated. Read the reference manual page 4 or a HD44780 datasheet if you aren't familiar with how the LCD module works.
To use the LCD, we first send the Function set instruction to enable two lines and 8-bit interface, then the Display control instruction to switch the display on, and then the Clear display instruction. We then output a status string ("Switch status:") using function outStrLCD() which starts by setting the address to '5', which lets us send character data to the LCD. After a delay just to be sure the LCD is ready, we enter a loop to output each character of the input string which in turn sets the appropriate data bits reflecting the binary value of the character. Another delay is used, then doWrite() updates the LCD, and another delay before the next iteration of the loop.
Back in doDemoLCD() the address is set to '4' again so we can send the DDRAM address instruction to start at the beginning of line 2 (position 0x40) of the LCD, then we call outStrLCD() to display buttStr ("B=0x"), after setting address to '4' we use DDRAM address instruction to move along the second line to position 0x49 so we can display switchStr (" S=0x"). I don't know why I added the space at the beginning of the string, it didn't turn out necessary but it works regardless.
So far on the second line of the display we have:
B=0x S=0x
We then enter a non-terminating while() loop in which we start by setting the DIO5 address to '1' to access buttons 8-F and we read in the button state using doRead(), which sets all data pins to inputs using setDataInput() and takes DIO5 CS and OE low so that the CPLD places the button state on the data pins. Then we can read in the data bits and set variable valueIn accordingly by making use of the bitWrite() function. After that we take CS and OE high, return the data pins to outputs using setDataOutput(), and return valueIn.
Returning to doDemoLCD() we have to convert the return value of doRead() to an ASCII value we can send to the LCD, which we do so using convByteToHexASCII(). In that function we split the input value valIn into lower and upper nybbles valDigitL and valDigitU since we are dealing with a 2 digit hex value. To convert the two nybbles into ASCII values we start by adding 0x30, which is the ASCII value for '0'. Then we check if the nybble is A - F and if so, we add 0x7, and since we know the value is at least 0xA, that will also be added, resulting in value of 0x41 for 'A', 0x42 for 'B', etc.
In doDemoLCD() we repeat the same process to read buttons 0-7 using DIO5 address '0' and convert to ASCII and then move to position 0x44 so we can use outStrLCD() to display the button state after "B=0x".
For the slide switches we use DIO5 address '2' and use the same technique as with the buttons to read the state and display on the LCD but at position 0x4E, after "S=0x".
Thus we will have displayed on the second line of the LCD:
B=0x0000 S=0x00
If all the switches and buttons were off. Pressing a button or sliding a switch to the on position will cause the corresponding bit to be displayed as a '1'.
All content of this and related pages is copyright (c) James S. 2024