背景
这是一个个人项目;它涉及将 FPGA 连接到 N64,然后 FPGA 接收到的字节值通过 UART 发送到我的计算机。它实际上功能非常好!不幸的是,在随机时间,设备会发生故障,然后恢复。通过调试,我设法找到了问题,但是我对如何解决它感到困惑,因为我对 VHDL 相当无能。
几天来我一直在玩弄 VHDL,我可能无法解决这个问题。
问题
我有一个示波器测量输入 FPGA 的 N64 信号,另一个通道连接到 FPGA 的输出。我也有记录计数器值的数字引脚。
本质上,N64 发送 9 个数据位,包括一个 STOP 位。计数器对接收到的数据位进行计数,当我达到 9 位时,FPGA 开始通过 UART 传输。
这是正确的行为:
FPGA是蓝色波形,橙色波形是N64的输入。在接收期间,我的 FPGA “回声”输入信号以进行调试。FPGA 计数到 9 后,开始通过 UART 传输数据。请注意,数字引脚数为 9,并且在 N64 完成后,FPGA 输出立即变为低电平。
下面是一个失败的例子:
请注意,计数器跳过了第 2 位和第 7 位!FPGA 到达终点,等待 N64 的下一个起始位,但什么也没有。所以FPGA超时并恢复。
这是 N64 接收模块的 VHDL。它包含计数器:s_bitCount。
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity N64RX is
port(
N64RXD : in STD_LOGIC; --Data input
clk25 : in STD_LOGIC;
clr : in STD_LOGIC;
tdre : in STD_LOGIC; --detects when UART is ready
transmit : out STD_LOGIC; --Signal to UART to transmit
sel : out STD_LOGIC;
echoSig : out STD_LOGIC;
bitcount : out STD_LOGIC_VECTOR(3 downto 0);
data : out STD_LOGIC_VECTOR(3 downto 0) --The significant nibble
);
end N64RX;
--}} End of automatically maintained section
architecture N64RX of N64RX is
type state_type is (start, delay2us, sigSample, waitForStop, waitForStart, timeout, count9bits, sendToUART);
signal state: state_type;
signal s_sel, s_echoSig, s_timeoutDetect : STD_LOGIC;
signal s_baudCount : STD_LOGIC_VECTOR(6 downto 0); --Counting variable for baud rate in delay
signal s_bitCount : STD_LOGIC_VECTOR(3 downto 0); --Counting variable for number of bits recieved
signal s_data : STD_LOGIC_VECTOR(8 downto 0); --Signal for data
constant delay : STD_LOGIC_VECTOR(6 downto 0) := "0110010"; --Provided 25MHz, 50 cycles is 2us
constant delayLong : STD_LOGIC_VECTOR(6 downto 0) := "1100100";
begin
n64RX: process(clk25, N64RXD, clr, tdre)
begin
if clr = '1' then
s_timeoutDetect <= '0';
s_echoSig <= '1';
s_sel <= '0';
state <= start;
s_data <= "000000000";
transmit <= '0';
s_bitCount <= "0000";
s_baudCount <= "0000000";
elsif (clk25'event and clk25 = '1') then --on rising edge of clock input
case state is
when start =>
--s_timeoutDetect <= '0';
s_sel <= '0';
transmit <= '0'; --Don't request UART to transfer
s_data <= "000000000";
s_bitCount <= X"0";
if N64RXD = '1' then
state <= start;
elsif N64RXD = '0' then --if Start bit detected
state <= delay2us;
end if;
when delay2us => --wait two microseconds to sample
--s_timeoutDetect <= '0';
s_sel <= '1';
s_echoSig <= '0';
if s_baudCount >= delay then
state <= sigSample;
else
s_baudCount <= s_baudCount + 1;
state <= delay2us;
end if;
when sigSample =>
--s_timeoutDetect <= '1';
s_echoSig <= N64RXD;
s_bitCount <= s_bitCount + 1;
s_baudcount <= "0000000";
s_data <= s_data(7 downto 0) & N64RXD;
state <= waitForStop;
when waitForStop =>
s_echoSig <= N64RXD;
if N64RXD = '0' then
state <= waitForStop;
elsif N64RXD = '1' then
state <= waitForStart;
end if;
when waitForStart =>
s_echoSig <= '1';
s_baudCount <= s_baudCount + 1;
if N64RXD = '0' then
s_baudCount <= "0000000";
state <= delay2us;
elsif N64RXD = '1' then
if s_baudCount >= delayLong then
state <= timeout;
elsif s_bitCount >= X"9" then
state <= count9bits;
else
state <= waitForStart;
end if;
end if;
when count9bits =>
s_sel <= '0';
if tdre = '0' then
state <= count9bits;
elsif tdre = '1' then
state <= sendToUART;
end if;
when sendToUART =>
transmit <= '1';
if tdre = '0' then
state <= start;
else
state <= sendToUART;
end if;
when timeout =>
--s_timeoutDetect <= '1';
state <= start;
end case;
end if;
end process n64RX;
--timeoutDetect <= s_timeoutDetect;
bitcount <= s_bitCount;
echoSig <= s_echoSig;
sel <= s_sel;
data <= s_data(4 downto 1);
end N64RX;
那么,有什么想法吗?调试提示?编码有限状态机的技巧?
与此同时,我会继续玩它(我最终会拥有它)!帮我堆栈交换,你是我唯一的希望!
编辑
在我的调试中进一步发现,状态会从waitForStart跳回到waitForStop。我给每个状态一个值,waitForStart 等于“5”,waitForStop 等于“4”。见下图: