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;
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.
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
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.
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!
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.
Könnte passen. 800 x 600 ist jenseits der originalen VGA-Spec, aber heutige Monitore sollten das natürlich alle können.
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
Sieht aus, als würdest du die Synchronimpulse noch nicht richtig auf die Reihe bekommen.
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
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; |
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?
Simulawer? Der Code aus seinem letzten Post hat unbelegte Signale, das wurde sicher nicht simuliert. Aber ja, das sollte man mal simulieren.
-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...
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.
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; |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.