news 2026/2/21 6:21:08

systemverilog--队列学习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
systemverilog--队列学习

近期在写功能模块的sv-ref_model时,想到使用队列来实现会方便很多,搜索队列的使用会有很多帖子,自己也是在前辈的基础上稍作总结,作为自己的记录,也供后续参考。

一、队列的核心概念

队列是一种大小可动态调整的有序集合,特点如下:

  • 索引访问:支持像数组一样用索引([0][1]…)访问元素,索引从 0 开始,$表示最后一个元素的索引。
  • 高效增删:在队列的头部和尾部添加 / 删除元素的时间复杂度为 O (1),比动态数组更高效。
  • 存储类型:可以存储基础类型(intbitbytestring)或复杂类型(类句柄、结构体)。
  • 声明语法:使用[$]标识,格式为数据类型 队列名[$];

二、队列的基础操作(核心)

下面通过代码示例展示队列的初始化、增删、访问、清空等基础操作,这些是日常使用中最频繁的操作。

1. 声明与初始化
module test_queue; initial begin // 1. 声明空队列 int q1[$]; string q2[$]; // 2. 声明并初始化队列(用{}赋值,元素用逗号分隔) int q3[$] = {10, 20, 30}; // 初始元素:10、20、30 int q4[$] = '{40, 50, 60}; // 也可以用'{}(SystemVerilog推荐写法) // 3. 打印队列(%p是格式化打印复合类型的占位符) $display("q1(空队列):%p", q1); $display("q3:%p", q3); $finish; end endmodule

输出结果

q1(空队列):'{} q3:'{10, 20, 30}
2. 元素的添加(头部 / 尾部)

队列提供了专门的方法用于在头部 / 尾部添加元素,也支持插入到指定位置:

module test_queue; initial begin int q[$] = {1, 2, 3}; $display("初始队列:%p", q); // 1. 尾部添加元素:push_back(最常用) q.push_back(4); // 队列变为:{1,2,3,4} $display("push_back(4)后:%p", q); // 2. 头部添加元素:push_front q.push_front(0); // 队列变为:{0,1,2,3,4} $display("push_front(0)后:%p", q); // 3. 插入到指定索引位置:insert(索引, 元素) q.insert(2, 99); // 在索引2的位置插入99,队列变为:{0,1,99,2,3,4} $display("insert(2,99)后:%p", q); $finish; end endmodule

输出结果

初始队列:'{1, 2, 3} push_back(4)后:'{1, 2, 3, 4} push_front(0)后:'{0, 1, 2, 3, 4} insert(2,99)后:'{0, 1, 99, 2, 3, 4}
3. 元素的移出/删除(头部 / 尾部 / 指定位置)
module test_queue; initial begin int q[$] = {0, 1, 99, 2, 3, 4}; $display("初始队列:%p", q); // 1. 尾部移出元素:pop_back(返回被移出的元素) int val1 = q.pop_back(); // 删除4,val1=4,队列变为:{0,1,99,2,3} $display("pop_back后:%p,被删除元素:%0d", q, val1); // 2. 头部移出元素:pop_front(返回被移出的元素) int val2 = q.pop_front(); // 删除0,val2=0,队列变为:{1,99,2,3} $display("pop_front后:%p,被删除元素:%0d", q, val2); // 3. 删除指定索引的元素:delete(索引) q.delete(1); // 删除索引1的99,队列变为:{1,2,3} $display("delete(1)后:%p", q); // 4. 清空整个队列:delete()(无参数) q.delete(); // 队列变为空 $display("delete()后(清空队列):%p", q); $finish; end endmodule

输出结果

