Tutorial: Advanced

This tutorial talks about some of the more advanced ways you can write and organize PHDL, as well as how PHDL can be used with tools other than PADS and Eagle.

Packages

Xtext ships with many features right out of the box, one of which is native support for packages and fully-qualified namespaces. Since they are so easy to implement in the framework, packages were added to the grammar specification for PHDL. Packages allow cross-references across file boundaries and allow source code to be split up into separate files (devices in library files, and design units in other files). This is quite different than using "include" directives which simply copy the source text from another file to the location of the include directive. Include directives are typically evaluated at compile and elaboration time, and do not lend themselves well to many of the features that IDE's provide. For these reasons, "include" directives have been discontinued in version 2.1, in favor of the use of packages.

In PHDL, packages can only be one level deep (in other words, they cannot be nested -- i.e. you cannot have a package within a package). The only objects that may be declared inside of a package are devices and designs (this includes hierarchical subdesigns). A simple package declaration with a few PHDL objects might look like this:

/**
 * A package of mosfet transistors
 */
package mosfet {
    device nmos {
        attr REFPREFIX = "Q";
        attr FOOTPRINT = "SOT-223";
        attr LIBRARY = "transistor-fet";
        pin gate = {$1}; // a $ is valid in a physical pin name
        pin source = {$2};
        pin drain = {$3};
    }
	
    device pmos {
        attr REFPREFIX = "Q";
        attr FOOTPRINT = "SOT-223";
        attr LIBRARY = "transistor-fet";
        pin gate = {$2};
        pin source = {$1};
        pin drain = {$3};
    }
}

The advantages of using packages are many. They provide a regular library structure similar to the way devices are maintained in layout tool libraries, and like those libraries, they may be entered only once and maintained in a repository or network location that everyone has access to. They set up a region called a "namespace" that encapsulates and qualifies all named objects within. This makes it easy to keep track of variations of devices, and collaboration of user libraries.

Qualified Namespaces

Packages provide a framework for qualified namespaces. This means that each named object within the package is prefixed with the package name using standard dot-notation to separate the two names. If a package called "foo" contains a device called "fum", then the device can be later referred to in a design as "foo.fum". Qualified names are best illustrated with an example:

package foo {
    device fum {
       ...
    }
    ...
}

// when referring to the device inside of the package above from within a design,
// use the fully qualified notation.  (designs will be discussed in a future tutorial)

design des {
    ... // more of the design code here
	
    // instancing device "fum" inside of package "foo"
    inst fum_inst of foo.fum {
    	...
    }
    
    // some more design down here
    ...
}

As another example, if we had placed all of the devices for the rc filter circuit we defined earlier into a package called mypackage, the design would look like this:

/**********************************************
 * A simple RC filter that that uses devices above
 */
design top {
    net in, out, gnd;
    
    // an instance of a resistor
    inst my_res of mypackage.resistor {
        a = in;
        b = out;
    }
    
    // an instance of a polarized capacitor
    inst my_cap of mypackage.capacitor {
        pos = out;
        neg = gnd;
    }
    
    // the input and output connectors
    // I/O is on p[1], and gnd is on p[0]
    inst(1:0) my_io of mypackage.hdr_2x1 {
        this(1).p[1] = in;
        this(0).p[1] = out;
        p[0] = gnd;
    }
}

A few restrictions exist with packages in PHDL to help eliminate design errors. The compiler will issue errors and the project will not build under the following circumstances:

If either of these cases were allowed, a unique qualified name could not be guaranteed. Default Xtext behavior resolves references on a first-come first-serve basis, so the first named object that matches the qualified name gets linked. Without these checks, there would be no way to guarantee which device actually gets instanced on the board.

A design may also reside in a package like this:

package myPackage {
    design top {
    	// all connectivity local to top declared inside here
    }
    // some devices or subdesigns, or (even another top level design) could also be declared here
}

IDE Tips

You can create a bunch of device declarations and then decide to put them all in a package. To do so, just use the mouse to highlight all lines of all the devices you want to place in a package, and then use [CTRL] + [SPACE] to activate content assist. From the drop down box, select the option to declare a package. After this, all previously selected devices will be "wrapped" inside a package declaration that you can give a name using the template tabbed field.

Translating the PHDL Netlist into Your Tool's Netlist Format

PADS and Eagle are natively supported by the PHDL compiler, however you can relatively easily, by extending a utility called phdltran, translate our generic PHDL Netlist into the netlist format of almost any tool you desire to use.

Getting Started With PHDL

The best place to start is to visit our installation instructions which will help you get PHDL up and running on your machine. Then, be sure to visit the tutorial page.