Jak debugować czerwone sygnały w ModelSIM?

11

Muszę zaprojektować maszynę stanową, używając tylko bramek NAND dla części kombinatorycznej i klapek D dla logiki sekwencyjnej. Wszystko powinno działać z zegarem 1 GHz / 53.

Teraz, zanim zaatakujesz mnie słowami „nie odrabimy za ciebie pracy domowej”, powiem ci, że złomowałem wszystko po inwestowaniu dni pracy i zacząłem robić wszystko bardziej rygorystycznie. Chcę to zrobić sam, ale ciągle otrzymuję losowe niezdefiniowane sygnały w najprostszych częściach projektu i jest to frustrujące.

Ok, więc przede wszystkim mam maszynę stanu i tabelę prawdy, którą zrobiłem dla niej na poniższym obrazku:

Schemat automatu stanów i tabela prawdy dla niego

Następną rzeczą są kmapy:

The Kmaps

Ponieważ w przypadku klapek D D = Q + okablowanie logiki kombinatorycznej (po zbudowaniu jej w uproszczonym bloku) nie powinno być zbyt trudne.

Ale mój pierwszy problem pojawia się na stanowisku testowym dla Q3 +. Pozwolę sobie umieścić tutaj w celu uproszczenia informacji szybki schemat, który przygotowałem dla Q3 +:

Schemat logiczny dla Q3 +

W dalszej części postu zobaczysz, że w VHDL faktycznie nazwałem wejścia in1Q3plus na in11Q3plus (11 wejść), ponieważ nie jest to ostatni blok (ostatni kombinacyjny blok logiczny składa się z czterech połączonych bloków Q3 +, Q2 +, Q1 +, Q0 + do sygnałów).

Musiałem więc zrobić wszystko przy użyciu bram NAND, co oznacza, że ​​musiałem przyjąć podejście strukturalne. Każda brama bazuje w zasadzie na bramkach NAND, a następnie nabiera złożoności (ale tylko bramki AND, OR i NOT są zapisywane strukturalnie z bramek NAND). Następnie mam bramkę OR z 3 wejściami, bramkę AND z 3 wejściami i bramkę OR z 5 wejściami (jak w przykładzie ze schematem logicznym), każde w oparciu o poprzednie 2 bramki AND i OR.

Każde stanowisko testowe aż do Q3plus (powyższy schemat) działało. Moja procedura testowania polega na wytwarzaniu sygnałów dla każdego wejścia, dzięki czemu mogę wygodnie oglądać sygnały w oknie Symulacji. Na przykład mam następujące sygnały dla 3-wejściowej bramki AND:

process
    begin
a1 <= '0' ; wait for 4ns;
a1 <= '1' ; wait for 4ns;
end process;

process
    begin
b1 <= '0' ; wait for 8ns;
b1 <= '1' ; wait for 8ns;
end process;

process
    begin
c1 <= '0' ; wait for 2ns;
c1 <= '1' ; wait for 2ns;
end process;

Połączenia wyglądałyby tak:

u1:ANDgate3 port map(A=>a1, B=>b1, C=>c1, fand3=>q1 );

Problem pojawia się, gdy chcę symulować stanowisko testowe Q3plus. Wygląda na to, że mam błąd tam, gdzie jest najmniej oczekiwany, na sygnale testowym, który zmienia wartość z 0 na 1 z okresem 2ns: |. Zamieszczę tutaj kod stanowiska testowego, po raz kolejny stwierdzając, że każde inne stanowisko testowe bramy działało bezbłędnie:

library ieee;
use ieee.std_logic_1164.all;

entity Q3plusTEST is
end Q3plusTEST;

architecture behavior of Q3plusTEST is
    component Q3plus is
    port(outQ3plus: out std_Logic;
    in1Q3plus: in std_Logic;
    in2Q3plus: in std_Logic;
    in3Q3plus: in std_Logic;
    in4Q3plus: in std_Logic;
    in5Q3plus: in std_Logic;
    in6Q3plus: in std_Logic;
    in7Q3plus: in std_Logic;
    in8Q3plus: in std_Logic;
    in9Q3plus: in std_Logic;
    in10Q3plus: in std_Logic;
    in11Q3plus: in std_Logic);
    end component;

signal a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11, outsignal: std_logic;

begin
    process
    begin
        a1<= '0'; wait for 4ns;
        a1<= '1'; wait for 4ns;
    end process;

    process
    begin
        a2<= '0'; wait for 6ns;
        a2<= '1'; wait for 6ns;
    end process;

    process
    begin
        a3<= '0'; wait for 8ns;
        a3<= '1'; wait for 8ns;
    end process;

    process
    begin
        a4<= '0'; wait for 10ns;
        a4<= '1'; wait for 10ns;
    end process;

    process
    begin
        a5<= '0'; wait for 12ns;
        a5<= '1'; wait for 12ns;
    end process;

    process
    begin
        a6<= '0'; wait for 14ns;
        a6<= '1'; wait for 14ns;
    end process;

    process
    begin
        a7<= '0'; wait for 16ns;
        a7<= '1'; wait for 16ns;
    end process;

    process
    begin
        a8<= '0'; wait for 18ns;
        a8<= '1'; wait for 18ns;
    end process;

    process
    begin
        a9<= '0'; wait for 20ns;
        a9<= '1'; wait for 20ns;
    end process;

    process
    begin
        a10<= '0'; wait for 22ns;
        a10<= '1'; wait for 22ns;
    end process;

    process
    begin
        a1<= '0'; wait for 24ns;
        a1<= '1'; wait for 24ns;
    end process;

    U1: Q3plus port map(in1Q3plus=> a1, in2Q3plus=>a2, in3Q3plus=>a3, in4Q3plus=>a4, in5Q3plus=>a5, in6Q3plus=>a6, in7Q3plus=>a7, in8Q3plus=>a8, in9Q3plus=>a9, in10Q3plus=>a10, in11Q3plus=>a11, outQ3plus=> outsignal); end behavior;

