news 2026/4/18 8:41:40

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/4/17 8:54:19

Node.js应用打包终极指南:一键生成跨平台可执行文件

Node.js应用打包终极指南:一键生成跨平台可执行文件 【免费下载链接】nexe 🎉 create a single executable out of your node.js apps 项目地址: https://gitcode.com/gh_mirrors/ne/nexe 你是否曾经为Node.js应用的部署而烦恼?需要确…

作者头像 李华
网站建设 2026/4/13 18:13:54

【dz-997】智能台灯

摘要 随着生活节奏的加快和健康意识的提升,合理控制照明时间、根据环境自动调节灯光已成为现代家居照明的重要需求。传统台灯多依赖手动开关,无法根据环境变化自动调节,也难以精准控制使用时长,不仅浪费能源,还可能因…

作者头像 李华
网站建设 2026/4/16 4:04:17

【dz-999】筒子纱的设计与实现

摘要 在纺织生产过程中,筒子纱的重量控制与环境监测对保证产品质量、提高生产效率至关重要。传统的筒子纱管理主要依赖人工称重和环境巡查,不仅效率低下、误差较大,而且难以实时掌握重量超标情况,容易影响后续加工环节的稳定性&a…

作者头像 李华
网站建设 2026/4/17 6:52:21

MCP认证必读:AZ-500云Agent文档全解析(专家级配置技巧曝光)

第一章:MCP AZ-500云Agent概述MCP AZ-500云Agent是微软认证安全工程师(Microsoft Certified: Security Engineer Associate)考试体系中的核心技术组件之一,专为云环境下的安全监控、威胁检测与合规性管理提供自动化支持。该代理部…

作者头像 李华
网站建设 2026/4/18 8:35:23

【MCP AZ-500云Agent优化终极指南】:揭秘高性能配置的5大核心策略

第一章:MCP AZ-500云Agent优化的核心价值在现代云安全架构中,MCP AZ-500云Agent不仅是监控与响应的关键组件,更是实现自动化防护策略的核心执行者。通过深度集成Azure Monitor、Microsoft Defender for Cloud及自定义策略引擎,AZ-…

作者头像 李华
网站建设 2026/4/18 7:08:09

2025 图纸加密全功能解析:8款图纸加密软件分享

在数字化设计与协同办公成为主流的今天,图纸作为企业的核心知识产权,其安全防护至关重要。本文将全面解析2025年值得关注的图纸加密技术,并重点介绍8款支持跨平台、跨终端同步的防护工具,帮助工程师与管理者在高效协作中筑牢安全防…

作者头像 李华