Problem beim Synthetisieren

Ich versuche, die strukturelle Implementierung des Ringzählers zu implementieren. Ich bekomme diesen Fehler:

ERROR:Xst:528 - Multisource in Unit <ringcounter> bei Signal <count<3>>; Dieses Signal ist mit mehreren Treibern verbunden.

Ich konnte es erfolgreich simulieren. Dieses Modul ist Teil des Projekts, das ich umsetze!..

Hier ist mein VHDL-Code:

entity DFF is
    Port (
      reset : in STD_LOGIC;
      clk : in  STD_LOGIC;
      D : in  STD_LOGIC;
      Q : out  STD_LOGIC);
end DFF;

architecture Behavioral of DFF is
begin

    process(clk,reset)
    begin
        if reset = '1' then
            Q <= '0';    -- clear register
        elsif (clk'event and clk = '1') then
            Q<=D; --positive edge of clock is used
        end if;
    end process;

end Behavioral;

--Code for ring counter

entity ringcounter is
  Port ( reset : in STD_LOGIC;
         clk : in  STD_LOGIC;
         count : out  STD_LOGIC_VECTOR (3 downto 0));
end ringcounter;

architecture Behavioral of ringcounter is

    signal q0,q1,q2,q3 : STD_LOGIC : = '0'; ---initialising the signals

    --signal temp :STD_LOGIC :       = '1'; --not using it as of now.

    component DFF is
        Port ( reset : in STD_LOGIC;
              clk : in  STD_LOGIC;
               D : in  STD_LOGIC;
               Q : out  STD_LOGIC);
    end component;

begin

    q3<= '1';

    DFF1: DFF port map(reset,clk,q3,q0);

    DFF2: DFF port map(reset,clk,q0,q1);

    DFF3: DFF port map(reset,clk,q1,q2);

    DFF4: DFF port map(reset,clk,q2,q3);

    count <= q3&q2&q1&q0;

end Behavioral;

Was läuft schief?

bearbeiten

Ich habe die Änderungen wie vorgeschlagen vorgenommen, aber während der Simulation wird die Ausgabe nicht für die Ringzählerausgabe aktualisiert, obwohl ich die Uhr angegeben habe! Die Ausgabe ist noch undefiniert!

Unten ist der geänderte Code

entity DFF is
    Port ( reset : in STD_LOGIC;
           clk : in  STD_LOGIC;
           D : in  STD_LOGIC;
           Q : out  STD_LOGIC);
end DFF;

architecture Behavioral of DFF is
begin

    process(clk,reset)
    begin
        if reset='1' then
            Q <= '0';    -- clear register
        elsif (clk'event and clk='1') then
            Q<=D; --positive edge of clock is used
        end if;
    end process;

end Behavioral;


------------CODE OF RING COUNTER-----------------------

entity ringcounter is
    Port ( reset : in STD_LOGIC;
           clk : in  STD_LOGIC;
           count : out  STD_LOGIC_VECTOR (3 downto 0));
end ringcounter;

architecture Behavioral of ringcounter is

    signal q0,q1,q2 : STD_LOGIC := '0'; ---initialising the signals

    signal q3 :STD_LOGIC := '1';

    component DFF is
        Port ( reset : in STD_LOGIC;
               clk : in  STD_LOGIC;
               D : in  STD_LOGIC;
               Q : out  STD_LOGIC);
    end component;

begin

    DFF1: DFF port map(reset,clk,q3,q0);

    DFF2: DFF port map(reset,clk,q0,q1);

    DFF3: DFF port map(reset,clk,q1,q2);

    DFF4: DFF port map(reset,clk,q2,q3);

    count <= q3&q2&q1&q0;

end Behavioral;

Ja, ich habe Reset angegeben. Dieses Mal wird der Wert nur auf Null gesetzt und es findet kein Übergang statt, was sehr offensichtlich ist, als ich versuchte, ein Flipflop mit voreingestelltem Eingang einzufügen, das einen 1-Wert in den Flipflop-Ring pumpt! ... Ich simuliere es nur. Wie stelle ich den Wert so ein, dass er nach dem Zurücksetzen/Voreinstellen verschoben wird? Übersehe ich eine Prozedur? ...

Das Problem ist jetzt also: Wie initialisiere ich alle Flipflops und beginne danach mit dem Schalten nacheinander mit dem Simulator? ...

Ich habe versucht, das Verhaltensmodell zu verwenden, ohne DFF zu verwenden. Unten ist der Code für dasselbe.

Entität ringCounter_BehaviorModel ist

Port ( CLK : in  STD_LOGIC;

       CLR : in  STD_LOGIC;

       Q : inout  STD_LOGIC_VECTOR (3 downto 0);

       NQ : inout  STD_LOGIC_VECTOR (3 downto 0));

EndringCounter_BehaviorModel;

Architektur Verhalten von ringCounter_BehaviorModel ist

Start

verarbeiten (CLK, CLR)

beginnen wenn (CLR ='0') dann

          Q<= "1000";                   

      elsif (CLR ='1') then

if CLK'event and CLK='1' then

        Q(0) <= Q(3);

        for i in 0 to 2 loop

        Q(i+1) <= Q(i);

        end loop;

    end if;

end if;

Prozess beenden;

Ende Verhalten;

Meine Frage ist, wenn ich es simuliere, erzwinge ich den Wert von clr auf 0, um den Zähler auf 1000 zu initialisieren, und gebe dem Takteingang ein Taktsignal. Nachdem ich auf Ausführen geklickt habe, konnte ich die Werte von Q als 1000 sehen, aber die Werte bleiben gleich, selbst wenn ich beobachte, dass der Takt zwischen 0 und 1 variiert.

Wenn ich es erneut ausführe, gehen alle Werte verloren und ich muss die Werte erneut erzwingen.

Bei clr = '1' erfolgt keine Initialisierung und keine Hoffnung auf Verschiebung der gewünschten Werte. Übersehe ich einen Punkt im Verfahren oder sollte ich den Code ändern oder ist die gemachte Beobachtung im Falle einer Simulation in Ordnung?

Die Zusammenfassung des Problems bleibt also immer noch dieselbe und besteht nur darin, den Ringzähler zu initialisieren und zu beginnen, sich im System zu drehen.

Könnten Sie genauer sagen, woher der Fehler kommt - welches Tool verwenden Sie Xilinx ISE oder Altera Quartus oder ähnliches?
bei deiner Bearbeitung - hast du einen Reset angegeben? Das Initialisieren des q3Signals bei der Deklaration wird nichts für die Simulation tun, da es von einer DFFInstanz gesteuert wird.
1) Setzen Sie während Ihres Tests nach dem ersten Taktimpuls clr auf 1? wenn es auf 1 bleibt, "gewinnt" die if clk-Kante nie 2) Sie brauchen das elsif CLR='1' nicht, es ist implizit, weil wir sonst den if CLR='0'-Pfad nehmen würden 3) Sie sollten es generell vermeiden inout außer beim Instanziieren von bidirektionalen Bussen der obersten Ebene, verwenden Sie out in der Portdeklaration und verwenden Sie Signale intern, z. B. signal q_int : std_logic_vector(3 downto 0); und ganz unten Q <= q_int; 4) Der bessere Weg, diese Rotation zu handhaben, wäre q_int <= q_int(2 downto 0) & q_int(3) innerhalb der if clk-Kante.

