jkang
jkang

Reputation: 549

Automatically pad SystemVerilog packed structs so that they can be put into a union

I have the following structs:

typedef struct packed {
  logic vld;
  logic [`ADDR_RNG] addr;
  logic [`CMD_RNG] cmd;
  logic [`IDX_RNG] idx;
} pkt1Type_t;

typedef struct packed {
  logic vld;
  logic [`ADDR2_RNG] addr;
  logic [`CMD_RNG] cmd;
  logic [`IDX_RNG] idx;
} pkt2Type_t;

typedef struct packed {
  logic [???] padding;
  pkt1Type_t pkt;
} pkt1TypePadded_t;
typedef struct packed {
  logic [???] padding;
  pkt2Type_t pkt;
} pkt2TypePadded_t;

typedef union packed {
  pkt1TypePadded_t pkt1;
  pkt2TypePadded_t pkt2;
} pkt_t;

Where ADDR_RNG and ADDR2_RNG can be different.

As I understand it, SV structs for design (synthesizable) need to be of the same size. Is there a programmatic way to compute the size of pkt1Type_t and pkt2Type_t, find the larger of the 2 and then use it as the range literal in the [???] section above?

Or do I need to compute this manually or through the preprocessor `define?

Upvotes: 1

Views: 1074

Answers (1)

dave_59
dave_59

Reputation: 42698

The dilemma here is only one union member needs to be padded to the size of the other member. But you cannot have a struct member with 0 width. So your packed union has to be at least 1-bit wider than the largest member

parameter MAXSIZE = ($bits(pkt1Type_t) > $bits(pkt2Type_t)) ? 
               $bits(pkt1Type_t) : $bits(pkt2Type_t);

typedef struct packed {
  logic [MAXSIZE-$bits(pkt1Type_t):0] padding;
  pkt1Type_t pkt;
} pkt1TypePadded_t;
typedef struct packed {
  logic [MAXSIZE-$bits(pkt2Type_t):0] padding;
  pkt2Type_t pkt;
} pkt2TypePadded_t;

typedef union packed {
  pkt1TypePadded_t pkt1;
  pkt2TypePadded_t pkt2;
} pkt_t;

There might be better approaches for what you are trying to do (i.e. tagged unions, let construct, but difficult to say without known more what you need to do with this.

Upvotes: 2

Related Questions