uart_rx: ein prozessmodell. spart weitere 3 logic elements :P
[hwmod.git] / src / uart_tx.vhd
index 7d06e4cdef757d6597f317bd1cab6a4c02bcee2a..a851656f02618a636ab8bfa915f43df8fcbf3a83 100644 (file)
@@ -1,54 +1,99 @@
 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_TX is (IDLE, STARTBITS, PAYLOAD, PARITY, STOP, DONE);
---     type PARITY_TYPE is (ODD, EVEN, NONE);
---end package int_types;
+use work.gen_pkg.all;
 
 entity uart_tx is
-port(
-       sys_clk : in std_logic;
-       sys_res : in std_logic;
-       --txd : out std_logic;
-       --tx_data : in std_logic;
-       tx_new : in std_logic;
-       tx_done : out std_logic
-);
+       generic (
+               CLK_FREQ : integer := 33000000;
+               BAUDRATE : integer := 115200
+       );
+       port(
+               sys_clk : in std_logic;
+               sys_res_n : in std_logic;
+               txd : out std_logic;
+               tx_data : in std_logic_vector(7 downto 0);
+               tx_new : in std_logic;
+               tx_done : out std_logic
+       );
 end entity uart_tx;
 
 architecture beh of uart_tx is
-       signal timer : integer range 0 to 65535;
-       signal timer_next : integer range 0 to 65535;
-       constant timer_max : integer := 35;
-       signal counter : integer;
-       signal counter_next : integer;
+       constant BAUD : integer := CLK_FREQ/BAUDRATE;
+
+       type STATE_UART_TX is (IDLE, SENDBITS, DONE);
+       signal state_int, state_next : STATE_UART_TX;
+
+       signal txd_next, txd_int : std_logic;
+       signal tx_done_next, tx_done_int : std_logic;
+       signal tx_to_send : std_logic_vector(10 downto 0);
+       signal bitcnt_int, bitcnt_next : integer range 0 to 11;
+       signal baudcnt_int, baudcnt_next : integer range 0 to BAUD;
 begin
-       process (sys_clk, sys_res)
+       txd <= txd_int;
+       tx_done <= tx_done_int;
+
+       process (sys_clk, sys_res_n)
        begin
-               if sys_res = '0' then
-                       counter <= 0;
-                       timer <= 0;
+               if sys_res_n = '0' then
+                       state_int <= IDLE;
+                       txd_int <= '1';
+                       tx_done_int <= '0';
+                       bitcnt_int <= 0;
+                       baudcnt_int <= 0;
+                       tx_to_send <= (others => '0');
                elsif rising_edge(sys_clk) then
-                       counter <= counter_next;
-                       timer <= timer_next;
+                       state_int <= state_next;
+                       txd_int <= txd_next;
+                       tx_done_int <= tx_done_next;
+                       bitcnt_int <= bitcnt_next;
+                       baudcnt_int <= baudcnt_next;
+                       -- STOPBIT (1) | DATA (8) | STARTBIT (1) | HIGHBIT (1)
+                       tx_to_send <= '1' & tx_data & '0' & '1';
                end if;
        end process;
 
-
-       process (timer, counter)
+       process(tx_new, tx_to_send, state_int, bitcnt_int, baudcnt_int,
+               tx_done_int, txd_int)
        begin
-               if (timer = timer_max) then
-                       timer_next <= 0;
-                       counter_next <= counter + 1;
-               else
-                       timer_next <= timer + 1;
-                       counter_next <= counter;
-               end if;
-       end process;
-
-       tx_done <= '0';
+               state_next <= state_int;
+               tx_done_next <= tx_done_int;
+               txd_next <= txd_int;
+               bitcnt_next <= bitcnt_int;
+               baudcnt_next <= baudcnt_int;
 
+               case state_int is
+                       when IDLE =>
+                               tx_done_next <= '0';
+                               txd_next <= '1';
+                               bitcnt_next <= 0;
+                               -- das highbyte sofort anlegen
+                               baudcnt_next <= BAUD;
+                               if tx_new = '1' then
+                                       state_next <= SENDBITS;
+                               end if;
+                       when SENDBITS =>
+                               if bitcnt_int <= 10 then
+                                       if baudcnt_int < BAUD then
+                                               baudcnt_next <= baudcnt_int + 1;
+                                       else
+                                               txd_next <= tx_to_send(bitcnt_int);
+                                               bitcnt_next <= bitcnt_int + 1;
+                                               baudcnt_next <= 0;
+                                       end if;
+                               else
+                                       -- fuer das stopbit auch noch warten
+                                       if baudcnt_int < BAUD then
+                                               baudcnt_next <= baudcnt_int + 1;
+                                       else
+                                               state_next <= DONE;
+                                       end if;
+                               end if;
+                       when DONE =>
+                               tx_done_next <= '1';
+                               if tx_new = '0' then
+                                       state_next <= IDLE;
+                               end if;
+               end case;
+       end process;
 end architecture beh;