我尝试使用串行协议将我的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;
谢谢你的帮助。
致以最诚挚的问候,
答案 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和键那样)应该被去抖动,或者你会读到同一键击的几个过渡。