Arka fon
Bu kişisel bir projedir; bir FPGA'nın bir N64'e bağlanmasıyla ilgili olarak, FPGA'nin aldığı bayt değerleri daha sonra UART üzerinden bilgisayarıma gönderilir. Aslında oldukça iyi çalışıyor! Ne yazık ki rastgele zamanlarda, cihaz başarısız olur, sonra iyileşir. Hata ayıklama yoluyla, sorunu bulmayı başardım, ancak VHDL ile oldukça beceriksiz olduğum için nasıl düzeltileceğimi bilemiyorum.
Birkaç gündür VHDL ile oynuyorum ve bunu çözemeyebilirim.
Sorun
FPGA'ya N64 sinyalini ölçen bir osiloskopum var ve diğer kanal FPGA'nın çıkışına bağlanıyor. Ayrıca sayaç değerini kaydeden dijital pinlerim var.
Esasen N64, bir DUR biti dahil 9 veri biti gönderir. Sayaç alınan veri bitlerini sayar ve 9 bite ulaştığımda FPGA UART üzerinden iletim yapmaya başlar.
İşte doğru davranış:
FPGA mavi dalga formudur ve turuncu dalga formu N64'ün girdisidir. Alma süresi boyunca, FPGA benim hata ayıklama amacıyla giriş sinyalini "echos". FPGA 9'a kadar saydıktan sonra, verileri UART üzerinden aktarmaya başlar. N64 bittikten hemen sonra dijital pinlerin 9'a ve FPGA çıkışının DÜŞÜK olduğuna dikkat edin.
İşte bir başarısızlık örneği:
Sayacın 2. ve 7. bitleri atladığına dikkat edin! FPGA sona ulaştı, N64'ten bir sonraki başlangıç bitini bekliyor ama hiçbir şey. Böylece FPGA zaman aşımına uğrar ve iyileşir.
Bu, N64 alma modülü için VHDL'dir. Şu sayacı içerir: 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;
Peki, herhangi bir fikir? Hata ayıklama ipuçları? Sonlu Durum Makinelerinin kodlanması hakkında ipuçları?
Bu arada, onunla oynamaya devam edeceğim (sonunda alacağım)! Stack Exchange'e yardım et, sen benim tek umudumsun!
Düzenle
Hata ayıklamamda bir başka keşifte, durumlar waitForStart'tan waitForStop'a geri dönecek. Her duruma '5' değerine waitForStart ve '4' değerine waitForStop ile bir değer verdim. Aşağıdaki resme bakın: