Difference between revisions of "Verilog Port Expressions"

From Verific Design Automation FAQ
Jump to: navigation, search
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 test (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
 +
</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.  
  
Output netlist:
+
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.
    module foo (p1, p2, p3, , p7);  // test.v(1[8:11])
+
        input p1;  // test.v(6[17:23])
+
        input p2;  // test.v(6[17:23])
+
        input [1:0]p3;
+
        input [2:0]p7;
+
        ...    
+
    endmodule
+
  
 +
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>
  
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.
+
'''Q2: Are "empty" ports Verilog-legal?'''
  
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.
+
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:
  
The original port expression of the renamed port is saved as attributes " orig_port_name" attached to the port.
+
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 [].
  
    key: " orig_port_name", value: port expression
+
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.''
 +
 
 +
For the example above, the netlist output from Verific is (note the leading space character of the attribute " orig_port_name"):
  
For the testcase above:
+
<nowiki>
 +
//
 +
// Verific Verilog Description of module test
 +
//
  
 +
module test (p1, p2, p3, , p7, p11, p12, ) /* verific  language=verilog,  cell_name=test */ ;  // test.sv(2)
 
     input p1 /* verific  orig_port_name=datain[0] */ ;
 
     input p1 /* verific  orig_port_name=datain[0] */ ;
 
     input p2 /* verific  orig_port_name=datain[0] */ ;
 
     input p2 /* verific  orig_port_name=datain[0] */ ;
 
     input [1:0]p3 /* verific  orig_port_name=datain[2] datain[1] */ ;
 
     input [1:0]p3 /* verific  orig_port_name=datain[2] datain[1] */ ;
 
     input [2:0]p7 /* verific  orig_port_name=datain[2] datain[1] datain[1] */ ;
 
     input [2:0]p7 /* verific  orig_port_name=datain[2] datain[1] datain[1] */ ;
 +
    output p11 /* verific  orig_port_name=dataout[3] */ ;
 +
    output [2:0]p12 /* verific  orig_port_name=dataout[2] dataout[1] dataout[0] */ ;
 +
    // Printing the identifier types
 +
    // datain  :  input [2:0] reg : nets: datain(bus)
 +
    // dataout  :  output [3:0] reg : nets: dataout(bus)
 +
   
 +
   
 +
    assign p1 = p2 /* verific  orig_port_name=datain[0] */ ;
 +
    assign p3[1] = p7[2] /* verific  orig_port_name=datain[2] */ ;
 +
    assign p3[0] = p7[0] /* verific  orig_port_name=datain[1] */ ;
 +
    assign p7[1] = p7[0] /* verific  orig_port_name=datain[1] */ ;
 +
   
 +
endmodule
 +
</nowiki>

Revision as of 10:59, 10 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 test (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
 

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.

For the example above, the netlist output from Verific is (note the leading space character of the attribute " orig_port_name"):

//
// Verific Verilog Description of module test
//

module test (p1, p2, p3, , p7, p11, p12, ) /* verific  language=verilog,  cell_name=test */ ;   // test.sv(2)
    input p1 /* verific  orig_port_name=datain[0] */ ;
    input p2 /* verific  orig_port_name=datain[0] */ ;
    input [1:0]p3 /* verific  orig_port_name=datain[2] datain[1] */ ;
    input [2:0]p7 /* verific  orig_port_name=datain[2] datain[1] datain[1] */ ;
    output p11 /* verific  orig_port_name=dataout[3] */ ;
    output [2:0]p12 /* verific  orig_port_name=dataout[2] dataout[1] dataout[0] */ ;
    // Printing the identifier types 
    // datain   :   input [2:0] reg : nets: datain(bus)
    // dataout   :   output [3:0] reg : nets: dataout(bus)
    
    
    assign p1 = p2 /* verific  orig_port_name=datain[0] */ ;
    assign p3[1] = p7[2] /* verific  orig_port_name=datain[2] */ ;
    assign p3[0] = p7[0] /* verific  orig_port_name=datain[1] */ ;
    assign p7[1] = p7[0] /* verific  orig_port_name=datain[1] */ ;
    
endmodule