Прежде всего, если вы хотите сделать ограниченную рандомизацию, вы не можете использовать $urandom(...)
. Вам нужно использовать классы и функцию randomize()
.
Поместите пиксели в класс matrix
:
class matrix;
parameter WIDTH = 10;
parameter HEIGHT = 5;
rand bit pixels[HEIGHT][WIDTH];
// ...
endclass
Я использовал bit
вместо bit [7:0]
, потому что мы хотим рандомизировать, включен ли пиксель или нет. Можно использовать bit [7:0]
, но пиксели в выключенном состоянии маловероятны. Подробнее об этом позже.
Мы моделируем ограничения, утверждающие, что рядом с недопустимым пикселем включены все остальные:
class matrix;
// ...
constraint on_next_to_off {
foreach (pixels[i,j]) {
if (pixels[i][j] == 0) {
pixels[i-1][j-1] != 0;
pixels[i-1][j] != 0;
pixels[i-1][j+1] != 0;
pixels[i][j-1] != 0;
pixels[i][j+1] != 0;
pixels[i+1][j-1] != 0;
pixels[i+1][j] != 0;
pixels[i+1][j+1] != 0;
}
}
}
endclass
Мы можем попытаться запустить это, но это не удастся. Это потому, что мы не занимались крайними случаями. Если пиксель находится на самой верхней строке, то нет никаких пикселей выше для ограничения, поэтому ограничения, которые ссылаются на i-1
, не имеют смысла и должны исключать этот случай. То же самое относится к самой нижней строке и к левому и крайнему правому столбцам. Мы должны добавить охрану для всех этих случаев:
class matrix;
// ...
constraint on_next_to_off {
foreach (pixels[i,j]) {
if (pixels[i][j] == 0) {
if (i > 1) {
if (j > 1)
pixels[i-1][j-1] != 0;
pixels[i-1][j] != 0;
if (j < WIDTH-1)
pixels[i-1][j+1] != 0;
}
if (j > 1)
pixels[i][j-1] != 0;
if (j < WIDTH-1)
pixels[i][j+1] != 0;
if (i < HEIGHT-1) {
if (j > 1)
pixels[i+1][j-1] != 0;
pixels[i+1][j] != 0;
if (j < WIDTH-1)
pixels[i+1][j+1] != 0;
}
}
}
}
endclass
Для отладки мы можем добавить функцию print()
к matrix
:
class matrix;
// ...
function void print();
foreach (pixels[i]) begin
string line;
foreach (pixels[,j])
line = $sformatf("%s %d", line, pixels[i][j]);
$display(line);
end
endfunction
endclass
Мы можем попробовать это с помощью следующего кода:
module test;
initial begin
matrix m = new();
if (!m.randomize())
$fatal(0, "randerr");
m.print();
end
endmodule
Если вы хотите использовать bit [7:0]
вместо bit
, ограничения будут работать. Как я упоминал выше, очень маловероятно, что решатель выберет 0
в качестве значения для пикселя, потому что у него есть 255 других возможностей для выбора. Чтобы сделать это более вероятным, вы можете добавить дополнительное ограничение, в котором говорится, что пиксели либо включены, либо выключены с равной вероятностью:
class matrix;
// ...
constraint on_or_off_equal {
foreach (pixels[i,j]) {
pixels[i][j] == 0 dist {
0 := 1,
1 := 1
};
}
}
endclass