初始队列:'{0, 1, 99, 2, 3, 4} pop_back后:'{0, 1, 99, 2, 3},被删除元素:4 pop_front后:'{1, 99, 2, 3},被删除元素:0 delete(1)后:'{1, 2, 3} delete()后(清空队列):'{}
4. 元素的访问与长度获取
module test_queue; initial begin int q[$] = {10, 20, 30, 40}; // 1. 通过索引访问元素(索引从0开始,$表示最后一个元素) $display("索引0的元素:%0d", q[0]); // 10 $display("最后一个元素(q[$]):%0d", q[$]); // 40 $display("倒数第二个元素(q[$-1]):%0d", q[$-1]); // 30 // 2. 获取队列长度:size()方法 $display("队列长度:%0d", q.size()); // 4 // 3. 修改指定索引的元素 q[1] = 200; // 索引1的元素从20改为200 $display("修改后队列:%p", q); // '{10,200,30,40} $finish; end endmodule

输出结果

索引0的元素:10 最后一个元素(q[$]):40 倒数第二个元素(q[$-1]):30 队列长度:4 修改后队列:'{10, 200, 30, 40}

三、队列的高级操作

1. 队列的切片(截取部分元素)

队列支持用[start:end]的切片语法截取指定范围的元素,返回新的队列:

module test_queue; initial begin int q[$] = {1, 2, 3, 4, 5}; // 1. 截取索引1到3的元素(包含1和3) int q_slice1[$] = q[1:3]; $display("q[1:3]:%p", q_slice1); // '{2,3,4} // 2. 截取从索引2到末尾的元素($表示最后一个索引) int q_slice2[$] = q[2:$]; $display("q[2:$]:%p", q_slice2); // '{3,4,5} // 3. 截取前3个元素(索引0到2) int q_slice3[$] = q[0:2]; $display("q[0:2]:%p", q_slice3); // '{1,2,3} $finish; end endmodule
2. 队列的拼接

使用{}运算符可以将多个队列(或单个元素)拼接成新的队列

module test_queue; initial begin int q1[$] = {1, 2}; int q2[$] = {3, 4}; // 1. 拼接两个队列 int q3[$] = {q1, q2}; $display("q1+q2:%p", q3); // '{1,2,3,4} // 2. 队列与单个元素拼接 int q4[$] = {q1, 99, q2}; $display("q1+99+q2:%p", q4); // '{1,2,99,3,4} // 3. 队列自身拼接(复制两倍) int q5[$] = {q1, q1}; $display("q1复制两倍:%p", q5); // '{1,2,1,2} $finish; end endmodule

最近在调试ref_model时要实现最邻近插值就用到了队列拼接功能,将一个队列q1复制两次,拼接在原有队列q2后面,实现语句:q2={q2, q1, q1}; 这样的实现是不是很简明?!

3. 队列的遍历(foreach 循环)

使用foreach循环可以遍历队列的所有元素,是处理队列数据的常用方式:

module test_queue; initial begin int q[$] = {10, 20, 30, 40}; $display("遍历队列元素:"); foreach (q[i]) begin $display("索引%0d的元素:%0d", i, q[i]); end // 遍历的同时修改元素(比如所有元素乘2) foreach (q[i]) begin q[i] = q[i] * 2; end $display("元素乘2后:%p", q); // '{20,40,60,80} $finish; end endmodule

输出结果

遍历队列元素: 索引0的元素:10 索引1的元素:20 索引2的元素:30 索引3的元素:40 元素乘2后:'{20, 40, 60, 80}
4. 复杂类型队列(类句柄队列)

队列可以存储类的句柄,常用于验证中存储事务对象(如 AHB/AXI 事务),注意需要使用深拷贝避免浅拷贝问题:

// 定义一个简单的事务类 class Trans; int data; // 深拷贝方法:创建新对象并复制属性 function Trans copy(); copy = new(); copy.data = this.data; endfunction endclass module test_queue; initial begin Trans q[$]; // 声明类句柄队列 Trans t1, t2; // 初始化队列 t1 = new(); t1.data = 100; t2 = new(); t2.data = 200; q.push_back(t1); q.push_back(t2); $display("队列元素值:%0d, %0d", q[0].data, q[1].data); // 100, 200 // 深拷贝:添加新对象到队列(避免浅拷贝) q.push_back(t1.copy()); q[2].data = 999; // 修改新对象,原对象不受影响 $display("修改后:%0d(原对象),%0d(新对象)", t1.data, q[2].data); // 100, 999 $finish; end endmodule

