Skip to content

verilog-mode AUTOs

Emacs verilog-mode writes code for you from comments such as /*AUTOARG*/, /*AUTOINST*/ and /*AUTOWIRE*/: the comment stays, and the code it stands for follows it. Files written that way open and edit like any other; this page is about the AUTOs themselves.

An AUTO is a comment that stands for code verilog-mode can work out on its own. You write the comment once; Code | Expand AUTOs (or C-c C-a in Emacs) writes the code after it, and you run it again whenever the design changes. The comment is never removed, so the file keeps saying what it is generated from. Teams use AUTOs to stop typing port lists by hand: an instance of a module with forty ports is one line to write, and it stays correct when a port is added.

Expanding is one command: Edit | Undo takes it back, and Code | Delete AUTOs removes what the AUTOs wrote (keeping the comments). So far Expand AUTOs writes /*AUTOINST*/, /*AUTOINSTPARAM*/, /*AUTOWIRE*/ and /*AUTOLOGIC*/; other AUTOs, such as /*AUTOARG*/, are left as they are and a hint names them.

The examples below all instantiate the same small FIFO. It lives in its own file, fifo.sv, in the same directory as the file being expanded — one of the places Expand AUTOs looks for a module (see where modules are found below). If a module cannot be found, nothing is changed and an error names it and the line of its instance: Line 2: can't locate 'fifo' module definition.

module fifo #(parameter WIDTH = 8, parameter DEPTH = 16)
(input clk,
input rst_n,
input wr_en,
input [WIDTH-1:0] wr_data,
input rd_en,
output [WIDTH-1:0] rd_data,
output full,
output empty);
endmodule

Every “after” below is exactly what Emacs verilog-mode writes, and exactly what Expand AUTOs writes (our tests compare the two). The gaps are tabs, 8 columns wide as in Emacs: for them to line up in the editor too, set Settings | Editor | Code Style | SystemVerilog, Tabs and Indents tab, Tab size to 8 (the plugin’s default is 4).

Write the instance with /*AUTOINST*/ where the port connections go:

module rx_path;
fifo u_fifo (/*AUTOINST*/);
endmodule

Expand AUTOs connects every port of fifo to a signal of the same name:

module rx_path;
fifo u_fifo (/*AUTOINST*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
.full (full),
.empty (empty),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

What to notice:

  • The ports are grouped under // Interfaces, // Outputs, // Inouts, // Inputs, in that order (a group appears only when there are such ports), each in the order the module declares them.
  • A vector port gets its range (wr_data[WIDTH-1:0]), so you can see the width without opening fifo.sv.
  • The connections line up in a column.

Connections you write before the comment are yours: the AUTO leaves out the ports they connect.

module rx_path;
fifo u_fifo (.clk (sys_clk),
.rst_n (sys_rst_n),
/*AUTOINST*/);
endmodule

becomes

module rx_path;
fifo u_fifo (.clk (sys_clk),
.rst_n (sys_rst_n),
/*AUTOINST*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
.full (full),
.empty (empty),
// Inputs
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

Everything between the AUTO comment and the closing parenthesis belongs to the AUTO: it is rewritten on every expansion. Put your own connections before the comment, never after it.

Someone added rst_n, full and empty to fifo after this instance was expanded:

module rx_path;
fifo u_fifo (/*AUTOINST*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
// Inputs
.clk (clk),
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

Run Expand AUTOs again: what the AUTO wrote before is replaced by what the module has now.

module rx_path;
fifo u_fifo (/*AUTOINST*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
.full (full),
.empty (empty),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

This is the main reason to use AUTOs: after a module changes, one command updates every instance of it in the file. Running it on an up-to-date file changes nothing.

A regular expression in quotes, /*AUTOINST("regex")*/, connects only the ports whose names match (Emacs regular expression syntax: ^ is the start of the name, $ its end). Here the AUTO connects the write side, three ports are connected by hand, and rd_en, full and empty are left unconnected (an unconnected input floats: in real code tie it off, as example 9 does):

module rx_path;
fifo u_fifo (.clk (sys_clk),
.rst_n (sys_rst_n),
.rd_data (rx_data),
/*AUTOINST("^wr_")*/);
endmodule

becomes

module rx_path;
fifo u_fifo (.clk (sys_clk),
.rst_n (sys_rst_n),
.rd_data (rx_data),
/*AUTOINST("^wr_")*/
// Inputs
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]));
endmodule

Starting the regex with ?! does the opposite: it connects the ports that do not match. Here full and empty stay unconnected:

module rx_path;
fifo u_fifo (/*AUTOINST("?!^\(full\|empty\)$")*/);
endmodule

becomes

