{"id":455,"date":"2017-01-17T10:00:28","date_gmt":"2017-01-17T18:00:28","guid":{"rendered":"http:\/\/www.verilogpro.com\/?p=455"},"modified":"2022-09-29T00:58:36","modified_gmt":"2022-09-29T07:58:36","slug":"systemverilog-structures-unions-design","status":"publish","type":"post","link":"https:\/\/www.verilogpro.com\/systemverilog-structures-unions-design\/","title":{"rendered":"SystemVerilog Struct and Union – for Designers too"},"content":{"rendered":"\n

SystemVerilog struct (ure) and union are very similar to their C programming counterparts, so you may already have a good idea of how they work. But have you tried using them in your RTL design? When used effectively, they can simplify your code and save a lot of typing. Recently, I tried incorporating SystemVerilog struct and union in new ways that I had not done before with surprisingly (or not surprisingly?) good effect. In this post I would like to share with you some tips on how you can also use them in your RTL design.<\/p>\n\n\n\n

What is a SystemVerilog Struct (ure)?<\/h2>\n\n\n\n

A SystemVerilog struct is a way to group several data types. The entire group can be referenced as a whole, or the individual data type can be referenced by name. It is handy in RTL coding when you have a collection of signals you need to pass around the design together, but want to retain the readability and accessibility of each separate signal.<\/p>\n\n\n\n

When used in RTL code, a packed<\/strong> SystemVerilog struct is the most useful. A packed struct is treated as a single vector, and each data type in the structure is represented as a bit field. The entire structure is then packed together in memory without gaps. Only packed data types and integer data types are allowed in a packed struct. Because it is defined as a vector, the entire structure can also be used as a whole with arithmetic and logical operators.<\/p>\n\n\n\n

An unpacked<\/strong> SystemVerilog struct, on the other hand, does not define a packing of the data types. It is tool-dependent how the structure is packed in memory. Unpacked struct probably will not synthesize by your synthesis tool, so I would avoid it in RTL code. It is, however, the default mode of a structure if the packed<\/strong> keyword is not used when defining the structure.<\/p>\n\n\n\n

SystemVerilog struct is often defined with the typedef<\/strong> keyword to give the structure type a name so it can be more easily reused across multiple files. Here is an example:<\/p>\n\n\n\n

typedef enum logic[15:0]\n{\n  ADD = 16'h0000,\n  SUB = 16'h0001\n} my_opcode_t;\n\ntypedef enum logic[15:0]\n{\n  REG = 16'h0000,\n  MEM = 16'h0001\n} my_dest_t;\n\ntypedef struct packed\n{\n  my_opcode_t  opcode; \/\/ 16-bit opcode, enumerated type\n  my_dest_t    dest; \/\/ 16-bit destination, enumerated type\n  logic [15:0] opA;\n  logic [15:0] opB;\n} my_opcode_struct_t;\n\nmy_opcode_struct_t cmd1;\n\ninitial begin\n  \/\/ Access fields by name\n  cmd1.opcode <= ADD;\n  cmd1.dest <= REG;\n  cmd1.opA <= 16'h0001;\n  cmd1.opB <= 16'h0002;\n\n  \/\/ Access fields by bit position\n  cmd1[63:48] <= 16'h0000\n  cmd1[47:32] <= 16'h0000;\n  cmd1[31:16] <= 16'h0003;\n  cmd1[15: 0] <= 16'h0004;\n\n  \/\/ Assign fields at once\n  cmd1 <= '{SUB, REG, 16'h0005, 16'h0006};\nend<\/pre>\n\n\n\n