A kod rzeczywistego bloku Q3plus to:

 library ieee;
use ieee.std_logic_1164.all;

entity Q3plus is
    port(outQ3plus: out std_Logic;
    in1Q3plus: in std_Logic;
    in2Q3plus: in std_Logic;
    in3Q3plus: in std_Logic;
    in4Q3plus: in std_Logic;
    in5Q3plus: in std_Logic;
    in6Q3plus: in std_Logic;
    in7Q3plus: in std_Logic;
    in8Q3plus: in std_Logic;
    in9Q3plus: in std_Logic;
    in10Q3plus: in std_Logic;
    in11Q3plus: in std_Logic);
    end Q3plus;

architecture behavior of Q3plus is
    component ORgate5 is
    port(AOR5: in std_logic;
    BOR5: in std_logic;
    COR5: in std_logic;
    DOR5: in std_logic;
    EOR5: in std_logic;
    f5or: out std_logic);
    end component;

    component ANDgate3 is
    port(A: in std_logic;
    B: in std_logic;
    C: in std_logic;
    fand3: out std_logic);
    end component;

    component ANDgate is
    port(xand: in std_logic;
    yand: in std_logic;
    fand: out std_logic);
    end component;

signal z1,z2,z3,z4,z5: std_logic;

begin
    U1: ANDgate port map(xand=> in1Q3plus, yand=> in2Q3plus, fand=> z1);
    U2: ANDgate port map(xand=> in3Q3plus, yand=> in4Q3plus, fand=> z2);
    U3: ANDgate port map(xand=> in5Q3plus, yand=> in6Q3plus, fand=> z3);
    U4: ANDgate port map(xand=> in7Q3plus, yand=> in8Q3plus, fand=> z4);
    U5: ANDgate3 port map(A=> in9Q3plus, B=> in10Q3plus, C=> in11Q3plus, fand3=> z5);
-- urmeaza toate portile de mai sus conectate la OR5
    U6: ORgate5 port map(AOR5=>z1, BOR5=> z2, COR5=> z3, DOR5=> z4, EOR5=> z5, f5or=> outQ3plus);

end behavior;

Stanowisko testowe daje następujący wynik:

symulacja stanowiska testowego

Jak widać, pierwszy sygnał ma dziwne zachowanie, następne sygnały działają poprawnie, a ostatni jest całkowicie niezdefiniowany. Oczywiście końcowy sygnał, wyjście, jest wadliwy.

Moje proste pytanie brzmiałoby: w jaki sposób mogę śledzić, gdzie sygnał zaczyna być uszkodzony? Czuję się jak totalny noob w tym bałaganie programu i naprawdę chcę to zakończyć. Z góry dziękuję za każdą odpowiedź.

Azur
źródło
1
Bardzo dobra prezentacja pytania. Chociaż Modelsim może zezwolić, 18nsjest to szczególnie nielegalne w standardzie VHDL i tak pozostanie. Istnieją dwa oddzielne elementy leksykalne, abstrakcyjny literał 18i identyfikator ns. Patrz IEEE Std 1076-2008 15.3 Elementy leksykalne, separatory i ograniczniki, ust. 4 - „.... Wymagany jest co najmniej jeden separator między identyfikatorem lub literałem abstrakcyjnym a sąsiadującym identyfikatorem lub literałem abstrakcyjnym”. Możesz napisać swój bodziec jako jeden proces, używając przyrostowego czasu w instrukcjach oczekiwania. Być może wskazywał bezpośrednio na niedoświadczony sygnał.
user8352
Czy możesz rozwinąć część dotyczącą bodźca? Myślę, że to, co powiedziałeś, jest czymś, czego często szukałem, ale nic nie znalazłem: ostrzeżeń, które wydają moje każde stanowisko testowe. Czy masz na myśli, że powinienem wpisać spację między 18 a ns ? edytuj Zweryfikowano, to był problem.
Azurium

Odpowiedzi:

9

Miło jest zobaczyć odpowiedni testbench i kod, który faktycznie pasuje do pytania o zmianę ...

Istnieją dwa proste sposoby na uszkodzenie sygnału:

  • napędzaj go z kilku źródeł sygnału
  • nie kieruj nim z żadnego

Teraz A11 pozostaje „U” przez cały czas, co sugeruje, że nie ma sterownika. Podczas gdy A1 zmienia na przemian prawidłowe i „X” nieprawidłowe wartości, co sugeruje, że ma więcej niż jeden sterownik.

Mając to na uwadze, sprawdź kod, w którym jeździsz A1 i A11.

Będziesz się śmiać ...

Aby rozwinąć część pytania „jak debugować”: wzbudzając podejrzenie, że sygnały nie były wyprowadzane z oczekiwanych źródeł, można użyć polecenia „Drivers” Modelsim, aby wyświetlić listę sterowników dla sygnału. Jeśli napisałeś nieco bardziej szczegółowy VHDL i oznaczyłeś każdy proces, uzyskałbyś tę samą odpowiedź bez konieczności przeglądania kodu ...

na przykład

Drive_A1 : process
begin
   a1 <= '0' ; wait for 4ns;
   ... etc
Brian Drummond
źródło
2
Cała ta frustracja, która narastała godzinami, wybuchnęła dobrym śmiechem. Zasługuję również na dobre uderzenie w twarz. Stanowisko testowe wydaje się teraz działać!
Azurium