--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity baud_gen is
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ scale : in std_logic_vector (15 downto 0);
+ clk_baud : out std_logic
+ );
+end baud_gen;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of baud_gen is
+
+ signal counter : std_logic_vector (15 downto 0);
+ signal clk_baud_s : std_logic;
+
+--------------------------------------------------------------------------------
+
+begin
+
+ process (clk, reset)
+ begin
+ if (reset = '1') then
+ counter <= (others => '0');
+ clk_baud_s <= '0';
+
+ elsif (rising_edge(clk)) then
+ if (counter = 0) then
+ counter <= scale;
+ clk_baud_s <= not clk_baud_s;
+
+ else
+ counter <= counter - 1;
+
+ end if;
+ end if;
+ end process;
+
+--------------------------------------------------------------------------------
+
+ clk_baud <= clk_baud_s;
+
+end behavioral;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity fifo is
+ generic (
+ width : integer := 2
+ );
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ we : in std_logic;
+ re : in std_logic;
+ d_in : in std_logic_vector (7 downto 0);
+ d_out : out std_logic_vector (7 downto 0);
+ full : out std_logic;
+ hfull : out std_logic;
+ empty : out std_logic;
+ overflow : out std_logic
+ );
+end fifo;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of fifo is
+
+ subtype mem_addr_t is std_logic_vector (width-1 downto 0);
+ type mem_t is array (3 downto 0) of std_logic_vector (7 downto 0);
+
+ signal memory : mem_t;
+
+ signal read_addr : mem_addr_t;
+ signal write_addr : mem_addr_t;
+
+ signal length : std_logic_vector (width downto 0);
+
+ signal full_s : std_logic;
+
+--------------------------------------------------------------------------------
+
+begin
+
+ process (clk, reset)
+ begin
+ if (reset = '1') then
+ length <= (others => '0');
+ overflow <= '0';
+
+ elsif (rising_edge(clk)) then
+ if ((re = '1') and (we = '0')) then
+ length <= length - 1;
+ elsif ((re = '0') and (we = '1')) then
+ if (full_s = '1') then
+ overflow <= '1';
+ else
+ length <= length + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+ process (clk, reset)
+ begin
+ if (reset = '1') then
+ read_addr <= (others => '0');
+ write_addr <= (others => '0');
+
+ elsif (rising_edge(clk)) then
+ if (re = '1') then
+ read_addr <= read_addr + 1;
+ end if;
+
+ if (we = '1') then
+ write_addr <= write_addr + 1;
+ memory (conv_integer(write_addr)) <= d_in;
+
+ if (full_s = '1') then
+ read_addr <= read_addr + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+
+--------------------------------------------------------------------------------
+
+ d_out <= memory (conv_integer(read_addr));
+
+ full_s <= '1' when (length >= 2**width) else '0';
+
+ full <= full_s;
+ hfull <= '1' when (length >= 2**(width-1)) else '0';
+ empty <= '1' when (length = 0) else '0';
+
+end behavioral;
+
--- /dev/null
+VHDL_MAIN = tb_uart
+VHDL_ENTITIES = uart.o \
+ tx.o \
+ fifo.o \
+ baud_gen.o \
+ tx_control.o
+
+STOP_TIME = 50us
+
+
+all: $(VHDL_MAIN)
+
+run: $(VHDL_MAIN)
+ ghdl -r $< --stop-time=$(STOP_TIME) --vcd=$<.vcd
+
+view: run
+ gtkwave $(VHDL_MAIN).vcd
+
+$(VHDL_MAIN): $(VHDL_MAIN).o $(VHDL_ENTITIES)
+ ghdl -e -fexplicit --ieee=synopsys $@
+
+%.o: %.vhd
+ ghdl -a -fexplicit --ieee=synopsys $<
+
+%.o: ../%.vhd
+ ghdl -a -fexplicit --ieee=synopsys $<
+
+clean:
+ rm -Rf *.o *.vcd $(VHDL_MAIN) results.txt work-obj93.cf
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity tb_baud_gen is
+end tb_baud_gen;
+
+
+architecture testbench of tb_baud_gen is
+
+ component baud_gen is
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ scale : in std_logic_vector (15 downto 0);
+ clk_baud : out std_logic
+ );
+ end component;
+
+ signal clk : std_logic;
+ signal reset : std_logic;
+
+ constant period : time := 2 us;
+ constant offset : time := 2 us;
+
+ signal scale : std_logic_vector (15 downto 0);
+ signal clk_baud : std_logic;
+
+--------------------------------------------------------------------------------
+
+begin
+ UUT : baud_gen port map (
+ clk => clk,
+ reset => reset,
+ scale => scale,
+ clk_baud => clk_baud
+ );
+
+ process
+ begin
+ clk <= '0';
+ wait for offset;
+
+ loop
+ clk <= '1';
+ wait for period/2;
+ clk <= '0';
+ wait for period/2;
+ end loop;
+ end process;
+
+
+ process
+ begin
+ reset <= '0';
+ wait for 1.2 * period;
+ reset <= '1';
+ wait for 3 * period;
+ reset <= '0';
+ wait;
+ end process;
+
+
+ process
+ begin
+ scale <= X"0000";
+
+ wait until reset = '0' and clk = '1';
+ wait for 0.1 * period;
+
+ wait;
+ end process;
+
+end testbench;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity tb_fifo is
+end tb_fifo;
+
+
+architecture testbench of tb_fifo is
+
+ component fifo is
+ generic (
+ width : integer := 2
+ );
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ we : in std_logic;
+ re : in std_logic;
+ d_in : in std_logic_vector (7 downto 0);
+ d_out : out std_logic_vector (7 downto 0);
+ overflow : out std_logic
+ );
+ end component;
+
+ signal clk : std_logic;
+ signal reset : std_logic;
+ signal we : std_logic;
+ signal re : std_logic;
+ signal d_in : std_logic_vector (7 downto 0) := (others => '0');
+ signal d_out : std_logic_vector (7 downto 0);
+ signal length : std_logic_vector (2 downto 0);
+ signal overflow : std_logic;
+
+ constant period : time := 1 us;
+ constant offset : time := 2 us;
+
+begin
+ UUT : fifo port map (
+ clk => clk,
+ reset => reset,
+ we => we,
+ re => re,
+ d_in => d_in,
+ d_out => d_out,
+ overflow => overflow
+ );
+
+ process
+ begin
+ clk <= '0';
+ wait for offset;
+
+ loop
+ clk <= '1';
+ wait for period/2;
+ clk <= '0';
+ wait for period/2;
+ end loop;
+ end process;
+
+
+ process
+ begin
+ reset <= '0';
+ wait for period;
+ reset <= '1';
+ wait for period;
+ reset <= '0';
+ wait;
+ end process;
+
+
+ process
+ begin
+ we <= '0';
+ re <= '0';
+ d_in <= "00000000";
+
+ wait for 0.1 * period;
+
+ wait for 2 * period;
+ d_in <= "01000001";
+ we <= '1';
+
+ wait for period;
+ d_in <= "01000010";
+
+ wait for period;
+ d_in <= "01000011";
+
+ wait for period;
+ d_in <= "01000011";
+
+ wait for period;
+ d_in <= "01000101";
+
+ wait for period;
+ we <= '0';
+
+ wait for 2 * period;
+ re <= '1';
+
+ wait for period;
+ re <= '0';
+
+ wait;
+ end process;
+
+end testbench;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity tb_tx is
+end tb_tx;
+
+
+architecture testbench of tb_tx is
+
+ component transmitter is
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ data : in std_logic_vector (7 downto 0);
+ we : in std_logic;
+ ready : out std_logic;
+ tx : out std_logic
+ );
+ end component;
+
+ signal clk : std_logic;
+ signal reset : std_logic;
+ signal data : std_logic_vector (7 downto 0) := (others => '0');
+ signal we : std_logic := '0';
+ signal ready : std_logic;
+ signal tx : std_logic;
+
+ constant period : time := 2 us;
+ constant offset : time := 2 us;
+
+begin
+ UUT : transmitter port map (
+ clk => clk,
+ reset => reset,
+ data => data,
+ we => we,
+ ready => ready,
+ tx => tx
+ );
+
+ process
+ begin
+ clk <= '0';
+ wait for offset;
+
+ loop
+ clk <= '1';
+ wait for period/2;
+ clk <= '0';
+ wait for period/2;
+ end loop;
+ end process;
+
+
+ process
+ begin
+ reset <= '0';
+ wait for 1.5 * period;
+ reset <= '1';
+ wait for 1 * period;
+ reset <= '0';
+ wait;
+ end process;
+
+
+ process
+ begin
+ wait until reset = '0';
+ wait for 0.1 * period;
+
+ wait until ready = '1';
+ data <= "01000001";
+ we <= '1';
+ wait until ready = '0';
+ data <= "00000000";
+ we <= '0';
+
+
+ wait until ready = '1';
+ wait for 1.5 * period;
+ data <= "01000010";
+ we <= '1';
+ wait until ready = '0';
+ data <= "00000000";
+ we <= '0';
+
+ wait;
+ end process;
+
+end testbench;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity tb_uart is
+end tb_uart;
+
+
+architecture testbench of tb_uart is
+
+ component uart is
+ generic (
+ output_fifo_width : integer
+ );
+ port (
+ mclk : in std_logic;
+ per_addr : in std_logic_vector (7 downto 0);
+ per_din : in std_logic_vector (15 downto 0);
+ per_en : in std_logic;
+ per_wen : in std_logic_vector (1 downto 0);
+ puc : in std_logic;
+ --per_irq_acc : in std_logic;
+ --per_irq : out std_logic;
+ per_dout : out std_logic_vector (15 downto 0);
+
+ txd : out std_logic
+ );
+ end component;
+
+ signal clk : std_logic;
+ signal reset : std_logic;
+
+ constant period : time := 1 us;
+ constant offset : time := 2 us;
+
+
+ signal per_addr : std_logic_vector (7 downto 0);
+ signal per_din : std_logic_vector (15 downto 0);
+ signal per_en : std_logic;
+ signal per_wen : std_logic_vector (1 downto 0);
+ signal per_dout : std_logic_vector (15 downto 0);
+
+ signal txd : std_logic;
+
+
+ type test_record is record
+ we : std_logic;
+ word : std_logic;
+ data : std_logic_vector (15 downto 0);
+ addr : std_logic_vector (15 downto 0);
+ end record;
+
+ type test_array is array (positive range <>) of test_record;
+
+ constant test_vectors : test_array := (
+ ('1','1',X"0002",X"0100"),
+ ('1','0',X"0065",X"0102")
+ );
+
+--------------------------------------------------------------------------------
+
+begin
+ UUT : uart port map (
+ mclk => clk,
+ per_addr => per_addr,
+ per_din => per_din,
+ per_en => per_en,
+ per_wen => per_wen,
+ puc => reset,
+ per_dout => per_dout,
+
+ txd => txd
+ );
+
+
+ process
+ begin
+ clk <= '0';
+ wait for offset;
+
+ loop
+ clk <= '1';
+ wait for period/2;
+ clk <= '0';
+ wait for period/2;
+ end loop;
+ end process;
+
+
+ process
+ begin
+ reset <= '0';
+ wait for period;
+ reset <= '1';
+ wait for period;
+ reset <= '0';
+ wait;
+ end process;
+
+
+ process
+ variable vector : test_record;
+ begin
+ per_addr <= X"00";
+ per_din <= X"0000";
+ per_en <= '0';
+ per_wen <= "00";
+
+ wait for 3.1 * period;
+
+
+ for i in test_vectors'range loop
+ vector := test_vectors(i);
+
+ per_addr <= vector.addr (8 downto 1);
+ per_en <= '1';
+
+ if (vector.word = '1') then
+ per_wen <= "11";
+ per_din <= vector.data (15 downto 0);
+
+ else
+ if (vector.addr(0) = '1') then
+ per_wen <= "10";
+ per_din <= vector.data (7 downto 0) & "00000000";
+ else
+ per_wen <= "01";
+ per_din <= "00000000" & vector.data (7 downto 0);
+ end if;
+ end if;
+
+ wait for period;
+
+ per_addr <= X"00";
+ per_din <= X"0000";
+ per_en <= '0';
+ per_wen <= "00";
+ end loop;
+
+ wait;
+ end process;
+
+end testbench;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity transmitter is
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ data : in std_logic_vector (7 downto 0);
+ we : in std_logic;
+ ready : out std_logic;
+ tx : out std_logic
+ );
+end transmitter;
+
+--------------------------------------------------------------------------------
+
+architecture dataflow of transmitter is
+
+ -- Output shift register (containing also start and stop bit).
+ signal tx_shift_reg : std_logic_vector (9 downto 0);
+ -- Register parallel to the output shift register where '1' shows the last
+ -- bit of the frame ('1' is in the place of stop bit).
+ signal tx_flag : std_logic_vector (9 downto 0);
+ -- Transmitting of new frame could be started with next tx_clk.
+ signal tx_ready : std_logic;
+
+--------------------------------------------------------------------------------
+
+begin
+
+ process (clk, reset)
+ begin
+ if (reset = '1') then
+ tx_shift_reg <= "1111111111";
+ tx_flag <= "0000000000";
+ tx_ready <= '1';
+
+ elsif (rising_edge(clk)) then
+ if (we = '1') then
+ tx_shift_reg <= '1' & data & '0';
+ tx_flag <= "1000000000";
+ tx_ready <= '0';
+
+ else
+ tx_shift_reg <= '1' & tx_shift_reg(9 downto 1);
+ tx_flag <= '0' & tx_flag(9 downto 1);
+
+ if (tx_flag(1) = '1') then
+ tx_ready <= '1';
+ end if;
+
+ end if;
+ end if;
+ end process;
+
+--------------------------------------------------------------------------------
+
+ ready <= tx_ready;
+
+ tx <= tx_shift_reg(0);
+
+end dataflow;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity tx_control is
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ tx_ready : in std_logic;
+ fifo_empty : in std_logic;
+ tx_we : out std_logic;
+ fifo_pop : out std_logic
+ );
+end tx_control;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of tx_control is
+
+ type state_t is (waiting, next_frame, transmitting);
+
+ signal state : state_t;
+
+--------------------------------------------------------------------------------
+
+begin
+
+ process (clk, reset)
+ begin
+ if (reset = '1') then
+ state <= waiting;
+
+ elsif (rising_edge(clk)) then
+ case state is
+ when waiting =>
+ if (fifo_empty = '0') then
+ state <= next_frame;
+ end if;
+
+ when next_frame =>
+ if (tx_ready = '0') then
+ state <= transmitting;
+ end if;
+
+ when transmitting =>
+ if (tx_ready = '1') then
+ if (fifo_empty = '0') then
+ state <= next_frame;
+ else
+ state <= waiting;
+ end if;
+ end if;
+ end case;
+ end if;
+ end process;
+
+
+ process (state, tx_ready)
+ begin
+ case state is
+ when waiting =>
+ tx_we <= '0';
+ fifo_pop <= '0';
+
+ when next_frame =>
+ tx_we <= '1';
+ if (tx_ready = '0') then
+ fifo_pop <= '1';
+ else
+ fifo_pop <= '0';
+ end if;
+
+ when transmitting =>
+ tx_we <= '0';
+ fifo_pop <= '0';
+ end case;
+ end process;
+
+--------------------------------------------------------------------------------
+
+end behavioral;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity uart is
+ generic (
+ output_fifo_width : integer := 2
+ );
+ port (
+ mclk : in std_logic;
+ per_addr : in std_logic_vector (7 downto 0);
+ per_din : in std_logic_vector (15 downto 0); -- unused
+ per_en : in std_logic;
+ per_wen : in std_logic_vector (1 downto 0); -- unused
+ puc : in std_logic; -- unused
+ --per_irq_acc : in std_logic; -- unused
+ --per_irq : out std_logic;
+ per_dout : out std_logic_vector (15 downto 0);
+
+ txd : out std_logic
+ );
+end uart;
+
+-- Registers:
+-- - Prescaler .16b
+-- - Modulator .8b
+-- - TX data .8b
+-- - TX enable
+-- - TX buffer full .1b
+-- - TX buffer empty .1b
+-- - TX buffer empty IE 1.b
+-- - RX data .8b
+-- - RX enable
+-- - RX buffer empty .1b
+-- - RX buffer half full .1b
+-- - RX buffer full .1b
+-- - RX buffer half full IE .1b
+-- - RX buffer full IE .1b
+-- - RX framing error .1b
+-- - RX buffer overflow .1b
+
+--------------------------------------------------------------------------------
+
+architecture dataflow of uart is
+
+ component tx_control is
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ tx_ready : in std_logic;
+ fifo_empty : in std_logic;
+ tx_we : out std_logic;
+ fifo_pop : out std_logic
+ );
+ end component;
+
+ component transmitter is
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ data : in std_logic_vector (7 downto 0);
+ we : in std_logic;
+ ready : out std_logic;
+ tx : out std_logic
+ );
+ end component;
+
+ component fifo is
+ generic (
+ width : integer := 2
+ );
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ we : in std_logic;
+ re : in std_logic;
+ d_in : in std_logic_vector (7 downto 0);
+ d_out : out std_logic_vector (7 downto 0);
+ full : out std_logic;
+ hfull : out std_logic;
+ empty : out std_logic;
+ overflow : out std_logic
+ );
+ end component;
+
+ component baud_gen is
+ port (
+ clk : in std_logic;
+ reset : in std_logic;
+ scale : in std_logic_vector (15 downto 0);
+ clk_baud : out std_logic
+ );
+ end component;
+
+--------------------------------------------------------------------------------
+
+ type boolean_vector is array (natural range <>) of boolean;
+
+--------------------------------------------------------------------------------
+
+ constant base_addr : integer := 16#0100#;
+
+ constant UBAUD : integer := base_addr + 00;
+ constant UTX : integer := base_addr + 02;
+
+ signal reg_we : std_logic_vector (511 downto 0);
+ signal reg_re : boolean_vector (511 downto 0);
+
+ signal tx_clk : std_logic;
+ signal tx_data : std_logic_vector (7 downto 0);
+ signal tx_we : std_logic;
+ signal tx_ready : std_logic;
+
+ signal tx_fifo_empty : std_logic;
+ signal tx_fifo_re : std_logic;
+ signal tx_fifo_we : std_logic;
+
+--------------------------------------------------------------------------------
+
+begin
+
+ process (per_addr, per_wen, per_en)
+ begin
+ for i in reg_re'range loop
+ reg_re (i) <= false;
+ reg_we (i) <= '0';
+
+ if (per_en = '1' and per_addr = i/2) then
+ reg_re (i) <= true;
+
+ if (per_wen (i mod 2) = '1') then
+ reg_we (i) <= '1';
+ end if;
+ end if;
+ end loop;
+ end process;
+
+
+ tx_control_0 : tx_control port map (
+ clk => mclk,
+ reset => puc,
+ tx_ready => tx_ready,
+ fifo_empty => tx_fifo_empty,
+ tx_we => tx_we,
+ fifo_pop => tx_fifo_re
+ );
+
+ transmitter_0 : transmitter port map (
+ clk => tx_clk,
+ reset => puc,
+ data => tx_data,
+ we => tx_we,
+ ready => tx_ready,
+ tx => txd
+ );
+
+ tx_fifo : fifo port map (
+ clk => mclk,
+ reset => puc,
+ we => tx_fifo_we,
+ re => tx_fifo_re,
+ d_in => per_din (7 downto 0),
+ d_out => tx_data,
+ full => open,
+ hfull => open,
+ empty => tx_fifo_empty,
+ overflow => open
+ );
+
+ baud_gen_0 : baud_gen port map (
+ clk => mclk,
+ reset => puc,
+ scale => "0000000000000000",
+ clk_baud => tx_clk
+ );
+
+
+--------------------------------------------------------------------------------
+
+ tx_fifo_we <= reg_we (UTX);
+
+end dataflow;
+