Difference between revisions of "Verilog Port Expressions"

From Verific Design Automation FAQ
Jump to: navigation, search
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
'''Q: Why are the ports in original Verilog file renamed to p1, p2, ....?'''
+
'''Q1: Why are the ports in original Verilog RTL file renamed to p1, p2, ... in the output netlist?'''
  
Input file:
+
Verilog RTL file:
    module foo ( datain[0], datain[0] /* same net into multiple port expression */,
+
<nowiki>
                datain[2:1]  /* part-select port expression */,
+
// Example of port expressions
                /* empty port expression */,
+
module bot (datain[0], datain[0] /* same net into multiple port expression */,
                {datain[2],datain[1], datain[1]} /* concatenation in port expression */
+
            datain[2:1]  /* part-select port expression */,
                ) ;
+
            /* empty port expression - nothing between the two commas */,
        input [2:0] datain ;
+
            {datain[2], datain[1], datain[1]} /* concatenation in port expression */,
        ...
+
            dataout[3], {dataout[2:0]}, /* another empty port expression due to the extra comma */
     endmodule
+
            );
 +
    input [2:0] datain;
 +
     output [3:0] dataout;
 +
endmodule
  
Output netlist:
+
module top (input  in1, in2,
    module foo (p1, p2, p3, , p7);   // test.v(1[8:11])
+
                  [2:1] in3,
        input p1;  // test.v(6[17:23])
+
                  mt1,
        input p2;  // test.v(6[17:23])
+
                  [3:1] in4,
        input [1:0]p3;
+
            output out1,
        input [2:0]p7;
+
                  [2:0] out2,
        ...    
+
                  mt2);
    endmodule
+
    bot inst (in1, in2, // datain[0], datain[0]
 +
              in3,      // datain[2:1]
 +
              mt1,      // empty port
 +
              in4,      // datain[2:1]
 +
              out1,    // dataout[3]
 +
              out2,    // dataout[3]
 +
              mt2);     // empty port
 +
endmodule
 +
</nowiki>
 +
The items enclosed in the () after the module name are not "port names," rather, they are "port expressions." Verilog defines that the port expressions of a module CANNOT be accessed by name (only by order). This means you cannot rely on the port names to be one thing or another.  
  
 +
Verific chooses to not adjust any particular naming scheme for complex port expressions, which also allows us to error out if named port instantiation occurs where the language disallows it.
  
The items in the () after the module name are not "port names," rather, they are "port expressions." Verilog defines that the port expressions on this module CANNOT be accessed by name (only by order). This means you cannot rely on the port names to be one thing or another.
+
The original port expression of the renamed port is saved as attribute " orig_port_name" attached to the port.
 +
<nowiki>
 +
    key: " orig_port_name", value: port expression
 +
</nowiki>
  
Verific chose to not adjust to any particular naming scheme for complex port expressions, which also allows us to error out if named port instantiation occurs where the language disallows it.
+
'''Q2: Are "empty" ports Verilog-legal?'''
  
The original port expression of the renamed port is saved as attributes " orig_port_name" attached to the port.
+
The Verilog example at the top of the page contains two "empty" port expressions (nothing between two commas or an extra comma at the end of the port expression list). This is legal as shown below:
  
     key: " orig_port_name", value: port expression
+
In BNF section A.1.2 of IEEE 1800-2017 LRM:
 +
<nowiki>
 +
module_nonansi_header ::=
 +
     { attribute_instance } module_keyword [ lifetime ] module_identifier
 +
    { package_import_declaration } [ parameter_port_list ] list_of_ports ;
 +
   
 +
list_of_ports ::= ( port { , port } )
 +
   
 +
port ::=
 +
      [ port_expression ]
 +
    | . port_identifier ( [ port_expression ] )
 +
</nowiki>
 +
"port_expression" is optional because it is enclosed within [].
 +
 
 +
In section 23.2.2.1 of the same LRM on "Non-ANSI style port declarations":
 +
 
 +
:''The port expression is optional because ports can be defined that do not connect to anything internal to the module.''
 +
 
 +
