Electrical – VHDL Sending Data from FPGA to TTL

fpgaterminalttlvhdl

I asked same question in stackoverflow but didn't get any good answer. I'm newbie in FPGAs and VHDL. This time, I m trying to send Data from FPGA to TTL. I' m using GPIO pins for TX and GND and Data can be changed with switch on FPGA. My issue is whenever i press the button on FPGA, I always see FF on terminal. I couldn't find where the problem is.

Here is TX code:

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

entity UART_Tx is
  port(
    CLK    : in  std_logic;
    Reset  : in  std_logic;
    Button : in  std_logic;
    Data   : in  std_logic_vector(7 downto 0);
    Out_Tx : out std_logic
  );
end entity;

Architecture Behavioral of UART_Tx is

  constant Baudrate   : integer                          := 9600;
  constant CLK_Hiz    : integer                          := 50000000;
  constant CLK_Bit    : integer                          := (CLK_Hiz / Baudrate) + 1;
  signal tx_Data_ind  : integer range 0 to 7;
  signal counter_baud : integer range 0 to (CLK_Bit - 1) := 0;
  signal shift_button : std_logic_vector (3 downto 0)    := (others => '0');
  signal button_out   : std_ulogic                       := '1';
  signal baud_pulse   : std_ulogic                       := '0';
  signal tx_enable    : std_ulogic                       := '0';
  signal tx_Data      : std_logic_vector (7 downto 0)    := (others => '0');
  signal tx_out       : std_ulogic;
  signal tx_ok        : std_ulogic                       := '0';
  signal counter_del  : std_ulogic                       := '0';

begin

  process(CLK, Reset)
  begin
    if (Reset = '0') then
      baud_pulse   <= '0';
      counter_baud <= 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_del = '1') then
        counter_baud <= 0;
      end if;
    end if;
  end process;

  process(CLK, Reset)
  begin
    if (Reset = '0') then
      tx_Data     <= (others => '0');
      tx_data_ind <= 0;
      tx_enable   <= '0';
    elsif (rising_edge(CLK)) then
      tx_out                   <= '1';
      out_tx                   <= tx_out;
      shift_button(3)          <= button;
      shift_button(2 downto 0) <= shift_button(3 downto 1);
      if shift_button(3 downto 0) = "001" then
        button_out <= '0';
      end if;
      if (button_out = '0') then
        counter_del <= '1';
        tx_out    <= '0';
        if (tx_out = '0') then
          tx_enable <= '1';
        end if;
        if (tx_enable = '1') then
          counter_del <= '0';
          tx_Data     <= Data;
          if (baud_pulse = '1') then
            tx_out <= tx_Data(tx_Data_ind);
            if (tx_data_ind < 7) then
              tx_Data_ind <= tx_Data_ind + 1;
            else
              tx_ok <= '1';
            end if;
            if (tx_ok = '1') then
              tx_Data     <= (others => '0');
              tx_Data_ind <= 0;
              tx_enable   <= '0';
              button_out  <= '1';
              tx_out      <= '1';
            end if;
          end if;
        end if;
      end if;
    end if;
  end process;
end Architecture;

Here is Testbench code:

library ieee;
use ieee.std_logic_1164.all;

entity tb_UART_Tx is
end tb_UART_Tx;

architecture tb of tb_UART_Tx is

    component UART_Tx
        port (CLK    : in std_logic;
              Reset  : in std_logic;
              Button : in std_logic;
              Data   : in std_logic_vector (7 downto 0);
              Out_Tx : out std_logic);
    end component;

    signal CLK    : std_logic:='0';
    signal Reset  : std_logic:='1';
    signal Button : std_logic:='1';
    signal Data   : std_logic_vector (7 downto 0);
    signal Out_Tx : std_logic;

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

begin

    dut : UART_Tx
    port map (CLK    => CLK,
              Reset  => Reset,
              Button => Button,
              Data   => Data,
              Out_Tx => Out_Tx);

clk_process: process
begin

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

    stimuli : process
    begin

          Reset <= '0';
          wait for 20 ns;
          Button <= '1';
          Data <= "00110000";

          wait for 30 ns;
          Button <= '0';
          wait for 50 ns;
          Button <= '1';
          wait for 1000 ns;
