uart_tx: WIP, todo: testbench
authorBernhard Urban <lewurm@gmail.com>
Tue, 25 May 2010 15:21:49 +0000 (17:21 +0200)
committerBernhard Urban <lewurm@gmail.com>
Tue, 25 May 2010 15:21:49 +0000 (17:21 +0200)
src/uart_tx.vhd

index f3ccc8f4e584bc4bdfbe0aea7793a77e7200379e..4c97578484e6d47899ae927bf4d12e2d3f7541a3 100644 (file)
@@ -9,95 +9,96 @@ use ieee.numeric_std.all;
 --end package int_types;
 
 entity uart_tx is
 --end package int_types;
 
 entity uart_tx is
-port(
-       sys_clk : in std_logic;
-       sys_res : in std_logic;
-       txd : out std_logic;
-       tx_data : in std_logic_vector(7 downto 0); -- map this to a larger register with containing input
-       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
 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 range 0 to 15;
-       signal counter_next : integer range 0 to 15;
-       signal txd_next : std_logic;
+       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(0 to 10);
+       signal bitcnt_int, bitcnt_next : integer range 0 to 10;
+       signal baudcnt_int, baudcnt_next : integer range 0 to BAUD;
 begin
 begin
-       process (sys_clk, sys_res)
+       txd <= txd_int;
+       tx_done <= tx_done_int;
+
+       process (sys_clk, sys_res_n)
        begin
        begin
-               if sys_res = '0' then
-                       counter <= 0;
-                       timer <= 0;
-                       txd <= '0';
-                       txd_next <= '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
                elsif rising_edge(sys_clk) then
-                       counter <= counter_next;
-                       timer <= timer_next;
-                       txd <= txd_next;
+                       state_int <= state_next;
+                       txd_int <= txd_next;
+                       tx_done_int <= tx_done_next;
+                       bitcnt_int <= bitcnt_next;
+                       baudcnt_int <= baudcnt_next;
+                       -- HIGHBIT (1) | STARTBIT (1) | DATA (8) | STOPBIT (1)
+                       -- TODO: passt das wegen der endianess?
+                       tx_to_send <= '1' & '0' & tx_data & '1';
                end if;
        end process;
 
                end if;
        end process;
 
-       process(timer)
+       process(tx_new, tx_to_send, state_int, bitcnt_int, baudcnt_int)
        begin
        begin
-               if (timer = timer_max) then
-                       timer_next <= 0;
-               else
-                       timer_next <= timer + 1;
-               end if;
-       end process;
+               state_next <= state_int;
+               tx_done_next <= tx_done_int;
+               txd_next <= txd_int;
+               bitcnt_next <= bitcnt_int;
+               baudcnt_next <= baudcnt_int;
 
 
-       process (timer, counter, tx_new)
-       begin
-               if (tx_new = '1') then
-                       if (timer = timer_max) then
-                               if (counter > 10) then
-                                       counter_next <= 0;
+               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
                                else
-                                       counter_next <= counter + 1;
+                                       -- 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 if;
-                       else
-                                       counter_next <= counter;
-                       end if;
-               else
-                               counter_next <= 0;
-               end if;
-       end process;
-
-       process (counter)
-       begin
-               -- TODO: this is always 8N1 and anything but optimal
-               case (counter) is 
-                       when 0 =>
-                               txd_next <= '1';
-                       when 1 =>
-                               txd_next <= tx_data(0);
-                       when 2 =>
-                               txd_next <= tx_data(1);
-                       when 3 =>
-                               txd_next <= tx_data(2);
-                       when 4 =>
-                               txd_next <= tx_data(3);
-                       when 5 =>
-                               txd_next <= tx_data(4);
-                       when 6 =>
-                               txd_next <= tx_data(5);
-                       when 7 =>
-                               txd_next <= tx_data(6);
-                       when 8 =>
-                               txd_next <= tx_data(7);
-                       when 9 =>
-                               txd_next <= '0';
-                       when 10 =>
-                               txd_next <= '1';
-                       when others =>
-                               txd_next <= '1';
                end case;
        end process;
                end case;
        end process;
-
-       tx_done <= '0';
-
 end architecture beh;
 end architecture beh;