Updated Port proposal, which includes UDP's

From: Michael McNamara (mac@surefirev.com)
Date: Mon Apr 19 1999 - 09:51:54 PDT


Here is an updated proposal, which includes UDP's:

<x-html><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
  <head>
    <title>ANSI Port Declarations</title>
  </head>

  <body bgcolor="ffffff">
    <h1>ANSI Port Declarations</h1>
    <p>
      This proposal adds an alternate method for declaring module,
      user defined primitives (UDP's), task and function ports to the
      Verilog Hardware Description Language.</p>
    <p>
    <hr width="10%" align=center>
    <h2> Port Declarations </h2>
    <hr>
    <p>
      At present, the Verilog language requires that the ports of a
      module (and of a UDP) be listed, by name, in parenthetical list
      just after the module name. Further, it is required that each
      port be again declared somewhere in the module as one of an
      <b>input</b>, <b>output</b> or <b>inout</b>. Optionally the port
      may again be declared as a <b>wire</b> (the default) or as a
      <b>reg</b>.
    </p>
<table border=1>
<td>
<table>
<tr>
<td valign="top">module_declaration </td><td>::= module_keyword <I>module</I>_identifier [ list_of_ports ] <B>;</B>&#9;{ module_item } <B>endmodule</b> </td>
</tr>
<tr>
<td valign="top">module_keyword</td><td>::= <B>module</B> | <B>macromodule</b></td>
</tr>
<tr>
<td valign="top">list_of_ports</td><td>::= <B>(</B> port { <B>,</B> port } <B>)</b></td>
</tr>
<tr>
<td valign="top">port</td> <td>::= [ port_expression ]</td>
</tr>
<td></td> <td>| <B>.</B> <I>port</I>_identifier <B>(</B> [ port_expression ] <B>) </td>
<tr>
<td valign="top">port_expression</td><td>::= port_reference </td>
</tr>
<tr>
<td></td><td>| <B>{</B> port_reference { <B>,</B> port_reference } <B>}</B></td>
</tr>
<tr>
<td valign="top">port_reference</td><td>::= <I>port</I>_identifier </td>
</tr>
<tr>
<td></td><td>| <I>port</I>_identifier <B>[</B> constant_expression <B>]</B></td></tr>
<tr>
<td></td><td>| <I>port</I>_identifier <B>[</B> <I>msb</I>_constant_expression <B>:</B> <I>lsb</I>_constant_expression <B>]</td></tr>
</table>
</td>
</table>
    <p>And then as a module item we have:</p>
<table border=1>
<td>
<table>
<tr>
<td>module_item</td><td>::= module_item_declaration</td>
</tr>
<tr>
<tr><td valign="top">module_item_declaration</td><td>::= parameter_declaration</td></tr>
<tr><td></td><td>| input_declaration</td></tr>
<tr><td></td><td>| output_declaration</td></tr>
<tr><td></td><td>| inout_declaration</td></tr>
<tr><td></td><td>| net_declaration</td></tr>
<tr><td></td><td>| reg_declaration</td></tr>
<tr><td></td><td><b>...</b></td></tr>

<tr><td valign="top">input_declaration </td><td>::= <B>input</B> <B>[</B> range <B>]</B> list_of_port_identifiers <B>;</b></td></tr>
<tr><td valign="top"><P>output_declaration </td><td>::= <B>output</B> <B>[</B> range <B>]</B> list_of_port_identifiers <B>;</b> </td></tr>
<tr><td valign="top"><P>inout_declaration </td><td>::= <B>inout</B> <B>[</B> range <B>]</B> list_of_port_identifiers <B>;</b> </td></tr>

</table>
</td>
</table>
    <p> Similarily for UDPs, we have:
<table border=1>
<td>
<table>
<tr><td>udp_declaration</td><td>::= <B>primitive</B> <I>udp</I>_identifier <B>(</B> udp_port_list <B>)</B> <B>;</b></td>
<tr><td></td><td>udp_port_declaration { udp_port_declaration }</td>
<tr><td></td><td>udp_body</td>
<tr><td></td><td><B>endprimitive</b></td>
<tr><td>udp_port_list</td><td>::= <I>output_port</I>_identifier <B>,</B> <I>input_port</I>_identifier { <B>,</B> <I>input_port</I>_identifier }</td>
<tr><td>udp_port_declaration</td><td>::= output_declaration</td>
<tr><td></td><td>| input_declaration</td>
<tr><td></td><td>| reg_declaration</td>
</table>
</td>
</table>
    <p> Of course these are very similar to the original C Programming
    Language, (affectionately known as K&R C), which was enhanced by
    simpler port declarations in ANSI C.
    </p>

    <p> Further, at present declarations of tasks and functions do not
    support a parenthetical list of ports. Instead the inputs, locals,
    and in the case of tasks, outputs and inouts of the tasks must be
    listed after the task or function name declaration.</p>

<table border=1>
<td>
<table>
<tr>
<td valign="top">function_declaration</td><td>::= <b>function</b> [range_or_type] <i>function</i>_identifier ; <br>function_item_declaration {function_item_declaration} <br>statement<br> <b>endfunction</b></td>
</tr>
<tr>
<tr><td valign="top">function_item_declaration</td><td>::= block_item_declaration</td></tr>
<tr><td></td><td>| input_declaration</td></tr>

<td valign="top">task_declaration</td><td>::= <b>task</b> <i>task</i>_identifier ;<br>task_item_declaration {task_item_declaration}<br> statement<br> <b>endtask</b></td>
</tr>
<tr>
<tr><td valign="top">task_item_declaration</td><td>::= block_item_declaration</td></tr>
<tr><td></td><td>| input_declaration</td></tr>
<tr><td></td><td>| output_declaration</td></tr>
<tr><td></td><td>| inout_declaration</td></tr>
</table>
</table>

    <p> After some discussion in the Verilog-1364 Behavioral Task
    Force, and later in the entire Verilog-1364 working group,
    consensus emerged supporting an extension to the Verilog language
    closely following that of ANSI C's enhancement to K&R C, as
    follows.</p>

    <p> For module, UDP, task and function declarations, users can
    either continue to use the existing syntax, or they can use the
    new parenthetical port declaration syntax.</p>
    
    <p> This proposal does the following, with the BNF below:
      <ol type="1">

        <li> enhances the <b>input_declaration</b>,
        <b>output_declaration</b>, and <b>inout_declaration</b> to
        allow specification of net or reg type and signedness.

        <li> allows <b>input_declaration</b>s,
        <b>output_declaration</b>s and <b>inout_declaration</b>s to be
        used as port_references.

        <li> allows <b>input_declaration</b>s and
        <b>output_declaration</b>s to be used in the udp_port_list.

        <li> introduces a <b>function_port_list</b> and
        <b>task_port_list</b> that can be used as an alternative to
        the current function and task declaration syntax.
        
        <li> introduces a <b>parameter_port_list</b> that can be used
        to define parameters and local parameters of modules, tasks
        and functions, especially where the parameters are used to
        size the width of input, output and inout ports.
            
        <li> introduces the semantic restriction that only those
        parameters in the #(..) list may be overridden. This means
        that a new style module, task or function declaration that
        includes no #(..) list, no parameters may be overridden.

        <li> introduces the semantic clarification that parameter
        overrides by position shall skip over any local parameters
        declarations in the paramter port list when calculating which
        override applies to which parameter declaration.

        <li> introduces the semantic restriction that a particular
        module, task or function declaration must either use the
        existing 1364-1995 port declaration syntax, or the new syntax;
        but may not mix both styles in the same declaration. A given
        design may use modules tasks and functions, where some are
        declared in the old syntax, and some in the new syntax.
    </ol>

<table border=1>
<td>
<table>
<tr>
<td valign="top">module_declaration </td><td>::= module_keyword <I>module</I>_identifier <font color="red"> [ parameter_port_list ] </font> [ list_of_ports ] <B>;</B>&#9;{ module_item } <B>endmodule</b> </td>
</tr>
<tr>
<td valign="top">module_keyword</td><td>::= <B>module</B> | <B>macromodule</b></td>
</tr>
<tr>
<td valign="top"><font color="red">parameter_port_list</font></td><td><font color="red">::= <B># (</B> parameter_declaration { parameter_declaration } <B>)</b></font></td>
</tr>
<tr>
<td valign="top">list_of_ports</td><td>::= <B>(</B> port { <B>,</B> port } <B>)</b></td>
</tr>
<tr>
<td valign="top">port</td> <td>::= [ port_expression ]</td>
</tr>
<td></td> <td>| <B>.</B> <I>port</I>_identifier <B>(</B> [ port_expression ] <B>) </td>
<tr>
<td valign="top">port_expression</td><td>::= port_reference </td>
</tr>
<tr>
<td></td><td>| <B>{</B> port_reference { <B>,</B> port_reference } <B>}</B></td>
</tr>
<tr>
<td valign="top">port_reference</td><td>::= <I>port</I>_identifier </td>
</tr>
<tr>
<td></td><td>| <I>port</I>_identifier <B>[</B> constant_expression <B>]</B></td></tr>
<tr>
<td></td><td>| <I>port</I>_identifier <B>[</B> <I>msb</I>_constant_expression <B>:</B> <I>lsb</I>_constant_expression <B>]</b></td></tr>
<tr>
<td></td><td>| <I>port</I>_identifier <B>[</B> constant_expression <B>]</B></td></tr>
<td></td><td><font color="red">| input_declaration</font></td></tr>
<td></td><td><font color="red">| output_declaration</font></td></tr>
<td></td><td><font color="red">| inout_declaration</font></td></tr>

<tr><td></td><td><b>...</b></td></tr>

<tr><td>udp_declaration</td><td>::= <B>primitive</B> <I>udp</I>_identifier <B>(</B> udp_port_list <B>)</B> <B>;</b></td>
<tr><td></td><td>udp_port_declaration { udp_port_declaration }</td>
<tr><td></td><td>udp_body</td>
<tr><td></td><td><B>endprimitive</b></td>
<tr><td>udp_port_list</td><td>::= <I>output_port</I>_identifier <B>,</B> <I>input_port</I>_identifier { <B>,</B> <I>input_port</I>_identifier }</td>
<tr><td></td><td><font color="red">| output_declaration <B>,</B> input_declaration { <B>,</B> input_declaration }</font></td>
<tr><td>udp_port_declaration</td><td>::= output_declaration</td>
<tr><td></td><td>| input_declaration</td>
<tr><td></td><td>| reg_declaration</td>

<tr><td></td><td><b>...</b></td></tr>

<tr><td valign="top">input_declaration </td><td>::= <B>input</B> <font color="red">[ <B>signed </B>] [ net_type ] </font> <B>[</B> range <B>]</B> list_of_port_identifiers</td></tr>
<tr><td valign="top">output_declaration </td><td>::= <B>output</B> <font color="red">[ <B>signed </B>] [ net_type ] </font> <B>[</B> range <B>]</B> list_of_port_identifiers</td></tr>
<tr><td valign="top"></td><td>::= <B>output</B> <font color="red">[ <B>signed </B>] [ reg_type ] </font> <B>[</B> range <B>]</B> list_of_port_identifiers</td></tr>
<tr><td valign="top"></td><td>::= <B>output</B> <font color="red">[ <B>signed </B>] [ reg_type ] </font> <B>[</B> range <B>]</B> list_of_reg_decl_assignments</td></tr>
<tr><td valign="top">inout_declaration </td><td>::= <B>inout</B> <font color="red">[ <B>signed </B>] [ net_type ] </font><B>[</B> range <B>]</B> list_of_port_identifiers</td></tr>
<tr>
<tr>
<tr>
<td valign="top">function_declaration</td><td>::= <b>function</b> [range_or_type] <i>function</i>_identifier ; <br>function_item_declaration {function_item_declaration} <br>statement<br> <b>endfunction</b></td>
</tr>
<tr><td valign="top"></td><td><font color="red"> | <b>function</b> [range_or_type] <i>function</i>_identifier ( function_port_list ) ; <br>block_item_declaration {block_item_declaration} <br>statement<br> <b>endfunction</b></font></td>
</tr>
<tr>
<tr><td valign="top">function_item_declaration</td><td>::= block_item_declaration</td></tr>
<tr><td></td><td>| input_declaration</td></tr>
<tr><td valign="top"><font color="red">function_port_list</td><td><font color="red">::= input_declaration { input_declaration } <br></td></tr>
<tr>
<td valign="top">task_declaration</td><td>::= <b>task</b> <i>task</i>_identifier ;<br>task_item_declaration {task_item_declaration}<br> statement<br> <b>endtask</b></td>
</tr>
<tr>
<td valign="top"></td><td><font color="red"> | <b>task</b> <i>task</i>_identifier ( task_port_list ) ;<br>block_item_declaration {block_item_declaration}<br> statement<br> <b>endtask</b></font></td>
</tr>
<tr>
<tr><td valign="top">task_item_declaration</td><td>::= block_item_declaration</td></tr>
<tr><td></td><td>| input_declaration</td></tr>
<tr><td></td><td>| output_declaration</td></tr>
<tr><td></td><td>| inout_declaration</td></tr>
<font color="red">
<tr><td valign="top"><font color="red">task_port_list</td><td><font color="red">::= task_port_item { task_port_item } </td></tr>
<tr><td valign="top"><font color="red">task_port_item</td><td><font color="red">::= input_declaration</td></tr>
<tr><td></td><td><font color="red">| output_declaration</td></tr>
<tr><td></td><td><font color="red">| inout_declaration</td></tr>
</font>
</table>
</td>
</table>
<p> Note that a separate proposal is adding the keyword <b>signed</b>
to the language; and the optional keyword signed is merely included
here to show that should signed constructs be introduced, it would be
legal to include the declaration in the port_reference production</p>
<p>Given this syntax, the following two module declarations are
equivalent:<p> <table border=1><td>
<xmp>
module acc_fsm( CLK, RST, IT_IL_RQ, IT_RQ_VLD, RdMsg,
                WrMsg, AccessOK, XX_IL_PIODONE, OM_IL_GT,
                RespVld, IL_IT_GT, CaptureAddress, CaptureData,
                IL_XX_PIORD, IL_XX_PIOWR, IL_OM_RQ,
                SelectResp, SetRespVld, ClrRespVld);
   parameter DATAWIDTH=64;
   input CLK, RST;
   input IT_IL_RQ,
                       IT_RQ_VLD,
                       RdMsg,
                       WrMsg,
                       AccessOK,
                       XX_IL_PIODONE;
   input OM_IL_GT,
                       RespVld;
   output [31:0] CaptureAddress;
   output [DATAWIDTH-1:0] CaptureData;
   output IL_IT_GT,
                       IL_XX_PIORD,
                       IL_XX_PIOWR,
                       IL_OM_RQ,
                       SelectResp,
                       SetRespVld,
                       ClrRespVld;
   reg [31:0] CaptureAddress;
   reg [DATAWIDTH-1:0] CaptureData,
   reg [2:0] LE_NxtState,
                       LE_State;
   reg IL_IT_GT,
                       IL_XX_PIORD;
   reg IL_XX_PIOWR,
                       IL_OM_RQ,
                       SelectResp,
                       SetRespVld,
                       ClrRespVld;
</xmp>
</td></table>
    <p>and</p>
<table border=1><td>
<xmp>
module acc_fsm #( parameter DATAWIDTH=64)
                 ( input wire CLK, RST, IT_IL_RQ, IT_RQ_VLD, RdMsg,
                              WrMsg, AccessOK, XX_IL_PIODONE,
                              OM_IL_GT, RespVld,
                   output reg [31:0] CaptureAddress,
                   output reg [DATAWIDTH-1:0] CaptureData,
                   output reg IL_IT_GT, IL_XX_PIORD, IL_XX_PIOWR,
                              IL_OM_RQ, SelectResp, SetRespVld, ClrRespVld
                 );
   reg [ 2 : 0] LE_NxtState,
                       LE_State;
</xmp>
</td></table>

<p> Things to note:
      <ol>
      <li> The second module declaration is much more compact.(38
      words instead of 70). Also note that this is a <b>small</b>
      example; many datapath modules contain as many as a thousand
      ports, each which may need to be declared three times.

      <li> The second module declaration is much easier to reuse:
      changing the width of the CaptureAddress bus to 48 bits requires
      modifying one location, instead of two, which potentially are
      many lines apart.

      <li> With the second module declaration local variables are
      clearly distinct from port variables.
        
      <li> With the second module declaration global analysis can
      examine just the port list in order to determine all necessary
      information about the input output characteristics of a module.

      <li> Declaring the modifiable parameter declarations in a
      separate list, with the list enclosed in '#(' and )' looks just
      like the module instance parameter override syntax. This also
      encapsulates and focuses attention the interface nature of these
      parameters.

      <li> Overall, the new module declaration centers the information
      that a user of this module must look at to successfully
      interface to the module in one place, at the top of the module.
      The details of the implementation are listed later. Hence Verilog
      becomes more object oriented.

      <li> There has been some suggestion that using constant
      functions in module i/o declarations to define widths would
      require that the definition of the constant function precede the
      use; however private discussion has cleared this up. The value
      of the parameters at the point of the 'call' to the constant
      function are all that is needed to determine its value. An
      exaple is useful:

