5.2. Prueba por comparación con un modelo de referencia

Otra técnica muy usada es la de comparar nuestra implementación contra una implementación de más alto nivel. La implementación de alto nivel se supone que es correcta y se trata de corroborar que nuestra implementación VHDL coincide. A la implementación de referencia se la suele denominar golden model. Esta técnica no es opuesta a la anterior y ambas pueden utilizarse en conjunto. Es de gran utilidad cuando lo que deseamos comprobar es complejo o bien deseamos probar muchos o todos los valores posibles de entrada.

La implementación del modelo de referencia abstracto puede realizarse en forma externa a nuestro banco de pruebas. Esto se puede hacer utilizando una gran cantidad de herramientas, algunos ejemplos comunes son C/C++, SystemC, MATLAB, etc. En este caso necesitaremos tomar los valores externos, esto se explica en la siguiente sección.

5.2.1. Ejemplo asincrónico

La implementación de nuestro conversor de BCD a Aiken es tan simple que es impensable una versión más abstracta. Por otro lado una prueba exhaustiva tampoco requiere de vectores muy grandes. Por lo que no es un caso en el cual se obtenga una ganancia importante. De todas maneras, y con fines ilustrativos, mostraremos como realizar este tipo de prueba usando el Ejemplo 5-1. A los fines de utilizar un algoritmo diferente se optó por implementar una verificación basada en el hecho de que el código Aiken es un código de peso 2-4-2-1. Esto implica que los tres bits menos significativos tienen el mismo peso que en binario, por lo que podemos computarlos de la misma manera que un unsigned. Sólo es necesario tener en cuenta que el peso del bit 3 es 2 en lugar de 8. La implementación propuesta se muestra en el Ejemplo 5-6.

Ejemplo 5-6. Comparación contra un modelo de referencia (t_b2a_3.vhdl)

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity T_B2A_3 is
end entity T_B2A_3;

architecture Simulador of T_B2A_3 is
   -- Declaración del componente a probar
   component BCD2Aiken is
      port(
         A  : in  std_logic_vector(3 downto 0);
         B  : out std_logic_vector(3 downto 0));
   end component BCD2Aiken;
   -- Señales auxiliares
   signal entrada : std_logic_vector(3 downto 0):="0000";
   signal salida  : std_logic_vector(3 downto 0);
begin
   -- Instancia del dispositivo a probar
   DUT : BCD2Aiken
      port map(A => entrada, B => salida);
   -- Proceso secuencial que realiza las pruebas
   pruebas:
   process
      variable valor : integer;
   begin
      report "Probando el conversor de BCD a Aiken" severity note;
      for i in 0 to 9 loop
          entrada <= std_logic_vector(to_unsigned(i,4));
          wait for 1 ns;
          -- Los 3 bits inferiores tienen el mismo peso que el binario (421)
          valor:=to_integer(unsigned(salida(2 downto 0)));
          -- El bit más pesado tiene peso 2 en lugar de 8
          if salida(3)='1' then
             valor:=valor+2;
          else
             assert salida(3)='0' report "Bit 3 no es ni 1 ni 0"
                severity failure;
          end if;
          assert valor=i report "Falla para "&
             integer'image(to_integer(unsigned(entrada)))
             severity failure;
      end loop;
      for i in 10 to 15 loop
          entrada <= std_logic_vector(to_unsigned(i,4));
          wait for 1 ns;
          assert salida="XXXX" report "No es XXXX para "&
             integer'image(to_integer(unsigned(entrada)))
             severity failure;
      end loop;
      report "Prueba exitosa!" severity note;
      wait;
   end process pruebas;
end architecture Simulador; -- Entity: T_B2A_3

5.2.2. Ejemplo sincrónico

Como ejemplo sincrónico mostraremos la validación de una máquina de estados. Tomaremos como ejemplo una máquina de estados mostrada en los apuntes. Se trata de un circuito que sirve para verificar si un dígito BCD es válido. Los datos ingresan en serie por la entrada Y, el bit menos significativo primero. Luego de haber ingresado los cuatro bits la salida Z indica con un 1 si la combinación es incorrecta. La máquina de estados utilizada para solucionar este problema se puede observar en la Figura 5-1. Los valores indicados junto a las transiciones corresponden a Y/Z.

Figura 5-1. Máquina de estados para verificar dígitos BCD

La implementación de dicha máquina de estados se muestra en el Ejemplo 5-7. La misma es equivalente a la entidad ejemplo3 del apunte, sólo posee cambios menores orientados a hacer un poco más simple la lectura del código.

Ejemplo 5-7. Implementación de la máquina de estados (check_bcd.vhdl)

library IEEE;
use IEEE.std_logic_1164.all;

entity check_bcd is
   port(
      Y, clk, MR : in  std_logic;
      Z          : out std_logic);
end entity check_bcd;

architecture d2proc of check_bcd is
   type tipo_estado is (a, b, d, e, h, i);
   signal estado, estaprox : tipo_estado;
begin
   secuencial:
   process (clk, MR)
   begin
      if MR='1' then
         estado <= a;
      elsif rising_edge(clk) then
         estado <= estaprox;
      end if;
   end process secuencial;

   combinacional:
   process (Y, estado)
   begin
      Z <= '0';
      estaprox <= a;
      case estado is
           when a =>
                estaprox <= b;
           when b =>
                if Y='0' then
                   estaprox <= d;
                else
                   estaprox <= e;
                end if;
           when d =>
                if Y='0' then
                   estaprox <= h;
                else
                   estaprox <= i;
                end if;
           when e =>
                estaprox <= i;
           when h =>
                null;
           when i =>
                Z <= Y;
           when others =>
                Z <= 'X';
      end case;
   end process combinacional;
end architecture d2proc; -- Entity: check_bcd

Como modelo de referencia utilizaremos una simple comparación: el dígito es válido si es menor que 10. El test bench propuesto se muestra en el Ejemplo 5-8. Notar que el test bench verifica todas las combinaciones posibles de cuatro bits. Por cada una inyecta en serie el valor por la entrada Y, en el último bit verifica que la salida Z coincida con lo esperado. También se verifica que Z sea 0 el resto del tiempo.

Ejemplo 5-8. Verificación de la máquina de estados (t_check_bcd.vhdl)

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library std;
use std.textio.all;

entity T_Check_BCD is
end entity T_Check_BCD;

architecture Simulador of T_Check_BCD is
   component check_bcd is
      port(
         Y, clk, MR : in  std_logic;
         Z          : out std_logic);
   end component check_bcd;

   constant FREQ_CLK : integer:=50; -- Frecuencia del reloj en MHz
   constant PERI_CLK : time:=1 us/FREQ_CLK;
   signal clk        : std_logic;      -- Reloj
   signal detener    : boolean:=false; -- Termina el test
   signal rst        : std_logic;      -- Pulso de reset
   signal y          : std_logic;      -- Entrada del DUT
   signal z          : std_logic;      -- Salida del DUT
begin
   gen_reloj:
   process
   begin
      clk <= '1', '0' after PERI_CLK/2;
      wait for PERI_CLK;
      if detener then
         wait;
      end if;
   end process gen_reloj;

   rst <= '1', '0' after PERI_CLK*3/2;

   dut : check_bcd
      port map(
         clk => clk, MR => rst, Y => y, Z => z);

   do_test:
   process
      variable l   : line;
      variable bin : unsigned(3 downto 0);
   begin
      write(l,string'("* Probando la máquina de estados"));
      writeline(output,l);
      wait until rst='0';

      -- Barrer todas las combinaciones
      for i in 0 to 15 loop
          bin:=to_unsigned(i,4);
          -- Ingresar los bits
          for j in 0 to 3 loop
              y <= bin(j);   -- Inyectar el bit
              wait until rising_edge(clk); -- Sincronizar
              -- Verificar
              if j=3 then
                 -- En el bit más pesado se indica si es válido o no
                 if i<10 then -- Valores válidos
                    assert z='0' report "Encendido para "&integer'image(i)
                       severity failure;
                 else -- Valores inválidos
                    assert z='1' report "Apagado para "&integer'image(i)
                       severity failure;
                 end if;
              else -- En el resto de los bits debería ser Z='0'
                 assert z='0' report "No es 0 para un bit intermedio: "&
                    integer'image(i)&" bit "&integer'image(j)
                    severity failure;
              end if;
          end loop;
      end loop;

      write(l,string'("* Todo OK!"));
      writeline(output,l);
      detener <= true;
      wait;
   end process do_test;
end architecture Simulador; -- Entity: T_Check_BCD
Copyright © 2011 UTN FRBA - INTI - Ing. Salvador E. Tropea