mikrocontroller.net

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


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.
Autor: Justin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Justin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: tja (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: tja (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Justin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

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

Autor: Justin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

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

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Arno (Gast)
Datum:

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

MfG, Arno

Autor: Justin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:




library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity vga is
    Port ( clk50 : in  STD_LOGIC;
           vga_red : out  STD_LOGIC_VECTOR (2 downto 0);
           vga_green : out  STD_LOGIC_VECTOR (2 downto 0);
           vga_blue : out  STD_LOGIC_VECTOR (2 downto 1);
           vga_hsync : out  STD_LOGIC;
           vga_vsync : out  STD_LOGIC;
           frame_addr : out  STD_LOGIC_VECTOR (14 downto 0);
           frame_pixel : in  STD_LOGIC_VECTOR (7 downto 0));
end vga;

architecture Behavioral of vga is
   -- Timing constants
   constant hRez       : natural := 640;
   constant vRez       : natural := 480;

   constant hMaxCount  : natural := 799;
   constant hStartSync : natural := 655;
   constant hEndSync   : natural := 751;
   constant vMaxCount  : natural := 525;
   constant vStartSync : natural := 490;
   constant vEndSync   : natural := 491;
   constant hsync_active : std_logic := '1';
   constant vsync_active : std_logic := '1';

   signal hCounter : unsigned(10 downto 0) := (others => '0');
   signal vCounter : unsigned(9 downto 0) := (others => '0');
   signal address : unsigned(16 downto 0) := (others => '0');
   signal blank : std_logic := '1';
  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;  
   
   process(clk25)
   begin
      if rising_edge(clk25) then
         -- Count the lines and rows      
         if hCounter = hMaxCount-1 then
            hCounter <= (others => '0');
            if vCounter = vMaxCount-1 then
               vCounter <= (others => '0');
            else
               vCounter <= vCounter+1;
            end if;
         else
            hCounter <= hCounter+1;
         end if;

         if blank = '0' then
            vga_red   <= frame_pixel(7 downto 5);
            vga_green <= frame_pixel(4 downto 2);
            vga_blue  <= frame_pixel(1 downto 0);
         else
            vga_red   <= (others => '0');
            vga_green <= (others => '0');
            vga_blue  <= (others => '0');
         end if;
   
         if vCounter  >= vRez then
            address <= (others => '0');
            blank <= '1';
         else 
            if hCounter  >= 0 and hCounter  < 640 then
               blank <= '0';
               
               address <= address+1;
               
            else
               blank <= '1';
            end if;
         end if;
   
         
         if hCounter > hStartSync and hCounter <= hEndSync then
            vga_hSync <= hsync_active;
         else
            vga_hSync <= not hsync_active;
         end if;

         
         if vCounter >= vStartSync and vCounter <= vEndSync then
            vga_vSync <= vsync_active;
         else
            vga_vSync <= not vsync_active;
         end if;
      end if;
   end process;
end Behavioral;





Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: -gb- (Gast)
Datum:

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

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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...

Autor: -gb- (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Justin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:





----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    00:47:27 09/09/2019 
-- Design Name: 
-- Module Name:    frame_buffer - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

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);
  SIGNAL clk25  :STD_LOGIC;
  
begin

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

  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;
  
  process(clk25)
  begin
    doutb <= ram(to_integer(unsigned(addr_b_reg)));
  end process;
    
  

end Behavioral;




Autor: Robert P. (fpgazumspass) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

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.