You can move logic that is normally implemented with CLBs to IOBs. By moving logic from CLBs to IOBs, additional logic can be implemented in the available CLBs. Using IOBs also improves design performance by increasing the number of available routing resources.
The XC4000 and Spartan devices have different IOB functions. The following sections provide a general description of the IOB function in XC4000E/EX/XLA/XL/XV and Spartan devices. A description of how to manually implement additional I/O features is also provided.
You can configure XC4000E/EX/XLA/XL/XV and Spartan IOBs as input, output, or bidirectional signals. You can also specify pull-up or pull-down resistors, independent of the pin usage.
These various buffer and I/O structures can be inferred from commands executed in a script or in your synthesis tool. The Set Port Is Pad (or equivalent) command in conjunction with the Insert Pads (or equivalent) command creates the appropriate buffer structure according to the direction of the specified port in the HDL code. You can add attributes to these commands to further control pull-up, pull-down, and clock buffer insertion, as well as slew-rate control. Some tools operate on I/Os by selecting a chip level (inserts I/O) or module level (no I/O) synthesis. Also, you can add synthesis tool attributes, such as BUFFER_SIG, to ports in your VHDL code to control insertion of I/Os.
The buffered input signal that drives the data input of a storage element can be configured as either a flip-flop or a latch. Additionally, the buffered signal can be used in conjunction with the input flip-flop or latch, or without the register.
To avoid external hold-time requirements, IOB input flip-flops and latches have a delay block between the external pin and the D input. You can remove this default delay by instantiating a flip-flop or latch with a NODELAY attribute. The NODELAY attribute decreases the setup-time requirement and introduces a small hold time.
If an IOB or register is instantiated in your HDL code, you may not be able to use the Set Port Is Pad (or equivalent) command on that port. Doing so may automatically infer a buffer on that port and create an invalid double-buffer structure. This varies with the tool you are using. Check with your synthesis vendor to see if partial instantiation interferes with automatic I/O insertion or the use of IOB registers.
Registers that connect to an input or output pad and require a Direct Clear or Preset pin are not implemented by the synthesis tool in the IOB. The VHDL emulation of GSR or GR on these registers prevents them from being pulled into the IOB. The VHDL emulation of GSR/GR through direct clear or preset pins is described in the Simulating Your Design chapter. If GSR/GR behavior is not completely described, automatic inferencing of GSR/GR does not occur. In this case, instantiate STARTBUF in VHDL, and fully describe the GSR/GR behavior except for registers that you want in the IOB. In VHDL, these registers do not initialize pre-route, but do indicate X's until the first data is registered. However, they do initialize properly during back-annotation. Verilog models initialize properly and do not interfere with the automatic use of IOB registers instead of CLB registers.
The output signal that drives the programmable tristate output buffer can be a registered or a direct output. The register is a positive-edge triggered flip-flop and the clock polarity can be inverted inside the IOB. (Xilinx software automatically optimizes any inverters into the IOB.) The XC4000 and Spartan output buffers can sink 12 mA. Two adjacent outputs can be inter-connected externally to sink up to 24mA.
Note: Most FPGA synthesis tools can optimize flip-flops attached to output pads into the IOB. However, some of these tools cannot optimize flip-flops into an IOB configured as a bidirectional pad. Refer to your synthesis tool documentation for more information.
Refer to your synthesis tool documentation for information on configuring I/O's, including how to control slew rate.
XC4000 and Spartan devices have programmable pull-up and pull-down resistors available in the I/O regardless of whether it is configured as an input, output, or bi-directional I/O. By default, all unused IOBs are configured as an input with a pull-up resistor. The value of the pull-ups and pull-downs vary depending on operating conditions and device process variances but should be approximately 50 K Ohms to 100 K Ohms. If a more precise value is required, use an external resistor. Refer to your synthesis tool documentation for information on how to specify internal pull-up or pull-down I/O resistors.
A function added to XC4000EX/XLA/XL/XV families is a two input multiplexer connected to the IOB output allowing the output clock to select either the output data or the IOB clock enable as the output pad. This allows you to share output pins between two signals, effectively doubling the number of device outputs without requiring a larger device or package. Additionally, this multiplexer can be configured as a two-input function generator allowing you to implement any 2-input logic function in the IOB thus freeing up additional logic resources in the device and allowing for very fast pin-to-pin data paths.
To use the output multiplexer (OMUX), you must instantiate it in your code. See the following VHDL and Verilog examples. Instantiation of the other types of two-input output primitives (such as OAND2, OOR2, and OXOR2) are similar to these examples.
Note: Since the OMUX uses the IOB output clock and clock enable routing structures, the output flip-flop (OFD) can not be used within the same IOB. The input flip-flop (IFD) can be used if the clock enable is not used.
------------------------------------------
-- OMUX_EXAMPLE.VHD --
-- Example of OMUX instantiation --
-- For an XC4000EX/XL/XV device --
-- HDL Synthesis Design Guide for FPGAs --
-- August 1997 --
------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
entity omux_example is
port (DATA_IN: in STD_LOGIC_VECTOR (1 downto 0);
SEL: in STD_LOGIC;
DATA_OUT: out STD_LOGIC);
end omux_example;
architecture XILINX of omux_example is
component OMUX2
port (D0, D1, S0 : in STD_LOGIC;
O : out STD_LOGIC);
end component;
begin
DUEL_OUT: OMUX2 port map (O=>DATA_OUT,
D0=>DATA_IN(0), D1=>DATA_IN(1), S0=>SEL);
end XILINX;
//////////////////////////////////////////
// OMUX_EXAMPLE.V //
// Example of instantiating an OMUX2 //
// in an XC4000EX/XL IOB //
// HDL Synthesis Design Guide for FPGAs //
// August 1997 //
//////////////////////////////////////////
module omux_example (DATA_IN, SEL, DATA_OUT) ;
input [1:0] DATA_IN ;
input SEL ;
output DATA_OUT ;
OMUX2 DUEL_OUT (.O(DATA_OUT), .D0(DATA_IN[0]),
.D1(DATA_IN[1]), .S0(SEL));
endmodule
XC5200 IOBs consist of an input buffer and an output buffer that can be configured as an input, output, or bi-directional I/O. The structure of the XC5200 is similar to the XC4000 IOB except the XC5200 does not contain a register/latch. The XC5200 IOB has a programmable pull-up or pull-down resistor, and two slew rate control modes (Fast and Slow) to minimize bus transients. The input buffer can be globally configured to TTL or CMOS levels, and the output buffer can sink or source 8.0 mA.
I/O buffer structures (as with the XC4000 IOBs) can be inferred from your synthesis tool script with the Set Port Is Pad (or equivalent) command in conjunction with the Insert Pads (or equivalent) command. Controlling pull-up and pull-down insertion and slew rate control are performed as previously described for the XC4000 IOB.
The XC5200 IOB also contains a delay element so that an input signal that is directly registered or latched can have a guaranteed zero hold time at the expense of a longer setup time. You can disable this (equivalent to NODELAY in XC4000) by instantiating an IBUF_F buffer for that input port. This only needs to be done for ports that connect directly to the D input of a register in which a hold time can be tolerated.
You can create bi-directional I/O with one or a combination of the following methods.
Xilinx FPGA IOBs consist of a direct input path into the FPGA through an input buffer (IBUF) and an output path to the FPGA pad through a tri-stated buffer (OBUFT). The input path can be registered or latched; the output path can be registered. If you instantiate or behaviorally describe the I/O, you must describe this bi-directional path in two steps. First, describe an input path from the declared INOUT port to a logic function or register. Second, describe an output path from an internal signal or function in your code to a tri-stated output with a tri-state control signal that can be mapped to an OBUFT.
You should always describe the I/O path at the top level of your code. If the I/O path is described in a lower level module, your synthesis tool may incorrectly create the I/O structure.
This section includes VHDL and Verilog examples that show how to infer a bi-directional I/O. In these examples, the input path is latched by a CLB latch that is gated by the active high READ_WRITE signal.
The output consists of two latched outputs with an AND and OR, and connected to a described tri-state buffer. The active low READ_WRITE signal enables the tri-state gate.
-------------------------------------------------------
-- BIDIR_INFER.VHD --
-- Example of inferring a Bi-directional pin --
-- August 1997 --
-------------------------------------------------------
Library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity bidir_infer is
port (DATA : inout STD_LOGIC_VECTOR(1 downto 0);
READ_WRITE : in STD_LOGIC);
end bidir_infer;
architecture XILINX of bidir_infer is
signal LATCH_OUT : STD_LOGIC_VECTOR(1 downto 0);
begin
process(READ_WRITE, DATA)
begin
if (READ_WRITE = '1') then
LATCH_OUT <= DATA;
end if;
end process;
process(READ_WRITE, LATCH_OUT)
begin
if (READ_WRITE = '0') then
DATA(0) <= LATCH_OUT(0) and LATCH_OUT(1);
DATA(1) <= LATCH_OUT(0) or LATCH_OUT(1);
else
DATA(0) <= 'Z';
DATA(1) <= 'Z';
end if;
end process;
end XILINX;
///////////////////////////////////////////////////////////////////
// BIDIR_INFER.V Version 1.1 //
// This is an example of an inference of a bi-directional signal. //
// Note: Logic description of port should always be on top-level //
// code when using Synopsys Compiler and verilog. //
// March 1998 //
////////////////////////////////////////////////////////////////////
module bidir_infer (DATA, READ_WRITE);
input READ_WRITE ;
inout [1:0] DATA ;
reg [1:0] LATCH_OUT ;
always @ (READ_WRITE or DATA)
begin
if (READ_WRITE == 1'b1)
LATCH_OUT <= DATA;
end
assign DATA[0] = READ_WRITE ? 1'bZ : (LATCH_OUT[0] & LATCH_OUT[1]);
assign DATA[1] = READ_WRITE ? 1'bZ : (LATCH_OUT[0] | LATCH_OUT[1]);
endmodule
Instantiating the bi-directional I/O gives you more control over the implementation of the circuit; however, as a result, your code is more architecture-specific and usually more verbose. The VHDL and Verilog examples in this section are identical to the examples in the Inferring Bi-directional I/O section; however, since there is more control over the implementation, an input latch is specified rather than the CLB latch inferred in the previous examples. The following examples are a more efficient implementation of the same circuit.
When instantiating I/O primitives, do not specify the Set Port Is Pad (or equivalent) command on the instantiated ports to prevent the I/O buffers from being inferred by your synthesis tool. This precaution also prevents the creation of an illegal structure.
-----------------------------------
-- BIDIR_INSTANTIATE.VHD --
-- Example of an instantiation --
-- of a Bi-directional pin --
-- August 1997 --
-----------------------------------
Library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity bidir_instantiate is
port (DATA : inout STD_LOGIC_VECTOR(1 downto 0);
READ_WRITE : in STD_LOGIC);
end bidir_instantiate;
architecture XILINX of bidir_instantiate is
signal LATCH_OUT : STD_LOGIC_VECTOR(1 downto 0);
signal DATA_OUT : STD_LOGIC_VECTOR(1 downto 0);
signal GATE : STD_LOGIC;
component ILD_1
port (D, G : in STD_LOGIC;
Q : out STD_LOGIC);
end component;
component OBUFT_S
port (I, T : in STD_LOGIC;
O : out STD_LOGIC);
end component;
begin
DATA_OUT(0) <= LATCH_OUT(0) and LATCH_OUT(1);
DATA_OUT(1) <= LATCH_OUT(0) or LATCH_OUT(1);
GATE <= not READ_WRITE;
INPUT_PATH_0 : ILD_1
port map (D => DATA(0), G => GATE,
Q => LATCH_OUT(0));
INPUT_PATH_1 : ILD_1
port map (D => DATA(1), G => GATE,
Q => LATCH_OUT(1));
OUPUT_PATH_0 : OBUFT_S
port map (I => DATA_OUT(0), T => READ_WRITE,
O => DATA(0));
OUPUT_PATH_1 : OBUFT_S
port map (I => DATA_OUT(1), T => READ_WRITE,
O => DATA(1));
end XILINX;
////////////////////////////////////////////
// BIDIR_INSTANTIATE.V //
// This is an example of an instantiation //
// of a bi-directional port. //
// August 1997 //
////////////////////////////////////////////
module bidir_instantiate (DATA, READ_WRITE);
input READ_WRITE ;
inout [1:0] DATA ;
reg [1:0] LATCH_OUT ;
wire [1:0] DATA_OUT ;
wire GATE ;
assign GATE = ~READ_WRITE;
assign DATA_OUT[0] = LATCH_OUT[0] & LATCH_OUT[1];
assign DATA_OUT[1] = LATCH_OUT[0] | LATCH_OUT[1];
// I/O primitive instantiation
ILD_1 INPUT_PATH_0 (.Q(LATCH_OUT[0]), .D(DATA[0]), .G(GATE));
ILD_1 INPUT_PATH_1 (.Q(LATCH_OUT[1]), .D(DATA[1]), .G(GATE));
OBUFT_S OUPUT_PATH_0 (.O(DATA[0]), .I(DATA_OUT[0]), .T(READ_WRITE));
OBUFT_S OUPUT_PATH_1 (.O(DATA[1]), .I(DATA_OUT[1]), .T(READ_WRITE));
endmodule
You can use LogiBLOX to create I/O structures in an FPGA. LogiBLOX gives you the same control as instantiating I/O primitives, and is usually less verbose. LogiBLOX is especially useful for bused I/O ports.
Note: Refer to the Using LogiBLOX in HDL Designs section section, for details on creating, instantiating, and compiling LogiBLOX modules.
Do not use the Set Port Is Pad (or equivalent) command on LogiBLOX-created ports. Also, when designing with Verilog, you must issue a Remove Design or equivalent command before writing out the .xnf files from your synthesis tool.
The following VHDL and Verilog examples show how to instantiate bi-directional I/O created with LogiBLOX. These examples produce the same results as the examples in the Instantiating Bi-directional I/O section.
---------------------------------------
-- BIDIR_LOGIBLOX.VHD --
-- Example of using LogiBLOX --
-- to create a Bi-directional port --
-- August 1997 --
---------------------------------------
------------------------------------------------------
-- LogiBLOX BIDI Module "bidir_io_from_lb"
-- Created by LogiBLOX version M1.3.7
-- on Mon Sep 8 13:14:02 1997
-- Attributes
-- MODTYPE = BIDI
-- BUS_WIDTH = 2
-- IN_TYPE = LATCH
-- OUT_TYPE = TRI
------------------------------------------------------
Library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity bidir_logiblox is
port (DATA : inout STD_LOGIC_VECTOR(1 downto 0);
READ_WRITE : in STD_LOGIC);
end bidir_logiblox;
architecture XILINX of bidir_logiblox is
signal LATCH_OUT : STD_LOGIC_VECTOR(1 downto 0);
signal DATA_OUT : STD_LOGIC_VECTOR(1 downto 0);
----------------------------------------------------
-- Component Declaration
----------------------------------------------------
component bidir_io_from_lb
PORT( O: IN STD_LOGIC_VECTOR(1 DOWNTO 0);
OE: IN STD_LOGIC;
IGATE: IN STD_LOGIC;
IQ: OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
P: INOUT STD_LOGIC_VECTOR(1 DOWNTO 0));
end component;
begin
DATA_OUT(0) <= LATCH_OUT(0) and LATCH_OUT(1);
DATA_OUT(1) <= LATCH_OUT(0) or LATCH_OUT(1);
----------------------------------------------------
-- Component Instantiation
----------------------------------------------------
BIDIR_BUSSED_PORT : bidir_io_from_lb
port map (O => DATA_OUT, OE => READ_WRITE,
IGATE => READ_WRITE, IQ => LATCH_OUT, P => DATA);
end XILINX;
///////////////////////////////////////////
// BIDIR_LOGIBLOX.V //
// This is an example of using LogiBLOX //
// to create a bi-directional port. //
// August 1997 //
///////////////////////////////////////////
//----------------------------------------------------
// LogiBLOX BIDI Module "bidir_io_from_lb"
// Created by LogiBLOX version M1.3.7
// on Mon Sep 8 17:10:15 1997
// Attributes
// MODTYPE = BIDI
// BUS_WIDTH = 2
// IN_TYPE = LATCH
// OUT_TYPE = TRI
//----------------------------------------------------
module bidir_logiblox (DATA, READ_WRITE);
input READ_WRITE ;
inout [1:0] DATA ;
reg [1:0] LATCH_OUT ;
wire [1:0] DATA_OUT ;
assign DATA_OUT[0] = LATCH_OUT[0] & LATCH_OUT[1];
assign DATA_OUT[1] = LATCH_OUT[0] | LATCH_OUT[1];
// LogiBLOX instantiation
bidir_io_from_lb BIDIR_BUSSED_PORT
( .O(DATA_OUT), .OE(READ_WRITE), .P(DATA),
.IQ(LATCH_OUT), .IGATE(READ_WRITE));
endmodule
module bidir_io_from_lb (O, OE, P, IQ, IGATE);
input [1:0] O;
input OE;
input IGATE;
inout [1:0] P;
output [1:0] IQ;
endmodule
Although Xilinx recommends allowing the software to select pin locations to ensure the best possible pin placement in terms of design timing and routing resources, sometimes you must define the pad locations prior to placement and routing. You can assign pad locations either from your synthesis tool's script prior to writing out the netlist file, or from a User Constraints File (UCF). Use one or the other method, but not both. Refer to your synthesis tool documentation for the correct syntax for configuring your I/O with the PLOC property. Also, refer to The Programmable Logic Data Book or the Xilinx Web site (http://support.xilinx.com) for the pad locations for your device and package.
Note: XC5200 devices do not have input and output flip-flops.
IOBs contain an input register or latch and an output register. IOB inputs can be register or latch inputs as well as direct inputs to the device array. Registers without a direct reset or set function can be moved into IOBs. Moving registers or latches into IOBs may reduce the number of CLBs used and decreases the routing congestion. In addition, moving input registers and latches into the IOB reduces the external setup time, as shown in the following figure.
Although moving output registers into the IOB may increase the internal setup time, it may reduce the clock-to-output delay, as shown in this figure. Most FPGA synthesis tools automatically move registers into IOBs if the Preset, Clear, and Clock Enable pins are not used.
Use the -pr (pack registers) option when running MAP. The -pr {i | o | b} (input | output | both) option specifies to the MAP program to move registers into IOBs under the following circumstances.
In some package/device pairs, not all pads are bonded to a package pin. You can use these unbonded IOBs and the flip-flops inside them in your design by instantiating them in the HDL code. You can implement shift registers with these unbonded IOBs. The VHDL and Verilog examples in this section show how to instantiate unbonded IOB flip-flops in a 4-bit shift register in an XC4000 device.
Note: The synthesis tool compilers cannot infer unbonded primitives. Refer to your synthesis tool documentation for a list of library primitives that can be used for instantiations.
-------------------------------------------------
-- UNBONDED_IO.VHD Version 1.0 --
-- XC4000 LCA has unbonded IOBs which have --
-- storage elements that can be used to build --
-- shift registers. --
-- Below is a 4-bit Shift Register using --
-- Unbonded IOB Flip Flops --
-- Xilinx HDL Synthesis Design Guide for FPGAs --
-- May 1997 --
-------------------------------------------------
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity unbonded_io is
port (A, B: in STD_LOGIC;
CLK: in STD_LOGIC;
Q_OUT: out STD_LOGIC);
end unbonded_io;
architecture XILINX of unbonded_io is
component IFD_U -- Unbonded Input FF with INIT=Reset
port (Q: out std_logic;
D, C: in std_logic);
end component;
component IFDI_U -- Unbonded Input FF with INIT=Set
port (Q: out std_logic;
D, C: in std_logic);
end component;
component OFD_U -- Unbonded Output FF with INIT=Reset
port (Q: out std_logic;
D, C: in std_logic);
end component;
component OFDI_U -- Unbonded Output FF with INIT=Set
port (Q: out std_logic;
D, C: in std_logic);
end component;
--- Internal Signal Declarations -----
signal U_Q : STD_LOGIC_VECTOR (3 downto 0);
signal U_D : STD_LOGIC;
begin
U_D <= A and B;
Q_OUT <= U_Q(0);
U3: OFD_U port map (Q => U_Q(3),
D => U_D,
C => CLK);
U2: IFDI_U port map (Q => U_Q(2),
D => U_Q(3),
C => CLK);
U1: OFDI_U port map (Q => U_Q(1),
D => U_Q(2),
C => CLK);
U0: IFD_U port map (Q => U_Q(0),
D => U_Q(1),
C => CLK);
end XILINX;
////////////////////////////////////////////////////
// UNBONDED.V //
// XC4000 family has unbonded IOBs which have //
// storage elements that can be used to build //
// functions lie shift registers. //
// Below is a 4-bit Shift Register using Unbonded //
// IOB Flip Flops //
// HDL Synthesis Design Guide for FPGAs //
// May 1997 //
////////////////////////////////////////////////////
module unbonded_io (A, B, CLK, Q_OUT);
input A, B, CLK;
output Q_OUT;
wire[3:0] U_Q;
wire U_D;
assign U_D = A & B;
assign Q_OUT = U_Q[0];
OFD_U U3 (.Q(U_Q[3]), .D(U_D), .C(CLK));
IFDI_U U2 (.Q(U_Q[2]), .D(U_Q[3]), .C(CLK));
OFDI_U U1 (.Q(U_Q[1]), .D(U_Q[2]), .C(CLK));
IFD_U U0 (.Q(U_Q[0]), .D(U_Q[1]), .C(CLK));
endmodule