--
-- Copyright (c) 1999-2000 University of California, Riverside.
-- Permission to copy is granted provided that this header remains
-- intact.  This software is provided with no warranties.
--
-- Version : 1.0
--

-------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;

-------------------------------------------------------------------------------

entity UAT is

    generic(STATUS_REG_ADDR : INTEGER := 65534;
            TX_REG_ADDR : INTEGER := 65535);

    port(rst      : in  STD_LOGIC;
         clk      : in  STD_LOGIC;
         addr     : in  UNSIGNED (15 downto 0);
         in_data  : in  UNSIGNED (7 downto 0);
         out_data : out UNSIGNED (7 downto 0);
         rd       : in  STD_LOGIC;
         wr       : in  STD_LOGIC;
         txout    : out STD_LOGIC);
end UAT;

-------------------------------------------------------------------------------

architecture BHV of UAT is

    constant CD_8 : UNSIGNED (7 downto 0) := "--------";
    constant CZ_8 : UNSIGNED (7 downto 0) := "ZZZZZZZZ";
    
    type STATE_TYPE is (ST_IDLE, ST_BIT7, ST_BIT6, ST_BIT5, ST_BIT4, 
                        ST_BIT3, ST_BIT2, ST_BIT1, ST_BIT0, ST_STOP);

    signal busy : STD_LOGIC;
    signal txbuffer : UNSIGNED (7 downto 0);
    signal state : STATE_TYPE;
begin

    process(rst, clk)
    begin

        if( rst = '1' ) then

            busy <= '0';
            txbuffer <= CD_8;
            state <= ST_IDLE;
            out_data <= CZ_8;
            txout <= '1';
            
        elsif( clk'event and clk = '1' ) then

            out_data <= CZ_8;

            -- listen to the bus
            if( rd = '1' and conv_integer(addr) = STATUS_REG_ADDR ) then

                out_data <= "0000000" & busy;
            elsif( wr = '1' and conv_integer(addr) = TX_REG_ADDR ) then

                busy <= '1';
                txbuffer <= in_data;
            end if;

            -- send serially
            case state is
                when ST_IDLE =>
                    if( busy = '1' ) then

                        txout <= '0';
                        state <= ST_BIT7;
                    end if;

                when ST_BIT7 =>
                    txout <= txbuffer(7);
                    state <= ST_BIT6;

                when ST_BIT6 =>
                    txout <= txbuffer(6);
                    state <= ST_BIT5;

                when ST_BIT5 =>
                    txout <= txbuffer(5);
                    state <= ST_BIT4;

                when ST_BIT4 =>
                    txout <= txbuffer(4);
                    state <= ST_BIT3;

                when ST_BIT3 =>
                    txout <= txbuffer(3);
                    state <= ST_BIT2;

                when ST_BIT2 =>
                    txout <= txbuffer(2);
                    state <= ST_BIT1;

                when ST_BIT1 =>
                    txout <= txbuffer(1);
                    state <= ST_BIT0;

                when ST_BIT0 =>
                    txout <= txbuffer(0);
                    state <= ST_STOP;

                when ST_STOP =>
                    busy <= '0';
                    txout <= '1';
                    state <= ST_IDLE;
            end case;
        end if;
    end process;
end BHV;
