100 lines
2.6 KiB
VHDL
100 lines
2.6 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.all;
|
|
|
|
entity uart_rx is
|
|
generic(
|
|
F_CLK : natural := 50_000_000; -- System clock speed
|
|
BAUD_RATE : natural := 115_200 -- Desired baudrate
|
|
);
|
|
port(
|
|
clk : in std_logic; -- System clock @ F_CLK
|
|
rst_a : in std_logic; -- Asynchronous reset
|
|
|
|
data : out std_logic_vector; -- Receive payload word (width determines width of UART payload)
|
|
data_valid : out std_logic; -- Data is valid
|
|
|
|
serial_in_a : in std_logic -- UART RX line (asynchronous) @ BAUDRATE
|
|
);
|
|
end entity uart_rx;
|
|
|
|
architecture rtl of uart_rx is
|
|
signal serial_in : std_logic;
|
|
|
|
constant BITCLK_MAX : integer := integer(real(F_CLK) / real(BAUD_RATE));
|
|
constant BITCLK_START : integer := BITCLK_MAX / 2;
|
|
signal bitclk_cnt : integer range 0 to BITCLK_MAX;
|
|
signal bit_stb : std_logic;
|
|
|
|
constant BITCNT_MAX : integer := 10;
|
|
signal cnt : integer range 0 to BITCNT_MAX;
|
|
signal busy : std_logic;
|
|
|
|
begin
|
|
synchronizer_rx_inst : entity work.synchronizer
|
|
generic map(
|
|
init_value => '1'
|
|
)
|
|
port map(
|
|
clk => clk,
|
|
rst => rst_a,
|
|
data_in_a(0) => serial_in_a,
|
|
data_out(0) => serial_in
|
|
);
|
|
|
|
rx : process(clk, rst_a) is
|
|
begin
|
|
if rst_a then
|
|
cnt <= 0;
|
|
data_valid <= '0';
|
|
|
|
elsif rising_edge(clk) then
|
|
data_valid <= '0';
|
|
|
|
if (cnt = 0 and serial_in = '0') or bit_stb = '1' then
|
|
if cnt = BITCNT_MAX then
|
|
cnt <= 0;
|
|
data_valid <= '1';
|
|
else
|
|
data <= serial_in & data(7 downto 1);
|
|
cnt <= cnt + 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process rx;
|
|
busy <= '1' when cnt /= 0 else '0';
|
|
|
|
bitclk : process(clk, rst_a) is
|
|
begin
|
|
if rst_a then
|
|
bit_stb <= '0';
|
|
bitclk_cnt <= 0;
|
|
|
|
elsif rising_edge(clk) then
|
|
bit_stb <= '0';
|
|
|
|
if not busy then
|
|
bitclk_cnt <= BITCLK_START;
|
|
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;
|