[SystemVerilog] Union

SystemVerilog Union用法详解

SystemVerilog 的 union 是一种复合数据类型,允许多个成员共享同一块存储空间。与 struct 不同,union 的所有成员占用相同的内存地址,适合表示同一数据在不同格式或视图下的多种解释。union 在硬件设计中用于紧凑存储和数据复用,在验证中用于灵活的数据表示。本文将详细介绍 SystemVerilog 中 union 的各种用法,包括基本定义、普通 union、打包 union、嵌套 union、参数化、以及在设计和验证中的应用,并提供示例代码和最佳实践。

1. Union 概述

union 是一种用户定义的复合数据类型,允许多个成员共享同一存储空间。访问 union 中的某个成员时,数据会按照该成员的类型解释。union 的主要特点包括:

  • 共享存储:所有成员占用同一内存,修改一个成员会影响其他成员。
  • 多视图表示:适合表示同一数据的多种格式(如整数和位向量)。
  • 综合支持union(特别是 packed union)可用于硬件设计。
  • 验证支持:在测试环境中表示多格式数据。

主要用途

  • 硬件设计:表示寄存器或数据包的多格式视图(如控制字段的不同解释)。
  • 验证:在测试环境中处理多类型数据(如事务的多种表示)。
  • 存储优化:减少内存占用,适合资源受限场景。

与 Struct 的对比

特性StructUnion
存储方式每个成员独立存储所有成员共享存储
内存大小成员大小之和(可能有填充)最大成员的大小
访问方式独立访问成员同一数据不同解释
典型用途组织相关数据多视图数据表示

基本语法

union [packed] [signed/unsigned] {
  type1 member1;
  type2 member2;
  ...
} union_name;
  • packed:可选,指定紧凑存储,适合硬件综合。
  • signed/unsigned:可选,指定 union 的符号性(通常与 packed 一起使用)。
  • type1, type2:成员的数据类型,如 logicint 等。
  • 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 中的成员必须是可综合类型(如 logicbit)。
  • 成员按声明顺序排列,位对齐由综合工具确定。
  • 存储大小由最大成员决定(此处为 16 位)。

带符号的 Packed Union

packed union 可以指定 signedunsigned,影响整体的符号性。

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 和嵌套的 unionpayload)。
  • 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 控制 valuehalves 的位宽。
  • 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 提供 bytenibbles 视图。
  • 每个元素独立存储,修改 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,提供 bytenibbles 视图。
  • 写入使用 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 常与 structclass 结合。
  • 确保访问正确的成员视图。

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. 注意事项与最佳实践

  1. 视图选择

    • 明确访问的 union 成员,避免误用视图。
    • 使用控制信号或标志区分视图(如 sel_view)。
  2. 综合支持

    • 使用 packed union 确保紧凑存储和综合支持。
    • 确保成员为可综合类型(如 logicbit)。
  3. 存储管理

    • 了解 union 存储大小(最大成员决定)。
    • 避免成员大小差异过大,浪费存储。
  4. 嵌套设计

    • 嵌套 unionstruct 时,保持结构清晰。
    • 使用 packed 优化位对齐。
  5. 验证环境

    • 在 UVM 中,使用 union 表示事务的多格式视图。
    • 结合 structclass 增强数据组织。
  6. 代码可读性

    • union 和成员提供有意义的名称。
    • 添加注释说明成员的用途和视图。
  7. 调试与验证

    • 检查 union 成员的赋值和访问逻辑。
    • 使用仿真工具验证不同视图的行为。

11. 总结

SystemVerilog 的 union 是一种灵活的复合数据类型,允许多个成员共享存储空间,适合表示数据的多格式视图。通过基本 union、打包 union、嵌套 union、参数化、数组等功能,union 在硬件设计和验证中提供了紧凑和高效的数据表示方式。在硬件设计中,packed union 优化寄存器和数据包的存储;在验证中,union 增强事务的灵活性。遵循最佳实践并根据应用场景选择合适的 union 用法,能够显著提高代码质量和设计效率。

12. 设计工具推荐

  • SZ901
    SZ901 是一款基于XVC协议的FPGA网络下载器。
    • 最高支持53M
    • 支持4路JTAG独立使用
    • 支持端口合并
    • 支持国产FLASH烧写
    • 下载器无限扩展
    • 配备专属程序固化软件,一键烧写,能大大减小程序固化时间!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值