输出结果

队列元素值:100, 200 修改后:100(原对象),999(新对象)

队列的类型可以是常用的int、bit、byte、logic等,也可以是自定义的类型,那么队列中的每个元素都是一个自定义的变量。

四、队列的常用场景(验证中)

  1. 事务存储:测试平台中存储生成的激励事务、监测到的总线事务(如 AHB/AXI 的读写事务)。
  2. 数据缓冲:在驱动器(Driver)和监视器(Monitor)中缓冲数据,实现异步数据处理。
  3. 动态数据处理:需要频繁添加 / 删除元素的场景(如过滤无效事务、排序事务)。

五、总结

  1. 队列的核心特性:SystemVerilog 队列是动态有序集合,支持索引访问,头部 / 尾部增删元素效率高,声明用[$]
  2. 常用基础操作
    操作/方法说明
    添加

    push_back() :尾部添加

    push_front() :头部添加

    移出

    pop_back() :尾部移出

    pop_front() :头部移出

    清空

    delete() :删除整个队列

    delete(n) :删除指定位置的元素

    长度size() :整个队列内元素个数
  3. 高级操作:支持切片[start:end]、拼接{}foreach遍历,可存储基础类型和复杂类型(类句柄需深拷贝)。
  4. 应用场景:主要用于验证中的事务存储、数据缓冲和动态数据处理,是 Testbench 编写的核心数据类型之一。

有更多的使用方法和注意事项欢迎大家留言讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/8 0:15:51

MonitorControl完整教程:轻松掌控Mac外接显示器设置

MonitorControl完整教程:轻松掌控Mac外接显示器设置 【免费下载链接】MonitorControl MonitorControl/MonitorControl: MonitorControl 是一款开源的Mac应用程序,允许用户直接控制外部显示器的亮度、对比度和其他设置,而无需依赖原厂提供的软…

作者头像 李华
网站建设 2026/2/11 20:24:06

Qualcomm Atheros QCA9377无线网卡Linux驱动完整教程与详细步骤

Qualcomm Atheros QCA9377无线网卡Linux驱动完整教程与详细步骤 【免费下载链接】Qualcomm-Atheros-QCA9377-Wifi-Linux Drivers and Firmware for Qualcomm Atheros QCA9377 0042 [rev. 30] 项目地址: https://gitcode.com/gh_mirrors/qu/Qualcomm-Atheros-QCA9377-Wifi-Lin…

作者头像 李华
网站建设 2026/2/20 3:26:41

电网智能体的“决策感官”:高精度AI气象如何使电网自主预测、调度,实时平衡万亿级新能源波动?

摘要本文系统阐述高精度AI气象技术如何作为电网智能体的核心感知与决策系统,通过多尺度气象融合预测、源-网-荷-储动态耦合及自主优化调度三大技术体系,破解高比例新能源接入下电力系统运行的确定性难题。研究显示,该系统可将风电/光伏功率预…

作者头像 李华
网站建设 2026/2/3 22:24:39

Rustup工具链管理完全指南:从安装到精通

Rustup工具链管理完全指南:从安装到精通 【免费下载链接】rustup The Rust toolchain installer 项目地址: https://gitcode.com/gh_mirrors/ru/rustup Rustup作为Rust编程语言的官方工具链管理器,是每个Rust开发者必须掌握的核心工具。它不仅能简…

作者头像 李华
网站建设 2026/2/17 9:37:06

XChart完全指南:轻松实现Java数据可视化

XChart完全指南:轻松实现Java数据可视化 【免费下载链接】XChart 项目地址: https://gitcode.com/gh_mirrors/xch/XChart 还在为Java项目中枯燥的数据展示而烦恼吗?XChart这款轻量级图表库能帮你快速将数据转化为生动的可视化图表!本…

作者头像 李华