SystemVerilog foreach Constraint
SystemVerilog提供了在约束内使用foreach循环的支持,因此可以约束数组。
foreach构造遍历数组的元素,其参数是表示数组中单个实体的标识符。
例
下面显示的代码声明了一个名为array的静态数组,其大小为5。此数组可以容纳5个元素,其中每个元素可以使用从0到4的索引进行访问。
该约束使用foreach循环遍历所有元素,并将每个元素的值分配给其索引的值。
class ABC;
rand bit[3:0] array [5];
// 此约束将遍历数组中的5个元素中的每个元素,并将每个元素设置为其特定索引的值
constraint c_array { foreach (array[i]) {
array[i] == i;
}
}
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("array = %p", abc.array);
end
endmodule
Simulation Log
ncsim> run
array = '{'h0, 'h1, 'h2, 'h3, 'h4}
ncsim: *W,RNQUIE: Simulation is complete.
此约束将遍历数组中的5个元素中的每个元素,并将每个元素设置为其特定索引的值
动态数组/队列
动态数组和队列在声明时没有大小,因此无法直接使用foreach循环。 因此,数组的大小必须直接分配或作为约束集的一部分进行约束。
Example
class ABC;
rand bit[3:0] darray []; // Dynamic array -> size unknown
rand bit[3:0] queue [$]; // Queue -> size unknown
// Assign size for the queue if not already known
constraint c_qsize { queue.size() == 5; }
// Constrain each element of both the arrays
constraint c_array { foreach (darray[i])
darray[i] == i;
foreach (queue[i])
queue[i] == i + 1;
}
// 可以像对队列一样使用约束来分配数组的大小,但是让我们在调用随机化之前分配大小
function new ();
darray = new[5]; // Assign size of dynamic array
endfunction
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("array = %p
queue = %p", abc.darray, abc.queue);
end
endmodule
Simulation Log
ncsim> run
array = '{'h0, 'h1, 'h2, 'h3, 'h4}
queue = '{'h1, 'h2, 'h3, 'h4, 'h5}
ncsim: *W,RNQUIE: Simulation is complete.
多维数组
SystemVerilog约束功能强大,足以应用于多维数组。在下面的示例中,我们具有带有打包结构的多维静态数组。
在这里,我们尝试将模式0xF0F0F分配给多维数组的每个元素。
class ABC;
rand bit[4:0][3:0] md_array [2][5]; // Multidimansional Arrays
constraint c_md_array {
foreach (md_array[i]) {
foreach (md_array[i][j]) {
foreach (md_array[i][j][k]) {
if (k %2 == 0)
md_array[i][j][k] == 'hF;
else
md_array[i][j][k] == 0;
}
}
}
}
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("md_array = %p", abc.md_array);
end
endmodule
Simulation Log
ncsim> run
md_array = '{'{'hf0f0f, 'hf0f0f, 'hf0f0f, 'hf0f0f, 'hf0f0f}, '{'hf0f0f, 'hf0f0f, 'hf0f0f, 'hf0f0f, 'hf0f0f}}
ncsim: *W,RNQUIE: Simulation is complete.
rand bit[4:0][3:0] md_array [2][5]
rand bit[4:0][3:0] md_array [2][5]
多维动态数组
约束多维动态数组会有些棘手,并非所有模拟器都支持。在下面显示的示例中,2D数组md_array的X或Y元素的大小未知。
class ABC;
rand bit[3:0] md_array [][]; // Multidimansional Arrays with unknown size
constraint c_md_array {
// First assign the size of the first dimension of md_array
md_array.size() == 2;
// Then for each sub-array in the first dimension do the following:
foreach (md_array[i]) {
// Randomize size of the sub-array to a value within the range
md_array[i].size() inside {[1:5]};
// Iterate over the second dimension
foreach (md_array[i][j]) {
// Assign constraints for values to the second dimension
md_array[i][j] inside {[1:10]};
}
}
}
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("md_array = %p", abc.md_array);
end
endmodule
Simulation Log
ncsim> run
md_array = '{'{'h9, 'h6, 'h7, 'h9, 'h1}, '{'h5, 'h9, 'h4, 'h2}}
ncsim: *W,RNQUIE: Simulation is complete.
数组约简迭代约束
这是SystemVerilog中支持的另一个非常有用的结构和技术。数组约简方法可以从未打包的整数值数组中生成单个值。这可以在约束中使用,以允许在随机化期间考虑表达式。例如,考虑N个元素的数组必须是随机的,以便所有元素的和等于某个值。可以将数组约简操作符与with子句一起使用,以便迭代数组的每个元素并将其包含在约束求解器中。
class ABC;
rand bit[3:0] array [5];
// Intrepreted as int'(array[0]) + int'(array[1]) + .. + int'(array[4]) == 20;
constraint c_sum { array.sum() with (int'(item)) == 20; }
endclass
module tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("array = %p", abc.array);
end
endmodule
Simulation Log
ncsim> run
array = '{'h4, 'h2, 'h2, 'h4, 'h8}
ncsim: *W,RNQUIE: Simulation is complete.
参考文献:
【1】https://www.chipverify.com/systemverilog/systemverilog-foreach-constraint
上一篇: oralce执行计划
下一篇: Oracle综合练习