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