<table border=1><td>
<xmp>
module acc_fsm #( parameter DATAWIDTH=8, TSIZE=cf_tsize(DATAWIDTH) )
                 ( input wire CLK, RST,
                   output reg [TSIZE-1:0] CaptureDataOut,
                   input wire [TSIZE-1:0] CaptureDataIn
                 );
   reg [2:0] LE_NxtState,
             LE_State;

  parameter B=DATAWIDTH*2;

  function [31:0] cf_tsize(input [31:0] w);
  cf_tsize = w**B;
  endfunction
endmodule
</xmp>
</td></table>

The parameter B is not yet defined at the location that TSIZE is
assigned the value of the constant function cf_tsize, and hence this
usage is illegal. The fix would be to move the definition of the
parameter B into the parameter port list. (perhaps even as a
localparam).

    </ol>
    <hr>
    <address><a href="mailto:mac@surefirev.com">Michael
    McNamara</a></address> <!-- Created: Wed Apr 1 15:28:56 PST 1998
    --> <!-- hhmts start --> Last modified: Fri Jan 8 18:16:27 PST
    1999 <!-- hhmts end -->
  </body>
</html>
</x-html>
And for the html challenged:

<p>ANSI Port Declarations

This proposal adds an alternate method for declaring module, user defined
primitives (UDP's), task and function ports to the Verilog Hardware
Description Language.

Port Declarations

At present, the Verilog language requires that the ports of a module (and of
a UDP) be listed, by name, in parenthetical list just after the module name.
Further, it is required that each port be again declared somewhere in the
module as one of an input, output or inout. Optionally the port may again be
declared as a wire (the default) or as a reg.

 module_declaration ::= module_keyword module_identifier [ list_of_ports
                     ] ; { module_item } endmodule
 module_keyword ::= module | macromodule
 list_of_ports ::= ( port { , port } )
 port ::= [ port_expression ]
                     | . port_identifier ( [ port_expression ] )
 port_expression ::= port_reference
                     | { port_reference { , port_reference } }
 port_reference ::= port_identifier
                     | port_identifier [ constant_expression ]
                     | port_identifier [ msb_constant_expression :
                     lsb_constant_expression ]

And then as a module item we have:

 module_item ::= module_item_declaration

 module_item_declaration ::= parameter_declaration
                         | input_declaration
                         | output_declaration
                         | inout_declaration
                         | net_declaration
                         | reg_declaration
                         ...
 input_declaration ::= input [ range ] list_of_port_identifiers ;
 output_declaration ::= output [ range ] list_of_port_identifiers ;
 inout_declaration ::= inout [ range ] list_of_port_identifiers ;

Similarily for UDPs, we have:

 udp_declaration ::= primitive udp_identifier ( udp_port_list ) ;
                      udp_port_declaration { udp_port_declaration }
                      udp_body
                      endprimitive

 udp_port_list ::= output_port_identifier , input_port_identifier {
                      , input_port_identifier }
 udp_port_declaration ::= output_declaration
                      | input_declaration
                      | reg_declaration

Of course these are very similar to the original C Programming Language,
(affectionately known as K&R C), which was enhanced by simpler port
declarations in ANSI C.

Further, at present declarations of tasks and functions do not support a
parenthetical list of ports. Instead the inputs, locals, and in the case of
tasks, outputs and inouts of the tasks must be listed after the task or
function name declaration.

 function_declaration ::= function [range_or_type]
                           function_identifier ;
                           function_item_declaration
                           {function_item_declaration}
                           statement
                           endfunction

 function_item_declaration ::= block_item_declaration
                           | input_declaration
 task_declaration ::= task task_identifier ;
                           task_item_declaration {task_item_declaration}
                           statement
                           endtask

 task_item_declaration ::= block_item_declaration
                           | input_declaration
                           | output_declaration
                           | inout_declaration

After some discussion in the Verilog-1364 Behavioral Task Force, and later
in the entire Verilog-1364 working group, consensus emerged supporting an
extension to the Verilog language closely following that of ANSI C's
enhancement to K&R C, as follows.

For module, UDP, task and function declarations, users can either continue
to use the existing syntax, or they can use the new parenthetical port
declaration syntax.

This proposal does the following, with the BNF below:

  1. enhances the input_declaration, output_declaration, and
     inout_declaration to allow specification of net or reg type and
     signedness.
  2. allows input_declarations, output_declarations and inout_declarations
     to be used as port_references.
  3. allows input_declarations and output_declarations to be used in the
     udp_port_list.
  4. introduces a function_port_list and task_port_list that can be used as
     an alternative to the current function and task declaration syntax.
  5. introduces a parameter_port_list that can be used to define parameters
     and local parameters of modules, tasks and functions, especially where
     the parameters are used to size the width of input, output and inout
     ports.
  6. introduces the semantic restriction that only those parameters in the
     #(..) list may be overridden. This means that a new style module, task
     or function declaration that includes no #(..) list, no parameters may
     be overridden.
  7. introduces the semantic clarification that parameter overrides by
     position shall skip over any local parameters declarations in the
     paramter port list when calculating which override applies to which
     parameter declaration.
  8. introduces the semantic restriction that a particular module, task or
     function declaration must either use the existing 1364-1995 port
     declaration syntax, or the new syntax; but may not mix both styles in
     the same declaration. A given design may use modules tasks and
     functions, where some are declared in the old syntax, and some in the
     new syntax.

 module_declaration ::= module_keyword module_identifier [
                           parameter_port_list ] [ list_of_ports ] ; {
                           module_item } endmodule
 module_keyword ::= module | macromodule
 parameter_port_list ::= # ( parameter_declaration {
                           parameter_declaration } )
 list_of_ports ::= ( port { , port } )
 port ::= [ port_expression ]
                           | . port_identifier ( [ port_expression ] )
 port_expression ::= port_reference
                           | { port_reference { , port_reference } }
 port_reference ::= port_identifier
                           | port_identifier [ constant_expression ]
                           | port_identifier [ msb_constant_expression :
                           lsb_constant_expression ]
                           | port_identifier [ constant_expression ]
                           | input_declaration
                           | output_declaration
                           | inout_declaration
                           ...

 udp_declaration ::= primitive udp_identifier ( udp_port_list )
                           ;
                           udp_port_declaration { udp_port_declaration }
                           udp_body
                           endprimitive
                           ::= output_port_identifier ,
 udp_port_list input_port_identifier { , input_port_identifier
                           }
                           | output_declaration , input_declaration { ,
                           input_declaration }
 udp_port_declaration ::= output_declaration
                           | input_declaration
                           | reg_declaration
                           ...
 input_declaration ::= input [ signed ] [ net_type ] [ range ]
                           list_of_port_identifiers
 output_declaration ::= output [ signed ] [ net_type ] [ range ]
                           list_of_port_identifiers
                           ::= output [ signed ] [ reg_type ] [ range ]
                           list_of_port_identifiers
                           ::= output [ signed ] [ reg_type ] [ range ]
                           list_of_reg_decl_assignments
 inout_declaration ::= inout [ signed ] [ net_type ] [ range ]
                           list_of_port_identifiers

 function_declaration ::= function [range_or_type]
                           function_identifier ;
                           function_item_declaration
                           {function_item_declaration}
                           statement
                           endfunction
                           | function [range_or_type] function_identifier
                           ( function_port_list ) ;
                           block_item_declaration {block_item_declaration}

                           statement
                           endfunction

 function_item_declaration ::= block_item_declaration
                           | input_declaration
 function_port_list ::= input_declaration { input_declaration }
 task_declaration ::= task task_identifier ;
                           task_item_declaration {task_item_declaration}
                           statement
                           endtask
                           | task task_identifier ( task_port_list ) ;
                           block_item_declaration {block_item_declaration}
                           statement
                           endtask

 task_item_declaration ::= block_item_declaration
                           | input_declaration
                           | output_declaration
                           | inout_declaration
 task_port_list ::= task_port_item { task_port_item }
 task_port_item ::= input_declaration
                           | output_declaration
                           | inout_declaration

