FPGA - Is it possible to change the pin direction/type during runtime?

On an FPGA, is it possible to mimic the behaviour of something like an Arduino, whereby the code running on the chip is able to designate a pin as an input or output?

Let's say the FPGA is configured as a processor. Further, lets say that we have three registers designated for controlling IO pins much like the Arduino equivalents:

Each port is controlled by three registers... The DDR register, determines whether the pin is an INPUT or OUTPUT. The PORT register controls whether the pin is HIGH or LOW, and the PIN register reads the state of INPUT pins set to input with pinMode().

How can you get the FPGA to use a register (like DDR) to change the direction of the pin, based on what the running program updates the register to? (By running program, I mean the program running on the processor the FPGA has been configured as).

I'm not sure if this is possible given how during pin assignment for synthesis you have to specify the pin direction. But hopefully I'm wrong? Could this be done somehow by using 'bidirectional' pin mode?

• Of course it is possible. There is inout type pin in Verilog, for this purpose. The logic of how it is controlled is up to you. – Eugene Sh. Feb 16 '18 at 22:18
• And I’ve tristated an output completely on the fly when designing part of a PLL. – Andy aka Feb 16 '18 at 22:20
• If you define the pin as bi-directional, it will always be receiving the state of the pin. Your FPGA code gets to decide whether to drive the pin. If it doesn't, the state is determined externally and you can consider the pin and input. If the FPGA enables the output driver, then it is an output and the state is determined by what the FPGA drives it with. Just make sure that the pin is only driven by one source at a time. – crj11 Feb 16 '18 at 22:22
• Yes. FPGAs and CPLDs almost all have tri-state pin drivers and pin input buffers. All are connected to the internal logic circuit array and can be driven or used by that circuitry as you like. Have a look at the I/O pin circuits in a typical FPGA datasheet. Try the datasheet for a Xilinx Spartan-3E. – TonyM Feb 16 '18 at 22:23
• @crj11 You've written your answer in the wrong place. Now it can not be vetted by the community or accepted as correct. – pipe Feb 16 '18 at 23:18

The answer is in most cases, yes. The GPIO pins on most FPGAs will be bidirectional, just like those on an ATMega (Arduino board MCU).

For an FPGA, you simply need to describe the logic for a tri-state buffer to be able to control the direction. This is quite simple in most cases.

To give an example, let's assume Verilog:

module tristate (
inout ioPin, //inout means bidirectional

input toPin,     //Data to io pin (i.e. PORT)
input direction, //Direction control (i.e. DDR)
output fromPin   //Data from io pin (i.e. PIN)
);

localparam INPUT = 1'b0;
assign ioPin = (direction == INPUT) ? 1'bz : toPin;
assign fromPin = ioPin;

endmodule


From the above code, the synthesis tools would infer a tristate buffer with a control pin. I've labelled the ports with the names of the corresponding ATMega registers. The ioPin signal connects to the outside world, and is declared as inout meaning bidirectional.

When the direction pin is high, then ioPin will be an output, driven with the value of toPin. When direction is low, then ioPin will be an input (driven by high-z). The fromPin signal will always reflect the value of ioPin regardless of whether it is an input or output.

You can make similar constructs in VHDL and schematic/netlist entry methods.

Additionally many FPGA manufactures will provide primitive elements for bidirectional buffers if you prefer to not rely on synthesis guesswork.

• Are there any drawbacks to also placing a tristate on the input side? I.e. fromPin = (direction == OUTPUT) ? 1'bz : ioPin – Jet Blue Feb 16 '18 at 22:49
• Also, by not having a buffer on the input side, would you not end up with a short circuit of sorts? Say you write 1/high to the io pin. You would simultaneously also be reading the same 1/high you are writing. So at the same time you are sourcing you are also sinking? – Jet Blue Feb 16 '18 at 23:25
• Well, fromPin is driving internal logic, so you can't make it tristate on most devices even if you wanted to (most FPGAs don't support internal tristate). And yes, you would expect to read back the same level that you're writing, unless there is an external short to ground or something. – alex.forencich Feb 16 '18 at 23:47