jueves

Contador Up-Down BCD

Después de tiempo ocupados por los cursos en la universidad, volvemos con unos sencillos ejercicios de introducción al lenguaje de descripción de hardware más famoso: vhdl.

Saludos

--contador up-down bcd
--con entradas de reset(clr) y enable

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

entity counter is
 port(
  clk: in std_logic;
  clr: in std_logic;
  en: in std_logic;
  q: out std_logic_vector(3 downto 0)
 );
end counter;

architecture behavioral of counter is
 signal qtemp: std_logic_vector(3 downto 0):="0000";
 signal ctrl: std_logic := '0';
begin
 process(clk, clr)
 begin
  if clr='0' then
   qtemp<=(others=>'0');
  elsif rising_edge(clk) then
   if en='1' then
    if ctrl = '0' then --up
     qtemp<=qtemp+1;
     if qtemp=8 then
        ctrl<='1';
     end if;
     else
      qtemp<=qtemp-1;
     if qtemp=1 then
        ctrl<='0';
     end if;
    end if;
   end if;
  end if;

 end process;
   
 q<=qtemp;
end behavioral;

lunes

Curso corto "Diseño Digital basado en FPGA's"

"Curioso Semáforo" en VHDL

Semáforo

-Este semáforo tiene 3 luces, verde, ambar y rojo,
-Esta normalmente en verde
-Para que cambie de color (verde a rojo) es necesario presionar un boton llamado stop, con lo cual el semáforo primero pasa de verde a ambar y permanece en ese estado durante 5 segundos.
-Luego pasa a rojo durante 20 segundos.
-Los últimos 5 segundos son mostrados en un display 7 segmentos
-Para luego regresar al color verde por defecto.

Diseño:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
USE ieee.std_logic_arith.all;

ENTITY semaforo IS
PORT( Clock, Stop: IN std_logic;
Luces: OUT std_logic_vector(2 DOWNTO 0);
Display: OUT std_logic_vector(4 DOWNTO 0));
END semaforo;

ARCHITECTURE description OF semaforo IS
--SIGNAL New_Clock: std_logic:='0';
SIGNAL Cuenta: std_logic_vector(4 DOWNTO 0):=(OTHERS=>'0');
TYPE Estados IS (S0, S1, S2);
SIGNAL Estado_Actual, Estado_Siguiente: Estados;
SIGNAL Cuenta_Display: std_logic_vector(4 DOWNTO 0):=(OTHERS=>'0');
BEGIN
--
----Generacion de clock_1hz
--New_Clock_Process: PROCESS(Clock)
--VARIABLE Contador: Integer:=1;
--BEGIN
--IF RISING_EDGE(Clock) THEN
-- IF (Contador = 25000000) THEN
-- New_Clock <= NOT New_Clock;
-- Contador:=1;
-- ELSE
-- Contador := Contador+1;
-- END IF;
--END IF;
--END PROCESS New_Clock_Process;

--FSM--

Logica_estado_siguiente: PROCESS(Estado_Actual, Stop, Cuenta)
BEGIN
CASE Estado_Actual IS
WHEN S0=>
IF Stop='1' THEN
Estado_Siguiente <= S1;
ELSE
Estado_Siguiente <= S0;
END IF;

WHEN S1=>
IF Cuenta= "00101" THEN
Estado_Siguiente <= S2;
ELSE
Estado_Siguiente <= S1;
END IF;

WHEN S2=>
IF Cuenta = "11001" THEN
Estado_Siguiente <= S0;
ELSE
Estado_Siguiente <= S2;
END IF;

END CASE;
END PROCESS Logica_estado_siguiente;

Cuenta_Process: PROCESS(Clock)
BEGIN
IF RISING_EDGE(Clock) THEN
CASE Estado_Actual IS
WHEN S0 => Cuenta <= (OTHERS=>'0');
WHEN S1 => Cuenta <= Cuenta+1;
WHEN S2 => Cuenta <= Cuenta+1;
END CASE;
END IF;
END PROCESS Cuenta_Process;
--

Memoria_Estado: PROCESS(Clock)
BEGIN
IF RISING_EDGE(Clock) THEN
Estado_Actual <= Estado_Siguiente;
END IF;
END PROCESS Memoria_Estado;

--SALIDA
Luces <="001" WHEN Estado_Actual = S0 ELSE
"010" WHEN Estado_Actual = S1 ELSE
"100"; --WHEN Estado_Actual = S2;

PROCESS(Clock)
BEGIN
IF RISING_EDGE(Clock) THEN
IF Estado_Actual=S2 AND (Cuenta = "10100") THEN
Cuenta_Display<="00101";
ELSIF Estado_Actual=S2 AND (Cuenta> "10100" AND Cuenta <= "11001") THEN
Cuenta_Display<= Cuenta_Display - 1;
END IF;
END IF;
END PROCESS;

Display<=Cuenta_Display;

END description;

--Nota: Se comentó parte del código para la simulación con un Clock definido en el vector de test.
Para la implementación en el FPGA, descomentar el proceso de generación de señal de reloj de 1 Hz, asimismo descomentar la linea en donde se crea la señal New_Clock. Hecho esto, en el resto del código VHDL modificar Clock por New_Clock.
--consultas: solo dejar un comentario :)

