SystemVerilog Union用法详解
SystemVerilog 的 union 是一种复合数据类型,允许多个成员共享同一块存储空间。与 struct 不同,union 的所有成员占用相同的内存地址,适合表示同一数据在不同格式或视图下的多种解释。union 在硬件设计中用于紧凑存储和数据复用,在验证中用于灵活的数据表示。本文将详细介绍 SystemVerilog 中 union 的各种用法,包括基本定义、普通 union、打包 union、嵌套 union、参数化、以及在设计和验证中的应用,并提供示例代码和最佳实践。
1. Union 概述
union 是一种用户定义的复合数据类型,允许多个成员共享同一存储空间。访问 union 中的某个成员时,数据会按照该成员的类型解释。union 的主要特点包括:
- 共享存储:所有成员占用同一内存,修改一个成员会影响其他成员。
- 多视图表示:适合表示同一数据的多种格式(如整数和位向量)。
- 综合支持:
union(特别是packed union)可用于硬件设计。 - 验证支持:在测试环境中表示多格式数据。
主要用途
- 硬件设计:表示寄存器或数据包的多格式视图(如控制字段的不同解释)。
- 验证:在测试环境中处理多类型数据(如事务的多种表示)。
- 存储优化:减少内存占用,适合资源受限场景。
与 Struct 的对比
| 特性 | Struct | Union |
|---|---|---|
| 存储方式 | 每个成员独立存储 | 所有成员共享存储 |
| 内存大小 | 成员大小之和(可能有填充) | 最大成员的大小 |
| 访问方式 | 独立访问成员 | 同一数据不同解释 |
| 典型用途 | 组织相关数据 | 多视图数据表示 |
基本语法
union [packed] [signed/unsigned] {
type1 member1;
type2 member2;
...
} union_name;
packed:可选,指定紧凑存储,适合硬件综合。signed/unsigned:可选,指定union的符号性(通常与packed一起使用)。type1, type2:成员的数据类型,如logic、int等。union_name:联合体的名称。
2. 基本 Union 定义与使用
union 的基本用法是定义多个共享存储的成员,并在代码中选择特定成员访问。
示例:简单 Union
module example;
union {
int value;
logic [31:0] bits;
} data;
initial begin
data.value = 42;
$display("Value: %d, Bits: %h", data.value, data.bits);
data.bits = 32'hDEADBEEF;
$display("Value: %d, Bits: %h", data.value, data.bits);
end
endmodule
说明:
data包含两个成员:value(32 位整数)和bits(32 位逻辑向量)。- 成员共享同一存储空间,修改
data.value会改变data.bits的值。 - 访问
data.value时按整数解释,访问data.bits时按位向量解释。
注意:
- 所有成员共享同一内存,修改一个成员会影响其他成员。
- 成员大小可以不同,但存储空间以最大成员为准(此处为 32 位)。
3. Packed Union
packed union 将所有成员紧凑存储,适合硬件设计中表示连续的位字段。packed union 支持整体赋值、位操作和综合。
示例:紧凑数据格式
module example;
union packed {
logic [15:0] halfword;
logic [7:0] bytes [2];
} data;
initial begin
data.halfword = 16'hA5B6;
$display("Halfword: %h, Byte[0]: %h, Byte[1]: %h", data.halfword, data.bytes[0], data.bytes[1]);
data.bytes[0] = 8'hFF;
$display("Halfword: %h, Byte[0]: %h, Byte[1]: %h", data.halfword, data.bytes[0], data.bytes[1]);
end
endmodule
说明:
data包含两个成员:halfword(16 位)和bytes(2 个 8 位数组)。packed确保成员紧凑排列为 16 位。- 修改
data.bytes[0]会影响data.halfword的低 8 位。
注意:
packed union中的成员必须是可综合类型(如logic、bit)。- 成员按声明顺序排列,位对齐由综合工具确定。
- 存储大小由最大成员决定(此处为 16 位)。
带符号的 Packed Union
packed union 可以指定 signed 或 unsigned,影响整体的符号性。
module example;
union packed signed {
shortint value;
logic [15:0] bits;
} data;
initial begin
data.value = -500;
$display("Value: %d, Bits: %h", data.value, data.bits);
data.bits = 16'hFFFF;
$display("Value: %d, Bits: %h", data.value, data.bits);
end
endmodule
说明:
signed指定union整体为有符号类型。value按有符号整数解释,bits按位向量解释。- 赋值
data.bits = 16'hFFFF对应data.value = -1。
注意:
- 符号性仅影响整体赋值或比较,成员按其类型处理。
- 确保成员类型与符号性兼容。
4. 嵌套 Union
union 支持嵌套,可以与 struct 或其他 union 组合,形成复杂的数据结构。
示例:嵌套 Union
module example;
struct packed {
logic [3:0] header;
union packed {
logic [7:0] byte_data;
logic [3:0] nibbles [2];
} payload;
} packet;
initial begin
packet.header = 4'hA;
packet.payload.byte_data = 8'hB6;
$display("Header: %h, Byte: %h, Nibble[0]: %h",
packet.header, packet.payload.byte_data, packet.payload.nibbles[0]);
packet.payload.nibbles[0] = 4'hF;
$display("Header: %h, Byte: %h, Nibble[0]: %h",
packet.header, packet.payload.byte_data, packet.payload.nibbles[0]);
end
endmodule
说明:
packet是一个struct,包含header和嵌套的union(payload)。payload提供两种视图:byte_data(8 位)和nibbles(2 个 4 位)。- 修改
nibbles[0]会影响byte_data的低 4 位。
注意:
- 嵌套
union增加复杂性,需确保访问逻辑清晰。 - 使用
packed确保紧凑存储和综合支持。
5. 参数化 Union
union 可以通过参数动态配置成员的位宽或其他属性,增强复用性。
示例:参数化 Union
module example #(parameter WIDTH = 8);
union packed {
logic [WIDTH-1:0] value;
logic [WIDTH/2-1:0] halves [2];
} data;
initial begin
data.value = 'hA5;
$display("Value: %h, Half[0]: %h, Half[1]: %h",
data.value, data.halves[0], data.halves[1]);
end
endmodule
说明:
- 参数
WIDTH控制value和halves的位宽。 halves数组的每个元素为WIDTH/2位。- 参数化提高了
union的灵活性。
注意:
- 参数必须在编译时确定。
- 确保成员大小和位对齐兼容。
6. Union 数组
union 可以作为数组元素,适合表示一组多格式数据。
示例:Union 数组
module example;
union packed {
logic [7:0] byte;
logic [3:0] nibbles [2];
} data [0:2];
initial begin
data[0].byte = 8'hA5;
data[1].nibbles[0] = 4'hF;
data[1].nibbles[1] = 4'hE;
$display("Data[0].byte: %h", data[0].byte);
$display("Data[1].nibbles: %h, %h", data[1].nibbles[0], data[1].nibbles[1]);
end
endmodule
说明:
data是一个包含 3 个union的数组,每个union提供byte和nibbles视图。- 每个元素独立存储,修改
data[0]不影响data[1]。 - 适合表示数据包队列或寄存器组。
注意:
- 数组大小需在编译时确定(硬件设计)。
- 确保访问正确的成员视图。
7. Union 在硬件设计中的应用
union 在硬件设计中常用于表示寄存器或数据的多视图,支持紧凑存储和综合。
示例:多格式寄存器
module reg_bank (input logic clk, rst_n, write_en,
input logic [7:0] write_data,
input logic sel_view, // 0: byte, 1: nibbles
output logic [7:0] read_data);
union packed {
logic [7:0] byte;
logic [3:0] nibbles [2];
} reg_file;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n)
reg_file = '0;
else if (write_en)
reg_file.byte = write_data; // 写入按 byte 视图
end
assign read_data = sel_view ? {reg_file.nibbles[0], reg_file.nibbles[1]} : reg_file.byte;
endmodule
说明:
reg_file是一个packed union,提供byte和nibbles视图。- 写入使用
byte视图,读取根据sel_view选择视图。 - 适合多格式寄存器或控制字段。
注意:
- 使用
packed确保位对齐和综合支持。 - 确保读写逻辑与视图选择一致。
8. Union 在验证中的应用
union 在验证环境(如 UVM)中用于表示事务或数据的多种格式,增强测试灵活性。
示例:UVM 验证中的 Union
import uvm_pkg::*;
`include "uvm_macros.svh"
module example;
union {
int value;
logic [31:0] bits;
} packet;
initial begin
packet.value = 100;
`uvm_info("TEST", $sformatf("Value: %0d, Bits: %h", packet.value, packet.bits), UVM_LOW)
packet.bits = 32'hDEADBEEF;
`uvm_info("TEST", $sformatf("Value: %0d, Bits: %h", packet.value, packet.bits), UVM_LOW)
end
endmodule
说明:
packet表示事务的两种视图:value(整数)和bits(位向量)。- 使用 UVM 宏打印不同视图的内容。
- 适合测试数据包或配置的多格式表示。
注意:
- 验证中,
union常与struct或class结合。 - 确保访问正确的成员视图。
9. Union 的高级用法
9.1 联合体字面量赋值
SystemVerilog 支持使用字面量为 union 赋值,但需指定成员。
module example;
union packed {
logic [7:0] byte;
logic [3:0] nibbles [2];
} data;
initial begin
data = '{byte: 8'hA5}; // 指定 byte 成员赋值
$display("Von Byte: %h, Nibble[0]: %h", data.byte, data.nibbles[0]);
end
endmodule
说明:
'{byte: value}指定byte成员赋值。- 提高代码可读性。
注意:
- 必须显式指定成员名称。
- 仅适用于简单赋值。
9.2 联合体比较
union 支持整体比较,但需访问特定成员。
module example;
union packed {
logic [7:0] byte;
logic [3:0] nibbles [2];
} data1, data2;
initial begin
data1.byte = 8'hA5;
data2.byte = 8'hA5;
if (data1.byte == data2.byte)
$display("Data1 and Data2 are equal (byte view)");
end
endmodule
说明:
- 比较基于特定成员(如
data1.byte)。 packed union支持位级比较。
注意:
- 比较时确保使用同一成员视图。
- 非综合类型可能导致比较不可靠。
10. 注意事项与最佳实践
-
视图选择:
- 明确访问的
union成员,避免误用视图。 - 使用控制信号或标志区分视图(如
sel_view)。
- 明确访问的
-
综合支持:
- 使用
packed union确保紧凑存储和综合支持。 - 确保成员为可综合类型(如
logic、bit)。
- 使用
-
存储管理:
- 了解
union存储大小(最大成员决定)。 - 避免成员大小差异过大,浪费存储。
- 了解
-
嵌套设计:
- 嵌套
union与struct时,保持结构清晰。 - 使用
packed优化位对齐。
- 嵌套
-
验证环境:
- 在 UVM 中,使用
union表示事务的多格式视图。 - 结合
struct或class增强数据组织。
- 在 UVM 中,使用
-
代码可读性:
- 为
union和成员提供有意义的名称。 - 添加注释说明成员的用途和视图。
- 为
-
调试与验证:
- 检查
union成员的赋值和访问逻辑。 - 使用仿真工具验证不同视图的行为。
- 检查
11. 总结
SystemVerilog 的 union 是一种灵活的复合数据类型,允许多个成员共享存储空间,适合表示数据的多格式视图。通过基本 union、打包 union、嵌套 union、参数化、数组等功能,union 在硬件设计和验证中提供了紧凑和高效的数据表示方式。在硬件设计中,packed union 优化寄存器和数据包的存储;在验证中,union 增强事务的灵活性。遵循最佳实践并根据应用场景选择合适的 union 用法,能够显著提高代码质量和设计效率。
12. 设计工具推荐
- SZ901:
SZ901 是一款基于XVC协议的FPGA网络下载器。- 最高支持53M
- 支持4路JTAG独立使用
- 支持端口合并
- 支持国产FLASH烧写
- 下载器无限扩展
- 配备专属程序固化软件,一键烧写,能大大减小程序固化时间!
455

被折叠的 条评论
为什么被折叠?



