Placa de prototipado FPGA Cyclone IV EP4CE6

EP4CE6 Detalle módulos

Existen en el mercado multitud de placas de entrenamiento FPGA. Ya hemos visto algunas en este blog, pero os quiero hablar de una que me ha llamado la atención por su enfoque diferente. Elegir una placa de entrenamiento a veces se complica, ya que no sólo hay que buscar una con la familia de FPGA que nos interesa, también hay que evaluar qué elementos periféricos trae consigo. ¿Necesitamos un display de siete segmentos? ¿botones? ¿salida VGA  o entrada para teclado? La aproximación de Waveshare me ha resultado interesante, ya que lejos de incluir una serie de elementos periféricos a la FPGA, ha optado por un sistema totalmente modular, lo que tiene ciertas ventajas (y desventajas, claro).

Core FPGA y expansión

 

La idea es ofrecer una placa FPGA básica, a la que llaman core, con la FPGA que necesitemos (ya sea de Altera o XILINX). Esta placa core puede acoplarse a una placa de expansión con una buena cantidad de conectores. En la fotografía anterior hay una FPGA de la familia Cyclone IV de Altera (se trata de la placa CoreEP4CE6) junto con la expansión, en este caso la DVK601. Cuidado porque dependiendo del modelo de FPGA hay que elegir una placa de expansión u otra. Por ejemplo si queremos usar la placa FPGA EP4CE10, tendremos que optar por la expansión DVK600.
La ventaja radica en que a esta placa de expansión podemos conectar aquellos módulos que vayamos necesitando (ya sean de los vendidos por Waveshare o de cualquier otro fabricante).

Complementos FPGA

Es esta imagen hay módulos que añaden un display de cuatro dígitos, pulsadores, lectores de memoria flash, una memoria SDRAM y un puerto VGA y PS/2. Hay mucha variedad. Por ejemplo, el display lo adquirí en la propia web del fabricante, pero los pulsadores son de Dealextreme.

Para probarla, he adaptado el código VHDL del reloj digital que ya vimos en un artículo anterior y demás he usado el circuito antirrebote de la semana pasada para añadir la funcionalidad de adelantar el minutero para ajustar la hora pulsando un botón. Así queda la placa de expansión con la FPGA, el display y los pulsadores.

montaje

Tengo que decir que el display se ilumina muy poco. La placa de expansión suministra 3.3V en lugar de 5V, que según las especificaciones del display, es la tensión correcta.  El código VHDL del reloj, tras adaptarlo, es el siguiente.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity digital_clock is
port (
  clk50mhz: 	in STD_LOGIC;
  display: 	out STD_LOGIC_VECTOR(7 downto 0);
  cur_display:	out STD_LOGIC_VECTOR(3 downto 0);
  point: out STD_LOGIC;
  button: in STD_LOGIC
);
end digital_clock;

