Forum: FPGA, VHDL & Co. dsub(vga) Monitor out of range


von Justin (Gast)


Lesenswert?

Hallo,

was bedeutet wenn auf einem Monitor folgende Ausgabe kommt:

"out of range

   23.7Khz / 38Hz"

Ich habe eine OV7670 Kamera und ein VGA Modul an meinen FPGA angepinned 
und ein VHDL Programm dazu geschrieben, erfolgreich synthetisiert und 
implementiert.

Ich habe auch die Clock für den VGA Teil meines Vhdl Programms halbiert, 
sodass eigentlich fast die korrekte Bildwiederholungsrate erreich werden 
kann:


Nun steht da aber irgendwas von 23.7Khz / 38Hz.


Wie kann man sowas debuggen?



SIGNAL clk25  :STD_LOGIC;

begin
   frame_addr <= std_logic_vector(address(16 downto 2));

  process (clk50)
begin
  if clk50'event and clk50='1' then
    if (clk25 = '0')then
      clk25 <= '1';
    else
      clk25 <= '0';
    end if;
  end if;
end process;

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Justin schrieb:

> was bedeutet wenn auf einem Monitor folgende Ausgabe kommt:
>
> "out of range
>
>    23.7Khz / 38Hz"

Dass dein Monitor diese Zeilen- und Bildfrequenz nicht synchronisieren 
kann.

Vermutlich ist ihm eine oder beide davon zu langsam. Üblich waren/sind 
31,5 kHz Horizontalfrequenz und mindestens 50 Hz Vertikalfrequenz.

von Justin (Gast)


Lesenswert?

Okay danke.

Dann liegt es vielleicht am Modul frame_buffer, welcher das Bindeglied 
zwischen capture Modul und vga Modul ist (ein synchroner Dual Port Block 
Ram).

Der bekommt von der capture Seite die PixelClock .
Das Problem ist, dass ich die clkb (also die Clock von VGA Seite 50MHZ ) 
nicht benutze in frame_buffer?



entity frame_buffer is
  generic(
    ADDR_WIDTH: integer := 15;
    DATA_WIDTH: integer := 8
    );
    Port ( clka : in  STD_LOGIC;
           wea : in  STD_LOGIC;
           addra : in  STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
           dina : in  STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
           clkb : in  STD_LOGIC;
           addrb : in  STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
           doutb : out  STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0));
end frame_buffer;

architecture Behavioral of frame_buffer is

  type ram_type is array (2**ADDR_WIDTH-1 downto 0)
    of STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
  signal ram: ram_type;
  signal addr_b_reg: STD_LOGIC_VECTOR(ADDR_WIDTH-1 downto 0);

