当前位置: 首页 > backend >正文

[SystemVerilog] Arrays

SystemVerilog Arrays用法详解

SystemVerilog 提供了丰富的数组类型,用于存储和操作一组数据,广泛应用于硬件设计和验证。数组类型包括固定大小数组、动态数组、关联数组和队列,每种类型针对不同场景提供了灵活性和效率。SystemVerilog 数组支持硬件建模(如寄存器文件、内存)和验证中的复杂数据处理(如测试用例、数据包队列)。本文将详细介绍 SystemVerilog 中数组的各种用法,包括定义、操作、方法、参数化、多维数组、以及在设计和验证中的应用,并提供示例代码和最佳实践。

1. Arrays 概述

SystemVerilog 的数组类型分为以下四类:

  1. 固定大小数组(Fixed-Size Arrays):在编译时确定大小,适合硬件建模。
  2. 动态数组(Dynamic Arrays):运行时分配大小,适合验证中的可变数据。
  3. 关联数组(Associative Arrays):使用非连续索引(如字符串或整数),适合稀疏数据。
  4. 队列(Queues):动态大小,支持高效的插入和删除操作,适合 FIFO 数据处理。

主要用途

  • 硬件设计:实现寄存器组、存储器或数据缓冲区。
  • 验证:存储测试数据、事务队列或配置信息。
  • 模块化:提高代码的组织性和可维护性。

基本特性

  • 支持多种数据类型(如 logicintstruct)。
  • 提供内置方法(如 size()push_back())简化操作。
  • 可结合参数化、多维数组等功能实现复杂数据结构。

2. 固定大小数组(Fixed-Size Arrays)

固定大小数组在编译时确定大小,适合硬件设计中的寄存器文件、内存或常量表。

2.1 定义与使用

语法

type array_name [size];

示例

module example;logic [7:0] mem [0:15]; // 16个8位元素initial beginmem[0] = 8'hAA;mem[1] = 8'hBB;$display("Mem[0]: %h, Mem[1]: %h", mem[0], mem[1]);end
endmodule

说明

  • mem 是一个包含 16 个 8 位元素的数组,索引从 0 到 15。
  • 通过索引(如 mem[0])访问元素。
  • 支持综合,适合硬件存储建模。

注意

  • 数组大小必须在编译时确定。
  • 索引超出范围会导致仿真错误或综合失败。

2.2 数组初始化

固定大小数组支持使用字面量或默认值初始化。

示例

module example;logic [3:0] data [0:3] = '{4'h1, 4'h2, 4'h3, 4'h4}; // 字面量初始化logic [7:0] mem [0:3] = '{default: 8'hFF}; // 默认值初始化initial begin$display("Data: %p", data);$display("Mem: %p", mem);end
endmodule

说明

  • '{...} 指定每个元素的值。
  • '{default: value} 为所有元素赋相同值。
  • %p 格式化显示数组内容。

注意

  • 字面量初始化需匹配数组大小。
  • 默认值必须与元素类型兼容。

3. 动态数组(Dynamic Arrays)

动态数组在运行时分配大小,适合验证中处理可变长度的数据。

3.1 定义与分配

语法

type array_name [];

示例

module example;int dyn_array [];initial begindyn_array = new[5]; // 分配5个元素dyn_array[0] = 10;dyn_array[4] = 50;$display("Size: %0d, Element[0]: %0d", dyn_array.size(), dyn_array[0]);end
endmodule

说明

  • 使用 new[size] 分配数组大小,元素初始化为默认值(int 为 0)。
  • size() 方法返回当前数组大小。
  • 支持运行时调整大小。

注意

  • 分配前数组为空,访问会导致错误。
  • 动态数组不支持综合,仅用于验证。

3.2 动态数组操作

支持重新分配、复制和删除操作。

示例

module example;int dyn_array [];initial begindyn_array = new[3]; // 分配3个元素dyn_array = '{1, 2, 3}; // 初始化$display("Initial: %p", dyn_array);dyn_array = new[5](dyn_array); // 扩展到5个元素,保留原有数据$display("Extended: %p", dyn_array);dyn_array.delete(); // 删除数组$display("Size after delete: %0d", dyn_array.size());end
endmodule

说明

  • new[size](old_array) 扩展数组,复制原有数据,新元素初始化为默认值。
  • delete() 清空数组,大小变为 0。
  • 动态调整适合验证中的数据处理。

注意

  • 重新分配会覆盖原有数据,除非使用复制构造。
  • 删除后需重新分配才能使用。

4. 关联数组(Associative Arrays)

关联数组使用非连续索引(如字符串、整数),适合存储稀疏或键值对数据。

4.1 定义与使用

语法

type array_name [index_type];

示例

module example;int assoc_array [string];initial beginassoc_array["apple"] = 1;assoc_array["banana"] = 2;$display("Apple: %0d, Banana: %0d", assoc_array["apple"], assoc_array["banana"]);end
endmodule

说明

  • 索引类型为 string,键为 "apple""banana"
  • 适合键值对存储,如配置表。

注意

  • 关联数组不支持综合,仅用于验证。
  • 未定义的索引访问会返回默认值(需检查存在性)。

4.2 关联数组方法

支持检查、遍历和删除操作。

示例

module example;int assoc_array [string];initial beginassoc_array["x"] = 10;assoc_array["y"] = 20;if (assoc_array.exists("x"))$display("x exists: %0d", assoc_array["x"]);$display("Size: %0d", assoc_array.num());assoc_array.delete("x"); // 删除单个元素$display("Size after delete: %0d", assoc_array.num());end
endmodule

说明

  • exists(index) 检查索引是否存在。
  • num() 返回元素数量。
  • delete(index) 删除指定元素,delete() 清空数组。

注意

  • 使用 exists() 避免访问无效索引。
  • 遍历需使用 foreachfirst()/next()

5. 队列(Queues)

队列是动态数组的扩展,支持在头部或尾部高效插入和删除,适合 FIFO 或列表操作。

5.1 定义与操作

语法

type queue_name [$];

示例

module example;int queue [$];initial beginqueue.push_back(10); // 尾部添加queue.push_front(20); // 头部添加$display("Queue: %p", queue);int val = queue.pop_front(); // 移除并返回头部$display("Popped: %0d, Queue: %p", val, queue);end
endmodule

说明

  • 方法包括 push_backpush_frontpop_backpop_front
  • 队列大小动态调整,初始为空。

注意

  • 队列不支持综合,仅用于验证。
  • 访问空队列(如 pop_front())会导致错误。

5.2 队列方法

支持插入、删除和查询操作。

示例

module example;int queue [$];initial beginqueue = '{1, 2, 3}; // 初始化queue.insert(1, 10); // 在索引1插入10$display("After insert: %p", queue);queue.delete(2); // 删除索引2$display("After delete: %p", queue);$display("Size: %0d", queue.size());end
endmodule

说明

  • insert(index, value) 在指定索引插入元素。
  • delete(index) 删除指定索引的元素。
  • size() 返回队列长度。

注意

  • 插入或删除操作会调整索引,需注意后续访问。
  • 使用 foreach 遍历队列。

6. 参数化数组

数组可以通过参数动态配置大小或位宽,增强复用性。

示例:参数化固定大小数组

module example #(parameter SIZE = 4, WIDTH = 8);logic [WIDTH-1:0] mem [0:SIZE-1];initial beginmem[0] = 'hA5;$display("Mem[0]: %h", mem[0]);end
endmodule

说明

  • 参数 SIZE 控制数组大小,WIDTH 控制元素位宽。
  • 适合可配置的存储器或寄存器组。

注意

  • 参数必须在编译时确定。
  • 确保参数值与硬件需求匹配。

7. 多维数组

SystemVerilog 支持多维数组,适合表示矩阵、表格或复杂存储结构。

示例:二维数组

module example;logic [7:0] matrix [0:3][0:2]; // 4x3二维数组initial beginmatrix[0][0] = 8'h11;matrix[1][1] = 8'h22;$display("Matrix[0][0]: %h, Matrix[1][1]: %h", matrix[0][0], matrix[1][1]);end
endmodule

说明

