CPLD to expand IO

  1. 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?

  2. jcsd
  3. NoTime

    NoTime 1,568
    Science Advisor
    Homework Helper

    Usually additional GPIO just involves address decoding.
    I might think a small PLD would be sufficient for that.
    What are you trying to do?
  4. berkeman

    Staff: Mentor

    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:

  5. 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?

  6. berkeman

    Staff: Mentor

    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.
  7. 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?
  8. berkeman

    Staff: Mentor

    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.
  9. 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?
  10. berkeman

    Staff: Mentor

    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.
  11. 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?
  12. berkeman

    Staff: Mentor

    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.
    Last edited: Oct 13, 2006
  13. Yes, that makes perfect sense. Thank you so much for your help.
  14. 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?
  15. berkeman

    Staff: Mentor

    Excellent question -- good to see that you are thinking about this. In the real world, you cannot just bring an asynchronous signal into a synchronous clocked circuit, because the setup and hold requirements of the input flipflop may not be met. If the input changes right as the clock to the FF is changing (violating the setup requirement typically), then the FF can enter a metastable state, and the output can be anything (high, low, or wandering around). This metastable state persists for some amount of time, depending on the physical logic devices used, but it is usually less than a clock period for the system.

    So, to avoid using this metastable output directly, you want to use two FFs in series to "synchronize" an asynchronous input with your clocked logic. That way, even if the first FF goes metastable because of a timing violation, the output of the first FF will be stable by the next clock, at which point the timing of the second FF is met, and the output of the second FF can be used by the rest of the synchronous circuitry.

    So in your OP circuit, for each of the asynchronous inputs, you would have two FFs in series, being clocked by the system/CPLD clock. That makes two 8-bit input registers, with the outputs of the first register going into the inputs of the 2nd register, and the outputs of the 2nd register are what you would read from your uC.

    I don't have a good online pointer for the concept of synchronizing asynchronous digital signals, but it should be in your textbook, or you can probably find more info via google. BTW, this is one of the fundamental interview questions that we ask all candidates for positions in our digital design group, and we even ask our analog candidates this question. It's fundamental to designing circuits that work in the real world.
Know someone interested in this topic? Share this thead via email, Google+, Twitter, or Facebook

Have something to add?