module rx_path;
fifo u_fifo (/*AUTOINST("?!^\(full\|empty\)$")*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

(\(…\) groups and \| means “or”: in Emacs regular expressions the parentheses and the bar are escaped.)

/*AUTOINSTPARAM*/ in the #( ) of an instance connects the module’s parameters, the same way:

module rx_path;
fifo #(/*AUTOINSTPARAM*/)
u_fifo (/*AUTOINST*/);
endmodule

becomes

module rx_path;
fifo #(/*AUTOINSTPARAM*/
// Parameters
.WIDTH (WIDTH),
.DEPTH (DEPTH))
u_fifo (/*AUTOINST*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
.full (full),
.empty (empty),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

Put the instance name on its own line, as here. If the last parameter’s connection comes from a template (next section), its // Templated comment goes at the end of the parameter list’s last line — and would comment out an instance name written on that line.

6. Renaming connections with AUTO_TEMPLATE

Section titled “6. Renaming connections with AUTO_TEMPLATE”

Most instances do not connect every port to a signal of the same name. An AUTO_TEMPLATE comment above the instance says, port by port, what to connect instead:

module rx_path;
/* fifo AUTO_TEMPLATE (
.clk (sys_clk),
.rst_n (sys_rst_n),
.rd_data (rx_data[]),
.full (),
); */
fifo u_fifo (/*AUTOINST*/);
endmodule

becomes

module rx_path;
/* fifo AUTO_TEMPLATE (
.clk (sys_clk),
.rst_n (sys_rst_n),
.rd_data (rx_data[]),
.full (),
); */
fifo u_fifo (/*AUTOINST*/
// Outputs
.rd_data (rx_data[WIDTH-1:0]), // Templated
.full (), // Templated
.empty (empty),
// Inputs
.clk (sys_clk), // Templated
.rst_n (sys_rst_n), // Templated
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

What to notice:

  • .rd_data (rx_data[]): [] stands for the port’s range, so the width still comes from the module.
  • .full () leaves the port unconnected.
  • Ports the template does not name are connected as usual.
  • Every templated connection is marked // Templated, so a reader knows where it comes from.

A template entry can name several ports with a regular expression (.wr_\(.*\) is every port starting with wr_); in the connection, \1 is what the group \(.*\) matched. @ is the instance’s number — the first digits in its name — so one template serves u_fifo0, u_fifo1… (here in names the write side and out the read side, so the input rd_en becomes ch0_out_en):

module rx_path;
/* fifo AUTO_TEMPLATE (
.wr_\(.*\) (ch@_in_\1[]),
.rd_\(.*\) (ch@_out_\1[]),
.full (ch@_full),
.empty (ch@_empty),
); */
fifo u_fifo0 (/*AUTOINST*/);
fifo u_fifo1 (/*AUTOINST*/);
endmodule

becomes

module rx_path;
/* fifo AUTO_TEMPLATE (
.wr_\(.*\) (ch@_in_\1[]),
.rd_\(.*\) (ch@_out_\1[]),
.full (ch@_full),
.empty (ch@_empty),
); */
fifo u_fifo0 (/*AUTOINST*/
// Outputs
.rd_data (ch0_out_data[WIDTH-1:0]), // Templated
.full (ch0_full), // Templated
.empty (ch0_empty), // Templated
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (ch0_in_en), // Templated
.wr_data (ch0_in_data[WIDTH-1:0]), // Templated
.rd_en (ch0_out_en)); // Templated
fifo u_fifo1 (/*AUTOINST*/
// Outputs
.rd_data (ch1_out_data[WIDTH-1:0]), // Templated
.full (ch1_full), // Templated
.empty (ch1_empty), // Templated
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (ch1_in_en), // Templated
.wr_data (ch1_in_data[WIDTH-1:0]), // Templated
.rd_en (ch1_out_en)); // Templated
endmodule

8. Numbers are not enough: naming instances

Section titled “8. Numbers are not enough: naming instances”

When the instance names are not numbered, give the template a regular expression for them in quotes. Its first group is what @ stands for:

module rx_path;
/* fifo AUTO_TEMPLATE "u_\(.*\)_fifo" (
.wr_data (@_wdata[]),
.rd_data (@_rdata[]),
); */
fifo u_video_fifo (/*AUTOINST*/);
fifo u_audio_fifo (/*AUTOINST*/);
endmodule

becomes

module rx_path;
/* fifo AUTO_TEMPLATE "u_\(.*\)_fifo" (
.wr_data (@_wdata[]),
.rd_data (@_rdata[]),
); */
fifo u_video_fifo (/*AUTOINST*/
// Outputs
.rd_data (video_rdata[WIDTH-1:0]), // Templated
.full (full),
.empty (empty),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (video_wdata[WIDTH-1:0]), // Templated
.rd_en (rd_en));
fifo u_audio_fifo (/*AUTOINST*/
// Outputs
.rd_data (audio_rdata[WIDTH-1:0]), // Templated
.full (full),
.empty (empty),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (audio_wdata[WIDTH-1:0]), // Templated
.rd_en (rd_en));
endmodule

For connections that need a computation, @"(…)" in a template is replaced by the value of an Emacs Lisp expression. The port’s details are there to use: vl-name (its name), vl-width (its width), vl-bits (its range), vl-dir ("input", "output"…), vl-cell-name (the instance’s name) and more. Here a spare FIFO gets its write data tied off at the port’s width ({WIDTH{1'b0}}), and its read data named after the instance:

module rx_path;
/* fifo AUTO_TEMPLATE (
.wr_en (1'b0),
.wr_data ({@"vl-width"{1'b0}}),
.rd_data (@"(upcase vl-cell-name)"_DATA[]),
); */
fifo u_spare (/*AUTOINST*/);
endmodule

becomes

module rx_path;
/* fifo AUTO_TEMPLATE (
.wr_en (1'b0),
.wr_data ({@"vl-width"{1'b0}}),
.rd_data (@"(upcase vl-cell-name)"_DATA[]),
); */
fifo u_spare (/*AUTOINST*/
// Outputs
.rd_data (U_SPARE_DATA[WIDTH-1:0]), // Templated
.full (full),
.empty (empty),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (1'b0), // Templated
.wr_data ({WIDTH{1'b0}}), // Templated
.rd_en (rd_en));
endmodule

10. Changing things between instances: AUTO_LISP

Section titled “10. Changing things between instances: AUTO_LISP”

/*AUTO_LISP(…)*/ runs Lisp too, and each instance sees what the AUTO_LISPs above it set. Here one template puts two FIFOs in different clock domains:

module rx_path;
/* fifo AUTO_TEMPLATE (
.clk (@"domain"_clk),
); */
/*AUTO_LISP(setq domain "core")*/
fifo u_core_fifo (/*AUTOINST*/);
/*AUTO_LISP(setq domain "io")*/
fifo u_io_fifo (/*AUTOINST*/);
endmodule

becomes

module rx_path;
/* fifo AUTO_TEMPLATE (
.clk (@"domain"_clk),
); */
/*AUTO_LISP(setq domain "core")*/
fifo u_core_fifo (/*AUTOINST*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
.full (full),
.empty (empty),
// Inputs
.clk (core_clk), // Templated
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
/*AUTO_LISP(setq domain "io")*/
fifo u_io_fifo (/*AUTOINST*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
.full (full),
.empty (empty),
// Inputs
.clk (io_clk), // Templated
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

verilog-mode reads its settings from a block of comments at the end of the file, the Emacs “local variables”. Here the connections are sorted by name and lined up at column 32:

module rx_path;
fifo u_fifo (/*AUTOINST*/);
endmodule
// Local Variables:
// verilog-auto-inst-sort:t
// verilog-auto-inst-column:32
// End:

becomes

module rx_path;
fifo u_fifo (/*AUTOINST*/
// Outputs
.empty (empty),
.full (full),
.rd_data (rd_data[WIDTH-1:0]),
// Inputs
.clk (clk),
.rd_en (rd_en),
.rst_n (rst_n),
.wr_data (wr_data[WIDTH-1:0]),
.wr_en (wr_en));
endmodule
// Local Variables:
// verilog-auto-inst-sort:t
// verilog-auto-inst-column:32
// End:

With verilog-auto-inst-param-value, the instance’s parameter values go into the ranges, and simple arithmetic is done for you — a 32-bit FIFO shows 32-bit connections:

module rx_path;
fifo #(.WIDTH(32)) u_fifo (/*AUTOINST*/);
endmodule
// Local Variables:
// verilog-auto-inst-param-value:t
// End:

becomes

module rx_path;
fifo #(.WIDTH(32)) u_fifo (/*AUTOINST*/
// Outputs
.rd_data (rd_data[31:0]),
.full (full),
.empty (empty),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (wr_data[31:0]),
.rd_en (rd_en));
endmodule
// Local Variables:
// verilog-auto-inst-param-value:t
// End:

Instances need signals, and every output of an instance needs a declaration. /*AUTOWIRE*/ writes them: a declaration for each output (and inout) of the module’s instances that the module does not declare yet. Here two FIFOs connected through a template:

module rx_path #(parameter WIDTH = 8) (input clk, input rst_n);
/*AUTOWIRE*/
/* fifo AUTO_TEMPLATE "u_\(.*\)_fifo" (
.wr_\(.*\) (@_in_\1[]),
.rd_\(.*\) (@_out_\1[]),
.full (@_full),
.empty (@_empty),
); */
fifo u_cmd_fifo (/*AUTOINST*/);
fifo u_rsp_fifo (/*AUTOINST*/);
endmodule

becomes

module rx_path #(parameter WIDTH = 8) (input clk, input rst_n);
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire cmd_empty; // From u_cmd_fifo of fifo.v
wire cmd_full; // From u_cmd_fifo of fifo.v
wire [WIDTH-1:0] cmd_out_data; // From u_cmd_fifo of fifo.v
wire rsp_empty; // From u_rsp_fifo of fifo.v
wire rsp_full; // From u_rsp_fifo of fifo.v
wire [WIDTH-1:0] rsp_out_data; // From u_rsp_fifo of fifo.v
// End of automatics
/* fifo AUTO_TEMPLATE "u_\(.*\)_fifo" (
.wr_\(.*\) (@_in_\1[]),
.rd_\(.*\) (@_out_\1[]),
.full (@_full),
.empty (@_empty),
); */
fifo u_cmd_fifo (/*AUTOINST*/
// Outputs
.rd_data (cmd_out_data[WIDTH-1:0]), // Templated
.full (cmd_full), // Templated
.empty (cmd_empty), // Templated
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (cmd_in_en), // Templated
.wr_data (cmd_in_data[WIDTH-1:0]), // Templated
.rd_en (cmd_out_en)); // Templated
fifo u_rsp_fifo (/*AUTOINST*/
// Outputs
.rd_data (rsp_out_data[WIDTH-1:0]), // Templated
.full (rsp_full), // Templated
.empty (rsp_empty), // Templated
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (rsp_in_en), // Templated
.wr_data (rsp_in_data[WIDTH-1:0]), // Templated
.rd_en (rsp_out_en)); // Templated
endmodule

What to notice:

  • Only outputs are declared: inputs are yours to drive, and you declare them yourself (or they are ports).
  • Each declaration says which instance drives it (// From u_cmd_fifo of fifo.v). The comment always names the module with .v, whatever file it is in (fifo.sv here): that is how verilog-mode writes it.
  • The width comes from the connection AUTOINST wrote: [WIDTH-1:0] is copied as written, so WIDTH must mean something in rx_path too — here it is rx_path’s own parameter. (Without it, the declaration would not compile: give the module the parameter, or use verilog-auto-inst-param-value, example 12, to have numbers instead.)
  • A signal you declare yourself anywhere in the module is not declared again.

/*AUTOLOGIC*/ works like AUTOWIRE and declares with logic, the SystemVerilog style. One AUTOLOGIC anywhere in a file makes every AUTOWIRE of the file use logic as well.

module rx_path #(parameter WIDTH = 8) (input clk, input rst_n);
/*AUTOLOGIC*/
fifo u_fifo (/*AUTOINST*/);
endmodule

becomes

module rx_path #(parameter WIDTH = 8) (input clk, input rst_n);
/*AUTOLOGIC*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
logic empty; // From u_fifo of fifo.v
logic full; // From u_fifo of fifo.v
logic [WIDTH-1:0] rd_data; // From u_fifo of fifo.v
// End of automatics
fifo u_fifo (/*AUTOINST*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
.full (full),
.empty (empty),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

15. Ports from the instances: AUTOINPUT and AUTOOUTPUT

Section titled “15. Ports from the instances: AUTOINPUT and AUTOOUTPUT”

A wrapper module often only passes its instance’s ports through. /*AUTOINPUT*/ declares an input for each input of the instances that the module does not declare and no other instance drives; /*AUTOOUTPUT*/ an output for each output of the instances that no other instance reads. Put them in the port list:

module fifo_wrap #(parameter WIDTH = 8) (
/*AUTOINPUT*/
/*AUTOOUTPUT*/
);
fifo u_fifo (/*AUTOINST*/);
endmodule

becomes

module fifo_wrap #(parameter WIDTH = 8) (
/*AUTOINPUT*/
// Beginning of automatic inputs (from unused autoinst inputs)
input clk, // To u_fifo of fifo.v
input rd_en, // To u_fifo of fifo.v
input rst_n, // To u_fifo of fifo.v
input [WIDTH-1:0] wr_data, // To u_fifo of fifo.v
input wr_en, // To u_fifo of fifo.v
// End of automatics
/*AUTOOUTPUT*/
// Beginning of automatic outputs (from unused autoinst outputs)
output empty, // From u_fifo of fifo.v
output full, // From u_fifo of fifo.v
output [WIDTH-1:0] rd_data // From u_fifo of fifo.v
// End of automatics
);
fifo u_fifo (/*AUTOINST*/
// Outputs
.rd_data (rd_data[WIDTH-1:0]),
.full (full),
.empty (empty),
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (wr_en),
.wr_data (wr_data[WIDTH-1:0]),
.rd_en (rd_en));
endmodule

What to notice:

  • In a port list the declarations end with a comma, and the last one of the list has none: the comma before the ) is taken away (and one is added after a port written before the AUTO, if it has none).
  • Written in the module body instead, below the port list, they are body declarations (input clk;).
  • /*AUTOINOUT*/ does the same for inouts.
  • Run Expand AUTOs again after you change fifo: the lists follow it.

With several instances, a signal one instance drives and another reads is a wire, not a port. A regular expression in the AUTO picks the ports by name ("^out_": the names starting with out_); the other outputs are left to AUTOWIRE:

module two_stage #(parameter WIDTH = 8) (
input clk,
input rst_n,
/*AUTOINPUT*/
/*AUTOOUTPUT("^out_")*/
);
/*AUTOWIRE*/
/* fifo AUTO_TEMPLATE "u_first" (
.wr_\(.*\) (in_\1[]),
.rd_\(.*\) (mid_\1[]),
.full (in_full),
.empty (mid_empty),
); */
fifo u_first (/*AUTOINST*/);
/* fifo AUTO_TEMPLATE "u_second" (
.wr_\(.*\) (mid_\1[]),
.rd_\(.*\) (out_\1[]),
.full (mid_full),
.empty (out_empty),
); */
fifo u_second (/*AUTOINST*/);
endmodule

becomes

module two_stage #(parameter WIDTH = 8) (
input clk,
input rst_n,
/*AUTOINPUT*/
// Beginning of automatic inputs (from unused autoinst inputs)
input [WIDTH-1:0] in_data, // To u_first of fifo.v
input in_en, // To u_first of fifo.v
input mid_en, // To u_first of fifo.v, ...
input out_en, // To u_second of fifo.v
// End of automatics
/*AUTOOUTPUT("^out_")*/
// Beginning of automatic outputs (from unused autoinst outputs)
output [WIDTH-1:0] out_data, // From u_second of fifo.v
output out_empty // From u_second of fifo.v
// End of automatics
);
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
wire in_full; // From u_first of fifo.v
wire [WIDTH-1:0] mid_data; // From u_first of fifo.v
wire mid_empty; // From u_first of fifo.v
wire mid_full; // From u_second of fifo.v
// End of automatics
/* fifo AUTO_TEMPLATE "u_first" (
.wr_\(.*\) (in_\1[]),
.rd_\(.*\) (mid_\1[]),
.full (in_full),
.empty (mid_empty),
); */
fifo u_first (/*AUTOINST*/
// Outputs
.rd_data (mid_data[WIDTH-1:0]), // Templated
.full (in_full), // Templated
.empty (mid_empty), // Templated
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (in_en), // Templated
.wr_data (in_data[WIDTH-1:0]), // Templated
.rd_en (mid_en)); // Templated
/* fifo AUTO_TEMPLATE "u_second" (
.wr_\(.*\) (mid_\1[]),
.rd_\(.*\) (out_\1[]),
.full (mid_full),
.empty (out_empty),
); */
fifo u_second (/*AUTOINST*/
// Outputs
.rd_data (out_data[WIDTH-1:0]), // Templated
.full (mid_full), // Templated
.empty (out_empty), // Templated
// Inputs
.clk (clk),
.rst_n (rst_n),
.wr_en (mid_en), // Templated
.wr_data (mid_data[WIDTH-1:0]), // Templated
.rd_en (out_en)); // Templated
endmodule

What to notice:

  • mid_data goes from u_first to u_second: it is a wire, declared by AUTOWIRE, and no port.
  • mid_en is read by both FIFOs and driven by neither: it is an input (// To u_first of fifo.v, ...).
  • in_full is an output nobody reads, but "^out_" keeps it out of the ports: AUTOWIRE declares it.
  • clk and rst_n are declared by hand, so AUTOINPUT leaves them.
  • "?!^out_" would do the opposite: every output except those starting with out_.

Every flop needs a reset value, and the list goes stale as the design grows. /*AUTORESET*/ in the reset branch of an always block writes a reset of zero for each signal the block assigns that you do not reset by hand:

module counter #(parameter WIDTH = 8) (
input clk,
input rst_n,
input en,
output reg [WIDTH-1:0] count,
output reg done
);
reg [1:0] state;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= 2'd1;
/*AUTORESET*/
end
else if (en) begin
count <= count + 1'b1;
done <= (count == {WIDTH{1'b1}});
state <= state + 1'b1;
end
end
endmodule

becomes

module counter #(parameter WIDTH = 8) (
input clk,
input rst_n,
input en,
output reg [WIDTH-1:0] count,
output reg done
);
reg [1:0] state;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= 2'd1;
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
count <= {WIDTH{1'b0}};
done <= 1'h0;
// End of automatics
end
else if (en) begin
count <= count + 1'b1;
done <= (count == {WIDTH{1'b1}});
state <= state + 1'b1;
end
end
endmodule

What to notice:

  • state is reset by hand before the AUTO, to 2'd1: AUTORESET leaves it alone.
  • The width comes from the declaration: {WIDTH{1'b0}} for [WIDTH-1:0], 1'h0 for one bit.
  • Signals assigned with <= get <=, those assigned with = get =.
  • Add a signal to the else branch and expand again: its reset appears.

The Expand AUTOs reference below lists the settings, and what each AUTO does exactly.

Code | Expand AUTOs writes what the AUTO comments stand for, from the current code, as verilog-mode’s verilog-auto (C-c C-a) does: what an AUTO wrote before is replaced. It is one command: Edit | Undo takes it back. So far it expands /*AUTOINST*/ and /*AUTOINSTPARAM*/, with their AUTO_TEMPLATEs, /*AUTOWIRE*/, /*AUTOLOGIC*/, /*AUTOINPUT*/, /*AUTOOUTPUT*/, /*AUTOINOUT*/ and /*AUTORESET*/; every other AUTO is left exactly as it is, and a hint names it.

module pair_top;
edge_pair u_pair (/*AUTOINST*/);
endmodule

becomes

module pair_top;
edge_pair u_pair (/*AUTOINST*/
// Outputs
.rise_a (rise_a),
.rise_b (rise_b),
// Inputs
.clk (clk),
.a (a),
.b (b));
endmodule

The connections are written as verilog-mode writes them, with the file’s indent-tabs-mode and tab-width:

  • Each port of the instantiated module is connected to the signal of its name, grouped under // Interfaces, // Outputs, // Inouts, // Inputs, in the order the module declares them (for a module with a Verilog-1995 header, its body declarations, whatever the header lists). Ports connected before the comment (.clk(sys_clk), /*AUTOINST*/) are left out. A port whose type is one of the module’s type parameters (output T q) goes under // Interfaces, as verilog-mode puts it.
  • A vector port’s range is written (d[7:0]); a multi-dimensional or unpacked one gets its ranges as a comment (m/*[3:0][1:0]*/); an interface port with a modport, the modport (bus.mst).
  • /*AUTOINST("regex")*/ connects only the ports whose name matches the (Emacs) regular expression; /*AUTOINST("?!regex")*/ those that do not.
  • File settings (local variables): verilog-auto-inst-vector (nil: no range when the module declares the signal with the same one; unsigned: none for signed ports), verilog-auto-inst-sort (by name), verilog-auto-inst-dot-name (.clk when the connection is the port’s name), verilog-auto-inst-column. verilog-auto-inst-param-value puts the instance’s parameter values (#(.W(16))) in the ranges and simplifies them ([W*2-1:0] becomes [31:0]).
  • /*AUTOINSTPARAM*/ in #( ) connects the module’s parameters the same way, under // Parameters: those declared with parameter — in a #( ) list, the entries after a parameter keyword up to a localparam one (#(A = 1, parameter B = 2, int C = 3) gives B and C, as in verilog-mode) — not localparams, nor the parameters inside a generate block, which an instance cannot set (verilog-mode connects those). If the last parameter is templated, its // Templated comes before the instance name on the same line, commenting it out, as verilog-mode writes it: put the instance name on the next line (#(/*AUTOINSTPARAM*/) then u1 (…).
  • AUTO comments and template heads are found in either case (/*autoinst*/, /* SUB AUTO_TEMPLATE), unless the file sets case-fold-search or verilog-case-fold to nil (a case-fold-search setting wins). The regular expressions matched against names — the AUTO’s own, a template’s instance regular expression — follow verilog-case-fold alone.
  • Not supported yet, left as it is: .*, and `defines in the file for a `NAME module name (verilog-auto-read-includes — use -DNAME=value in the flags). An instance of a module that does not parse is left as it is too.

A template above the instances says what some ports connect to; the nearest one above an instance applies (else the first below). Several modules may share one.

/* sub AUTO_TEMPLATE "u_\(.*\)" (
.clk (sys_clk),
.data_\(.*\) (bus_\1[]),
.q (q_@),
); */
  • .port names one port; a regular expression (Emacs syntax) names the ports it matches, @ in it standing for a number. A port named by an entry takes that entry (the last one naming it), else the first regular expression that matches it.
  • In the connection, \1… are the port expression’s groups; @ is the instance’s number — the first group of the template’s instance regular expression, else the first digits of the instance’s name; [] is the port’s range (nothing for one bit); [][] its ranges as AUTOINST writes them; [].[@] one element of an unpacked port. An @ needs that group: if the instance’s name matches an instance regular expression without one ("u_"), expanding stops with an error naming the line.
  • Templated connections get // Templated (verilog-auto-inst-template-numbers: with the line of the template entry, or lhs its port name — for a regular expression, as verilog-mode compiles it: .r@_l shows ^r\([0-9]+\)_l$). //AUTONOHOOKUP after an entry is carried over — after a regular expression with @, as in verilog-mode, only if the file’s first line has it. On the last port, with verilog-auto-inst-template-numbers t, // Templated <line> AUTONOHOOKUP is not recognised as a template comment, by verilog-mode either, so each Expand adds another.
  • A // Templated you wrote after a connection before the AUTO comment is kept (verilog-mode removes it).
  • verilog-auto-inst-template-required: only ports a template names are connected.

verilog-mode lets a file carry Emacs Lisp, and so does Expand AUTOs — run in a sandbox that cannot read or write files, start programs or reach the network. Each evaluation, and all of them together, have a budget of work and memory; beyond it expanding stops with an error, where Emacs would keep going until C-g. Expand AUTOs shows a progress whose Cancel stops it, changing nothing:

  • @"(…)" in a template connection is replaced by the value of its Lisp: .b (@"(* 8 @)") connects b of instance u_3 to 24. @ in it is the instance number; the port’s variables are those verilog-mode documents: vl-name, vl-bits, vl-mbits, vl-width, vl-dir, vl-memory, vl-modport, vl-cell-type, vl-cell-name. Quote a string as \"…\" in a port-name entry, \\"…\\" in a regular-expression entry, as in verilog-mode.
  • /*AUTO_LISP(…)*/ comments define functions and set variables: each AUTOINST sees those above it (/*AUTO_LISP(setq tense "was")*/ between two instances changes the second), and setting a verilog-mode variable changes that setting from there on.
  • eval: in the local variables runs too (// eval:(defun uc (x) (upcase x))).
  • The functions are the Emacs ones such code uses — strings, numbers, lists, regular expressions, format, defun, let, if, cond, while… — checked against Emacs on some 490 expressions, errors included (expanding then stops with the error and the line). fboundp knows the sandbox’s functions only. A function the sandbox does not have leaves the AUTO as it is and the hint names it (Lisp function insert-file-contents); in eval: or AUTO_LISP, the whole file is left, as its settings are then unknown. verilog-read-defines and verilog-read-includes are not supported yet, nor, with verilog-auto-read-includes, a template that needs a define’s value.

/*AUTOWIRE*/ declares, below its line, each output and inout of the module’s instances that the module does not declare, as verilog-mode’s verilog-auto-wire does:

  • The instances are read back from the text as AUTOINST wrote it: the lines after each // Outputs, // Inouts, // Inputs (and interface) comment, one connection per line. Connections you write by hand under such a comment count too; others (before the AUTO comment, without a section comment) do not.
  • A connection gives a net and its range as written (q[3:0]); a concatenation gives each of its nets; constants, expressions and empty () give nothing. A connection without a range declares one bit, whatever the port’s width. A connection with AUTONOHOOKUP after it (//AUTONOHOOKUP in a template) is not declared.
  • A net several instances drive is declared once (// From u_a of sub.v, ...), with its ranges combined; ranges that cannot be combined keep the last one and add Couldn't Merge to the comment.
  • Declared already, and not declared again: a port, parameter, variable, net, genvar or instance of the module, anywhere in it (generate and begin blocks, every `ifdef branch — not in functions or tasks), and the names of /*AUTO_CONSTANT(a, b)*/ comments.
  • The type is the port’s (logic, int unsigned…), wire for a plain port; verilog-auto-wire-type sets it ("logic", "wire"), and verilog-auto-wire-comment (nil) leaves out the comments.
  • /*AUTOLOGIC*/ does the same with logic; one AUTOLOGIC anywhere makes the file’s wire type logic.
  • Left as it is (the hint says why) when an instance of the module was left as it is, when the module has a .*, when the module has an AUTO not supported yet that declares signals (AUTOINPUT, AUTOOUTPUT…: verilog-mode runs those first), when the file has an /*AUTOINSERTLISP(…)*/ (what it writes may declare signals), or when it would declare a signal that the old block of an AUTO left as it is (AUTOREG, AUTOREGINPUT…) declares, or when an AUTO not supported yet is on the same line (the block below is that AUTO’s too).
  • Differences from verilog-mode, deliberate: a variable whose type is a typedef, and an instance’s name, count as declared (verilog-mode declares them again, which does not compile); an AUTOWIRE in a module without a port list declares that module’s wires (verilog-mode reads the next module’s); a class or interface declared inside the module does not change which module the AUTOWIRE is in (verilog-mode then reads only up to endclass, or from class). A module whose name is a macro (module `NAME (…)) is left as it is.

/*AUTOOUTPUT*/, /*AUTOINPUT*/ and /*AUTOINOUT*/ declare ports for the module’s instances, below their line, as verilog-mode’s verilog-auto-output, verilog-auto-input and verilog-auto-inout do:

  • The instances are read as for AUTOWIRE (above). An output of an instance becomes an output unless the module has a port of that name or another instance reads it (as input or inout); an input becomes an input unless the module declares the name at all (port, net, variable, parameter, genvar, AUTO_CONSTANT) or an instance drives it; an inout becomes an inout unless the module has a port of that name or an instance has it as input or output.
  • They run in that order, then AUTOLOGIC and AUTOWIRE, each seeing what the ones before declared: a signal AUTOOUTPUT declared is not a wire too; two AUTOINPUTs of a module do not declare a name twice.
  • An argument keeps only some names: /*AUTOINPUT("^rx_")*/ the names the regular expression (Emacs syntax) matches anywhere, "?!^rx_" those it does not. Then verilog-auto-input-ignore-regexp (-output-, -inout-) leaves out the names it matches (with ?!, keeps only those). Both ignore case unless verilog-case-fold is nil. Two arguments stop the expansion with verilog-mode’s error, Expected <= 1 parameters.
  • Inside parentheses (the port list) each declaration ends with a comma, the comma before the ) is removed, and one is added after a port written before (not after (, a comma, (* … *) or `endif). An AUTO on the same line as the ) it is in stops the expansion with verilog-mode’s error, Mismatching (). Elsewhere, each ends with a semicolon.
  • The type is the port’s, verilog-auto-wire-type if set (none when it is "wire" and the type is none or logic), else verilog-auto-declare-nettype; with verilog-auto-inst-param-value, a type parameter the instance sets gives its value (#(.T_t(logic [3:0]))).
  • Left as they are for the same reasons as AUTOWIRE (but AUTOTIEOFF, which runs after them, does not leave them), and when another AUTO on their line is left (the block below is shared, and kept). An AUTO left makes those run after it in its module left too (an AUTOWIRE would see what an AUTOOUTPUT declares).
  • An argument that is not a string (/*AUTOINPUT(foo)*/) keeps all names, as in verilog-mode.
  • Differences from verilog-mode, deliberate: an interface port of the module and an instance’s name count as declared (verilog-mode declares an input of the same name again, which does not compile). The line an error names may differ from verilog-mode’s.

/*AUTORESET*/ writes, right after itself, a reset of zero for each signal its always block assigns, as verilog-mode’s verilog-auto-reset does:

  • The block is the one of the nearest always, always_ff, always_comb, always_latch or @ before the AUTO, read as verilog-mode reads it — a scan of the text, not a parse: every signal assigned anywhere in it counts (a bit, part or element assigned resets the whole signal; {a, b} <= … both), for loop variables do not.
  • Left out: every word between the nearest begin, if, case, casex, casez, always, always_ff, always_comb, always_latch or @ before the AUTO and the AUTO — what you reset by hand there, and what those lines read. A struct member is left out when the struct is.
  • <= for a signal assigned with <= anywhere in the block, = otherwise; verilog-assignment-delay goes after <=. With verilog-auto-reset-blocking-in-non set to nil, signals assigned only with = are left out of a block that has <=.
  • The value is zero at the declaration’s width: 8'h0, 4'sh0 (signed), {WIDTH{1'b0}}, '0/*NOWIDTH*/ when the width cannot be told; verilog-auto-reset-widths nil gives 0, unbased '0. A name matching verilog-active-low-regexp gets ~. A declaration whose type is a name not matching verilog-typedef-regexp is not read (width 1), as in verilog-mode.
  • A signal no longer assigned loses its reset: what the AUTO wrote before is not read.
  • Sorted by name; indented as the AUTO’s line. What follows the AUTO on its line ends up after // End of automatics, as in verilog-mode — so the next expansion deletes it: keep the AUTO alone on its line.
  • Left as it is (the hint says why) when a define it reads needs verilog-auto-read-includes, or when it is a second AUTORESET on the same line (verilog-mode stops with an error there).
  • Difference from verilog-mode: a declaration whose range is a define alone ([`RANGE]) is not read (width 1; verilog-mode writes '0/*NOWIDTH*/).

The instantiated module is found where verilog-mode looks for it: in the file, then <module>.v, .va, .sv in the file’s directory — or in verilog-library-directories with verilog-library-extensions, and in verilog-library-files; verilog-library-flags takes simulator arguments (-y dir, -v file, +incdir+dir, -Idir, +libext+.x, -f file, -F file, -DNAME=value for a `NAME module name). If it is none of those, the project is searched. Its ports are read with every `ifdef branch, as verilog-mode reads them, so the result does not depend on the defines in effect.

Code | Delete AUTOs removes what the AUTOs wrote and keeps the AUTO comments, as verilog-mode’s verilog-delete-auto (C-c C-d) does — for a smaller diff, or before editing by hand what an AUTO would overwrite. It is one command: Edit | Undo brings everything back.

module edge_pair (/*AUTOARG*/
// Outputs
rise_a, rise_b,
// Inputs
clk, a, b
);
…
edge_det u_a (/*AUTOINST*/
// Outputs
.hist (hist_a[1:0]), // Templated
…
.d (a)); // Templated

becomes

module edge_pair (/*AUTOARG*/);
…
edge_det u_a (/*AUTOINST*/);

What is removed, as verilog-mode removes it:

After Removed
/*AUTOARG*/, /*AUTOINST*/, /*AUTOINSTPARAM*/, /*AUTOSENSE*/ (/*AS*/), /*AUTOCONCATWIDTH*/ The text up to the parenthesis that closes the list the comment is in
Any other /*AUTO…*/ — /*AUTOWIRE*/, /*AUTOREG*/, /*AUTOINPUT("^in_")*/, your own The lines from the next one, if it starts with // Beginning, through the line with // End of automatics
A .* in an instance, when only ) or a // Outputs, // Inouts, // Inputs, // Interfaces or // Interfaced comment follows it The connections verilog-mode expanded it to, up to the )
— Everywhere, // Templated and // Implicit .* comments at the end of a line

AUTO comments are found in either case (/*autoinst*/ too), but not inside another comment or a string, and an AUTO_TEMPLATE comment is never removed. A .* followed by connections you wrote (.*, .clk(sys_clk)) is left alone, as is every .* when the file sets verilog-auto-star-expand to nil in its local variables.

If an AUTO that ends at a parenthesis is not inside one, or the parenthesis is never closed, nothing is removed at all (verilog-mode stops there, keeping what it removed before) and the message names the line.

verilog-mode keeps its settings per file, at the end of the file:

// Local Variables:
// verilog-auto-star-expand:nil
// End:

These are read as Emacs reads them: the text before Local Variables: (here // ) must start each line up to End:, a value may continue on the next lines, and settings on the first line (// -*- verilog-indent-level: 3 -*-) count too. An eval: entry runs in the Lisp sandbox when AUTOs are expanded (Lisp in AUTOs); Delete AUTOs never runs it.

  1. Open rtl/edge_pair.v from the sample project and choose Code | Delete AUTOs: the port lists become (/*AUTOARG*/), the two wire lines and their // Beginning/// End of automatics lines go, and each instance becomes edge_det u_a (/*AUTOINST*/);. The AUTO_TEMPLATE comment stays. Edit | Undo brings it all back.

  2. Create rtl/pair_top.v with module pair_top; edge_pair u_pair (/*AUTOINST*/); endmodule on three lines, as above, and choose Code | Expand AUTOs: the five ports of edge_pair are connected, outputs first.

  3. In rtl/edge_pair.v, change .rise (rise_@), in the AUTO_TEMPLATE to .rise (r_@), and choose Code | Expand AUTOs: the instances connect .rise (r_a) and .rise (r_b), and AUTOWIRE declares the new wires r_a and r_b; the hint names AUTOARG, left as it is.

  4. Change it to .rise (@"(upcase vl-cell-name)"), and choose Code | Expand AUTOs again: the instances connect .rise (U_A) and .rise (U_B), the instance names in capitals, and AUTOWIRE declares U_A and U_B.

  5. Replace rtl/pair_top.v from step 2 with a port list holding the two AUTOs, each on its own line: module pair_top (, /*AUTOINPUT*/, /*AUTOOUTPUT*/, );, then edge_pair u_pair (/*AUTOINST*/); and endmodule, and choose Code | Expand AUTOs: the inputs a, b, clk and the outputs rise_a, rise_b are declared in the port list, each with a comma but the last.