3.7. Unidad aritm´etico l´ ogica (ALU)
3.7.2. Modelado mediante bloque process
El comportamiento de la ALU tambi´en puede ser descrito empleando un bloque process sensible a tres se˜nales: los dos operandos y la se˜nal de selecci´on de la operaci´on.
--- -- ALU
-- architecture: bloque process
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.ALU_CONSTANTS.all;
architecture ALU_bloqueProcess of ALU is begin
begin
case mode is
when "000" => C <= std_logic_vector(signed(A)+signed(A));
when "001" => C <= std_logic_vector(signed(A)+signed(B));
when "010" => C <= std_logic_vector(signed(A)-signed(B));
when "011" => C <= std_logic_vector(-signed(A));
when "100" => C <= A and B;
when "101" => C <= A or B;
when "110" => C <= A xor B;
when others => C <= not A;
end case;
end process;
end architecture ALU_bloqueProcess;
---
3.7.3 Programación del banco de pruebas
Como hemos visto en otros ejemplos, el banco de pruebas est´a t´ıpicamente for- mado por las tres partes siguientes: el dispositivo que va a ser probado (UUT), el c´odigo para la generaci´on de los vectores de test y el c´odigo para comprobar los resultados del test.
A´un en el caso de una ALU sencilla como esta, examinar que la ALU realiza correctamente las operaciones para todos los posibles valores de los operadores consumir´ıa bastante tiempo. En la pr´actica esta t´ecnica ser´ıa inviable, por lo cual debe seleccionarse un conjunto de vectores de test, por ejemplo, atendiendo a los criterios siguientes:
– Se escogen valores de los operandos entorno al cero. Por ejemplo: −2, −1, 0, 1 y 2.
– Se escogen valores de los operandos en el l´ımite inferior de su rango. Si
MIN_NEG_DATA representa el valor m´ınimo que puede tomar el operando, entonces se escogen los valoresMIN_NEG_DATA, . . . ,MIN_NEG_DATA+4 para cada uno de los operandos.
– Se escogen valores de los operandos en el l´ımite superior de su rango. Si
MAX_POS_DATA representa el valor m´aximo que puede tomar el operando, entonces se escogen los valoresMAX_POS_DATA-4, . . . ,MAX_POS_DATApara cada uno de los operandos.
– Finalmente, se escogen algunos valores “al azar”, m´as o menos distribuidos uniformemente en el rango de los operandos.
Se ha definido un package con las constantes globales del banco de pruebas, cuyo valor es calculado a partir de las constantes globales de la ALU.
--- -- Definici´on de constantes globales
-- del banco de pruebas de la ALU
use work.ALU_CONSTANTS.all;
package TB_ALU_CONSTANTS is
constant SEL_MAX : integer := 2**SEL_BITS - 1;
constant MAX_POS_DATA : integer := 2**(WIDTH-1) - 1;
constant MIN_NEG_DATA : integer := -2**(WIDTH-1);
constant DELAY : time := 10 ns;
end package TB_ALU_CONSTANTS;
---
A continuaci´on se muestra el c´odigo del banco de pruebas.
--- -- Banco de pruebas para la ALU
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.ALU_CONSTANTS.all;
use work.TB_ALU_CONSTANTS.all;
entity TB_ALU is
constant PERIOD : time := 100 ns;
end entity TB_ALU;
architecture TB_ALU of TB_ALU is
signal A,B,C : std_logic_vector (WIDTH-1 downto 0);
signal mode : std_logic_vector (SEL_BITS-1 downto 0);
component ALU is
port ( C : out std_logic_vector (WIDTH-1 downto 0); A, B : in std_logic_vector (WIDTH-1 downto 0); mode : in std_logic_vector (SEL_BITS-1 downto 0) );
end component ALU;
-- Procedure que calcula C (expected_C) y lo compara con el -- valor de C que se pasa como argumento (actual_C)
-- Si ambos valores no coinciden, se muestra un mensaje y se -- incrementa el contador de errores (error_count)
procedure check_ALU
( i, j, k : in integer;
actual_C : in std_logic_vector (WIDTH-1 downto 0); error_count : inout integer ) is
variable expected_C : integer;
begin case k is
when 0 => expected_C := i*2;
when 1 => expected_C := i+j;
when 2 => expected_C := i-j;
when 3 => expected_C := -i;
when 4 => expected_C := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED(i,WIDTH)) and std_logic_vector(TO_SIGNED(j,WIDTH)) ));
when 5 => expected_C := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED(i,WIDTH)) or std_logic_vector(TO_SIGNED(j,WIDTH)) ));
when 6 => expected_C := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED(i,WIDTH)) xor std_logic_vector(TO_SIGNED(j,WIDTH)) ));
when others => expected_C := TO_INTEGER(signed(
not std_logic_vector(TO_SIGNED(i,WIDTH)) ));
end case;
expected_C := TO_INTEGER(TO_SIGNED(expected_C,WIDTH));
-- Trunca el resultado a WIDTH bits
assert( expected_C = TO_INTEGER(signed(actual_C)) )
report "ERROR. Ops: " & integer’image(i) & "," & integer’image(j) & ", Operacion: " & integer’image(k) &
", resultado esperado: " &
integer’image(expected_C) & ", resultado actual: " &
integer’image(TO_INTEGER(signed(actual_C))) & "en el instante " &
time’image(now);
if (expected_C /= TO_INTEGER(signed(actual_C))) then
error_count := error_count + 1;
end if;
end procedure check_ALU;
-- Fin de la definici´on del procedure
begin
UUT : component ALU port map (C, A, B, mode);
-- bloque process para generar los vectores de test y -- comprobar el resultado
main : process is
variable error_count : integer := 0;
report "Comienza la simulaci´on";
-- Vectores de test: operandos con valor pr´oximo a cero
for i in -2 to 2 loop for j in -2 to 2 loop
for k in 0 to SEL_MAX loop
A <= std_logic_vector(TO_SIGNED(i,WIDTH)); b <= std_logic_vector(TO_SIGNED(j,WIDTH)); mode <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait for DELAY;
check_ALU(i, j, k, C, error_count);
end loop;
end loop;
end loop;
-- Vectores de test: operandos con valor pr´oximo al m´ınimo
for i in MIN_NEG_DATA to MIN_NEG_DATA+4 loop for j in MIN_NEG_DATA to MIN_NEG_DATA+4 loop
for k in 0 to SEL_MAX loop
A <= std_logic_vector(TO_SIGNED(i,WIDTH)); b <= std_logic_vector(TO_SIGNED(j,WIDTH)); mode <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait for DELAY;
check_ALU(i, j, k, C, error_count);
end loop;
end loop;
end loop;
-- Vectores de test: operandos con valor pr´oximo al m´aximo
for i in MAX_POS_DATA-4 to MAX_POS_DATA loop for j in MAX_POS_DATA-4 to MAX_POS_DATA loop
for k in 0 to SEL_MAX loop
A <= std_logic_vector(TO_SIGNED(i,WIDTH)); b <= std_logic_vector(TO_SIGNED(j,WIDTH)); mode <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait for DELAY;
check_ALU(i, j, k, C, error_count);
end loop;
end loop;
end loop;
-- Vectores de test: operandos con valores al azar
for i in 0 to 9 loop for j in 0 to 9 loop
A <= std_logic_vector(TO_SIGNED(41*i-273,WIDTH)); b <= std_logic_vector(TO_SIGNED(89*j-384,WIDTH)); mode <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait for DELAY;
check_ALU(41*i-273, 89*j-384, k, C, error_count);
end loop;
end loop;
end loop;
wait for DELAY;
-- Informe mostrando el resultado del test
if (error_count=0) then
report "Finaliza la simulaci´on: 0 errores";
else
report "Finaliza la simulaci´on: " & integer’image(error_count) & "errores";
end if;
wait; -- Termina la simulaci´on
end process main;
end architecture TB_ALU;
---