97 lines
2.8 KiB
VHDL
97 lines
2.8 KiB
VHDL
|
-- -------------------------------------------------------------------------- --
|
||
|
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
||
|
-- -------------------------------------------------------------------------- --
|
||
|
-- TODO
|
||
|
-- -------------------------------------------------------------------------- --
|
||
|
-- Author : Markus Koch <markus@notsyncing.net>
|
||
|
-- Contributors : None
|
||
|
-- License : Mozilla Public License (MPL) Version 2
|
||
|
-- -------------------------------------------------------------------------- --
|
||
|
|
||
|
library ieee;
|
||
|
use ieee.std_logic_1164.all;
|
||
|
use ieee.numeric_std.all;
|
||
|
use ieee.math_real.round;
|
||
|
|
||
|
entity uart_tx is
|
||
|
generic(
|
||
|
F_CLK : integer := 50_000_000; -- System clock speed
|
||
|
BAUD_RATE : integer := 115_200 -- Desired baudrate
|
||
|
);
|
||
|
port(
|
||
|
clk : in std_logic; -- System clock @ F_CLK
|
||
|
rst_a : in std_logic; -- Asynchronous reset
|
||
|
|
||
|
data : in std_logic_vector; -- Data to send (width determines width of UART payload)
|
||
|
data_valid : in std_logic; -- Data is valid, TX at next opportunity
|
||
|
|
||
|
data_latched : out std_logic; -- The data word has been latched, go ahead and apply the next one, or negate data_valid to end the transaction after the current word
|
||
|
busy : out std_logic; -- The core is busy transmitting a data word
|
||
|
serial_out : out std_logic -- UART TX line
|
||
|
);
|
||
|
end entity uart_tx;
|
||
|
|
||
|
architecture rtl of uart_tx is
|
||
|
constant COUNTER_MAX : natural := 10;
|
||
|
|
||
|
signal sr : std_logic_vector((data'length + 1) - 1 downto 0);
|
||
|
|
||
|
signal bit_cnt : integer range 0 to COUNTER_MAX;
|
||
|
|
||
|
constant BITCLK_MAX : integer := integer(real(F_CLK) / real(BAUD_RATE));
|
||
|
signal bitclk_cnt : integer range 0 to BITCLK_MAX;
|
||
|
signal bit_stb : std_logic;
|
||
|
|
||
|
begin
|
||
|
tx_fsm : process(clk, rst_a) is
|
||
|
begin
|
||
|
if (rst_a = '1') then
|
||
|
sr <= (others => '1');
|
||
|
bit_cnt <= 0;
|
||
|
data_latched <= '0';
|
||
|
|
||
|
elsif (rising_edge(clk)) then
|
||
|
data_latched <= '0';
|
||
|
|
||
|
if ((bit_stb = '1') or (bit_cnt = 0)) then
|
||
|
sr <= '1' & sr(sr'high downto 1);
|
||
|
if (bit_cnt = 0) then
|
||
|
if (data_valid = '1') then
|
||
|
data_latched <= '1';
|
||
|
sr <= data & '0';
|
||
|
bit_cnt <= COUNTER_MAX;
|
||
|
end if;
|
||
|
else
|
||
|
bit_cnt <= bit_cnt - 1;
|
||
|
end if;
|
||
|
end if;
|
||
|
end if;
|
||
|
end process tx_fsm;
|
||
|
serial_out <= sr(0); -- @suppress PID1: Not a readback signal
|
||
|
|
||
|
busy <= '1' when (bit_cnt /= 0) or (data_valid = '1') else '0';
|
||
|
|
||
|
bitclk : process(clk, rst_a) is
|
||
|
begin
|
||
|
if rst_a then
|
||
|
bit_stb <= '0';
|
||
|
bitclk_cnt <= BITCLK_MAX;
|
||
|
|
||
|
elsif rising_edge(clk) then
|
||
|
bit_stb <= '0';
|
||
|
|
||
|
if not busy then
|
||
|
bitclk_cnt <= BITCLK_MAX;
|
||
|
else
|
||
|
if bitclk_cnt = 0 then
|
||
|
bitclk_cnt <= BITCLK_MAX;
|
||
|
bit_stb <= '1';
|
||
|
else
|
||
|
bitclk_cnt <= bitclk_cnt - 1;
|
||
|
end if;
|
||
|
end if;
|
||
|
end if;
|
||
|
end process bitclk;
|
||
|
|
||
|
end architecture rtl;
|