struct结构体可以用来定义格式相对固定的数据结构,无论验证环境还是设计代码中都可以用来组织固定格式的信息,比如module input/outpu、fifo出入队信息。最近也仔细学习了下,将之前没有关注过的细节汇总下。
先定义一个结构体,最简单的unpacked struct定义方式如下:
typedef struct{
logic ty, par;
logic [3:0] id;
logic [3:0] addr;
integer data;
} frame_info;
frame_info f1, f2[1:0];
细节1:结构体的花式赋值方式;
不得不说,结构体的赋值方式多种多样,比如说可以这样直接赋值:
f1.ty = 1'b1;
f1.addr = 4'ha;
$display("frame_info = %0d, %0d, %0d, %0d, %0d", f1.ty, f1.par, f1.id, f1.addr, f1.data);
还可以这样整体赋值:
f1 = '{'b0, 'b1, 'd3, 'd6, 'd20};
$display("frame_info = %0d, %0d, %0d, %0d, %0d", f1.ty, f1.par, f1.id, f1.addr, f1.data);
还可以这样整个数组赋值,注意高位在前低位在后:
f2 = '{'{'b0, 'b1, 'd3, 'd6, 'd20}, '{'b1, 'b0, 'd2, 'd7, 'd40}};
$display("frame_info = %0d, %0d, %0d, %0d, %0d", f2[1].ty, f2[1].par, f2[1].id, f2[1].addr, f2[1].data);
还可以这样按名称赋值,注意加default:
f1 = '{ty:'b1, par:'b0, data:'d52, default:'0};
$display("frame_info = %0d, %0d, %0d, %0d, %0d", f1.ty, f1.par, f1.id, f1.addr, f1.data);
还可以按类型赋值,同样注意加default,但是例如logic[7:0]这种我想加进去报错了 :
f1 = '{logic:'1, integer:'d100, default:'0};
$display("frame_info = %0d, %0d, %0d, %0d, %0d", f1.ty, f1.par, f1.id, f1.addr, f1.data);
你甚至可以混合乱炖赋值:
f1 = '{data:'hff, logic:'h1, default:'0};
$display("frame_info = %0d, %0d, %0d, %0d, %0d", f1.ty, f1.par, f1.id, f1.addr, f1.data);
细节2:默认struct是unpacked的,即地址空间并不连续;需要连续的地址空间,需要packed;
例如如下定义:
typedef struct{
logic ty, par;
logic [3:0] id;
logic [3:0] addr;
logic [7:0] data;
} frame_upa;
typedef struct packed{
logic ty, par;
logic [3:0] id;
logic [3:0] addr;
logic [7:0] data;
} frame_pac;
logic vr_data;
frame_upa f1 = '{'b0, 'b1, 'd3, 'd6, 'd20};
frame_pac f2 = '{'b1, 'b1, 'd5, 'd2, 'd80};
直接取值是没有问题的:
vr_data = f1.data;
vr_data = f2.data;
但是按照占位整体赋值会报错:
f1 = 18'h1F5;
对于packed类型来说,这些操作都是ok的:
f2 = 18'h1F5;
vr_data = f2[7:0];
vr_data = f2 >> 2;