From a7c062206f85c96e0ebd6760f74e22bf530a3462 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Tue, 25 May 2010 17:21:49 +0200 Subject: [PATCH] uart_tx: WIP, todo: testbench --- src/uart_tx.vhd | 153 ++++++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/src/uart_tx.vhd b/src/uart_tx.vhd index f3ccc8f..4c97578 100644 --- a/src/uart_tx.vhd +++ b/src/uart_tx.vhd @@ -9,95 +9,96 @@ use ieee.numeric_std.all; --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 - 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 - 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; - 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 - 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; - process(timer) + process(tx_new, tx_to_send, state_int, bitcnt_int, baudcnt_int) 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 - 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; - 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; - - tx_done <= '0'; - end architecture beh; -- 2.25.1