Electronic – FPGA – Is it possible to change the pin direction/type during runtime

fpgagpiopins

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?

Best Answer

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.