Фон
Це особистий проект; що стосується підключення FPGA до N64, значення байтів, які отримує FPGA, потім надсилаються через UART на мій комп'ютер. Він насправді функціонує досить добре! На випадковий час, на жаль, пристрій вийде з ладу, після чого відновиться. За допомогою налагодження мені вдалося знайти проблему, проте я наткнувся на те, як її виправити, оскільки я досить некомпетентний із VHDL.
Я вже пару днів граю з ВГДЛ, і, можливо, я не можу це вирішити.
Проблема
У мене є осцилограф, що вимірює сигнал N64 в FPGA, а інший канал підключається до виходу FPGA. У мене також є цифрові штифти, які записують значення лічильника.
По суті, N64 посилає 9 бітів даних, включаючи біт STOP. Лічильник підраховує отримані біти даних, і коли я досягаю 9 біт, FPGA починає передавати через UART.
Ось правильна поведінка:
FPGA - синя форма хвилі, а помаранчева - це вхід N64. Під час прийому моя FPGA "відголошує" сигнал входу для цілей налагодження. Після того, як FPGA налічує до 9, вона починає передавати дані через UART. Зауважте, що цифрові штифти нараховують до 9, а вихід FPGA стає низьким відразу після завершення N64.
Ось приклад відмови:
Зауважте, що лічильник пропускає біти 2 та 7! FPGA доходить до кінця, чекаючи наступного запуску біт від N64, але нічого. Таким чином, FPGA закінчується та відновлюється.
Це VHDL для модуля прийому N64. Він містить лічильник: 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". Дивіться зображення нижче: