vhdl seltsames Ausgangsflackern mit Prüfstand

Ich bin neu bei vhdl und fpga. Ich arbeite derzeit mit einem in vhdl programmierten basys3-Board mit vivado. Ich habe einen 3 (binär) bis 8 (dezimal) -Dencoder mit einer for-Schleife erstellt. Mein Prüfstand ist auch mit einer for-Schleife. Was ich jetzt bemerke, ist ein seltsames Flackern der Ausgabe zwischen meinen normalen Ausgabeänderungen. Kann mir jemand eine Ursache für dieses Problem nennen?

hauptsächlich:

entity bindec38 is
Port ( sw : in STD_LOGIC_VECTOR (2 downto 0) := (others => '0');
       led : out STD_LOGIC_VECTOR (7 downto 0)  := (others => '0'));
end bindec38;

architecture Behavioral of bindec38 is
begin
process (sw)
variable int : integer := 0; 
begin

    int := to_integer(unsigned(sw));
    for j in 0 to 7 loop
        if (int = j) then
           led(int) <= '1'; -- correct schrijven deze led hoog
        else  
           led(j) <= '0'; -- schrijven de andere dan laag tijdens de loop
        end if;
    end loop;
end process;

end Behavioral;

Prüfstand:

entity simdec is
--  Port ( );
end simdec;

architecture Behavioral of simdec is

component bindec38 is
    Port ( sw : in STD_LOGIC_VECTOR (2 downto 0);
       led : out STD_LOGIC_VECTOR (7 downto 0));
end component bindec38;

-- input signal
signal sw : STD_LOGIC_VECTOR (2 downto 0) := (others => '0');
-- output singal
signal led : STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
begin

UUT: bindec38
Port Map (sw => sw, led => led);

-- sim process
sim_pro: process begin   
for i in 0 to 7 loop
sw <= std_logic_vector(to_unsigned(i, 3));
wait for 100 ns;    
end loop;

wait;
end process;            

end Behavioral;

siehe die Simulationsausgabe, Simulationes passiert nur in 2 von 8 Übergängen.

Wow, so etwas sehe ich zum ersten Mal in einem Simulator

Antworten (2)

Sie haben einen asynchronen Decoder entworfen und eine Nachimplementierung oder Timing-Simulation durchgeführt.

Da eine Timing-Simulation das reale Timing Ihres platzierten und gerouteten Designs verwendet, hat jedes Signal ein geringfügig anderes Timing, selbst wenn die Signale Teil desselben logischen Elements sind, wie beispielsweise swin Ihrem Fall.

Unabhängig davon, welche Logik Ihr FPGA zur Implementierung der Schaltung verwendet, da es asynchron ist, wenn die Signale zu unterschiedlichen Zeiten am Eingang dieser Logik ankommen, wechselt der Ausgang in einigen Fällen durch Zwischenzustände, wenn Ihr logisches Element nur einmal übergeht. Wie die andere Antwort zeigt, erzeugen diese Rennbedingungen Runt-Impulse in der Ausgabe.

Am Beispiel des Übergangs swvon 3nach sind die möglichen Übergänge in den binären Signalen, die diese Zahl darstellen, abhängig von der detaillierten Führung dieser Signale im FPGA:4

"011" > "111" > "110" > "100" = 3 > 7 > 6 > 4
"011" > "111" > "101" > "100" = 3 > 7 > 5 > 4
"011" > "010" > "110" > "100" = 3 > 2 > 6 > 5
"011" > "010" > "000" > "100" = 3 > 2 > 0 > 4
"011" > "001" > "000" > "100" = 3 > 1 > 0 > 4
"011" > "001" > "101" > "100" = 3 > 1 > 5 > 4
"011" > "101" > "100" = 3 > 5 > 4
"011" > "110" > "100" = 3 > 6 > 4
"011" > "100" = 3 > 4

Wie Sie sehen können, könnte Ihr Einer-aus-n-Decoder je nach Routing und resultierendem Timing während des Übergangs in eine Vielzahl von Eingängen sehen swund so eine entsprechende Vielzahl von Ausgängen erzeugen. Beachten Sie, dass die Zwischenübergänge in einem sehr kurzen Zeitraum auftreten, typischerweise unter 1 Nanosekunde in einem modernen FPGA.

Vergleichen wir dies mit einem der Übergänge, der keine Runts in der Ausgabe anzeigt, wenn von nach swgeht . Die möglichen Übergänge sind:45

"100" > "101" = 4 > 5

