Sehen Sie sich dieses Stück Code an (Bild auf X umdrehen)
PROCESS(iCLK)
BEGIN
IF (rising_edge(iCLK)) THEN
-- Mise en mémoire du pixel
ram(640*IdxC + PixX) <= PIXIN;
-- Choix traitement
IF (SWITCH='1') THEN
PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX);
ELSE
PIXOUT <= ram(640*(2-IdxC) - PixX + 1);
END IF;
END IF;
END PROCESS;
Wenn ich es kompiliere, nimmt das Gesamtprojekt etwa 15 % der Logikelemente und 13 % der gesamten Speicherbits ein (QuartusII auf Zyklon III). Wenn ich den Code auf ändere
PROCESS (iCLK)
BEGIN
IF(rising_edge(iCLK)) THEN
-- Mise en mémoire du pixel
ram(640*IdxC + PixX) <= PIXIN;
-- Choix traitement
IF (SWITCH='1') THEN
PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX);
ELSE
IF (PixX > 1 AND PixX < 640) THEN
PIXOUT <= ram(640*(2-IdxC) - PixX + 1);
ELSE
PIXOUT <= x"111";
END IF;
END IF;
END IF;
END PROCESS;
Ich bekomme
Error (276003): Cannot convert all sets of registers into RAM megafunctions when creating nodes. The resulting number of registers remaining in design exceeds the number of registers in the device or the number specified by the assignment max_number_of_registers_from_uninferred_rams. This can cause longer compilation time or result in insufficient memory to complete Analysis and Synthesis
Das scheint, dass ich das Design nicht mehr anpassen kann. Ich glaube das nicht. Gibt es einen Fehler im Compiler oder mache ich etwas falsch?
Ich habe die Quartus II Web Edition
Fügen Sie einfach einige --
Kommentare wie folgt in die Zeilen ein und es wird erneut kompiliert:
PROCESS (iCLK)
BEGIN
IF (rising_edge(iCLK)) THEN
-- Mise en mémoire du pixel
ram(640*IdxC + PixX) <= PIXIN;
-- Choix traitement
IF (SWITCH='1') THEN
PIXOUT <= ram(640*((IdxC + 1) mod 2) + PixX);
ELSE
-- IF (PixX > 1 AND PixX < 640) THEN
PIXOUT <= ram(640*(2-IdxC) - PixX + 1);
-- ELSE
-- PIXOUT <= x"111";
-- END IF;
END IF;
END IF;
END PROCESS;
Dieser Code funktioniert mit dem Megafunktions-RAM 2-Port:
PROCESS (iCLK)
BEGIN
IF rising_edge(iCLK) THEN
-- Ecrire linéairement dans la RAM le pixel de la cam
RAMWRITE <= TO_UNSIGNED(640*IdxC + PixX - 1, 11);
-- Choix traitement
IF (SWITCH='1') THEN
RAMREAD <= TO_UNSIGNED(640*((IdxC + 1) mod 2) + PixX - 1, 11);
PIXOUT <= PIXMEM;
ELSE
RAMREAD <= TO_UNSIGNED(640*(2-IdxC) - PixX, 11);
IF (PixX > 1 AND PixX < 640) THEN
PIXOUT <= PIXMEM;
ELSE
PIXOUT <= x"FFF";
END IF;
END IF;
END IF;
END PROCESS;
Ich würde nicht sagen, dass es ein Fehler ist, es ist eher eine Einschränkung, und in gewisser Weise macht es absolut Sinn. Sie wollen, dass es auf ein Dual-Port-Ram schlussfolgert, der Compiler will auf ein Dual-Port-RAM schliessen, aber der Prozess im Problem-Snippet beschreibt die Adresseingabe des Leseports des Rams nicht richtig, weil nicht alle Pfade abgedeckt sind, also es müsste ein Latch ableiten, während Sie wirklich wollen, dass es egal ist. Damit machst du es dem Compiler im Grunde schwer.
Beachten Sie, dass zum Ableiten des RAM auch einige Signale und deren Werte abgeleitet werden müssen, von denen eines der Adresseingang ist. Im synchronen Verfahren ist der Wert für dieses abgeleitete Signal für den Fall, der in PIXOUT <= x"111" endet, nicht definiert. Es müsste also ein Latch abgeleitet werden, und die Warnung wäre ein umständliches "Schluss-Latch auf abgeleitetes Adresssignal des abgeleiteten RAM". Am Ende ist es etwas zu viel, also gibt es wahrscheinlich auf, aber dann passt die alternative Lösung nicht zum Gerät. Ich sage nicht, dass dies der genaue Grund ist, warum es aufgibt, aber es sollte klar sein, dass der Compiler Schwierigkeiten haben würde, die Lücken für den abgeleiteten RAM zu füllen, wenn man bedenkt, wie dieser Prozess codiert wurde.
Alle Lösungen, die funktionieren, decken alle Fälle für das Adresssignal ab, gefolgert oder nicht. Sie könnten das Deklarieren des Signals testen und es dann auf die gleiche Weise codieren, sodass es auf einen Latch schließen muss, und es kann sogar kompiliert werden, da es jetzt zumindest ein explizit deklariertes Signal hätte, auf das es sich beziehen kann.
Die Codierungsstile zum Ableiten von RAM-Blöcken für Altera finden Sie unter http://www.altera.com/literature/hb/qts/qts_qii51007.pdf#page13
Dies ist einer der Gründe, warum dringend empfohlen wird, dass Sie, wenn Sie vorhandene Hardwareblöcke verwenden möchten, diese entweder als solche instanziieren, um Mehrdeutigkeiten zu vermeiden, oder den geeigneten Codierungsstilen folgen, damit sie einfach und angemessen abgeleitet werden können.
Beachten Sie auch, dass sich ein Simulator damit nicht befassen müsste, da er nicht per se auf einen RAM-Block schließen und sich mit dem mehrdeutigen Don't Care vs Latch dieses Phantomsignals befassen müsste, da es in der Simulation nicht existiert.
David Tweed
Olivier Monnom
user_1818839
David Tweed
user_1818839
else PIXOUT <= ram(some addr) or x"111";
ausreichen wird ...Olivier Monnom