--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;