Ir al contenido principal

Divisor de frecuencia para reloj de 1Hz en VHDL

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).

Modelsim
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.

Divisor de frecuencia

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.

Asignación de pines

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

Entradas populares de este blog

Creando firmas de virus para ClamAV

ClamAv es un antivirus opensource y multiplataforma creado por Tomasz Kojm muy utilizado en los servidores de correo Linux. Este antivirus es desarrollado por la comunidad, y su utilidad práctica depende de que su base de datos de firmas sea lo suficientemente grande y actualizado. Para ello es necesario que voluntarios contribuyan activamente aportando firmas. El presente artículo pretende describir de manera sencilla cómo crear firmas de virus para ClamAV y contribuir con ellas a la comunidad.

Ingeniería inversa de un parche de Microsoft Windows

A estas alturas ya hemos asumido que la seguridad total en Internet es, cuanto menos, un mito. Ningún software está libre de vulnerabilidades, y por mucha auditoría, test de intrusión o pruebas de fuzzing que nos empeñemos en hacer, ninguna metodología puede demostrar sin lugar a dudas que un software es 100% seguro. Ante este panorama, hay dos tendencias mayoritarias a la hora de hacer públicas las vulnerabilidades. Por un lado, están los que piensan que cuando se descubre un fallo ha de hacerse público de forma inmediata. En este escenario, la publicación de una vulnerabilidad es el pistoletazo de salida para una carrera entre el desarrollador para sacar el parche y los "malos" para lograr explotarla. Esta política es conocida como full disclosure . Por otro lado, tenemos a los siguen una política responsible disclosure , que abogan por mantener la vulnerabilidad en secreto hasta la salida del parche por parte del desarrollador. Sin entrar en cuestiones filosóficas que no...

Manejo de grafos con NetworkX en Python

El aprendizaje computacional es un área de investigación que en los últimos años ha tenido un auge importante, sobre todo gracias al aprendizaje profundo (Deep Learning). Pero no todo son redes neuronales. Paralelamente a estas técnicas, más bien basadas en el aprendizaje de patrones, también hay un auge de otras técnicas, digamos, más basadas en el aprendizaje simbólico. Si echamos la vista algunos años atrás, podemos considerar que quizá, la promesa de la web semántica como gran base de conocimiento ha fracasado, pero no es tan así. Ha ido transmutándose y evolucionando hacia bases de conocimiento basadas en ontologías a partir de las cuales es posible obtener nuevo conocimiento. Es lo que llamamos razonamiento automático y empresas como Google ya lo utilizan para ofrecerte información adicional sobre tus búsquedas. Ellos lo llaman Grafos de Conocimiento o Knowledge Graphs . Gracias a estos grafos de conocimiento, Google puede ofrecerte información adicional sobre tu búsqueda, ad...