Фон
Это личный проект; это касается подключения FPGA к N64, байтовые значения, которые получает FPGA, затем отправляются через UART на мой компьютер. Это на самом деле работает довольно хорошо! К сожалению, в случайное время устройство выйдет из строя, а затем восстановится. Благодаря отладке мне удалось найти проблему, однако я нахожусь в тупике, как ее исправить, потому что я довольно некомпетентен с VHDL.
Я играю с VHDL уже пару дней и, возможно, я не в состоянии решить эту проблему.
Проблема
У меня есть осциллограф, который измеряет сигнал N64 в ПЛИС, а другой канал подключается к выходу ПЛИС. У меня также есть цифровые контакты, записывающие значение счетчика.
По сути, N64 отправляет 9 бит данных, включая бит STOP. Счетчик считает полученные биты данных, и когда я достигну 9 бит, FPGA начнет передачу через UART.
Вот правильное поведение:
ПЛИС - это синяя форма волны, а оранжевая форма - это вход N64. На время приема моя ПЛИС "эхом" передает сигнал ввода для целей отладки. После того, как 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;
Итак, есть идеи? Советы по отладке? Советы по кодированию конечных автоматов?
В то же время, я буду продолжать играть с этим (у меня это будет в конечном итоге)! Помоги мне Stack Exchange, ты моя единственная надежда!
редактировать
Еще одно открытие в моей отладке - состояния переместятся с waitForStart обратно на waitForStop. Каждому состоянию я присвоил значение с waitForStart, равным «5», и waitForStop, равным «4». Смотрите изображение ниже: