initial uart_rx
[hwmod.git] / src / uart_rx.vhd
diff --git a/src/uart_rx.vhd b/src/uart_rx.vhd
new file mode 100644 (file)
index 0000000..90dcedc
--- /dev/null
@@ -0,0 +1,157 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+--use work.gen_pkg.all;
+
+--package int_types is
+--     type STATE_UART_RX is (IDLE, BUSY, DONE);
+--end package int_types;
+
+entity uart_rx is
+port(
+       sys_clk : in std_logic;
+       sys_res : in std_logic;
+       txd : in std_logic; -- warning: this is asynchronous input!
+       tx_data : out std_logic_vector(7 downto 0); -- map this to a larger register with containing input
+       tx_new : out std_logic;
+);
+end entity uart_rx;
+
+architecture beh of uart_rx is
+       constant timer_max : integer := 35;
+
+       signal timer, timer_next : integer range 0 to 65535;
+       signal counter, counter_next : integer range 0 to 15;
+       signal state, state_next : STATE_UART_RX;
+       signal tx_data_pref : std_logic_vector(7 downto 0); -- FIXME: this isnt named next so that the interface isn't called tx_data_next ...
+
+begin
+--FIXME:
+       process(sys_clk, sys_res_n)
+               begin
+               if sys_res_n = ‘0‘ then
+                       -- Set reset state
+                       state <= IDLE;
+                       tx_data_prev <= X"0";
+               elsif rising_edge(sys_clk) then
+                       -- Store next state
+                       state <= state_next;
+                       tx_data_prev <= tx_data;
+               end if;
+       end process;
+
+       process(state, txd, counter)
+       begin
+               state_next <= state;
+               case state is
+                       when IDLE =>
+                               if (txd = 0) then
+                                       state_next <= BUSY;
+                               else
+                                       state_next <= IDLE;
+                               end if;
+                       when BUSY =>
+                               if (counter = 9) then --FIXME: is this true?
+                                       state_next <= DONE;
+                               else
+                                       state_next <= BUSY;
+                               end if;
+                       when DONE =>
+                               state_next <= IDLE;
+               end case;
+       end process;
+
+       process(state)
+       begin
+               -- Set default values
+               -- for the outputs
+               tx_new <= ‘0‘;
+
+               -- Calculate the outputs
+               -- based on the current
+               -- state
+               case state is
+                       when IDLE =>
+                               tx_new <= ‘0‘;
+                       when BUSY =>
+                               tx_new <= ‘0‘;
+                               case (counter)
+                                       tx_data(counter-2) <= txd;
+                               end case;
+                       when DONE =>
+                               tx_new <= '1';
+               end case;
+       end process;
+-- END FIXME: do fill this out CORRECTLY
+
+       process (sys_clk, sys_res)
+       begin
+               if sys_res = '0' then
+                       counter <= 0;
+                       timer <= 0;
+               elsif rising_edge(sys_clk) then
+                       counter <= counter_next;
+                       timer <= timer_next;
+               end if;
+       end process;
+
+       process(timer)
+       begin
+               if (timer = timer_max) then
+                       timer_next <= 0;
+               else
+                       timer_next <= timer + 1;
+               end if;
+       end process;
+
+       process (timer, counter, tx_new)
+       begin
+               if (tx_new = '1') then
+                       if (timer = timer_max) then
+                               if (counter > 10) then
+                                       counter_next <= 0;
+                               else
+                                       counter_next <= counter + 1;
+                               end if;
+                       else
+                                       counter_next <= counter;
+                       end if;
+               else
+                               counter_next <= 0;
+               end if;
+       end process;
+
+       process (counter, txd)
+       begin
+               tx_data <= tx_data_prev;
+               -- TODO: we probably want oversampling and averaging + failure!
+               -- FIXME: this is per se not synthesisable
+               case (counter) is
+                       when 0 => --start bit
+                               assert (txd = '0');
+                       when 1 =>
+                               tx_data(0) <= txd;
+                       when 2 =>
+                               tx_data(1) <= txd;
+                       when 3 =>
+                               tx_data(2) <= txd;
+                       when 4 =>
+                               tx_data(3) <= txd;
+                       when 5 =>
+                               tx_data(4) <= txd;
+                       when 6 =>
+                               tx_data(5) <= txd;
+                       when 7 =>
+                               tx_data(6) <= txd;
+                       when 8 =>
+                               tx_data(7) <= txd;
+                       when 9 => -- stop bit
+                               assert (txd = '1');
+                       when others => -- idle
+                               assert (txd = '1');
+               end case;
+       end process;
+
+       tx_done <= '0';
+
+end architecture beh;