This is an old revision of the document!


Specifying gate sizes

The gate sizing can be specified using prs sub-language but using the newly introduced sizing sub-language is recommended. This tutorial will show how to specify gate sizes using the new sizing sub-language.

Before writing a prs for inverter, let’s assume that we have the following specification included in the configuration file. Here, unit_n is the unit drive strength of the NMOS transistor and equal to 5 lambda.

real lambda 0.3e-6
real p_n_ratio 2.0
int unit_n 5

Example 1 - Basic sizing

Now, using our inverter example from first tutorial (inv.act), we can specify sizing for unit sized inverter as:

defproc inv (bool? in; bool! out)
{
   prs {
     in => out-
   }
    sizing{
      out {-1}
    }
}

inv U1;

The statement out {-1} specifies that nmos in the pull-down network is sized for unit drive strength i.e. 5 lambda (1.5 μm). The pmos in pull-up network will be sized automatically based on p_n_ratio as 10 lambda (3 μm). We can also write this as out {+1} to indicate that pmos pull-up should be sized for pmos unit drive strength (unit_n * p_n_ratio) i.e. 10 lambda. In this case, the nmos in pull-down network will be sized automatically.

Example 2 - Using template

We could also write the same inverter description using template keyword to design a parameterized inverter as:

template<pint sz>
defproc inv (bool? in; bool! out)
{
   prs {
     in => out-
   }
    sizing{
      out {-sz}
    }
}

inv<1> U1;
inv<2> U2;

Here, the drive strength of the pull-down network is specified using integer parameter sz. Note that inverters of different drive strength can then be instantiated by statement inv<1> U1 for unit drive strength and inv<2> U2 for 2x drive strength.

Example 3 - Using implementation relation

The implementation relation is used to implement a type, process, or channel using another type, channel, or process. Let’s look at the example below:

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

template<pint drive>
defproc szinv <: inv()
{
  sizing {
     o {-drive}
  }
}

defproc INVX1 <: szinv<1> () { }
defproc INVX2 <: szinv<2> () { }

INVX1 A1;
INVX2 A2;

Here, two inverters are defined using the implementation relation (written as <:). The process INVX1 is an implementation of process szinv which is an implementation of process inv. In this example, processes INVX1 and INVX2 both have the same logical production rules but different sizing specifications.

The use of implementation relation may look unnecessary for a small component such as inverter but it can be useful in complex circuits. For example, a standard cell library of logical gates with multiple drive strengths can be designed by using the same logical description of each gate with different sizing.