Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> VHDL

Como criar um testbench de autoverificação


Um testbench de autoverificação é um programa VHDL que verifica a exatidão do dispositivo em teste (DUT) sem depender de um operador para inspecionar manualmente a saída. O testbench de autoverificação é executado inteiramente por conta própria e imprime uma mensagem “OK” ou “Falha” no final.

Cada módulo VHDL deve ter um testbench de autoverificação associado. É importante poder verificar se todos os módulos têm o comportamento pretendido a qualquer momento. Por exemplo, quando você faz alterações no DUT, em um submódulo ou em um módulo de interface. Todos nós sabemos que as coisas podem quebrar, e sua melhor ferramenta para detectar esses problemas é o testbench de autoverificação.

O dispositivo em teste


Vamos pular direto e criar um exemplo de um testbench de autoverificação. Primeiro, precisamos de algo para testar, um DUT. Para isso criei o módulo no código abaixo. É um conversor de código binário para Gray.
library ieee;
use ieee.std_logic_1164.all;

entity gray_converter is
  port (
    bin : in std_logic_vector;
    gray : out std_logic_vector
  );
end gray_converter; 

architecture rtl of gray_converter is
begin

  process(bin) is
  begin
    gray(gray'high) <= bin(bin'high);

    for i in bin'high - 1 downto bin'low loop
      gray(i) <= bin(i + 1) xor bin(i);
    end loop;

  end process;

end architecture;

O código cinza é um esquema de codificação de número alternativo, diferente da codificação binária regular. A principal propriedade e propósito do código Gray é que apenas um bit muda ao contar entre valores numéricos adjacentes.
Decimal Binário Cinza
0 0000 0000
1 0001 0001
2 0010 0011
3 0011 0010
4 0100 0110
5 0101 0111
6 0110 0101
7 0111 0100
8 1000 1100
9 1001 1101
10 1010 1111
11 1011 1110
12 1100 1010
13 1101 1011
14 1110 1001
15 1111 1000

A tabela acima mostra como o código Gray difere do código binário.

A bancada de teste


Começaremos criando o testbench básico e instanciando o DUT dentro dele. O código abaixo mostra o arquivo testbench com o DUT instanciado e todas as importações necessárias.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

use std.env.finish;

entity gray_converter_tb is
end gray_converter_tb;

architecture sim of gray_converter_tb is

  signal bin : std_logic_vector(3 downto 0) := (others => '0');
  signal gray : std_logic_vector(3 downto 0);

begin

  DUT : entity work.gray_converter(rtl)
  port map (
    bin => bin,
    gray => gray
  );

end architecture;

Observe que estamos importando std.env.finish que requer VHDL-2008. Se você tentar compilar o testbench no ModelSim sem alterar nada, receberá o seguinte erro:
# ** Warning: gray_converter_tb.vhd(6): (vcom-1516)
Package "STD.ENV" does not exist in this language version.

Felizmente, isso pode ser facilmente corrigido definindo a versão VHDL do arquivo testbench como VHDL-2008. Clique com o botão direito do mouse no arquivo .vhd do testbench e selecione Propriedades→VHDL→Usar 1076-2008->OK.

Você não precisa alterar nada para o DUT. É normal usar uma versão superior do VHDL para testbenches do que para os módulos RTL. Você sempre quer poder usar as construções VHDL mais recentes em seu testbench, mas a maioria das ferramentas de síntese não as suporta.

Gerando a entrada


Nossa próxima adição ao testbench será o processo que gera entradas para o DUT. É sempre melhor criar um teste exaustivo, um teste que tente todos os valores de entrada possíveis. Embora, se houver muitas permutações, você pode ficar restrito a fazer apenas casos de canto.

As entradas e saídas do nosso DUT são de alcance não especificado. No entanto, farei um palpite de que testar com comprimentos de vetor de quatro bits é suficiente para revelar qualquer possível problema com este módulo.

O código abaixo contém todo o processo para gerar a sequência de entrada.
PROC_SEQUENCE : process
begin

  -- Test all possible input values
  for i in 0 to 2**bin'length - 1 loop
    bin <= std_logic_vector(to_unsigned(i, bin'length));
    wait for 10 ns;
  end loop;

  -- Finally, test the wrapped value
  bin <= (others => '0');
  wait for 10 ns;

  report "Test: OK";
  finish;

end process;

O primeiro pedaço de código é um loop For que gera a sequência de contagem do valor mais baixo possível ao valor mais alto possível. Entre os valores, esperamos 10 nanossegundos para permitir que o DUT reaja. Embora, qualquer valor de nanossegundo maior que 0 teria funcionado, porque a lógica dentro do DUT é puramente combinacional.

A segunda parte do código é para testar a situação em que o contador de entrada volta a 0, que era o valor de entrada inicial. Depois disso, não há necessidade de mais testes porque o DUT continuará a produzir os mesmos resultados repetidamente.

As duas últimas linhas de código dentro do processo são para finalizar o teste normalmente. O texto “Test:OK” é impresso no console e, em seguida, a simulação é interrompida usando a palavra-chave “finish” do VHDL-2008.

Observe que, se você executar o ModelSim com o botão Executar padrão, o ModelSim irá avisá-lo com a caixa de diálogo sair depois que o testbench for concluído com sucesso. Esse comportamento pode ser alterado ao iniciar o Vsim a partir de um script ou da linha de comando. Adicione a opção “-onfinish stop” ao comando Vsim, conforme descrito na referência de comando ModelSim.

Verificando a saída


Agora estamos fornecendo entradas ao DUT, mas não há nenhuma verificação da saída. O testbench imprimirá “Test:OK”, independentemente de a saída estar correta ou não. Vamos fazer algo sobre isso.

Ao criar um algoritmo de verificação, você deve sempre tentar implementar o teste de forma diferente do DUT. Caso contrário, uma falha fundamental na lógica pode passar despercebida porque está presente no DUT, bem como no algoritmo testbench.

Seguindo este princípio, vamos testar a saída do DUT não verificando se o código Gray está correto, mas sim que apenas um bit muda de um número para o próximo. Afinal, essa é toda a razão para usar o código Gray em primeiro lugar. O código abaixo mostra um processo que realiza esse tipo de verificação.
PROC_CHECKER : process
    variable prev : std_logic_vector(gray'range);
    variable count : integer;
begin
  wait on bin;

  prev := gray;

  -- Wait for all delta cycles to propagate
  wait for 1 ns;
  
  -- Count the number of changed bits
  count := 0;
  for i in gray'range loop
    if gray(i) /= prev(i) then
      count := count + 1;
    end if;
  end loop;

  assert count = 1
    report integer'image(count) & " bits changed, should have been 1"
    severity failure;
  
end process;

O processo é sensível ao bin sinal, a entrada para o DUT. Poderíamos ter usado uma lista de sensibilidade com o mesmo resultado, mas prefiro usar apenas instruções Wait no código testbench. É uma convenção que facilita saber se você está lidando com um testbench ou um módulo RTL apenas observando como o código é escrito.

Na linha de segundos, copiamos a saída anterior do DUT. Lembre-se, este é o primeiro ciclo delta após o bin sinal mudou, e o DUT não pode reagir ainda. Portanto, é seguro copiar a saída do DUT assumindo que este é o valor antigo.

Em seguida, esperamos 1 nanossegundo para permitir que toda a lógica combinacional no DUT seja concluída. Agora, a saída do DUT deve ser estável e podemos examinar seu valor com segurança.

Na próxima parte do código, usamos um loop For para contar o número de bits alterados na saída do DUT.

Finalmente, vem a instrução Assert que verifica se o número de bits alterados é exatamente 1. As instruções Assert funcionam verificando a condição, que neste caso é count = 1 . Se a condição for avaliada como false , uma asserção será gerada e o simulador parará antes que a mensagem “Test:OK” seja impressa.

É aconselhável incluir a declaração de relatório opcional com a declaração de declaração. Este texto será impresso se a asserção falhar. Em nosso exemplo, forneço uma breve explicação do evento que causou a falha do testbench.

Executando o testbench


É hora de executar nosso testbench para verificar se o DUT está funcionando corretamente. Após iniciar a simulação no ModelSim, e pressionar o botão “run -all”, vemos que a mensagem “Test:OK” é impressa no console.
VSIM 1> run -all
# ** Note: Test: OK
#    Time: 170 ns  Iteration: 0  Instance: /gray_converter_tb




Testando o testbench


Eu sempre gosto de criar uma condição de falha no DUT apenas para ver se o testbench funciona. Às vezes, isso ocorre naturalmente devido a erros reais no DUT enquanto você o desenvolve. Mas se isso não acontecer, basta criar um erro brevemente para testar o testbench.

Para conseguir isso, editarei o código do DUT para criar um erro travado em 0 no bit número 3. Após este teste, removerei o erro com o conhecimento de que o testbench é capaz de detectar tais erros. O código abaixo mostra o processo DUT com a linha de código adicional.
process(bin) is
begin
  gray(gray'high) <= bin(bin'high);

  for i in bin'high - 1 downto bin'low loop
    gray(i) <= bin(i + 1) xor bin(i);
  end loop;

  -- Emulate a stuck at zero error
  gray(3) <= '0';

end process;

Quando executamos o testbench agora, podemos ver que o testbench para e o erro é impresso antes que a linha “Test:OK” seja alcançada. A transcrição do console ModelSim é mostrada abaixo.
VSIM 2> run -all
# ** Failure: 0 bits changed, should have been 1
#    Time: 81 ns  Iteration: 0
Process: /gray_converter_tb/PROC_CHECKER File: gray_converter_tb.vhd
# Break in Process PROC_CHECKER at ray_converter_tb.vhd line 61

Primeiros passos com testbenches de autoverificação


Você deve ser capaz de criar um testbench de autoverificação usando o que aprendeu neste artigo. Crie o hábito de sempre criar testbenches de autoverificação para todos os seus módulos VHDL. Vai poupar tempo a longo prazo.

Não há problema em ser criativo ao escrever testbenches. Mais do que ao escrever módulos RTL porque nem todas as construções VHDL podem ser sintetizadas, mas o testbench não precisa ser sintetizado. Espere gastar pelo menos tanto tempo escrevendo testes quanto você gasta escrevendo o DUT.

Se você quer levar a sério os testes, pode estar interessado em meu * próximo curso de VHDL e FPGA. No curso, vou orientá-lo através do processo de design completo, desde a ideia até o protótipo de FPGA de trabalho físico. Vamos criar vários testbenches de autoverificação.

Atualizado em 12 de outubro de 2020: Eu completei o curso. Clique na imagem abaixo para saber mais.

Vou ensinar a você as melhores práticas para criar com sucesso projetos VHDL e FPGA da maneira certa. O conhecimento que adquiri ao longo de muitos anos na academia e depois de trabalhar como engenheiro de hardware na indústria de defesa será repassado a você.

Leia mais sobre o curso Dot Matrix VHDL e FPGA aqui!

Abre:

A ser decidido .

VHDL

  1. Como criar um modelo CloudFormation usando AWS
  2. Como criar um centro de excelência em nuvem?
  3. Como criar uma estratégia de nuvem cuidadosamente projetada
  4. Como criar UX sem Fricção
  5. Como criar uma lista de strings em VHDL
  6. Como criar um testbench orientado por Tcl para um módulo de bloqueio de código VHDL
  7. Como parar a simulação em um testbench VHDL
  8. Como criar uma lista vinculada em VHDL
  9. Como criar cidades inteligentes centradas no ser humano
  10. Como criar uma matriz de objetos em Java