U
unfrostedpoptart
Guest
Hi all.
Writing some generic register code and trying (again) to find a clean way to do it. For verification, it's easy using classes and even the whole UVM Register methodology. However, for RTL, not so much.
I have N registers and need to declare the various constants associated with them and also declare struct types for each. The tricky part is that each register can have up to M fields, where M is the number of bits in the register. Each of these also has parameters associated with them. The catch is that structs can't take parameters! I want something like this:
typedef struct packed {
logic [3:0] lsb;
logic [3:0] msb;
} my_bit_t;
typedef struct packed {
logic [3:0] address;
logic [3:0] num_fields;
my_bit_t [$clog2(num_fields)-1:0] bit_config;
} my_reg_t;
The "cleanest" workaround seems to be to always define M fields (my_bit_t [$clog2(M)-1:0] ) and just put dummy data in the unused ones.
Any better way (and not using macros, which will surely turn into an non-functional mess)?
Thanks,
David
Writing some generic register code and trying (again) to find a clean way to do it. For verification, it's easy using classes and even the whole UVM Register methodology. However, for RTL, not so much.
I have N registers and need to declare the various constants associated with them and also declare struct types for each. The tricky part is that each register can have up to M fields, where M is the number of bits in the register. Each of these also has parameters associated with them. The catch is that structs can't take parameters! I want something like this:
typedef struct packed {
logic [3:0] lsb;
logic [3:0] msb;
} my_bit_t;
typedef struct packed {
logic [3:0] address;
logic [3:0] num_fields;
my_bit_t [$clog2(num_fields)-1:0] bit_config;
} my_reg_t;
The "cleanest" workaround seems to be to always define M fields (my_bit_t [$clog2(M)-1:0] ) and just put dummy data in the unused ones.
Any better way (and not using macros, which will surely turn into an non-functional mess)?
Thanks,
David