Tutorial

This tutorial walks you through some very simple examples of PHDL code. It assumes that you have already visited the installation page and that you have a working environment to develop PHDL.

If you have any questions or comments, please contact us by visiting our community page or clicking here.

RC Filter Circuit - The HelloWorld of PHDL

In order to see the power and learn the basics of PHDL, this page will guide you through what you need to do in order to create a simple rc-filter design in PHDL.

Note: For convenience we will show you here, the syntax needed to define this circuit and how to compile it from the command line. But we highly suggest that you use the eclipse plugin which is used throughout the rest of the tutorial, because of the very useful features such as syntax highlighting, content assist, and automatic code completion, as well as real-time syntax/error checking. However, the compiler will have the same output, whether done through the command line or the eclipse plugin.
If you would like to skip to the more detailed part of the tutorial, that gives more details on the language and how to use the help available in the eclipse environment, click here.


Therefore, you can follow along in either your favorite text editor or within the eclipse environement itself.

Declaring Devices

The first thing to do when creating a board design in PHDL is to determine the devices that you will need and to define them so that you will be able to use them in your design.

A device is declared as follows:

device <device_name> {
	attr REFPREFIX = "";
	attr FOOTPRINT = "";
	attr LIBRARY = "";
	//other desired attributes
	
	//Pin Declarations
	pin a = {1};
	pin b = {2};
}

Device Declaration

Devices are defined using the device keyword followed by a <device_name>, or PhdlID (a unique identifier for your device that you can use to instance it and use it later in your design). A PhdlID can contain letters, numbers, or any of the following characters: _, +, -, $, /, @, or !

Attributes

Attributes are declared using the attr keyword followed by an ID containing letters or numbers but not starting with a number. These are then followed by an equals sign and the attributes value in quotes and semicolon.
There are Three required attributes for each device declaration. The REFPREFIX attribute will be used by the compiler to generate a unique name for the multiple devices instanced in your design. The FOOTPRINT attribute is the unique footprint/device name in the layout editor you desire to use, such as Eagle or PADS. The LIBRARY attribute is the name of the library within Eagle or PADS, that the footprint resides in. The compiler uses these to generate a script and netlist that can be run or opened in your layout editor, to finish the layout process.
There are several optional special attributes that will be explained later on in the tutorial.
You can add any other custom attributes that you desire as well.

Pin Declarations

After the attributes, you declare the pins of your device. This is done using the following notation:

					pin <logical_name> = {<physical_name>};

The pin keyword is followed by a <logical_name> by which you want to refer to the pin in your design, (The logical-name is usually a useful name explaining what the pin is to be used for). These are followed by an equals sign and a <physical_name> within curly braces and a semicolon. (The physical pin is the name of the pad as refered to in the Eagle of PADS library you are using.)


In this rc filter circuit, we will need to use a resistor, a capacitor, and a two pin header we defined them according to the Eagle libraries as follows:

/*******************************************
 * Device Library
 */					
device resistor {
	attr REFPREFIX = "R";
	attr FOOTPRINT = "R0603";
	attr LIBRARY = "rcl";
	attr VALUE = "1k"; //Set a default resistance

	pin a = {1};
	pin b = {2};
}
device capacitor {
	attr REFPREFIX = "C";
	attr FOOTPRINT = "C0603";
	attr LIBRARY = "rcl";
	attr VALUE = "100uF"; //Set a default capacitance

	pin pos = {1};
	pin neg = {2};
}		
device hdr_2x1 {
	attr REFPREFIX = "J";
	attr FOOTPRINT = "1X02";
	attr LIBRARY = "pinhead";
	
	pin[0:1] p = {p0,p1};
}

Note: Notice that the pins on the header were declared as an array. This can be very useful and will be explained in more detail later on in the tutorial.

Type the above code into your text editor, or copy it from here.

Parts of a Design

Now that we have the devices declared, we can create a design which uses them. There are three essential things to have in a design:

Design Declaration

Designs are defined using the design keyword followed by an ID, consisting of letters and numbers but not starting with a number.

design <design_name> {

}

Net Declarations

Nets are declared using the net keyword followed by a unique <net_name> or PhdlID, (consisting of letters, numbers, and the same symbols as with the device names explained above), and ended with a semicolon.

					net <net_name>;

