Los circuitos digitales, a no ser que sean asíncronos, van comandados por un reloj cuya frecuencia puede variar según el tipo de sistema digital del que se trate. Desde microprocesador 6502 que funcionaba con un reloj de 1Mhz hasta los actuales, que funcionan en el orden de los gigahercios, no han pasado ni cuatro décadas. En un sistema digital complejo es habitual que necesitemos obtener diferentes frecuencia de reloj para diferentes subsistemas. Un ejemplo muy claro puede ser el de un reloj digital que tiene que contar los segundos, por lo tanto, necesita un reloj de 1Hz (un pulso por segundo).
En este artículo vamos a ver un ejemplo práctico de cómo obtener un reloj de 1Hz a partir de otro de 50Mhz en VHDL, y vamos a probarlo un una FPGA.La técnica usada para dividir la frecuencia de un reloj es usar biestables conectados en cascada. En la siguiente esquema se detalla el funcionamiento.
Cada biestable divide la frecuencia a la mitad, así que la idea es ir acoplando biestables hasta obtener la frecuencia deseada. En la práctica pueden usarse contadores integrados como el 7493. En una FPGA podemos conseguir el mismo efecto usando un contador, aunque la mayoría ya trae circuitos especializados para ello, vamos a ver cómo se hace en VHDL.
Para este ejemplo voy a usar una placa basada en una FPGA Altera EP1C3T144 (de la familia Cyclone I). Esta placa tiene un reloj interno de 50Mhz, así que sin más preámbulo os muestro el código VHDL del divisor de frecuencia.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; entity digital_clock_top is port ( clk50mhz: in STD_LOGIC; clk: out STD_LOGIC ); end digital_clock_top; architecture rtl of digital_clock_top is constant max_count: INTEGER := 50000000; signal count: INTEGER range 0 to max_count; signal clk_state: STD_LOGIC := '0'; begin gen_clock: process(clk50mhz, clk_state, count) begin if clk50mhz'event and clk50mhz='1' then if count < max_count then count <= count+1; else clk_state <= not clk_state; count <= 0; end if; end if; end process; persecond: process (clk_state) begin clk <= clk_state; end process; end rtl;El módulo tiene una entrada, que es el reloj de 50Mhz, y una salida que cambiará de estado una vez por segundo (1Hz).
Un reloj de 50Mhz realiza un ciclo cada 20ns, sin embargo, nosotros necesitamos que los haga cada segundo. Como 50Mhz son 50.000.000Hz, he usado un contador que lleva la cuenta del número de cambios de estado de la entrada de reloj. Cuando este contador llega a 50.000.000, se cambia el estado del reloj de salida (el de 1Hz). En realidad, si analizas el código, estoy usando una señal llamada clk_state para gestionar el estado del reloj de salida. Esto es debido a que en VHDL no es posible leer el estado de una señal de salida y, por lo tanto, la operación clk->not clk es ilegal. Se podría haber usado un buffer, pero me he llevado más de una desagradable sorpresa usándolos en circuitos más complejos, así que personalmente prefiero evitarlos.
También habrás observado que uso un segundo proceso para cambiar el estado del reloj de salida. Lo cierto es que no es necesario y podría haberse puesto la instrucción clk<=clk_state justo después de cerrar el el proceso principal, pero como normalmente querremos hacer algo útil con este reloj (por ejemplo, mostrar la hora en un display), lo he situado en un proceso aparte. Os dejo el código de un techbench por si queréis simularlo.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity test is
end entity test;
architecture testbench of test is
signal clk1 : STD_LOGIC := '0';
signal clk_out : STD_LOGIC;
begin
clk1 <= not clk1 after 20 ns;
conec: entity work.digital_clock_top(rtl) port map (clk1, clk_out);
end architecture testbench;
El resultado de la simulación se puede ver en la imagen de la cabecera del artículo.Ahora vamos a probarlo en la FPGA. En la placa que estoy usando, la entrada de reloj se encuentra en el pin 92 de la FPGA, así que es ahí donde asignaremos la señal clk50mzh del código VHDL. La salida clk vamos a asignarla al pin 57, que está conectado a un led.
Os dejo un vídeo con el resultado final en el que se observa como parpadea el led con una cadencia de 1 segundo.



Comentarios
Publicar un comentario