Note that a separate proposal is adding the keyword signed to the language;
and the optional keyword signed is merely included here to show that should
signed constructs be introduced, it would be legal to include the
declaration in the port_reference production

Given this syntax, the following two module declarations are equivalent:

 module acc_fsm( CLK, RST, IT_IL_RQ, IT_RQ_VLD, RdMsg,
                 WrMsg, AccessOK, XX_IL_PIODONE, OM_IL_GT,
                 RespVld, IL_IT_GT, CaptureAddress, CaptureData,
                 IL_XX_PIORD, IL_XX_PIOWR, IL_OM_RQ,
                 SelectResp, SetRespVld, ClrRespVld);
    parameter DATAWIDTH=64;
    input CLK, RST;
    input IT_IL_RQ,
                        IT_RQ_VLD,
                        RdMsg,
                        WrMsg,
                        AccessOK,
                        XX_IL_PIODONE;
    input OM_IL_GT,
                        RespVld;
    output [31:0] CaptureAddress;
    output [DATAWIDTH-1:0] CaptureData;
    output IL_IT_GT,
                        IL_XX_PIORD,
                        IL_XX_PIOWR,
                        IL_OM_RQ,
                        SelectResp,
                        SetRespVld,
                        ClrRespVld;
    reg [31:0] CaptureAddress;
    reg [DATAWIDTH-1:0] CaptureData,
    reg [2:0] LE_NxtState,
                        LE_State;
    reg IL_IT_GT,
                        IL_XX_PIORD;
    reg IL_XX_PIOWR,
                        IL_OM_RQ,
                        SelectResp,
                        SetRespVld,
                        ClrRespVld;

