Sigo diseñando sencillos circuitos digitales en VHDL. Así que aquí estoy de nuevo con otro code-kata, ahora simulando en el banco de pruebas, el tic tac de un reloj interno que muchos circuitos electrónicos tienen dentro. Es decir, muchas veces tendremos que desencadenar acciones en circuitos al son del tic tac de un reloj o varios. Para simular este tic tac que tendremos que generar estas señales 10101010101.. cambiando de 0 a 1, y de 1 a 0, cada cierto tiempo simulando así una velocidad en Hercios.
Por ejemplo, los microprocesadores tienen internamente una señal de reloj, que actualmente suele variar del orden de los 2000-3000 MHzs. En las placas de desarrollo FPGAs podemos tener un reloj de 50-100 MHzs. Así sucesivamente, mediante señales de reloj, podremos disparar acciones y movimientos de los bits de un lado a otro, de un circuito a otro, de un componente a otro. De esta forma es cómo se orquestan realmente las acciones internas de muchos procesamientos digitales..
Al grano, un contador de 4 bits al son del tic tac del reloj
Más fácil leer el código que explicarlo:
-- Circuito que usa el reloj para incrementar
-- un contador de 4 bits con cada flanco de subida
-- del reloj.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity usingClock is
port (
counter : out std_logic_vector (3 downto 0);
clock : in std_logic
);
end entity;
architecture arch_usingClock of usingClock is
signal auxCounter : std_logic_vector (3 downto 0);
begin
counter <= auxCounter;
main_process : process(clock)
begin
if (rising_edge(clock)) then
if (auxCounter = "UUUU") then
auxCounter <= "0000";
else
auxCounter <= std_logic_vector(unsigned(auxCounter) + 1);
end if;
end if;
end process;
end architecture;
Mira que aquí el circuito queda independiente de la velocidad del reloj. Sea cual sea su velocidad, irá contando subidas del flanco 0 a 1 del reloj que está conectado en la señal de entrada clock.
El banco de pruebas, donde se simula la velocidad del reloj
-- Simulando un reloj de 100 MHzs --
-- 100 MHzs equivale a hacer tic tac en 10 nanosegundos,
-- así haremos 100 000 000 veces tic tac..
library IEEE;
use IEEE.std_logic_1164.all;
entity usingClock_tb is
end entity;
architecture arch_usingClock_tb of usingClock_tb is
component usingClock is
port (
counter : out std_logic_vector (3 downto 0);
clock : in std_logic
);
end component;
signal testClock : std_logic := '0';
signal testCounter : std_logic_vector (3 downto 0);
signal tics : integer := 0;
begin
testing_unit: usingClock port map (
counter => testCounter,
clock => testClock
);
generate_clock : process
begin
-- Imprime mensaje por pantalla..
report "Tic tac..";
-- Cuenta tic cuando el reloj vale '1'.
if (testClock = '1') then
tics <= tics + 1;
end if ;
-- Esto hace el comportamiento simulado de un reloj
-- real. Si está a 0 lo pone a 1, y si está a 1 lo
-- pone a 0.
testClock <= not testClock;
wait for 5 ns; -- Tiempo de espera en un flanco de reloj.
if (tics > 20) then
wait;
end if ;
report "tics " & integer'image(tics);
report "testClock " & std_logic'image(testClock);
end process;
end architecture;
Si todo ha ido bien, al simularlo se tiene que ver una señal como la de la imagen del principio. En la señal counter tenemos que tener que va de 0 a 15 y vuelta a empezar, contando los tictacs. Es decir, en hexadecimal, como tenemos un valor en counter de 4 bits, tenemos 16 posibles valores, que son: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E y F. De aquí que se ven estos valores en la imagen del principio.