1. Test Bench en VHDL
1. Creamos el proyecto en Quartus de la siguiente manera
Damos click en New Project Wizard o desde File, como sea.
Aparecerá esta ventana, damos next
2. Cambiamos la dirección a donde deseemos guardar el proyecto
Colocamos la ruta de la carpeta en donde se guardará y le damos un nombre, damos next
4. Dependiendo de la tarjeta con la que se trabaje, se coloca el tipo de tarjeta
En las 2 pestañas, elegimos lo siguiente (ModelSim-Altera, VHDL), damos next
6. Damos en OK
Copiamos un ejemplo de una maquina sincrónica:
library ieee;
use ieee.std_logic_1164.all;
entity ejmss is
port( clk, rstn, w : in std_logic;
z : out std_logic);
end ejmss;
architecture behaviour of ejmss is
type estado is (a,b,c);
signal y: estado := a;
begin
process(clk,rstn)
begin
if rstn = '0' then y <= a;
elsif (clk = '1' and clk'event) then
case y is
when a =>
if w = '0' then y <= a;
7. else y <= b; end if;
when b =>
if w = '0' then y <= a;
else y <= c; end if;
when c =>
if w = '1' then y <= c;
else y <= a; end if;
end case;
end if;
end process;
process(y,w)
begin
z <= '0';
case y is
when b =>
if w = '1' then z <= '1'; end if;
when c => z <= '1';
when others => z <= '0';
end case;
end process;
end behaviour;
8. guardamos con el mismo nombre de la entidad
Le damos prioridad jerárquica al momento de compilar.
9. Listo
Hasta aquí solose ha compiladounamáquinade estadofinito. Ahoracreamosotroarchivotipo
VHDL para hacer el testbench,pararealizarlo,debemosde saberel funcionamientodel código,
sólo se le va a asignar entradas como estímulos.
Se lo creara a partir de un código hecho:
--test bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
-- Declaracion de la entidad de tu testbench. No se declara ningún puerto aquí
ENTITY test_tb IS
END test_tb;
ARCHITECTURE solucion OF test_tb IS
-- colocar al lado de
COMPONENT el nombre de la entidad
COMPONENT mealy_out
--Copia y Pega de los
puertos de entrada y salida de tu módulo.
10. port(A1,A2,clk,resetn :
in std_logic;
W
: out std_logic);
END COMPONENT;
--Declaración e
inicialización de las señales internas de entrada de nuestro bloque test_tb
signal A1
: std_logic := '0';
signal A2
: std_logic := '0';
signal clk
: std_logic := '0';
signal resetn
: std_logic := '0';
signal W
: std_logic := 'Z';
-- Definición del periodo
de reloj
constantclk_period: time
:= 1 ns;
BEGIN
-- Instanciar la unidad
bajo prueba (UUT - Unit Under Test)
-- enla etiquetade uut:
va el nombre de la entidad
-- en port map colocar
las entradas y salidas en orden.
uut: mealy_out PORT
MAP (A1, A2, clk, resetn, W);
-- Definicion del
proceso de la señal de reloj( Clock con duty cycle del 50% es generado aquí.
clk_process :process
11. begin
clk <= '0';
waitfor clk_period/2;--
La señal es '0' por 0.5 ns.
clk <= '1';
waitfor clk_period/2; --
La señal es '1' para los siguientes 0.5 ns.
end process;
-- Stimulus process
stim_proc: process
begin -- colocar los
valores de la entrada en el tiempo
wait for 0.5 ns;
resetn <= '1';
wait for 3 ns;
A1 <= '0'; A2 <= '1'; --
Bucle en a
wait for 3 ns;
A1 <= '1'; A2 <= '0'; --
paso a b
wait for 3 ns;
A1 <= '1'; A2 <= '1';--
bucle en b
wait for 3 ns;
A1 <= '0'; A2 <= '1'; --
paso a c
wait for 3 ns;
A1 <= '0'; A2 <= '1'; --
bucle en c
wait for 3 ns;
A1 <= '1';
-- vuelvo a a
wait for 3 ns;
resetn <= '0';
12. wait;
end process;
END solucion;
Y lo modificamos:
--test bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
-- Declaracion de la entidad de tu testbench. No se declara ningún puerto aquí
ENTITY test_tb IS
END test_tb;
ARCHITECTURE solucion OF test_tb IS
-- colocar al lado de
COMPONENT el nombre de la entidad
COMPONENT ejmss
--Copia y Pega de los
puertos de entrada y salida de tu módulo.
PORT( clk, rstn, w
: in std_logic;
z
: out std_logic);
END COMPONENT;
--Declaración e
inicialización de las señales internas de entrada de nuestro bloque test_tb
signal clk
: std_logic:='0'; -
-se puede colocar las variables con otros nombres
signal rstn
: std_logic:='0'; -
- igual estas variables tienen que ir al portmap
13. signal w
: std_logic := '0';
-- Definición del periodo
de reloj
constantclk_period: time
:= 1 ns;
BEGIN
-- Instanciar la unidad
bajo prueba (UUT - Unit Under Test)
-- enla etiquetade uut:
va el nombre de la entidad
-- en port map colocar
las entradas y salidas en orden.
uut: ejmss PORT MAP
(clk, rstn, w, z);
-- Definicion del
proceso de la señal de reloj( Clock con duty cycle del 50% es generado aquí.
clk_process :process
begin
clk <= '0';
waitfor clk_period/2; --
La señal es '0' por 0.5 ns.
clk <= '1';
waitfor clk_period/2; --
La señal es '1' para los siguientes 0.5 ns.
end process;
-- Stimulus process
stim_proc: process
begin -- colocar los
valores de la entrada en el tiempo
wait for 5 ns; --
esperamos por 5 ns con los valores predeterminados
14. resetn <= '1'; --
desactivamos el reset con 1 en este caso
wait for 3 ns;
w <= '0'; -- Bucle en
estado a
wait for 3 ns;
w <= '1'; -- paso al
estado b
wait for 3 ns;
w <= '0'; -- vuelvo para
el estado a
wait for 3 ns;
w <= '1'; -- paso al
estado b
wait for 3 ns;
w <= '1'; -- paso al
estado c
wait for 3 ns;
w <= '1'; -- Bucle en c
wait for 3 ns;
w <= '0'; -- regreso al
estado a
wait for 3 ns;
resetn <= '0';
wait;
end process;
END solucion;
15. Y compilamos de nuevopara ver que error debemos de corregir en el tb si es que se presenta
uno. Este archivono lo elevamosde nivel jerárquico,solologuardamoscon el nombre puesto
en la entidad.
2. Ahorael paso para hacerla pruebadel códigodel tb,esasegurarciertascosascomo las
rutas del tb y el Modelsim
16. Nos metemos en Tools >> Options…
Nos aseguramos que tenga la drección del ModelSim
17. La ruta de acceso a esta carpeta está en esta dirección (solo la carpeta)
Ahora nos dirigimos a esta parte
21. Ya hecho todo estos pasos, para simular el test bench nos dirigimos a:
Esperamos….
Con laslupasdamos zoom,,dependemásomenos,para verlosciclosde reloj,comopodemos
vertenemosel clockarribarstn que es reset,se mantiene por5 ns enbajo,esdecirreseteado,
la salida generada por las entradas puestas a mano se muestran al último, se lo puede
comprobar viendo el código del programa ejmss.vhd, este reloj no tiene límite de parada, así
que cuando ya haya rebasado el tiempo de simulación de las entradas (haga una estimación
sumando todos los tiempos) debe de dar en Stop para que no consuma recursos la pc.
22. Otra forma de generar el código del test bench es haciendo un waveform
Ya estando acá colocamos lasentradasy salidasyprocedemosadarestímulos,esdecir,valores
a las entradas y salidas
Guardamos con cualquier nombre y damos en Run Functional Simulation.
23. Tenemos simulado lo que se ha realizado
Ahora tenemos que dirigirnos a
Damosclickeneste ynosgeneraelcódigodetestbench,sólohabríaqueverificarloenlacarpeta
del proyecto o la dirección que nos muestra abajo que sería Waveform.vwf.vht
24. Lo abrimos con un editor, en este caso se usará el notepad ++
25.
26.
27. ¡Listo!.... Ahora simulemos:
Hacemos los mismos pasos, creamos un archivo VHDL, copiamos el código generado y
guardamos el archivo con el mismo nombre de la entidad, cambiamosla ruta de dirección en
settings y simulamos, no se requiere compilar de nuevo el archivo ya que este lo genera la
máquina:
Vemosque este tiene unalimitaciónde tiempo,el anteriorse vade largo con el tiempo,a este
no hay que ponerle stop ya que tiene un código en el clock
t_prcs_clk: PROCESS
BEGIN
LOOP
clk <= '0';
WAIT FOR 10000 ps;
clk <= '1';
WAIT FOR 10000 ps;
IF (NOW >= 1000000 ps) THEN WAIT; END IF;
END LOOP;
END PROCESS t_prcs_clk;
Archivo disponible en: https://tinyurl.com/ejemplo-1-vhd-tb
28. PWM
Tenemos el código en VHDL de un PWM.
Test Bench 1
library ieee;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity tb_pwm is
end tb_pwm;
architecture solution of tb_pwm is
component pwm_dc_101
PORT(
clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
entrada: IN STD_LOGIC_VECTOR(6 downto 0);
salida : OUT STD_LOGIC
);
end component;
signal clk : STD_LOGIC := '0';
signal reset : STD_LOGIC := '0';
signal entrada : STD_LOGIC_VECTOR(6 downto 0):= (others => '0');
signal salida : STD_LOGIC := '0';
constant clk_period : time := 100 ns;
begin
utt : pwm_dc_101 port map (clk, reset,entrada, salida );
clk_process : process
begin
clk <= '0';
wait for clk_period/2 ;
clk <='1';
wait for clk_period/2 ;
29. end process;
-- Proceso de estímulos.
stim_proc: process
begin
-- Estado de reset.
reset <= '1';
wait for 100 ns;
reset <= '0';
-- Simulación.
entrada <= "0000000"; -- Porcentaje en 0%.
wait for clk_period* 200; -- Esperamos dos ciclos completos.
entrada <= "0000001"; -- Porcentaje en 1%.
wait for clk_period * 200; -- Esperamos dos ciclos completos.
entrada <= "0011110"; -- Porcentaje en 30%.
wait for clk_period * 200; -- Esperamos dos ciclos completos.
entrada <= "1010000"; -- Porcentaje en 80%.
wait for clk_period * 200; -- Esperamos dos ciclos completos.
entrada <= "1100011"; -- Porcentaje en 99%.
wait for clk_period * 200; -- Esperamos dos ciclos completos.
entrada <= "1100100"; -- Porcentaje en 100%.
wait for clk_period * 200; -- Esperamos dos ciclos completos.
entrada <= "1111000"; -- Porcentaje en 120%.
wait for clk_period * 200; -- Esperamos dos ciclos completos.
wait;
end process;
end solution;
Vemosque losvaloresde entradaque se colocó como incremental aumentanel dutycycle del
PWM
30. Test Bench 2
Generamos el tb con estos valores puestos manualmente
-- Copyright (C) 2017 Intel Corporation. All rights reserved.
-- Your use of Intel Corporation's design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Intel Program License
-- Subscription Agreement, the Intel Quartus Prime License Agreement,
-- the Intel MegaCore Function License Agreement, or other
-- applicable license agreement, including, without limitation,
-- that your use is for the sole purpose of programming logic
-- devices manufactured by Intel and sold by Intel or its
-- authorized distributors. Please refer to the applicable
-- agreement for further details.
--
*****************************************************************************
-- This file contains a Vhdl test bench with test vectors .The test vectors
-- are exported from a vector file in the Quartus Waveform Editor and apply to
-- the top level entity of the current Quartus project .The user can use this
-- testbench to simulate his design using a third-party simulation tool .
31. --
*****************************************************************************
-- Generated on "10/03/2017 00:31:06"
-- Vhdl Test Bench(with test vectors) for design : pwm_dc_101
--
-- Simulation tool : 3rd Party
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY pwm_dc_101_vhd_vec_tst IS
END pwm_dc_101_vhd_vec_tst;
ARCHITECTURE pwm_dc_101_arch OF pwm_dc_101_vhd_vec_tst IS
-- constants
-- signals
SIGNAL clk : STD_LOGIC;
SIGNAL entrada : STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL reset : STD_LOGIC;
SIGNAL salida : STD_LOGIC;
COMPONENT pwm_dc_101
PORT (
clk : IN STD_LOGIC;
entrada : IN
STD_LOGIC_VECTOR(6 DOWNTO 0);
reset : IN STD_LOGIC;
salida : OUT STD_LOGIC
);
END COMPONENT;
BEGIN
i1 : pwm_dc_101
PORT MAP (
-- list connections between master ports and signals
clk => clk,
entrada => entrada,
reset => reset,
salida => salida
32. );
-- clk
t_prcs_clk: PROCESS
BEGIN
LOOP
clk <= '0';
WAIT FOR 250 ps;
clk <= '1';
WAIT FOR 250 ps;
IF (NOW >= 1000000 ps)
THEN WAIT; END IF;
END LOOP;
END PROCESS t_prcs_clk;
-- reset
t_prcs_reset: PROCESS
BEGIN
reset <= '1';
WAIT FOR 60000 ps;
reset <= '0';
WAIT;
END PROCESS t_prcs_reset;
-- entrada[6]
t_prcs_entrada_6: PROCESS
BEGIN
entrada(6) <= '1';
WAIT FOR 1537 ps;
FOR i IN 1 TO 2
LOOP
entrada(6) <= '0';
WAIT FOR 4000 ps;
entrada(6) <= '1';
WAIT FOR 2666 ps;
END LOOP;
entrada(6) <= '0';
WAIT FOR 4000 ps;
33. entrada(6) <= '1';
WAIT FOR 1131 ps;
entrada(6) <= '0';
WAIT FOR 1361 ps;
entrada(6) <= '1';
WAIT FOR 2250 ps;
entrada(6) <= '0';
WAIT FOR 2750 ps;
entrada(6) <= '1';
WAIT FOR 2250 ps;
entrada(6) <= '0';
WAIT FOR 671389 ps;
entrada(6) <= '1';
WAIT;
END PROCESS t_prcs_entrada_6;
-- entrada[5]
t_prcs_entrada_5: PROCESS
BEGIN
entrada(5) <= '0';
WAIT FOR 440 ps;
entrada(5) <= '1';
WAIT FOR 7200 ps;
entrada(5) <= '0';
WAIT FOR 12948 ps;
entrada(5) <= '1';
WAIT FOR 4600 ps;
entrada(5) <= '0';
WAIT FOR 374812 ps;
entrada(5) <= '1';
WAIT FOR 300000 ps;
entrada(5) <= '0';
WAIT FOR 240000 ps;
entrada(5) <= '1';
WAIT;
END PROCESS t_prcs_entrada_5;
-- entrada[4]
t_prcs_entrada_4: PROCESS
34. BEGIN
entrada(4) <= '0';
WAIT FOR 1019 ps;
entrada(4) <= '1';
WAIT FOR 4900 ps;
entrada(4) <= '0';
WAIT FOR 5100 ps;
entrada(4) <= '1';
WAIT FOR 4900 ps;
entrada(4) <= '0';
WAIT FOR 4081 ps;
entrada(4) <= '1';
WAIT FOR 630 ps;
entrada(4) <= '0';
WAIT FOR 3500 ps;
entrada(4) <= '1';
WAIT FOR 1500 ps;
entrada(4) <= '0';
WAIT FOR 3500 ps;
entrada(4) <= '1';
WAIT FOR 870 ps;
entrada(4) <= '0';
WAIT FOR 240000 ps;
entrada(4) <= '1';
WAIT FOR 130000 ps;
entrada(4) <= '0';
WAIT FOR 230000 ps;
entrada(4) <= '1';
WAIT FOR 70000 ps;
entrada(4) <= '0';
WAIT FOR 90000 ps;
entrada(4) <= '1';
WAIT;
END PROCESS t_prcs_entrada_4;
-- entrada[3]
t_prcs_entrada_3: PROCESS
BEGIN
35. entrada(3) <= '0';
WAIT FOR 6254 ps;
entrada(3) <= '1';
WAIT FOR 3600 ps;
entrada(3) <= '0';
WAIT FOR 6400 ps;
entrada(3) <= '1';
WAIT FOR 1619 ps;
entrada(3) <= '0';
WAIT FOR 996 ps;
entrada(3) <= '1';
WAIT FOR 985 ps;
entrada(3) <= '0';
WAIT FOR 3473 ps;
entrada(3) <= '1';
WAIT FOR 3900 ps;
entrada(3) <= '0';
WAIT FOR 202773 ps;
entrada(3) <= '1';
WAIT FOR 40000 ps;
entrada(3) <= '0';
WAIT FOR 60000 ps;
entrada(3) <= '1';
WAIT FOR 70000 ps;
entrada(3) <= '0';
WAIT FOR 150000 ps;
entrada(3) <= '1';
WAIT FOR 150000 ps;
entrada(3) <= '0';
WAIT FOR 160000 ps;
entrada(3) <= '1';
WAIT;
END PROCESS t_prcs_entrada_3;
-- entrada[2]
t_prcs_entrada_2: PROCESS
BEGIN
entrada(2) <= '1';
36. WAIT FOR 808 ps;
FOR i IN 1 TO 2
LOOP
entrada(2) <= '0';
WAIT FOR 3733 ps;
entrada(2) <= '1';
WAIT FOR 2933 ps;
END LOOP;
entrada(2) <= '0';
WAIT FOR 4729 ps;
entrada(2) <= '1';
WAIT FOR 2019 ps;
entrada(2) <= '0';
WAIT FOR 2300 ps;
entrada(2) <= '1';
WAIT FOR 1033 ps;
entrada(2) <= '0';
WAIT FOR 2300 ps;
entrada(2) <= '1';
WAIT FOR 1033 ps;
entrada(2) <= '0';
WAIT FOR 2300 ps;
entrada(2) <= '1';
WAIT FOR 146 ps;
entrada(2) <= '0';
WAIT FOR 90000 ps;
entrada(2) <= '1';
WAIT FOR 110000 ps;
entrada(2) <= '0';
WAIT FOR 100000 ps;
entrada(2) <= '1';
WAIT FOR 70000 ps;
entrada(2) <= '0';
WAIT FOR 230000 ps;
entrada(2) <= '1';
WAIT FOR 70000 ps;
entrada(2) <= '0';
37. WAIT FOR 160000 ps;
entrada(2) <= '1';
WAIT;
END PROCESS t_prcs_entrada_2;
-- entrada[1]
t_prcs_entrada_1: PROCESS
BEGIN
entrada(1) <= '0';
WAIT FOR 1620 ps;
entrada(1) <= '1';
WAIT FOR 4800 ps;
entrada(1) <= '0';
WAIT FOR 5200 ps;
entrada(1) <= '1';
WAIT FOR 4800 ps;
entrada(1) <= '0';
WAIT FOR 7705 ps;
entrada(1) <= '1';
WAIT FOR 3400 ps;
entrada(1) <= '0';
WAIT FOR 52475 ps;
entrada(1) <= '1';
WAIT FOR 40000 ps;
entrada(1) <= '0';
WAIT FOR 60000 ps;
entrada(1) <= '1';
WAIT FOR 50000 ps;
entrada(1) <= '0';
WAIT FOR 40000 ps;
entrada(1) <= '1';
WAIT FOR 60000 ps;
entrada(1) <= '0';
WAIT FOR 150000 ps;
entrada(1) <= '1';
WAIT FOR 70000 ps;
entrada(1) <= '0';
WAIT FOR 310000 ps;
38. entrada(1) <= '1';
WAIT;
END PROCESS t_prcs_entrada_1;
-- entrada[0]
t_prcs_entrada_0: PROCESS
BEGIN
entrada(0) <= '0';
WAIT FOR 2725 ps;
entrada(0) <= '1';
WAIT FOR 3400 ps;
entrada(0) <= '0';
WAIT FOR 6600 ps;
entrada(0) <= '1';
WAIT FOR 3400 ps;
entrada(0) <= '0';
WAIT FOR 3875 ps;
entrada(0) <= '1';
WAIT FOR 545 ps;
entrada(0) <= '0';
WAIT FOR 2700 ps;
entrada(0) <= '1';
WAIT FOR 2300 ps;
entrada(0) <= '0';
WAIT FOR 2700 ps;
entrada(0) <= '1';
WAIT FOR 1755 ps;
entrada(0) <= '0';
WAIT FOR 20000 ps;
entrada(0) <= '1';
WAIT FOR 30000 ps;
entrada(0) <= '0';
WAIT FOR 100000 ps;
entrada(0) <= '1';
WAIT FOR 50000 ps;
entrada(0) <= '0';
WAIT FOR 170000 ps;
entrada(0) <= '1';
39. WAIT FOR 80000 ps;
entrada(0) <= '0';
WAIT;
END PROCESS t_prcs_entrada_0;
END pwm_dc_101_arch;
Guardandoeste códigocon el nombre de laentitycomovhdy despuéscambiandoel directorio
de la simulación del tb tenemos
Archivos disponible en: https://tinyurl.com/pwm-tb-prueba