Contexte
Ceci est un projet personnel; en ce qui concerne la connexion d'un FPGA à un N64, les valeurs d'octets que le FPGA reçoit sont ensuite envoyées via UART à mon ordinateur. Il fonctionne plutôt bien! À des moments aléatoires, malheureusement, l'appareil échouera, puis récupérera. Grâce au débogage, j'ai réussi à trouver le problème, mais je suis perplexe sur la façon de le résoudre car je suis assez incompétent avec VHDL.
Je joue avec le VHDL depuis quelques jours et je suis peut-être incapable de résoudre ce problème.
Le problème
J'ai un oscilloscope mesurant le signal N64 dans le FPGA, et l'autre canal se connecte à la sortie du FPGA. J'ai également des broches numériques enregistrant la valeur du compteur.
Essentiellement, le N64 envoie 9 bits de données, dont un bit STOP. Le compteur compte les bits de données reçus et lorsque j'atteins 9 bits, le FPGA commence à transmettre via UART.
Voici le comportement correct:
Le FPGA est la forme d'onde bleue et la forme d'onde orange est l'entrée du N64. Pendant la durée de réception, mon FPGA "fait écho" le signal de l'entrée à des fins de débogage. Une fois que le FPGA compte jusqu'à 9, il commence à transmettre les données via UART. Notez que les broches numériques comptent jusqu'à 9 et que la sortie FPGA devient FAIBLE immédiatement après la fin du N64.
Voici un exemple d'échec:
Notez que le compteur ignore les bits 2 et 7! Le FPGA atteint la fin, attendant le prochain bit de démarrage du N64 mais rien. Le FPGA expire donc et récupère.
Il s'agit du VHDL pour le module de réception N64. Il contient le compteur: 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;
Alors, des idées? Conseils de débogage? Conseils sur le codage des machines à états finis?
En attendant, je continuerai à jouer avec (je l'aurai éventuellement)! Aidez-moi Stack Exchange, vous êtes mon seul espoir!
Éditer
Une autre découverte dans mon débogage, les états passeront de waitForStart à waitForStop. J'ai donné à chaque état une valeur avec waitForStart égal à '5' et waitForStop égal à '4'. Voir l'image ci-dessous: