• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

SOC/IP验证工程师

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

systermverilog中流操作符的详细用法

概述

流操作符(Streaming Operator)是 SystemVerilog 中专门用于数据打包(Pack)与解包(Unpack) 的利器。它能够将多个分散的数据信号组合成一个连续的比特流,或者从一个比特流中拆分出独立的数据信号。

在数字验证中,流操作符的应用场景非常广泛:总线事务打包、UVM 环境中的事务序列化、端序转换、协议数据处理等,都能通过它简洁高效地实现。


一、基本语法

流操作符有两种形式:

形式 方向 含义
{<<{ ... }} 从右向左(←) 先处理的操作数出现在结果的高位
{>>{ ... }} 从左向右(→) 先处理的操作数出现在结果的低位
// 打包:将分散的数据组合成一个数据
packed_data = {<<{a, b, c}};   // 从右向左打包
packed_data = {>>{a, b, c}};   // 从左向右打包

// 解包:从一个数据中拆分出多个数据
{>>{x, y, z}} = packed_data;   // 从左向右解包
{<<{x, y, z}} = packed_data;   // 从右向左解包

二、方向控制的详细说明

<<(从右向左):先处理列表中最右边的操作数,将其放在结果的高位。

>>(从左向右):先处理列表中最左边的操作数,将其放在结果的低位。

示例:方向不同,结果完全不同

假设有三个 4 位信号:a=4'hA,b=4'hB,c=4'hC:

logic [11:0] packed_data;

// 从右向左打包:先处理 c,再 b,最后 a
packed_data = {<<{a, b, c}};   // 结果:12'hCBA

// 从左向右打包:先处理 a,再 b,最后 c
packed_data = {>>{a, b, c}};   // 结果:12'hABC

方向控制特性在大小端转换(Big-Endian / Little-Endian)场景中尤其有用。


三、分块流操作(指定块大小)

可以在流操作符后面指定块大小(chunk size),表示按多大的位宽进行分组后再流式处理。

语法

{<< 块大小 { 数据 }}   // 按指定块大小从右向左处理
{>> 块大小 { 数据 }}   // 按指定块大小从左向右处理

示例 1:按 16 位分块

int j = { "A", "B", "C", "D" };  // 假设每个字母占 8 位,共 32 位
{ << 16 {j}}  // 按 16 位分块从右向左处理
// 结果:先取 j[15:0]("C""D"),再取 j[31:16]("A""B")
// 最终流为:"C" "D" "A" "B"

示例 2:按 4 位分块

{ << 4 { 6'b11_0101 }}  // 按 4 位分块从右向左处理
// 6'b11_0101 按 4 位划分:{6'b11, 6'b0101} → 先取右块 4'b0101,再取左块 2'b11
// 最终流为:4'b0101, 2'b11 → 即 "0101_11"

关键理解

  1. 先划分,再流式处理:先将数据按指定块大小划分,再按方向逐个块处理。
  2. 块内顺序保持不变:每个块内部的比特顺序是保持不变的,变的是块与块之间的顺序。

四、处理动态大小的数据(with 子句)

当流操作涉及动态数组(dynamic array)或队列(queue) 时,需要使用 with 子句来指定其大小。

基本用法

byte stream[$];           // 字节流队列
int  header;
int  len;
byte payload[];           // 动态数组
int  crc;

// 打包:将 header、len、payload、crc 按字节从右向左打包成流
q = {<< byte { header, len, payload, crc }};

// 解包:从流中恢复数据
{<< byte { header, len, payload with [0 +: len], crc }} = stream;

with 子句详解

  • payload with [0 +: len]:表示从 payload[0] 开始,选取 len 个元素。
  • [base +: width] 是 SystemVerilog 的索引部分选择(indexed part-select),表示从 base 开始向上选取 width 位。
  • with 子句的作用是告知编译器动态数组在流操作中应该取多长。

多个动态数组的处理("贪婪"规则)

如果流操作中有多个动态大小的数据,流操作符是 "贪婪"(greedy) 的——它会将剩余的所有比特都填充到第一个动态数组中。

// 假设 stream 有 100 个字节
{<< byte { dyn1, dyn2 }} = stream;
// dyn1 会吃掉所有 100 个字节,dyn2 为空!

因此,当有多个动态数组时,必须使用 with 子句明确指定每个的大小,否则行为可能不符合预期。

动态数组切片(Variable Slice)

流操作符还支持对数组进行变量切片(variable slicing),这是普通数组切片(要求常量)做不到的:

bit [7:0] cache[2][10];
bit [7:0] data_ca[];
int Start = 2, End = 5;

// 使用流操作符实现变量切片
data_ca = {>>{cache[index_req] with [Start:End]}};

五、常见应用场景

1. 端序转换

bit [31:0] big_endian_data;
bit [31:0] little_endian_data;

// 大端 ↔ 小端转换(按字节反转)
little_endian_data = {<< 8 {big_endian_data}};

2. 数组与位向量互转

bit [7:0] byte_array[4];     // 4 个字节
bit [31:0] word;

// 数组 → 位向量(打包)
word = {>> 8 {byte_array}};  // byte_array[0] 在高位

// 位向量 → 数组(解包)
{>> 8 {byte_array}} = word;

3. UVM 事务序列化

class Transaction;
  rand int  addr;
  rand int  data;
  rand byte payload[];
  // ...
endclass

// 打包成字节流发送
byte stream[$];
Transaction tr = new;
tr.randomize();
stream = {<< byte { tr.addr, tr.data, tr.payload }};

4. 协议帧解析

// 以太网帧头快速检查
if ({>> 8 {frame_header}} == 32'h12345678) begin
  // 匹配帧头
end

六、重要注意事项

1. 只能用于"可打包"类型

流操作符适用于所有可打包类型(packable types)——即元素本身是整型(bit、logic、int 等)的数组或结构体。

2. 总比特数必须匹配(除非使用动态数组)

对于固定大小的数据类型,源和目标的总比特数必须完全一致。

bit [7:0] src[3];    // 24 位
bit [31:0] dst;      // 32 位

// 错误!24 位 → 32 位,比特数不匹配
dst = {>>{src}};     // ❌ 编译错误

3. 流操作符左对齐(Left Justified)

当流操作的目标位宽大于源位宽时,结果会左对齐(高位补零)。

4. 与位拼接运算符 {} 的区别

特性 流操作符 {>>{}} 位拼接 {}
操作对象 数组、结构体等复合类型 单个信号或常量
动态大小 支持(配合 with) 不支持
分块处理 支持指定块大小 不支持
可读性 处理大量数据时更简洁 少量数据拼接更直观

七、总结

特性 说明
核心功能 将数据在"分散的多个变量"与"连续的比特流"之间高效转换
方向 >> 从左向右,<< 从右向左
分块 {<< N {data}} 按 N 位分块处理
动态数组 使用 with 子句指定大小
主要用途 端序转换、总线打包、UVM 事务序列化、协议解析

流操作符让原本需要多行循环或复杂拼接的代码,变成了一行简洁的表达式,是 SystemVerilog 验证工程师的必备技能。🚀

posted on 2026-07-05 10:48  SOC验证工程师  阅读(61)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3