and

 module acc_fsm #( parameter DATAWIDTH=64)
                  ( input wire CLK, RST, IT_IL_RQ, IT_RQ_VLD, RdMsg,
                               WrMsg, AccessOK, XX_IL_PIODONE,
                               OM_IL_GT, RespVld,
                    output reg [31:0] CaptureAddress,
                    output reg [DATAWIDTH-1:0] CaptureData,
                    output reg IL_IT_GT, IL_XX_PIORD, IL_XX_PIOWR,
                               IL_OM_RQ, SelectResp, SetRespVld, ClrRespVld
                  );
    reg [ 2 : 0] LE_NxtState,
                        LE_State;

Things to note:

  1. The second module declaration is much more compact.(38 words instead of
     70). Also note that this is a small example; many datapath modules
     contain as many as a thousand ports, each which may need to be declared
     three times.
  2. The second module declaration is much easier to reuse: changing the
     width of the CaptureAddress bus to 48 bits requires modifying one
     location, instead of two, which potentially are many lines apart.
  3. With the second module declaration local variables are clearly distinct
     from port variables.
  4. With the second module declaration global analysis can examine just the
     port list in order to determine all necessary information about the
     input output characteristics of a module.
  5. Declaring the modifiable parameter declarations in a separate list,
     with the list enclosed in '#(' and )' looks just like the module
     instance parameter override syntax. This also encapsulates and focuses
     attention the interface nature of these parameters.
  6. Overall, the new module declaration centers the information that a user
     of this module must look at to successfully interface to the module in
     one place, at the top of the module. The details of the implementation
     are listed later. Hence Verilog becomes more object oriented.
  7. There has been some suggestion that using constant functions in module
     i/o declarations to define widths would require that the definition of
     the constant function precede the use; however private discussion has
     cleared this up. The value of the parameters at the point of the 'call'
     to the constant function are all that is needed to determine its value.
     An exaple is useful:
      module acc_fsm #( parameter DATAWIDTH=8, TSIZE=cf_tsize(DATAWIDTH) )
                       ( input wire CLK, RST,
                         output reg [TSIZE-1:0] CaptureDataOut,
                         input wire [TSIZE-1:0] CaptureDataIn
                       );
         reg [2:0] LE_NxtState,
                   LE_State;

        parameter B=DATAWIDTH*2;

        function [31:0] cf_tsize(input [31:0] w);
        cf_tsize = w**B;
        endfunction
      endmodule

     The parameter B is not yet defined at the location that TSIZE is
     assigned the value of the constant function cf_tsize, and hence this
     usage is illegal. The fix would be to move the definition of the
     parameter B into the parameter port list. (perhaps even as a
     localparam).

<p>Michael McNamara
Last modified: Fri Jan 8 18:16:27 PST 1999



This archive was generated by hypermail 2.1.4 : Mon Jul 08 2002 - 12:53:26 PDT and
sponsored by Boyd Technology, Inc.