Tuesday, 12 May 2015

SystemVerilog Enumerated Types : Same literal in more than one enumerated types

A well known SystemVerilog limitation is that the same literal cannot appear in more enumerated types within a package (or more precisely within a scope).
 
Let's look at a concrete example.

package my_pkg1;
  typedef enum {
    NONE,
    TX,
    RX

  } direction_e;

  typedef enum {
    NONE,
    ADD,
    SUB

  } math_action_e;
endpackage : my_pkg1

module top();
  import my_pkg1 :: *;
  direction_e dir_type;
  math_action_e math_action;

  initial begin
    dir_type    = my_pkg1 :: NONE;
    math_action = my_pkg1 :: NONE;
    $display("dir_type=%s, math_action=%s", dir_type.name(), math_action.name());
  end
endmodule : top

As discussed above, this code won't compile, because NONE is declared in both types.

//Output:
//** Error: Enum literal name 'NONE' already exists.


What I've seen people do in this case is try to uniquely the names by adding either prefixes or suffixes. For example, the math_action_e type would contain the value NONE2, in order not to clash with the NONE from direction_e.


Other simple solution would be to define each type in its own package. In the main package we would then import both of these packages:

package my_pkg1;
  typedef enum {
    NONE,
    TX,
    RX

  } direction_e;
endpackage : my_pkg1

package my_pkg2;
  typedef enum {
    NONE,
    ADD,
    SUB

  } math_action_e;
endpackage : my_pkg2


module top();
  import my_pkg1 :: *;
  import my_pkg2 :: *;

  direction_e dir_type;
  math_action_e math_action;

  initial begin
    dir_type        =  my_pkg1 :: NONE;
    math_action  =  my_pkg2 :: NONE;
    $display("dir_type=%s, math_action=%s", dir_type.name(), math_action.name());
  end
endmodule : top
We've solved the collision problem, because each type is now defined in its own scope.


In above example if I assign NONE directly without using any scope then simulator would cowardly refuse to compile the code above, because the literal NONE was imported via wildcards multiple times and it's ambiguous.

  initial begin
    dir_type        =  NONE;
    math_action  =  NONE;
    $display("dir_type=%s, math_action=%s", dir_type.name(), math_action.name());
  end

//Output:
//** Error: Identifier 'NONE' is not directly visible.
//   Found multiple Declaration of 'NONE' through wildcard imports from these packages : my_pkg1, my_pkg2
//** Error: Undefined variable: 'NONE'.
You can read more about it here

2 comments: