This is an old revision of the document!


Simple combinational gates

The following specifies a number of combinational gates, where the process names correspond to the commonly used names for the gates.

defproc inverter (bool? i; bool! o)
{
  prs {
    i => o-
  }
}

defproc nand2 (bool? a, b; bool! c)
{
  prs {
    a & b => c-
  }
}

defproc nor2 (bool? a, b; bool! c)
{
  prs {
    a | b => c-
  }
}

While all the syntax should be familiar, this example also uses , to create multiple variables of the same type. For nand2 and nor2, there are three variables in the port list. a and b have the same type (bool?), whereas c has a different type (bool!).

If we wanted to create a two-input and gate, we could simply write:

defproc and2 (bool? a, b; bool! c)
{
  prs {
    a & b => c+
  }
}

This would be accepted by ACT, and the production rule simulator prsim can simulate such rules without difficulty. However, a circuit designer would look at this and point out that we cannot implement this directly using a single pull-up and pull-down network in static CMOS. Instead, someone used to circuit design would write:

defproc and2 (bool? a, b; bool! c)
{
  bool _c;
  prs {
    a & b => _c-    
    _c => c-
  }
}

In this example, we have introduced a local variable _c. This variable is only visible within the process in the ACT language1). _c is the output of a nand operation, and then it is inverted to generate the output c.

Since we already have defined nand2 as well as inverter, an alternative approach would be to re-use those circuits as follows:

defproc and2 (bool? a, b; bool! c)
{
  bool _c;
  nand2 n(a,b,_c);
  inverter i(_c,c);
}

Here, the body of and2 has three instances: _c (a Boolean signal), n (a nand2), and i (an inverter). In addition, the syntax includes connections to the ports of both n and i.

In terms of naming, the ports of n are n.a, n.b, and n.c; similarly the ports for i are i.i and i.o. ACT uses the dot as a hierarchy separator. This version of an and2 contains one level of hierarchy.

ACT provides a very flexible mechanism for connecting signals. The following a variants that correspond to the same connections.

defproc and2 (bool? a, b; bool! c)
{
  bool _c;
  nand2 n;
  inverter i;
  n.a = a; 
  n.b = b;
  n.c = _c;
  i.i = _c;
  i.o = c;
}

The = operator is used to connect two variables. Since connections correspond to aliasing (once two Booleans are connected, they are the same signal as far as the circuit is concerned).

defproc and2 (bool? a, b; bool! c)
{
  bool _c;
  nand2 n(.a=a, .b=b, .c=_c);
  inverter i(.i=_c, .o=c);
}
1)
Simulators typically give you access to any signal you wish to see to simplify debugging