【YOLO 训练专用】安防数据集
2026/6/23 22:50:07
近期在写功能模块的sv-ref_model时,想到使用队列来实现会方便很多,搜索队列的使用会有很多帖子,自己也是在前辈的基础上稍作总结,作为自己的记录,也供后续参考。
队列是一种大小可动态调整的有序集合,特点如下:
[0]、[1]…)访问元素,索引从 0 开始,$表示最后一个元素的索引。int、bit、byte、string)或复杂类型(类句柄、结构体)。[$]标识,格式为数据类型 队列名[$];。下面通过代码示例展示队列的初始化、增删、访问、清空等基础操作,这些是日常使用中最频繁的操作。
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}队列提供了专门的方法用于在头部 / 尾部添加元素,也支持插入到指定位置:
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}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()后(清空队列):'{}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}队列支持用[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使用{}运算符可以将多个队列(或单个元素)拼接成新的队列:
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}; 这样的实现是不是很简明?!
使用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}队列可以存储类的句柄,常用于验证中存储事务对象(如 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等,也可以是自定义的类型,那么队列中的每个元素都是一个自定义的变量。
[$]。| 操作/方法 | 说明 |
| 添加 | push_back() :尾部添加 push_front() :头部添加 |
| 移出 | pop_back() :尾部移出 pop_front() :头部移出 |
| 清空 | delete() :删除整个队列 delete(n) :删除指定位置的元素 |
| 长度 | size() :整个队列内元素个数 |
[start:end]、拼接{}、foreach遍历,可存储基础类型和复杂类型(类句柄需深拷贝)。有更多的使用方法和注意事项欢迎大家留言讨论。