You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.1 KiB

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart_tx is
port(
i_clk_baudrate : in std_logic;
i_reset_n : in std_logic;
i_tx_send : in std_logic;
i_msb_first : in std_logic;
i_tx_data_vec : in std_logic_vector(7 downto 0);
o_tx_pin : out std_logic;
o_tx_sent : out std_logic
);
end;
architecture uart_tx_rtl of uart_tx is
type z_uart_t is (idle, sending);
constant c_START_BIT : std_logic := '0';
constant c_STOP_BIT : std_logic := '1';
signal s_tx_buf_vec : std_logic_vector(7 downto 0) := x"00";
function reverse_any_vector (a: in std_logic_vector)
return std_logic_vector is
variable result: std_logic_vector(a'RANGE);
alias aa: std_logic_vector(a'REVERSE_RANGE) is a;
begin
for i in aa'RANGE loop
result(i) := aa(i);
end loop;
return result;
end; -- function reverse_any_vector
begin
uart_tx_main_proc: process(i_clk_baudrate)
variable z_uart : z_uart_t := idle;
variable v_trans_cnt : integer range 0 to 10 := 0;
begin
if rising_edge(i_clk_baudrate) then
-- Syncrhonous reset only.
if (i_reset_n = '0') then
o_tx_pin <= '1';
o_tx_sent <= '1';
z_uart := idle;
else
case z_uart is
when idle =>
if (i_tx_send = '1') then
if (i_msb_first = '1') then
s_tx_buf_vec <= i_tx_data_vec;
else
s_tx_buf_vec <= reverse_any_vector(i_tx_data_vec);
end if;
o_tx_sent <= '0';
o_tx_pin <= c_START_BIT;
z_uart := sending;
end if;
when sending =>
if (v_trans_cnt >= 8) then
v_trans_cnt := 0;
o_tx_sent <= '1';
o_tx_pin <= c_STOP_BIT;
z_uart := idle;
else
o_tx_pin <= s_tx_buf_vec(7-v_trans_cnt);
v_trans_cnt := v_trans_cnt + 1;
end if;
end case;
end if; -- reset
end if; -- clk
end process uart_tx_main_proc; -- main
end;