jclin
jclin

Reputation: 2559

Using assignment pattern for union inside a struct in SystemVerilog

This is an example for illustration. In SystemVerilog, it has array assignment pattern and struct assignment pattern syntax. No matter the union construct here is packed or unpacked, whether it is synthesizable or not, is it a valid usage for assignment pattern? If yes, what value should be for union x?

typedef struct {
  int a;
  byte b;
  union packed {
      int c;
      bit [31:0] d;
  } x;
} S;

module top (s);
  output S s;
  assign s = '{int:2, default:1};
endmodule

If no, is it means I have to specify the initial value each field by field for the unpacked structure?

initial begin
  s.a = 2;
  s.b = 1;
  s.x.c = 2;
end

Upvotes: 1

Views: 10952

Answers (3)

Jonathan Mayer
Jonathan Mayer

Reputation: 348

I think identifying union members by type instead of name is an anti-pattern, but YMMV. I had the same question, and I think the answer is "you can't."

It might clarify the issue if the union members are themselves packed structs:

module tb();

typedef struct packed {
  logic [7:0] b1;
  logic [7:0] b0;
} two_bytes_t;

typedef struct packed {
  logic [3:0] n3;
  logic [3:0] n2;
  logic [3:0] n1;
  logic [3:0] n0;
} four_nibbles_t;

typedef union packed {
  two_bytes_t two_bytes;
  four_nibbles_t four_nibbles;
} my_union_t;

my_union_t my_union;

typedef struct packed {
  logic [7:0] a;
  my_union_t u;
} my_struct_t;

my_struct_t my_struct;

initial begin
  my_union.two_bytes = '{b0: 1, b1: 2};
  my_union.four_nibbles = '{n0: 1, n1: 1, n2: 3, n3: 4};
  $display("%p", my_union);

`ifdef UNDEFINED
  // this doesn't work:
  //
  my_struct = '{
    u.two_bytes: '{b0: 3, b1: 4},
    default: '0
  };
  // produces:
  //     u.two_bytes: '{b0: 3, b1: 4},
  //               |
  // xmelab: *E,CUVUNF (./foo.sv,35|14): Hierarchical name component lookup failed for 'u' at 'tb'.
  //     u.two_bytes: '{b0: 3, b1: 4},
  //     |
  // xmelab: *E,URCEN (./foo.sv,35|4): Unresolved constant expression VST_AP_ITEM.
`endif
  // this works:
  my_struct = '0;
  my_struct.u.two_bytes = '{b0: 1, b1: 2};
  $display("%p", my_struct);
end

endmodule : tb

Upvotes: 0

Paddu
Paddu

Reputation: 246

I tried this modified example:

typedef bit [31:0] Word;
typedef struct {
  int a;
  byte b;
  union packed {
      int c;
      Word d;
  } x;
  union packed {
      Word d;
      int c;
  } y;
} S;

module top (s);
  output S s;
  assign s = '{ int:2, Word:3, default:1 };

  initial begin
    #10
        $display ("s.a = %d, s.b = %h, s.x.c = %d, s.x.d = %h s.y.d = %h s.y.c = %d",
                  s.a, s.b, s.x.c, s.x.d, s.y.d, s.y.c);
  end 
endmodule

Modelsim gives this output:

s.a =           2, s.b = 01, s.x.c =           3, s.x.d = 00000003 s.y.d = 00000002 s.y.c =           2

whereas VCS gives this output:

s.a =           2, s.b = 01, s.x.c =           3, s.x.d = 00000003 s.y.d = 00000003 s.y.c =           3

This shows that simulators treat such code the way they want and there is no standard behaviour to be expected.

The following syntax would be safer to use:

assign s = '{ int:2, default:1, x:3, y:4 };

With this both Modelsim & VCS give:

s.a =           2, s.b = 01, s.x.c =           3, s.x.d = 00000003 s.y.d = 00000004 s.y.c =           4

Upvotes: 1

sm535
sm535

Reputation: 587

I modified your code little bit to print the assigned values.

typedef struct {
  int a;        
  byte b;       
  union packed {
      int c;
      bit [31:0] d;
  } x; 
} S;

module top (s);
  output S s;
  assign s = '{int:2, default:1};

  initial begin
    #10
        $display ("s.a = %d, s.b = %h, s.x.c = %d, s.x.d = %h", s.a, s.b, s.x.c, s.x.d);
  end 
endmodule

Following is the result from ncsim:

s.a =           2, s.b = 01, s.x.c =           1, s.x.d = 00000001

And from vcs:

s.a =           2, s.b = 01, s.x.c =           1, s.x.d = 00000001

Hope this answers your question.

Upvotes: 2

Related Questions