Rebotar en el botón DDR de Nexys4

3

Estoy tratando de implementar un transmisor UART simple, donde la tarjeta DDR Nexys4 está enviando caracteres ASCII a mi PC, que puedo ver usando Tera Term. El problema que tengo es que cuando presiono uno de los botones para enviar los datos de UART, sigo obteniendo mucho del mismo carácter a la vez, y el número no es exacto (por ejemplo, si intento enviar 0x66, obtengo el carácter 'f' a veces 102 veces, a veces 97 veces, etc). Pensé que necesitaba rebotar el botón, así que busqué un módulo para él. Pero parece que esto no tiene efecto. Me gustaría recibir ayuda sobre lo que está mal con la forma en que lo he hecho.

Aquí está el código para el UART: (basado en este ejemplo enlace )

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity uart_deb is
    Port ( I_CLK, I_RST, I_TXSIG : in STD_LOGIC;
    I_TXDATA : in STD_LOGIC_VECTOR(7 downto 0);    
    O_TXRDY, O_TX : out STD_LOGIC );
end uart_deb;

architecture STRUCTURE of uart_deb is

component uart_tx 
    Port (
         I_CLK : in STD_LOGIC;
         I_RST : in STD_LOGIC;
         I_TXSIG : in STD_LOGIC;

         I_TXDATA : in STD_LOGIC_VECTOR(7 downto 0);
         O_TXRDY : out STD_LOGIC;
         O_TX : out STD_LOGIC

     );
end component;



component debounce 
  GENERIC(
    counter_size  :  INTEGER := 19); --counter size (19 bits gives 10.5ms with 50MHz clock)
  PORT(
    I_CLK     : IN  STD_LOGIC;  --input clock
    button  : IN  STD_LOGIC;  --input signal to be debounced
    result  : OUT STD_LOGIC); --debounced signal
END component;

signal RES : STD_LOGIC;

begin
    G1: debounce port map (I_CLK, I_TXSIG, RES);
    G2: uart_tx port map (I_CLK, I_RST, RES, I_TXDATA, O_TXRDY, O_TX);
end;

la fuente uart_tx:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity uart_tx is
    Generic ( baud : integer := 9600);
    Port (
         I_CLK : in STD_LOGIC;
         I_RST : in STD_LOGIC;
         I_TXSIG : in STD_LOGIC;

         I_TXDATA : in STD_LOGIC_VECTOR(7 downto 0);
         O_TXRDY : out STD_LOGIC;
         O_TX : out STD_LOGIC

     );
end uart_tx;

architecture Behavioral of uart_tx is
    signal tx_data : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
    signal tx_state : integer := 0;
    signal tx_rdy : STD_LOGIC := '1';
    signal tx : STD_LOGIC := '1';

    constant BIT_PD : integer := integer(50000000 / baud); -- 100MHz clock limit    
    signal tx_clk_counter : integer := BIT_PD;
    signal tx_clk : STD_LOGIC := '0'; 
begin

    clk_gen: process (I_CLK)
    begin
            if rising_edge(I_CLK) then
                if tx_clk_counter = 0 then
                    tx_clk_counter <= BIT_PD;
                    tx_clk <= not tx_clk;
                else
                    tx_clk_counter <= tx_clk_counter - 1;
                end if;
            end if;
    end process;                

    O_TX <= tx;
    O_TXRDY <= tx_rdy;

    tx_proc: process (tx_clk, I_RST, I_TXSIG, tx_state)
    begin
        if rising_edge(tx_clk) then
            if I_RST = '1' then
                tx_state <= 0;
                tx_data <= X"00";
                tx_rdy <= '1';
                tx <= '1';
            else
                if tx_state = 0 and I_TXSIG = '1' then
                    tx_state <= 1;
                    tx_data <= I_TXDATA;
                    tx_rdy <= '0';
                    tx <= '0';
                elsif tx_state < 9 and tx_rdy = '0' then
                    tx <= tx_data(0);
                    tx_data <= '0' & tx_data(7 downto 1);
                    tx_state <= tx_state + 1;
                elsif tx_state = 9 and tx_rdy = '0' then
                    tx <= '1';
                    tx_rdy <= '1';
                    tx_state <= 0;
                end if;
            end if;
        end if;                
    end process;

end Behavioral;

y la fuente de debouncer:

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

ENTITY debounce IS
  GENERIC(
    counter_size  :  INTEGER := 19); --counter size (19 bits gives 10.5ms with 50MHz clock)
  PORT(
    I_CLK     : IN  STD_LOGIC;  --input clock
    button  : IN  STD_LOGIC;  --input signal to be debounced
    result  : OUT STD_LOGIC); --debounced signal
END debounce;

ARCHITECTURE logic OF debounce IS
  SIGNAL flipflops   : STD_LOGIC_VECTOR(1 DOWNTO 0); --input flip flops
  SIGNAL counter_set : STD_LOGIC;                    --sync reset to zero
  SIGNAL counter_out : STD_LOGIC_VECTOR(counter_size DOWNTO 0) := (OTHERS => '0'); --counter output
