(I posted same question in stackoverflow but didn't get right answer)
I'm newbie in VHDL. So today, after UART Tx, I tried to read Datas that coming from Realterm terminal. I only wrote Rx codes to just see data. I also used 7 segment display and 7 LED to see what data I receieved. When you look testbench results, the problem is when 3 bit register is "110" twice times, program jumps into rx_data_bit without doing rx_start_bit <= '1'
EDIT 1: Codes and testbench results are updated. Now the issue is rx_data_bit never goes '0' so rx_stop_bit never goes '1'
EDIT 2: I think problem is here
if(rx_data_bit = '1') then
counter_del_half <= '0';
if(half_pulse = '1')then
rx_reg((rx_counter)) <= in_Data_rx;
if(rx_counter < 8 and baud_pulse = '1')then
rx_counter <= rx_counter + 1;
if(rx_counter = 8) then
rx_data_bit <= '0';
rx_stop_bit <= '1';
end if;
end if;
end if;
end if;
EDIT 3: Now, counter counts correctly but I got a question here. Should rx_counter's first bit (1) do last half bit long or 1 bit long? Also, rx_stop_bit must be '1', when rx_counter reaches 9.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_Rx is
port (
CLK: in std_logic;
nReset: in std_logic;
in_Data_Rx: in std_logic;
Segment7_1: out std_logic_vector (6 downto 0);
Segment7_2: out std_logic_vector (6 downto 0)
);
end UART_Rx;
architecture Behavioral of UART_Rx is
-- CLOCK AND BUTTON SIGNALS --
constant Baudrate: integer:= 9600;
constant CLK_Hiz: integer:= 50000000;
constant CLK_Bit: integer:= (CLK_Hiz / Baudrate) + 1;
signal counter_baud: integer range 0 to (CLK_Bit - 1):= 0;
signal counter_half: integer range 0 to ((CLK_Bit - 1)/2):= 0;
signal counter_del_baud: std_ulogic:= '0';
signal counter_del_half: std_ulogic:= '0';
signal baud_pulse: std_ulogic:= '0';
signal half_pulse: std_ulogic:= '0';
-- RX SIGNALS --
signal rx_reg: std_logic_vector (7 downto 0):= (others => '0');
signal rx_reg_counter: std_logic_vector (2 downto 0):= (others => '0');
signal rx_counter: integer range 0 to 9:= 0;
signal rx_first_bit: std_ulogic:= '1';
signal rx_start_bit: std_ulogic:= '0';
signal rx_data_bit: std_ulogic:= '0';
signal rx_stop_bit: std_ulogic:= '0';
signal rx_data_al: std_ulogic:= '0';
begin
-- CLOCK PROCESS --
clk_process: process(CLK,nReset)
begin
if(nReset = '0') then
baud_pulse <= '0';
counter_baud <= 0;
half_pulse <= '0';
counter_half <= 0;
elsif(rising_edge(CLK)) then
if(counter_baud < (CLK_Bit - 1)) then
counter_baud <= counter_baud + 1;
baud_pulse <= '0';
else
counter_baud <= 0;
baud_pulse <= '1';
end if;
if(counter_half < (CLK_Bit - 1)/2) then
counter_half <= counter_half + 1;
half_pulse <= '0';
else
counter_half <= 0;
half_pulse <= '1';
end if;
if(counter_del_baud = '1') then
counter_baud <= 0;
end if;
if(counter_del_half = '1') then
counter_half <= 0;
end if;
end if;
end process;
rx_process: process(CLK, nReset)
begin
if(rising_edge(CLK)) then
rx_reg_counter <= rx_reg_counter (1 downto 0) & in_Data_Rx;
if(rx_first_bit = '1' and rx_reg_counter (2 downto 0) = "110") then
counter_del_baud <= '1';
rx_start_bit <= '1';
rx_first_bit <= '0';
end if;
if(rx_start_bit = '1') then
counter_del_baud <= '0';
if(baud_pulse = '1') then
counter_del_baud <= '1';
rx_start_bit <= '0';
rx_data_bit <= '1';
counter_del_half <= '1';
end if;
end if;
if(rx_data_bit = '1') then
counter_del_half <= '0';
counter_del_baud <= '0';
if(half_pulse = '1')then
rx_data_bit <= '0';
rx_data_al <= '1';
rx_counter <= 1;
end if;
end if;
if(rx_data_al = '1') then
rx_reg(rx_counter - 1) <= in_Data_rx;
if(rx_counter > 0 and rx_counter < 9) then
if(baud_pulse = '1')then
rx_counter <= rx_counter + 1;
if(rx_counter = 9) then
rx_data_al <= '0';
rx_stop_bit <= '1';
end if;
end if;
end if;
end if;
if(rx_stop_bit = '1')then
rx_counter <= 0;
if(baud_pulse = '1') then
rx_stop_bit <= '0';
rx_reg_counter <= (others => '1');
rx_first_bit <= '1';
end if;
end if;
case rx_reg(3 downto 0) is --abcdefg--
when "0000" => segment7_1 <= "0000001"; -- '0'
when "0001" => segment7_1 <= "1001111"; -- '1'
when "0010" => segment7_1 <= "0010010"; -- '2'
when "0011" => segment7_1 <= "0000110"; -- '3'
when "0100" => segment7_1 <= "1001100"; -- '4'
when "0101" => segment7_1 <= "0100100"; -- '5'
when "0110" => segment7_1 <= "0100000"; -- '6'
when "0111" => segment7_1 <= "0001111"; -- '7'
when "1000" => segment7_1 <= "0000000"; -- '8'
when "1001" => segment7_1 <= "0000100"; -- '9'
when "1010" => segment7_1 <= "0001000"; -- 'A'
when "1011" => segment7_1 <= "1100000"; -- 'B'
when "1100" => segment7_1 <= "0110001"; -- 'C'
when "1101" => segment7_1 <= "1000010"; -- 'D'
when "1110" => segment7_1 <= "0110000"; -- 'E'
when "1111" => segment7_1 <= "0111000"; -- 'F'
when others => segment7_1 <= "1111111";
end case;
case rx_reg(7 downto 4) is
when "0000" => segment7_2 <= "0000001"; -- '0'
when "0001" => segment7_2 <= "1001111"; -- '1'
when "0010" => segment7_2 <= "0010010"; -- '2'
when "0011" => segment7_2 <= "0000110"; -- '3'
when "0100" => segment7_2 <= "1001100"; -- '4'
when "0101" => segment7_2 <= "0100100"; -- '5'
when "0110" => segment7_2 <= "0100000"; -- '6'
when "0111" => segment7_2 <= "0001111"; -- '7'
when "1000" => segment7_2 <= "0000000"; -- '8'
when "1001" => segment7_2 <= "0000100"; -- '9'
when "1010" => segment7_2 <= "0001000"; -- 'A'
when "1011" => segment7_2 <= "1100000"; -- 'B'
when "1100" => segment7_2 <= "0110001"; -- 'C'
when "1101" => segment7_2 <= "1000010"; -- 'D'
when "1110" => segment7_2 <= "0110000"; -- 'E'
when "1111" => segment7_2 <= "0111000"; -- 'F'
when others => segment7_2 <= "1111111";
end case;
rx_reg <= (others => '0');
end if;
end process;
end Behavioral;
Here is the testbench code:
library ieee;
use ieee.std_logic_1164.all;
entity tb_UART_Rx is
end tb_UART_Rx;
architecture tb of tb_UART_Rx is
component UART_Rx
port (CLK : in std_logic;
nReset : std_logic:='1';
in_Data_Rx : std_logic:='1';
Segment7_1 : out std_logic_vector (6 downto 0):= (others => '0');
Segment7_2 : out std_logic_vector (6 downto 0):= (others => '0'));
end component;
signal CLK : std_logic;
signal nReset : std_logic:='1';
signal in_Data_Rx : std_logic:='1';
signal rx_reg_counter: std_logic_vector (2 downto 0):= (others => '1');
signal Segment7_1 : std_logic_vector (6 downto 0):= (others => '0');
signal Segment7_2 : std_logic_vector (6 downto 0):= (others => '0');
constant TbPeriod : time := 20 ns;
signal TbSimEnded : std_logic := '0';
begin
dut : UART_Rx
port map (CLK => CLK,
nReset => nReset,
in_Data_Rx => in_Data_Rx,
Segment7_1 => Segment7_1,
Segment7_2 => Segment7_2);
clk_process: process
begin
CLK <= '0';
wait for TbPeriod/2;
CLK <= '1';
wait for TbPeriod/2;
end process;
stimuli : process
begin
nReset <= '0';
wait for 100 ns;
nReset <= '1';
wait for 100 ns;
in_Data_Rx <= '1';
wait for 0.104 ms;
in_Data_Rx <= '0';
wait for 0.104 ms;
in_Data_Rx <= '0';
wait for 0.104 ms;
in_Data_Rx <= '1';
wait for 0.104 ms;
in_Data_Rx <= '1';
wait for 0.104 ms;
in_Data_Rx <= '1';
wait for 0.104 ms;
in_Data_Rx <= '0';
wait for 0.104 ms;
in_Data_Rx <= '0';
wait for 0.104 ms;
in_Data_Rx <= '0';
wait for 0.104 ms;
in_Data_Rx <= '0';
wait for 0.104 ms;
in_Data_Rx <= '1';
wait;
end process;
end tb;
configuration cfg_tb_UART_Rx of tb_UART_Rx is
for tb
end for;
end cfg_tb_UART_Rx;
Here is the testbench results:
Thanks.
Best Answer
From the simulation snapshot it seems you are working with Xilinx FPGA.
Xilinx offers ready VHDL/verilog codes for UART communication called the kcuart. You don't need to write a separate code for it (saves 'lot' of time). Just configure it for your UART specs and enjoy.