MAQUINA DE ESTADOS MOORE Simulación del proceso de cobro de una maquina dispensadora. Arroyo Martinez Rubén Aarón Hernández Martinez Alejandro Zanella Montiel Marco Samuel Diciembre 2015 ELECTRÓNICA FINAL Proyecto final Máquina de Moore Es un autómata de estados finitos, es decir, una máquina automática programable capaz de realizar determinadas operaciones de manera autónoma, donde las salidas están determinadas por el estado presente únicamente sin depender necesariamente de la entrada. Es indispensable el uso de un diagrama de estados para una mejor visualización y entendimiento del sistema para su realización y/o manipulación. Proyecto final Mediante los conocimientos obtenidos a lo largo del curso de Electrónica Digital implementaremos en una tarjeta FPGA el desarrollo una máquina de estados Moore capaz de simular la operación de cobro de una dispensadora de café con precio de nueve pesos, la cual aceptara monedas de un peso, dos, cinco y diez pesos. Al ingreso de cada moneda, un exhibidor (Display 1) de la tarjeta desplegara la cantidad acumulada hasta la entrega de producto a partir de esto mostrara el cambio, con ayuda de un segundo exhibidor (Display 2) mostraremos la salida del producto representada con la letra “P”. La introducción de las monedas se llevara a cabo con el uso de tres PushButton Switches y un Slide Switch. Diagrama de estados (Especificaciones siguiente hoja) Especificaciones: = 0000 Moneda de “cero pesos”. = 0001 Moneda de un peso. = 0010 Moneda de dos pesos. = 0100 Moneda de cinco pesos. = 1000 Moneda de diez pesos. Las líneas punteadas para mejor visualización del diagrama fueron obviadas tal* y como se indica: = La entrada de 0000 a partir del estado “s9” hasta el estado “s18” provocara ir al estado “s0”. = La entrada de 0001 a partir del estado “s9” hasta el estado “s18” provocara ir al estado “s1”. = La entrada de 0010 a partir del estado “s9” hasta el estado “s18” provocara ir al estado “s2”. = La entrada de 0100 a partir del estado “s9” hasta el estado “s18” provocara ir al estado “s5”. = La entrada de 1000 a partir del estado “s9” hasta el estado “s18” provocara ir al estado “s10”. si c-p si = Estado presente. c = cambio (Ej. $2 0010). p = producto. Diagrama de entidad global Entidades: Divisor de frecuencias. Receptor de pulsos asíncronos. Final (Estados). BCD (Convertidor a siete segmentos). CLK RST CLK CLK_OUT Divisor A X Y CLK RST Pulsos A B X Y CLK RST Pulsos B C D X Y CLK RST Pulsos X Y CLK RST Pulsos X H BCD Display 1 S CLK C RST F X H BCD D FINAL Display 2 Código: Divisor de frecuencias library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity divisor is port ( clk : in STD_LOGIC; rst : in STD_LOGIC; clk_out: out STD_LOGIC); end divisor; architecture Behavioral of divisor is signal temporal: std_logic := '0'; signal counter : integer range 0 to 14999999:= 0; begin frequency_divider: process (rst, clk) begin if (rst = '1') then temporal <= '0'; counter <= 0; elsif rising_edge(clk) then if (counter = 14999999) then temporal <= NOT(temporal); counter <= 0; else counter <= counter + 1; end if; end if; end process; clk_out <= temporal; end Behavioral; Código: Receptor de pulsos asíncronos library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity pulsos is port ( x1: in std_logic; clk: in std_logic; rst: in std_logic; y: out std_logic ); end pulsos; architecture Behavioral of pulsos is signal signal signal signal x: std_logic; temporal: std_logic := '0'; pulse1: std_logic := '0'; counter : integer range 0 to 1 := 0; begin x <= not (x1); counter1: process (pulse1, clk, temporal) begin if (x= '1' AND pulse1 = '0' AND temporal = '0') then temporal <= '1'; pulse1 <= '1'; elsif (rising_edge(clk) AND temporal = '1') then if (counter = 1) then temporal <= '0'; counter <= 0; else counter <= counter + 1; pulse1 <= '0'; end if; end if; end process; y <= pulse1; end Behavioral; Código: Final (Estados) library ieee; use ieee.std_logic_1164.all; entity final is port ( clk: in std_logic; rst: in std_logic; a: in std_logic; b: in std_logic; c: in std_logic; d: in std_logic; f: out std_logic_vector (3 downto 0); -- f = display 2 (salida de producto) s: out std_logic_vector (3 downto 0)); -- s = display 1 (0-8 $ cantidad acumulada 9-18 $ cambio ) end final; architecture armpfinal of final is type state_type is (s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13,s14,s15,s16,s17,s18); signal Qp, Qs: state_type; begin comb: process(Qp,a,b,c,d) begin case Qp is when s0 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "0000"; -- Cantidad acumulada f <= "0000"; -- Salida de producto when s1 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s1; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s2; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s3; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s6; else -- $10 pesos Qs <= s11; end if; s <= "0001"; -- Cantidad acumulada f <= "0000"; -- Salida de producto when s2 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s2; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s3; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s4; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s7; else -- $10 pesos Qs <= s12; end if; s <= "0010"; -- Cantidad acumulada f <= "0000"; -- Salida de producto when s3 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s3; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s4; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s5; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s8; else -- $10 pesos Qs <= s13; end if; s <= "0011"; -- Cantidad acumulada f <= "0000"; -- Salida de producto when s4 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s4; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s5; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s6; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s9; else -- $10 pesos Qs <= s14; end if; s <= "0100"; -- Cantidad acumulada f <= "0000"; -- Salida de producto when s5 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s5; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s6; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s7; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s10; else -- $10 pesos Qs <= s15; end if; s <= "0101"; -- Cantidad acumulada f <= "0000"; -- Salida de producto when s6 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s6; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s7; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s8; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s11; else -- $10 pesos Qs <= s16; end if; s <= "0110"; -- Cantidad acumulada f <= "0000"; -- Salida de producto when s7 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s7; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s8; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s9; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s12; else -- $10 pesos Qs <= s17; end if; s <= "0111"; -- Cantidad acumulada f <= "0000"; -- Salida de producto when s8 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s8; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s9; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s10; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s13; else -- $10 pesos Qs <= s18; end if; s <= "1000"; -- Cantidad acumulada f <= "0000"; -- Salida de producto when s9 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "0000"; f <= "1111"; -- Salida de producto when s10 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "0001"; -- Cambio $$$ f <= "1111"; -- Salida de producto when s11 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "0010"; -- Cambio $$$ f <= "1111"; -- Salida de producto when s12 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "0011"; -- Cambio $$$ f <= "1111"; -- Salida de producto when s13 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "0100"; -- Cambio $$$ f <= "1111"; -- Salida de producto when s14 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "0101"; -- Cambio $$$ f <= "1111"; -- Salida de producto when s15 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "0110"; -- Cambio $$$ f <= "1111"; -- Salida de producto when s16 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "0111"; -- Cambio $$$ f <= "1111"; -- Salida de producto when s17 => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "1000"; -- Cambio $$$ f <= "1111"; -- Salida de producto when others => if (a='0') and (b='0') and (c='0') and (d='0')then -- $0 pesos Qs <= s0; elsif (a='0')and (b='0') and (c='0') and (d='1')then -- $1 peso Qs <= s1; elsif (a='0')and (b='0') and (c='1') and (d='0')then -- $2 pesos Qs <= s2; elsif (a='0')and (b='1') and (c='0') and (d='0')then -- $5 pesos Qs <= s5; else -- $10 pesos Qs <= s10; end if; s <= "1001"; -- Cambio $$$ f <= "1111"; -- Salida de producto end case; end process comb; sec: process(rst, clk) begin if (rst = '1') then Qp <= s0; elsif (clk'event and clk='1') then Qp <= Qs; end if; end process sec; end armpfinal; Código: BCD (Convertidor a siete segmentos) library IEEE; use ieee.std_logic_1164.all; entity bcd is port( x : in std_logic_vector(3 downto 0); h : out std_logic_vector(6 downto 0)); end bcd; architecture SIMPLE1 of bcd is signal display0: std_logic_vector (6 downto 0); begin bcd: process(x,display0) begin case x is when "0000" => display0 <= "1111110"; when "0001" => display0 <= "0110000"; when "0010" => display0 <= "1101101"; when "0011" => display0 <= "1111001"; when "0100" => display0 <= "0110011"; when "0101" => display0 <= "1011011"; when "0110" => display0 <= "1011111"; when "0111" => display0 <= "1110000"; when "1000" => display0 <= "1111111"; when "1001" => display0 <= "1110011"; when "1010" => display0 <= "1110111"; when "1011" => display0 <= "0011111"; when "1100" => display0 <= "1001110"; when "1101" => display0 <= "0111101"; when "1110" => display0 <= "1001111"; when "1111" => display0 <= "1100111"; when others => display0 <= "1000111"; end case; h <= not(display0); end process; end SIMPLE1; -- desplegara la "P". Capturas de pantalla de simulación en Active Divisor de frecuencias (Simulación realizada con el valor del programa inicial de counter 0 a 124999). Receptor de pulsos asíncronos (Simulación realizada con el valor del programa inicial de counter 0 a 10). Final (Estados). BCD (Convertidor a siete segmentos). Conclusiones finales Arroyo Martinez Rubén Aarón: Son diversas las experiencias y nuevos conocimientos descubiertos en este trabajo final, aplicamos lo visto durante el curso. Al enfrentarnos con las especificaciones del diseño fue necesario pensar cómo transformarlas en una máquina de estados, haciendo diagramas y tablas ya que estos nos facilitaron la escritura del código. Lo siguiente fue hacer las simulaciones y buscar posibles problemas en la máquina para solucionarlos y poder implementar el programa en la tarjeta FPGA Hernández Martinez Alejandro Este proyecto final me ayudo a reafirmar conocimientos adquiridos durante el curso de electrónica digital, hubo partes de poca dificultad como el desarrollo del diagrama de estados y elaboración del código, otras no tanto como el entendimiento de los códigos anexos que fueron asimilados con mejor claridad en la parte simuladora del software Active, aprendí parte del uso de una tarjeta FPGA, hubo complicaciones, claro, pero fueron resueltas, en conclusión me pareció un buen proyecto que generaliza la materia. Zanella Montiel Marco Samuel El proyecto me pareció muy interesante, ya que aplicamos todos los conocimientos vistos en clase. Mis compañeros y yo aprendimos a programar y a como simular en una tarjeta FPGA, en lo personal la práctica me gustó mucho aunque fue un poco difícil.