使用UART通信PC-DE0 Nano

时间:2015-03-03 15:45:03

标签: vhdl uart intel-fpga

我尝试使用串行协议将我的FPGA连接到笔记本电脑。为此,我在FPGA端实现了UART协议。

FPGA和笔记本电脑之间的连接是通过UART-TTL到USB转换器完成的。我在笔记本电脑侧得到了错误的框架。 因此,我使用逻辑分析仪连续分析我的帧,我观察到发送的帧不稳定,即有时接收到错误的帧而不是发送的帧。

以下是串行核心的代码:

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;

实例化串行核心的控制单元如下:

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;

谢谢你的帮助。

致以最诚挚的问候,

1 个答案:

答案 0 :(得分:2)

任何异步输入都必须在使用前重新同步,否则您的电路将变为亚稳态,并且会出现不稳定的行为。在您的顶层,sw和key是异步的。

同步电路通常是2个级联触发器,只需在代码中使用第二个触发器的输出:

    ...

    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);

    ...

你还应该知道机械输入(如sw和键那样)应该被去抖动,或者你会读到同一键击的几个过渡。