ACT netlist to Verilog netlist

The act2v tool can be used to convert an ACT structural netlist into Verilog syntax. This is useful if you need a structural Verilog netlist—for example, as an input to a commercial or other third party tool (e.g. for place and route, visualization, etc.).

The usage is:

Usage: act2v [act-options] [-Bmf] [-c <cells>] [-p <proc>] <act>

Given an ACT file and the top-level process name, this prints a Verilog netlist. The tool takes the following command-line options in addition to the standard common ACT options:

  • -p <proc> : specify the top-level process name (required)
  • -c <cells> : use <cells> as the cells file, and run cell extraction (ala prs2cells) before generating the Verilog netlist. Note: for this to work properly, the top-level process should also be instantiated in the ACT.
  • -m : use mangled names rather than escaped names in the Verilog output
  • -f : fuse the wire/reg directive with input/output directives
  • -B : turns on black box mode (in case black box mode is off by default for your technology). This option is deprecated and black box mode should be turned on by default in the ACT configuration files.

As a simple example, consider the following ACT file:

example.act
defproc inverter (bool? i; bool! o)
{
  prs {
    i => o-
  }
}
 
defproc nand2 (bool? a, b; bool! c)
{
  prs {
    a & b => c-
  }
}
 
defproc and2 (bool? a, b; bool! c)
{
  nand2 n(.a=a, .b=b);
  inverter i(.i=n.c, .o=c);  // note that we don't need the intermediate name _c
}

A simple use-case would be to generate a Verilog netlist for and2, and the command is:

$ act2v -p and2 example.act > eg1.v

This will generate a netlist that looks like this:

//
// Verilog module for: inverter<>
//
module inverter(i, o);
   input i;
   output o;
 
// -- signals ---
   reg o;
   wire i;
 
// --- instances
endmodule
...
//
// Verilog module for: and2<>
//
module and2(a, b, c);
   input a;
   input b;
   output c;
 
// -- signals ---
   reg \i.i ;
   wire a;
   wire b;
   reg c;
 
// --- instances
inverter \i  (.i(\i.i ), .o(c));
nand2 \n  (.a(a), .b(b), .c(\i.i ));
endmodule

A few observations:

  • The Verilog escaping approach is used to keep the names as similar to the original ACT names as possible. In the example, the name i.i is escaped in the and2 module definition.
  • All production rules have been stripped out. That's because this is for netlist translation, and not used to generate a Verilog simulation model. This is intentional; a translated Verilog simulation model might easily pass tests in Verilog, but that may not be an accurate view of reality. ''actsim'' is a better way to simulate the circuit for functionality.

Some Verilog tools can't handle the escapes correctly; in this case, you should use the -m option to turn on name mangling, which will convert the escaped names into mangled names automatically.

Finally, some Verilog tools don't like the separate wire and input/output designations. To support those, the -f option can be used to fuse the two different declarations into a single one. Note that some tools don't like the fused syntax, which is why both approaches are supported. Adding -f and -m for the same example above produces the following output for the generic technology that comes with the ACT installation:

//
// Verilog module for: inverter<>
//
module inverter(i, o);
 
// -- signals ---
   input    wire i;
   output    reg o;
 
// --- instances
endmodule
 
//
// Verilog module for: nand2<>
//
module nand2(a, b, c);
 
// -- signals ---
   output    reg c;
   input    wire a;
   input    wire b;
 
// --- instances
endmodule
 
//
// Verilog module for: and2<>
//
module and2(a, b, c);
 
// -- signals ---
   input    wire b;
   output    reg c;
   input    wire a;
   reg i_ai;
 
// --- instances
inverter i  (.i(i_ai), .o(c));
nand2 n  (.a(a), .b(b), .c(i_ai));
endmodule