1
\$\begingroup\$

(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:

Testbench Results

Thanks.

\$\endgroup\$

2 Answers 2

0
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ Thank you for information. But I only use ISE for testbench simulation. I normally use Quartus and I have Altera DE0 FPGA. In this project, UART code must belongs to me. \$\endgroup\$
    – Griffo
    Aug 18, 2017 at 11:37
  • \$\begingroup\$ Okay. Even then I'd like you to go through that code for your reference. It might help solve your problem. Basically it is HDL code. \$\endgroup\$
    – samjay
    Aug 21, 2017 at 4:12
-1
\$\begingroup\$
        if(rx_first_bit <= '1' and rx_reg_counter (2 downto 0) = "110") then
            counter_del_baud <= '0';
            rx_start_bit     <= '1';
            rx_first_bit      <= '0';
            if(baud_pulse <= '1') then
                rx_start_bit  <= '0';
                rx_data_bit   <= '1';
                counter_del_half <= '1';
            end if;

All of these lines of code occur simultaneously, you have rx_start_bit driven twice as far as I am concerned whenever the if statement is true.

Also I am a novice but I am curious wherever baud_pulse <= '1' and baud_pulse = '1' are the same?

Cheers!

\$\endgroup\$
6
  • \$\begingroup\$ Thank you for your answer. In this part of code, I wanted to drive rx_start_bit for 1 clock bit but in test bench, rx_start_bit is driven 5 bit long. Also baud_pulse <= '1' is signal assignment operation and baud_pulse = '1' shows a statement. Thank you for remind me. \$\endgroup\$
    – Griffo
    Aug 17, 2017 at 15:12
  • 2
    \$\begingroup\$ @Griffo In an if-statement, <= is "less than or equal". So for a single bit, it's always true. \$\endgroup\$ Aug 17, 2017 at 15:40
  • \$\begingroup\$ @BlairFonville Yep, I noticed it. I think using "end if"s wrong place causes the problem. \$\endgroup\$
    – Griffo
    Aug 17, 2017 at 15:43
  • 1
    \$\begingroup\$ I guess the main point I was trying to make is in in this snipper rx_start_bit <= '0' and rx_start_bit <= '1' are not in statements that are mutually exclusive. So both could potentially happen, it's not a good practice to drive it that way. You could maybe find a flag that would differentiate the two ( if that's what you're looking for) \$\endgroup\$
    – zoder
    Aug 17, 2017 at 16:15
  • 1
    \$\begingroup\$ @zoder -1 because your comments and initial concern are complete bullshit. There's nothing wrong with scheduling assignments like this in a properly written process. \$\endgroup\$
    – DonFusili
    Jul 30, 2018 at 11:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.