Note that Verific created ports with name for empty ports. By default, the empty ports are not written out in the Verilog netlist output (similar to the module in the input RTL file).
 +
 
 +
If a module with empty ports is instantiated by another module, as in the example at the top of this page, its empty ports need to be written out in the Verilog netlist output. Otherwise the netlist output is not Verilog-legal.
 +
 
 +
To write out empty ports, the runtime flag ''''db_verilog_writer_preserve_empty_ports'''' has to be set to 0 (it is set to 1 by default). Each of the empty ports will have the attribute ' empty_port' attached to it.
 +
 
 +
For the example above, the netlist output from Verific is:
 +
 
 +
<nowiki>
 +
//
 +
// Verific Verilog Description of module top
 +
//
 +
 
 +
module top (in1, in2, in3, mt1, in4, out1, out2, mt2) /* verific  language=verilog,  cell_name=top, language="verilog", cell_name="top" */ ;  // test.v.golden.new(6)
 +
    input in1;  // test.v.golden.new(7)
 +
    input in2;  // test.v.golden.new(8)
 +
    input [2:1]in3;  // test.v.golden.new(9)
 +
    input [2:1]mt1;  // test.v.golden.new(10)
 +
    input [3:1]in4;  // test.v.golden.new(11)
 +
    output out1;  // test.v.golden.new(12)
 +
    output [2:0]out2;  // test.v.golden.new(13)
 +
    output [2:0]mt2;  // test.v.golden.new(14)
 +
    // Printing the identifier types
 +
    // in1  :  input  wire : nets: in1(net)
 +
    // in2  :  input  wire : nets: in2(net)
 +
    // in3  :  input [2:1] reg : nets: in3(bus)
 +
    // mt1  :  input [2:1] reg : nets: mt1(bus)
 +
    // in4  :  input [3:1] reg : nets: in4(bus)
 +
    // out1  :  output  wire : nets: out1(net)
 +
    // out2  :  output [2:0] reg : nets: out2(bus)
 +
    // mt2  :  output [2:0] reg : nets: mt2(bus)
 +
   
 +
   
 +
    bot inst (.p1(in1), .p2(in2), .p3({in3}), .p6(mt1[1]), .p7({in4}),
 +
        .p11(out1), .p12({out2}), .p16(mt2[0]));  // test.v.golden.new(26)
 +
   
 +
endmodule
  
For the testcase above:
+
//
 +
// Verific Verilog Description of module bot
 +
//
  
     input p1 /* verific orig_port_name=datain[0] */ ;
+
module bot (p1, p2, p3, p6, p7, p11, p12, p16) /* verific  language=verilog,  cell_name=bot, language="verilog", cell_name="bot" */ ;  // test.v.golden.new(35)
     input p2 /* verific orig_port_name=datain[0] */ ;
+
     input p1 /* verific orig_port_name="datain" */ ;  // test.v.golden.new(36)
     input [1:0]p3 /* verific orig_port_name=datain[2] datain[1] */ ;
+
    input p2 /* verific orig_port_name="datain" */ ;  // test.v.golden.new(37)
     input [2:0]p7 /* verific orig_port_name=datain[2] datain[1] datain[1] */ ;
+
    input [1:0]p3;  // test.v.golden.new(38)
 +
    input p6 /* verific empty_port=1 */ ;   // test.v.golden.new(39)
 +
     input [2:0]p7;  // test.v.golden.new(40)
 +
    output p11 /* verific orig_port_name="dataout" */ ;  // test.v.golden.new(41)
 +
    output [2:0]p12;  // test.v.golden.new(42)
 +
    input p16 /* verific empty_port=1 */ ;   // test.v.golden.new(43)
 +
     // Printing the identifier types
 +
    // p1  :  input  wire : nets: p1(net)
 +
    // p2  :  input  wire
 +
    // p3  :  input [1:0] reg : nets: p3(bus)
 +
    // p6  :  input  wire : nets: p6(net)
 +
    // p7  :  input [2:0] reg
 +
    // p11  :  output  wire : nets: p11(net)
 +
    // p12  :  output [2:0] reg : nets: p12(bus)
 +
    // p16  :  input  wire : nets: p16(net)
 +
   
 +
    wire p2 /* verific orig_port_name="datain" */ ;  // test.v.golden.new(36)
 +
    wire [1:0]p3_c /* verific orig_port_name="datain" */ ;  // test.v.golden.new(38)
 +
    wire p6 /* verific empty_port=1 */ ;   // test.v.golden.new(39)
 +
     wire p11 /* verific orig_port_name="dataout" */ ;  // test.v.golden.new(41)
 +
    wire [2:0]p12 /* verific orig_port_name="dataout" */ ;  // test.v.golden.new(42)
 +
    wire p16 /* verific empty_port=1 */ ;  // test.v.golden.new(43)
 +
   
 +
    assign p1 = p2 /* verific orig_port_name="datain" */ ;  // test.v.golden.new(36)
 +
    assign p3[1] = p7[2] /* verific orig_port_name="datain" */ ;  // test.v.golden.new(38)
 +
    assign p3[0] = p7[1] /* verific orig_port_name="datain" */ ;  // test.v.golden.new(38)
 +
    assign p7[0] = p7[1] /* verific orig_port_name="datain" */ ;   // test.v.golden.new(40)
 +
   
 +
endmodule
 +
</nowiki>

Latest revision as of 13:40, 13 February 2023

Q1: Why are the ports in original Verilog RTL file renamed to p1, p2, ... in the output netlist?

Verilog RTL file:

// Example of port expressions
module bot (datain[0], datain[0] /* same net into multiple port expression */,
             datain[2:1]  /* part-select port expression */,
             /* empty port expression - nothing between the two commas */,
             {datain[2], datain[1], datain[1]} /* concatenation in port expression */,
             dataout[3], {dataout[2:0]}, /* another empty port expression due to the extra comma */
            );
    input [2:0] datain;
    output [3:0] dataout;
endmodule

module top (input  in1, in2,
                   [2:1] in3,
                   mt1,
                   [3:1] in4,
            output out1,
                   [2:0] out2,
                   mt2);
    bot inst (in1, in2, // datain[0], datain[0]
              in3,      // datain[2:1]
              mt1,      // empty port
              in4,      // datain[2:1]
              out1,     // dataout[3]
              out2,     // dataout[3]
              mt2);     // empty port
endmodule
 

The items enclosed in the () after the module name are not "port names," rather, they are "port expressions." Verilog defines that the port expressions of a module CANNOT be accessed by name (only by order). This means you cannot rely on the port names to be one thing or another.

Verific chooses to not adjust any particular naming scheme for complex port expressions, which also allows us to error out if named port instantiation occurs where the language disallows it.

The original port expression of the renamed port is saved as attribute " orig_port_name" attached to the port.

    key: " orig_port_name", value: port expression
 

Q2: Are "empty" ports Verilog-legal?

The Verilog example at the top of the page contains two "empty" port expressions (nothing between two commas or an extra comma at the end of the port expression list). This is legal as shown below:

In BNF section A.1.2 of IEEE 1800-2017 LRM:

module_nonansi_header ::=
    { attribute_instance } module_keyword [ lifetime ] module_identifier
    { package_import_declaration } [ parameter_port_list ] list_of_ports ;
    
list_of_ports ::= ( port { , port } )
    
port ::=
      [ port_expression ]
    | . port_identifier ( [ port_expression ] )
 

"port_expression" is optional because it is enclosed within [].

In section 23.2.2.1 of the same LRM on "Non-ANSI style port declarations":

The port expression is optional because ports can be defined that do not connect to anything internal to the module.

Note that Verific created ports with name for empty ports. By default, the empty ports are not written out in the Verilog netlist output (similar to the module in the input RTL file).

If a module with empty ports is instantiated by another module, as in the example at the top of this page, its empty ports need to be written out in the Verilog netlist output. Otherwise the netlist output is not Verilog-legal.

