FrenchRiviera
FrenchRiviera

Reputation: 9

Communication PC-DE0 Nano using UART

I'm trying to connect my FPGA with my laptop using the serial protocol. For that purpose, I implemented the UART protocol on the FPGA side.

The connection between the FPGA and the Laptop is done with the UART-TTL to USB converter. I Get the wrong frame on the Laptop side. Thus, I analyse my frame continuously using a logic analyzer, I observed that the frame sent wasn't stable, i.e sometimes a wrong frame is received instead of the one sent.

Below is the code for the serial core :

library ieee ;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity TX is 

    port(

        CLK: in std_logic;
        START: in std_logic;
        BUSY : out std_logic;
        DATA: in std_logic_vector(7 downto 0);
        TX_LINE: out std_logic

        );
end TX;


architecture MAIN of TX is 

signal PRSCL : integer range 0 to 5208:=0;
signal index : integer range 0 to 9:=0;
signal DATAFLL : std_logic_vector (9 downto 0);
signal TX_FLAG: STD_LOGIC:='0';

begin 

process(CLK)
begin 

if(CLK'EVENT and CLK='1') then 
    if(TX_FLAG='0' and START='1') then 
        TX_FLAG<='1';
        BUSY<='1';
        DATAFLL(0)<='0';
        DATAFLL(9)<='1';
       DATAFLL(8 downto 1)<=DATA;
        TX_LINE<='1';
  end if;
 -- send data , 50MHz /9600=5208 (9600: the baudrate)
  IF(TX_FLAG='1') then

      IF (PRSCL <5207) then 
            PRSCL<=PRSCL+1;
      else 
          PRSCL<=0;
      end if;

     IF(PRSCL=2600)THEN

           TX_LINE<=DATAFLL(INDEX);
            IF(INDEX<9)THEN
                 INDEX<=INDEX+1;
            ELSE
                 TX_FLAG<='0';
                 BUSY<='0';
                 INDEX<=0;
             END IF;

        END IF; 
   END IF;

END IF; 

end process ;

end MAIN;

The control unit to instantiate the serial core is below :

library ieee ;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity UART is

    port (

        CLOCK_50: in std_logic;
        SW: in std_logic_vector(3 downto 0);
        KEY: in std_logic_vector(1 downto 0);
        LEDG : out std_logic_vector (7 downto 0);
        UART_TXD : out std_logic;
        UART_RXD: in std_logic
        );
end UART ;


ARCHITECTURE MAIN OF UART IS

SIGNAL TX_DATA: STD_LOGIC_VECTOR(7  downto 0);
SIGNAL TX_START: STD_LOGIC:='0';
SIGNAL TX_BUSY: STD_LOGIC:='0';
SIGNAL RX_DATA: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL RX_BUSY: STD_LOGIC:='0';


COMPONENT TX
    PORT(
        CLK:IN STD_LOGIC;
        START:IN STD_LOGIC;
        BUSY:OUT STD_LOGIC;
        DATA: IN STD_LOGIC_VECTOR(7 downto 0);
        TX_LINE:OUT STD_LOGIC
        );
END COMPONENT TX;

BEGIN 

C1: TX PORT MAP (CLOCK_50,TX_START,TX_BUSY,TX_DATA,UART_TXD);
--C2: RX PORT MAP (CLOCK_50,UART_RXD,RX_DATA,RX_BUSY);

PROCESS(CLOCK_50)
BEGIN

IF(CLOCK_50'EVENT AND CLOCK_50='1')THEN

   IF(KEY(0)='1' AND TX_BUSY='0')THEN -- Key(0)='0' MEAN that the key is pressed 
            TX_DATA<="0000" & SW(3 DOWNTO 0);
            TX_START<='1';
            LEDG<=TX_DATA;
    ELSE
            TX_START<='0';
            TX_DATA<=(others=>'0') ;
    END IF;

END IF;
END PROCESS;
END MAIN;

Thanks for you help.

Best regards,

Upvotes: 1

Views: 2272

Answers (1)

Jonathan Drolet
Jonathan Drolet

Reputation: 3388

Any asynchronous input have to be resynchronized before use, otherwise your circuit will become metastable and erratic behaviour will follow. On your top level, sw and key are asynchronous.

A synchronization circuit is typically 2 cascaded flip-flops, only the output of the second flip-flop should be used in your code:

    ...

    signal sw_resync1  : std_logic_vector(3 downto 0);
    signal sw_resync2  : std_logic_vector(3 downto 0);
    signal key_resync1 : std_logic_vector(3 downto 0);
    signal key_resync2 : std_logic_vector(3 downto 0);
begin
    RESYNC: process(CLOCK_50)
    begin
        if (CLOCK_50'event and CLOCK_50 = '1') then
            SW_resync1  <= SW;
            SW_resync2  <= SW_resync1;
            KEY_resync1 <= KEY;
            KEY_resync2 <= KEY_resync1;
        end if;
    end process RESYNC;

    ...

    IF(KEY_resync2(0)='1' AND TX_BUSY='0')THEN -- Key(0)='0' MEAN that the key is pressed 
        TX_DATA<="0000" & SW_resync2(3 DOWNTO 0);

    ...

You should also be aware that mechanical inputs (suck as sw and key) should be debounced or you will read several transitions for the same key stroke.

Upvotes: 2

Related Questions