HDL (hardware description language) is a specialized language used to describe the structure/behavior of real world circuits.
It is used by circuit designers to simulate circuits and logic prior to wiring and fabricating a hardware circuit.
HDL allows circuit designers to simulate circuits at a high level without being connected to specific components.
Basic building blocks & introduction to the language— ¶
This programming language is built by simulating hardware chips and wiring. Normal programming functions are replaced with specialized chips that are added to the current wiring design. Every base chip must be written as it’s own file and imported to be used in the current chip, though they may be reused as often as desired.
1// Single line comments start with two forward slashes.
2
3/*
4 * Multiline comments can be written using '/*' and 'star/'.
5 * These are often used as comments.
6 *
7 * Note that they cannot be nested and will end at the first 'star/'.
8 */
9
10////////////////////////////////////////////////////
11// 1. Chips & Components
12////////////////////////////////////////////////////
13/*
14 * Unlike other languages HDL creates an individual chip (function) per file
15 * These are defined with a name, input arguments, output arguments
16 * and finally the parts/logic of that specific chip.
17 */
18
19// Note CHIP is capitalized, the chip name does not need to be.
20CHIP Ex {
21 IN a, // Single bit (0 or 1) variable.
22 c[16]; // 16 bit variable bus of single bit values.
23
24 OUT out[16], // 16 bit variable bus output.
25 carry; // Single bit output variable
26
27 PARTS:
28 // The functional components of the chip.
29}
30
31// Lines are ended with semicolons but can be continued using commas. The
32// whitespace is ignored.
33
34
35
36////////////////////////////////////////////////////
37// 2. Inputs, Outputs, & Variables
38////////////////////////////////////////////////////
39/*
40 * Variables and IO are treated as pins/wires and can carry a single bit
41 * of data (0 or 1).
42 */
43
44// Hardware works on low level 0's and 1's, in order to use a constant
45// high or low we use the terms true and false.
46a=false; // This is a 0 value.
47b=true; // This is a 1 value.
48
49// Inputs and outputs can be defined as single bits
50IN a, b; // Creates two single bit inputs
51
52// They can also be defined as busses act as arrays where each
53// index can contain a single bit value.
54OUT c[16]; // Creates a 16 bit output array.
55
56// Bussed values can be accessed using brackets
57a[0] // The first indexed value in the bus a.
58a[0..3] // The first 4 values in the a bus.
59// Values can also be passed in entirety. For example if the function
60// foo() takes an 8 bit input bus and outputs a 2 bit bus:
61foo(in=a[0..7], out=c); // C is now a 2 bit internal bus
62
63
64// Note that internally defined busses cannot be subbussed!
65// To access these elements, output or input them separately:
66foo(in[0]=false, in[1..7]=a[0..6], out[0]=out1, out[1]=out2);
67// out1 and out2 can then be passed into other circuits within the design.
68
69
70
71////////////////////////////////////////////////////
72// Combining Subsystems
73////////////////////////////////////////////////////
74/*
75 * HDL relies heavily on using smaller "building block" chips to then be
76 * added into larger and more complex designs. Creating the smaller components
77 * and then adding them to the larger circuit allows for fewer lines of code
78 * as well as reduction in total rewriting of code.
79 */
80
81// We are writing the function AND that checks if inputs I and K are both one.
82// To implement this chip we will use the built in NAND gate as well as design
83// a custom NOT gate to invert a single input.
84
85// First we construct the Negation (not) chip. We will use the logically
86// complete gate NAND that is built in for this task.
87CHIP Not {
88 IN i; // Not gates only take one single bit input.
89 OUT o; // The negated value of a.
90
91 PARTS:
92 // Add the input to the built in chip, which then sends output to the NOT
93 // output. This effectively negates the given value.
94 Nand(a=i, b=i, out=o);
95}
96
97// By using the built in NAND gate we were able to construct a NOT gate
98// that works like a real world hardware logic chip. Now we must construct
99// the AND gate using these two gate primitives.
100
101// We define a two input, single output AND gate:
102CHIP And {
103 IN i, k; // Two single bit inputs.
104 OUT o; // One single bit output.
105
106 PARTS:
107 // Insert I and K into the nand gate and store the output in an internal
108 // wire called notOut.
109 Nand(a=i,b=k,out=notOut);
110
111 // Use the not gate we constructed to invert notOut and send to the AND
112 // output.
113 Not(in=notOut,out=o);
114}
115
116// Easy! Now we can use Nand, And, and Not gates in higher level circuits.
117// Many of these low level components are built in to HDL but any chip can
118// be written as a submodule and used in larger designs.
Test Files ¶
When working with the nand2tetris hardware simulator chips written using HDL will then be processed against test and comparison files to test functionality of the simulated chip versus the expected output. To do this a test file will be loaded into the hardware simulator and run against the simulated hardware.
1// First the chip the test file is written for is loaded
2load <chip name>.hdl
3
4// We set the output file for the simulated chip output as well as the comparison
5// file that it will be tested against. We also specify what the output is
6// expected to look like. In this case there will be two output columns, each
7// will be buffered by a single space on either side and 4 binary values in
8// the center of each column.
9output-file <chip name>.out,
10compare-to <chip name>.cmp,
11output-list in%B1.4.1 out%B1.4.1;
12
13// Then we set initial values for inputs to the chip. For example
14set enable1 1, // set input enable1 to 1
15set enable2 0, // set input enable2 to 0
16
17// The clock is also controlled in the test file using tick and tock. Tick is a
18// positive pulse and tock takes the clock back to 0. Clock cycles can be run
19// multiple times in a row with no other changes to inputs or outputs.
20tick,
21tock,
22
23// Finally we output the first expected value (from the test file) which is then
24// compared with the first line of real output from our HDL circuit. This output
25// can be viewed in the <chip name>.out file.
26output;
27
28// An example of <chip name>, a chip that takes in a 4 bit value as input and
29// adds 1 to that value could have the following as test code:
30
31// Set the input value to 0000, clock pulse, compare output from cmp file to actual out.
32set in %B0000,
33tick,
34tock,
35output;
36
37// Set the input value to 0110, clock pulse, compare output from cmp file to actual out.
38set in %B0110,
39tick,
40tock,
41output;
42
43// The expected output for case 1 should be 0001 and case 2 expects 0111, lets
44// learn a little more about comparison files before finalizing our lesson.
Comparison Files ¶
Now lets take a look at comparison files, the files that hold what the test file compares with the actual output of an HDL chip in the hardware simulator!
1// Like the <chip name> example above, the structure of the comparison file
2// would look something like this
3| in | out |
4| 0000 | 0001 |
5| 0110 | 0111 |
6
7// Notice how the input values specified in the test case are equivalent to the
8// `in` column of the comparison file, and that the space buffer is 1 on either side.
9
10// If the output from the HDL code we not this, such as the output below, then the
11// test will fail and the user will know that the simulated chip is not correctly designed.
12| in | out |
13| 0000 | 0001 |
14| 0110 | 0110 | // Error! The chip did not add 1 here, something went wrong.
This is incredibly useful as it allows designers to simulate chip logic prior to fabricating real life hardware and identify problems in their designs. Be warned that errors in the test or comparison files can lead to both false positives and also the more damaging false negatives so ensure that the logic is sound behind the test creation.
Good luck and happy coding!