Beim Schreiben von VHDL empfehle ich dringend, std_logic_vector (slv) anstelle von integer (int) für SIGNALS zu verwenden . (Andererseits kann die Verwendung von int für Generika, einige Konstanten und einige Variablen sehr nützlich sein.) Einfach ausgedrückt, wenn Sie ein Signal vom Typ int deklarieren oder einen Bereich für eine Ganzzahl angeben müssen, tun Sie dies wahrscheinlich etwas stimmt nicht.
Das Problem mit int ist, dass der VHDL-Programmierer keine Ahnung hat, wie die interne Logik des int aussieht, und wir sie daher nicht nutzen können. Wenn ich beispielsweise ein Int im Bereich von 1 bis 10 definiere, habe ich keine Ahnung, wie der Compiler diese Werte codiert. Hoffentlich wird es als 4 Bit codiert, aber darüber hinaus wissen wir nicht viel. Wenn Sie die Signale im FPGA prüfen könnten, könnten sie als "0001" bis "1010" oder als "0000" bis "1001" codiert sein. Es ist auch möglich, dass es auf eine Weise codiert ist, die für uns Menschen absolut keinen Sinn ergibt.
Stattdessen sollten wir nur slv anstelle von int verwenden, da wir dann die Kontrolle über die Codierung haben und auch direkten Zugriff auf die einzelnen Bits haben. Ein direkter Zugriff ist wichtig, wie Sie später sehen werden.
Wir könnten einfach ein int in slv umwandeln, wenn wir Zugriff auf die einzelnen Bits benötigen, aber das wird sehr chaotisch, sehr schnell. Das ist, als würde man das Schlimmste aus beiden Welten bekommen, anstatt das Beste aus beiden Welten. Ihr Code ist für den Compiler schwer zu optimieren und für Sie fast unmöglich zu lesen. Ich empfehle das nicht.
Wie gesagt, mit slv haben Sie die Kontrolle über die Bitcodierungen und den direkten Zugriff auf die Bits. Was können Sie damit machen? Ich zeige Ihnen einige Beispiele. Angenommen, Sie müssen alle 4.294.000.000 Takte einmal einen Impuls ausgeben. So würden Sie dies mit int machen:
signal count :integer range 0 to 4293999999; -- a 32 bit integer
process (clk)
begin
if rising_edge(clk) then
if count = 4293999999 then -- The important line!
count <= 0;
pulse <= '1';
else
count <= count + 1;
pulse <= '0';
end if;
end if;
end process;
Und der gleiche Code mit slv:
use ieee.numeric_std.all;
signal count :std_logic_vector (32 downto 0); -- a 33 bit integer, one extra bit!
process (clk)
begin
if rising_edge(clk) then
if count(count'high)='1' then -- The important line!
count <= std_logic_vector(4293999999-1,count'length);
pulse <= '1';
else
count <= count - 1;
pulse <= '0';
end if;
end if;
end process;
Der größte Teil dieses Codes ist zwischen int und slv identisch, zumindest im Sinne der Größe und Geschwindigkeit der resultierenden Logik. Natürlich zählt einer hoch und der andere runter, aber das ist für dieses Beispiel nicht wichtig.
Der Unterschied liegt in "der wichtigen Linie".
Mit dem Beispiel int wird dies zu einem Komparator mit 32 Eingängen führen. Bei 4-Eingangs-LUTs, die der Xilinx Spartan-3 verwendet, sind 11 LUTs und 3 Logikstufen erforderlich. Einige Compiler konvertieren dies möglicherweise in eine Subtraktion, die die Übertragskette verwendet und das Äquivalent von 32 LUTs umfasst, jedoch möglicherweise schneller als 3 Logikebenen ausgeführt wird.
Im SLV-Beispiel gibt es keinen 32-Bit-Vergleich, also "Null LUTs, Null Logikpegel". Die einzige Strafe ist, dass unser Zähler ein zusätzliches Bit ist. Da das zusätzliche Timing für dieses zusätzliche Zählerbit alle in der Übertragskette liegt, gibt es eine zusätzliche Timing-Verzögerung "fast Null".
Dies ist natürlich ein extremes Beispiel, da die meisten Leute auf diese Weise keinen 32-Bit-Zähler verwenden würden. Dies gilt zwar für kleinere Zähler, der Unterschied ist jedoch weniger dramatisch, obwohl er immer noch signifikant ist.
Dies ist nur ein Beispiel für die Verwendung von slv over int, um ein schnelleres Timing zu erzielen. Es gibt viele andere Möglichkeiten, slv zu nutzen - es bedarf nur einiger Vorstellungskraft.
Update: Es wurden Inhalte hinzugefügt, um Martin Thompsons Kommentare zur Verwendung von int mit "if (count-1) <0" zu adressieren.
(Hinweis: Ich gehe davon aus, dass Sie "if count <0" gemeint haben, da dies meiner SLV-Version mehr entspricht und die Notwendigkeit dieser zusätzlichen Subtraktion beseitigt.)
Unter bestimmten Umständen kann dies zu der beabsichtigten Logikimplementierung führen, es kann jedoch nicht garantiert werden, dass sie immer funktioniert. Dies hängt von Ihrem Code ab und davon, wie Ihr Compiler den int-Wert codiert.
Abhängig von Ihrem Compiler und der Art und Weise, wie Sie den Bereich Ihres int angeben, ist es durchaus möglich, dass ein int-Wert von Null nicht in einen Bitvektor von "0000 ... 0000" codiert, wenn er in die FPGA-Logik aufgenommen wird. Damit Ihre Variation funktioniert, muss sie in "0000 ... 0000" codiert sein.
Angenommen, Sie definieren ein Int mit einem Bereich von -5 bis +5. Sie erwarten, dass ein Wert von 0 in 4 Bits wie "0000" und +5 als "0101" und -5 als "1011" codiert wird. Dies ist das typische Zweikomplement-Codierungsschema.
Aber nehmen Sie nicht an, dass der Compiler Zweierkomplement verwenden wird. Obwohl ungewöhnlich, könnte das Einsen-Komplement zu einer "besseren" Logik führen. Oder der Compiler könnte eine Art "voreingenommene" Codierung verwenden, wobei -5 als "0000", 0 als "0101" und +5 als "1010" codiert wird.
Wenn die Codierung des int "korrekt" ist, wird der Compiler wahrscheinlich ableiten, was mit dem Übertragsbit zu tun ist. Aber wenn es falsch ist, wird die resultierende Logik schrecklich sein.
Es ist möglich, dass die Verwendung eines int auf diese Weise zu einer angemessenen logischen Größe und Geschwindigkeit führt, dies ist jedoch keine Garantie. Wenn Sie zu einem anderen Compiler wechseln (z. B. XST zu Synopsis) oder zu einer anderen FPGA-Architektur wechseln, kann genau das Falsche passieren.
Unsigned / Signed vs. slv ist eine weitere Debatte. Sie können dem Ausschuss der US-Regierung dafür danken, dass er uns so viele Optionen für VHDL gegeben hat. :) Ich benutze slv, weil dies der Standard für die Schnittstelle zwischen Modulen und Kernen ist. Abgesehen davon und in einigen anderen Fällen in Simulationen glaube ich nicht, dass die Verwendung von slv gegenüber signierten / nicht signierten einen großen Vorteil hat. Ich bin mir auch nicht sicher, ob signierte / nicht signierte Unterstützung dreifach angegebene Signale unterstützen.