diff --git a/lib/uart/juart_rx.vhd b/lib/uart/juart_rx.vhd
new file mode 100644
index 0000000..ca6e337
--- /dev/null
+++ b/lib/uart/juart_rx.vhd
@@ -0,0 +1,188 @@
+-- UART Receiver
+--
+-- Version : 1.00
+-- Version Date : 15 December 2016
+--
+------------------------------------------------------------------------------------
+--
+-- Library declarations
+--
+-- The Unisim Library is used to define Xilinx primitives. It is also used during
+-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
+--
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+--
+------------------------------------------------------------------------------------
+--
+-- Main Entity
+--
+entity juart_rx is
+ Port ( serial_in : in std_logic;
+ data_out : out unsigned(7 downto 0);
+ data_strobe : out std_logic;
+ en_16_x_baud : in std_logic;
+ clk : in std_logic;
+ rst : in std_logic);
+ end juart_rx;
+--
+------------------------------------------------------------------------------------
+--
+-- Start of Main Architecture
+--
+architecture behavior of juart_rx is
+--
+------------------------------------------------------------------------------------
+--
+------------------------------------------------------------------------------------
+--
+-- Signals used
+--
+------------------------------------------------------------------------------------
+--
+signal bit_count_rst : std_logic;
+signal bit_count : natural range 0 to 15;
+signal data_valid : std_logic;
+signal shiftreg_en : std_logic;
+signal shiftreg : unsigned (7 downto 0);
+signal sample_count_rst : std_logic;
+signal sample_count : unsigned (15 downto 0);
+signal idle_count : natural range 0 to 15;
+signal is_idle : std_logic;
+signal bit_sample : std_logic;
+
+type state_t is (idle, wait_start, start, shift, stop);
+
+signal state : state_t;
+signal state_next : state_t;
+--
+--
+begin
+
+bit_sample <= sample_count(8);
+is_idle <= '1' when idle_count = 0 else '0';
+
+data_out_reg:
+process(clk)
+begin
+ if rising_edge(clk) then
+ data_strobe <= '0';
+ if data_valid = '1' then
+ data_out <= shiftreg;
+ data_strobe <= '1';
+ end if;
+ end if;
+end process;
+
+proc_state_next:
+process(clk)
+begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ state <= idle;
+ else
+ state <= state_next;
+ end if;
+ end if;
+end process;
+
+statemachine:
+process(state, is_idle, bit_count, bit_sample, serial_in)
+begin
+ state_next <= state;
+ sample_count_rst <= '1';
+ bit_count_rst <= '1';
+ shiftreg_en <= '0';
+ data_valid <= '0';
+
+ case state is
+ when idle =>
+ if is_idle = '1' then
+ state_next <= wait_start;
+ end if;
+ when wait_start =>
+ if serial_in = '0' then
+ sample_count_rst <= '0';
+ state_next <= start;
+ end if;
+ when start =>
+ sample_count_rst <= '0';
+ if bit_sample = '1' then
+ state_next <= shift;
+ end if;
+ when shift =>
+ shiftreg_en <= '1';
+ sample_count_rst <= '0';
+ bit_count_rst <= '0';
+ if bit_count = 8 then
+ state_next <= stop;
+ end if;
+ when stop =>
+ state_next <= idle;
+ data_valid <= '1';
+
+ when others =>
+ state_next <= idle;
+ end case;
+end process;
+
+shift_register:
+process(clk)
+begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ shiftreg <= (others => '0');
+ elsif shiftreg_en = '1' and bit_sample = '1' then
+ shiftreg <= shiftreg(shiftreg'left-1 downto 0) & serial_in;
+ end if;
+ end if;
+end process;
+
+sample_counter:
+process(clk)
+begin
+ if rising_edge(clk) then
+ if sample_count_rst = '1' then
+ sample_count <= (sample_count'left downto 1 => '0') & '1';
+ elsif en_16_x_baud = '1' then
+ sample_count <= sample_count(sample_count'left-1 downto 0) & sample_count(sample_count'left);
+ end if;
+ end if;
+end process;
+
+bit_counter:
+process(clk)
+begin
+ if rising_edge(clk) then
+ if bit_count_rst = '1' then
+ bit_count <= 0;
+ elsif bit_count /= 15 and bit_sample = '1' then
+ bit_count <= bit_count + 1;
+ end if;
+ end if;
+end process;
+
+idle_detector:
+process(clk)
+begin
+ if rising_edge(clk) then
+ if serial_in = '0' then
+ idle_count <= 15;
+ elsif idle_count /= 0 then
+ idle_count <= idle_count - 1;
+ else
+ idle_count <= 15;
+ end if;
+ end if;
+end process;
+
+end behavior;
+
+------------------------------------------------------------------------------------
+--
+-- END OF FILE
+--
+------------------------------------------------------------------------------------
+
+
diff --git a/lib/uart/juart_tx.vhd b/lib/uart/juart_tx.vhd
new file mode 100644
index 0000000..b2d369f
--- /dev/null
+++ b/lib/uart/juart_tx.vhd
@@ -0,0 +1,124 @@
+-- UART Transmitter
+--
+-- Version : 1.00
+-- Version Date : 15 December 2016
+--
+------------------------------------------------------------------------------------
+--
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+--
+------------------------------------------------------------------------------------
+--
+-- Main Entity
+--
+entity juart_tx is
+ Port ( data_in : in unsigned(7 downto 0);
+ send_character : in std_logic;
+ en_16_x_baud : in std_logic;
+ serial_out : out std_logic;
+ Tx_complete : out std_logic;
+ clk : in std_logic;
+ rst : in std_logic
+ );
+ end juart_tx;
+--
+------------------------------------------------------------------------------------
+--
+-- Start of Main Architecture
+--
+architecture behavior of juart_tx is
+--
+------------------------------------------------------------------------------------
+--
+------------------------------------------------------------------------------------
+--
+-- Signals used
+--
+------------------------------------------------------------------------------------
+--
+signal dinreg : unsigned (7 downto 0);
+signal shiftreg : unsigned (9 downto 0);
+signal busy : std_logic;
+signal start : std_logic;
+signal shift_enable : std_logic;
+signal shift_enable_count : unsigned (3 downto 0);
+signal bit_count : unsigned (3 downto 0);
+
+--
+--
+begin
+serial_out <= shiftreg(shiftreg'left);
+Tx_complete <= not busy;
+
+shift_enable_counter:
+process(clk)
+begin
+ if rising_edge(clk) then
+ shift_enable <= '0';
+ if rst = '1' then
+ shift_enable_count <= (others => '1');
+ elsif en_16_x_baud = '1' then
+ if shift_enable_count = 0 then
+ shift_enable <= '1';
+ shift_enable_count <= (others => '1');
+ else
+ shift_enable_count <= shift_enable_count - 1;
+ end if;
+ end if;
+ end if;
+end process;
+
+bit_counter:
+process(clk)
+begin
+ if rising_edge(clk) then
+ if start = '1' then
+ bit_count <= to_unsigned(shiftreg'length-1, bit_count'length);
+ elsif shift_enable = '1' then
+ if not (bit_count = 0) then
+ bit_count <= bit_count - 1;
+ end if;
+ end if;
+ end if;
+end process;
+
+transmit:
+process(clk)
+begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ shiftreg <= (others => '1');
+ busy <= '0';
+ start <= '0';
+ elsif busy = '0' then
+ if send_character = '1' then
+ busy <= '1';
+ start <= '1';
+ dinreg <= data_in;
+ end if;
+ elsif shift_enable = '1' then
+ if start = '1' then
+ start <= '0';
+ shiftreg <= '0' & dinreg & '1';
+ elsif bit_count /= 0 then
+ shiftreg <= shiftreg(shiftreg'left-1 downto 0) & '1';
+ if bit_count = 1 then
+ busy <= '0';
+ end if;
+
+ end if;
+ end if;
+ end if;
+end process;
+
+end behavior;
+
+------------------------------------------------------------------------------------
+--
+-- END OF FILE
+--
+------------------------------------------------------------------------------------
+
+
diff --git a/lib/uart/sim/tb_juart_rx.fdo b/lib/uart/sim/tb_juart_rx.fdo
new file mode 100644
index 0000000..10889a5
--- /dev/null
+++ b/lib/uart/sim/tb_juart_rx.fdo
@@ -0,0 +1,14 @@
+## NOTE: Do not edit this file.
+##
+
+vlib work
+vcom -explicit -93 "../juart_rx.vhd"
+vcom -explicit -93 "../tb_juart_rx.vhd"
+
+#restart -force
+vsim -t 1ps -lib work tb_juart_rx
+do {tb_juart_rx.wdo}
+view wave
+view structure
+view signals
+run 6.0us
diff --git a/lib/uart/sim/tb_juart_rx.wdo b/lib/uart/sim/tb_juart_rx.wdo
new file mode 100644
index 0000000..6b6c661
--- /dev/null
+++ b/lib/uart/sim/tb_juart_rx.wdo
@@ -0,0 +1,37 @@
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate -format Logic /tb_juart_rx/rst
+add wave -noupdate -format Logic /tb_juart_rx/clk
+add wave -noupdate -format Logic /tb_juart_rx/en_16_x_baud
+add wave -noupdate -format Logic /tb_juart_rx/serial_in
+add wave -noupdate -format Logic /tb_juart_rx/data_strobe
+add wave -noupdate -format Literal -radix hexadecimal /tb_juart_rx/data_reg
+add wave -noupdate -divider {JUART RX}
+add wave -noupdate -format Logic /tb_juart_rx/inst_juart_rx/bit_sample
+add wave -noupdate -format Literal -radix unsigned /tb_juart_rx/inst_juart_rx/bit_count
+add wave -noupdate -format Literal -radix unsigned /tb_juart_rx/inst_juart_rx/shiftreg
+add wave -noupdate -format Literal /tb_juart_rx/inst_juart_rx/sample_count
+add wave -noupdate -format Logic /tb_juart_rx/inst_juart_rx/is_idle
+add wave -noupdate -format Literal /tb_juart_rx/inst_juart_rx/state
+add wave -noupdate -format Literal /tb_juart_rx/inst_juart_rx/state_next
+add wave -noupdate -format Literal /tb_juart_rx/inst_juart_rx/idle_count
+add wave -noupdate -format Logic /tb_juart_rx/inst_juart_rx/bit_count_rst
+add wave -noupdate -format Logic /tb_juart_rx/inst_juart_rx/sample_count_rst
+add wave -noupdate -format Logic /tb_juart_rx/inst_juart_rx/data_strobe
+add wave -noupdate -format Literal -radix hexadecimal /tb_juart_rx/data_out
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {362114 ps} 0}
+configure wave -namecolwidth 150
+configure wave -valuecolwidth 100
+configure wave -justifyvalue left
+configure wave -signalnamewidth 1
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+update
+WaveRestoreZoom {0 ps} {6300 ns}
diff --git a/lib/uart/sim/tb_juart_tx.fdo b/lib/uart/sim/tb_juart_tx.fdo
new file mode 100644
index 0000000..9f76a06
--- /dev/null
+++ b/lib/uart/sim/tb_juart_tx.fdo
@@ -0,0 +1,14 @@
+## NOTE: Do not edit this file.
+##
+
+vlib work
+vcom -explicit -93 "../juart_tx.vhd"
+vcom -explicit -93 "../tb_juart_tx.vhd"
+
+#restart -force
+vsim -t 1ps -lib work tb_juart_tx
+do {tb_juart_tx.wdo}
+view wave
+view structure
+view signals
+run 6.0us
diff --git a/lib/uart/sim/tb_juart_tx.wdo b/lib/uart/sim/tb_juart_tx.wdo
new file mode 100644
index 0000000..bc05d8f
--- /dev/null
+++ b/lib/uart/sim/tb_juart_tx.wdo
@@ -0,0 +1,33 @@
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate -format Logic /tb_juart_tx/rst
+add wave -noupdate -format Logic /tb_juart_tx/clk
+add wave -noupdate -format Logic /tb_juart_tx/en_16_x_baud
+add wave -noupdate -format Logic /tb_juart_tx/send_character
+add wave -noupdate -format Logic /tb_juart_tx/serial_out
+add wave -noupdate -format Logic /tb_juart_tx/tx_complete
+add wave -noupdate -format Literal -radix hexadecimal /tb_juart_tx/data_in
+add wave -noupdate -divider JUART_TX
+add wave -noupdate -format Literal -radix hexadecimal /tb_juart_tx/inst_juart_tx/shiftreg
+add wave -noupdate -format Literal -radix hexadecimal /tb_juart_tx/inst_juart_tx/dinreg
+add wave -noupdate -format Logic /tb_juart_tx/inst_juart_tx/start
+add wave -noupdate -format Logic /tb_juart_tx/inst_juart_tx/busy
+add wave -noupdate -format Logic /tb_juart_tx/inst_juart_tx/shift_enable
+add wave -noupdate -format Literal -radix unsigned /tb_juart_tx/inst_juart_tx/shift_enable_count
+add wave -noupdate -format Literal -radix unsigned /tb_juart_tx/inst_juart_tx/bit_count
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {40000 ps} 0}
+configure wave -namecolwidth 150
+configure wave -valuecolwidth 100
+configure wave -justifyvalue left
+configure wave -signalnamewidth 1
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+update
+WaveRestoreZoom {0 ps} {2100 ns}
diff --git a/lib/uart/tb_juart_rx.vhd b/lib/uart/tb_juart_rx.vhd
new file mode 100644
index 0000000..b2811e0
--- /dev/null
+++ b/lib/uart/tb_juart_rx.vhd
@@ -0,0 +1,104 @@
+-------------------------------------------------------------------------
+-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
+-- This file: cpu_embedded using cpu_core and rom
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+entity tb_juart_rx is
+end;
+
+architecture behave of tb_juart_rx is
+
+ -- Number of user data words for simulation
+ constant CLK_PERIOD : time := 10 ns;
+
+ signal rst : std_logic := '1';
+ signal clk : std_logic := '1';
+ signal en_16_x_baud : std_logic := '1';
+ signal serial_in : std_logic := '1';
+ signal data_strobe : std_logic;
+ signal data_out : unsigned(7 downto 0);
+ signal serial_word : unsigned(7 downto 0) := X"AA";
+
+ signal data_reg : unsigned(7 downto 0);
+begin
+
+inst_juart_rx : entity work.juart_rx
+ PORT MAP
+ (
+ rst => rst,
+ clk => clk,
+ en_16_x_baud => en_16_x_baud,
+ data_strobe => data_strobe,
+ data_out => data_out,
+ serial_in => serial_in
+ );
+
+
+CLK_GEN: process
+ begin
+ wait for CLK_PERIOD/2;
+ clk <= not clk;
+ end process;
+
+PROC_DATAREG: process
+ begin
+ wait until rising_edge(clk) and data_strobe = '1';
+ data_reg <= data_out;
+ end process;
+
+------------------------------------------------------------------------------------------
+
+STIMULUS: process
+
+
+ begin
+
+ wait for 3*CLK_PERIOD;
+ rst <= '0';
+
+ serial_word <= X"AA";
+ wait for 16*CLK_PERIOD;
+ serial_in <= '0';
+ wait for 16*CLK_PERIOD;
+ for i in serial_word'length-1 downto 0 loop
+ serial_in <= serial_word(i);
+ wait for 16*CLK_PERIOD;
+ end loop;
+ serial_in <= '1';
+ wait for 16*CLK_PERIOD;
+ serial_word <= X"55";
+ serial_in <= '0';
+ wait for 16*CLK_PERIOD;
+
+ for i in serial_word'length-1 downto 0 loop
+ serial_in <= serial_word(i);
+ wait for 16*CLK_PERIOD;
+ end loop;
+ serial_in <= '1';
+ wait;
+
+ end process;
+
+end architecture behave;
diff --git a/lib/uart/tb_juart_tx.vhd b/lib/uart/tb_juart_tx.vhd
new file mode 100644
index 0000000..cc11f9d
--- /dev/null
+++ b/lib/uart/tb_juart_tx.vhd
@@ -0,0 +1,96 @@
+-------------------------------------------------------------------------
+-- Project: JCPU, a portable 8-bit RISC CPU written in VHDL
+-- This file: cpu_embedded using cpu_core and rom
+--
+-- Copyright (C) 2007 J. Ahrensfeld
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see .
+--
+-- For questions and ideas, please contact the author at jens@jayfield.org
+--
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+entity tb_juart_tx is
+end;
+
+architecture behave of tb_juart_tx is
+
+ -- Number of user data words for simulation
+ constant CLK_PERIOD : time := 10 ns;
+
+ signal rst : std_logic := '1';
+ signal clk : std_logic := '1';
+ signal en_16_x_baud : std_logic := '1';
+ signal send_character : std_logic := '0';
+ signal serial_out : std_logic;
+ signal Tx_complete : std_logic;
+ signal data_in : unsigned(7 downto 0) := (others => '0');
+
+begin
+
+inst_juart_tx : entity work.juart_tx
+ PORT MAP
+ (
+ rst => rst,
+ clk => clk,
+ en_16_x_baud => en_16_x_baud,
+ send_character => send_character,
+ Tx_complete => Tx_complete,
+ data_in => data_in,
+ serial_out => serial_out
+ );
+
+
+CLK_GEN: process
+ begin
+ wait for CLK_PERIOD/2;
+ clk <= not clk;
+ end process;
+
+------------------------------------------------------------------------------------------
+
+STIMULUS: process
+
+
+ begin
+
+ wait for 3*CLK_PERIOD;
+ rst <= '0';
+ wait for 3*CLK_PERIOD;
+ wait until rising_edge(clk);
+ data_in <= X"A5";
+ wait until rising_edge(clk) and Tx_complete = '1';
+ send_character <= '1';
+ wait until rising_edge(clk) and Tx_complete = '0';
+ send_character <= '0';
+ wait until rising_edge(clk) and Tx_complete = '1';
+ data_in <= X"AA";
+ wait until rising_edge(clk) and Tx_complete = '1';
+ send_character <= '1';
+ wait until rising_edge(clk) and Tx_complete = '0';
+ send_character <= '0';
+ data_in <= X"55";
+ wait until rising_edge(clk) and Tx_complete = '1';
+ send_character <= '1';
+ wait until rising_edge(clk) and Tx_complete = '0';
+ send_character <= '0';
+ wait;
+
+ end process;
+
+end architecture behave;