  • matrix 是一个 4x3 的二维数组,每个元素为 8 位。
  • 通过多级索引(如 matrix[0][0])访问元素。
  • 适合图像数据或内存建模。

注意

  • 多维数组支持综合,但高维度可能增加复杂性。
  • 确保索引范围有效。

示例:多维动态数组

module example;int dyn_matrix [][];initial begindyn_matrix = new[3]; // 分配3行foreach (dyn_matrix[i])dyn_matrix[i] = new[2]; // 每行分配2列dyn_matrix[0][0] = 10;dyn_matrix[1][1] = 20;$display("Matrix: %p", dyn_matrix);end
endmodule

说明

  • 动态分配二维数组,需为每行单独分配。
  • 适合验证中的可变矩阵。

注意

  • 多维动态数组需逐级分配。
  • 不支持综合,仅用于验证。

8. 数组在硬件设计中的应用

固定大小数组广泛用于硬件设计中的存储器、寄存器组或数据缓冲区。

示例:寄存器文件

module reg_file (input logic clk, rst_n, write_en,input logic [1:0] addr,input logic [7:0] write_data,output logic [7:0] read_data);logic [7:0] regs [0:3];always_ff @(posedge clk or negedge rst_n) beginif (!rst_n)regs = '{default: 0};else if (write_en)regs[addr] <= write_data;endassign read_data = regs[addr];
endmodule

说明

  • regs 是一个 4 个 8 位寄存器的数组。
  • 支持同步写和异步读。
  • 适合硬件存储建模。

注意