domingo

Robot Seguidor de Linea Negra-Pista Basica

Explicacion:

Robot con 2 sensores y 2 motores que solo giran en un sentido( adelantar,parar).
Los 2 sensores se encuentran afuera y entre la linea negra, si los 2 sensores leen blanco, avanzan, si el sensor izquierdo lee negro, el robot gira a la izquierda, y si el sensor derecho lee negro,el robot gira derecha, no existe la opcion negro,negro ya que es imposible que tome esos valores, ya que es una linea basica sin intersecciones.

Codigo en VHDL:

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

entity seguidor is
port(start,clock,sensor_i,sensor_d:in std_logic;
motor_i,motor_d :out std_logic);
end seguidor;

architecture solucion of seguidor is
type estados is (s0,s1,s2,s3);
signal es,ep:estados;
begin
process(clock)
begin
if clock='1' and clock'event then
ep<=es;
end if;
end process;

process(ep)
begin
es<=ep;
case ep is
when s0 => motor_i<='0'; motor_d<='0';
if start='1' then
es<=s1;
else
es<=s0;
end if;
when s1 => motor_i<='1'; motor_d<='1';
if sensor_i='0' and sensor_d='1' then
es<=s2;
elsif sensor_i='1' and sensor_d='0' then
es<=s3;
end if;
when s2 => motor_i<='0'; motor_d<='1';
if sensor_i='0' and sensor_d='1' then
es<=s2;
else
es<=s1;
end if;
when s3 => motor_i<='1'; motor_d<='0';
if sensor_i='1' and sensor_d='0' then
es<=s3;
else
es<=s1;
end if;
end case;
end process;
end solucion;

sábado

Shift Register SISO con Control de Desplazamiento

LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY siso_register IS
GENERIC(x: integer:=8);
PORT( Data_IN: std_logic;
Q: OUT std_logic;
Direction, Clock, Reset, SH: IN std_logic);
END siso_register;

ARCHITECTURE description OF siso_register IS
SIGNAL Q_Temp: std_logic_vector((x-1) DOWNTO 0):=(OTHERS=>'X');
BEGIN

SHIFT_PROCESS: PROCESS(Clock, Reset)
BEGIN
IF (Reset='1') THEN
Q_Temp<=(OTHERS=>'0');
ELSIF RISING_EDGE(Clock) THEN
IF(SH='1' AND Direction='1') THEN
--Desplazamiento Derecha
Q_Temp((x-2) DOWNTO 0)<=Q_Temp((x-1) DOWNTO 1);
Q_Temp(x-1)<=Data_IN;
ELSIF (SH='1' AND Direction='0') THEN
Q_Temp((x-1) DOWNTO 1)<=Q_Temp((x-2) DOWNTO 0);
Q_Temp(0)<=Data_IN;
--Desplazamiento Izquierda
END IF;
END IF;
END PROCESS SHIFT_PROCESS;

WITH Direction SELECT
Q <= Q_Temp(0) WHEN '1',
Q_Temp(x-1) WHEN '0',
'X' when OTHERS;
END description;

Shift Register PISO con Control de Desplazamiento

LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY piso_register IS
GENERIC( x: INTEGER:=8);
PORT( Data_IN: IN std_logic_vector((x-1) DOWNTO 0); --8 Bits
Clock, Reset, Direction, SH_nLD: IN std_logic;
Q: OUT std_logic);
END piso_register;
ARCHITECTURE description OF piso_register IS
SIGNAL Q_Temp: std_logic_vector((x-1) DOWNTO 0):=(OTHERS=>'X'); --Inside Q
BEGIN

SHIFT_PROCESS: PROCESS(Clock, Reset)
BEGIN
IF (Reset='1') THEN
Q_Temp<=(OTHERS=>'0');
ELSIF RISING_EDGE(Clock) THEN
IF(SH_nLD='0') THEN
--CARGA DE DATOS
Q_Temp<=Data_IN;
ELSIF (SH_nLD='1' AND Direction='1') THEN
--DESPLAMIENTO DERECHA
Q_Temp((x-2) DOWNTO 0)<=Q_Temp((x-1) DOWNTO 1);
Q_Temp(x-1)<='0';
ELSIF (SH_nLD='1' AND Direction='0') THEN
--DESPLAZAMIENTO IZQUIERDA
Q_Temp((x-1) DOWNTO 1)<=Q_Temp((x-2) DOWNTO 0);
Q_Temp(0)<='0';
END IF;
END IF;
END PROCESS SHIFT_PROCESS;


WITH Direction SELECT

Q<= Q_Temp(0) WHEN '1',
Q_Temp(x-1) WHEN '0',
'X' WHEN OTHERS;
END description;

viernes

Clock

The statement:
(Clock='1' and Clock'event)

is'nt equal to:
RISING_EDGE(clock)
This last statement is more rigorous,

remember...
std_logic can have nine diferent values,
then you can also use: (Clock='1' and Clock'event) and Clock'last_event='0' in the sequential process.