Multiple comma seperated nets can be declared on the same line:

					net in, out, gnd, vcc;

Device Instantiations

Devices are instanced as follows:

inst <unique_device_identifier> of <device_name> {
	
	//Pin assignments
	<logical_pin_name> = <net_name>;
	<logical_pin_name> = <net_name>;
	//...
}

The inst keyword is followed by a <unique_device_identifier>, consisting of numbers and letters, but not starting with a number. The of keyword is then used followed by the <device_name> as defined in the device definitions above, in order to specify which specific device you want to use.

Within the curly brackets the pins defined in the device definition must be assigned to existing nets declared earlier in the design using the following syntax:

					<logical_pin_name> = <net_name>;

Putting it all Together

1. In order to create our design, first we declare our design, we'll call this design top:

design top {
					
}

2. Next we declare the nets we are going to need for the design:

design top {
	
	net in, out, gnd;
					
}

3. Now we instance the resister and capacitor that we will need in our RC circuit:

design top {
	
	net in, out, gnd;
	
	// an instance of a resistor
	inst my_res if resistor {
		a = in;
		b = out;
	}
	
	//an instance of a polarized capacitor
	inst my_cap of capacitor {
		pos = out;
		neg = gnd;
	}
					
}

4. Now we need to instance two headers to be used for input and output to our filter. But because we want two of them we could either instance them both individually or more easily/quickly as an array which we will do here:

design top {
	
	net in, out, gnd;
	
	// an instance of a resistor
	inst my_res of resistor {
		a = in;
		b = out;
	}
	
	//an instance of a polarized capacitor
	inst my_cap of 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 hdr_2x1 {	//Instances an array of 2 headers indexed from 1 to 0
		this(1).p[1] = in;	//Assigns pin 1 of the 1st instance or my_io to the in net
		this(0).p[1] = out;	//Assigns pin 1 of the 0th instance of my_io to the out net
		p[0] = gnd;		//Assigns pin 0 of both instances of my_io to the gnd net
	}				
}

Copy the design code from here and add it to the end of the file where you are working.


5. So putting it all together, the finished design looks like this:

/*******************************************
 * Device Library
 */					
device resistor {
	attr REFPREFIX = "R";
	attr FOOTPRINT = "R0603";
	attr LIBRARY = "rcl";
	attr VALUE = "1k"; //Set a default resistance

	pin a = {1};
	pin b = {2};
}
device capacitor {
	attr REFPREFIX = "C";
	attr FOOTPRINT = "C0603";
	attr LIBRARY = "rcl";
	attr VALUE = "100uF"; //Set a default capacitance

	pin pos = {1};
	pin neg = {2};
}		
device hdr_2x1 {
	attr REFPREFIX = "J";
	attr FOOTPRINT = "1X02";
	attr LIBRARY = "pinhead";
	
	pin[0:1] p = {p0,p1};
}

/*************************************
 * RC Circuit Design
 */
design top {
	
	net in, out, gnd;
	
	// an instance of a resistor
	inst my_res of resistor {
		a = in;
		b = out;
	}
	
	//an instance of a polarized capacitor
	inst my_cap of 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 hdr_2x1 {	//Instances an array of 2 headers indexed from 1 to 0
		this(1).p[1] = in;	//Assigns pin 1 of the 1st instance or my_io to the in net
		this(0).p[1] = out;	//Assigns pin 1 of the 0th instance of my_io to the out net
		p[0] = gnd;		//Assigns pin 0 of both instances of my_io to the gnd net
	}				
}

Note: The device libraries can optionally be in different files within the same directory as the design.

The entire design can be downloaded all in one file here.

Compiling the Design

Now that we've completed the design, all we need to do is build the project and the compiler will generate the output files in a src-gen folder which will be created along-side the folder where your src code is stored.

Eclipse Plugin

If using eclipse, the only thing you will need to do is save the file or files you are using within a src folder in the project and the compiler will automatically create a src-gen folder alongside with the generated output.

Command-Line Based Compiler


If desiring to use the command-line based compiler:

(The above assumes that "." is on your classpath variable.)

Note: Also use the -? flag for help on more command-line flag options.

Generated Output

There will be 6 files generated in the src-gen folder by the compiler:

Note: 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.

This concludes the Hello World - RC Filter Circuit Example. Continue with the tutorial to learn more capabilities of the language.

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.