/* 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 ; 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 } 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 | 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 data_type list_of_param_assignments ; parameter_declaration ::= parameter [ signing ] { packed_dimension } [ range ] 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 [ 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 [ port_type ] list_of_port_identifiers | input . port_identifier ( [ port_expression ] ) output_declaration ::= 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 ; 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 ; 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 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 /* 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_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_statement } endfunction [ : function_identifier ] | function [ automatic ] [ signing ] [ range_or_type ] [ interface_identifier . ] function_identifier ( function_port_list ) ; { 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_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_data_declaration | { attribute_instance } event_declaration | { attribute_instance } local_parameter_declaration | { attribute_instance } parameter_declaration 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 } 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 } 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 ) 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 ] | 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.