El documento presenta el diseño de un contador universal y su simulación en un Test Bench. Se describe el código VHDL del contador y del Test Bench creado para probar su funcionamiento ascendente, descendente y de pausa mediante diferentes estímulos en las señales de entrada. Finalmente, se muestran las formas de onda obtenidas que evidencian que el contador opera de acuerdo a las condiciones establecidas.
2. Planteamiento del problema
Creacion de un Test Bench para simulación
Se simulara un contador universal, para ello se creara un Test Bench en el cual se
ingresaran los estimulas necesarios para observar que el contador funciones de acuerdo a la
siguiente tabla.
Figura 1.
1
3. DESARROLLO
El programa del contador es el siguiente
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity univ_bin_counter is
GENERIC( N:integer:=8);
PORT( clk, reset: in std_logic;
syn_clr, load, en, up: in std_logic;
d: in std_logic_vector(N-1 downto 0);
max_tick, min_tick: out std_logic;
q: out std_logic_vector(N-1 downto 0)
);
end univ_bin_counter;
architecture Behavioral of univ_bin_counter is
signal r_reg: unsigned(N-1 downto 0);
signal r_next: unsigned(N-1 downto 0);
begin
process(clk,reset)
begin
if(reset = '1') then
r_reg <= (others => '0');
elsif(clk'event and clk = '1') then
r_reg <= r_next;
end if;
end process;
-- Next state logic
r_next <= (others => '0') when syn_clr = '1' else
unsigned(d) when load = '1' else
r_reg + 1 when en='1' and up='1' else
r_reg - 1 when en='1' and up='0' else
r_reg;
-- Output logic
q <= std_logic_vector(r_reg);
max_tick <= '1' when r_reg = (2**N-1) else '0';
min_tick <= '1' when r_reg = 0 else '0';
end Behavioral;
4. El programa desarrollado para la simulación es la mostrada a continuación
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY univ_bin_counter_tb IS
END univ_bin_counter_tb;
ARCHITECTURE behavior OF univ_bin_counter_tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT univ_bin_counter
GENERIC(N:INTEGER:=8);
PORT(
clk : IN std_logic;
reset : IN std_logic;
syn_clr : IN std_logic;
load : IN std_logic;
en : IN std_logic;
up : IN std_logic;
d : IN std_logic_vector(N-1 downto 0);
max_tick : OUT std_logic;
min_tick : OUT std_logic;
q : OUT std_logic_vector(N-1 downto 0)
);
END COMPONENT;
constant three : integer:=3;
--Inputs
signal clk : std_logic := '0';
signal reset : std_logic := '0';
signal syn_clr : std_logic := '0';
signal load : std_logic := '0';
signal en : std_logic := '0';
signal up : std_logic := '0';
signal d : std_logic_vector(three-1 downto 0) := (others => '0');
--Outputs
signal max_tick : std_logic;
signal min_tick : std_logic;
signal q : std_logic_vector(three-1 downto 0);
5. -- Clock period definitions
constant clk_period : time := 20 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: univ_bin_counter
GENERIC MAP(N => three)
PORT MAP (
clk => clk,
reset => reset,
syn_clr => syn_clr,
load => load,
en => en,
up => up,
d => d,
max_tick => max_tick,
min_tick => min_tick,
q => q
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
reset <= '1', '0' after clk_period/2;
-- Stimulus process
stim_proc: process
begin
--***********************************
-- Initial input
--***********************************
syn_clr <= '0';
load <= '0';
en <= '0';
up <= '1'; -- Count up
d <= (others => '0');
wait until falling_edge(clk);
wait until falling_edge(clk);
--***********************************
-- Test load
--***********************************
load <= '1';
d <= "011";
6. wait until falling_edge(clk);
load <= '0';
-- Pause 2 clocks
wait until falling_edge(clk);
wait until falling_edge(clk);
--***********************************
-- Test syn_clear
--***********************************
syn_clr <= '1'; --Clear
wait until falling_edge(clk);
syn_clr <= '0';
--***********************************
-- Test up counter and pause
--***********************************
en <= '1';
up <= '1';
for i in 1 to 10 loop -- count 10 clock
wait until falling_edge(clk);
end loop;
en <= '0';
wait until falling_edge(clk);
en <= '1';
wait until falling_edge(clk);
wait until falling_edge(clk);
--***********************************
-- Test down counter
--***********************************
up <= '0';
for i in 1 to 10 loop --Run 10 clocks
wait until falling_edge(clk);
end loop;
--************************************
-- Other wait conditions
--************************************
--Continue wait conditions q=2
wait until q = "010";
wait until falling_edge(clk);
up <= '1';
-- Continue until min_tick change value
wait on min_tick;
wait until falling_edge(clk);
up <= '0';
wait for 4*clk_period;
en <= '0';
wait for 4*clk_period;
--************************************
-- Terminate simulation
--************************************
8. Asignación de pines en PlanAhead
Aquí no se realiza ninguna asignación de pines porque solo es una simulación.
Evidencia de Funcionamiento
De acuerdo a la tabla, nos dice que si syn_clr = 1 la salida será cero, y esto se puede ver en
la figura 2.
Figura 2.
Ahora, si load = 1, syn_clr = 0 la salida (q) toma el valor de la entrada (d) (Ver figura 3).
Figura 3.
9. Para que sea un contador ascendente, se debe cumplir que en y up estén en alto y que
syn_clr y load este en bajo (Ver figura 4).
Figura 4.
En los dos marcadores se puede apreciar que el contador es ascendente cuando se
cumplen estas condiciones.
Para que sea un contador descendente, se debe cumplir que en estén en alto y que
syn_clr, up y load estén en bajo (Ver figura 5).
Figura 5.
En los dos marcadores se puede apreciar que el contador es descendente cuando se
cumplen estas condiciones.
10. Para que se mantenga (Pause) la salida las condiciones que se deben cumplir son que
syn_clr, load y en estén en bajo, el estado de up no importa (Ver figura 6 y 7).
Figura 6.
Figura 7.