{"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
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\ntypedef 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