begin
  process(clka)
  begin
    if(clka'event and clka = '1') then
      if(wea = '1') then
        ram(to_integer(unsigned(addra))) <= dina;
      end if;
      addr_b_reg <= addrb;
    end if;
  end process;

  doutb <= ram(to_integer(unsigned(addr_b_reg)));


end Behavioral;



Beste Grüße

von tja (Gast)


Lesenswert?

nein, daran liegt es sicher nicht.

Lies dir doch nochmal genau durch was Jörg geschrieben hat:

Jörg W. schrieb:
> Dass dein Monitor diese Zeilen- und Bildfrequenz nicht synchronisieren
> kann.
>
> Vermutlich ist ihm eine oder beide davon zu langsam. Üblich waren/sind
> 31,5 kHz Horizontalfrequenz und mindestens 50 Hz Vertikalfrequenz.


Und dann ließ dir durch, was in Wikipedia über Röhrenmonitore steht bzw. 
über das VGA Signal über DSUB Buchse, und dann simulierst du einfach mal 
dein VGA Modul und schaust, ob das alles zusammenpasst.

von tja (Gast)


Lesenswert?

Justin schrieb:
> SIGNAL clk25  :STD_LOGIC;
>
> begin
>    frame_addr <= std_logic_vector(address(16 downto 2));
>
>   process (clk50)
> begin
>   if clk50'event and clk50='1' then
>     if (clk25 = '0')then
>       clk25 <= '1';
>     else
>       clk25 <= '0';
>     end if;
>   end if;
> end process;

btw. das ist ganz böse!!!! Sowas macht man gar nicht. Entweder du gehst 
über eine PLL oder du erzeugst dir ein Clock-Enable Signal!

von Justin (Gast)


Lesenswert?

Hallo,

ich glaube meine Clock hatte die falsche Frequenz.
Bei einer Resolution von 600x800 und 60 HZ Bildwiederholungsrate 
benötige nach dieser Formel hier:

1056*628*60=39.8Mhz Clock

Diese Formel habe ich in Pong chu's Buch gefunden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Könnte passen.  800 x 600 ist jenseits der originalen VGA-Spec, aber 
heutige Monitore sollten das natürlich alle können.

von Justin (Gast)


Angehängte Dateien:

Lesenswert?

Jetzt erscheint auch etwas auf dem Monitor. Allerdings ist das Ergebnis 
sehr dürftig . Ich sehe nur blaue, rote und grüne Streifen :(.
Siehe angefügtes Bild.

Beste Grüße

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Sieht aus, als würdest du die Synchronimpulse noch nicht richtig auf die 
Reihe bekommen.

von Duke Scarring (Gast)


Lesenswert?

Versuch doch erstmal ein Testbild über VGA auszugeben, einfach um 
sicherzustellen, das die Ausgabe funktioniert.

Zu VGA in VHDL sollte es genügend Tutorials/Youtube-Videos geben...

Duke

von Arno (Gast)


Lesenswert?

Tipp zum Timing von VGA: Schau dir 
http://xtiming.sourceforge.net/cgi-bin/xtiming.pl an.

MfG, Arno

von Justin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo ich habe einige Parameter meine Implementierung geändert und es 
ist nun wenigstens ein wenig vom Kamerabild zu erkennen.
Wenn auch etwas komisch, das Bild wiederholt sich zweimal.



Hier das Hdl Modul:

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
-- Uncomment the following library declaration if using
5
-- arithmetic functions with Signed or Unsigned values
6
use IEEE.NUMERIC_STD.ALL;
7
8
-- Uncomment the following library declaration if instantiating
9
-- any Xilinx primitives in this code.
10
--library UNISIM;
11
--use UNISIM.VComponents.all;
12
13
entity vga is
14
    Port ( clk50 : in  STD_LOGIC;
15
           vga_red : out  STD_LOGIC_VECTOR (2 downto 0);
16
           vga_green : out  STD_LOGIC_VECTOR (2 downto 0);
17
           vga_blue : out  STD_LOGIC_VECTOR (2 downto 1);
18
           vga_hsync : out  STD_LOGIC;
19
           vga_vsync : out  STD_LOGIC;
20
           frame_addr : out  STD_LOGIC_VECTOR (14 downto 0);
21
           frame_pixel : in  STD_LOGIC_VECTOR (7 downto 0));
22
end vga;
23
24
architecture Behavioral of vga is
25
   -- Timing constants
26
   constant hRez       : natural := 640;
27
   constant vRez       : natural := 480;
28
29
   constant hMaxCount  : natural := 799;
30
   constant hStartSync : natural := 655;
31
   constant hEndSync   : natural := 751;
32
   constant vMaxCount  : natural := 525;
33
   constant vStartSync : natural := 490;
34
   constant vEndSync   : natural := 491;
35
   constant hsync_active : std_logic := '1';
36
   constant vsync_active : std_logic := '1';
37
38
   signal hCounter : unsigned(10 downto 0) := (others => '0');
39
   signal vCounter : unsigned(9 downto 0) := (others => '0');
40
   signal address : unsigned(16 downto 0) := (others => '0');
41
   signal blank : std_logic := '1';
42
  SIGNAL clk25  :STD_LOGIC;
43
44
begin
45
   frame_addr <= std_logic_vector(address(16 downto 2));
46
  
47
  process (clk50)
48
begin
49
  if clk50'event and clk50='1' then
50
    if (clk25 = '0')then
51
      clk25 <= '1';
52
    else
53
      clk25 <= '0';
54
    end if;
55
  end if;
56
end process;  
57
   
58
   process(clk25)
59
   begin
60
      if rising_edge(clk25) then
61
         -- Count the lines and rows      
62
         if hCounter = hMaxCount-1 then
63
            hCounter <= (others => '0');
64
            if vCounter = vMaxCount-1 then
65
               vCounter <= (others => '0');
66
            else
67
               vCounter <= vCounter+1;
68
            end if;
69
         else
70
            hCounter <= hCounter+1;
71
         end if;
72
73
         if blank = '0' then
74
            vga_red   <= frame_pixel(7 downto 5);
75
            vga_green <= frame_pixel(4 downto 2);
76
            vga_blue  <= frame_pixel(1 downto 0);
77
         else
78
            vga_red   <= (others => '0');
79
            vga_green <= (others => '0');
80
            vga_blue  <= (others => '0');
81
         end if;
82
   
83
         if vCounter  >= vRez then
84
            address <= (others => '0');
85
            blank <= '1';
86
         else 
87
            if hCounter  >= 0 and hCounter  < 640 then
88
               blank <= '0';
89
               
90
               address <= address+1;
91
               
92
            else
93
               blank <= '1';
94
            end if;
95
         end if;
96
   
97
         
98
         if hCounter > hStartSync and hCounter <= hEndSync then
99
            vga_hSync <= hsync_active;
100
         else
101
            vga_hSync <= not hsync_active;
102
         end if;
103
104
         
105
         if vCounter >= vStartSync and vCounter <= vEndSync then
106
            vga_vSync <= vsync_active;
107
         else
108
            vga_vSync <= not vsync_active;
109
         end if;
110
      end if;
111
   end process;
112
end Behavioral;

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


Lesenswert?

Der Clock 25MHz ist Käse. Mach da mal einem anständigen Clock-Enable 
draus.

Justin schrieb:
> das Bild wiederholt sich zweimal.
Wieviele solcher selbstgebastelten Takte sind in deinem Design?

Justin schrieb:
> ein VHDL Programm dazu geschrieben, erfolgreich synthetisiert und
> implementiert.
Ich kann dir einen Dreizeiler schreiben, der sich problemlos 
synthetisieren und implementieren lässt und trotzdem nicht wie erwartet 
funktioniert.
Oder volksnah: man kann auch Käse synthetisch herstellen, wenn man die 
Zutaten für Käse in den Prozess gibt.

BTW: warum misst du nicht einfach mal, wie deine Sync Impulse passen? 
Und zudem: passt das Timing wenigstens in der Simulation?

von -gb- (Gast)


Lesenswert?

Simulawer? Der Code aus seinem letzten Post hat unbelegte Signale, das 
wurde sicher nicht simuliert. Aber ja, das sollte man mal simulieren.

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


Angehängte Dateien:

Lesenswert?

-gb- schrieb:
> Aber ja, das sollte man mal simulieren.
Naja, sieht so schlecht erstmal nicht aus. Deshalb habe ich auf die 
Messtechnik hingewiesen. Wäre ja ungeschickt, wenn da am Synceingang nur 
etwa 2,5V High-Pegel ankämen. Denn das könnte so einem 5V-Röhrenhobel 
evtl. nicht ganz reichen...

von -gb- (Gast)


Lesenswert?

Das stimmt also wäre es gut wenn er es misst oder eine Fertighardware 
verwendet die das richtig macht. So ein FPGA eval Board.
Ich würde da generell erstmal einfacher rangehen. Also z. B. ein 
Rechteck auf die äußerste Pixelreihen malen die sichtbar sein sollen. 
Das geht ganz einfach und wenn das gut sichtbar ist würde ich mir über 
den RAM Gedanken machen.

von Justin (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe nun mal ein example vga projekt raufgeladen und siehe Bild 
läuft da alles perfekt.

Der RAM dieses FPGAs beträgt 360kb.Vielleicht sollte ich mal auf 240x180 
Auflösung versuchen??
Habe mir letztens noch extra einen SRAM bestellt, dürfte auch bald 
kommen.
Der könnte die ganze Problematik dann lösen.



hier mein aktueller framebuffer vhd code:



1
----------------------------------------------------------------------------------
2
-- Company: 
3
-- Engineer: 
4
-- 
5
-- Create Date:    00:47:27 09/09/2019 
6
-- Design Name: 
7
-- Module Name:    frame_buffer - Behavioral 
8
-- Project Name: 
9
-- Target Devices: 
10
-- Tool versions: 
11
-- Description: 
12
--
13
-- Dependencies: 
14
--
15
-- Revision: 
16
-- Revision 0.01 - File Created
17
-- Additional Comments: 
18
--
19
----------------------------------------------------------------------------------
20
library IEEE;
21
use IEEE.STD_LOGIC_1164.ALL;
22
23
-- Uncomment the following library declaration if using
24
-- arithmetic functions with Signed or Unsigned values
25
use IEEE.NUMERIC_STD.ALL;
26
27
-- Uncomment the following library declaration if instantiating
28
-- any Xilinx primitives in this code.
29
--library UNISIM;
30
--use UNISIM.VComponents.all;
31
32
entity frame_buffer is
33
  generic(
34
    ADDR_WIDTH: integer := 15;
35
    DATA_WIDTH: integer := 8
36
    );
37
    Port ( clka : in  STD_LOGIC;
38
           wea : in  STD_LOGIC;
39
           addra : in  STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
40
           dina : in  STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
41
           clkb : in  STD_LOGIC;
42
           addrb : in  STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
43
           doutb : out  STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0));
44
end frame_buffer;
45
46
architecture Behavioral of frame_buffer is
47
48
  type ram_type is array (2**ADDR_WIDTH-1 downto 0)
49
    of STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
50
  signal ram: ram_type;
51
  signal addr_b_reg: STD_LOGIC_VECTOR(ADDR_WIDTH-1 downto 0);
52
  SIGNAL clk25  :STD_LOGIC;
53
  
54
begin
55
56
  process (clkb)
57
     begin
58
    if clkb'event and clkb='1' then
59
          if (clk25 = '0')then
60
             clk25 <= '1';
61
          else
62
             clk25 <= '0';
63
          end if;
64
       end if;
65
     end process;
66
67
  process(clka)
68
  begin
69
    if(clka'event and clka = '1') then
70
      if(wea = '1') then
71
        ram(to_integer(unsigned(addra))) <= dina;
72
      end if;
73
      addr_b_reg <= addrb;
74
    end if;
75
  end process;
76
  
77
  process(clk25)
78
  begin
79
    doutb <= ram(to_integer(unsigned(addr_b_reg)));
80
  end process;
81
    
82
  
83
84
end Behavioral;

von Robert P. (fpgazumspass) Benutzerseite


Lesenswert?

Je nachdem was du vorhast brauchst du keinen vollständigen Framebuffer.
Viele (die meisten?) Homecomputer und Konsolen bis ~1990 hatten sowas 
gar nicht. Eigentlich kam das erst als schnelle UND große RAMs verfügbar 
waren.

Wenn dein Code nicht funktioniert, dann hat das mit dem Framebuffer 
wenig zu tun.
Für einen einfachen Test kannst du z.b. für Rot die untersten Bits der X 
Komponente und für Grün die untersten Bits der Y Komponente nutzen.

Das ganze in den Code mit dem Framebuffer (der, der funktioniert) und du 
kannst dir das RAM sparen.


Justin schrieb:
> Habe mir letztens noch extra einen SRAM bestellt, dürfte auch bald
> kommen.

Je nach Auflösung, Farbtiefe, RAM-Anbindung und Ramgeschwindigkeit wird 
es knapp mit dem Framebuffer in einem externen SRAM.

Bsp: mit 1280x1024 und 16Bit sind es schon 157Mbyte pro Sekunde, also 
nur schwer machbar mit SRAM die man mal eben dranfädeln kann.

Wenn du deine 640x480 nimmst und jedes Pixel 2 mal zeigst (320x240) bei 
nur 8 Bit, dann kommst du mit <5Mbyte aus. Da bleibt dann sogar noch 
Bandbreite übrig den Framebuffer zu aktualisieren.

Das dürfte aber eine anspruchsvolle Aufgabe sein, jedenfalls im 
Vergleich dazu eine VGA Ausgabe zu realisieren.

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.