--        Button <= '0';
--        wait for 30 ns;
--        Button <= '1';

        TbSimEnded <= '1';
        wait;
    end process;

end tb;

configuration cfg_tb_UART_Tx of tb_UART_Tx is
    for tb
    end for;
end cfg_tb_UART_Tx;

Added Testbench results

EDIT: Guys thank you all for your interest. I guess I found the solution. The problem was my button register had no starting point. So when the code starts, register starts with 000 to 100. So I added a register starting point (111) and use baud pulses in right places. Now, code works perfectly.

Here is the working code:

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

entity UART_Tx is
port(
            CLK:        in std_logic;
            nReset:     in std_logic;
            nButton:    in std_logic;
            Data:       in std_logic_vector (7 downto 0);
            Data_Tx:    out std_logic
            );
end UART_Tx;

architecture Behavioral of UART_Tx is


constant Baudrate:   integer:= 9600;
constant CLK_Hiz:    integer:= 50000000;
constant CLK_Bit:    integer:= (CLK_Hiz / Baudrate) + 1;
signal tx_counter:   integer range 1 to 9:= 1;
signal counter_baud: integer range 0 to (CLK_Bit - 1):= 0;
signal shift_nButton:std_logic_vector (3 downto 0):= (others => '1');
signal tx_reg:       std_logic_vector (7 downto 0):= (others => '0');
signal nButton_out:  std_ulogic:= '1';
signal baud_pulse:   std_ulogic;
signal tx_out:       std_ulogic:= '1';
signal counter_del:  std_ulogic;
signal start_bit:    std_ulogic:='0';
signal data_bit:     std_ulogic:='0';
signal stop_bit:     std_ulogic:='0';


begin
process(CLK,nReset)
    begin
        if(nReset = '0') then
            baud_pulse   <= '0';
            counter_baud <= 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_del = '1') then
                    counter_baud <= 0;
                end if; 
            end if;                 
end process;

    process(CLK, nReset)
        begin
        Data_Tx <= tx_out;

        if(nReset = '0') then
            tx_reg    <= (others => '0');
            tx_counter <= 1;
            elsif(rising_edge(CLK)) then
                    shift_nButton(3)          <=  nButton;
                    shift_nButton(2 downto 0) <= shift_nButton(3 downto 1);
                if shift_nButton(2 downto 0)  = "001" then
                    nButton_out <= '0';
                    counter_del <= '1';
                    start_bit   <= '1'; 
                end if;

                if(nButton_out = '1') then
                   tx_out      <= '1';              

                elsif(nButton_out = '0') then
                      counter_del <= '0';
                        if(start_bit = '1') then
                            tx_out      <= '0';   
                            tx_reg      <= Data;
                            if(baud_pulse = '1') then
                               start_bit  <= '0';
                               data_bit   <= '1';
                            end if;
                        end if;

                        if(data_bit = '1')then
                            if(tx_counter > 0 and tx_counter < 10) then
                                tx_out         <= tx_reg((tx_counter)-1);
                                if(baud_pulse = '1') then
                                   tx_counter  <= tx_counter + 1;
                                if(tx_counter = 9)then
                                        data_bit <= '0';
                                        stop_bit <= '1';
                                    end if;
                                end if;     
                            end if;
                        end if;

                        if(stop_bit = '1') then
                            tx_out      <= '1';
                            tx_counter      <= 1;
                            if(baud_pulse = '1') then
                            stop_bit    <= '0';
                            nButton_out <= '1';
                            tx_reg      <= (others => '0');
                            end if;
                        end if;
                end if;     
        end if;
end process;
end Behavioral;

Best Answer

First, drawing a state-flow diagram for your design would help both you and us to solve the problem.

A couple of things jump out at me:

1. Where you write

if shift_button(3 downto 0) = "001" then

should be if shift_button(2 downto 0) = "001" then

2. When you press your button, you are going to be holding it for many clock cycles. Your design shifts a 1 into shift_button at evey clock cycle, per:

elsif (rising_edge(CLK)) then
    tx_out <= '1';
    out_tx <= tx_out;
    shift_button(3) <= button;
...

so your shift_button register will immediately go to all 1s.

Related Topic