/* SB - General comments:
1) I tried to add attribute_instances where appropriate, to
match the usage in the 1364-2001 bnf
2) There were many productions where a recursive production
in the SV d3 bnf didn't make sense as recursive (for
example, statement has a production 'identifier : statement'
which would suggest that 'abc: def: foo = 3;' is
valid.
3) When in doubt about ambiguous bnf, I ran tests through
systemsim to check. This was to ensure that I didn't
introduce "enhancements" that were not intended in the
bnf.
4) The structure of the SV d3 bnf and 1364-2001 bnf are
radically different, so the mapping of the SV d3 bnf
may not be obvious
*/
Annex A
Formal syntax definition
(normative)
The formal syntax of Verilog HDL is described using Backus-Naur Form (BNF).
A.1 Source text
A.1.1 Library source text
library_text ::= { library_descriptions }
/* SB do we need '[unit] [precision]' here? I would think that
it's only important for source_text, not library_text */
library_descriptions ::=
library_declaration
| include_statement
| config_declaration
library_declaration ::=
library library_identifier file_path_spec [ { , file_path_spec } ]
[ -incdir file_path_spec [ { , file_path_spec } ] ] ;
file_path_spec ::= file_path
include_statement ::= include <file_path_spec> ;
A.1.2 Configuration source text
config_declaration ::=
config config_identifier ;
design_statement
{config_rule_statement}
endconfig
design_statement ::= design { [library_identifier.]cell_identifier } ;
config_rule_statement ::=
default_clause liblist_clause
| inst_clause liblist_clause
| inst_clause use_clause
| cell_clause liblist_clause
| cell_clause use_clause
default_clause ::= default
inst_clause ::= instance inst_name
inst_name ::= topmodule_identifier{.instance_identifier}
cell_clause ::= cell [ library_identifier.]cell_identifier
liblist_clause ::= liblist [{library_identifier}]
use_clause ::= use [library_identifier.]cell_identifier[:config]
A.1.3 Module and primitive source text
source_text ::= [unit] [precision] { description }
description ::=
module_declaration
| udp_declaration
| module_root_item
| statement
/* SB - restricting $root involves description:
module_root_item allows declaration of everything (except parameter,
localparam, specparam)
statement allows you to do anything...
*/
module_declaration ::=
{ attribute_instance } module_keyword module_identifier [ parameter_port_list ]
[ list_of_ports ] ; [unit] [precision] { module_item }
endmodule
| { attribute_instance } module_keyword module_identifier [ parameter_port_list ]
[ list_of_port_declarations ] ; [unit] [precision]
{ non_port_module_item }
endmodule
module_keyword ::= module | macromodule
interface_declaration ::=
{ attribute_instance } interface interface_identifier [ parameter_port_list ]
[ list_of_ports ] ; [unit] [precision] { interface_item }
endinterface [: interface_identifier]
| { attribute_instance } interface interface_identifier [ parameter_port_list ]
[ list_of_port_declarations ] ; [unit] [precision]
{ non_port_interface_item }
endinterface [: interface_identifier]
unit ::= [ timeunit [ time_literal ] ; ]
precision ::= [ timeprecision [ time_literal ] ; ]
A.1.4 Module parameters and ports
parameter_port_list ::= # ( parameter_declaration { , parameter_declaration } )
list_of_ports ::= ( port { , port } )
list_of_port_declarations ::=
( port_declaration { , port_declaration } )
| ( )
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 [ range_expression ]
port_declaration ::=
{ attribute_instance } inout_declaration
| { attribute_instance } input_declaration
| { attribute_instance } output_declaration
| { attribute_instance } interface_port_declaration
A.1.5 Module items
module_common_item ::=
{ attribute_instance } module_or_generate_item_declaration
| { attribute_instance } interface_instantiation
module_item ::=
port_declaration ;
| non_port_module_item
module_or_generate_item ::=
{ attribute_instance } module_or_generate_item_declaration
| { attribute_instance } parameter_override
| { attribute_instance } continuous_assign
| { attribute_instance } gate_instantiation
| { attribute_instance } udp_instantiation
| { attribute_instance } module_instantiation
| { attribute_instance } initial_construct
| { attribute_instance } always_construct
/* SB - the three following statment types were not referenced by
other productions in the SV d3, so I put them here since
this seemed to be the most logical place */
| { attribute_instance } combinational_statement
| { attribute_instance } latch_statement
| { attribute_instance } ff_statement
| module_common_item
module_root_item ::=
{ attribute_instance } module_instantiation
| interface_declaration
| module_common_item
module_or_generate_item_declaration ::=
net_declaration
| reg_declaration
| integer_declaration
| real_declaration
| time_declaration
| realtime_declaration
| data_declaration
| event_declaration
| genvar_declaration
| task_declaration
| function_declaration
non_port_module_item ::=
{ attribute_instance } generated_module_instantiation
| { attribute_instance } local_parameter_declaration
| { attribute_instance } module_or_generate_item
| { attribute_instance } parameter_declaration
| { attribute_instance } specify_block
| { attribute_instance } specparam_declaration
| module_declaration
parameter_override ::= defparam list_of_param_assignments ;
A.1.6 Interface items
interface_or_generate_item ::=
{ attribute_instance } continuous_assign
| { attribute_instance } initial_construct
| { attribute_instance } always_construct
/* SB - the three following statment types were not referenced by
other productions in the SV d3, so I put them here since
this seemed to be the most logical place */
| { attribute_instance } combinational_statement
| { attribute_instance } latch_statement
| { attribute_instance } ff_statement
| { attribute_instance } local_parameter_declaration
| { attribute_instance } parameter_declaration
| module_common_item
| { attribute_instance } modport_declaration
interface_item ::=
port_declaration
| non_port_interface_item
non_port_interface_item ::=
{ attribute_instance } generated_interface_instantiation
| { attribute_instance } local_parameter_declaration
| { attribute_instance } parameter_declaration
| { attribute_instance } specparam_declaration
| interface_or_generate_item
| interface_declaration
A.2 Declarations
A.2.1 Declaration types
A.2.1.1 Module parameter declarations
local_parameter_declaration ::=
localparam [ signing ] { packed_dimension } [ range ] list_of_param_assignments ;
| localparam integer list_of_param_assignments ;
| localparam real list_of_param_assignments ;
| localparam realtime list_of_param_assignments ;
| localparam time list_of_param_assignments ;
| localparam data_type list_of_param_assignments ;
parameter_declaration ::=
parameter [ signing ] { packed_dimension } [ range ] list_of_param_assignments ;
| parameter integer list_of_param_assignments ;
| parameter real list_of_param_assignments ;
| parameter realtime list_of_param_assignments ;
| parameter time list_of_param_assignments ;
| parameter data_type list_of_param_assignments ;
| parameter type list_of_type_assignments ;
specparam_declaration ::=
specparam [ range ] list_of_specparam_assignments ;
/* SB - The SV draft3 bnf would enhance the specparam to be identical
to the localparam. If that is what we want to do, then we should
remove all the special stuff for specparam_assignments and
make specparam the same as localparam */
A.2.1.2 Port declarations
inout_declaration ::= inout [ net_type ] [ signed ] [ range ] list_of_port_identifiers
inout_declaration ::= inout [ port_type ] list_of_port_identifiers
| inout . port_identifier ( [ port_expression ] )
/* SB - I don't particularly care for this... I remember deliberately
disallowing this style in V2K1. It allows jumpered ports (i.e.
"inout .m1(x), inout .m2(x)") that would normally not be
allowed with the ansi style because port identifiers would otherwise
have to be unique... if that's desirable, then this is a
also a desireable enhancement.
NOTE: Limitations (same as Draft3 BNF) are that:
1) Can't specify a list of ports this way
Example of unsupported: module foo(inout .m1(x), .m2(y));
2) Can't specify type, signedness or size
Example of unsupported: module foo(inout signed [31:0] .m1(x));
*/
input_declaration ::= input [ net_type ] [ signed ] [ range ]
list_of_port_identifiers
input_declaration ::= input [ port_type ] list_of_port_identifiers
| input . port_identifier ( [ port_expression ] )
output_declaration ::=
output [ net_type ] [ signed ] [ range ]
list_of_port_identifiers
| output [ reg ] [ signed ] [ range ]
list_of_port_identifiers
| output reg [ signed ] [ range ]
list_of_variable_port_identifiers
| output [ output_variable_type ]
list_of_port_identifiers
| output output_variable_type
list_of_variable_port_identifiers
output [ port_type ] list_of_port_identifiers
| output . port_identifier ( [ port_expression ] )
| output data_type list_of_variable_port_identifiers
interface_port_declaration ::=
interface list_of_interface_identifiers
| interface . modport_identifier list_of_interface_identifiers
| identifier list_of_interface_identifiers
| identifier . modport_identifier list_of_interface_identifiers
A.2.1.3 Type declarations
block_data_declaration ::=
block_variable_declaration
| constant_declaration
| type_declaration
| state_declaration
constant_declaration ::= const data_type const_assignment ;
/* SB - I changed constant_declaration to use const_assignment
with only allows a constant expression on the rhs. It
seemed like a typo to allow any expression, and systemsim
agreed.
*/
data_declaration ::=
variable_declaration
| constant_declaration
| type_declaration
| state_declaration
event_declaration ::= event list_of_event_identifiers ;
genvar_declaration ::= genvar list_of_genvar_identifiers ;
integer_declaration ::= integer list_of_variable_identifiers ;
net_declaration ::=
net_type [ signing ]
[ delay3 ] list_of_net_identifiers ;
| net_type [ drive_strength ] [ signing ]
[ delay3 ] list_of_net_decl_assignments ;
| net_type [ vectored | scalared ] [ signing ]
{ packed_dimension } range [ delay3 ] list_of_net_identifiers ;
| net_type [ drive_strength ] [ vectored | scalared ] [ signing ]
{ packed_dimension } range [ delay3 ] list_of_net_decl_assignments ;
| trireg [ charge_strength ] [ signing ]
[ delay3 ] list_of_net_identifiers ;
| trireg [ drive_strength ] [ signing ]
[ delay3 ] list_of_net_decl_assignments ;
| trireg [ charge_strength ] [ vectored | scalared ] [ signing ]
{ packed_dimension } range [ delay3 ] list_of_net_identifiers ;
| trireg [ drive_strength ] [ vectored | scalared ] [ signing ]
{ packed_dimension } range [ delay3 ] list_of_net_decl_assignments ;
real_declaration ::= real list_of_real_identifiers ;
realtime_declaration ::= realtime list_of_real_identifiers ;
reg_declaration ::= reg [ signing ] [ range ]
list_of_variable_identifiers ;
state_declaration ::= state { state_list } state_identifier [ delay_or_event_control ] ;
state_list ::= and_states | or_states
and_states ::= state and state { and state }
or_states ::= state , state { , state }
state ::= [ { state_list } ] state_identifier
time_declaration ::= time list_of_variable_identifiers ;
type_declaration ::=
typedef data_type type_declaration_identifier ;
| typedef interface_identifier { [ constant_expression ] } . type_identifier
type_declaration_identifier ;
block_variable_declaration ::=
[ lifetime ] data_type list_of_variable_identifiers ;
| lifetime data_type list_of_variable_decl_assignments ;
/* SB - The SV d3 bnf didn't appear to allow variable declarations
in seq or par blocks, but it did specify
variable_declaration as part of a data_declaration, that
allows the user to optionally specify the lifetime and
make initial assignments.
Since the declarations used in functions and tasks are
identical to those in blocks, it suggested that these
enhancements were intended for the seq/par blocks as
well. Since decl assignments were deliberately disallowed in
1364-2001, I checked the systemsim implementation and
found that decl assignments are only allowed when the
lifetime is explicitly specified. Thus I added that
restriction into the production above.
*/
variable_declaration ::=
[ lifetime ] data_type list_of_variable_identifiers_or_assignments ;
lifetime ::= static | automatic
A.2.2 Declaration data types
A.2.2.1 Net and variable types
output_variable_type ::= integer | time
real_type ::=
real_identifier [ = constant_expression ]
| real_identifier dimension { dimension }
variable_type ::=
variable_identifier [ = constant_expression ]
| variable_identifier dimension { dimension }
/* SB - moved variable_type to variable_declaration_identifier
data_type ::=
integer_vector_type [ signing ] { packed_dimension } [ range ]
| integer_atom_type [ signing ] { packed_dimension }
| type_declaration_identifier
| non_integer_type
| struct { { struct_union_member } }
| union { { struct_union_member } }
| enum { enum_identifier [ = constant_expression ]
{ , enum_identifier [ = constant_expression ] } }
/* SB - I made the enum require at least one identifier because
it seemed to be a accidental to allow 'enum {} myenum;'
and systemsim agreed with me.
*/
| void
integer_atom_type ::= byte | char | shortint | int | longint | integer
integer_type ::= integer_vector_type | integer_atom_type
integer_vector_type ::= bit | logic | reg
net_type ::=
supply0 | supply1
| tri | triand | trior | tri0 | tri1
| wire | wand | wor
non_integer_type ::= time | shortreal | real | realtime | $built-in
/* SB - realtime was missing from SV d3 bnf. I've added
it for completenes */
port_type ::=
data_type { packed_dimension }
| net_type [ signing ] { packed_dimension }
| trireg [ signing ] { packed_dimension }
| event
/* SB - IMPLICIT PORT TYPE
following was not in SV d3, but is part of 1364-2001 as
explicit parts of input, output and inout. I've extended
the single dimension of 1364-2001 to support SV array passing */
| [ signing ] { packed_dimension } range
signing ::= [ signed ] | [ unsigned ]
simple_type ::= integer_type | non_integer_type | type_identifier
struct_union_member ::= data_type list_of_variable_identifiers_or_assignments ;
A.2.2.2 Strengths
drive_strength ::=
( strength0 , strength1 )
| ( strength1 , strength0 )
| ( strength0 , highz1 )
| ( strength1 , highz0 )
| ( highz0 , strength1 )
| ( highz1 , strength0 )
strength0 ::= supply0 | strong0 | pull0 | weak0
strength1 ::= supply1 | strong1 | pull1 | weak1
charge_strength ::= ( small ) | ( medium ) | ( large )
A.2.2.3 Delays
delay3 ::= # delay_value | # ( delay_value [ , delay_value [ , delay_value ] ] )
delay2 ::= # delay_value | # ( delay_value [ , delay_value ] )
delay_value ::=
unsigned_number
| parameter_identifier
| specparam_identifier
| mintypmax_expression
A.2.3 Declaration lists
list_of_event_identifiers ::= event_identifier [ unpacked_dimension { unpacked_dimension }]
{ , event_identifier [ unpacked_dimension { unpacked_dimension }] }
list_of_genvar_identifiers ::= genvar_identifier { , genvar_identifier }
list_of_interface_identifiers ::= interface_identifier { unpacked_dimension }
{ , interface_identifier { unpacked_dimension } }
list_of_net_decl_assignments ::= net_decl_assignment { , net_decl_assignment }
list_of_net_identifiers ::= net_identifier [ unpacked_dimension { unpacked_dimension }]
{ , net_identifier [ unpacked_dimension { unpacked_dimension }] }
list_of_param_assignments ::= param_assignment { , param_assignment }
list_of_port_identifiers ::= port_identifier { unpacked_dimension }
{ , port_identifier { unpacked_dimension } }
list_of_udp_port_identifiers ::= port_identifier { , port_identifier }
list_of_real_identifiers ::= real_type { , real_type }
list_of_specparam_assignments ::= specparam_assignment { , specparam_assignment }
list_of_type_assignments ::= type_assignment { , type_assignment }
list_of_variable_decl_assignments ::= variable_decl_assign_identifier { , variable_decl_assign_identifier }
list_of_variable_identifiers ::= variable_declaration_identifier { , variable_declaration_identifier }
list_of_variable_identifiers_or_assignments ::=
list_of_variable_decl_assignments
| list_of_variable_identifiers
list_of_variable_port_identifiers ::= port_identifier { unpacked_dimension } [ = constant_expression ]
{ , port_identifier { unpacked_dimension } [ = constant_expression ] }
A.2.4 Declaration assignments
const_assignment ::= const_identifier = constant_expression
net_decl_assignment ::= net_identifier = expression
param_assignment ::= parameter_identifier = constant_expression
specparam_assignment ::=
specparam_identifier = constant_mintypmax_expression
| pulse_control_specparam
type_assignment ::= type_identifier = data_type
pulse_control_specparam ::=
PATHPULSE$ = ( reject_limit_value [ , error_limit_value ] ) ;
| PATHPULSE$specify_input_terminal_descriptor$specify_output_terminal_descriptor
= ( reject_limit_value [ , error_limit_value ] ) ;
error_limit_value ::= limit_value
reject_limit_value ::= limit_value
limit_value ::= constant_mintypmax_expression
A.2.5 Declaration ranges
unpacked_dimension ::= [ dimension_constant_expression : dimension_constant_expression ]
packed_dimension ::= [ dimension_constant_expression : dimension_constant_expression ]
range ::= [ msb_constant_expression : lsb_constant_expression ]
A.2.6 Function declarations
function_declaration ::=
function [ automatic ] [ signing ] [ range_or_type ]
[ interface_identifier . ] function_identifier ;
function_item_declaration { function_item_declaration }
{ function_statement }
endfunction [ : function_identifier ]
| function [ automatic ] [ signing ] [ range_or_type ]
[ interface_identifier . ] function_identifier ( function_port_list ) ;
block_item_declaration { block_item_declaration }
{ function_statement }
endfunction [ : function_identifier ]
/* SB - The SV d3 bnf had 'endfunction [: identifier : ]' which
didn't make sense, looked like a typo, and gave a syntax
error in systemsim. I removed the extra ':'
*/
function_item_declaration ::=
block_item_declaration
| { attribute_instance } input_declaration ;
| { attribute_instance } output_declaration ;
| { attribute_instance } inout_declaration ;
function_port_item ::=
{ attribute_instance } input_declaration
| { attribute_instance } output_declaration
| { attribute_instance } inout_declaration
function_port_list ::= function_port_item { , function_port_item }
function_port_list ::= { attribute_instance } input_declaration { , { attribute_instance } input_declaration }
range_or_type ::= range | integer | real | realtime | time
function_prototype ::= function data_type ( list_of_function_proto_formals )
named_function_proto ::= function data_type function_identifier ( list_of_function_proto_formals )
list_of_function_proto_formals ::=
[ { attribute_instance } function_proto_formal { ,
{ attribute_instance } function_proto_formal } ]
function_proto_formal ::=
input data_type [ variable_declaration_identifier ]
| inout data_type [ variable_declaration_identifier ]
| output data_type [ variable_declaration_identifier ]
| variable_declaration_identifier
/* SB - Protype functions are also in the SV d3 bnf, but aren't referred to
by any of the other productions. They appear to be part of modports
but are not adequately described in the text or tied to the modport
production. */
range_or_type ::=
{ packed_dimension } range
| data_type
A.2.7 Task declarations
task_declaration ::=
task [ automatic ] [ interface_identifier . ] task_identifier ;
{ task_item_declaration }
{ statement }
endtask [ : task_identifier ]
| task [ automatic ] [ interface_identifier . ] task_identifier ( task_port_list ) ;
{ block_item_declaration }
{ statement }
endtask [ : task_identifier ]
task_item_declaration ::=
block_item_declaration
| { attribute_instance } input_declaration ;
| { attribute_instance } output_declaration ;
| { attribute_instance } inout_declaration ;
task_port_list ::= task_port_item { , task_port_item }
task_port_item ::=
{ attribute_instance } [ port ] input_declaration
| { attribute_instance } [ port ] output_declaration
| { attribute_instance } [ port ] inout_declaration
| { attribute_instance } port event list_of_port_identifiers
/* SB - What's with the 'port'? It's not described in the text.
We should either remove it from the bnf or add it to the
text.
/* SB - Protype tasks are also in the SV d3 bnf, but aren't referred to
by any of the other productions. They appear to be part of modports
but are not adequately described in the text or tied to the modport
production. */
task_prototype ::=
task ( { attribute_instance } task_proto_formal
{ , { attribute_instance } task_proto_formal } )
named_task_proto ::= task task_identifier ( task_proto_formal { , task_proto_formal } )
task_proto_formal ::=
[ port ] input data_type [ variable_declaration_identifier ]
| [ port ] inout data_type [ variable_declaration_identifier ]
| [ port ] output data_type [ variable_declaration_identifier ]
| port event variable
A.2.8 Block item declarations
block_item_declaration ::=
{ attribute_instance } block_reg_declaration
{ attribute_instance } block_data_declaration
| { attribute_instance } event_declaration
| { attribute_instance } integer_declaration
| { attribute_instance } local_parameter_declaration
| { attribute_instance } parameter_declaration
| { attribute_instance } real_declaration
| { attribute_instance } realtime_declaration
| { attribute_instance } time_declaration
block_reg_declaration ::= reg [ signing ] [ range ]
list_of_block_variable_identifiers ;
list_of_block_variable_identifiers ::=
block_variable_type { , block_variable_type }
block_variable_type ::=
variable_identifier
| variable_identifier dimension { dimension }
A.2.9 Interface declarations
modport_declaration ::= modport list_of_modport_identifiers ;
list_of_modport_identifiers ::= modport_item { , modport_item }
modport_item ::= modport_identifier ( modport_port { , modport_port } )
modport_port ::=
input [port_type] port_identifier
| output [port_type] port_identifier
| inout [port_type] port_identifier
| interface_identifier . port_identifier
A.3 Primitive instances
A.3.1 Primitive instantiation and instances
gate_instantiation ::=
cmos_switchtype [delay3]
cmos_switch_instance { , cmos_switch_instance } ;
| enable_gatetype [drive_strength] [delay3]
enable_gate_instance { , enable_gate_instance } ;
| mos_switchtype [delay3]
mos_switch_instance { , mos_switch_instance } ;
| n_input_gatetype [drive_strength] [delay2]
n_input_gate_instance { , n_input_gate_instance } ;
| n_output_gatetype [drive_strength] [delay2]
n_output_gate_instance { , n_output_gate_instance } ;
| pass_en_switchtype [delay2]
pass_enable_switch_instance { , pass_enable_switch_instance } ;
| pass_switchtype
pass_switch_instance { , pass_switch_instance } ;
| pulldown [pulldown_strength]
pull_gate_instance { , pull_gate_instance } ;
| pullup [pullup_strength]
pull_gate_instance { , pull_gate_instance } ;
cmos_switch_instance ::= [ name_of_gate_instance ] ( output_terminal , input_terminal ,
ncontrol_terminal , pcontrol_terminal )
enable_gate_instance ::= [ name_of_gate_instance ] ( output_terminal , input_terminal , enable_terminal )
mos_switch_instance ::= [ name_of_gate_instance ] ( output_terminal , input_terminal , enable_terminal )
n_input_gate_instance ::= [ name_of_gate_instance ] ( output_terminal , input_terminal { , input_terminal } )
n_output_gate_instance ::= [ name_of_gate_instance ] ( output_terminal { , output_terminal } , input_terminal )
pass_switch_instance ::= [ name_of_gate_instance ] ( inout_terminal , inout_terminal )
pass_enable_switch_instance ::= [ name_of_gate_instance ] ( inout_terminal , inout_terminal , enable_terminal )
pull_gate_instance ::= [ name_of_gate_instance ] ( output_terminal )
/* SB - This makes arrays of instances multi-dimentional, which
is not mentioned in the text of the standard.
I added the multi-dimension requirement here even though
the SV d3 bnf did not require the identifier before
specification of the ranges because it seemed to be an
unintended ambiguity in the bnf and gave a syntax error
in systemsim. */
name_of_gate_instance ::= gate_instance_identifier [ range ] { range }
A.3.2 Primitive strengths
pulldown_strength ::=
( strength0 , strength1 )
| ( strength1 , strength0 )
| ( strength0 )
pullup_strength ::=
( strength0 , strength1 )
| ( strength1 , strength0 )
| ( strength1 )
A.3.3 Primitive terminals
enable_terminal ::= expression
inout_terminal ::= net_lvalue
input_terminal ::= expression
ncontrol_terminal ::= expression
output_terminal ::= net_lvalue
pcontrol_terminal ::= expression
A.3.4 Primitive gate and switch types
cmos_switchtype ::= cmos | rcmos
enable_gatetype ::= bufif0 | bufif1 | notif0 | notif1
mos_switchtype ::= nmos | pmos | rnmos | rpmos
n_input_gatetype ::= and | nand | or | nor | xor | xnor
n_output_gatetype ::= buf | not
pass_en_switchtype ::= tranif0 | tranif1 | rtranif1 | rtranif0
pass_switchtype ::= tran | rtran
A.4 Module, interface and generated instantiation
A.4.1 Instantiation
A.4.1.1
Module instantiation
module_instantiation ::=
module_identifier [ parameter_value_assignment ]
module_instance { , module_instance } ;
parameter_value_assignment ::= # ( list_of_parameter_assignments )
list_of_parameter_assignments ::=
ordered_parameter_assignment { , ordered_parameter_assignment } |
named_parameter_assignment { , named_parameter_assignment }
ordered_parameter_assignment ::= expression
named_parameter_assignment ::= . parameter_identifier ( [ expression ] )
module_instance ::= name_of_instance ( [ list_of_port_connections ] )
/* SB - This makes arrays of instances multi-dimentional, which
is not mentioned in the text of the standard.
I added the multi-dimension requirement here even though
the SV d3 bnf did not require the identifier before
specification of the ranges because it seemed to be an
unintended ambiguity in the bnf and gave a syntax error
in systemsim. */
name_of_instance ::= module_instance_identifier { range } [ range ]
list_of_port_connections ::=
ordered_port_connection { , ordered_port_connection }
| named_port_connection { , named_port_connection }
ordered_port_connection ::= { attribute_instance } [ expression ]
named_port_connection ::= { attribute_instance } .port_identifier ( [ expression ] )
A.4.1.2 Interface instantiation
interface_instantiation ::=
interface_identifier [ parameter_value_assignment ]
module_instance { , module_instance } ;
A.4.2 Generated instantiation
A.4.2.1 Generated module instantiation
generated_module_instantiation ::= generate { generate_module_item } endgenerate
generate_module_item_or_null ::= generate_module_item | ;
generate_module_item ::=
generate_module_conditional_statement
| generate_module_case_statement
| generate_module_loop_statement
| generate_module_block
| module_or_generate_item
generate_module_conditional_statement ::=
if ( constant_expression ) generate_module_item_or_null
[ else generate_module_item_or_null ]
generate_module_case_statement ::=
case ( constant_expression )
genvar_module_case_item { genvar_module_case_item }
endcase
genvar_module_case_item ::=
constant_expression { , constant_expression } : generate_module_item_or_null
| default [ : ] generate_module_item_or_null
generate_module_loop_statement ::=
for ( genvar_decl_assignment ; constant_expression ; genvar_assignment )
begin : generate_block_identifier { generate_module_item } end
generate_module_named_block
genvar_assignment ::=
genvar_identifier = constant_expression
| genvar_identifier assignment_operator constant_expression
| bump_operator genvar_identifier
| genvar_identifier bump_operator
/* SB - I only added the bump_operator to the
genvar_assignment. The SV d3 bnf added all unary
operators, but as the bump_operator is the only unary
operator that modifies the value of the genvar variable,
it is the only one that makes sense here. */
genvar_decl_assignment ::=
[ genvar ] genvar_identifier = constant_expression
generate_module_named_block ::=
begin : generate_block_identifier { generate_module_item } end
| generate_block_identifier : generate_module_block
generate_module_block ::=
begin [ : generate_block_identifier ] { generate_module_item } end
/* SB - Shouldn't generate_block have an optional identifier
after the end, just like other begin/end pairs??? */
A.4.2.2 Generated interface instantiation
generated_interface_instantiation ::= generate { generate_interface_item } endgenerate
generate_interface_item_or_null ::= generate_interface_item | ;
generate_interface_item ::=
generate_interface_conditional_statement
| generate_interface_case_statement
| generate_interface_loop_statement
| generate_interface_block
| interface_or_generate_item
generate_interface_conditional_statement ::=
if ( constant_expression ) generate_interface_item_or_null [ else generate_interface_item_or_null ]
generate_interface_case_statement ::= case ( constant_expression )
genvar_interface_case_item { genvar_interface_case_item } endcase
genvar_interface_case_item ::= constant_expression { , constant_expression } :
generate_interface_item_or_null | default [ : ] generate_interface_item_or_null
generate_interface_loop_statement ::=
for ( genvar_decl_assignment ; constant_expression ; genvar_assignment )
generate_interface_named_block
begin : generate_block_identifier { generate_interface_item } end
generate_interface_named_block ::=
begin : generate_block_identifier { generate_module_item } end
| generate_block_identifier : generate_module_block
generate_interface_block ::= begin [ : generate_block_identifier ] { generate_interface_item } end
A.5 UDP declaration and instantiation
A.5.1 UDP declaration
udp_declaration ::=
{ attribute_instance } primitive udp_identifier ( udp_port_list ) ;
udp_port_declaration { udp_port_declaration }
udp_body
endprimitive
| { attribute_instance } primitive udp_identifier ( udp_declaration_port_list ) ;
udp_body
endprimitive
A.5.2 UDP ports
udp_port_list ::= output_port_identifier , input_port_identifier { , input_port_identifier }
udp_declaration_port_list ::=
udp_output_declaration , udp_input_declaration { , udp_input_declaration }
udp_port_declaration ::=
udp_output_declaration ;
| udp_input_declaration ;
| udp_reg_declaration ;
udp_output_declaration ::=
{ attribute_instance } output port_identifier
| { attribute_instance } output reg port_identifier [ = constant_expression ]
udp_input_declaration ::= { attribute_instance } input list_of_udp_port_identifiers
udp_reg_declaration ::= { attribute_instance } reg variable_identifier
A.5.3 UDP body
udp_body ::= combinational_body | sequential_body
combinational_body ::= table combinational_entry { combinational_entry } endtable
combinational_entry ::= level_input_list : output_symbol ;
sequential_body ::= [ udp_initial_statement ] table sequential_entry { sequential_entry } endtable
udp_initial_statement ::= initial output_port_identifier = init_val ;
init_val ::= 1'b0 | 1'b1 | 1'bx | 1'bX | 1'B0 | 1'B1 | 1'Bx | 1'BX | 1 | 0
sequential_entry ::= seq_input_list : current_state : next_state ;
seq_input_list ::= level_input_list | edge_input_list
level_input_list ::= level_symbol { level_symbol }
edge_input_list ::= { level_symbol } edge_indicator { level_symbol }
edge_indicator ::= ( level_symbol level_symbol ) | edge_symbol
current_state ::= level_symbol
next_state ::= output_symbol | -
output_symbol ::= 0 | 1 | x | X
level_symbol ::= 0 | 1 | x | X | ? | b | B
edge_symbol ::= r | R | f | F | p | P | n | N | *
A.5.4 UDP instantiation
udp_instantiation ::= udp_identifier [ drive_strength ] [ delay2 ]
udp_instance { , udp_instance } ;
/* SB - This makes arrays of instances multi-dimentional, which
is not mentioned in the text of the standard.
I added the multi-dimension requirement here even though
the SV d3 bnf did not require the identifier before
specification of the ranges because it seemed to be an
unintended ambiguity in the bnf and gave a syntax error
in systemsim. */
udp_instance ::= [ name_of_udp_instance ] { range } ( output_terminal , input_terminal
{ , input_terminal } )
name_of_udp_instance ::= udp_instance_identifier [ range ]
A.6 Behavioral statements
A.6.1 Continuous assignment statements
continuous_assign ::= assign [ drive_strength ] [ delay3 ] list_of_net_assignments ;
list_of_net_assignments ::= net_assignment { , net_assignment }
net_assignment ::= net_lvalue = expression
A.6.2 Procedural blocks and assignments
initial_construct ::= initial statement
always_construct ::= always statement
combinational_statement ::= always_comb statement
latch_statement ::= always_latch statement
ff_statement ::= always_ff statement
blocking_assignment ::=
variable_lvalue = [ delay_or_event_control ] expression
| operator_assignment
operator_assignment ::= variable_lvalue assignment_operator expression
assignment_operator ::= = | *= | /= | %= | += | - = | <<= | >>= | &= | ^= | |=
nonblocking_assignment ::= variable_lvalue <= [ delay_or_event_control ] expression
/* SB - SV d3 bnf allowed 'force a, b = 1;' but that looked
incorrect and since systemsim agreed with me, I didn't
add it to procedural_continuous_assignments. */
procedural_continuous_assignments ::=
assign variable_assignment
| deassign variable_lvalue
| force variable_assignment
| force net_assignment
| release variable_lvalue
| release net_lvalue
function_blocking_assignment ::= variable_lvalue = expression
function_statement_or_null ::=
function_statement
| { attribute_instance } ;
A.6.3 Parallel and sequential blocks
function_seq_block ::= begin [ : block_identifier
{ block_item_declaration } ] { function_statement } end
variable_assignment ::= variable_lvalue = expression
par_block ::= fork [ : block_identifier ]
{ block_item_declaration } ]
{ statement } join [ : block_identifier ]
seq_block ::= begin [ : block_identifier ]
{ block_item_declaration } ]
{ statement } end [ : block_identifier ]
A.6.4 Statements
statement ::=
[ block_identifier : ] statement_item
statement_item ::=
{ attribute_instance } blocking_assignment ;
| { attribute_instance } case_statement
| { attribute_instance } conditional_statement
| { attribute_instance } transition_statement
| { attribute_instance } transition_to_state statement_or_null
| { attribute_instance } bump_expression
/* SB - SV d3 bnf allowed expression as a statement, but the only
expression that makes sense as a statement is the bump
operator. Since systemsim agrees with me, I have only
allowed the pre and post bump operators here */
| { attribute_instance } disable_statement
| { attribute_instance } event_trigger
| { attribute_instance } loop_statement
| { attribute_instance } jump_statement
| { attribute_instance } nonblocking_assignment ;
| { attribute_instance } par_block
| { attribute_instance } procedural_continuous_assignments ;
| { attribute_instance } procedural_timing_control_statement
| { attribute_instance } seq_block
| { attribute_instance } system_task_enable
| { attribute_instance } task_enable
| { attribute_instance } wait_statement
| { attribute_instance } process statement
statement_or_null ::=
statement
| { attribute_instance } ;
function_statement ::=
[ block_identifier : ] function_statement_item
function_statement_item ::=
{ attribute_instance } function_blocking_assignment ;
| { attribute_instance } function_case_statement
| { attribute_instance } function_conditional_statement
| { attribute_instance } function_transition_statement
| { attribute_instance } transition_to_state function_statement_or_null
| { attribute_instance } bump_expression
/* SB - SV d3 bnf allowed expression as a statement, but the only
expression that makes sense as a statement is the bump
operator. Since systemsim agrees with me, I have only
allowed the pre and post bump operators here */
| { attribute_instance } function_loop_statement
| { attribute_instance } jump_statement
| { attribute_instance } function_seq_block
| { attribute_instance } disable_statement
| { attribute_instance } system_task_enable
A.6.5 Timing control statements
delay_control ::=
# delay_value
| # ( mintypmax_expression )
delay_or_event_control ::=
delay_control
| event_control
| repeat ( expression ) event_control
disable_statement ::=
disable hierarchical_task_identifier ;
| disable hierarchical_block_identifier ;
event_control ::=
@ event_identifier
| @ ( event_expression )
| @*
| @ (*)
event_trigger ::=
-> hierarchical_event_identifier ;
event_expression ::=
expression [ iff expression ]
| hierarchical_identifier [ iff expression ]
| [ edge ] expression [ iff expression ]
| negedge expression
| event_expression or event_expression
| event_expression , event_expression
edge ::= posedge | negedge | changed
/* SB - The SV d3 bnf adds all of these to the jump statement, but
since there are limitations on where these are allowed as
a statement, we should consider specifying every place
they are allowed (much like the way the 1364-2001 bnf
separates the statements allowed in functions from the
rest of the functions. */
jump_statement ::=
return [ expression ] ;
| break ;
| continue ;
procedural_timing_control_statement ::=
delay_or_event_control statement_or_null
wait_statement ::=
wait ( expression ) statement_or_null
A.6.6 Conditional statements
conditional_statement ::=
[ unique_priority ] if ( expression )
statement_or_null [ else statement_or_null ]
| if_else_if_statement
if_else_if_statement ::=
[ unique_priority ] if ( expression ) statement_or_null
{ else [ unique_priority ] if ( expression ) statement_or_null }
[ else statement_or_null ]
function_conditional_statement ::=
[ unique_priority ] if ( expression ) function_statement_or_null
[ else function_statement_or_null ]
| function_if_else_if_statement
function_if_else_if_statement ::=
[ unique_priority ] if ( expression ) function_statement_or_null
{ else [ unique_priority ] if ( expression ) function_statement_or_null }
[ else function_statement_or_null ]
unique_priority ::= unique | priority
A.6.7 Case statements
case_statement ::=
[ unique_priority ] case ( expression )
case_item { case_item } endcase
| [ unique_priority ] casez ( expression )
case_item { case_item } endcase
| [ unique_priority ] casex ( expression )
case_item { case_item } endcase
case_item ::=
expression { , expression } : statement_or_null
| default [ : ] statement_or_null
function_case_statement ::=
[ unique_priority ] case ( expression )
function_case_item { function_case_item } endcase
| [ unique_priority ] casez ( expression )
function_case_item { function_case_item } endcase
| [ unique_priority ] casex ( expression )
function_case_item { function_case_item } endcase
function_case_item ::=
expression { , expression } : function_statement_or_null
| default [ : ] function_statement_or_null
A.6.8 Transition statements
transition_statement ::=
transition ( hierarchical_identifier )
transition_item { transition_item } endtransition
function_transition_statement ::=
transition ( hierarchical_identifier )
function_transition_item { function_transition_item } endtransition
transition_item ::=
list_of_state_conditions : statement_or_null
| default [ : ] statement_or_null
function_transition_item ::=
list_of_state_conditions : function_statement_or_null
| default [ : ] function_statement_or_null
list_of_state_conditions ::= state_condition { , state_condition }
state_condition ::= state_identifier { and state_identifier }
transition_to_state ::=
->> hierarchical_identifier . state_identifier
| ->> hierarchical_identifier . ( state_condition )
| [ transition_identifier ] ->> state_condition
/* SB - I mapped machine_name to hierarchical_identifier as that
seemed to be the intention. */
A.6.9 Looping statements
function_loop_statement ::=
forever function_statement
| repeat ( expression ) function_statement_or_null
| while ( expression ) function_statement_or_null
| for ( variable_decl_or_assignment ; expression ; variable_assignment )
function_statement_or_null
| do function_statement while ( expression )
loop_statement ::=
forever statement
| repeat ( expression ) statement_or_null
| while ( expression ) statement_or_null
| for ( variable_decl_or_assignment ; expression ; variable_assignment )
statement_or_null
| do statement while ( expression )
variable_decl_or_assignment ::=
data_type list_of_variable_identifiers_or_assignments ;
| variable_assignment
A.6.10 Task enable statements
system_task_enable ::= system_task_identifier [ ( expression { , expression } ) ] ;
task_enable ::= hierarchical_task_identifier [ ( expression { , expression } ) ] ;
A.7 Specify section
A.7.1 Specify block declaration
specify_block ::= specify { specify_item } endspecify
specify_item ::=
specparam_declaration
| pulsestyle_declaration
| showcancelled_declaration
| path_declaration
| system_timing_check
pulsestyle_declaration ::=
pulsestyle_onevent list_of_path_outputs ;
| pulsestyle_ondetect list_of_path_outputs ;
showcancelled_declaration ::=
showcancelled list_of_path_outputs ;
| noshowcancelled list_of_path_outputs ;
A.7.2 Specify path declarations
path_declaration ::=
simple_path_declaration ;
| edge_sensitive_path_declaration ;
| state_dependent_path_declaration ;
simple_path_declaration ::=
parallel_path_description = path_delay_value
| full_path_description = path_delay_value
parallel_path_description ::=
( specify_input_terminal_descriptor [ polarity_operator ] => specify_output_terminal_descriptor )
full_path_description ::=
( list_of_path_inputs [ polarity_operator ] *> list_of_path_outputs )
list_of_path_inputs ::=
specify_input_terminal_descriptor { , specify_input_terminal_descriptor }
list_of_path_outputs ::=
specify_output_terminal_descriptor { , specify_output_terminal_descriptor }
A.7.3 Specify block terminals
specify_input_terminal_descriptor ::=
input_identifier
| input_identifier [ constant_expression ]
| input_identifier [ range_expression ]
specify_output_terminal_descriptor ::=
output_identifier
| output_identifier [ constant_expression ]
| output_identifier [ range_expression ]
input_identifier ::= input_port_identifier | inout_port_identifier
output_identifier ::= output_port_identifier | inout_port_identifier
A.7.4 Specify path delays
path_delay_value ::=
list_of_path_delay_expressions
| ( list_of_path_delay_expressions )
list_of_path_delay_expressions ::=
t_path_delay_expression
| trise_path_delay_expression , tfall_path_delay_expression
| trise_path_delay_expression , tfall_path_delay_expression , tz_path_delay_expression
| t01_path_delay_expression , t10_path_delay_expression , t0z_path_delay_expression ,
tz1_path_delay_expression , t1z_path_delay_expression , tz0_path_delay_expression
| t01_path_delay_expression , t10_path_delay_expression , t0z_path_delay_expression ,
tz1_path_delay_expression , t1z_path_delay_expression , tz0_path_delay_expression
t0x_path_delay_expression , tx1_path_delay_expression , t1x_path_delay_expression ,
tx0_path_delay_expression , txz_path_delay_expression , tzx_path_delay_expression
t_path_delay_expression ::= path_delay_expression
trise_path_delay_expression ::= path_delay_expression
tfall_path_delay_expression ::= path_delay_expression
tz_path_delay_expression ::= path_delay_expression
t01_path_delay_expression ::= path_delay_expression
t10_path_delay_expression ::= path_delay_expression
t0z_path_delay_expression ::= path_delay_expression
tz1_path_delay_expression ::= path_delay_expression
t1z_path_delay_expression ::= path_delay_expression
tz0_path_delay_expression ::= path_delay_expression
t0x_path_delay_expression ::= path_delay_expression
tx1_path_delay_expression ::= path_delay_expression
t1x_path_delay_expression ::= path_delay_expression
tx0_path_delay_expression ::= path_delay_expression
txz_path_delay_expression ::= path_delay_expression
tzx_path_delay_expression ::= path_delay_expression
path_delay_expression ::= constant_mintypmax_expression
edge_sensitive_path_declaration ::=
parallel_edge_sensitive_path_description = path_delay_value
| full_edge_sensitive_path_description = path_delay_value
parallel_edge_sensitive_path_description ::=
( [ edge_identifier ] specify_input_terminal_descriptor =>
specify_output_terminal_descriptor [ polarity_operator ] : data_source_expression )
full_edge_sensitive_path_description ::=
( [ edge_identifier ] list_of_path_inputs *>
list_of_path_outputs [ polarity_operator ] : data_source_expression )
data_source_expression ::= expression
edge_identifier ::= posedge | negedge
state_dependent_path_declaration ::=
if ( module_path_expression ) simple_path_declaration
| if ( module_path_expression ) edge_sensitive_path_declaration
| ifnone simple_path_declaration
polarity_operator ::= + | -
A.7.5 System timing checks
A.7.5.1 System timing check commands
system_timing_check ::=
$setup_timing_check
| $hold _timing_check
| $setuphold_timing_check
| $recovery_timing_check
| $removal_timing_check
| $recrem_timing_check
| $skew_timing_check
| $timeskew_timing_check
| $fullskew_timing_check
| $period_timing_check
| $width_timing_check
| $nochange_timing_check
$setup_timing_check ::=
$setup ( data_event , reference_event , timing_check_limit [ , [ notify_reg ] ] ) ;
$hold _timing_check ::=
$hold ( reference_event , data_event , timing_check_limit [ , [ notify_reg ] ] ) ;
$setuphold_timing_check ::=
$setuphold ( reference_event , data_event , timing_check_limit , timing_check_limit
[ , [ notify_reg ] [ , [ stamptime_condition ] [ , [ checktime_condition ]
[ , [ delayed_reference ] [ , [ delayed_data ] ] ] ] ] ] ) ;
$recovery_timing_check ::=
$recovery ( reference_event , data_event , timing_check_limit [ , [ notify_reg ] ] ) ;
$removal_timing_check ::=
$removal ( reference_event , data_event , timing_check_limit [ , [ notify_reg ] ] ) ;
$recrem_timing_check ::=
$recrem ( reference_event , data_event , timing_check_limit , timing_check_limit
[ , [ notify_reg ] [ , [ stamptime_condition ] [ , [ checktime_condition ]
[ , [ delayed_reference ] [ , [ delayed_data ] ] ] ] ] ] ) ;
$skew_timing_check ::=
$skew ( reference_event , data_event , timing_check_limit [ , [ notify_reg ] ] ) ;
$timeskew_timing_check ::=
$timeskew ( reference_event , data_event , timing_check_limit
[ , [ notify_reg ] [ , [ event_based_flag ] [ , [ remain_active_flag ] ] ] ] ) ;
$fullskew_timing_check ::=
$fullskew ( reference_event , data_event , timing_check_limit , timing_check_limit
[ , [ notify_reg ] [ , [ event_based_flag ] [ , [ remain_active_flag ] ] ] ] ) ;
$period_timing_check ::=
$period ( controlled_reference_event , timing_check_limit [ , [ notify_reg ] ] ) ;
$width_timing_check ::=
$width ( controlled_reference_event , timing_check_limit ,
threshold [ , [ notify_reg ] ] ) ;
$nochange_timing_check ::=
$nochange ( reference_event , data_event , start_edge_offset ,
end_edge_offset [ , [ notify_reg ] ] ) ;
A.7.5.2 System timing check command arguments
checktime_condition ::= mintypmax_expression
controlled_reference_event ::= controlled_timing_check_event
data_event ::= timing_check_event
delayed_data ::=
terminal_identifier
| terminal_identifier [ constant_mintypmax_expression ]
delayed_reference ::=
terminal_identifier
| terminal_identifier [ constant_mintypmax_expression ]
end_edge_offset ::= mintypmax_expression
event_based_flag ::= constant_expression
notify_reg ::= variable_identifier
reference_event ::= timing_check_event
remain_active_flag ::= constant_mintypmax_expression
stamptime_condition ::= mintypmax_expression
start_edge_offset ::= mintypmax_expression
threshold ::=constant_expression
timing_check_limit ::= expression
A.7.5.3 System timing check event definitions
timing_check_event ::=
[timing_check_event_control] specify_terminal_descriptor [ &&& timing_check_condition ]
controlled_timing_check_event ::=
timing_check_event_control specify_terminal_descriptor [ &&& timing_check_condition ]
timing_check_event_control ::=
posedge
| negedge
| edge_control_specifier
specify_terminal_descriptor ::=
specify_input_terminal_descriptor
| specify_output_terminal_descriptor
edge_control_specifier ::= edge [ edge_descriptor [ , edge_descriptor ] ]
edge_descriptor1 ::=
01
| 10
| z_or_x zero_or_one
| zero_or_one z_or_x
zero_or_one ::= 0 | 1
z_or_x ::= x | X | z | Z
timing_check_condition ::=
scalar_timing_check_condition
| ( scalar_timing_check_condition )
scalar_timing_check_condition ::=
expression
| ~ expression
| expression == scalar_constant
| expression === scalar_constant
| expression != scalar_constant
| expression !== scalar_constant
scalar_constant ::=
1'b0 | 1'b1 | 1'B0 | 1'B1 | 'b0 | 'b1 | 'B0 | 'B1 | 1 | 0
A.8 Expressions
A.8.1 Concatenations
concatenation ::= { expression { , expression } }
constant_concatenation ::= { constant_expression { , constant_expression } }
constant_multiple_concatenation ::= { constant_expression constant_concatenation }
module_path_concatenation ::= { module_path_expression { , module_path_expression } }
module_path_multiple_concatenation ::= { constant_expression module_path_concatenation }
multiple_concatenation ::= { constant_expression concatenation }
net_concatenation ::= { net_concatenation_value { , net_concatenation_value } }
net_concatenation_value ::=
hierarchical_net_identifier
| hierarchical_net_identifier [ expression ] { [ expression ] }
| hierarchical_net_identifier [ expression ] { [ expression ] } [ range_expression ]
| hierarchical_net_identifier [ range_expression ]
| net_concatenation
variable_concatenation ::= { variable_concatenation_value { , variable_concatenation_value } }
variable_concatenation_value ::=
hierarchical_variable_identifier
| hierarchical_variable_identifier [ expression ] { [ expression ] }
| hierarchical_variable_identifier [ expression ] { [ expression ] } [ range_expression ]
| hierarchical_variable_identifier [ range_expression ]
| variable_concatenation
A.8.2 Function calls
constant_function_call ::= function_identifier { attribute_instance }
( constant_expression { , constant_expression } )
function_call ::= hierarchical_function_identifier{ attribute_instance }
( expression { , expression } )
genvar_function_call ::= genvar_function_identifier { attribute_instance }
( constant_expression { , constant_expression } )
system_function_call ::= system_function_identifier
[ ( expression { , expression } ) ]
A.8.3 Expressions
base_expression ::= expression
bump_expression ::=
bump_operator variable_lvalue
| variable_lvalue bump_operator
conditional_expression ::= expression1 ? { attribute_instance } expression2 : expression3
constant_base_expression ::= constant_expression
constant_expression ::=
constant_primary
| unary_operator { attribute_instance } constant_primary
| constant_expression binary_operator { attribute_instance } constant_expression
| constant_expression ? { attribute_instance } constant_expression : constant_expression
| string
constant_mintypmax_expression ::=
constant_expression
| constant_expression : constant_expression : constant_expression
constant_range_expression ::=
constant_expression
| msb_constant_expression : lsb_constant_expression
| constant_base_expression +: width_constant_expression
| constant_base_expression -: width_constant_expression
dimension_constant_expression ::= constant_expression
expression1 ::= expression
expression2 ::= expression
expression3 ::= expression
expression ::=
primary
| unary_operator { attribute_instance } primary
| { attribute_instance } bump_expression
/* SB - I didn't add bump_operator to unary_operator because
it doesn't make sense unless the operand can be changed
and systemsim only seems to allow this syntax as well */
| ( operator_assignment )
| expression binary_operator { attribute_instance } expression
| conditional_expression
| string
lsb_constant_expression ::= constant_expression
mintypmax_expression ::=
expression
| expression : expression : expression
module_path_conditional_expression ::= module_path_expression ? { attribute_instance }
module_path_expression : module_path_expression
module_path_expression ::=
module_path_primary
| unary_module_path_operator { attribute_instance } module_path_primary
| module_path_expression binary_module_path_operator { attribute_instance }
module_path_expression
| module_path_conditional_expression
module_path_mintypmax_expression ::=
module_path_expression
| module_path_expression : module_path_expression : module_path_expression
msb_constant_expression ::= constant_expression
range_expression ::=
expression
| msb_constant_expression : lsb_constant_expression
| base_expression +: width_constant_expression
| base_expression -: width_constant_expression
width_constant_expression ::= constant_expression
A.8.4 Primaries
constant_primary ::=
constant_concatenation
| constant_function_call
| ( constant_mintypmax_expression )
| constant_multiple_concatenation
| genvar_identifier
| number
| parameter_identifier
| specparam_identifier
| time_literal
| '0 | '1 | 'z | 'Z | 'x | 'X
module_path_primary ::=
number
| identifier
| module_path_concatenation
| module_path_multiple_concatenation
| function_call
| system_function_call
| constant_function_call
| ( module_path_mintypmax_expression )
primary ::=
number
| hierarchical_identifier
| hierarchical_identifier [ expression ] { [ expression ] }
| hierarchical_identifier [ expression ] { [ expression ] } [ range_expression ]
| hierarchical_identifier [ range_expression ]
| concatenation
| multiple_concatenation
| function_call
| system_function_call
| constant_function_call
| ( mintypmax_expression )
| ( expression )
| { expression { , expression } }
| { expression { expression } }
| simple_type ' ( expression )
| simple_type ' { expression { , expression } }
| simple_type ' { expression { expression } }
| time_literal
| '0 | '1 | 'z | 'Z | 'x | 'X
| data_type
/* SB - I doubt we want data_type here... it doesn't make
sense in many expressions. We need to know what places it
makes sense and add it only to those types of
expressions.
*/
time_literal ::= integer [ . integer ] time_unit
time_unit ::= s | ms | us | ns | ps | fs
A.8.5 Expression left-side values
net_lvalue ::=
hierarchical_net_identifier
| hierarchical_net_identifier [ constant_expression ] { [ constant_expression ] }
| hierarchical_net_identifier [ constant_expression ] { [ constant_expression ] } [ constant_range_expression ]
| hierarchical_net_identifier [ constant_range_expression ]
| hierarchical_net_identifier ( [ constant_expression { , constant_expression } ] )
| net_concatenation
variable_lvalue ::=
variable_lvalue_item [ bump_operator ]
| hierarchical_variable_identifier ( [ constant_expression { , constant_expression } ] )
/* SB - This handles some of the postfix_expression
production. The rest was added to
hierarchical_variable_identifier. Since this production
was recursive, it was hard to know which applied to only
the leaf of the recursion vs what applied to every
stage. For example, I guessed that 'a->b->c' was ok, so
it went into hierarchical_variable_identifier, but I
guessed that a[1, 3, 5, 2].b[2:4].c([21, 24]) was not, so
these production elements stayed here. */
variable_lvalue_item ::=
hierarchical_variable_identifier
| hierarchical_variable_identifier [ expression ] { [ expression ] }
| hierarchical_variable_identifier [ expression ] { [ expression ] } [ range_expression ]
| hierarchical_variable_identifier [ range_expression ]
| variable_concatenation
A.8.6 Operators
unary_operator ::=
+ | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
binary_operator ::=
+ | - | * | / | % | == | != | === | !== | && | || | **
| < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<
bump_operator ::= + + | - -
unary_module_path_operator ::=
! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
binary_module_path_operator ::=
== | != | && | || | & | | | ^ | ^~ | ~^
A.8.7 Numbers
number ::=
decimal_number
| octal_number
| binary_number
| hex_number
| real_number
real_number1 ::=
unsigned_number . unsigned_number
| unsigned_number [ . unsigned_number ] exp [ sign ] unsigned_number
exp ::= e | E
decimal_number ::=
unsigned_number
| [ size ] decimal_base unsigned_number
| [ size ] decimal_base x_digit { _ }
| [ size ] decimal_base z_digit { _ }
binary_number ::= [ size ] binary_base binary_value
octal_number ::= [ size ] octal_base octal_value
hex_number ::= [ size ] hex_base hex_value
sign ::= + | -
size ::= non_zero_unsigned_number
non_zero_unsigned_number1 ::= non_zero_decimal_digit { _ | decimal_digit}
unsigned_number1 ::= decimal_digit { _ | decimal_digit }
binary_value1 ::= binary_digit { _ | binary_digit }
octal_value1 ::= octal_digit { _ | octal_digit }
hex_value1 ::= hex_digit { _ | hex_digit }
decimal_base1 ::= '[s|S]d | '[s|S]D
binary_base1 ::= '[s|S]b | '[s|S]B
octal_base1 ::= '[s|S]o | '[s|S]O
hex_base1 ::= '[s|S]h | '[s|S]H
non_zero_decimal_digit ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
decimal_digit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
binary_digit ::= x_digit | z_digit | 0 | 1
octal_digit ::= x_digit | z_digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
hex_digit ::=
x_digit | z_digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
| a | b | c | d | e | f | A | B | C | D | E | F
x_digit ::= x | X
z_digit ::= z | Z | ?
A.8.8 Strings
string ::= " { Any_ASCII_Characters_except_new_line } "
A.9 General
A.9.1 Attributes
attribute_instance ::= (* attr_spec { , attr_spec } *)
attr_spec ::=
attr_name = constant_expression
| attr_name
attr_name ::= identifier
A.9.2 Comments
comment ::=
one_line_comment
| block_comment
one_line_comment ::= // comment_text \n
block_comment ::= /* comment_text */
comment_text ::= { Any_ASCII_character }
A.9.3 Identifiers
arrayed_identifier ::=
simple_arrayed_identifier
| escaped_arrayed_identifier
block_identifier ::= identifier
cell_identifier ::= identifier
config_identifier ::= identifier
const_identifier ::= identifier
enum_identifier ::= identifier
escaped_arrayed_identifier ::= escaped_identifier [ range ]
escaped_hierarchical_identifier4 ::=
escaped_hierarchical_branch
{ .simple_hierarchical_branch | .escaped_hierarchical_branch }
escaped_identifier ::= \ {Any_ASCII_character_except_white_space} white_space
event_identifier ::= identifier
function_identifier ::= identifier
gate_instance_identifier ::= arrayed_identifier
generate_block_identifier ::= identifier
genvar_function_identifier ::= identifier /* Hierarchy disallowed */
genvar_identifier ::= identifier
hierarchical_block_identifier ::= hierarchical_identifier
hierarchical_event_identifier ::= hierarchical_identifier
hierarchical_function_identifier ::= hierarchical_identifier
hierarchical_identifier ::=
simple_hierarchical_identifier
| escaped_hierarchical_identifier
hierarchical_net_identifier ::= hierarchical_identifier
hierarchical_variable_identifier ::= hierarchical_identifier
hierarchical_task_identifier ::= hierarchical_identifier
identifier ::=
simple_identifier
| escaped_identifier
interface_identifier ::= identifier
inout_port_identifier ::= identifier
input_port_identifier ::= identifier
instance_identifier ::= identifier
library_identifier ::= identifier
memory_identifier ::= identifier
modport_identifier ::= identifier
module_identifier ::= identifier
module_instance_identifier ::= arrayed_identifier
net_identifier ::= identifier
output_port_identifier ::= identifier
parameter_identifier ::= identifier
port_identifier ::= identifier
real_identifier ::= identifier
simple_arrayed_identifier ::= simple_identifier [ range ]
simple_hierarchical_identifier3 ::=
simple_hierarchical_branch [ .escaped_identifier ]
simple_identifier2 ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_$ ] }
specparam_identifier ::= identifier
state_identifier ::= identifier
system_function_identifier5 ::= $[ a-zA-Z0-9_$ ]{ [ a-zA-Z0-9_$ ] }
system_task_identifier5 ::= $[ a-zA-Z0-9_$ ]{ [ a-zA-Z0-9_$ ] }
task_identifier ::= identifier
terminal_identifier ::= identifier
text_macro_identifier ::= simple_identifier
topmodule_identifier ::= identifier
type_declaration_identifier ::= type_identifier { packed_dimension }
type_identifier ::= identifier
udp_identifier ::= identifier
udp_instance_identifier ::= arrayed_identifier
variable_decl_assign_identifier ::=
variable_identifier { unpacked_dimension } [ = constant_expression ]
variable_declaration_identifier ::=
variable_identifier { unpacked_dimension }
variable_identifier ::= identifier
A.9.4 Identifier branches
/* SB - Some of the production elements of postfix_expression
(see comments with variable_lvalue definition) were
incorporated here. The ones that seemed to apply to every
stage of a path went here and the rest went into
variable_lvalue.
I also added support for the multiple dimensional arrays
of instances. */
simple_hierarchical_branch3 ::=
simple_identifier [{ [ unsigned_number ] ]}
[ { . simple_identifier [{ [ unsigned_number ] ]} } ]
| simple_identifier [{ [ unsigned_number ]} ]
[ { -> simple_identifier [{ [ unsigned_number ] ]} } ]
escaped_hierarchical_branch4 ::=
escaped_identifier [{ [ unsigned_number ] ]}
[ { . escaped_identifier [{ [ unsigned_number ] ]} } ]
| escaped_identifier [{ [ unsigned_number ] ]}
[ { -> escaped_identifier [{ [ unsigned_number ] ]} } ]
A.9.5 White space
white_space ::= space | tab | newline | eof6
NOTES
1) Embedded spaces are illegal.
2) A simple_identifier and arrayed_reference shall start with an alpha or underscore (_) character, shall have at least one character, and shall not have any spaces.
3) The period (.) in simple_hierarchical_identifier and simple_hierarchical_
branch shall not be preceded or followed by white_space.
4) The period in escaped_hierarchical_identifier and escaped_hierarchical_
branch shall be preceded by white_space, but shall not be followed by white_space.
5) The $ character in a system_function_identifier or system_task_identifier shall not be followed by white_space. A system_function_identifier or system_task_identifier shall not be escaped.
6) End of file.