  • 确保数组大小和索引与硬件需求匹配。
  • 验证综合工具支持。

9. 数组在验证中的应用

动态数组、关联数组和队列在验证环境(如 UVM)中用于存储测试数据、事务或配置。

示例:UVM 验证中的队列

import uvm_pkg::*;
`include "uvm_macros.svh"module example;int tx_queue [$];initial begintx_queue.push_back(100);tx_queue.push_back(200);`uvm_info("TEST", $sformatf("Queue: %p", tx_queue), UVM_LOW)tx_queue.pop_front();`uvm_info("TEST", $sformatf("After pop: %p", tx_queue), UVM_LOW)end
endmodule

说明

  • tx_queue 存储事务数据。
  • 使用 UVM 宏打印队列内容。
  • 队列适合事务处理或 FIFO 测试。

注意

  • 验证中,结合 structclass 增强数据组织。
  • 确保队列操作(如 pop)在非空时执行。

10. 数组的高级用法

10.1 数组切片

SystemVerilog 支持数组切片,提取或赋值部分元素。

module example;logic [7:0] data [0:5] = '{8'h1, 8'h2, 8'h3, 8'h4, 8'h5, 8'h6};initial beginlogic [7:0] slice [] = data[1:3]; // 提取索引1到3$display("Slice: %p", slice);end
endmodule

说明

  • data[1:3] 提取 {8'h2, 8'h3, 8'h4}
  • 切片返回动态数组。

注意

  • 切片不支持综合,仅用于验证。
  • 确保切片范围有效。

10.2 数组方法综合

固定大小数组支持部分内置方法(如 summin),可用于验证。

module example;int values [0:3] = '{10, 20, 30, 40};initial begin$display("Sum: %0d", values.sum());$display("Min: %0d", values.min());end
endmodule

说明

  • sum() 计算数组元素之和。
  • min() 返回最小值。
  • 支持 max()product() 等。

注意

  • 这些方法不支持综合,仅用于验证。
  • 确保数组非空。

11. 注意事项与最佳实践

  1. 类型选择

    • 硬件设计使用固定大小数组,支持综合。
    • 验证中使用动态数组、关联数组或队列,处理可变数据。
  2. 综合支持

    • 仅固定大小数组支持综合,确保大小和索引确定。
    • 验证综合工具对数组操作的支持。
  3. 初始化

    • 显式初始化数组,避免 X 或未定义值。
    • 使用字面量或默认值简化初始化。
  4. 操作安全

    • 动态数组和队列需检查大小或存在性(如 exists()size())。
    • 避免访问空数组或无效索引。
  5. 参数化

    • 使用参数配置数组大小或位宽,增强复用性。
    • 确保参数值与设计需求一致。
  6. 验证环境

    • 在 UVM 中,使用队列或关联数组存储事务。
    • 结合 structclass 组织复杂数据。
  7. 代码可读性

    • 为数组提供有意义的名称和注释。
    • 使用 foreach 或方法简化遍历和操作。
  8. 调试与验证

    • 检查数组的初始值和操作逻辑。
    • 使用仿真工具验证数组行为。

12. 总结

SystemVerilog 的数组类型(固定大小数组、动态数组、关联数组和队列)为硬件设计和验证提供了灵活的数据存储和操作方式。固定大小数组适合硬件建模,如寄存器文件和存储器;动态数组、关联数组和队列适合验证中的可变数据处理,如事务队列和配置表。通过参数化、多维数组、切片和内置方法,数组支持复杂数据结构和高效操作。遵循最佳实践并根据应用场景选择合适的数组类型,能够显著提高代码质量和设计效率。

13. 设计工具推荐

  • SZ901
    SZ901 是一款基于XVC协议的FPGA网络下载器。
    • 最高支持53M
    • 支持4路JTAG独立使用
    • 支持端口合并
    • 支持国产FLASH烧写
    • 下载器无限扩展
    • 配备专属程序固化软件,一键烧写,能大大减小程序固化时间!
http://www.xdnf.cn/news/3495.html

相关文章:

  • JGQ516Ⅱ数据采集湿法袋式除尘器实验装置
  • DRV8301 三相电机驱动芯片的硬件参数与应用设计
  • 【AI论文】ReasonIR:为推理任务训练检索器
  • HarmonyOS应用开发中实现本地化存储的几种方式
  • 接口幂等性保证:技术方案与实践指南
  • Three.js + React 实战系列-3D 个人主页:构建 About 组件 (响应式 + 互动 + 动效)✨
  • 【Shell 脚本编程】详细指南:第四章 - 循环结构(for、while、until) 深度解析
  • Java 基础--数组(Array):存储数据的“排排坐”
  • 青蛙Todo:高效管理日程,提升工作学习效率
  • L39.【LeetCode题解】面试题 01.07. 旋转矩阵(四种方法)
  • 鸿蒙开发:如何解决软键盘弹出后的间距
  • [免费]SpringBoot+Vue非物质文化网站系统【论文+源码+SQL脚本】
  • 2025五一杯数学建模竞赛B题 矿山数据处理 保姆级教程讲解|模型讲解
  • Spring AI开发跃迁指南(第二章:急速上手3——Advisor核心原理、源码讲解及使用实例)
  • 如何使用网站备份到u盘,网站数据备份到U盘的方法
  • Python 函数装饰器和闭包(装饰器基础知识)
  • 二叉搜索树中的搜索(递归解决)
  • 【Shell 脚本编程】详细指南:第一章 - 基础入门与最佳实践
  • 软件工程国考
  • C++负载均衡远程调用学习之消息路分发机制
  • python创建Directory和python package的区别
  • 【分享】数据恢复大师6.10[特殊字符]恢复手机误删的数据[特殊字符]
  • 运维工作中,Ansible常用模块有哪些?
  • 【云备份】服务端工具类实现
  • 解决 Oracle EXPDP 無法鎖定 NFS 相關錯誤: ORA-27086 flock: No locks available
  • ActiveMQ 性能优化与网络配置实战(一)
  • 2025MathorCup数学应用挑战赛B题
  • 机器视觉开发-打开摄像头
  • GAMES202-高质量实时渲染(Real-time Environment Mapping)
  • 【二】 数字图像的运算 (下)【数字图像处理】