Forum: FPGA, VHDL & Co. Scheinbar einfacher VHDL-Code nicht Synthetisierbar? / Vivado 2019.2 / Artix7


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Matthias (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

mein Design ist nicht mehr synthetisierbar (Synthese braucht statt 
2-3Minuten --> unendlich lange), wenn folgender Code enthalten ist:
    type VGA_line is ARRAY(548 downto 0) of std_logic_vector(11 downto 0);
    type VGA_moni is ARRAY(1080 downto 0) of vga_line;
    signal VGA_monitor: VGA_moni;
    signal x : STD_LOGIC_VECTOR(11 downto 0) := (OTHERS => '0');
    signal y : STD_LOGIC_VECTOR(11 downto 0) := (OTHERS => '0');
    P1: Process(CLK100MHZ)
    BEGIN
        if rising_edge(CLK100MHZ) THEN
            if x < x"438" THEN
                if y < x"224" THEN
                    y <= STD_LOGIC_VECTOR(unsigned(y)+1);
                    VGA_monitor (to_integer(unsigned(x))) (to_integer(unsigned(y))) <= (OTHERS => '1') ;
                elsif y = x"224" THEN
                    VGA_monitor (to_integer(unsigned(x))) (to_integer(unsigned(y))) <= (OTHERS => '1') ;
                    y <= (OTHERs => '0');
                    x <= STD_LOGIC_VECTOR(unsigned(x)+1);
                END IF;
            END IF;
        end if;
    END PROCESS;

Verstehen würde ich es, wenn es eine Warnung/Fehler wegen der größe des 
Array's gäbe. Immerhin ~800KByte.

Aber warum sollte es generell nicht möglich sein das zu Synthetisieren?
Danke für eine Aufklärung ;)

Schöne Grüße,
Matthias

von muriel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Was verstehst du denn unter unendlich lange?

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Deine Beschreibung ist nicht typisch für BlockRAM. Die Synthese wird 
also versuchen statt BlockRAM LUTRAM/FFs zu verwenden. Und das kann sehr 
lange dauern bis die Synthese dann fertig ist. Dann bekommst du nach 
einiger Zeit die Meldung, dass dein FPGA zu >100% ausgelastet ist.

Ich würde das also so umschreiben, dass die Synthese das als RAM erkennt 
und BRAMs verwendet, dann geht das auch einigermaßen schnell.

Edit: Wenn du Artix schreibst, das passt sowieso nur in den dicksten 
XC7A200 rein. Verwendest du den?

: Bearbeitet durch User
von Robert P. (fpgazumspass) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Das würden nicht 800 KByte werden, sondern rund 1335Kbyte, weil 
Blockrams keine 12 Bit Breite können und demzufolge 18 Bit Breite 
verwendet werden muss.

Zum anderen ist der Array

- 2 Dimensional

- als geschachtelter Typ (in 2 Zeilen)

- als downto
beschrieben, also gleich 3 eher ungewöhnliche Dinge.

Mein Tipp: experimentier damit in geringerer Größe(z.b. 20x20) bis es 
ein Blockram wird, dann erhöhe die Größe.

Hier ist meine (gekürzte) Beschreibung eines Framebuffers die für einen 
Artix 7 mit 2019.2 Blockram synthetisiert, nur Schreibseite, Leseseite 
ist identisch in einem zweiten Prozess:
type tPixelArray is array(0 to (256 * 192) - 1) of std_logic_vector(17 downto 0);
signal PixelArray : tPixelArray := (others => (others => '0'));

process (clk100)
begin
   if rising_edge(clk100) then
         
      pixel_in_addr   <= pixel_in_x + (pixel_in_y * 256);
      if (pixel_in_we_1 = '1') then
         PixelArray(pixel_in_addr) <= pixel_in_data_1;
      end if;
      
   end if;
end process;

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Robert P. schrieb:
> Zum anderen ist der Array
> - 2 Dimensional
> - als geschachtelter Typ (in 2 Zeilen)
> - als downto beschrieben, also gleich 3 eher ungewöhnliche Dinge.
Weiterhin hat das Array ein "Off-by-One" Problem, weil jede Zeile ein 
Pixel zuviel hat und zudem das ganze Bild eine Zeile zuviel.

Matthias schrieb:
> Aber warum sollte es generell nicht möglich sein das zu Synthetisieren?
Was sthet denn im Synthesizer User Guide zum Thema RAMs? Wie musst du so 
ein RAM beschreiben, dass der Synthesizer das richtig erkennt und 
umsetzen kann?

> Verstehen würde ich es, wenn es eine Warnung/Fehler wegen der größe des
> Array's gäbe.
Und was passiert, wenn du nur so und zum Test die Arrays(*) etwas 
kleiner machst und "nur" VGA(**) ausgibst?

Wenn du die x und y zu Integern machst, dann wird dein Code ganz schnell 
leserlich. Dann musst du z.B. nicht laufend konvertieren und mit 
Hexzahlen vergleichen. Da sieht man dann schnell eigenartige Sachen:
    signal x : integer range 0 to 1080 := 0;
    signal y : integer range 0 to 548 := 0;
:
    P1: Process(CLK100MHZ)
    BEGIN
        if rising_edge(CLK100MHZ) THEN
            if x < 1080 THEN
                if y < 548 THEN
                    y <= y+1; -- (***)
                    VGA_monitor(x)(y) <= (OTHERS => '1') ; -- kurios:
                else -- hier ist y>= 548
                    VGA_monitor(x)(y) <= (OTHERS => '1') ; -- zweimal hintereinander das selbe?
                    y <= 0;
                    x <= x+1;
                END IF;
            END IF;
        end if;
    END PROCESS;

(*) besser ganz ohne Apostroph
(**) VGA hat 640x480 Pixel, insofern ist deine Namensgebung sehr 
unglücklich
(***) ich hoffe, dir ist an dieser Stelle das Verhalten von Signalen in 
Prozessen bekannt. Denn ich könnte die Reihenfolge der Zuweisungen in 
diesem Prozess mit dem selben Syntheseergebnis auch so sortieren:
    signal x : integer range 0 to 1080 := 0;
    signal y : integer range 0 to 548 := 0;
:
    P1: Process(CLK100MHZ)
    BEGIN
        if rising_edge(CLK100MHZ) THEN
            if x < 1080 THEN
                if y < 548 THEN
                    VGA_monitor(x)(y) <= (OTHERS => '1') ;
                    y <= y+1;
                else -- hier ist y >= 548
                    x <= x+1;
                    VGA_monitor(x)(y) <= (OTHERS => '1') ;
                    y <= 0;
                END IF;
            END IF;
        end if;
    END PROCESS;
Und natürlich könnte man das noch zusammenfassen und dafür sorgen, dass 
die Zähler nicht über die 548 bzw. 1080 Pixel hinauslaufen:
[/vhdl]
    signal x : integer range 0 to 1079 := 0;
    signal y : integer range 0 to 547 := 0;
:
    P1: Process(CLK100MHZ)
    BEGIN
        if rising_edge(CLK100MHZ) THEN
            if x <= 1079 THEN
                VGA_monitor(x)(y) <= (OTHERS => '1') ;
                if y < 547 THEN
                    y <= y+1;
                else
                    y <= 0;
                    x <= x+1;
                END IF;
            END IF;
        end if;
    END PROCESS;
[/vhdl]

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.