uart in vhdl send a string

46 Views Asked by At

I am learning vhdl and fpga, I have a digilent board Nexys 4. I am trying to send via UART a string. I have been sucessful in sending a character every time a button is clicked on the board.

Now I want to send the whole string after every button click, but I don't get any output from the terminal (I use putty). What am I doing wrong?

This is the top module, I believe the problem may be here but I am not 100% sure.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity UART_tx_top is
port(btnC : in std_logic;
      clk : in std_logic;
     RsTx : out std_logic);
end UART_tx_top;

architecture behavioral of UART_tx_top is

signal string_to_send : string := "Hello World!";
constant string_length : integer := 12;
signal tx_index : integer := 0;
type state_type is (TX_WAIT_BTN, TX_SEND_CHAR, TX_SEND_WAIT); 

signal state   : state_type := TX_WAIT_BTN;  
signal uartRdy : std_logic;
signal uartSend: std_logic;
signal uartData: std_logic_vector (7 downto 0);
signal initStr : std_logic_vector (7 downto 0) := x"41";
signal btnCclr : std_logic;
signal btnC_prev : std_logic;
  
component UART_tx_ctrl
generic(baud : integer);
port(send : in std_logic;
      clk : in std_logic;
     data : in std_logic_vector (7 downto 0);
    ready : out std_logic;
  uart_tx : out std_logic);
end component;

component debounce is
port(clk : in std_logic;
     btn : in std_logic;
 btn_clr : out std_logic);
end component;

begin
process(clk)
begin
if rising_edge(clk) then
btnC_prev <= btnCclr;
case state is
when TX_WAIT_BTN => 
    if btnC_prev = '0' and btnCclr = '1' then 
    state <= TX_SEND_CHAR; 
    end if;
when TX_SEND_CHAR =>
    if tx_index < string_length then
    uartData <= std_logic_vector(to_unsigned(character'pos(string_to_send(tx_index + 1)), 8));
    --initStr <= std_logic_vector(unsigned(initStr) + 1);
    tx_index <= tx_index + 1;
    --state <= TX_SEND_WAIT;
    else
       uartData <= (others => '0');
       tx_index <=0;
       state <= TX_WAIT_BTN;
    end if;
when TX_SEND_WAIT =>    
    if uartRdy = '1' then state <= TX_WAIT_BTN; 
    end if;     
end case;
end if;
end process;

uartSend <= '1' when (state = TX_SEND_CHAR) else '0';

SX : UART_tx_ctrl generic map(baud => 19200)
port map(send => uartSend, data => uartData, clk => clk, ready => uartRdy, uart_tx => RsTx);

dbc : debounce port map(clk => clk, btn => btnC, btn_clr => btnCclr);

end behavioral;

1

There are 1 best solutions below

1
Mario On

To me it looks like you are not waiting for every single character to be sent out. You are just updating the uartData on every clock cycle without checking the uartRdy signal.

So I assume the TX_SEND_WAIT state you commented out would be actually what you need. In that state (or create a second one) you just have to check if you're at the end of the string or if there are more characters to send.