'I tried writing UART VHDL code for loopback testing. Can anyone help me how to write a testbench for it

UART loopback testing code for an FPGA:

-- 
-- Inputs/Outputs:
--
--   SYS:
--    I_clk            - system clock - at least 16x baud rate for recieve
--                       but can be less if only using TX.
--    I_clk_baud_count - the number of cycles of I_clk between baud ticks
--                       used to set a known transmit/recieve baud rate.
--    I_reset          - reset line. ideally, reset whilst changing baud.
--
--   TX:
--    I_txData   - data to transmit.
--    I_txSig    - signal to transmit (deassert when txReady low) or
--                 change I_txData to stream out.
--    O_txRdy    - '1' when idle, '0' when transmitting.
--    O_tx       - actual serial output.
--
--   RX:
--    I_rx           - actual serial input.
--    I_rxCont       - receive enable/continue.
--    O_rxData       - data received.
--    O_rxSig        - data available signal - does not deassert until new
--                     frame starts being received.

entity UART is
Port (I_clk : in STD_LOGIC; 
      I_reset: in STD_LOGIC; 
      O_tx : out STD_LOGIC; 
      I_rx : in STD_LOGIC;
      O_txRdy : out STD_LOGIC);
end UART;

architecture Behavioral of UART is
constant I_clk_baud_count :integer:=10416;       -- for 100MHz @ 9600 baud rate
signal I_txSig : STD_LOGIC;
signal tx_data : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
signal tx_state: integer := 0;
signal tx_rdy : STD_LOGIC := '1';
signal tx: STD_LOGIC := '1';
signal rx_sample_count : integer := 0;
signal rx_sample_offset : integer := 3;
signal rx_state: integer := 0;
signal rx_data : STD_LOGIC_VECTOR(7 downto 0) := (others => '0');
signal rx_sig : STD_LOGIC := '0';
signal rx_clk_counter : integer := 0;
signal rx_clk_reset : STD_LOGIC := '0';
signal rx_clk_baud_tick: STD_LOGIC := '0';
signal tx_clk_counter : integer := 0;
signal tx_clk : STD_LOGIC := '0';

constant OFFSET_START_BIT: integer := 7;        -- for start bit
constant OFFSET_DATA_BITS: integer := 15;       -- for data bit
constant OFFSET_STOP_BIT: integer := 7;         -- for stop bit


begin
-- clock process
clk_gen: process (I_clk)
begin
    if rising_edge(I_clk) then
        -- RX baud 'ticks' generated for sampling, with reset
        if (rx_clk_counter = 0) then
        -- x16 sampled - so chop off 4 LSB
            rx_clk_counter <= I_clk_baud_count;
            rx_clk_baud_tick <= '1';
        else
            if (rx_clk_reset = '1') then
                rx_clk_counter <= I_clk_baud_count;
            else
                rx_clk_counter <= rx_clk_counter - 1;
            end if;
            rx_clk_baud_tick <= '0';
        end if;
 
-- TX standard baud clock, no reset   
        if (tx_clk_counter = 0) then
        -- chop off LSB to get a clock
            tx_clk_counter <= I_clk_baud_count;
            tx_clk <= not tx_clk;
        else
            tx_clk_counter <= tx_clk_counter - 1;
        end if;
    end if;
end process;

-- transmission process

tx_proc: process (tx_clk, I_reset, I_txSig, tx_state)
begin
    -- TX runs off the TX baud clock
    if rising_edge(tx_clk) then
        if I_reset = '1' then
            tx_state <= 0;
            tx_data <= X"00";
            tx_rdy <= '1';
            tx <= '1';
        else
            if (tx_state = 0 and I_txsig = '1') then
                tx_state <= 1;
                tx_rdy <= '0';
                tx <= '0';   -- start bit
            elsif (tx_state < 9 and tx_rdy = '0') then
                tx <= tx_data(0);
                tx_data <= '0' & tx_data (7 downto 1);
                tx_state <= tx_state + 1;
            elsif (tx_state = 9 and tx_rdy = '0') then
                tx <= '1';  -- stop bit
                tx_rdy <= '1';
                tx_state <= 0;
            end if;
        end if;
    end if;
end process;

-- receiving process

rx_proc: process (I_clk, I_reset, I_rx)
begin
    -- RX runs off the system clock, and operates on baud 'ticks'
    if rising_edge(I_clk) then
        if (rx_clk_reset = '1') then
            rx_clk_reset <= '0';
        end if;
        if (I_reset = '1') then
            rx_state <= 0;
            rx_sig <= '0';
            rx_sample_count <= 0;
            rx_sample_offset <= OFFSET_START_BIT;
            rx_data <= X"00";
        elsif (I_rx = '0' and rx_state = 0) then
            -- first encounter of falling edge start

            rx_state <= 1; -- start bit sample stage
            rx_sample_offset <= OFFSET_START_BIT;
            rx_sample_count <= 0;

            -- need to reset the baud tick clock to line up with the start 
            -- bit leading edge.
            rx_clk_reset <= '1';
        elsif (rx_clk_baud_tick = '1' and I_rx = '0' and rx_state = 1) then
            -- inc sample count
            rx_sample_count <= rx_sample_count + 1;
            if (rx_sample_count = rx_sample_offset) then
                -- start bit sampled, time to enable data
                rx_sig <= '0';
                rx_state <= 2;
                rx_data <= X"00";
                rx_sample_offset <= OFFSET_DATA_BITS; 
                rx_sample_count <= 0;
            end if;
        elsif (rx_clk_baud_tick = '1' and rx_state >= 2  and rx_state < 10) then
            -- sampling data
            if (rx_sample_count = rx_sample_offset) then
                rx_data(6 downto 0) <= rx_data(7 downto 1);
                rx_data(7) <= I_rx;
                rx_sample_count <= 0;
                rx_state <= rx_state + 1;
            else
                rx_sample_count <= rx_sample_count + 1;
            end if;
        elsif (rx_clk_baud_tick = '1' and rx_state = 10) then
            if (rx_sample_count = OFFSET_STOP_BIT) then
                rx_state <= 0;
                rx_sig <= '1';
                tx_data <= rx_data; 
            else
                rx_sample_count <= rx_sample_count + 1;
            end if;
        end if;
    end if;
end process;

O_tx <= tx;
O_txRdy <= tx_rdy;
I_txSig <= rx_sig;

end Behavioral;



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source