|
CAST and IRSIM
There are manpages for irsim on the student machines. If you want to learn
about all the irsim commands, try man irsim .
Here is an example of a CAST file, with comments explaining the different parts.
Please read the file
that describes 314/parts.cast for information about the
building blocks being used below. /* import standard definitions of
two-input NAND, two-input NOR,
inverter, and flops */
import "314/parts.cast";
/* define two-input And using Nand and inverter */
define And2() (node a, b, out)
{
node x; // declare intermediate node
Nand2() (a,b,x); // create two-input nand, output is x
Inv() (x,out); // invert x to get out
}
/* define two-input Or using Nor and inverter */
define Or2() (node a, b, out)
{
node x; // declare intermediate node
Nor2() (a,b,x); // create two-input nor
Inv() (x,out);
}
While this CAST file defines And2 and Or2 , it doesn't
create any circuits. Let's say we save this CAST file as foo.cast ,
and now want to create a circuit with combinational logic that computes out =
a AND b OR c . The following file defines this circuit, using the
definitions we've just created: import "foo.cast"; // get my
definitions
node a, b, c; // declare boolean-valued inputs
node out; // declare boolean-valued output
node x; // intermediate node
And2() (a,b,x);
Or2() (x,c,out);
If this were saved in file.cast , running prs2sim
file.cast
generates file.sim and file.al , that can be simulated
with irsim by running: irsim.sh file.sim file.al
Some commonly used irsim commands can be found
here
.
We can instantiate a positive edge-triggered flop by saying; posFLOP()
(inputnode, outputnode);
This instantiates a single flop with input inputnode , and output outputnode .
This can be used to create state-holding elements and to build finite-state
machines. Don't forget to import 314/parts.cast before trying to
create a flop, since this file contains the definitions for posFLOP .
Loops |
|
Let's say we wanted to define a block that took two sets of 8 one-bit inputs,
ANDed the correspond bits of the two inputs, and produced 8 one-bit outputs. A
convenient way to group signals together is to use an array. The definition of
this block would look like: import "myparts.cast"; // get my definitions
/* Note the way the array of inputs and outputs is declared. In this
example, node[8] is the type specifying an array of 8 nodes. */
define BlockAnd() (node[8] a,b, out)
{
node[8] x;
Nand2() (a[0],b[0],x[0]);
Inv() (x[0],out[0]);
Nand2() (a[1],b[1],x[1]);
Inv() (x[1],out[1]);
/* this is getting tedious... */
...
Nand2() (a[7],b[7],x[7]);
Inv() (x[7],out[7]);
}
To avoid all this typing, CAST supports a syntactic loop
construct. Using this construct, the same circuit as the one shown above would
be written as: import "myparts.cast"; // get my definitions
/* Note the way the array of inputs and outputs is declared. In this
example, node[8] is the type specifying an array of 8 nodes. */
define BlockAnd() (node[8] a,b, out)
{
node[8] x;
<i:8: Nand2() (a[i],b[i],x[i]); Inv() (x[i],out[i]); >
}
Note that the two ways to describe the BlockAnd result
in identical circuits. The loop construct is just a convenience; the
loop would be expanded out before the circuit is created.
|
|
|
| |