'Define type in generate block and use it outside

I'm attempting to define a user-defined type in a generate block and then access it in the scope outside the generate block. Something like this:

generate
    if (SOME_PARAM == 0) begin
        typedef struct packed {
            logic [A-1:0][B-1:0] field1;
            logic [C-1:0] field2;
        } struct_id_t;
    end
    else begin
        typedef struct packed {
            logic [SOME_PARAM-1:0] other_field;
            logic [A-1:0][B-1:0] field1;
            logic [C-1:0] field2;
        } struct_id_t;
    end
endgenerate
struct_id_t some_struct_instance;

The last line of code triggers an error indicating that struct_id_t is undefined. Apparently, generate blocks create a local scope, which would explain the error.

Is there another way to accomplish this?

Before discussing what I've considered/tried, I'll first say that I understand one solution to this is to place all uses of struct_id_t in the local scope created by the generate block. However, this would require quite a bit of code duplicated between the blocks that I'd really prefer to avoid.

Other things I've considered:

A compiler directive does not create a local scope like a generate block. Unfortunately, (System)Verilog does not have an ifeq compiler directive, so I don't think this will work.

I also tried to forward declare the type. Something like:

typedef struct struct_id_t;
generate
    if (SOME_PARAM == 0) begin
        typedef struct packed {
            logic [A-1:0][B-1:0] field1;
            logic [C-1:0] field2;
        } struct_id_t;
    end
    else begin
        typedef struct packed {
            logic [SOME_PARAM-1:0] other_field;
            logic [A-1:0][B-1:0] field1;
            logic [C-1:0] field2;
        } struct_id_t;
    end
endgenerate
struct_id_t some_struct_instance;

The resulting error complains about struct_id_t never being defined. Section 6.18 of the 1800-2012 standard explains the error:

The actual data type definition of a forward typedef declaration shall be resolved within the same local scope or generate block.

So, the definition needs to be in the same scope.

I tried to create a label for the generate blocks that includes the parameter definition. That way I believe I could access the type hierarchically. Something along the lines of gen_name[SOME_PARAM].struct_id_t. But it seems that's not a valid name for a generate block.

What are my options?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source