BEGIN

  counter_set <= flipflops(0) xor flipflops(1);   --determine when to start/reset counter

  PROCESS(I_CLK)
  BEGIN
    IF(I_CLK'EVENT and I_CLK = '1') THEN
      flipflops(0) <= button;
      flipflops(1) <= flipflops(0);
      If(counter_set = '1') THEN                  --reset counter because input is changing
        counter_out <= (OTHERS => '0');
      ELSIF(counter_out(counter_size) = '0') THEN --stable input time is not yet met
        counter_out <= counter_out + 1;
      ELSE                                        --stable input time is met
        result <= flipflops(1);
      END IF;    
    END IF;
  END PROCESS;
END logic;

el archivo de restricciones:

## Clock signal
set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { I_CLK }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
create_clock -add -name sys_clk_pin -period 20.00 -waveform {0 5} [get_ports {I_CLK}];


##Switches

set_property -dict { PACKAGE_PIN J15   IOSTANDARD LVCMOS33 } [get_ports { I_TXDATA[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
set_property -dict { PACKAGE_PIN L16   IOSTANDARD LVCMOS33 } [get_ports { I_TXDATA[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
set_property -dict { PACKAGE_PIN M13   IOSTANDARD LVCMOS33 } [get_ports { I_TXDATA[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
set_property -dict { PACKAGE_PIN R15   IOSTANDARD LVCMOS33 } [get_ports { I_TXDATA[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
set_property -dict { PACKAGE_PIN R17   IOSTANDARD LVCMOS33 } [get_ports { I_TXDATA[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4]
set_property -dict { PACKAGE_PIN T18   IOSTANDARD LVCMOS33 } [get_ports { I_TXDATA[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
set_property -dict { PACKAGE_PIN U18   IOSTANDARD LVCMOS33 } [get_ports { I_TXDATA[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
set_property -dict { PACKAGE_PIN R13   IOSTANDARD LVCMOS33 } [get_ports { I_TXDATA[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7]

## LEDs

set_property -dict { PACKAGE_PIN H17   IOSTANDARD LVCMOS33 } [get_ports { O_TXRDY }]; #IO_L18P_T2_A24_15 Sch=led[0]


##Buttons

set_property -dict { PACKAGE_PIN N17   IOSTANDARD LVCMOS33 } [get_ports { I_RST }]; #IO_L9P_T1_DQS_14 Sch=btnc
set_property -dict { PACKAGE_PIN M18   IOSTANDARD LVCMOS33 } [get_ports { I_TXSIG }]; #IO_L4N_T0_D05_14 Sch=btnu


##USB-RS232 Interface

#set_property -dict { PACKAGE_PIN C4    IOSTANDARD LVCMOS33 } [get_ports { UART_TXD_IN }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in
set_property -dict { PACKAGE_PIN D4    IOSTANDARD LVCMOS33 } [get_ports { O_TX }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out
#set_property -dict { PACKAGE_PIN D3    IOSTANDARD LVCMOS33 } [get_ports { UART_CTS }]; #IO_L12N_T1_MRCC_35 Sch=uart_cts
#set_property -dict { PACKAGE_PIN E5    IOSTANDARD LVCMOS33 } [get_ports { UART_RTS }]; #IO_L5N_T0_AD13N_35 Sch=uart_rts
    
pregunta nnja

2 respuestas

2

No revisé todos los materiales enviados, pero tendría que suponer que no está manejando correctamente la entrada del interruptor. Sí, tiene que rebotar, pero luego debe detectar adecuadamente la transición desde la que desea activar la transmisión UART. Eso podría ser, por supuesto, de la transición de inserción o de la transición de lanzamiento.

Si no detecta correctamente la transición (borde), terminará detectando el interruptor presionado una y otra vez, lo que resultará en muchas transmisiones UART hasta que se suelte el interruptor. Lo más probable es que el número de variable que está viendo esté relacionado con el tiempo que se presionó el botón.

    
respondido por el Michael Karas
1

La velocidad en baudios que ha elegido es de 9600 bps. Lo que significa que su UART tomará alrededor de \ $ 1/9600 \ aproximadamente 0.1 ms \ $ para enviar un bit. Lo que significa enviar un fotograma completo con 8 bits, un bit de inicio y un bit de parada, el UART tomará solo \ $ 1 ms \ $.

Ha introducido algunos TX_DATA y ha presionado el botón para habilitar la transmisión. Entonces, ¿qué pasará si el botón permanece en estado ON por ejemplo, 100 ms? Se enviará el marco de datos 100 veces ¿verdad? Su lógica de rebote no hace nada para ayudar en este caso. Simplemente comprueba si la entrada del interruptor es estable durante al menos 10 ms, y alimenta la misma lógica al pin habilitado TXSIG del UART.

    
respondido por el MITU RAJ

Lea otras preguntas en las etiquetas