library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity uart is
Port ( RX : in STD_LOGIC;
TX : out STD_LOGIC;
CLK : in STD_LOGIC);
end uart;
architecture Behavioral of uart is
constant max : integer := (100000000/(2*9600))-1;
signal CLK_9600 : STD_LOGIC;
signal CLK_cnt : integer range 0 to max := 0;
type state is (start, s0, s1, s2, s3, s4, s5, s6, s7, stop);
signal current_state_rec : state;
signal next_state_rec : state;
signal current_state_snd : state;
signal next_state_snd : state;
type matrix_1 is array (0 to 19) of STD_LOGIC_VECTOR(7 downto 0);
type matrix_2 is array (0 to 19) of STD_LOGIC_VECTOR(7 downto 0);
signal memory_in : matrix_1;
signal memory_out : matrix_2;
signal akku_vector : STD_LOGIC_VECTOR(7 downto 0);
signal rec_complete_flag : STD_LOGIC;
signal snd_complete_flag : STD_LOGIC;
signal memory_full_flag : STD_LOGIC;
signal write_address : integer range 0 to 19;
signal read_address : integer range 0 to 19;
begin
memory_out <= memory_in;
process(CLK)
begin
if rising_edge(CLK) then
if CLK_cnt = max then
CLK_cnt <= 0;
CLK_9600 <= not(CLK_9600);
else
CLK_cnt <= CLK_cnt + 1;
end if;
end if;
end process;
process(CLK_9600)
begin
if rising_edge(CLK_9600) then
current_state_rec <= next_state_rec;
current_state_snd <= next_state_snd;
akku_vector <= RX & akku_vector(7 downto 1);
end if;
end process;
process(rec_complete_flag, CLK_9600)
begin
if rec_complete_flag = '1' and rising_edge(CLK_9600) then
if write_address = 19 then
write_address <= 0;
memory_full_flag <= '1';
memory_in(write_address) <= akku_vector;
else
write_address <= write_address + 1;
memory_full_flag <= '0';
memory_in(write_address) <= akku_vector;
end if;
end if;
end process;
process(snd_complete_flag, CLK_9600)
begin
if snd_complete_flag = '1' and rising_edge(CLK_9600) then
if read_address = 19 then
read_address <= 0;
else
read_address <= read_address + 1;
end if;
end if;
end process;
process(RX, current_state_rec)
begin
case current_state_rec is
when start =>
if RX = '0' then
next_state_rec <= s0;
else
next_state_rec <= start;
end if;
rec_complete_flag <= '0';
when s0 =>
next_state_rec <= s1;
rec_complete_flag <= '0';
when s1 =>
next_state_rec <= s2;
rec_complete_flag <= '0';
when s2 =>
next_state_rec <= s3;
rec_complete_flag <= '0';
when s3 =>
next_state_rec <= s4;
rec_complete_flag <= '0';
when s4 =>
next_state_rec <= s5;
rec_complete_flag <= '0';
when s5 =>
next_state_rec <= s6;
rec_complete_flag <= '0';
when s6 =>
next_state_rec <= s7;
rec_complete_flag <= '0';
when s7 =>
next_state_rec <= stop;
rec_complete_flag <= '0';
when others =>
next_state_rec <= start;
rec_complete_flag <= '1';
end case;
end process;
process(memory_full_flag, current_state_snd, read_address, memory_out)
begin
case current_state_snd is
when start =>
if memory_full_flag = '1' then
next_state_snd <= s0;
TX <= '0';
else
next_state_snd <= start;
TX <= '1';
end if;
snd_complete_flag <= '0';
when s0 =>
next_state_snd <= s1;
TX <= memory_out(read_address)(0);
snd_complete_flag <= '0';
when s1 =>
next_state_snd <= s2;
TX <= memory_out(read_address)(1);
snd_complete_flag <= '0';
when s2 =>
next_state_snd <= s3;
TX <= memory_out(read_address)(2);
snd_complete_flag <= '0';
when s3 =>
next_state_snd <= s4;
TX <= memory_out(read_address)(3);
snd_complete_flag <= '0';
when s4 =>
next_state_snd <= s5;
TX <= memory_out(read_address)(4);
snd_complete_flag <= '0';
when s5 =>
next_state_snd <= s6;
TX <= memory_out(read_address)(5);
snd_complete_flag <= '0';
when s6 =>
next_state_snd <= s7;
TX <= memory_out(read_address)(6);
snd_complete_flag <= '0';
when s7 =>
next_state_snd <= stop;
TX <= memory_out(read_address)(7);
snd_complete_flag <= '0';
when others =>
if (read_address = 19) and (memory_full_flag = '1') then
next_state_snd <= stop;
snd_complete_flag <= '0';
else
next_state_snd <= start;
snd_complete_flag <= '1';
end if;
TX <= '1';
end case;
end process;
end Behavioral;