Electrical – VHDL: Receiving Data from Terminal to FPGA using TTL

communicationfpgaterminalttlvhdl

(I posted same question in stackoverflow but didn't get right answer)

I'm newbie in VHDL. So today, after UART Tx, I tried to read Datas that coming from Realterm terminal. I only wrote Rx codes to just see data. I also used 7 segment display and 7 LED to see what data I receieved. When you look testbench results, the problem is when 3 bit register is "110" twice times, program jumps into rx_data_bit without doing rx_start_bit <= '1'


EDIT 1: Codes and testbench results are updated. Now the issue is rx_data_bit never goes '0' so rx_stop_bit never goes '1'


EDIT 2: I think problem is here

             if(rx_data_bit = '1') then
                counter_del_half <= '0';
                if(half_pulse = '1')then
                   rx_reg((rx_counter)) <= in_Data_rx;  
                   if(rx_counter < 8 and baud_pulse = '1')then
                      rx_counter <= rx_counter + 1;
                      if(rx_counter = 8) then
                         rx_data_bit <= '0';
                         rx_stop_bit  <= '1';
                    end if;
                end if;
            end if;
        end if;

EDIT 3: Now, counter counts correctly but I got a question here. Should rx_counter's first bit (1) do last half bit long or 1 bit long? Also, rx_stop_bit must be '1', when rx_counter reaches 9.

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

entity UART_Rx is
port     ( 
            CLK:         in  std_logic;
            nReset:      in  std_logic;
            in_Data_Rx:  in  std_logic;
            Segment7_1:  out std_logic_vector (6 downto 0);
            Segment7_2:  out std_logic_vector (6 downto 0)
            );
end UART_Rx;

architecture Behavioral of UART_Rx is
-- CLOCK AND BUTTON SIGNALS --
constant Baudrate:       integer:= 9600;
constant CLK_Hiz:        integer:= 50000000;
constant CLK_Bit:        integer:= (CLK_Hiz / Baudrate) + 1;
signal counter_baud:     integer range 0 to (CLK_Bit - 1):= 0;
signal counter_half:     integer range 0 to ((CLK_Bit - 1)/2):= 0;
signal counter_del_baud: std_ulogic:= '0';
signal counter_del_half: std_ulogic:= '0';
signal baud_pulse:       std_ulogic:= '0';
signal half_pulse:       std_ulogic:= '0';

-- RX SIGNALS --
signal rx_reg:           std_logic_vector (7 downto 0):= (others => '0');
signal rx_reg_counter:   std_logic_vector (2 downto 0):= (others => '0');
signal rx_counter:       integer range 0 to 9:= 0;
signal rx_first_bit:     std_ulogic:= '1';
signal rx_start_bit:     std_ulogic:= '0';
signal rx_data_bit:      std_ulogic:= '0';
signal rx_stop_bit:      std_ulogic:= '0';
signal rx_data_al:       std_ulogic:= '0';

begin
-- CLOCK PROCESS --
clk_process: process(CLK,nReset)
    begin
        if(nReset = '0') then
            baud_pulse   <= '0';
            counter_baud <=  0;
            half_pulse   <= '0';
            counter_half <=  0;
            elsif(rising_edge(CLK)) then
                if(counter_baud < (CLK_Bit - 1)) then   
                    counter_baud <= counter_baud + 1;
                    baud_pulse   <= '0';        
                else    
                    counter_baud <= 0;
                    baud_pulse   <= '1'; 
                end if;

                if(counter_half < (CLK_Bit - 1)/2) then
                    counter_half <= counter_half + 1;
                    half_pulse <= '0';
                else
                    counter_half <= 0;
                    half_pulse   <= '1';
                end if;

                if(counter_del_baud = '1') then
                    counter_baud <= 0;
                end if;

               if(counter_del_half = '1') then
                    counter_half <= 0;
                end if;
            end if;         
end process;
rx_process: process(CLK, nReset)
    begin   
            if(rising_edge(CLK)) then
                rx_reg_counter <= rx_reg_counter (1 downto 0) & in_Data_Rx;
                if(rx_first_bit = '1' and rx_reg_counter (2 downto 0) = "110") then
                    counter_del_baud <= '1';
                    rx_start_bit     <= '1';
                    rx_first_bit     <= '0';
                end if;

                if(rx_start_bit = '1') then
                    counter_del_baud <= '0';
                    if(baud_pulse = '1') then
                       counter_del_baud <= '1';
                        rx_start_bit  <= '0';
                        rx_data_bit   <= '1';
                        counter_del_half <= '1';
                    end if; 
                end if;

                if(rx_data_bit = '1') then
                    counter_del_half <= '0';
                    counter_del_baud <= '0';
                    if(half_pulse = '1')then
                        rx_data_bit  <= '0';
                        rx_data_al   <= '1';
                        rx_counter   <= 1;
                    end if;
                end if;

                    if(rx_data_al = '1') then
                        rx_reg(rx_counter - 1) <= in_Data_rx;   
                        if(rx_counter > 0 and rx_counter < 9) then
                            if(baud_pulse = '1')then
                                rx_counter <= rx_counter + 1;
                                if(rx_counter = 9) then
                                    rx_data_al  <= '0';
                                    rx_stop_bit <= '1';
                                end if;
                            end if;
                        end if;
                    end if;

                if(rx_stop_bit = '1')then
                    rx_counter  <= 0;
                    if(baud_pulse = '1') then
                        rx_stop_bit    <= '0';
                        rx_reg_counter <= (others => '1');
                        rx_first_bit   <= '1';
                    end if;
                end if; 

case rx_reg(3 downto 0) is  --abcdefg--
when "0000" => segment7_1 <= "0000001";  -- '0'
when "0001" => segment7_1 <= "1001111";  -- '1'
when "0010" => segment7_1 <= "0010010";  -- '2'
when "0011" => segment7_1 <= "0000110";  -- '3'
when "0100" => segment7_1 <= "1001100";  -- '4' 
when "0101" => segment7_1 <= "0100100";  -- '5'
when "0110" => segment7_1 <= "0100000";  -- '6'
when "0111" => segment7_1 <= "0001111";  -- '7'
when "1000" => segment7_1 <= "0000000";  -- '8'
when "1001" => segment7_1 <= "0000100";  -- '9'
when "1010" => segment7_1 <= "0001000";  -- 'A'
when "1011" => segment7_1 <= "1100000";  -- 'B'
when "1100" => segment7_1 <= "0110001";  -- 'C'
when "1101" => segment7_1 <= "1000010";  -- 'D'
when "1110" => segment7_1 <= "0110000";  -- 'E' 
when "1111" => segment7_1 <= "0111000";  -- 'F'
when others => segment7_1 <= "1111111";
end case;

case rx_reg(7 downto 4) is
when "0000" => segment7_2 <= "0000001";  -- '0'
when "0001" => segment7_2 <= "1001111";  -- '1'
when "0010" => segment7_2 <= "0010010";  -- '2'
when "0011" => segment7_2 <= "0000110";  -- '3'
when "0100" => segment7_2 <= "1001100";  -- '4' 
when "0101" => segment7_2 <= "0100100";  -- '5'
when "0110" => segment7_2 <= "0100000";  -- '6'
when "0111" => segment7_2 <= "0001111";  -- '7'
when "1000" => segment7_2 <= "0000000";  -- '8'
when "1001" => segment7_2 <= "0000100";  -- '9'
when "1010" => segment7_2 <= "0001000";  -- 'A'
when "1011" => segment7_2 <= "1100000";  -- 'B'
when "1100" => segment7_2 <= "0110001";  -- 'C'
when "1101" => segment7_2 <= "1000010";  -- 'D'
when "1110" => segment7_2 <= "0110000";  -- 'E' 
when "1111" => segment7_2 <= "0111000";  -- 'F'
when others => segment7_2 <= "1111111";
end case;
rx_reg <= (others => '0');
end if;
end process;
end Behavioral;

Here is the testbench code:

library ieee;
use ieee.std_logic_1164.all;

entity tb_UART_Rx is
end tb_UART_Rx;

architecture tb of tb_UART_Rx is

    component UART_Rx
        port (CLK        : in std_logic;
              nReset     : std_logic:='1';
              in_Data_Rx : std_logic:='1';
              Segment7_1 : out std_logic_vector (6 downto 0):= (others => '0');
              Segment7_2 : out std_logic_vector (6 downto 0):= (others => '0'));
    end component;

    signal CLK           :  std_logic;
    signal nReset        :  std_logic:='1';
    signal in_Data_Rx    :  std_logic:='1';
    signal rx_reg_counter:  std_logic_vector (2 downto 0):= (others => '1');
    signal Segment7_1    :  std_logic_vector (6 downto 0):= (others => '0');
    signal Segment7_2    :  std_logic_vector (6 downto 0):= (others => '0');

    constant TbPeriod : time := 20 ns; 
    signal TbSimEnded : std_logic := '0';

begin

    dut : UART_Rx
    port map (CLK        => CLK,
              nReset     => nReset,
              in_Data_Rx => in_Data_Rx,
              Segment7_1 => Segment7_1,
              Segment7_2 => Segment7_2);

    clk_process: process
     begin

    CLK <= '0';
    wait for TbPeriod/2;
    CLK <= '1';
    wait for TbPeriod/2;
     end process;

    stimuli : process
    begin

        nReset <= '0';
        wait for 100 ns;
        nReset <= '1';
        wait for 100 ns;
          in_Data_Rx <= '1';
          wait for 0.104 ms;
          in_Data_Rx <= '0';
          wait for 0.104 ms;
          in_Data_Rx <= '0';
          wait for 0.104 ms;
          in_Data_Rx <= '1';
          wait for 0.104 ms;
          in_Data_Rx <= '1';
          wait for 0.104 ms;
          in_Data_Rx <= '1';
          wait for 0.104 ms;
          in_Data_Rx <= '0';
          wait for 0.104 ms;
          in_Data_Rx <= '0';
          wait for 0.104 ms;
          in_Data_Rx <= '0';
          wait for 0.104 ms;
          in_Data_Rx <= '0';
          wait for 0.104 ms;
          in_Data_Rx <= '1';



        wait;
    end process;

end tb;


configuration cfg_tb_UART_Rx of tb_UART_Rx is
    for tb
    end for;
end cfg_tb_UART_Rx;

Here is the testbench results:

Testbench Results

Thanks.

Best Answer

From the simulation snapshot it seems you are working with Xilinx FPGA.

Xilinx offers ready VHDL/verilog codes for UART communication called the kcuart. You don't need to write a separate code for it (saves 'lot' of time). Just configure it for your UART specs and enjoy.

Related Topic