architecture beh of digital_clock is
  constant max_count: INTEGER := 25000000; -- 50000000/2
  constant max_refresh_count: INTEGER := 100000; -- 50Mzh/100000=500Hz
  signal count: INTEGER range 0 to max_count;
  signal refresh_count: INTEGER range 0 to max_refresh_count;
  signal refresh_state: STD_LOGIC_VECTOR(1 downto 0) := (others => '0');
  signal clk_state: STD_LOGIC := '0';
  signal display_sel: STD_LOGIC_VECTOR(3 downto 0) := (others => '0');
  shared variable hora1, hora2, min1, min2: INTEGER range 0 to 10 := 0;
  shared variable segundos: INTEGER range 0 to 59 := 0;
  constant CNT_SIZE : integer := 19;
 
  function digito(numero:INTEGER) return STD_LOGIC_VECTOR is
	variable salida: STD_LOGIC_VECTOR(7 downto 0);
  begin
	case numero is
		when 0 => salida := "11000000"; -- 0 
		when 1 => salida := "11111001"; -- 1
		when 2 => salida := "10100100"; -- 2
		when 3 => salida := "10110000"; -- 3
		when 4 => salida := "10011001"; -- 4
		when 5 => salida := "10010010"; -- 5
		when 6 => salida := "10000011"; -- 6
		when 7 => salida := "11111000"; -- 7 
		when 8 => salida := "10000000"; -- 8
		when 9 => salida := "10010000"; -- 9
		when others => salida := "11111111";
	end case;
	return(salida);
  end digito;
	
  begin
    cur_display <= display_sel;

    gen_clock: process(clk50mhz, clk_state, count)
    begin
	if clk50mhz'event and clk50mhz='1' then
		-- contador 1HZ
		if count < max_count then 
			count <= count + 1;
		else
			clk_state <= not clk_state;
			count <= 0;
		end if;
		
		-- contador 500Hz (para refresco del display)
		if refresh_count < max_refresh_count then
			refresh_count <= refresh_count + 1;
		else
			refresh_state <= refresh_state + 1;
			refresh_count <= 0; 
                end if; 
         end if; 
      end process; 

      show_display: process(refresh_state) 
      begin -- selección del display 
          case refresh_state is 
              when "00" => display_sel <= "0001"; -- display 0 
              when "01" => display_sel <= "0010"; -- display 1 
              when "10" => display_sel <= "0100"; -- display 2 
              when "11" => display_sel <= "1000"; -- display 3 
              when others => display_sel <= "1111"; 
           end case; 
           -- mostrar hora 
           case display_sel is 
              when "0001" => display <= digito(hora2); -- display 0 
              when "0010" => display <= digito(hora1); -- display 1 
              when "0100" => display <= digito(min2); -- display 2 
              when "1000" => display <= digito(min1); -- display 3 
              when others => display <= "11111111"; 
            end case;
	
	    -- parpadeo del punto
	    point <= clk_state;
	 end process;
	
  persecond: process (clk_state)
  begin
  
  
	if clk_state'event and clk_state='1' then
		
		-- contador de segundos
		if segundos < 59 then
			-- comprobar pulsacion de boton
			if button = '0' then
				segundos := 0;
				min1 := min1 + 1; -- +1 minuto
			else 
				segundos := segundos + 1;
			end if;
		else 
			segundos := 0;
			min1 := min1 + 1; -- +1 minuto
		end if;
		
		-- segundo dígito minutero
		if min1 = 10 then
			min2 := min2 + 1;
			min1 := 0;
		end if;
		
		-- primer dígito hora
		if min2 = 6 then
			hora1 := hora1 + 1;
			min2 := 0;
		end if;
		
		-- segundo dígito hora
		if hora1 = 10 then
			hora2 := hora2 + 1;
			hora1 := 0;
		end if;
			
		if hora2=2 and hora1=4 then
			hora2 := 0;
			hora1 := 0;
		end if;
	end if;
  end process;
end beh;

 

Los cambios más importantes son los siguientes:

Aprovechando que el display tiene dos puntos para separar horas y minutos, se ha añadido una señal llamada point para controlar el parpadeo. Otra diferencia es que ahora, tal y como se ve en el siguiente esquema, la selección del display de siete segmentos se hace a través de un transistor configurado en emisor común, lo que quiere decir que ahora el display se selecciona con una señal a nivel alto (el primer display se selecciona con 0001 en lugar de 1110 como hacíamos en el artículo anterior).

Esquema display

También se ha añadido la circuitería necesaria para adelantar el minutero al pulsar el botón. En cada ciclo de un segundo se comprueba si el botón está pulsado y si es así, se incrementa el tiempo en un minuto.

El pulsador antirrebote no ha cambiado, pero lo vuelvo a recordar aquí de todas formas.

 

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity debouncer is
	port (
		clk	: in std_logic;
		btn_in	: in std_logic;
		btn_out	: out std_logic);
end debouncer;

architecture beh of debouncer is
    constant CNT_SIZE : integer := 19;
    signal btn_prev   : std_logic := '0';
    signal counter    : std_logic_vector(CNT_SIZE downto 0) := (others => '0');

begin
    process(clk)
    begin
	if (clk'event and clk='1') then
		if (btn_prev xor btn_in) = '1' then
			counter <= (others => '0');
			btn_prev <= btn_in;
		elsif (counter(CNT_SIZE) = '0') then
			counter <= counter + 1;
        	else
			btn_out <= btn_prev;
		end if;
	end if;
    end process;
end beh;

 

Llamadme nostálgico, pero cuando hay que acoplar pocos dispositivos, como en este caso, prefiero usar el capturador de esquemáticos en lugar de hacer un mapeo con VHDL. Este es el conexionado del reloj y el circuito antirrebote.

Circuito

Los pines están bien documentados en la wiki del propio fabricante, así que no entraré en detalle. Simplemente os dejo la configuración en pin planner para el conexionado del display y el botón.

pin planner

En este vídeo se puede ver el reloj en funcionamiento.

CompartirShare on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

Sé el primero en comentar en "Placa de prototipado FPGA Cyclone IV EP4CE6"

Deja un comentario.

Tu dirección de correo no será publicada.


*