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


von Matthias (Gast)


Lesenswert?

Hallo zusammen,

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


Lesenswert?

Was verstehst du denn unter unendlich lange?

von Gustl B. (-gb-)


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


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:
1
type tPixelArray is array(0 to (256 * 192) - 1) of std_logic_vector(17 downto 0);
2
signal PixelArray : tPixelArray := (others => (others => '0'));
3
4
process (clk100)
5
begin
6
   if rising_edge(clk100) then
7
         
8
      pixel_in_addr   <= pixel_in_x + (pixel_in_y * 256);
9
      if (pixel_in_we_1 = '1') then
10
         PixelArray(pixel_in_addr) <= pixel_in_data_1;
11
      end if;
12
      
13
   end if;
14
end process;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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:
1
    signal x : integer range 0 to 1080 := 0;
2
    signal y : integer range 0 to 548 := 0;
3
:
4
    P1: Process(CLK100MHZ)
5
    BEGIN
6
        if rising_edge(CLK100MHZ) THEN
7
            if x < 1080 THEN
8
                if y < 548 THEN
9
                    y <= y+1; -- (***)
10
                    VGA_monitor(x)(y) <= (OTHERS => '1') ; -- kurios:
11
                else -- hier ist y>= 548
12
                    VGA_monitor(x)(y) <= (OTHERS => '1') ; -- zweimal hintereinander das selbe?
13
                    y <= 0;
14
                    x <= x+1;
15
                END IF;
16
            END IF;
17
        end if;
18
    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:
1
    signal x : integer range 0 to 1080 := 0;
2
    signal y : integer range 0 to 548 := 0;
3
:
4
    P1: Process(CLK100MHZ)
5
    BEGIN
6
        if rising_edge(CLK100MHZ) THEN
7
            if x < 1080 THEN
8
                if y < 548 THEN
9
                    VGA_monitor(x)(y) <= (OTHERS => '1') ;
10
                    y <= y+1;
11
                else -- hier ist y >= 548
12
                    x <= x+1;
13
                    VGA_monitor(x)(y) <= (OTHERS => '1') ;
14
                    y <= 0;
15
                END IF;
16
            END IF;
17
        end if;
18
    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]

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.