As a first step towards learning VHDL and using FPGAs, I want to implement a simple UART transmitter which only transmits a constant bit-sequence according to the UART protocol with 9600 8N1 configuration.
I'm using a Altera Cyclone II EP2C5T144C8N board which has a 50MHz clock.
The transmitter is supposed to cycle through all the bits in the bitstring repeatedely on every rising clock of the 9600 Hz clock, which is generated by a counter beforehand.
The VHDL code is as follows:
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;
Top level entity
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;
The output on the TX pin is not what I expect. It transmits the 'A', then 3 garbage characters, then 'A' again. I captured the signals with a logic analyzer:
This does not correspond at all to the bit sequence I have programmed above. It seems that it inserts 0 bits after it has cycles through, which throws off the UART decoder? The 9600 clock looks however right.
Question: What is wrong with the code that causes this?