I/O Circuitry Insertion and Advanced Netlisting Using Test Benches
Overview
- JHDL will automatically insert pads for you as described in
previous sections on basic netlisting.
- However, it cannot handle bidirectional pads or user-defined
clocks.
- You have a number of options available to you for inserting I/O
circuitry - you can manually instance library primitives or you can
use Logic calls.
- When you netlist there are two flags available to control what
JHDL emits in terms of top level I/O circuitry and ports.
Inserting I/O Circuitry Manually
As described earlier in this user's manual, it is possible to have
JHDL automagically insert I/O circuitry (pads and I/O buffers) for the
top-level ports in a JHDL design. This makes it possible to quickly
generate an EDIF file. However, it is only suitable for simple
designs since it cannot handle bidirectional top-level ports and
user-defined clocking. In this section you will learn the mechanisms
available to you to insert the required I/O circuitry into your design
prior to netlisting.
Instancing Library Primitives for I/O Circuitry
As mentioned previously, the primitive library for each technology
supported is available for manual insertion in JHDL. In this section,
manual insertion of buffers for Xilinx technology is covered. From
this, users should be able to determine how this would be done in
other technologies supported by JHDL.
In Xilinx, inserting an IBUF primitive between the port and your user
circuitry is all that must be done:
new ibuf(this, portWire, userCircuitryWire);
Once this is done, you do put commands on portWire like any
other wire. That is, the IBUF simulates just fine. Similarly, for
outputs:
new obuf(this, userCircuitryWire, portWire);
Inout ports have the added need for a select wire to enable the
tri-state output buffer. Here is
the code:
new ibuf(this, portWire, userCircuitryWire);
new obuft(this, userCircuitryWire, enableWire, portWire);
Note that in these examples, no actual pad cells are inserted - just
buffers. This is because in Xilinx the pad cells are not needed.
Also, some users have reported problems when inserting pad cells for some
Xilinx technologies.
Beyond these examples, the user can look in the library
documentation for the technology of interest to see
how to insert other kinds of buffers and clocking circuitry such as
CLKDLL's, IBUFG cells, and BUFG cells.
Pad Insertion Methods in Logic
The Logic class contains convenience functions for inserting pads and
buffers as well. These include:
-
padIn - an input buffer
-
padOut - an output buffer
-
padOutT - a tri-state output buffer
-
padInout - a combination of padOutT and padIn which provides a bidirectional
I/O driver
-
padClock - a driver and the necessary buffering to make a clock use
dedicated FPGA clock resources (low-skew interconnect, etc)
The Xilinx library, for example, contains many, many different I/O
drivers. The JHDL library contains most of them. Consult the API
documentation to see how to instance these.
Accessing the Default Global Clock When Manually Inserting
Pads
There is one situation not covered by the above discussion. That is
when your design uses default clocking, the question arises: how do
you get hold of the default global clock wire and use it to manually
instance pads? This code fragment will do so:
Wire CLK = getGlobalClock(getSystem());
new ibufg(this, CLK, userCircuitryClock);
Once again, consult your vendor's documentation on precisely what
cells are required on a clock input (DLL's, DCM's, BUFG's, etc).
I/O Insertion Strategies
Usually, adding I/O circuitry is the last thing you do prior to
netlisting. A strategy which has proven useful to other users of JHDL
is this: simulate and verify your design without any I/O circuitry included.
When you are ready to netlist, make a new cell which is just a wrapper
around your own design and which inserts the needed I/O circuitry and
then do a final simulation on that prior to netlisting.
Inserting Drop-Ins and Other Circuitry
Regardless of whether you let JHDL do some of the work of inserting pads
for you, there are cases where you will need to insert additional pads,
drivers, and drop-ins. Here are a few examples for Virtex:
-
The Virtex library contains a "startup_virtex" block. Wiring an input from
a pad to its GSR port provides a system-wide asynchronous reset capability.
Wiring an input from a pad to its GTS port allows an outside signal to
tri-state all output pins on the FPGA. Consult the Xilinx Library Guide
for further information. Note that JHDL will NOT simulate these functionalities.
Nevertheless you may want to include them for proper hardware execution.
-
Xilinx FPGA's provide a readback capability which is accessed via a readback
drop-in circuit and specific pins. Consult the Xilinx Library Guide for further
information.
-
Many FPGA boards require special memory or FIFO drop-ins for proper
operation. Consult the board documentation for information on what
needs to be inserted.
NOTE: the JHDL libraries for Xilinx 4K, Virtex, and Virtex2 are
relatively complete. However, some cells (such as the startup and
readback blocks) are there for completeness for netlisting and for
importing external EDIF designs into JHDL and do NOT contain
simulation models. Thus, do not be surprised if simulations of blocks
like startup_virtex don't reflect their real behavior. This is
another case where you may choose to do the majority of simulation
without any off these things inserted and only include them in the
wrapper design you create for the I/O circuitry.
Netlisting
Netlisting can be as simple as executing the following in your testbench:
tm.netlist( my_chip, "chip.edn" );
where my_chip is a pointer to the top-level cell you want netlisted.
However, where does tm come from? Remember back in the section
on test benches where you had to create a TechMapper before you built
your circuit? That is what tm is. Here is the code to remind you how
to do it:
VirtexTechMapper tm = (new VirtexTechMapper(true));
setDefaultTechMapper(tm);
...
tm.netlist(my_chip, "chip.edn");
However, there are a collection of options that should be set to get
just the behavior
you want. Here is the first:
tm.setInsertPads(boolean flg); // flg=false means don't insert pads.
This allows you to control whether JHDL will automatically insert pads
on your top level ports when you call the netlister. There are 2 cases where you would set this to
false. First, you may want to insert the pads yourself. Second, you may
want to generate a black box netlist of your design. That is, you
don't want any pads on the design since you are going to take the netlist
that JHDL generates and use it in another CAD tool as a black box.
The second option to set is:
tm.setInsertTopLevelPorts(boolean flg);
This allows you to control whether a port interface is emitted for your
top level design. Usually (when generating EDIF for a whole chip) you want
this to be false. However, you would want to set this to true for generating
a black box netlist.
Here is a code snippet showing the first part of a test bench
which does netlisting:
import byucc.jhdl.base.*;
import byucc.jhdl.Logic.*;
import byucc.jhdl.Xilinx.Virtex.*;
public class tb_cnt extends Logic implements TestBench {
static VirtexTechMapper tm;
static Cell mycnt;
static HWSystem hw;
public static void main(String argv[]) {
hw = new HWSystem();
tb_cnt tb = new tb_cnt(hw);
tm.setInsertPads(true);
tm.setInsertTopLevelPorts(false);
tm.netlist(mycnt, "c.edn");
System.out.println("Netlisting done.");
}
...
public tb_cnt(Node parent) {
super(parent);
tm = new VirtexTechMapper(true);
setDefaultTechMapper(tm);
clr = wire(1, "clr");
q = wire(4, "q");
mycnt = new cnt(this, clr, q);
...
}
To summarize, here is a discussion of the four possible uses of these
two flags:
-
setInsertPads(false), setInsertTopLevelPorts(false) => Use this if you want to insert your own pads on
a design.
-
setInsertPads(false), setInsertTopLevelPorts(true) => use this if generating
a black box netlist. Your design will have no pads and will have
ports on the top level entity.
-
setInsertPads(true), setInsertTopLevelPorts(false) => Use this if
generating a netlist for a complete chip and want JHDL to
automatically insert the pads for you.
-
setInsertPads(true), setInsertTopLevelPorts(true) => this is illegal. The
Xilinx downstream tools will complain that you have wires which both tie
to input ports and to input buffers and pads.
JHDL 0.3.45
Copyright (c) 1998-2003 Brigham Young University. All rights reserved.
Last updated on 11 May 2006