----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    19:46:54 07/14/2014 
-- Design Name: 
-- Module Name:    Uart_TX_State - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity Uart_TX_State is
  port (
    CLK : in std_logic;
    RESET : in std_logic;
    uartSend : out std_logic;
    uartRdy : in std_logic;
    Rom_addr : out std_logic_vector (5 downto 0)
  );
end Uart_TX_State;

architecture Behavioral of Uart_TX_State is

--The type definition for the UART state machine type. Here is a description of what
--occurs during each state:
-- RST_REG     -- Do Nothing. This state is entered after configuration or a user reset.
--                The state is set to LD_INIT_STR.
-- LD_INIT_STR -- The Welcome String is loaded into the sendStr variable and the strIndex
--                variable is set to zero. The welcome string length is stored in the StrEnd
--                variable. The state is set to SEND_CHAR.
-- SEND_CHAR   -- uartSend is set high for a single clock cycle, signaling the character
--                data at sendStr(strIndex) to be registered by the UART_TX_CTRL at the next
--                cycle. Also, strIndex is incremented (behaves as if it were post 
--                incremented after reading the sendStr data). The state is set to RDY_LOW.
-- RDY_LOW     -- Do nothing. Wait for the READY signal from the UART_TX_CTRL to go low, 
--                indicating a send operation has begun. State is set to WAIT_RDY.
-- WAIT_RDY    -- Do nothing. Wait for the READY signal from the UART_TX_CTRL to go high, 
--                indicating a send operation has finished. If READY is high and strEnd = 
--                StrIndex then state is set to WAIT_BTN, else if READY is high and strEnd /=
--                StrIndex then state is set to SEND_CHAR.
-- WAIT_BTN    -- Do nothing. Wait for a button press on BTNU, BTNL, BTND, or BTNR. If a 
--                button press is detected, set the state to LD_BTN_STR.


type UART_STATE_TYPE is (RST_REG, LD_INIT_STR, SEND_CHAR, RDY_LOW, WAIT_RDY, WAIT_BTN, LD_BTN_STR);

constant RESET_CNTR_MAX : std_logic_vector(17 downto 0) := "110000110101000000";-- 100,000,000 * 0.002 = 200,000 = clk cycles per 2 ms
constant ADDR_MAX : natural := 63;
										 
--UART_TX_CTRL control signals
signal uartSend1 : std_logic := '0';
signal uartData : std_logic_vector (7 downto 0):= "00000000";
signal uartTX : std_logic;


--Current uart state signal
signal uartState : UART_STATE_TYPE := RST_REG;
signal reset_cntr : std_logic_vector (17 downto 0) := (others=>'0');
signal addra : std_logic_vector (5 downto 0):= "000000";

begin

process(CLK) begin
  if (rising_edge(CLK)) then
    if ((reset_cntr = RESET_CNTR_MAX) or (uartState /= RST_REG)) then
      reset_cntr <= (others=>'0');
    else
      reset_cntr <= reset_cntr + 1;
    end if;
  end if;
end process;

--Next Uart state logic (states described above)
process (CLK) begin
  if (rising_edge(CLK)) then
    if (RESET = '1') then
      uartState <= RST_REG;
    else	
      case uartState is 
      when RST_REG =>
        if (reset_cntr = RESET_CNTR_MAX) then
          uartState <= LD_INIT_STR;
        end if;
      when LD_INIT_STR =>
        uartState <= SEND_CHAR;
      when SEND_CHAR =>
        uartState <= RDY_LOW;
      when RDY_LOW =>
        uartState <= WAIT_RDY;
      when WAIT_RDY =>
        if (uartRdy = '1') then
          if (addra = ADDR_MAX) then
            uartState <= WAIT_BTN;
          else
            uartState <= SEND_CHAR;
          end if;
        end if;
      when WAIT_BTN =>
        uartState <= WAIT_BTN;
      when others=> --should never be reached
        uartState <= RST_REG;
      end case;
    end if ;
  end if;
end process;

--Conrols the strIndex signal so that it contains the index
--of the next character that needs to be sent over uart
char_count_process : process (CLK) begin
  if (rising_edge(CLK)) then
    if (uartState = RST_REG) then
      addra <= "000000";
    elsif (uartState = SEND_CHAR) then
      addra <= addra + 1;
    end if;
  end if;
end process;

--Controls the UART_TX_CTRL signals
char_load_process : process (CLK) begin
  if (rising_edge(CLK)) then
    if (uartState = SEND_CHAR) then
      uartSend1 <= '1';
    else
      uartSend1 <= '0';
    end if;
  end if;
end process;

Rom_addr <=  addra;
uartSend <= uartSend1;
end Behavioral;