Da sich nur ein Bit ändert, gibt es nur einen möglichen Übergang. Daher sehen Sie an diesem Übergang keine Runts, egal wie die Signale geroutet werden.

Lassen Sie uns nun darüber nachdenken, wie die Tools Ihre Schaltung tatsächlich implementieren. Sie können den implementierten Schaltplan einchecken, aber jeder ledAusgang sollte von einem separaten Look-Up-Table-Element (LUT) angesteuert werden. Sie können die Tools verwenden, um die logische Gleichung jeder LUT anzuzeigen, aber im Wesentlichen werden sie prüfen, ob die 3-Bit- swEingabe dieser bestimmten entspricht led. Wo die andere Antwort falsch ist, dass, nur weil die Logik in einer einzigen LUT implementiert ist, dies nicht bedeutet, dass diese Rennbedingungen nur ein Simulationsartefakt sind.

Um dies wieder auf den Übergang zu beziehen 3, 4da jede ledAusgabe in einer anderen LUT implementiert ist, wird das von jeder LUT gesehene Timing unterschiedlich sein. Wir sehen Runt-Impulse an den Ausgängen 1, 2, 6und . 7Daraus können wir ableiten, dass die LUT für led(1)sah entweder 3 > 1 > 0 > 4 oder 3 > 1 > 5 > 4, led(2)sah entweder 3 > 2 > 6 > 5 oder 3 > 2 > 0 > 5 und so weiter.

Der übliche Weg, Runts zu vermeiden, ist die Verwendung eines synchronen Designs, dh eines, das eine Uhr verwendet. swBeachten Sie, dass die Eingabe ( in diesem Fall) auch synchron zu sein muss, damit dies zuverlässig funktioniert clk.

process(clk)
begin
  if (rising_edge(clk)) then
    led <= (others => '0');
    led(to_integer(unsigned(sw)) <= '1';
  end if;
end process;

Nun sieht der eine von n Decoder immer noch die variierenden Übergänge an den LUT-Eingängen und hat entsprechende Runts an den LUT-Ausgängen, aber diese Ausgänge speisen dann ein Register. Da in einem synchronen System, das das Timing erfüllt hat, die Übergänge alle abgeschlossen sein werden, wenn die Taktflanke auftritt, wird die endgültige Ausgabe keine Runt-Impulse aufweisen.

Eine andere Möglichkeit besteht darin, zu entscheiden, dass Sie sich nicht um diese Runt-Impulse kümmern. In einem Design, das einfach einige LEDs ansteuert, ist es Ihnen wahrscheinlich egal, ob die Möglichkeit besteht, dass die falsche LED für 0,5 Nanosekunden aufleuchtet.

Der wichtigste Punkt bei all dem ist, dass dies nicht nur Simulationsartefakte sind und in einem Design Probleme in der realen Welt verursachen können.

Wenn das Ding im Großen und Ganzen von einem Zähler irgendeiner Form gesteuert wird, können Sie manchmal Gray-Codes verwenden, um das Problem mit Fabric-Verzögerungen zu vermeiden, das dieses Problem selbst im Fall einer einzelnen LUT verursacht (@scary_jeff hat damit recht). Der einzelne LUT-Fall entfernt die logische Verzögerung aus dem Bild, lässt aber die Ausbreitungszeiten durch die Struktur.

Das Sagen ist, dass es nur auftritt, wenn zwei der Eingänge gleichzeitig den Zustand ändern ...

Grundsätzlich haben Sie zumindest für den Simulator eine Rennbedingung, bei der die Logik, die einen Ausgang ansteuert, zwei verschiedene Pfade mit unterschiedlichen Ausbreitungsverzögerungen hat, und daher erhalten Sie einen Runt-Impuls, bis der zweite Logiksatz aufholt. Wenn Sie viel im Schaltplan haben, den Ihr Werkzeug produziert, sollten Sie dies sehen.

Beachten Sie, dass dies in einer synthetisierten Schaltung auf einem echten Gate-Array wirklich passieren kann oder nicht, da ich vermute, dass mit nur 3 Eingängen im Spiel alles tatsächlich auf 1 LUT pro Ausgang zusammenbricht, was dieses Problem eindeutig nicht hat.

Dies ist wahrscheinlich ein Simulationsartefakt (aber etwas, das Sie in asynchroner Logik erhalten können), da ein Pfad, der diese Ausgänge ansteuert, ein Gate mehr im Wert von Delta-Zyklen hat als ein anderer, sodass Sie die Race-Bedingung sehen.