배경
이것은 개인 프로젝트입니다. FPGA를 N64에 연결하는 것과 관련하여 FPGA가 수신하는 바이트 값은 UART를 통해 내 컴퓨터로 전송됩니다. 실제로는 꽤 잘 작동합니다! 불행히도 임의의 시간에 장치가 실패한 다음 복구됩니다. 디버깅을 통해 문제를 찾을 수 있었지만 VHDL에 대해 무능하기 때문에 문제를 해결하는 방법에 어려움이 있습니다.
나는 며칠 동안 VHDL과 함께 놀았으며 이것을 해결할 수 없을 수도 있습니다.
문제
N64 신호를 FPGA로 측정하는 오실로스코프가 있고 다른 채널은 FPGA의 출력에 연결됩니다. 카운터 값을 기록하는 디지털 핀도 있습니다.
기본적으로 N64는 STOP 비트를 포함하여 9 개의 데이터 비트를 전송합니다. 카운터는 수신 된 데이터 비트를 카운트하고 9 비트에 도달하면 FPGA는 UART를 통해 전송을 시작합니다.
올바른 동작은 다음과 같습니다.
FPGA는 파란색 파형이고 주황색 파형은 N64의 입력입니다. 수신 기간 동안, FPGA는 디버깅 목적으로 입력 신호를 "echos"합니다. FPGA는 9로 카운트 한 후 UART를 통해 데이터를 전송하기 시작합니다. 디지털 핀은 9로 카운트되고 N64가 완료된 직후 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'인 값을 지정했습니다. 아래 이미지를보십시오 :