Como gerar números aleatórios em VHDL
O VHDL tem um gerador pseudo-aleatório embutido, mas ele só pode gerar números de ponto flutuante entre 0 e 1. Felizmente, você pode derivar disso qualquer outro tipo de formato de dados aleatório que precise. Continue lendo este artigo para descobrir como produzir
real
ou integer
valores de qualquer intervalo, bem como aleatório std_logic_vector
sequências e time
valores. O
uniform
procedimento do pacote IEEE MATH_REAL é a base para os algoritmos descritos neste artigo. Observe que uniform
depende de software para gerar números aleatórios. Portanto, nenhum desses algoritmos é sintetizável. Você só pode usá-los em testbenches. procedure UNIFORM(variable SEED1, SEED2 : inout POSITIVE; variable X : out REAL);
A listagem acima mostra o protótipo do
uniform
procedimento. Ele precisa de duas variáveis de semente para funcionar e as modificará toda vez que você chamar o procedimento. A saída, X, é o número aleatório, que sempre tem um valor entre 0 e 1. Assim como outros geradores de números pseudo-aleatórios,
uniform
irá gerar a mesma sequência de números quando chamado com os mesmos valores iniciais. Devido a esse comportamento, você pode executar novamente o testbench e obter o mesmo resultado ao usar os mesmos valores de semente. Consulte o documento Efficient and Portable Combined Random Number Generators de Pierre L'Ecuyer para obter uma descrição detalhada de como esse algoritmo funciona. Você também pode visualizar uma implementação real do algoritmo no simulador VHDL de código aberto GHDL.
O caso de teste
Todos os exemplos neste artigo usam o valor 999 para ambas as sementes. Declaramos as variáveis de semente conforme listado abaixo na região declarativa de um processo. Em seguida, implementamos nossos algoritmos de randomização personalizados como funções impuras dentro do mesmo processo.
variable seed1, seed2 : integer := 999;
Você pode baixar um testbench completo contendo todos os exemplos deste artigo usando o formulário abaixo. O arquivo Zip também contém um projeto ModelSim com um script que compila e executa a simulação para você.
Valor real aleatório
O
uniform
procedimento gera um real
aleatório valor entre 0,0 e 1,0. Os real
type é o formato de ponto flutuante do VHDL. No entanto, é provável que você queira que o número aleatório esteja em um intervalo diferente. impure function rand_real(min_val, max_val : real) return real is variable r : real; begin uniform(seed1, seed2, r); return r * (max_val - min_val) + min_val; end function;
Felizmente, podemos traduzir facilmente a saída de
uniform
multiplicando com uma escala e adicionando um deslocamento a ela. O código acima mostra uma função que retorna um real
aleatório valor dentro de um intervalo mínimo/máximo. Valor inteiro aleatório
Para gerar um
integer
aleatório valor dentro de um intervalo especificado, você deve multiplicar por uma escala e adicionar um deslocamento a ela. Mas há uma armadilha que você deve evitar. Você não pode simplesmente gerar um real
aleatório valor dentro do intervalo e arredonde-o para um integer
. A ilustração acima mostra o problema. No exemplo, pretendemos gerar um
integer
aleatório valor no intervalo -1 a 1. Se basearmos nosso integer
em um real
aleatório que vai precisamente para os pontos finais, os inteiros min e max recebem apenas metade da probabilidade de serem escolhidos. Arredondando para 0 integer
value acontece na metade das vezes, mesmo que haja três opções de números. impure function rand_int(min_val, max_val : integer) return integer is variable r : real; begin uniform(seed1, seed2, r); return integer( round(r * real(max_val - min_val + 1) + real(min_val) - 0.5)); end function;
No código acima, corrigimos o problema de arredondamento do endpoint ajustando o
real
aleatório valor para incluir um adicional de 0,5 acima e abaixo dos pontos de extremidade. Std_logic_vector aleatório
Existem muitas maneiras de preencher um vetor com valores aleatórios, mas esse método funciona com vetores de qualquer comprimento. Estou usando um loop for para percorrer o vetor e selecionar um valor aleatório para cada bit. No código abaixo, o
len
parâmetro determina o comprimento do std_logic_vector
aleatório para retornar. impure function rand_slv(len : integer) return std_logic_vector is variable r : real; variable slv : std_logic_vector(len - 1 downto 0); begin for i in slv'range loop uniform(seed1, seed2, r); slv(i) := '1' when r > 0.5 else '0'; end loop; return slv; end function;
Valor de tempo aleatório
Às vezes você precisa gerar um
time
aleatório valor em seu testbench. Talvez você queira simular uma interface externa que grava rajadas de dados em momentos aleatórios. Seja qual for o motivo, aleatório time
os valores são fáceis de produzir. impure function rand_time(min_val, max_val : time; unit : time := ns) return time is variable r, r_scaled, min_real, max_real : real; begin uniform(seed1, seed2, r); min_real := real(min_val / unit); max_real := real(max_val / unit); r_scaled := r * (max_real - min_real) + min_real; return real(r_scaled) * unit; end function;
Para gerar um
time
aleatório valor em VHDL, você deve primeiro converter os valores mínimo e máximo desejados para real
tipos. Então, depois que a fórmula de randomização fizer sua mágica, você converte o resultado de volta para um VHDL time
modelo. Observe que você deve fornecer a unidade de tempo de simulação que está usando no simulador como argumento para esta função, conforme mostrado no código acima. O pacote aleatório OSVVM
Por fim, como alternativa à criação manual do algoritmo de randomização, você pode usar o pacote Random da biblioteca OSVVM. Possui múltiplas funções sobrecarregadas para gerar valores aleatórios para todos os tipos de VHDL.
Open Source VHDL Verification Methodology (OSVVM) é uma biblioteca VHDL para criar testbenches estruturados. O pacote Random é apenas um dos muitos pacotes úteis nesta biblioteca.
library osvvm; use osvvm.RandomPkg.all;
O código acima mostra como importar o pacote OSVVM. ModelSim inclui a biblioteca pronta para uso, então você não precisa baixá-la para este simulador. Consulte o arquivo RandomPck.vhd do repositório OSVVM GitHub para encontrar uma função de randomização adequada para suas necessidades.
VHDL
- Como criar uma lista de strings em VHDL
- Como parar a simulação em um testbench VHDL
- Como criar um controlador PWM em VHDL
- Como criar uma lista vinculada em VHDL
- Como usar um procedimento em um processo em VHDL
- Como usar uma função impura em VHDL
- Como usar uma função em VHDL
- Como criar uma máquina de estado finito em VHDL
- Como usar um procedimento em VHDL
- Como gerar números aleatórios em Java