OpenCores
URL https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [uart.vhd] - Diff between revs 3 and 5

Show entire file | Details | Blame | View Log

Rev 3 Rev 5
Line 1... Line 1...
--------------------------------------------------------------------------------
-- FILE:      uart.vhd
--| @file uart.vhd
-- BRIEF:     UART TX/RX module
--| @brief implements a universal asynchronous receiver transmitter with
-- LICENSE:   MIT
--| parameterisable baud rate. tested on a spartan 6 lx9 connected to a
-- COPYRIGHT: Richard James Howe (2019)
--| silicon labs cp210 usb-uart bridge.
--
--|
-- The UART (Universal Asynchronous Receiver/Transmitter) is one of the simplest
--| @author         peter a bennett
-- serial communication methods available. It is often used for debugging, for
--| @copyright      (c) 2012 peter a bennett
-- issuing commands to embedded devices and sometimes even for uploading firmware
--| @license        Apache 2.0
-- to devices. The data format and speed are configurable but there is no method
--| @email          pab850@googlemail.com
-- for automatically configuring a UART, both sides must have agreed on the
--| @contact        www.bytebash.com
-- settings before hand. Configurable options include; baud, use of an
--|
-- even of odd parity bit, number of data bits and number of stop bits.
--| See https://github.com/pabennett/uart
--
--|
-- The clock is not transmitted as part of the signal (which is why baud
--| There have been many changes to the original code, consult the git logs
-- must be agreed upon before hand), a single packet starts with a 'start bit',
--| for a full list of changes.
-- where the line goes low. The receiver must synchronize to this start bit (it
--|
-- resets the clock that generates pulse at the sample rate and baud when it
--| @note Changes made to range to stop Xilinx warnings and with formatting,
-- encounters a start bit).
--| the UART has also been wrapped up in a package and top level component
--
--| (called "uart_top") to make the interface easier to use and less confusing.
-- A transmission with 8 data bits, 1 parity bit and 1 stop bit looks like
--| This has not be tested yet.
-- this:
--|
-- ____   ______________________________   ________________
--| @note Somewhere along the chain from the computer, to the Nexys3 board,
--     \_/|0|1|2|3|4|5|6|7|P|S|         \_/
--| to the UART module, and finally to the H2 core, bytes are being lost in
--     Start   Data     Parity Stop    |--- More data --->
--| transmission from the computer. This UART really should be buffered
--
--| as well.
-- Start bits are always low, stop bits high. The most common format is
--|
-- 8 data bits, no parity bit, and 1 stop bit at either 9600 or 115200 baud.
--|  START 0 1 2 3 4 5 6 7 STOP
--
--| ----\_/-|-|-|-|-|-|-|-|-|-------
-- For the receiver a clock that is a multiple of the baud is used so the
--|
-- bits can be sampled with a higher frequency than the bit rate.
--------------------------------------------------------------------------------
--
library ieee;
-- Some notes:
 
-- * We can transmit from an 8-bit UART to a less than 8-bit UART fine, so
 
-- long as parity is not used, as
 
-- * Certain UARTs have the ability to transmit a BREAK signal by holding
 
-- the line low for a period greater than the packet length. We can transmit
 
-- that by lowering the baud rate and transmitting all zeroes. Receiving a
 
-- break (correctly) would require changing the receiver.
 
--
 
--
 
-- See:
 
-- * <https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter>
 
--
 
-- NOTE: We could replace this entire package with an entirely software driven
 
-- solution. The only hardware we would need two timers driven at the sample
 
-- rate (one for RX, one for TX) and a deglitched RX signal. An interrupt
 
-- would be generated on the timers expiry.
 
library ieee, work;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
 
use ieee.numeric_std.all;
 
use work.util.common_generics;
 
 
package uart_pkg is
package uart_pkg is
 
        constant uart_8N1: std_ulogic_vector(7 downto 0) := "10000100";
 
 
        component uart_top is
        component uart_tx is
        generic (baud_rate: positive; clock_frequency: positive; fifo_depth: positive := 8);
                generic (g: common_generics; N: positive; format: std_ulogic_vector(7 downto 0) := uart_8N1);
        port (
        port (
                clk:                 in      std_ulogic;
                clk:                 in      std_ulogic;
                rst:                 in      std_ulogic;
                rst:                 in      std_ulogic;
 
                        cr:    out std_ulogic;
 
                        baud:   in std_ulogic; -- Pulse at baud
 
                        tx:    out std_ulogic;
 
                        ok:    out std_ulogic;
 
                        ctr:    in std_ulogic_vector(format'range);
 
                        ctr_we: in std_ulogic;
 
                        we:     in std_ulogic; -- di write enable
 
                        di:     in std_ulogic_vector(N - 1 downto 0));
 
        end component;
 
 
                rx_data:             out     std_ulogic_vector(7 downto 0);
        component uart_rx is
                rx_fifo_empty:       out     std_ulogic;
                generic (g: common_generics; N: positive; D: positive; format: std_ulogic_vector(7 downto 0) := uart_8N1);
                rx_fifo_full:        out     std_ulogic;
                port (
                rx_data_re:          in      std_ulogic;
                        clk:     in std_ulogic;
 
                        rst:     in std_ulogic;
 
                        cr:     out std_ulogic;
 
                        baud, sample: in std_ulogic;
 
                        failed: out std_ulogic_vector(1 downto 0);
 
                        ctr:    in std_ulogic_vector(7 downto 0);
 
                        ctr_we: in std_ulogic;
 
                        rx:     in std_ulogic;
 
                        we:    out std_ulogic;
 
                        do:    out std_ulogic_vector(N - 1 downto 0));
 
        end component;
 
 
                tx_data:             in      std_ulogic_vector(7 downto 0);
        component uart_baud is -- Generates a pulse at the sample rate and baud
                tx_fifo_full:        out     std_ulogic;
                generic (g: common_generics; init: integer; N: positive := 16; D: positive := 3);
                tx_fifo_empty:       out     std_ulogic;
                port (
                tx_data_we:          in      std_ulogic;
                        clk:      in std_ulogic;
 
                        rst:      in std_ulogic;
 
                        we:       in std_ulogic;
 
                        cnt:      in std_ulogic_vector(N - 1 downto 0);
 
                        cr:       in std_ulogic := '0';
 
                        sample:  out std_ulogic;
 
                        baud:    out std_ulogic);
 
        end component;
 
 
                tx:                  out     std_ulogic;
        component uart_core is
                rx:                  in      std_ulogic);
                generic (g: common_generics; baud: positive := 115200; format: std_ulogic_vector(7 downto 0) := uart_8N1);
 
                port (
 
                        clk:    in std_ulogic;
 
                        rst:    in std_ulogic;
 
 
 
                        tx:    out std_ulogic;
 
                        tx_ok: out std_ulogic;
 
                        tx_we:  in std_ulogic;
 
                        tx_di:  in std_ulogic_vector(7 downto 0);
 
 
 
                        rx:     in std_ulogic;
 
                        rx_ok: out std_ulogic;
 
                        rx_nd: out std_ulogic;
 
                        rx_re:  in std_ulogic;
 
                        rx_do: out std_ulogic_vector(7 downto 0);
 
 
 
                        reg:             in std_ulogic_vector(15 downto 0);
 
                        clock_reg_tx_we: in std_ulogic;
 
                        clock_reg_rx_we: in std_ulogic;
 
                        control_reg_we:  in std_ulogic);
        end component;
        end component;
 
 
        component uart_core is
        component uart_top is
                generic (baud_rate: positive; clock_frequency: positive);
                generic (
 
                        g:        common_generics;
 
                        baud:     positive := 115200;
 
                        format:   std_ulogic_vector(7 downto 0) := uart_8N1;
 
                        use_fifo: boolean := false);
                port (
                port (
                        clk:       in      std_ulogic;
                        clk:       in      std_ulogic;
                        rst:       in      std_ulogic;
                        rst:       in      std_ulogic;
                        din:       in      std_ulogic_vector(7 downto 0);
 
                        din_stb:   in      std_ulogic;
 
                        din_ack:   out     std_ulogic := '0';
 
                        din_busy:  out     std_ulogic;
 
 
 
                        dout:      out     std_ulogic_vector(7 downto 0);
 
                        dout_stb:  out     std_ulogic;
 
                        dout_ack:  in      std_ulogic;
 
                        dout_busy: out     std_ulogic;
 
 
 
                        tx:        out     std_ulogic;
                        tx:        out     std_ulogic;
                        rx:        in      std_ulogic);
                        tx_fifo_full:  out std_ulogic;
 
                        tx_fifo_empty: out std_ulogic;
 
                        tx_fifo_we:     in std_ulogic;
 
                        tx_fifo_data:   in std_ulogic_vector(7 downto 0);
 
 
 
                        rx:             in std_ulogic;
 
                        rx_fifo_full:  out std_ulogic;
 
                        rx_fifo_empty: out std_ulogic;
 
                        rx_fifo_re:     in std_ulogic;
 
                        rx_fifo_data:  out std_ulogic_vector(7 downto 0);
 
 
 
                        reg:             in std_ulogic_vector(15 downto 0);
 
                        clock_reg_tx_we: in std_ulogic;
 
                        clock_reg_rx_we: in std_ulogic;
 
                        control_reg_we:  in std_ulogic);
        end component;
        end component;
 
 
end package;
        component uart_tb is
 
                generic(g: common_generics);
 
        end component;
 
 
---- UART Package --------------------------------------------------------------
        constant ctr_use_parity:  integer := 0;
 
        constant ctr_even_parity: integer := 1;
 
        function ctr_stop_bits(ctr: std_ulogic_vector(7 downto 0)) return integer;
 
        function ctr_data_bits(ctr: std_ulogic_vector(7 downto 0)) return integer;
 
end package;
 
 
---- UART Top ------------------------------------------------------------------
package body uart_pkg is
 
        function ctr_stop_bits(ctr: std_ulogic_vector(7 downto 0)) return integer is
 
                variable ii: std_ulogic_vector(1 downto 0);
 
        begin
 
                ii := ctr(3 downto 2);
 
                return to_integer(unsigned(ii));
 
        end function;
 
 
 
        function ctr_data_bits(ctr: std_ulogic_vector(7 downto 0)) return integer is
 
                variable ii: std_ulogic_vector(3 downto 0);
 
        begin
 
                ii := ctr(7 downto 4);
 
                return to_integer(unsigned(ii));
 
        end function;
 
end;
 
 
library ieee;
library ieee, work;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.numeric_std.all;
use work.util.fifo;
use work.uart_pkg.all;
use work.uart_pkg.uart_core;
use work.util.common_generics;
 
 
entity uart_top is
entity uart_top is
        generic (baud_rate: positive; clock_frequency: positive; fifo_depth: positive := 8);
        generic (
 
                g: common_generics;
 
                baud: positive := 115200;
 
                format: std_ulogic_vector(7 downto 0) := uart_8N1;
 
                use_fifo: boolean := false);
        port (
        port (
                clk:                 in      std_ulogic;
                clk:                 in      std_ulogic;
                rst:                 in      std_ulogic;
                rst:                 in      std_ulogic;
 
 
                rx_data:             out     std_ulogic_vector(7 downto 0);
                tx:            out std_ulogic;
                rx_fifo_empty:       out     std_ulogic;
 
                rx_fifo_full:        out     std_ulogic;
 
                rx_data_re:          in      std_ulogic;
 
 
 
                tx_data:             in      std_ulogic_vector(7 downto 0);
 
                tx_fifo_full:        out     std_ulogic;
                tx_fifo_full:        out     std_ulogic;
                tx_fifo_empty:       out     std_ulogic;
                tx_fifo_empty:       out     std_ulogic;
                tx_data_we:          in      std_ulogic;
                tx_fifo_we:     in std_ulogic;
 
                tx_fifo_data:   in std_ulogic_vector(7 downto 0);
 
 
                tx:                  out     std_ulogic;
                rx:             in std_ulogic;
                rx:                  in      std_ulogic);
                rx_fifo_full:  out std_ulogic;
 
                rx_fifo_empty: out std_ulogic;
 
                rx_fifo_re:     in std_ulogic;
 
                rx_fifo_data:  out std_ulogic_vector(7 downto 0);
 
 
 
                reg:             in std_ulogic_vector(15 downto 0);
 
                clock_reg_tx_we: in std_ulogic;
 
                clock_reg_rx_we: in std_ulogic;
 
                control_reg_we:  in std_ulogic);
end entity;
end entity;
 
 
architecture behav of uart_top is
architecture structural of uart_top is
        signal rx_sync, rx_uart, tx_uart: std_ulogic := '0';
        constant fifo_depth: positive := 8;
 
        signal rx_ok, rx_nd, rx_push, rx_re: std_ulogic;
 
        signal rx_pushed: std_ulogic_vector(rx_fifo_data'range);
 
        signal tx_pop, tx_ok: std_ulogic;
 
        signal tx_popped: std_ulogic_vector(tx_fifo_data'range);
 
        signal tx_fifo_empty_b, rx_fifo_full_b: std_ulogic;
 
begin
 
        uart_core_0: work.uart_pkg.uart_core
 
                generic map(g => g, baud => baud, format => format)
 
                port map(
 
                        clk => clk,
 
                        rst => rst,
 
 
        signal din:       std_ulogic_vector(7 downto 0) := (others => '0');
                        tx    => tx,
        signal din_stb:   std_ulogic := '0';
                        tx_we => tx_pop,
        signal din_ack:   std_ulogic := '0';
                        tx_di => tx_popped,
        signal din_busy:  std_ulogic := '0';
                        tx_ok => tx_ok,
 
 
 
                        rx    => rx,
 
                        rx_nd => rx_nd,
 
                        rx_ok => rx_ok,
 
                        rx_do => rx_pushed,
 
                        rx_re => rx_push,
 
 
 
                        reg => reg,
 
                        clock_reg_rx_we => clock_reg_rx_we,
 
                        clock_reg_tx_we => clock_reg_tx_we,
 
                        control_reg_we  => control_reg_we);
 
 
 
        ugen0: if not use_fifo generate
 
                        tx_pop        <= tx_fifo_we;
 
                        tx_popped     <= tx_fifo_data;
 
                        tx_fifo_full  <= not tx_ok;
 
                        tx_fifo_empty <= tx_ok;
 
 
 
                        rx_push       <= rx_fifo_re;
 
                        rx_fifo_data  <= rx_pushed;
 
                        rx_fifo_full  <= rx_nd;
 
                        rx_fifo_empty <= not rx_nd;
 
        end generate;
 
 
 
        ugen1: if use_fifo generate
 
                tx_fifo_empty <=               tx_fifo_empty_b;
 
                tx_pop        <= tx_ok and not tx_fifo_empty_b;
 
                uart_fifo_tx_0: work.util.fifo
 
                        generic map(g => g,
 
                                   data_width => tx_fifo_data'length,
 
                                   fifo_depth => fifo_depth)
 
                        port map (clk  => clk, rst => rst,
 
                                  di   => tx_fifo_data,
 
                                  we   => tx_fifo_we,
 
                                  re   => tx_pop,
 
                                  do   => tx_popped,
 
                                  full => tx_fifo_full, empty => tx_fifo_empty_b);
 
 
 
                rx_fifo_full <=                         rx_fifo_full_b;
 
                rx_push      <= rx_nd and rx_ok and not rx_fifo_full_b;
 
                uart_fifo_rx_0: work.util.fifo
 
                        generic map(g => g,
 
                                   data_width => rx_fifo_data'length,
 
                                   fifo_depth => fifo_depth,
 
                                   read_first => false)
 
                        port map (clk  => clk, rst => rst,
 
                                  di   => rx_pushed,
 
                                  we   => rx_push,
 
                                  re   => rx_fifo_re,
 
                                  do   => rx_fifo_data,
 
                                  full => rx_fifo_full_b, empty => rx_fifo_empty);
 
        end generate;
 
end architecture;
 
 
        signal dout:      std_ulogic_vector(7 downto 0) := (others => '0');
library ieee, work;
        signal dout_stb:  std_ulogic := '0';
use ieee.std_logic_1164.all;
        signal dout_ack:  std_ulogic := '0';
use ieee.numeric_std.all;
        signal dout_busy: std_ulogic := '0';
use work.uart_pkg.all;
 
use work.util.common_generics;
 
 
        signal tx_fifo_re:             std_ulogic := '0';
entity uart_core is
        signal tx_fifo_empty_internal: std_ulogic := '1';
        generic (
        signal tx_fifo_full_internal:  std_ulogic := '0';
                g: common_generics;
 
                baud: positive := 115200;
 
                format: std_ulogic_vector(7 downto 0) := uart_8N1);
 
        port (
 
                clk:    in std_ulogic;
 
                rst:    in std_ulogic;
 
 
        signal wrote_c, wrote_n: std_ulogic := '0';
                tx:    out std_ulogic; -- physical UART TX signal
 
                tx_ok: out std_ulogic; -- not busy
 
                tx_we:  in std_ulogic; -- write data
 
                tx_di:  in std_ulogic_vector(7 downto 0);
 
 
 
                rx:     in std_ulogic; -- physical UART RX signal
 
                rx_ok: out std_ulogic; -- data has no errors (parity or frame)
 
                rx_re:  in std_ulogic; -- read data
 
                rx_nd: out std_ulogic; -- new data available
 
                rx_do: out std_ulogic_vector(7 downto 0);
 
 
 
                reg:             in std_ulogic_vector(15 downto 0);
 
                clock_reg_tx_we: in std_ulogic;
 
                clock_reg_rx_we: in std_ulogic;
 
                control_reg_we:  in std_ulogic);
 
end entity;
 
 
begin
architecture structural of uart_core is
        uart_deglitch: process (clk, rst)
        constant tx_init: integer  := g.clock_frequency / (baud * 16); -- 54 = 115200 @ 100 MHz
        begin
        constant rx_init: positive := tx_init - 1; -- 50 = 115200 @ 100 MHz + Fudge Factor
                if rst = '1' then
        constant N: positive := 8;
                        wrote_c <= '0';
        signal tx_sample, tx_baud, tx_cr: std_ulogic;
 
        signal rx_sample, rx_baud, rx_cr, rx_we: std_ulogic;
 
        signal rx_fail: std_ulogic_vector(1 downto 0);
 
        signal rx_ok_buf: std_ulogic;
 
        signal do, do_c, do_n: std_ulogic_vector(rx_do'range);
 
        signal fail_c, fail_n: std_ulogic_vector(1 downto 0);
 
        signal nd_c, nd_n: std_ulogic; -- new data
 
begin
 
        rx_ok_buf <= not (fail_c(0) or fail_c(1)) after g.delay;
 
        rx_ok <= rx_ok_buf;
 
        rx_do <= do after g.delay;
 
        rx_nd <= nd_c and rx_ok_buf after g.delay; -- no new data if there are errors
 
 
 
        process (clk, rst)
 
        begin
 
                if rst = '1' and g.asynchronous_reset then
 
                        do_c   <= (others => '0') after g.delay;
 
                        fail_c <= (others => '0') after g.delay;
 
                        nd_c   <= '0' after g.delay;
                elsif rising_edge(clk) then
                elsif rising_edge(clk) then
                        rx_sync <= rx;
                        if rst = '1' and not g.asynchronous_reset then
                        rx_uart <= rx_sync;
                                do_c   <= (others => '0') after g.delay;
                        tx      <= tx_uart;
                                fail_c <= (others => '0') after g.delay;
                        wrote_c <= wrote_n;
                                nd_c   <= '0' after g.delay;
 
                        else
 
                                do_c <= do_n     after g.delay;
 
                                nd_c <= nd_n     after g.delay;
 
                                fail_c <= fail_n after g.delay;
 
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
        process(dout_stb, tx_fifo_empty_internal, tx_fifo_full_internal, din_ack, wrote_c, din_busy)
        process (do_c, do, nd_c, rx_we, rx_re, fail_c, rx_fail)
        begin
        begin
                        dout_ack    <= '0';
                do_n   <= do_c   after g.delay;
                        din_stb     <= '0';
                nd_n   <= nd_c   after g.delay;
                        tx_fifo_re  <= '0';
                fail_n <= fail_c after g.delay;
                        wrote_n     <= wrote_c;
                if rx_we = '1' then
 
                        nd_n   <= '1'     after g.delay;
                        if dout_stb = '1' then
                        do_n   <= do      after g.delay;
                                dout_ack <= '1';
                        fail_n <= rx_fail after g.delay;
                        end if;
                elsif rx_re = '1' then
 
                        nd_n   <= '0' after g.delay;
                        if tx_fifo_empty_internal = '0' and tx_fifo_full_internal = '0' and din_busy = '0' then
 
                                tx_fifo_re <= '1';
 
                                wrote_n    <= '1';
 
                        elsif din_ack = '0' and wrote_c = '1' then
 
                        --elsif wrote_c = '1' then
 
                                -- assert din_ack = '1' on the next cycle?
 
                                din_stb    <= '1';
 
                                wrote_n    <= '0';
 
                        end if;
                        end if;
        end process;
        end process;
 
 
        rx_fifo: work.util.fifo
        baud_tx: work.uart_pkg.uart_baud
                generic map (
                generic map(g => g, init => tx_init, N => reg'length, D => 3)
                        data_width => 8,
 
                        fifo_depth => fifo_depth)
 
                port map(
                port map(
                        clk   => clk,
                        clk   => clk,
                        rst   => rst,
                        rst   => rst,
                        di    => dout,
                        we     => clock_reg_tx_we,
                        we    => dout_stb,
                        cnt    => reg,  -- 0x32/50 is 152000 @ 100MHz clk
                        re    => rx_data_re,
                        cr     => tx_cr,
                        do    => rx_data,
                        sample => tx_sample,
                        full  => rx_fifo_full,
                        baud   => tx_baud);
                        empty => rx_fifo_empty);
 
 
        baud_rx: work.uart_pkg.uart_baud
        tx_fifo: work.util.fifo
                generic map(g => g, init => rx_init, N => reg'length, D => 3)
                generic map (
 
                        data_width => 8,
 
                        fifo_depth => fifo_depth)
 
                port map(
                port map(
                        clk   => clk,
                        clk   => clk,
                        rst   => rst,
                        rst   => rst,
                        di    => tx_data,
                        we     => clock_reg_rx_we,
                        we    => tx_data_we,
                        cnt    => reg,
                        re    => tx_fifo_re,
                        cr     => rx_cr,
                        do    => din,
                        sample => rx_sample,
                        full  => tx_fifo_full_internal,
                        baud   => rx_baud);
                        empty => tx_fifo_empty_internal);
 
 
        tx_0: work.uart_pkg.uart_tx
        tx_fifo_empty <= tx_fifo_empty_internal;
                generic map(g => g, N => N, format => format)
        -- @bug This is a hack, it should be just 'tx_fifo_full_internal', but
 
        -- it does not work correctly, so as a temporary hack the busy signal
 
        -- is or'd in so the data source can block until the FIFO is 'not full'
 
        -- and not lose any data thinking it has been transmitted.
 
        tx_fifo_full  <= '1' when tx_fifo_full_internal = '1' or din_busy = '1' else '0';
 
 
 
        uart: work.uart_pkg.uart_core
 
                generic map(
 
                        baud_rate => baud_rate,
 
                        clock_frequency => clock_frequency)
 
                port map(
                port map(
                        clk      => clk,
                        clk      => clk,
                        rst      => rst,
                        rst      => rst,
                        din      => din,
 
                        din_stb  => din_stb,
 
                        din_ack  => din_ack,
 
                        din_busy => din_busy,
 
                        dout     => dout,
 
                        dout_stb => dout_stb,
 
                        dout_ack => dout_ack,
 
                        dout_busy=> dout_busy,
 
                        rx       => rx_uart,
 
                        tx       => tx_uart);
 
 
 
end;
                        cr      => tx_cr,
 
                        baud    => tx_baud,
 
                        ok      => tx_ok,
 
                        we      => tx_we,
 
                        ctr     => reg(reg'high downto reg'high - 7),
 
                        ctr_we  => control_reg_we,
 
                        di      => tx_di,
 
                        tx      => tx);
 
 
---- UART Top ------------------------------------------------------------------
        rx_0: work.uart_pkg.uart_rx
 
                generic map(g => g, N => N, D => 3, format => format)
---- UART Core -----------------------------------------------------------------
                port map(
 
                        clk     => clk,
 
                        rst     => rst,
 
 
library ieee;
                        baud    => rx_baud,
 
                        sample  => rx_sample,
 
                        cr      => rx_cr,
 
                        failed  => rx_fail,
 
                        ctr     => reg(reg'low + 7 downto reg'low),
 
                        ctr_we  => control_reg_we,
 
                        we      => rx_we,
 
                        do      => do,
 
                        rx      => rx);
 
end architecture;
 
 
 
-- This module generates a sample pulse and a baud pulse. The sample rate
 
-- can be controlled by setting 'cnt'. This sample rate is then divided by
 
-- 2^(D+1) to get the baud.
 
library ieee, work;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.numeric_std.all;
 
use work.uart_pkg.all;
 
use work.util.common_generics;
 
 
entity uart_core is
entity uart_baud is
        generic(baud_rate: positive; clock_frequency: positive);
        generic (g: common_generics; init: integer; N: positive := 16; D: positive := 3);
        port(
        port(
                clk:       in      std_ulogic;
                clk:       in      std_ulogic;
                rst:       in      std_ulogic;
                rst:       in      std_ulogic;
                din:       in      std_ulogic_vector(7 downto 0);
 
                din_stb:   in      std_ulogic;
 
                din_ack:   out     std_ulogic := '0';
 
                din_busy:  out     std_ulogic;
 
 
 
                dout:      out     std_ulogic_vector(7 downto 0);
 
                dout_stb:  out     std_ulogic;
 
                dout_ack:  in      std_ulogic;
 
                dout_busy: out     std_ulogic;
 
 
 
                tx:        out     std_ulogic;
                we:      in std_ulogic;
                rx:        in      std_ulogic);
                cnt:     in std_ulogic_vector(N - 1 downto 0);
end entity;
                cr:      in std_ulogic := '0';
 
 
architecture behav of uart_core is
                sample: out std_ulogic;  -- sample pulse
 
                baud:   out std_ulogic); -- baud (sample rate / 2^(D+1))
 
end entity;
 
 
        constant uart_tx_count_max: positive := 7;
architecture behaviour of uart_baud is
        constant uart_rx_count_max: positive := 7;
        constant cmp_init: std_ulogic_vector := std_ulogic_vector(to_unsigned(init, cnt'length));
        ----------------------------------------------------------------------------
        signal cmp_c, cmp_n: std_ulogic_vector(cnt'range)  :=  cmp_init;
        -- baud generation
        signal cnt_c, cnt_n: std_ulogic_vector(cnt'range)  := (others => '0');
        ----------------------------------------------------------------------------
        signal div_c, div_n: std_ulogic_vector(D downto 0) := (others => '0');
        constant c_tx_divider_val: integer := clock_frequency / baud_rate;
        signal pul_c, pul_n: std_ulogic := '0';
        constant c_rx_divider_val: integer := clock_frequency / (baud_rate * 16);
        signal pulse: std_ulogic := '0';
 
begin
        signal baud_counter:            integer range 0 to c_tx_divider_val;
        pulse  <= (not cr) and pul_n and (pul_c xor pul_n) after g.delay; -- rising edge detector
        signal baud_tick:               std_ulogic := '0';
        baud   <= (not cr) and div_n(div_n'high) and (div_c(div_c'high) xor div_n(div_n'high)) after g.delay;
        signal oversample_baud_counter: integer range 0 to c_rx_divider_val := 0;
        sample <= pulse;
        signal oversample_baud_tick:    std_ulogic := '0';
 
 
        process (clk, rst)
        ----------------------------------------------------------------------------
        begin
        -- transmitter signals
                if rst = '1' and g.asynchronous_reset then
        ----------------------------------------------------------------------------
                        cmp_c <= cmp_init after g.delay;
        type    uart_tx_states is (idle,
                        cnt_c <= (others => '0') after g.delay;
                                wait_for_tick,
                        div_c <= (others => '0') after g.delay;
                                send_start_bit,
                        pul_c <= '0' after g.delay;
                                transmit_data,
 
                                send_stop_bit);
 
 
 
        signal  uart_tx_state: uart_tx_states := idle;
 
 
 
        signal  uart_tx_data_block:  std_ulogic_vector(7 downto 0) := (others => '0');
 
        signal  uart_tx_data:        std_ulogic := '1';
 
        signal  uart_tx_count:       integer range 0 to uart_tx_count_max := 0;
 
        signal  uart_rx_data_in_ack: std_ulogic := '0';
 
        ----------------------------------------------------------------------------
 
        -- receiver signals
 
        ----------------------------------------------------------------------------
 
        type    uart_rx_states is (rx_wait_start_synchronise,
 
                                    rx_get_start_bit,
 
                                    rx_get_data,
 
                                    rx_get_stop_bit,
 
                                    rx_send_block);
 
 
 
        signal  uart_rx_state:        uart_rx_states := rx_get_start_bit;
 
        signal  uart_rx_bit:          std_ulogic := '1'; -- @note should the be 0 or 1?
 
        signal  uart_rx_data_block:   std_ulogic_vector(7 downto 0) := (others => '0');
 
        signal  uart_rx_data_vec:     std_ulogic_vector(1 downto 0) := (others => '0');
 
        signal  uart_rx_filter:       unsigned(1 downto 0)  := (others => '1');
 
        signal  uart_rx_count:        integer range 0 to uart_rx_count_max  := 0;
 
        signal  uart_rx_data_out_stb: std_ulogic := '0';
 
        signal  uart_rx_bit_spacing:  unsigned (3 downto 0) := (others => '0');
 
        signal  uart_rx_bit_tick:     std_ulogic := '0';
 
begin
 
 
 
        din_ack  <= uart_rx_data_in_ack;
 
        dout     <= uart_rx_data_block;
 
        dout_stb <= uart_rx_data_out_stb;
 
        tx       <= uart_tx_data;
 
 
 
        din_busy  <= '0' when uart_tx_state = idle else '1';
 
        dout_busy <= '0' when uart_rx_state = rx_get_start_bit or uart_rx_state = rx_send_block else '1';
 
 
 
        -- the input clk is 100MHz, this needs to be divided down to the
 
        -- rate dictated by the baud_rate. for example, if 115200 baud is selected
 
        -- (115200 baud = 115200 bps - 115.2kbps) a tick must be generated once
 
        -- every 1/115200
 
        tx_clk_divider: process (clk, rst)
 
        begin
 
                if rst = '1' then
 
                        baud_counter <= 0;
 
                        baud_tick    <= '0';
 
                elsif rising_edge (clk) then
                elsif rising_edge (clk) then
                        if baud_counter = c_tx_divider_val then
                        if rst = '1' and not g.asynchronous_reset then
                                baud_counter <= 0;
                                cmp_c <= cmp_init after g.delay;
                                baud_tick    <= '1';
                                cnt_c <= (others => '0') after g.delay;
 
                                div_c <= (others => '0') after g.delay;
 
                                pul_c <= '0' after g.delay;
                        else
                        else
                                baud_counter <= baud_counter + 1;
                                cmp_c <= cmp_n after g.delay;
                                baud_tick    <= '0';
                                cnt_c <= cnt_n after g.delay;
 
                                div_c <= div_n after g.delay;
 
                                pul_c <= pul_n after g.delay;
                        end if;
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
        -- get data from din and send it one bit at a time
        process (pulse, div_c, cr, we)
        -- upon each baud tick. lsb first.
 
        -- wait 1 tick, send start bit (0), send data 0-7, send stop bit (1)
 
        uart_send_data: process(clk, rst)
 
        begin
        begin
                if rst = '1' then
                div_n <= div_c after g.delay;
                        uart_tx_data        <= '1';
                if cr = '1' or we = '1' then
                        uart_tx_data_block  <= (others => '0');
                        div_n <= (others => '0') after g.delay;
                        uart_tx_count       <= 0;
                        div_n(div_n'high) <= '1' after g.delay;
                        uart_tx_state       <= idle;
                elsif pulse = '1' then
                        uart_rx_data_in_ack <= '0';
                        div_n <= std_ulogic_vector(unsigned(div_c) + 1) after g.delay;
                elsif rising_edge(clk) then
 
                        uart_rx_data_in_ack <= '0';
 
                        case uart_tx_state is
 
                        when idle =>
 
                                if din_stb = '1' then
 
                                        uart_tx_data_block  <= din;
 
                                        uart_rx_data_in_ack <= '1';
 
                                        uart_tx_state       <= wait_for_tick;
 
                                end if;
 
                        when wait_for_tick =>
 
                                if baud_tick = '1' then
 
                                        uart_tx_state    <= send_start_bit;
 
                                end if;
 
                        when send_start_bit =>
 
                                if baud_tick = '1' then
 
                                        uart_tx_data  <= '0';
 
                                        uart_tx_state <= transmit_data;
 
                                        uart_tx_count <= 0;
 
                                end if;
 
                        when transmit_data =>
 
                                if baud_tick = '1' then
 
                                        if uart_tx_count < uart_tx_count_max then
 
                                                uart_tx_data  <= uart_tx_data_block(uart_tx_count);
 
                                                uart_tx_count <= uart_tx_count + 1;
 
                                        else
 
                                                uart_tx_data  <= uart_tx_data_block(7);
 
                                                uart_tx_count <= 0;
 
                                                uart_tx_state <= send_stop_bit;
 
                                        end if;
 
                                end if;
 
                        when send_stop_bit =>
 
                                if baud_tick = '1' then
 
                                        uart_tx_data <= '1';
 
                                        uart_tx_state <= idle;
 
                                end if;
 
                        when others =>
 
                                uart_tx_data  <= '1';
 
                                uart_tx_state <= idle;
 
                        end case;
 
                end if;
                end if;
        end process;
        end process;
 
 
        -- generate an oversampled tick (baud * 16)
        process (cmp_c, cnt_c, we, cnt, cr)
        oversample_clk_divider: process (clk, rst)
 
        begin
        begin
                if rst = '1' then
                cmp_n <= cmp_c after g.delay;
                        oversample_baud_counter <= 0;
                cnt_n <= cnt_c after g.delay;
                        oversample_baud_tick    <= '0';
 
                elsif rising_edge (clk) then
                if we = '1' then
                        if oversample_baud_counter = c_rx_divider_val then
                        cmp_n <= cnt after g.delay;
                                oversample_baud_counter <= 0;
                        cnt_n <= (others => '0') after g.delay;
                                oversample_baud_tick    <= '1';
                        pul_n <= '0' after g.delay;
 
                elsif cr = '1' then
 
                        cnt_n <= (others => '0') after g.delay;
 
                        pul_n <= '0' after g.delay;
 
                elsif cnt_c = cmp_c then
 
                        cnt_n <= (others => '0') after g.delay;
 
                        pul_n <= '1' after g.delay;
                        else
                        else
                                oversample_baud_counter <= oversample_baud_counter + 1;
                        cnt_n <= std_ulogic_vector(unsigned(cnt_c) + 1) after g.delay;
                                oversample_baud_tick    <= '0';
                        pul_n <= '0' after g.delay;
                        end if;
 
                end if;
                end if;
        end process;
        end process;
 
end architecture;
 
 
 
library ieee, work;
 
use ieee.std_logic_1164.all;
 
use work.uart_pkg.all;
 
use work.util.common_generics;
 
use work.util.parity;
 
 
 
entity uart_rx is
 
        generic (
 
                g: common_generics;
 
                N: positive;
 
                D: positive;
 
                format: std_ulogic_vector(7 downto 0) := uart_8N1);
 
        port (
 
                clk:    in std_ulogic;
 
                rst:    in std_ulogic;
 
                cr:    out std_ulogic;        -- reset sample/baud clock when start bit detected
 
                baud, sample: in std_ulogic; -- pulses at baud and sample rate
 
                failed: out std_ulogic_vector(1 downto 0);
 
                ctr:    in std_ulogic_vector(7 downto 0);
 
                ctr_we: in std_ulogic;
 
                rx:     in std_ulogic;        -- physical RX signal
 
                we:    out std_ulogic;        -- write 'do' to output register
 
                do:    out std_ulogic_vector(N - 1 downto 0));
 
end entity;
 
 
        -- synchronise rxd to the oversampled baud
architecture behaviour of uart_rx is
        rxd_synchronise: process(clk, rst)
        type state is (reset, idle, start, data, parity, stop, done);
 
        signal state_c, state_n: state;
 
        signal ctr_c, ctr_n: std_ulogic_vector(ctr'range);
 
        signal rx_c, rx_n: std_ulogic_vector(do'range);
 
        signal sr_c, sr_n: std_ulogic_vector(D - 1 downto 0);
 
        signal rx_sync: std_ulogic;
 
        signal count_c, count_n: integer range 0 to N - 1;
 
        signal majority: std_ulogic;
 
        signal fail_c, fail_n: std_ulogic_vector(1 downto 0);
 
begin
 
        do     <= rx_c after g.delay;
 
        failed <= fail_c after g.delay;
 
 
 
        assert D < 4 severity failure;
 
 
 
        majority_1: if D = 1 generate
 
                majority <= sr_c(0) after g.delay;
 
        end generate;
 
 
 
        majority_2: if D = 2 generate
 
                majority <= sr_c(0) and sr_c(1) after g.delay; -- even wins is 'sr_c(0) or sr_c(1)'
 
        end generate;
 
 
 
        majority_3: if D = 3 generate
 
                majority <= (sr_c(0) and sr_c(1)) or (sr_c(1) and sr_c(2)) or (sr_c(0) and sr_c(2)) after g.delay;
 
        end generate;
 
 
 
        process (clk, rst)
 
                procedure reset is
 
                begin
 
                        rx_c     <= (others => '0') after g.delay;
 
                        sr_c     <= (others => '0') after g.delay;
 
                        fail_c   <= (others => '0') after g.delay;
 
                        ctr_c    <= (others => '0') after g.delay;
 
                        state_c  <= reset after g.delay;
 
                        count_c  <= 0 after g.delay;
 
                        rx_sync  <= '0' after g.delay;
 
                end procedure;
        begin
        begin
                if rst = '1' then
                if rst = '1' and g.asynchronous_reset then
                        uart_rx_data_vec <= (others => '0');
                        reset;
                elsif rising_edge(clk) then
                elsif rising_edge(clk) then
                        if oversample_baud_tick = '1' then
                        if rst = '1' and not g.asynchronous_reset then
                                uart_rx_data_vec(0) <= rx;
                                reset;
                                uart_rx_data_vec(1) <= uart_rx_data_vec(0);
                        else
 
                                rx_c     <= rx_n after g.delay;
 
                                sr_c     <= sr_n after g.delay;
 
                                state_c  <= state_n after g.delay;
 
                                count_c  <= count_n after g.delay;
 
                                fail_c   <= fail_n after g.delay;
 
                                ctr_c    <= ctr_n after g.delay;
 
                                rx_sync  <= rx after g.delay;
                        end if;
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
        -- filter rxd with a 2 bit counter.
        process (rx_c, sr_c, ctr_c, ctr_we, ctr, state_c, rx_sync, baud, sample, count_c, fail_c, majority)
        rxd_filter: process(clk, rst)
 
        begin
        begin
                if rst = '1' then
                fail_n  <= fail_c after g.delay;
                        uart_rx_filter <= (others => '1');
                rx_n    <= rx_c after g.delay;
                        uart_rx_bit    <= '1';
                sr_n    <= sr_c after g.delay;
                elsif rising_edge(clk) then
                ctr_n   <= ctr_c after g.delay;
                        if oversample_baud_tick = '1' then
                state_n <= state_c after g.delay;
                                -- filter rxd.
                we      <= '0' after g.delay;
                                if uart_rx_data_vec(1) = '1' and uart_rx_filter < 3 then
                cr      <= '0' after g.delay;
                                        uart_rx_filter <= uart_rx_filter + 1;
                count_n <= count_c after g.delay;
                                elsif uart_rx_data_vec(1) = '0' and uart_rx_filter > 0 then
 
                                        uart_rx_filter <= uart_rx_filter - 1;
                if sample = '1' then
 
                        sr_n <= sr_c(sr_c'high - 1 downto sr_c'low) & rx_sync after g.delay;
 
                end if;
 
 
 
                case state_c is
 
                when reset =>
 
                        rx_n     <= (others => '0') after g.delay;
 
                        sr_n     <= (others => '0') after g.delay;
 
                        fail_n   <= (others => '0') after g.delay;
 
                        ctr_n    <= format after g.delay; -- 8 bits, 1 stop bit, parity off
 
                        state_n  <= idle after g.delay;
 
                when idle =>
 
                        count_n <= 0 after g.delay;
 
                        if rx_sync = '0' then -- and majority = '1' then
 
                                state_n <= start after g.delay;
 
                                cr      <= '1' after g.delay;
 
                                sr_n    <= (others => '0') after g.delay;
 
                                fail_n  <= (others => '0') after g.delay;
 
                        end if;
 
                when start =>
 
                        if baud = '1' then
 
                                if majority /= '0' then
 
                                        state_n   <= done after g.delay; -- frame error
 
                                        fail_n(0) <= '1' after g.delay;
 
                                else
 
                                        state_n <= data after g.delay;
                                end if;
                                end if;
                                -- set the rx bit.
                                sr_n <= (others => '0') after g.delay;
                                if uart_rx_filter = 3 then
 
                                        uart_rx_bit <= '1';
 
                                elsif uart_rx_filter = 0 then
 
                                        uart_rx_bit <= '0';
 
                                end if;
                                end if;
 
                when data =>
 
                        rx_n(count_c) <= majority after g.delay;
 
                        if baud = '1' then
 
                                if count_c = (ctr_data_bits(ctr_c) - 1) then
 
                                        count_n <= 0 after g.delay;
 
                                        if ctr_c(ctr_use_parity) = '1' then
 
                                                state_n <= parity after g.delay;
 
                                        else
 
                                                state_n <= stop after g.delay;
                        end if;
                        end if;
 
                                else
 
                                        count_n <= count_c + 1 after g.delay;
                end if;
                end if;
        end process;
                                sr_n <= (others => '0') after g.delay;
 
                        end if;
        rx_bit_spacing: process (clk, rst)
                when parity =>
        begin
                        if baud = '1' then
                if rising_edge(clk) then
                                if (ctr_c(ctr_use_parity) = '1') and (majority /= parity(rx_c, ctr_c(ctr_even_parity))) then
                        uart_rx_bit_tick <= '0';
                                        fail_n(1) <= '1' after g.delay; -- parity error, still process stop bits
                        if oversample_baud_tick = '1' then
                                end if;
                                if uart_rx_bit_spacing = 15 then
                                state_n <= stop after g.delay;
                                        uart_rx_bit_tick <= '1';
                                sr_n <= (others => '0') after g.delay;
                                        uart_rx_bit_spacing <= (others => '0');
                        end if;
 
                when stop =>
 
                        if baud = '1' then
 
                                if majority /= '1' then
 
                                        state_n   <= done after g.delay; -- frame error
 
                                        fail_n(0) <= '1' after g.delay;
 
                                elsif count_c = ctr_stop_bits(ctr_c) then
 
                                        state_n <= done after g.delay;
                                else
                                else
                                        uart_rx_bit_spacing <= uart_rx_bit_spacing + 1;
                                        count_n <= count_c + 1 after g.delay;
                                end if;
                                end if;
                                if uart_rx_state = rx_get_start_bit then
 
                                        uart_rx_bit_spacing <= (others => '0');
 
                                end if;
                                end if;
 
                when done => -- The consuming module needs to store rx_c/fail_c immediately
 
                        we      <= '1' after g.delay;
 
                        state_n <= idle after g.delay;
 
                        --rx_n    <= (others => '0') after g.delay;
 
                        --sr_n    <= (others => '0') after g.delay;
 
                        --fail_n  <= (others => '0') after g.delay;
 
                end case;
 
 
 
                if ctr_we = '1' then
 
                        if not (state_c = idle or state_c = done or state_c = reset) then
 
                                rx_n      <= (others => '0') after g.delay;
 
                                state_n   <= idle after g.delay;
 
                                we        <= '1' after g.delay;
 
                                fail_n(0) <= '1' after g.delay; -- frame error!
                        end if;
                        end if;
 
                        ctr_n <= ctr after g.delay;
                end if;
                end if;
        end process;
        end process;
 
end architecture;
 
 
 
library ieee, work;
 
use ieee.std_logic_1164.all;
 
use work.uart_pkg.all;
 
use work.util.common_generics;
 
use work.util.parity;
 
 
        uart_receive_data: process(clk, rst)
entity uart_tx is
 
        generic (g: common_generics; N: positive; format: std_ulogic_vector(7 downto 0) := uart_8N1);
 
        port (
 
                clk:    in std_ulogic;
 
                rst:    in std_ulogic;
 
                cr:    out std_ulogic;
 
                baud:   in std_ulogic; -- Pulse at baud
 
                tx:    out std_ulogic;
 
                ok:    out std_ulogic;
 
                ctr:    in std_ulogic_vector(format'range);
 
                ctr_we: in std_ulogic;
 
                we:     in std_ulogic; -- di write enable
 
                di:     in std_ulogic_vector(N - 1 downto 0));
 
end entity;
 
 
 
architecture behaviour of uart_tx is
 
        type state is (reset, idle, start, data, parity, stop);
 
        signal state_c, state_n: state;
 
        signal di_c, di_n: std_ulogic_vector(di'range);
 
        signal ctr_c, ctr_n: std_ulogic_vector(ctr'range);
 
        signal busy: std_ulogic;
 
        signal parity_c, parity_n: std_ulogic;
 
        signal count_c, count_n: integer range 0 to 15;
 
begin
 
        busy <= '0' when state_c = idle else '1' after g.delay;
 
        ok <= not busy after g.delay;
 
 
 
        process (clk, rst)
 
                procedure reset is
 
                begin
 
                        di_c     <= (others => '0') after g.delay;
 
                        ctr_c    <= (others => '0') after g.delay;
 
                        state_c  <= reset after g.delay;
 
                        parity_c <= '0' after g.delay;
 
                        count_c  <= 0 after g.delay;
 
                end procedure;
        begin
        begin
                if rst = '1' then
                if rst = '1' and g.asynchronous_reset then
                        uart_rx_state        <= rx_get_start_bit;
                        reset;
                        uart_rx_data_block   <= (others => '0');
 
                        uart_rx_count        <= 0;
 
                        uart_rx_data_out_stb <= '0';
 
                elsif rising_edge(clk) then
                elsif rising_edge(clk) then
                        case uart_rx_state is
                        if rst = '1' and not g.asynchronous_reset then
                        when rx_get_start_bit =>
                                reset;
                                if oversample_baud_tick = '1' and uart_rx_bit = '0' then
 
                                        uart_rx_state <= rx_get_data;
 
                                end if;
 
                        when rx_get_data =>
 
                                if uart_rx_bit_tick = '1' then
 
                                        if uart_rx_count < uart_rx_count_max then
 
                                                uart_rx_data_block(uart_rx_count) <= uart_rx_bit;
 
                                                uart_rx_count <= uart_rx_count + 1;
 
                                        else
 
                                                uart_rx_data_block(7) <= uart_rx_bit;
 
                                                uart_rx_count <= 0;
 
                                                uart_rx_state <= rx_get_stop_bit;
 
                                        end if;
 
                                end if;
 
                        when rx_get_stop_bit =>
 
                                if uart_rx_bit_tick = '1' then
 
                                        if uart_rx_bit = '1' then
 
                                                uart_rx_state        <= rx_send_block;
 
                                                uart_rx_data_out_stb <= '1';
 
                                        end if;
 
                                end if;
 
                        when rx_send_block =>
 
                                if dout_ack = '1' then
 
                                        uart_rx_data_out_stb  <= '0';
 
                                        uart_rx_data_block    <= (others => '0');
 
                                        uart_rx_state         <= rx_get_start_bit;
 
                                else
                                else
                                        uart_rx_data_out_stb  <= '1';
                                di_c     <= di_n after g.delay;
 
                                ctr_c    <= ctr_n after g.delay;
 
                                state_c  <= state_n after g.delay;
 
                                parity_c <= parity_n after g.delay;
 
                                count_c  <= count_n after g.delay;
 
                        end if;
 
                end if;
 
        end process;
 
 
 
        process (di_c, di, ctr_c, ctr_we, ctr, state_c, we, baud, parity_c, count_c)
 
        begin
 
                count_n <= count_c after g.delay;
 
                state_n <= state_c after g.delay;
 
                di_n    <= di_c after g.delay;
 
                ctr_n   <= ctr_c after g.delay;
 
                tx <= '1' after g.delay;
 
                cr <= '0';
 
 
 
                if ctr_c(ctr_use_parity) = '1' then
 
                        parity_n <= parity(di_c, ctr_c(ctr_even_parity)) after g.delay;
 
                else
 
                        parity_n <= '0' after g.delay;
 
                end if;
 
 
 
                case state_c is
 
                when reset  =>
 
                        state_n  <= idle after g.delay;
 
                        ctr_n    <= format after g.delay; -- 8 bits, 1 stop bit, parity off
 
                        count_n  <= 0 after g.delay;
 
                        parity_n <= '0' after g.delay;
 
                        di_n     <= (others => '0') after g.delay;
 
                when idle   =>
 
                        count_n  <= 0 after g.delay;
 
                        if ctr_we = '1' then -- NB. We can either lose data, or control writes
 
                                ctr_n <= ctr after g.delay;
 
                        elsif we = '1' then
 
                                di_n    <= di after g.delay;
 
                                cr      <= '1';
 
                                state_n <= start after g.delay;
 
                        end if;
 
                when start  =>
 
                        tx <= '0' after g.delay;
 
                        if baud = '1' then
 
                                state_n <= data after g.delay;
 
                        end if;
 
                when data   =>
 
                        tx <= di_c(count_c) after g.delay;
 
                        if baud = '1' then
 
                                if count_c = (ctr_data_bits(ctr_c) - 1) then
 
                                        count_n <= 0 after g.delay;
 
                                        if ctr_c(ctr_use_parity) = '1' then
 
                                                state_n <= parity after g.delay;
 
                                        else
 
                                                state_n <= stop after g.delay;
 
                                        end if;
 
                                else
 
                                        count_n <= count_c + 1 after g.delay;
 
                                end if;
 
                        end if;
 
                when parity =>
 
                        tx <= parity_c after g.delay;
 
                        if baud = '1' then
 
                                state_n <= stop after g.delay;
 
                        end if;
 
                when stop   =>
 
                        tx <= '1' after g.delay;
 
                        if baud = '1' then
 
                                if count_c = ctr_stop_bits(ctr_c) then
 
                                        count_n <= 0 after g.delay;
 
                                        state_n <= idle after g.delay;
 
                                else
 
                                        count_n <= count_c + 1 after g.delay;
 
                                end if;
                                end if;
                                end if;
                        when others =>
 
                                uart_rx_state <= rx_get_start_bit;
 
                        end case;
                        end case;
 
        end process;
 
end architecture;
 
 
 
library ieee, work;
 
use ieee.std_logic_1164.all;
 
use ieee.numeric_std.all;
 
use work.uart_pkg.all;
 
use work.util.common_generics;
 
 
 
entity uart_tb is
 
        generic(g: common_generics);
 
end entity;
 
 
 
architecture testing of uart_tb is
 
        constant clock_period: time     := 1000 ms / g.clock_frequency;
 
        constant use_fifo:     boolean  := true;
 
        signal rst, clk:     std_ulogic := '1';
 
        signal stop:         boolean    := false;
 
        signal loopback:     boolean    := true;
 
        signal tx, rx:       std_ulogic;
 
        signal di, do:       std_ulogic_vector(7 downto 0);
 
        signal reg:          std_ulogic_vector(15 downto 0);
 
        signal clock_reg_tx_we: std_ulogic;
 
        signal clock_reg_rx_we: std_ulogic;
 
        signal control_reg_we:  std_ulogic;
 
 
 
        signal tx_fifo_full:  std_ulogic;
 
        signal tx_fifo_empty: std_ulogic;
 
        signal tx_fifo_we:    std_ulogic := '0';
 
        signal rx_fifo_full:  std_ulogic;
 
        signal rx_fifo_empty: std_ulogic;
 
        signal rx_fifo_re:    std_ulogic := '0';
 
begin
 
        -- duration: process begin wait for 20000 us; stop <= true; wait; end process;
 
        clk_process: process
 
        begin
 
                rst <= '1';
 
                wait for clock_period * 5;
 
                rst <= '0';
 
                while not stop loop
 
                        clk <= '1';
 
                        wait for clock_period / 2;
 
                        clk <= '0';
 
                        wait for clock_period / 2;
 
                end loop;
 
                wait;
 
        end process;
 
 
 
        stimulus: process
 
                procedure write(data: std_ulogic_vector(di'range)) is
 
                begin
 
                        wait for clock_period * 1;
 
                        while tx_fifo_full = '1' loop
 
                                wait for clock_period;
 
                        end loop;
 
                        di <= data;
 
                        tx_fifo_we <= '1';
 
                        wait for clock_period;
 
                        tx_fifo_we <= '0';
 
                end procedure;
 
        begin
 
                di <= x"00";
 
                wait until rst = '0';
 
                wait for clock_period;
 
                reg             <=  x"8080";
 
                control_reg_we  <=  '1';
 
                wait for clock_period;
 
                control_reg_we  <=  '0';
 
                reg             <=  x"0036";
 
                clock_reg_tx_we <=  '1';
 
                wait for clock_period;
 
                clock_reg_tx_we <=  '0';
 
                clock_reg_rx_we <=  '1';
 
                reg             <=  x"0035";
 
                wait for clock_period;
 
                clock_reg_rx_we <=  '0';
 
                wait for clock_period;
 
 
 
                write(x"AA");
 
                write(x"BB");
 
                write(x"CC");
 
                write(x"DD");
 
                write(x"EE");
 
                write(x"FF");
 
                wait for clock_period;
 
                while tx_fifo_empty = '0' loop
 
                        wait for clock_period;
 
                end loop;
 
                loopback <= false;
 
                wait for clock_period * 50000;
 
                stop <= true;
 
                wait;
 
        end process;
 
 
 
        ack: process
 
        begin
 
                while not stop loop
 
                        if rx_fifo_empty = '0' then
 
                                rx_fifo_re <= '1';
 
                        else
 
                                rx_fifo_re <= '0';
                end if;
                end if;
 
                        wait for clock_period;
 
                end loop;
 
                wait;
        end process;
        end process;
end;
        rx <= tx when loopback else '0'; -- loop back test
 
        uut: work.uart_pkg.uart_top
 
                generic map (g => g, baud => 115200, format => uart_8N1, use_fifo => use_fifo)
 
                port map (
 
                        clk => clk,
 
                        rst => rst,
 
 
 
                        tx             =>  tx,
 
                        tx_fifo_full   =>  tx_fifo_full,
 
                        tx_fifo_empty  =>  tx_fifo_empty,
 
                        tx_fifo_we     =>  tx_fifo_we,
 
                        tx_fifo_data   =>  di,
 
 
 
                        rx             =>  rx,
 
                        rx_fifo_full   =>  rx_fifo_full,
 
                        rx_fifo_empty  =>  rx_fifo_empty,
 
                        rx_fifo_re     =>  rx_fifo_re,
 
                        rx_fifo_data   =>  do,
 
 
 
                        reg             => reg,
 
                        clock_reg_tx_we => clock_reg_tx_we,
 
                        clock_reg_rx_we => clock_reg_rx_we,
 
                        control_reg_we  => control_reg_we);
 
 
 
end architecture;
 
 
---- UART Core -----------------------------------------------------------------
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.