VHDL: UART TX simple no funciona

0

Como primer paso para aprender VHDL y usar FPGA, quiero implementar un transmisor UART simple que solo transmita una secuencia de bits constante según el protocolo UART con configuración 9600 8N1.

Estoy usando una placa Altera Cyclone II EP2C5T144C8N que tiene un reloj de 50MHz.

Se supone que el transmisor realiza un ciclo a través de todos los bits en la cadena de bits repetidamente en cada reloj ascendente del reloj de 9600 Hz, que se genera de antemano por un contador.

El código VHDL es el siguiente:

uart_test.vhdl :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use IEEE.std_logic_unsigned.ALL;

entity UART_TX is
    Port (clk9600: in std_logic;    -- 9600 Hz clock
            TX : out std_logic      -- TX pin
    );
end UART_TX;

architecture Behavioral of UART_TX is
-- dummy data
-- idle (1) for a 3 cycles, start bit (1 to 0 transition), 8 bits of data ('A'), stop bit (=1)
constant bits_to_transmit : std_logic_vector (0 to 12) := "1110100000101";
signal current_bit : std_logic :='1';
signal current_index: integer range 0 to 12 := 0;

begin
    process (clk9600) -- on every clock tick
    begin  
        if rising_edge(clk9600) then
            -- grab the current bit (in first iteration current_index = 0)
            current_bit <= bits_to_transmit(current_index);
            -- increment index by one (automatically overflows back to 0)
            current_index <= current_index + 1;
        end if;
    end process; 
    -- assign TX the current bit
    TX <= current_bit;
end Behavioral;

Entidad de nivel superior blinky.vhdl :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
use IEEE.std_logic_unsigned.ALL;
use WORK.all;

entity blinky is
    Port (clock50: in std_logic;        -- internal 50MHz clock
            TX_out : out std_logic;     -- transmit pin
            clock9600: out std_logic    -- 9600Hz clock out for debug
            );
end blinky;

architecture Behavioral of blinky is

-- counter for frequency dividing 50 MHz to 9600 (Clk period is 50000000 / 9600 / 2 = ~2604)
signal c : integer range 0 to 2604 := 0; 
signal internal_clk9600 : std_logic := '0';

-- component prototypes
component UART_TX is
    Port (clk9600: in std_logic;    -- 9600 Hz clock
            TX : out std_logic      -- TX pin
    );
end component;

begin
    process begin  
      wait until rising_edge(clock50);
      if (c<2604) then
          c <= c+1;
      else
          c <= 0;
          internal_clk9600 <= not internal_clk9600;
      end if; 
   end process; 

    clock9600 <= internal_clk9600;
    my_uart_tx : UART_TX port map (clk9600=>internal_clk9600, TX=>TX_out);  
end Behavioral;

La salida en el pin TX no es lo que espero. Transmite 'A', luego 3 caracteres basura, luego 'A' nuevamente. Capturé las señales con un analizador lógico:

Estonocorrespondeenabsolutoalasecuenciadebitsqueheprogramadoanteriormente.Parecequeinserta0bitsdespuésdequetieneciclos,loquearrojaeldecodificadorUART?Sinembargo,elreloj9600parececorrecto.

Pregunta:¿Quéestámalconelcódigoquecausaesto?

Notaalmargen:elvisorRTLmuestrauncircuitoquemeparecebien.

    

1 respuesta

3

No soy un gurú de VHDL, pero creo que tu comentario

  

: incrementa el índice en uno (se desborda automáticamente a 0)

es engañoso, y tienes que restablecer explícitamente el índice después de 12.

    
respondido por el Spehro Pefhany

Lea otras preguntas en las etiquetas