De fondo
Este es un proyecto personal; se refiere a la conexión de un FPGA para un N64, los valores de bytes que el FPGA recibe luego son enviados a través de la UART para mi equipo. Que funciona realmente muy bien! A veces al azar por desgracia, el dispositivo va a fallar, luego se recupera. A través de la depuración, me las he arreglado para encontrar el problema, sin embargo, estoy perplejo en cómo solucionarlo porque estoy bastante incompetente con VHDL.
He estado jugando con el VHDL para un par de días y me puede ser incapaz de resolver esto.
El Problema
Tengo un osciloscopio medir la N64 de la señal en la FPGA, y el otro canal se conecta a la salida de la FPGA. También tengo los pines digitales de grabación el valor del contador.
Esencialmente, la N64 envía 9 bits de datos, incluyendo un bit de PARADA. El contador cuenta los bits de datos recibidos y cuando llego a 9 bits, el FPGA empieza a transmitir a través de UART.
Aquí el comportamiento correcto:
El FPGA es la forma de onda azul y el naranja de la forma de onda es la entrada de la N64. Para la duración de la recepción, mi FPGA "echos" la señal de la entrada para propósitos de depuración. Después de la FPGA cuenta a 9, comienza la transmisión de datos a través de la UART. Observe que los pines digitales contar hasta 9 y el FPGA salida pasa a nivel BAJO, inmediatamente después de la N64 es terminado.
He aquí un ejemplo de un fracaso:
Aviso de que el contador se salta los bits 2 y 7! El FPGA llega a la final, a la espera para el siguiente bit de inicio de la N64, pero nada. Así que la FPGA y se recupera.
Este es el VHDL para el N64 recibir módulo. Contiene el contador: 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;
Así que, ¿alguna idea? Sugerencias de depuración? Consejos sobre la codificación de Máquinas de Estado Finito?
Mientras tanto, voy a seguir jugando con ella (voy a tener que eventualmente)! Me ayudan Intercambio de la Pila, tú eres mi única esperanza!
Editar
Un descubrimiento en mi depuración, los estados va a saltar de waitForStart de vuelta a waitForStop. Me dio a cada estado un valor con waitForStart igual a '5' y waitForStop igual a '4'. Ver la imagen de abajo: