Auf den ersten Blick würde man erwarten, dass sich der folgende VHDL-Quellcode wie ein Schieberegister verhält. In diesem q wäre im Laufe der Zeit
"UUUU0", "UUU00", "UU000", "U0000", "00000", ....
Stattdessen ist es immer U
nach fünf (oder mehr) aufeinanderfolgenden Taktzyklen.
Warum ist das?
Dieser Code ist eigentlich eine stark vereinfachte Version einer weitaus komplizierteren Simulation. Aber es zeigt die Symptome, die ich sehe.
Es zeigt dieses interessante und unerwartete Ergebnis während der Simulation unter ModelSim und ActiveHDL. Ich habe keine anderen Simulatoren ausprobiert und möchte (zweitens zur Erklärung der Ursache) wissen, ob andere auf die gleiche Weise handeln.
Um diese Frage richtig zu beantworten, müssen Sie Folgendes verstehen:
- Ich weiß, dass dies nicht der beste Weg ist, ein Schieberegister zu implementieren
- Ich weiß, dass dies für die RTL-Synthese zurückgesetzt werden sollte.
- Ich weiß, dass ein Array von std_logic ein std_logic_vector ist.
- Ich kenne den Aggregationsoperator
&
.
Was ich auch gefunden habe:
- Wenn die Zuordnung
temp(0)<='0';
innerhalb des Prozesses verschoben wird, funktioniert sie. - Wenn die Schleife entpackt ist (siehe kommentierten Code), funktioniert sie.
Ich werde noch einmal betonen, dass dies eine sehr vereinfachte Version eines viel komplizierteren Designs (für eine Pipeline-CPU) ist, das so konfiguriert ist, dass nur die unerwarteten Simulationsergebnisse angezeigt werden. Die tatsächlichen Signaltypen sind nur eine Vereinfachung. Aus diesem Grund müssen Sie Ihre Antworten mit dem Code im Formular so wie er ist betrachten.
Ich vermute, dass der Optimierer der VHDL-Simulations-Engine fälschlicherweise (oder möglicherweise gemäß Spezifikation) nicht die Mühe macht, die Ausdrücke innerhalb der Schleife auszuführen, da sich keine Signale außerhalb ändern, obwohl ich dies widerlegen kann, indem ich die nicht verpackte Schleife in eine Schleife setze.
Ich gehe daher davon aus, dass die Antwort auf diese Frage eher mit den Standards für die VHDL-Simulation unerklärlicher VHDL-Syntax und der Art und Weise zu tun hat, wie VHDL-Simulationsmodule ihre Optimierungen vornehmen, als ob ein gegebenes Codebeispiel der beste Weg ist, etwas zu tun oder nicht.
Und nun zum Code, den ich simuliere:
library ieee;
use ieee.std_logic_1164.all;
entity test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end entity;
architecture example of test_simple is
type t_temp is array(4 downto 0) of std_logic;
signal temp : t_temp;
begin
temp(0) <= '0';
p : process (clk)
begin
if rising_edge(clk) then
for i in 1 to 4 loop
temp(i) <= temp(i - 1);
end loop;
--temp(1) <= temp(0);
--temp(2) <= temp(1);
--temp(3) <= temp(2);
--temp(4) <= temp(3);
end if;
end process p;
q <= temp(4);
end architecture;
Und der Prüfstand:
library ieee;
use ieee.std_logic_1164.all;
entity Bench is
end entity;
architecture tb of bench is
component test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end component;
signal clk:std_logic:='0';
signal q:std_logic;
signal rst:std_logic;
constant freq:real:=100.0e3;
begin
clk<=not clk after 0.5 sec / freq;
TB:process
begin
rst<='1';
wait for 10 us;
rst<='0';
wait for 100 us;
wait;
end process;
--Note: rst is not connected
UUT:test_simple port map (clk=>clk,q=>q) ;
end architecture;
temp(0)
keine "Ereignisse" zugeordnet sind. Durch das Einfügen der Zuweisung in process
wird eine Zuordnung zu den Uhrereignissen erstellt, die dazu führen, dass sie funktioniert. Ich frage mich, ob das Hinzufügen einer after
Klausel zur Zuweisung eine mögliche Problemumgehung wäre.