バックグラウンド
これは個人的なプロジェクトです。FPGAをN64に接続すると、FPGAが受信したバイト値はUARTを介してコンピューターに送信されます。それは実際にはかなりうまく機能します!不幸にも不定期に、デバイスは失敗し、その後回復します。デバッグによって問題を見つけることができましたが、VHDLにはかなりの能力がないため、修正方法に困惑しています。
私は2日間VHDLをいじっていて、これを解決できないかもしれません。
問題
FPGAへのN64信号を測定するオシロスコープがあり、他のチャネルはFPGAの出力に接続しています。カウンター値を記録するデジタルピンもあります。
基本的に、N64はSTOPビットを含む9つのデータビットを送信します。カウンターは受信したデータビットをカウントし、9ビットに達すると、FPGAはUARTを介して送信を開始します。
正しい動作は次のとおりです。
FPGAは青色の波形で、オレンジ色の波形はN64の入力です。受信中、私のFPGAはデバッグの目的で入力の信号を "エコー"します。FPGAが9までカウントした後、UARTを介してデータの送信を開始します。N64が終了した直後にデジタルピンが9にカウントされ、FPGA出力がLOWになることに注意してください。
失敗の例を次に示します。
カウンターがビット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」の値を指定しました。下の画像をご覧ください。