Difference between revisions of "Verilog Port Expressions"

From Verific Design Automation FAQ
Jump to: navigation, search
 
Line 4: Line 4:
 
  <nowiki>
 
  <nowiki>
 
// Example of port expressions
 
// Example of port expressions
module test (datain[0], datain[0] /* same net into multiple port expression */,
+
module bot (datain[0], datain[0] /* same net into multiple port expression */,
 
             datain[2:1]  /* part-select port expression */,
 
             datain[2:1]  /* part-select port expression */,
 
             /* empty port expression - nothing between the two commas */,
 
             /* empty port expression - nothing between the two commas */,
Line 12: Line 12:
 
     input [2:0] datain;
 
     input [2:0] datain;
 
     output [3:0] dataout;
 
     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
 
endmodule
 
  </nowiki>
 
  </nowiki>
Line 45: Line 61:
 
:''The port expression is optional because ports can be defined that do not connect to anything internal to the module.''
 
:''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"):
+
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>
 
  <nowiki>
 
//
 
//
// Verific Verilog Description of module test
+
// 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 test (p1, p2, p3, , p7, p11, p12, ) /* verific  language=verilog,  cell_name=test */ ;  // test.sv(2)
+
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[0] */ ;
+
     input p1 /* verific orig_port_name="datain" */ ;   // test.v.golden.new(36)
     input p2 /* verific orig_port_name=datain[0] */ ;
+
     input p2 /* verific orig_port_name="datain" */ ;   // test.v.golden.new(37)
     input [1:0]p3 /* verific orig_port_name=datain[2] datain[1] */ ;
+
     input [1:0]p3;  // test.v.golden.new(38)
     input [2:0]p7 /* verific  orig_port_name=datain[2] datain[1] datain[1] */ ;
+
    input p6 /* verific empty_port=1 */ ;   // test.v.golden.new(39)
     output p11 /* verific orig_port_name=dataout[3] */ ;
+
     input [2:0]p7// test.v.golden.new(40)
     output [2:0]p12 /* verific orig_port_name=dataout[2] dataout[1] dataout[0] */ ;
+
     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  
 
     // Printing the identifier types  
     // datain   :  input [2:0] reg : nets: datain(bus)
+
     // p1  :  input  wire : nets: p1(net)
     // dataout   :  output [3:0] reg : nets: dataout(bus)
+
    // 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[0] */ ;
+
     assign p1 = p2 /* verific orig_port_name="datain" */ ;   // test.v.golden.new(36)
     assign p3[1] = p7[2] /* verific orig_port_name=datain[2] */ ;
+
     assign p3[1] = p7[2] /* verific orig_port_name="datain" */ ;   // test.v.golden.new(38)
     assign p3[0] = p7[0] /* verific orig_port_name=datain[1] */ ;
+
     assign p3[0] = p7[1] /* verific orig_port_name="datain" */ ;   // test.v.golden.new(38)
     assign p7[1] = p7[0] /* verific orig_port_name=datain[1] */ ;
+
     assign p7[0] = p7[1] /* verific orig_port_name="datain" */ ;   // test.v.golden.new(40)
 
      
 
      
 
endmodule
 
endmodule
 
  </nowiki>
 
  </nowiki>

Latest revision as of 14: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