Latar Belakang
Ini adalah proyek pribadi; itu tentang menghubungkan FPGA ke N64, nilai byte yang diterima FPGA kemudian dikirim melalui UART ke komputer saya. Ini sebenarnya berfungsi cukup baik! Sayangnya, secara acak, perangkat akan gagal, lalu pulih. Melalui debugging, saya sudah berhasil menemukan masalah, namun saya bingung bagaimana cara memperbaikinya karena saya cukup tidak kompeten dengan VHDL.
Saya sudah bermain-main dengan VHDL selama beberapa hari sekarang dan saya mungkin tidak mampu menyelesaikan ini.
Masalah
Saya memiliki osiloskop yang mengukur sinyal N64 ke dalam FPGA, dan saluran lainnya terhubung ke output FPGA. Saya juga memiliki pin digital yang merekam nilai penghitung.
Pada dasarnya, N64 mengirimkan 9 bit data, termasuk bit STOP. Penghitung menghitung bit data yang diterima dan ketika saya mencapai 9 bit, FPGA mulai mentransmisikan melalui UART.
Inilah perilaku yang benar:
FPGA adalah bentuk gelombang biru dan bentuk gelombang oranye adalah input dari N64. Selama menerima, FPGA saya "menggema" sinyal input untuk keperluan debugging. Setelah jumlah FPGA menjadi 9, FPGA mulai mengirimkan data melalui UART. Perhatikan bahwa pin digital dihitung hingga 9 dan output FPGA menjadi RENDAH segera setelah N64 selesai.
Berikut ini contoh kegagalan:
Perhatikan bahwa penghitung melompati bit 2 dan 7! FPGA mencapai akhir, menunggu bit awal berikutnya dari N64 tetapi tidak ada. Jadi, FPGA mati dan pulih.
Ini adalah VHDL untuk modul penerimaan N64. Ini mengandung penghitung: 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;
Jadi, ada ide? Kiat debugging? Tips tentang pengkodean Mesin Hingga Negara?
Sementara itu, saya akan terus bermain-main dengannya (saya akan memilikinya pada akhirnya)! Bantu saya Stack Exchange, Anda satu-satunya harapan saya!
Edit
Penemuan lebih lanjut dalam debugging saya, negara akan melompat dari waitForStart kembali ke waitForStop. Saya memberi setiap negara nilai dengan waitForStart sama dengan '5' dan waitForStop sama dengan '4'. Lihat gambar di bawah ini: