Em projetos digiatis complexos, testes direcionados isoladamente não conseguem cobrir toda a lógica do código. Por isso, adota-se a técnica de teste aleatório com restrições (Constrained Random Test) para gerar automaticamente conjuntos de teste não direcionados.
- Sintaxe de Restrições (Constraints)
2.1 Expressões de Restrição
Apenas variáveis compostas por bits (inteiros, vetores de bits) podem ser randomizadas; strings não são suportadas. A randomização de variáveis envolve três etapas: declaração com rand ou randc, definição de restrições com a palavra-chave constraint e chamada da função randomize(). Diferenças entre rand e randc:
- rand: a cada randomização a variável gera um valor, podendo repetir valores entre execuções consecutivas.
- randc: periodicidaed cíclica; o valor só se repete depois que todos os valores possíveis tiverem sido gerados.
Exemplo de expressão de restrição (verifique sempre o resultado da randomização – uma falha pode gerar valores desconhecidos):
class pacote;
rand logic [3:0] src, dst;
randc logic [9:0] dados;
constraint cons_src {
src > 0;
src < 10;
dst > 0;
}
constraint cons_randc {
dados > 100;
}
endclass
module test_tb;
pacote p;
initial begin
p = new();
assert(p.randomize()); // retorna 1 se ok, 0 se falha
end
endmodule
Operações matemáticas também podem ser usadas:
class pacote;
rand logic [9:0] addr;
rand logic [4:0] odd_dat, even_dat;
constraint cons_addr {
addr % 8 == 0;
}
constraint cons_dat {
odd_dat % 2 == 1;
even_dat % 2 == 0;
}
endclass
2.2 Restrições com Pesos (Weight Constraints)
O operador dist gera valores aleatórios com pesos diferentes. A sintaxe usa := ou :/:
- := – cada valor dentro do intervalo tem o mesmo peso.
- :/ – o peso total é distribuído igualmente entre os valores do intervalo.
A soma dos pesos não precisa ser 100. O operador inside gera valores com pesos iguais. Exemplo:
class pacote;
rand logic [4:0] src, dst;
rand logic [9:0] addr;
constraint cons_src {
src dist {0:=40, [1:3]:=60};
// src=0: 40/220; src=1,2,3: cada um 60/220
}
constraint cons_dst {
dst dist {0:/40, [1:3]:/60};
// dst=0: 40/100; dst=1,2,3: cada um 20/100
}
constraint cons_addr {
addr inside {[$:10],[100:$]}; // $ representa máximo/mínimo
}
endclass
2.3 Restrições Condicionais
Os operadores -> e if-else ativam restrições apenas quando certas condições são verdadeiras:
class pacote;
bit en;
rand logic [1:0] src, dst;
rand logic [1:0] addr;
constraint cons_src_dst {
(src==0) -> dst==0; // se src=0, dst só pode ser 0
}
constraint cons_addr {
if (en != 0) {
src inside {[1:3]}; // en != 0: src entre 1 e 3
dst inside {[1:3]};
}
else {
src == 0;
dst == 0;
}
}
O uso de solve...before guia a distribuição de probabilidade (válido apenas para rand):
class pacote;
rand bit x;
rand logic [1:0] y;
constraint cons_rand {
(x==0) -> y==3;
}
constraint cons_xy {
(x==0) -> y==3;
solve x before y; // x é escolhido primeiro, depois y
}
endclass
Sem solve before: 5 combinações equiprováveis (x=0,y=3; x=1,y=0..3). Com solve before: x tem 50% cada, e dentro de cada x a distribuição de y é uniforme (y=3 quando x=0; y=0..3 com 25% cada quando x=1).
2.4 Restrições Bidirecionais
Múltiplas variáveis podem ser restritas mutuamente:
class pacote;
rand logic [4:0] x, y, z;
constraint cons_xyz {
x < y;
y > 5;
z < x;
x > 1;
}
endclass
2.5 Restrições Embutidas (Inline Constraints)
Usando randomize() with para adicionar restrições temporárias:
class pacote;
rand logic [3:0] addr;
rand logic [9:0] dados;
constraint cons_addr {
addr inside {[0:9], [13:15]};
}
endclass
module test_tb;
pacote p;
initial begin
p = new();
assert(p.randomize() with {addr == 0; dados > 100;});
assert(p.randomize() with {addr > 5; dados > 20;});
end
endmodule
2.6 Restrições com Arrays
Restrições sobre soma, tamanho e valores individuais de arrays:
class pacote;
rand logic [4:0] len[];
constraint cons_len {
len.size() inside {[5:10]};
len.sum < 50;
foreach (len[i]) len[i] inside {[1:4]};
}
endclass
- Utilização das Restrições
3.1 Usando Valores Não Aleatórios (rand_mode)
Após várias randomizações, pode-se fixar um valor usando rand_mode(0):
class pacote;
rand logic [3:0] addr;
rand logic [9:0] dados;
constraint cons_addr {
addr inside {[0:9], [13:15]};
}
endclass
module test_tb;
pacote p;
initial begin
p = new();
assert(p.randomize());
...
p.dados.rand_mode(0);
p.dados = 541;
assert(p.randomize()); // dados fixo em 541, addr aleatório
end
endmodule
3.2 Randomização de Variáveis Específicas
Randomizar apenas algumas variáveis do objeto:
class pacote;
rand logic [3:0] addr;
rand logic [9:0] dados;
constraint cons_addr {
addr inside {[0:9], [13:15]};
}
endclass
module test_tb;
pacote p;
initial begin
p = new();
assert(p.randomize(addr)); // só randomiza addr
assert(p.randomize(dados)); // só randomiza dados
end
endmodule
3.3 Ativar/Desativar Restrições (constraint_mode)
Desligar restrições individuais ou gerais:
class pacote;
rand logic [3:0] addr;
rand logic [9:0] dados;
constraint cons_addr {
addr inside {[0:9], [13:15]};
}
constraint cons_dados {
dados inside {[10:105]};
}
endclass
module test_tb;
pacote p;
initial begin
p = new();
p.constraint_mode(0); // desliga todas
p.cons_addr.constraint_mode(1); // reativa apenas addr
assert(p.randomize());
end
endmodule
3.4 Uso de pre_randomize e post_randomize
Funções void, sem retorno, não podem consumir tempo. A ordem de execução: pre_randomize() → randomize() → post_randomize(). Exemplo:
class pacote;
rand bit [7:0] x, y, z;
bit en = 0;
constraint cons_xyz {
if (en == 0)
z == x + y;
else
z == x;
}
function void pre_randomize();
en = 1;
endfunction
function void post_randomize();
z = y;
endfunction
endclass
module test_tb;
pacote p;
initial begin
p = new();
assert(p.randomize());
end
endmodule
- Funções de Randomização
| Função | Descrição |
|---|---|
$random() |
Distirbuição uniforme, retorna inteiro com sinal de 32 bits |
$urandom() |
Distribuição uniforme, retorna inteiro sem sinal de 32 bits |
$urandom_range() |
Distribuição uniforme em intervalo (obrigatório limite superior, inferior opcional) |
$dist_exponential() |
Decaimento exponencial |
$dist_normal() |
Distribuição normal (gaussiana) |
$dist_poisson() |
Distribuição de Poisson |
$dist_uniform() |
Distribuição uniforme |