Is there a way in SystemVerilog to directly cast the output of a module to the desired type without an intermediate variable?

Essentially I was trying to figure out a way that I don’t have to use this clumsy workaround in my RTL to get it to compile cleanly. After trying several fruitless ways of searching for the answer, I decided to try leaving the question here for the experts.

Consider the following simplified example of what I had to do to get a clean compile of my synthesizable RTL. (please forgive any possible minor syntax errors as I manually obfuscated this from my real design and didn’t compile it afterward)

typedef enum logic [1:0]
   {ENUM_A,
    ENUM_B,
    ENUM_C,
    ENUM_D
    } t_gen_enum;

module example
   (input  t_gen_enum enum_in,
    output t_gen_enum enum_out
    );

   logic [$bits(t_gen_enum)-1:0] enum_out_temp;

   STANDARD_CELL_BUF enum_out_buffer [$bits(t_gen_enum)-1:0]
      (.i(enum_in),
       .o(enum_out_temp));

   assign enum_out = t_gen_enum'(enum_out_temp);

endmodule

If I try to connect the enumerated output in the same way I connect to the input, I get a warning like the following from vcs.

Warning-[ENUMASSIGN] Illegal assignment to enum variable
<filename>, <line_number>
example, "STANDARD_CELL_BUF enum_out_buffer[($bits(t_gen_enum) - 1):0]( .i (enum_in),  .o (enum_out));"
  Only expressions of the enum type can be assigned to an enum variable. 
  The type wire is incompatible with the enum 't_gen_enum'
  Expression: o
  Use the static cast operator to convert the expression to enum type.

Specifically it seems to be able to handle the enum being assigned to the inputs of the standard cell (which is an old school wire type) but not assigning the multiple wire type outputs back to the enumerated type.

I tried the obviously incorrect way (just in case) of putting the type cast directly in the output connection, but that naturally doesn’t work.

module example
   (input  t_gen_enum enum_in,
    output t_gen_enum enum_out
    );

   STANDARD_CELL_BUF enum_out_buffer [$bits(t_gen_enum)-1:0]
      (.i(enum_in),
       .o(t_gen_enum'(enum_out)}));

endmodule

I also tried one suggestion from this thread that does get rid of the compile warnings from vcs, but I’m not completely clear if the enum_out remains officially enumerated or not. The example code from trying this would be as follows.

module example
   (input  t_gen_enum enum_in,
    output t_gen_enum enum_out
    );

   STANDARD_CELL_BUF enum_out_buffer [$bits(t_gen_enum)-1:0]
      (.i(enum_in),
       .o({enum_out}));

endmodule

My workaround does compile cleanly, but feels clumsy. The other workaround is fairly clean but I’m not sure if the signal actually remains enumerated after connecting using the {} syntax.

I might be stuck with this, but hoping that someone here might know a better way.

Leave a Comment