Hi Everyone,
I am struggling to make this design work. UART alone is ok but when I
add FIFO to accumulate data I receive missreads on the PC.
Design:
-- UART Transmitter
-- Baud: 7200
-- Clock: 27MHz
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity uart_tx is
port
(
reset : in std_logic;
stop : in std_logic;
clk : in std_logic;
rx : in std_logic;
tx : buffer std_logic;
tx_rdy : buffer std_logic
);
end entity;
architecture rtl of uart_tx is
--signal data : std_logic_vector( 7 downto 0) := "01000001"; --ASCII
value of alphabet 'A' in hex
--signal data : std_logic_vector(7 downto 0) := "01011111"; --ASCII
value of alphabet '_' in hex
signal data : std_logic_vector(7 downto 0) := "00000000";
signal next_data : std_logic_vector(2 downto 0) := "000"; --ASCII
value of alphabet '_' in hex
--variable to count the clock pulse
signal count : integer range 0 to 3749 := 3749; --7200 baud generator
variable (27MHz/7200)
signal bit_number : integer range 0 to 1200 :=0; --start bit+8 data
bits+stop bit+10 buffer bits
signal write_enable : std_logic:='0';
signal read_enable : std_logic:='0';
signal fifo_prog_empty : std_logic:='0';
signal fifo_empty : std_logic:='0';
signal fifo_prog_full : std_logic:='0';
signal fifo_full : std_logic:='0';
signal counter : std_logic_vector(24 downto 0):=(OTHERS => '0');
signal data_gen : std_logic_vector(7 downto 0):=(OTHERS => '0');
signal second_stop : std_logic:='0';
COMPONENT FIFO_memory
PORT (
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
full : OUT STD_LOGIC;
empty : OUT STD_LOGIC;
prog_full : OUT STD_LOGIC;
prog_empty : OUT STD_LOGIC
);
END COMPONENT;
begin
process (reset,clk)
begin
if reset = '1' then
tx <= '1';
tx_rdy <= '0';
count <= 0;
--next_data <= "000";
bit_number <= 0;
elsif (rising_edge(clk)) then
if (count = 3749) then
if (bit_number = 0 and rx = '1' and tx_rdy = '1') then
tx <= '0'; --start bit
tx_rdy <= '0';
elsif(bit_number = 9) then
tx <= '1'; -- stop bit
elsif((bit_number > 0) and (bit_number < 9)) then
tx <= data(bit_number-1); --8 data bits
tx_rdy <= '0';
elsif(bit_number > 9) then
tx <= '1'; --10 logic high bits as a buffer before the next
transmission
tx_rdy <= '1';
end if;
-- make sure transmission stops only after last bit was
transmitted
if ((second_stop = '1') and (bit_number > 9)) then
bit_number <= bit_number;
else
bit_number <= bit_number+1;
end if;
if(bit_number = 13) then --resetting the bit number
bit_number <=0;
end if;
end if;
count <= count+1;
if (count = 3750) then --resetting the baud generator counter
count <=0;
end if;
end if;
end process;
read_enable <= '1' when (count = 3750 and bit_number = 0 and
second_stop = '0') else '0';
process(clk) begin
if rising_edge(clk) then
if fifo_prog_full = '1' then
second_stop <= '0';
elsif ((fifo_prog_empty = '1') and (fifo_prog_full = '0')) then
second_stop <= '1';
end if;
end if;
end process;
-- input data for FIFO
-- process(clk,reset) begin
--
-- if reset = '1' then
--
-- data_gen <= (OTHERS => '0');
--
-- elsif rising_edge(clk) then
--
-- data_gen <= data_gen + '1';
--
-- end if;
--
-- end process;
-- write enable for FIFO
process(clk,reset) begin
if reset = '1' then
counter <= (OTHERS => '0');
data_gen <= (OTHERS => '0');
elsif rising_edge(clk) then
if counter = "1111110111110111" then --"1100110111111110011000000"
then
counter <= (OTHERS => '0');
data_gen <= data_gen + '1';
else
counter <= counter + '1';
end if;
end if;
end process;
write_enable <= '1' WHEN counter = "1111110111110111" else '0';
FIFO : FIFO_memory
PORT MAP (
clk => clk,
rst => reset,
din => data_gen,
wr_en => write_enable,
rd_en => read_enable,
dout => data,
full => fifo_full,
empty => fifo_empty,
prog_full => fifo_prog_full,
prog_empty => fifo_prog_empty
);
end rtl;
Test Bench:
------------------------------------------------------------------------
--------
-- Company:
-- Engineer:
--
-- Create Date: 12:17:41 12/27/2016
-- Design Name:
-- Module Name:
C:/Users/Alessandro/Desktop/UART_TX3/simple_uart/testbench.vhd
-- Project Name: simple_uart
-- Target Device:
-- Tool versions:
-- Description:
--
-- VHDL Test Bench Created by ISE for module: uart_tx
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes:
-- This testbench has been automatically generated using types std_logic
and
-- std_logic_vector for the ports of the unit under test. Xilinx
recommends
-- that these types always be used for the top-level I/O of a design in
order
-- to guarantee that the testbench will bind correctly to the
post-implementation
-- simulation model.
------------------------------------------------------------------------
--------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY testbench IS
END testbench;
ARCHITECTURE behavior OF testbench IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT uart_tx
PORT(
reset : IN std_logic;
stop : IN std_logic;
clk : IN std_logic;
rx : IN std_logic;
tx : BUFFER std_logic;
tx_rdy : BUFFER std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal rx : std_logic := '0';
signal stop : std_logic := '0';
signal reset : std_logic := '0';
--Outputs
signal tx : std_logic;
signal tx_rdy : std_logic;
-- Clock period definitions
constant clk_period : time := 37 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: uart_tx PORT MAP (
reset => reset,
stop => stop,
clk => clk,
rx => rx,
tx => tx,
tx_rdy => tx_rdy
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
reset_proc :process
begin
reset <= '1';
wait for 100 ns;
reset <= '0';
wait for 10000000 ms;
end process;
stop_proc :process
begin
stop <= '0';
wait for 100000000 ms;
stop <= '1';
wait for 100 ns;
end process;
-- Stimulus process
stim_proc: process
begin
rx <= '1';
wait until tx_rdy = '0';
rx <= '0';
wait until tx_rdy = '1';
end process;
END;