目录
1. What is part select and array slicing?
1. What is part select and array slicing?
Slicing是指从数组中选择一个连续区间的元素,比如说,a[3:5],表示选择数组a中的索引为3,4,5的元素。Slice is a selection of one or more contiguous elements of an array, whereas part select is a selection of one or more contiguous bits of an element.
需要注意的是,SystemVerilog与Python在Slicing处理方面有细微差别,Python中是不包含上界的,而SystemVerilog中则是包含上界。比如说在Python中a[3:5]是指选择数组中索引为3和4的元素,不包括索引为5的元素。
part-select是指对一个多比特数据选择其中一段连续区间内的数据,比如说对于32比特的整型数a,a[3:5]表示选择a[3],a[4],a[5]。
2. Dynamic part select
2.1 错误的写法
在普通用法中,不管是part-select还是array slicing,上界和下界应该都是常数。而不能是变量,比如说,你不能像下面这么用:
program partselect_arrayslice;
bit [63:0] data;
byte byte_data[8];
byte byte_data2[3];
initial begin : example1
void'(std::randomize(data));
for(int k=0; k<8; k++)begin
byte_data[k] = data[k*8+7 : k*8];
end
end
endprogram
这段代码编译后会报告错误:
最直观的做法就是不用for-loop,直接逐个赋值就是了,如下所示:
2.2 直观的正确写法
program partselect_arrayslice;
bit [63:0] data;
byte byte_data[8];
byte byte_data2[3];
initial begin : example2
void'(std::randomize(data));
$display("Value of data is %h",data);
// Using part select to copy data from data to byte_data.
byte_data[0] = data[07:0];
byte_data[1] = data[15:8];
byte_data[2] = data[23:16];
byte_data[3] = data[31:24];
byte_data[4] = data[39:32];
byte_data[5] = data[47:40];
byte_data[6] = data[55:48];
byte_data[7] = data[63:56];
$display("After the part select...");
foreach(byte_data[i])
$display("\t byte_data[%0d] = %h",i,byte_data[i]);
end
endprogram
运行后会得到(当然由于以上data是随机生成的,所以每次运行可能得到不同结果):
2.3 简明的写法
在比特数比较少的时候自然这样做也可以,但是比特数很多的时候,比如说256比特的数据像以上这样拆分要写32条语句,这就有点郁闷了。甚至在验证环境中这个比特数是可变的,像以上这样确定性的分拆本身就不可能了。该怎么办呢?
SystemVerilog提供了如下所示的简明的写法(但是,老实讲为什么就不能按照直观的方式定义成a[k:j]之类的写法我也不甚了了,还要进一步学习):
+: Notation
byte = data[j +: k];
j -> bit start position
k -> Number of bits up from j’th position
如上所述,j表示起点位置,k表示从起点位置开始的连续区间的长度。“+:”是用于索引上升区间,类似的还有索引下降区间的写法,如下所示:
-: Notation
byte = data[j -: k];
j -> bit start position
k -> Number of bits down from the j’th position
利用这个语法,以上例子可以改写为:
program partselect_arrayslice;
bit [63:0] data;
byte byte_data[8];
byte byte_data2[3];
initial begin : example3
void'(std::randomize(data));
$display("Value of data is %h",data);
// Using part select to copy data from data to byte_data.
$display("After the ascending part select...");
foreach(byte_data[i])begin
byte_data[i] = data[8*i +: 8];
$display("\t byte_data[%0d] = %h",i,byte_data[i]);
end
$display("After the descending part select...");
foreach(byte_data[i])begin
byte_data[i] = data[8*i+7 -: 8];
$display("\t byte_data[%0d] = %h",i,byte_data[i]);
end
endprogram
3. Dynamic array slicing
与part-select相似,array slicing也可以用以上这种语法来实现动态的区间选择。
如下例所示为纯行为级的模拟一个信号处理中常用的滑动窗的数据窗移动的处理过程。如果这个数据窗宽度非常大,用直接赋值的方法就会非常繁琐,而用"+:"或者"-:"则非常简单明了。
program partselect_arrayslice;
bit [63:0] data;
byte byte_data[8];
byte byte_data2[3];
initial begin : example4
foreach(byte_data[i]) begin
//void'(std::randomize(byte_data[i])); // NG.
byte tmp;
void'(std::randomize(tmp));
byte_data[i] = tmp;
$display("byte_data[%d] = %h",i,byte_data[i]);
end
// Dynamic array slicing to simulate sliding window
for(int k=0; k<5; k++)begin
byte_data2 = byte_data[k +: 3];
$display("byte_data2 = %h %h %h",byte_data2[0],byte_data2[1],byte_data2[2]);
end
end
endprogram
运行结果如下,可以看出byte_data2中存储的3个字节的数据是byte_data中的一个宽度为3的窗口内的数据。
Ref: SystemVerilog Array Slice - Verification Guide