To write out empty ports, the runtime flag 'db_verilog_writer_preserve_empty_ports' has to be set to 0 (it is set to 1 by default). Each of the empty ports will have the attribute ' empty_port' attached to it.

For the example above, the netlist output from Verific is:

//
// Verific Verilog Description of module top
//

module top (in1, in2, in3, mt1, in4, out1, out2, mt2) /* verific  language=verilog,  cell_name=top, language="verilog", cell_name="top" */ ;   // test.v.golden.new(6)
    input in1;   // test.v.golden.new(7)
    input in2;   // test.v.golden.new(8)
    input [2:1]in3;   // test.v.golden.new(9)
    input [2:1]mt1;   // test.v.golden.new(10)
    input [3:1]in4;   // test.v.golden.new(11)
    output out1;   // test.v.golden.new(12)
    output [2:0]out2;   // test.v.golden.new(13)
    output [2:0]mt2;   // test.v.golden.new(14)
    // Printing the identifier types 
    // in1   :   input  wire : nets: in1(net)
    // in2   :   input  wire : nets: in2(net)
    // in3   :   input [2:1] reg : nets: in3(bus)
    // mt1   :   input [2:1] reg : nets: mt1(bus)
    // in4   :   input [3:1] reg : nets: in4(bus)
    // out1   :   output  wire : nets: out1(net)
    // out2   :   output [2:0] reg : nets: out2(bus)
    // mt2   :   output [2:0] reg : nets: mt2(bus)
    
    
    bot inst (.p1(in1), .p2(in2), .p3({in3}), .p6(mt1[1]), .p7({in4}), 
        .p11(out1), .p12({out2}), .p16(mt2[0]));   // test.v.golden.new(26)
    
endmodule

//
// Verific Verilog Description of module bot
//

module bot (p1, p2, p3, p6, p7, p11, p12, p16) /* verific  language=verilog,  cell_name=bot, language="verilog", cell_name="bot" */ ;   // test.v.golden.new(35)
    input p1 /* verific orig_port_name="datain" */ ;   // test.v.golden.new(36)
    input p2 /* verific orig_port_name="datain" */ ;   // test.v.golden.new(37)
    input [1:0]p3;   // test.v.golden.new(38)
    input p6 /* verific empty_port=1 */ ;   // test.v.golden.new(39)
    input [2:0]p7;   // test.v.golden.new(40)
    output p11 /* verific orig_port_name="dataout" */ ;   // test.v.golden.new(41)
    output [2:0]p12;   // test.v.golden.new(42)
    input p16 /* verific empty_port=1 */ ;   // test.v.golden.new(43)
    // Printing the identifier types 
    // p1   :   input  wire : nets: p1(net)
    // p2   :   input  wire
    // p3   :   input [1:0] reg : nets: p3(bus)
    // p6   :   input  wire : nets: p6(net)
    // p7   :   input [2:0] reg
    // p11   :   output  wire : nets: p11(net)
    // p12   :   output [2:0] reg : nets: p12(bus)
    // p16   :   input  wire : nets: p16(net)
    
    wire p2 /* verific orig_port_name="datain" */ ;   // test.v.golden.new(36)
    wire [1:0]p3_c /* verific orig_port_name="datain" */ ;   // test.v.golden.new(38)
    wire p6 /* verific empty_port=1 */ ;   // test.v.golden.new(39)
    wire p11 /* verific orig_port_name="dataout" */ ;   // test.v.golden.new(41)
    wire [2:0]p12 /* verific orig_port_name="dataout" */ ;   // test.v.golden.new(42)
    wire p16 /* verific empty_port=1 */ ;   // test.v.golden.new(43)
    
    assign p1 = p2 /* verific orig_port_name="datain" */ ;   // test.v.golden.new(36)
    assign p3[1] = p7[2] /* verific orig_port_name="datain" */ ;   // test.v.golden.new(38)
    assign p3[0] = p7[1] /* verific orig_port_name="datain" */ ;   // test.v.golden.new(38)
    assign p7[0] = p7[1] /* verific orig_port_name="datain" */ ;   // test.v.golden.new(40)
    
endmodule