Antworten (3)

Innerhalb des Ringzählers wird q3 sowohl durch die gleichzeitige Zuweisung q3<='1' als auch durch DFF4 zugewiesen. Beides gleichzeitig kann man nicht haben.

Ich bin mir nicht sicher, ob das den beabsichtigten Effekt haben wird. ringcounterDie DFFs sind alle in einem Ring miteinander verkettet - wie kann man beim Zurücksetzen initialisiert werden, ohne einen zweiten Treiber hinzuzufügen?

Du machst unnötige Arbeit. Sie sollten kein DFF-Primitive erstellen müssen. Der Synther ist schlau genug, um einen std_logic_vector, der sozusagen „getaktet“ ist (dh von einem Prozessblock mit clk in der Sensitivitätsliste umgeben ist), in eine Sammlung von DFFs umzuwandeln.

Beseitigen Sie das DFF-Primitive, erstellen Sie stattdessen einen std_logic_vector und erstellen Sie dann in Ringcounter einen Prozess, der beim Zurücksetzen (Ihr Reset ist asynchron, übrigens, falls das für Sie einen Unterschied macht) Ihren std_logic_vector mit dem Standardwert lädt Sie wollen (zB "1000"). Und dann dreht es bei einer steigenden Taktflanke jedes Element des Ringzählers nach links.

Wenn Sie dabei Probleme haben, kann ich später noch einmal vorbeischauen und Ihnen zeigen, wie es geht. Aber ich lasse Sie lieber zuerst versuchen, es selbst herauszufinden.

Ich habe die von dir genannte Methode ausprobiert. Wo ich ein klares Signal verwende, um das Flip-Flop zu initialisieren und bei steigender Taktflanke die Daten zu verschieben.

Wie die Antwort von Apalopohapa zeigt, besteht Ihr Problem darin, dass mehrere Treiber dasselbe Signal verwenden. Die Anweisung q3 <= '1'ist immer aktiv - es ist nicht nur eine Initialisierung. Da Sie std_logicand not std_ulogicverwenden, ist dies technisch gesehen kein Fehler, und der Simulator wird es problemlos ausführen (möglicherweise mit unbeabsichtigten Ergebnissen, obwohl das Problem manchmal maskiert wird, weil es sich zufällig in etwas löst, das funktioniert).

Wenn Sie möchten, dass Ihr Zähler nach dem Zurücksetzen um startet "1000"und jede Uhr rotiert (was so aussieht, als würden Sie es tun), wäre eine Möglichkeit, ihn DFFso zu ändern, dass er optional Qauf voreingestellt werden kann '1', anstatt ihn immer auf zurückzusetzen '0'. Sie könnten dies tun, indem Sie entweder eine presetEingabe oder ein generisches oder etwas hinzufügen, das seinen Initialisierungswert festlegt. Es gibt auch andere Ansätze, die funktionieren würden.