# CPLD to expand IO

by j777
Tags: cpld, expand
 P: 148 Hi, I would like to use a CPLD to add additional GPIO to a microcontroller. I've never used a CPLD before so I'm in search of a good book that will get me up to speed. Does anybody have any recommendations on books or other applicable material? Thanks
 Sci Advisor HW Helper P: 1,571 Usually additional GPIO just involves address decoding. I might think a small PLD would be sufficient for that. What are you trying to do?
 Mentor P: 41,122 As NoTime says, you might be able to use a smaller PAL instead of a CPLD, but even the 32-cell CPLDs are pretty simple to use. I like the Vantis Mach-3 series, because they have nice wide minterm capability. Here is the Application Note page at Lattice Semiconductor's website: http://www.latticesemi.com/dynamic/index.cfm?fuseaction=view_category&document_type=31&jsessionid=ba30f8f9 aba5x$3F$3F\$
 P: 148 CPLD to expand IO Thanks for the suggesstions but I'm looking at using an Altera MAXII CPLD because I would like to add 2 8bit input ports (Port A and B), 2 8bit output ports (Port C and D, 2 8bit GPIO ports (Port E and F), address decoding for these ports, and possibly an interface to a serial ADC. This is my first time using a CPLD (or any PLD for that matter) so I have a nice little adventure ahead of me. The CPLD is attached to an 8bit multiplexed bus with ALE, RD, and WR strobes. So far I have the CPLD latch the address from the bus and use tri-state buffers to read ports A and B and write to ports C and D. A latch is also used on ports C and D to latch the output values from the buffer. If I want to be able to read ports C and D is it as simple as using an additional tri-state buffer per port to put the latched output values onto the data bus? Or is there a better way to do this? The 2 GPIO ports are to include an 8bit data direction register per port that allows for each port pin to be configured as either an input or an output. A write to the port should only change the values of pins configured as outputs and all pins should be able to be read. Does anybody have any ideas on the best way to implement this? Thanks
 Mentor P: 41,122 Everything you mention is very do-able. You will want to have some number of address lines go into the part, and use those to select among the various registers and functions you describe. Some of the registers will be the control registers (like for the pin direction configuration you mention), and others will be the input and output ports themselves. This technique is called memory-mapped IO, and is common in microcontroller (uC) circuits. You decode a range of addresses, and use those addresses to select which register or function you are working with in the CPLD.
 P: 148 I understand the concept of memory mapped IO but what I really need is some guidance on how to implement the logic inside the CPLD to perform what I described above. What I'm really stuck on is how to implement the data direction registers. Actually maintaining the values for one of these registers is not a problem for me (decoding the address and doing read/write to correct register) instead its the association between a data direction register (DDR) and its port that I'm struggling with. For example if a pin is changed from an input to an output in the DDR the corresponding port pin should be changed to a default output value. Can somebody give me some help with the logic involved in this type of thing?
 Mentor P: 41,122 What language are you coding the CPLD in? Even if you're just using ABEL-HDL, there are constructs that you can use like if-then statements. If you use VHDL or Verilog, you get even more abstract statements that you can use to intuitively code up mulplexers and such.
 P: 148 I'm using Verilog. I must let you know that my skill level in combinational logic is -beginner-. My real struggle here is the logic. Can you give me a little guidance?
 Mentor P: 41,122 What reference do you have for learning CPLD design with Verilog? Does it cover instantiating registers and implementing MUXes? For the thing you want to do with switchable IO pin directions, you will have an input register with a Tri-statable output register connected to the same pins. Each output flop will have an individual Tri-state enable, and that will be driven by the pin direction register. So even if it is configured as an output, you can still read back that output value via the input register.
 P: 148 Ok, thank you...thats exactly the type of response I was looking for. Now I just have to try to wrap my head around it.... :) Can you explain the last sentence in more detail?
Mentor
P: 41,122
 Quote by j777 Can you explain the last sentence in more detail?
 Quote by berkeman Each output flop will have an individual Tri-state enable, and that will be driven by the pin direction register. So even if it is configured as an output, you can still read back that output value via the input register.
Let's say register 0 is the direction control register, register 1 is the input register, and register 2 is the output register. You will need to decide how you want to handle the input register -- whether you just read the inputs directly and transparently, or whether you want to store the external inputs on each CPLD clock, and even if you want to synchronize them (which you should with asynchronous inputs to avoid metastability problems). Let's say you just decide to read the inputs transparently for now.

So that means register 0 and 2 each consist of 8 flip-flops apiece, which are written by your uC to your CPLD when the correct addresses are decoded on write cycles. When register 1 is decoded on a read cycle, the 8 external inputs are driven onto the uC data bus.

Let's say that the bits in register 0 are active high to enable the tri-state outputs of register 2. So if you write reg0 <-- 0x0F, that enables the low 4 bits of reg2 as outputs, and leaves the high 4 bits of reg2 tri-stated. The outputs of reg2 are connected to your 8 bi-directional IO lines, so any lines that are enabled as outputs (by the data in reg0) will have those outputs driven by the data in reg2. Any other bits that are tri-stated can be used as inputs. And when you read reg1 to read the bidirectional IO byte, you see your own data on any lines that you are driving, and the external data on any lines that you are not driving.

Makes sense?

EDIT -- fixed some reg2/3 mixups in numbering.
 P: 148 Yes, that makes perfect sense. Thank you so much for your help.
 P: 148 Ok, I've implemented what you have described with the inputs being read directly. Lastnight I was thinking about the inputs and the possible metastability problems and I remembered you had mentioned something about it. What is the difference between storing the inputs on each CPLD clock and synchronizing them? Wouldn't storing them on each CPLD clock synchronize them?