Forum: FPGA, VHDL & Co. pixel bewegen bei vga-ansteuerung


von Mar B. (sepp12)


Lesenswert?

Hallo Leute,

arbeite zur Zeit als Einsteiger in Vhdl an einer vga-ansteuerung. 
Hintergrund und einzelne unterschiedlich farbige Quadrate bzw. Rechtecke 
hab ich schon ausgegeben.

Würde die jetzt einfach mal gerne von unten nach oben durch den 
Bildbereich laufen lassen, allerdings verstehe ich nicht wie ich da 
überhaupt ansetzen soll, vll. kann mir hier jemand den Tipp geben?

hier mein bisheriger Vhdl Code:
1
----------------------------------------------------------------------------------
2
-- Company: 
3
-- Engineer: 
4
-- 
5
-- Create Date:    21:46:37 04/08/2014 
6
-- Design Name: 
7
-- Module Name:    VGA - PROGRAMM 
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
use IEEE.std_logic_arith.ALL;
23
use ieee.std_logic_unsigned.all;
24
25
26
27
-- Uncomment the following library declaration if using
28
-- arithmetic functions with Signed or Unsigned values
29
--use IEEE.NUMERIC_STD.ALL;
30
31
-- Uncomment the following library declaration if instantiating
32
-- any Xilinx primitives in this code.
33
--library UNISIM;
34
--use UNISIM.VComponents.all;
35
36
entity VGA is
37
38
PORT
39
(
40
41
clk_50 : IN   std_logic;
42
43
v_sync:  OUT  std_logic;
44
h_sync:   OUT  std_logic;
45
46
red:    OUT  std_logic_vector (2 DOWNTO 0);
47
green:  OUT  std_logic_vector (2 DOWNTO 0);
48
blue:    OUT  std_logic_vector (2 DOWNTO 0)
49
50
);
51
52
end VGA;
53
54
55
56
57
58
architecture PROGRAMM  of VGA is
59
60
signal clk_25          : std_logic;
61
signal horizontal_counter : std_logic_vector (9 downto 0);
62
signal vertical_counter   : std_logic_vector (9 downto 0);
63
signal x              : std_logic_vector (9 downto 0);
64
signal y              : std_logic_vector (9 downto 0);
65
66
begin
67
68
--------------------------------------------25MHz-Takt fuer VGA--------------------------------------------
69
70
process (clk_50)               
71
begin
72
  if (clk_50 'EVENT and clk_50='1') then
73
    if (clk_25 = '0') then
74
      clk_25 <= '1';
75
    else
76
      clk_25 <= '0';
77
    end if;
78
  end if;
79
end process;
80
81
82
83
84
85
86
87
88
process(clk_50)
89
90
begin
91
92
---------------------------Horizontaler Synchronisationsimpuls---------------------------
93
if(clk_25 'Event and clk_25 = '1')then
94
    
95
   horizontal_counter <= horizontal_counter + "0000000001";
96
97
   if(horizontal_counter > "1010010000" and horizontal_counter < "1011110000") then -- >656 and <752
98
      h_sync <= '0';
99
   else
100
      h_sync <= '1';
101
   end if;
102
103
      if(horizontal_counter = "1100100000") then                           --800
104
      horizontal_counter <= "0000000000";
105
      vertical_counter <=  vertical_counter + "0000000001";
106
   end if;
107
  
108
  if(horizontal_counter > "0000000000" and horizontal_counter < "1010000001") then -- > 0 and < 641
109
      blue <= "000";
110
      red <= "000";
111
      green <= "111";
112
   else
113
      blue <= "000";
114
      red <= "000";
115
      green <= "000";
116
  end if;
117
118
  
119
 
120
---------------------------Vertikaler Synchronisationsimpuls---------------------------
121
   
122
   if (vertical_counter > "111101010" and vertical_counter < "111101101") then     -- > 490 and < 493
123
      v_sync <= '0';
124
   else
125
      v_sync <= '1';
126
   end if;
127
   
128
   if(vertical_counter > "111100000" and vertical_counter < "1000001110") then     -- >480 and < 526
129
      blue <= "000";
130
      red <= "000";
131
      green <= "000"; 
132
   end if;
133
   
134
   if(vertical_counter = "1000001110") then                             --525
135
      vertical_counter <= "0000000000";
136
   end if;
137
  
138
139
140
  
141
  x <="0000110010";
142
  y <="0011110000";
143
  
144
if(horizontal_counter > "0000000000" and horizontal_counter < "1010000001") then  
145
if((vertical_counter > y) and (vertical_counter < (y+"100000")) 
146
and (horizontal_counter > x) and (horizontal_counter < (x+"100000")))then
147
148
      blue <= "000";
149
      red <= "111";
150
      green <= "000";
151
    
152
153
                                         
154
end if;
155
end if;
156
end if;
157
158
159
160
    
161
end process;
162
163
end PROGRAMM;



mfg sepp12

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


Lesenswert?

Wenn du diese zwei Zähler hier
1
  signal horizontal_counter : std_logic_vector (9 downto 0);
2
  signal vertical_counter   : std_logic_vector (9 downto 0);
als integer deklarieren würdest, dann wäre dieser Vergleich ganz kurz 
und einfach zu lesen:
1
 if(horizontal_counter > 0 and horizontal_counter < 641) then
Als Tipp: verwende die numeric_std statt der std_logic_arith und der 
std_logic_unsigned...

Hier ist die Sensitivliste falsch:
1
process(clk_50)
2
begin
3
if(clk_25 'Event and clk_25 = '1')then
Der Prozess ist eigentlich nur auf clk_25 sensitiv. Aber das jetzt noch 
nicht ändern, denn so werden keine Takte erzeugt:
1
process (clk_50)               
2
begin
3
  if (clk_50 'EVENT and clk_50='1') then
4
    if (clk_25 = '0') then
5
      clk_25 <= '1';
6
    else
7
      clk_25 <= '0';
8
    end if;
9
  end if;
10
end process;
Verwende diesen clk_25 als Clock-Enable und nimm nur den 50MHz Takt als 
richtigen Takt. So etwa:
1
process (clk_50)               
2
begin
3
  if (clk_50 'EVENT and clk_50='1') then
4
    if (clk_25 = '0') then
5
      clk_25 <= '1';
6
    else
7
      clk_25 <= '0';
8
    end if;
9
  end if;
10
end process;
11
12
process(clk_50)  -- jetzt passt die Sensitivliste 
13
begin
14
if(clk_50 'Event and clk_50 = '1') then -- im ganzen Design der selbe Takt!!
15
  if clk_25='1' then -- das ist ein Clock-Enable
16
     ...dein Code

Martin Braun schrieb:
> Würde die jetzt einfach mal gerne von unten nach oben durch den
> Bildbereich laufen lassen, allerdings verstehe ich nicht wie ich da
> überhaupt ansetzen soll, vll. kann mir hier jemand den Tipp geben?
Du nimmst jetzt vier Register und definierst damit den Anfang und das 
Ende eines Farbwechsels. Diese Register vergleichst du laufend mit dem 
x- und dem y-Zähler und schaltest die Farbe passend um.
Und ab und zu änderst du die Werte dieser Register. Dadurch bewegt sich 
das andersfarbige Viereck...

: Bearbeitet durch Moderator
von Mar B. (sepp12)


Lesenswert?

Erstmal danke für die Hilfe.

"Du nimmst jetzt vier Register und definierst damit den Anfang und das
Ende eines Farbwechsels."

Wie ist das zu verstehen, denke an diesen Punkt liegt mein Problem. vll. 
bräcuhte ich da noch einen weiteren Denkanstoß bzw. Erklärung?

mfg sepp12

von GS (chromosoma)


Lesenswert?

Hier, guck mal mein Tutorial an. Vllt hilft das;)


https://www.youtube.com/watch?v=WK5FT5RD1sU

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


Lesenswert?

Mar B. schrieb:
> Wie ist das zu verstehen, denke an diesen Punkt liegt mein Problem. vll.
> bräcuhte ich da noch einen weiteren Denkanstoß bzw. Erklärung?
Mal angenommen, deine VGA Erzeugung läuft schon richtig, dann würde ich 
für ein blaues Rechteck sowas vorschlagen:
1
 if horizontal_counter >= links and vertikal_counter >= oben then 
2
       blue  <= "111";
3
       red   <= "000";
4
       green <= "000";
5
 end if;
6
7
 if horizontal_counter > rechts and vertikal_counter > unten then 
8
       blue  <= "000";
9
       red   <= "000";
10
       green <= "000";
11
 end if;

Und dann machst du einen zweiten Prozess auf, in dem die Werte für 
links, rechts , oben und unten z.B. jede Zehntelsekunde neu berechnet 
werden. Wenn du z.B. auf rechts und links jeweils 1 addierst, solange 
links < 640, und dann jeweils 1 subtrahierst, solange rechts > 0, dann 
wandert das Rechteck immmer hin und her (du wirst herausfinden: du musst 
dir die Richtung natürlich merken).
Selbes für oben und unten, und das Rechteck wandert ausdauernd diagonal 
über den Bildschirm...

von Mar B. (sepp12)


Lesenswert?

Danke hat mir sehr geholfen.

Probiere das heute gleich aus!

Was ich mich gestern noch gefragt habe ich hätte eigtl vor am schluss so 
eine art videospiel daraus zu machen,in dem eine spielfigur objekten 
ausweicht.

Wie kann man eigtl. Spielfiguren z.b. so eine art "super mario"
darstellen?

Muss ich mir die aus den einzelnen pixeln zusammensetzen oder is dies in 
der art nicht möglich ?

mfg Sepp12

von Duke Scarring (Gast)


Lesenswert?

Mar B. schrieb:
> Muss ich mir die aus den einzelnen pixeln zusammensetzen
Ja. Aber üblicherweise wird man Sprites, Buchstaben und Grafiken aus 
einem Speicher (RAM oder ROM) holen.

Hier gbt es eine Einführung in FPGAs:
http://www.youtube.com/watch?v=X51Qxdyb2Wo
Ab ca. 26:00 gibt es eine Demo und anschließend die Erklärung dazu.

Duke

von peter (Gast)


Lesenswert?

Das DE-1Board hat Farbvectoren RGB 0-3 und nicht 0-2.

Gruss

von peter (Gast)


Lesenswert?

Jup, das sieht ja gut aus.

Ich habe mein Viereck (Rot ) auf einen Platz gesetzt.
Es funktioniert.

Wie sieht jetzt bitte der Prozess aus um es zu verschieben nach rechts 
und nach lnks? Kommt in die Sensitiv-Liste ein clk mit 
rechts-links-oben-unten, oder ohne clk?

Danke.
Gruss
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use ieee.numeric_std.ALL;
4
5
entity vga_timing1 is
6
port(
7
  clk50_in  : in std_logic;
8
  hs_out    : out std_logic;
9
  vs_out    : out std_logic;
10
  
11
  red_out   : OUT STD_LOGIC_VECTOR(3 downto 0);
12
  green_out : OUT STD_LOGIC_VECTOR(3 downto 0);
13
  blue_out  : OUT STD_LOGIC_VECTOR(3 downto 0)
14
  ); 
15
end vga_timing1;
16
17
architecture behavioral of vga_timing1 is
18
19
signal clk25    : std_logic:='0';
20
signal hcounter : integer := 0;
21
signal vcounter : integer := 0;
22
signal links : integer := 200;
23
signal rechts : integer := 220;
24
signal oben : integer := 200;
25
signal unten : integer := 220;
26
27
begin
28
29
-- generate a 25Mhz clock
30
process (clk50_in)
31
begin
32
  if clk50_in'event and clk50_in='1' then
33
    clk25 <= not clk25;
34
  end if;
35
end process;
36
37
process (clk25)
38
begin
39
  if clk25'event and clk25 = '1' then
40
    if (hcounter >= links) and (hcounter < rechts) and (vcounter >= oben) and (vcounter < unten) then 
41
       red_out<="1000";
42
     else
43
       red_out<="0000";
44
   end if;
45
  end if;
46
end process;
47
48
process (clk25)
49
begin
50
  if clk25'event and clk25 = '1' then
51
    if hcounter >= (639+16) and hcounter <= (639+16+96) then
52
      hs_out <= '0';
53
    else
54
      hs_out <= '1';
55
    end if;
56
  
57
    if vcounter >= (479+10) and vcounter <= (479+10+2) then
58
      vs_out <= '0';
59
     else
60
      vs_out <= '1';
61
    end if;
62
  
63
--- horizontal counts from 0 to 799
64
    hcounter <= hcounter+1;
65
  
66
    if hcounter = 799 then
67
      vcounter <= vcounter+1;
68
      hcounter <= 0;
69
    end if;
70
  
71
--- vertical counts from 0 to 524
72
    if vcounter = 524 then 
73
      vcounter <= 0;
74
    end if;
75
  end if;
76
end process;
77
78
end behavioral;

von peter (Gast)


Lesenswert?

Ich möchte das Viereck bitte mit 2 Tasten bewegen.

Danke.

von peter (Gast)


Lesenswert?

Wenn sw gedrückt dann hat er '0' ansonsten '1'.

Ich habe jetzt diesen Process mit reingesetzt:
1
process(sw(0),rechts,links)
2
begin   
3
  if (sw(0) ='0') then
4
    rechts <= rechts+1;
5
    links <= links+1;
6
    if rechts >= 640 then
7
      rechts <=120;
8
      links <=100;
9
    end if;  
10
  end if;    
11
end process;

Es ist nur ab zu ein roter Streifen zu sehen.

Gruss

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


Lesenswert?

peter schrieb:
> Ich möchte das Viereck bitte mit 2 Tasten bewegen.
Du solltest also zuallererst diese Tasten einsynchronisieren.
Und dann eine Flankenerkennung drauf ansetzen.
Und dann bei erkannter Flanke die Grenzen ändern...

Hier mein Vorschlag zum Anpassen:
1
port(
2
   ...
3
   x_taster, y_taster  : in std_logic;
4
   ...
5
  ); 
6
:
7
:
8
signal xsr : std_logic_vector(3 downto 0) :=  (others=>'0');
9
signal ysr : std_logic_vector(3 downto 0) :=  (others=>'0');
10
:
11
:
12
begin
13
:
14
:
15
-- generate a 25Mhz clock !!! Wie gesagt: so macht man das nicht!
16
    clk25 <= not clk25;
17
:
18
:
19
20
process begin
21
  wait untilk rising_edge(clk25);
22
  xsr <= xsr(2 downto 0) & x_taster; -- Taster eintakten
23
  ysr <= ysr(2 downto 0) & y_taster;
24
  if xsr = "0111" then -- steigende Flanke
25
     if links = 619 then
26
        links  <= 0;
27
        rechts <= 20;
28
     else
29
        links  <= links+1;
30
        rechts <= rechts+1;
31
     end if;
32
  end if;
33
  if ysr = "0111" then
34
     if oben = 459 then
35
        oben  <= 0;
36
        unten <= 20;
37
     else
38
        oben  <= oben+1;
39
        unten <= unten+1;
40
     end if;
41
  end if;
42
end process;
43
  
44
:
45
:

Gib doch besser beim Integer den range mit an:
1
signal clk25    : std_logic:='0';
2
signal hcounter : integer range 0 to 751 := 0;
3
signal vcounter : integer range 0 to 491 := 0;
4
signal links    : integer range 0 to 619 := 200;
5
signal rechts   : integer range 20 to 639 := 220;
6
signal oben     : integer range 0  to 459 := 200;
7
signal unten    : integer range 20 to 479 := 220;
Dann kann der simulator gleich meckern, wenn was schiefläuft...

peter schrieb:
> Ich habe jetzt diesen Process mit reingesetzt:...
Ein Zähler, der ohne Takt gezählt wird: das ist eine kombinatorische 
Schleife.
http://www.lothar-miller.de/s9y/archives/42-Kombinatorische-Schleifen.html

: Bearbeitet durch Moderator
von Lattice User (Gast)


Lesenswert?

peter schrieb:
> Wenn sw gedrückt dann hat er '0' ansonsten '1'.
>
> Ich habe jetzt diesen Process mit reingesetzt:
>
1
> process(sw(0),rechts,links)
2
> begin
3
>   if (sw(0) ='0') then
4
>     rechts <= rechts+1;
5
>     links <= links+1;
6
>     if rechts >= 640 then
7
>       rechts <=120;
8
>       links <=100;
9
>     end if;
10
>   end if;
11
> end process;
12
>
>
> Es ist nur ab zu ein roter Streifen zu sehen.
>
> Gruss

Da das ein combinatorischer Prozess ist, ist er viel zu schnell. 
Ausserdem enthält er Latches, eine sehr schlechte Idee.

Pack das in den existierened Prozess (einmal pro Bild abfragen)
1
--- vertical counts from 0 to 524
2
    if vcounter = 524 then 
3
      vcounter <= 0;
4
5
      if (sw(0) ='0') then
6
        rechts <= rechts+1;
7
        links <= links+1;
8
        if rechts >= 640 then
9
          rechts <=120;
10
          links <=100;
11
        end if;  
12
      end if;    
13
    end if;

Davon abgesehen muss sw(0) noch entprellt und einsynchrinsiert werden, 
damit es zuverlässig funktioniert.

von Duke Scarring (Gast)


Lesenswert?

peter schrieb:
> mit 2 Tasten
Hast Du die entprellt?
http://www.lothar-miller.de/s9y/categories/5-Entprellung

peter schrieb:
> process(sw(0),rechts,links)
> begin
>   if (sw(0) ='0') then
Das ist kombinatorische Logik und dürfte ein bischen zu schnell gehen, 
als das Du es mit dem Auge sehen kannst.

peter schrieb:
> um es zu verschieben nach rechts
> und nach lnks?
Du mußt Deine "links" und "rechts" Signale verändern. Aber nur so 
schnell, das Du noch was sehen kannst.

Duke

von Peter B. (funkheld)


Lesenswert?

Jup, danke. Jetzt funktioniert es.
Die Tasten sind von Haus aus schon Entprellt beim DE-1.

Habe clk-50 reingenommen.
Jetzt kann ich mit den beiden Druck-Tastern das Quadrat hin und her 
schieben. Wenn es rechts anstösst(640) bleibt es stehen und wenn es 
links anstösst bleibt es stehen(0).
1
process(clk50_in,sw,rechts,links)
2
begin  
3
  if clk50_in'event and clk50_in='1' then
4
    if (c<499999) then       
5
      c <= c+1;                
6
    else    
7
      if (sw(0) ='0') then
8
        rechts <= rechts+1;
9
        links <= links+1;
10
        if rechts >= 640 then
11
          rechts <=640;
12
          links <=620;
13
        end if;  
14
      end if;
15
      if (sw(1) ='0') then
16
        rechts <= rechts-1;
17
        links <= links-1;
18
        if links = 0 then
19
          rechts <=20;
20
          links <=0;
21
        end if;  
22
      end if;
23
      c <= 0;  
24
    end if;  
25
  end if;
26
end process;

Gruss

: Bearbeitet durch User
von Lattice User (Gast)


Lesenswert?

Peter Bierbach schrieb:
> Jup, danke. Jetzt funktioniert es.
> Die Tasten sind von Haus aus schon Entprellt beim DE-1.
>

Auch einsynchronisert auf deine clk50?
Wenn nicht wird manchmal beim Drücken der Tasten das Viereck wild 
springen und sich u.U. auch in der Breite ändern. Da du nur alle 10 
Milliseknden abfrägst wird das sehr sehr selten sein, ist aber genau die 
Art von Fehlern die sich nachträglich nur extrem schwer auffinden 
lassen.
1
process(clk50_in,sw,rechts,links)
Ein synchroner getakter Prozess darf nur die Clock, (und eventuell ein 
asynchrones Reset) in der Sensitivitylist haben.

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


Lesenswert?

Peter Bierbach schrieb:
> if (sw(0) ='0') then
Peter, das mit dem Einsynchronisieren hast du gelesen? Willst du 
wissen, WARUM man das macht? Dann klick da drauf:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Genau sowas hast du dir da gerade gebaut.

: Bearbeitet durch Moderator
von Peter B. (funkheld)


Lesenswert?

Jup danke für den Hinweis.

Hier habe ich jetzt alle 4 Drucktasten reingebracht.
Das Viereck bleibt an den Kanten stehen  wenn es anstösst und dann muss 
man mit den Tasten die Richtung ändern. Mit meiner Zählschleife vom 
clk-50 (200000) läuft das Viereck flink und schlierenfrei über den 
Screen(640x480.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use ieee.numeric_std.ALL;
4
5
entity vga_timing1 is
6
port(
7
  clk50_in  : in std_logic;
8
  hs_out    : out std_logic;
9
  vs_out    : out std_logic;
10
  sw        : in STD_LOGIC_VECTOR(3 downto 0);
11
  
12
  red_out   : OUT STD_LOGIC_VECTOR(3 downto 0);
13
  green_out : OUT STD_LOGIC_VECTOR(3 downto 0);
14
  blue_out  : OUT STD_LOGIC_VECTOR(3 downto 0)
15
  ); 
16
end vga_timing1;
17
18
architecture behavioral of vga_timing1 is
19
20
signal clk25    : std_logic:='0';
21
signal hcounter : integer := 0;
22
signal vcounter : integer := 0;
23
signal links : integer := 100;
24
signal rechts : integer := 120;
25
signal oben : integer := 100;
26
signal unten : integer := 120;
27
signal c : integer range 0 to 500000 := 0; 
28
29
begin
30
31
process(clk50_in,sw,rechts,links,oben, unten)
32
begin  
33
  if clk50_in'event and clk50_in='1' then
34
    if (c<200000) then       
35
      c <= c+1;                
36
    else    
37
      if (sw(0) ='0') then
38
        rechts <= rechts+1;
39
        links <= links+1;
40
        if rechts = 640 then
41
          rechts <=640;
42
          links <=620;
43
              end if;  
44
      end if;
45
      if (sw(1) ='0') then
46
        rechts <= rechts-1;
47
        links <= links-1;
48
        if links = 0 then
49
          rechts <=20;
50
          links <=0;
51
        end if;  
52
      end if;
53
      if (sw(2) ='0') then
54
        unten <= unten+1;
55
        oben <= oben+1;
56
        if unten = 480 then
57
          unten <=480;
58
          oben <=460;
59
        end if;  
60
      end if;
61
      if (sw(3) ='0') then
62
        unten <= unten-1;
63
        oben <= oben-1;
64
        if oben = 0 then
65
          unten <=20;
66
          oben <=0;
67
        end if;  
68
      end if;
69
      c <= 0;  
70
    end if;  
71
  end if;
72
end process;  
73
74
process (clk50_in)
75
begin
76
  if clk50_in'event and clk50_in='1' then
77
    clk25 <= not clk25;
78
  end if;
79
end process;
80
81
process (clk25)
82
begin
83
  if clk25'event and clk25 = '1' then
84
    if (hcounter >= links) and (hcounter < rechts) and (vcounter >= oben) and (vcounter < unten) then 
85
       red_out<="1000";
86
     else
87
       red_out<="0000";
88
   end if;
89
  end if;
90
end process;
91
92
process (clk25)
93
begin
94
  if clk25'event and clk25 = '1' then
95
    if hcounter >= (639+16) and hcounter <= (639+16+96) then
96
      hs_out <= '0';
97
    else
98
      hs_out <= '1';
99
    end if;
100
  
101
    if vcounter >= (479+10) and vcounter <= (479+10+2) then
102
      vs_out <= '0';
103
     else
104
      vs_out <= '1';
105
    end if;
106
  
107
--- horizontal counts from 0 to 799
108
    hcounter <= hcounter+1;
109
  
110
    if hcounter = 799 then
111
      vcounter <= vcounter+1;
112
      hcounter <= 0;
113
    end if;
114
  
115
--- vertical counts from 0 to 524
116
    if vcounter = 524 then 
117
      vcounter <= 0;
118
    end if;
119
  end if;
120
end process;
121
122
end behavioral;

von Lattice User (Gast)


Lesenswert?

Peter Bierbach schrieb:
> Jup danke für den Hinweis.
>
> Hier habe ich jetzt alle 4 Drucktasten reingebracht.
> Das Viereck bleibt an den Kanten stehen  wenn es anstösst und dann muss
> man mit den Tasten die Richtung ändern. Mit meiner Zählschleife vom
> clk-50 (200000) läuft das Viereck flink und schlierenfrei über den
> Screen(640x480.
>

Ab und zu wird Tearing zu sehen sein, immer dann wenn sich die Position 
ändert während das Viereck gerade ausgegeben wird.
Abhilfe: Position nur wärend des Vsyncs ändern.
Da das eventuell etwas langsam ist, Doublebuffering verwenden.
Im Tastenprozess: z.b links_neu statt links ändern,
Im Displayprozess bei vcounter = 524, links <= links_neu.

von Peter B. (funkheld)


Lesenswert?

Jup danke.
Das wird wohl erst gehen wenn der Screen aus dem RAM bedient wird 
(Doublebuffering)?

-----------------------
Ausserdem enthält er Latches, eine sehr schlechte Idee
-----------------------
Warum sind die Latches nicht gut im zusätzlichen Process(sensitivity)?


Danke.

Gruss

: Bearbeitet durch User
von Lattice User (Gast)


Lesenswert?

Peter Bierbach schrieb:
> Jup danke.
> Das wird wohl erst gehen wenn der Screen aus dem RAM bedient wird?
>
Wieso, dein Bild ist im Prinzip durch die 4 Register 
links,rechts,oben,unten bestimmt. Und diese 4 Register kannst du 
Doublebuffern. Lies nochmal die 2 letzen Zeilen meines vorigen Postings.

Nochmal zur Erinnerung: *Einsynchronisieren*:
Beitrag "Re: pixel bewegen bei vga-ansteuerung"

von max (Gast)


Lesenswert?

Weil Latches nicht getaktet sind:
http://electronics.stackexchange.com/questions/38645/why-are-inferred-latches-bad

Du hast auch 2 Takte in deinem System. Das kann bei falschen 
Taktübergängen zu Problemen führen. Deshalb Clock-enable verwenden:
1
process (clk_50)               
2
begin
3
  if (clk_50 'EVENT and clk_50='1') then
4
    clk_25 <= not clk_25;
5
    if (clk_25 = '1') then -- das ist ein Clock-Enable
6
        if hcounter >= (639+16) and hcounter <= (639+16+96) then
7
          hs_out <= '0';
8
        else
9
          hs_out <= '1';
10
        end if;
11
        ...Rest von deinem Code

Das Einsynchronisieren der Tastensignale hat nichts mit dem Prellen zu 
tun, sondern damit, dass die Tastensignale asynchron zu deinem Takt 
sind. Dies führt zu Timingverletzungen... deswegen wie Hr. Miller es auf 
seiner Homepage hat machen.

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


Lesenswert?

max schrieb:
> Deshalb Clock-enable verwenden
Ein Dejavu: Beitrag "Re: pixel bewegen bei vga-ansteuerung"

Leider zeigt sich Peter hier recht lernresistent...

von Peter B. (funkheld)


Lesenswert?

So habe ich es geändert mit rechts_neu usw.
Mit sw kann ich jetzt auch die Farbe vom Viereck ändern.

Die Geschwindigkeit hat hier keine Einbußen.
Warum muss das bei vcounter=524 rein?

Danke.
Gruss
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use ieee.numeric_std.ALL;
4
5
entity vga_timing1 is
6
port(
7
  clk50_in  : in std_logic;
8
  hs_out    : out std_logic;
9
  vs_out    : out std_logic;
10
  key       : in STD_LOGIC_VECTOR(3 downto 0);
11
  sw        : in STD_LOGIC_VECTOR(2 downto 0);
12
  
13
  red_out   : OUT STD_LOGIC_VECTOR(3 downto 0);
14
  green_out : OUT STD_LOGIC_VECTOR(3 downto 0);
15
  blue_out  : OUT STD_LOGIC_VECTOR(3 downto 0)
16
  ); 
17
end vga_timing1;
18
19
architecture behavioral of vga_timing1 is
20
21
signal clk25    : std_logic:='0';
22
signal hcounter : integer := 0;
23
signal vcounter : integer := 0;
24
signal links_neu : integer := 100;
25
signal rechts_neu : integer := 120;
26
signal oben_neu : integer := 100;
27
signal unten_neu : integer := 120;
28
signal links : integer := 0;
29
signal rechts : integer := 0;
30
signal oben : integer := 0;
31
signal unten : integer := 0;
32
signal c : integer range 0 to 500000 := 0; 
33
signal red   : STD_LOGIC_VECTOR(3 downto 0);
34
signal green : STD_LOGIC_VECTOR(3 downto 0);
35
signal blue  : STD_LOGIC_VECTOR(3 downto 0);
36
37
begin
38
39
process(sw)
40
begin  
41
  if (sw(0) ='1') then 
42
    red<="1111";
43
    green<="0000";
44
    blue<="0000";
45
  end if;
46
  if (sw(1) ='1') then 
47
    red<="0000";
48
    green<="1111";
49
    blue<="0000";
50
  end if;
51
  if (sw(2) ='1') then 
52
    red<="0000";
53
    green<="0000";
54
    blue<="1111";
55
  end if;
56
end process;  
57
58
process(clk50_in,key,rechts_neu,links_neu,oben_neu, unten_neu)
59
begin  
60
  if clk50_in'event and clk50_in='1' then
61
    if (c<200000) then       
62
      c <= c+1;                
63
    else    
64
      if (key(0) ='0') then
65
        rechts_neu <= rechts_neu+1;
66
        links_neu <= links_neu+1;
67
        if rechts_neu = 640 then
68
          rechts_neu <=640;
69
          links_neu <=620;
70
        end if;  
71
      end if;
72
      if (key(1) ='0') then
73
        rechts_neu <= rechts_neu-1;
74
        links_neu <= links_neu-1;
75
        if links_neu = 0 then
76
          rechts_neu <=20;
77
          links_neu <=0;
78
        end if;  
79
      end if;
80
      if (key(2) ='0') then
81
        unten_neu <= unten_neu+1;
82
        oben_neu <= oben_neu+1;
83
        if unten_neu = 480 then
84
          unten_neu <=480;
85
          oben_neu <=460;
86
        end if;  
87
      end if;
88
      if (key(3) ='0') then
89
        unten_neu <= unten_neu-1;
90
        oben_neu <= oben_neu-1;
91
        if oben_neu = 0 then
92
          unten_neu <=20;
93
          oben_neu <=0;
94
        end if;  
95
      end if;
96
      c <= 0;  
97
    end if;  
98
  end if;
99
end process;  
100
101
process (clk50_in)
102
begin
103
  if clk50_in'event and clk50_in='1' then
104
    clk25 <= not clk25;
105
  end if;
106
end process;
107
108
process (clk25)
109
begin
110
  if clk25'event and clk25 = '1' then
111
    if (hcounter >= links) and (hcounter < rechts) and (vcounter >= oben) and (vcounter < unten) then 
112
       red_out<= red;
113
       green_out<=green;
114
       blue_out<=blue;
115
     else
116
       red_out<="0000";
117
       green_out<="0000";
118
       blue_out<="0000";
119
   end if;
120
  end if;
121
end process;
122
123
process (clk25,unten_neu,oben_neu,rechts_neu,links_neu)
124
begin
125
  if clk25'event and clk25 = '1' then
126
    if hcounter >= (639+16) and hcounter <= (639+16+96) then
127
      hs_out <= '0';
128
    else
129
      hs_out <= '1';
130
    end if;
131
  
132
    if vcounter >= (479+10) and vcounter <= (479+10+2) then
133
      vs_out <= '0';
134
     else
135
      vs_out <= '1';
136
    end if;
137
  
138
--- horizontal counts from 0 to 799
139
    hcounter <= hcounter+1;
140
  
141
    if hcounter = 799 then
142
      vcounter <= vcounter+1;
143
      hcounter <= 0;
144
    end if;
145
  
146
--- vertical counts from 0 to 524
147
    if vcounter = 524 then 
148
      rechts <= rechts_neu;
149
      links <= links_neu;
150
      oben <= oben_neu;
151
      unten <= unten_neu;
152
      vcounter <= 0;
153
    end if;
154
  end if;
155
end process;
156
157
end behavioral;

von Peter B. (funkheld)


Lesenswert?

Hmmm. unter Doublebuffern verstehe ich das fertige Bild aus dem RAM auf 
den SCreen abbilden.

Muss das jetzt so in jedem Process, wo die clk_25 als sensitive 
gebraucht wird?
-------------------------
if(clk_50 'Event and clk_50 = '1') then -- im ganzen Design der selbe 
Takt!!
  if clk_25='1' then -- das ist ein Clock-Enable
--------------------------
1
process (clk50_in)
2
begin
3
if (clk50_in 'EVENT and clk50_in='1') then
4
  if clk25 = '1' then
5
    if (hcounter >= links) and (hcounter < rechts) and (vcounter >= oben) and (vcounter < unten) then 
6
       red_out<= red;
7
       green_out<=green;
8
       blue_out<=blue;
9
     else
10
       red_out<="0000";
11
       green_out<="0000";
12
       blue_out<="0000";
13
   end if;
14
  end if;
15
end if;  
16
end process;
17
18
process (clk50_in,unten_neu,oben_neu,rechts_neu,links_neu)
19
begin
20
if(clk50_in 'Event and clk50_in = '1') then 
21
  if clk25 = '1' then
22
    if hcounter >= (639+16) and hcounter <= (639+16+96) then
23
      hs_out <= '0';
24
    else
25
      hs_out <= '1';
26
    end if;
27
  
28
    if vcounter >= (479+10) and vcounter <= (479+10+2) then
29
      vs_out <= '0';
30
     else
31
      vs_out <= '1';
32
    end if;
33
  
34
--- horizontal counts from 0 to 799
35
    hcounter <= hcounter+1;
36
  
37
    if hcounter = 799 then
38
      vcounter <= vcounter+1;
39
      hcounter <= 0;
40
    end if;
41
  
42
--- vertical counts from 0 to 524
43
    if vcounter = 524 then 
44
      rechts <= rechts_neu;
45
      links <= links_neu;
46
      oben <= oben_neu;
47
      unten <= unten_neu;
48
      vcounter <= 0;
49
    end if;
50
  end if;
51
end if;  
52
end process;

Danke.
Gruss

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


Lesenswert?

Peter Bierbach schrieb:
> Hmmm. unter Doublebuffern verstehe ich das fertige Bild aus dem RAM auf
> den SCreen abbilden.
Man kann auch nur die Koordinaten des Teils des bildes, das sich 
ändert puffern. Denn nur dieser Teil kann Probleme machen. Auch das 
ist Double Buffering...

von Peter B. (funkheld)


Lesenswert?

Warum gibt es bei "c" keine Fehlermeldung, obwohl "c" nicht in der 
Empfindlichkeitsliste steht?

Danke.
1
process(clk50_in,key,rechts_neu,links_neu,oben_neu, unten_neu)
2
begin  
3
  if clk50_in'event and clk50_in='1' then
4
    if (c<200000) then       
5
      c <= c+1;                
6
    else    
7
      if (key(0) ='0') then
8
        rechts_neu <= rechts_neu+1;
9
        links_neu <= links_neu+1;
10
        if rechts_neu = 640 then
11
          rechts_neu <=640;
12
          links_neu <=620;
13
        end if;  
14
      end if;
15
      if (key(1) ='0') then
16
        rechts_neu <= rechts_neu-1;
17
        links_neu <= links_neu-1;
18
        if links_neu = 0 then
19
          rechts_neu <=20;
20
          links_neu <=0;
21
        end if;  
22
      end if;
23
      if (key(2) ='0') then
24
        unten_neu <= unten_neu+1;
25
        oben_neu <= oben_neu+1;
26
        if unten_neu = 480 then
27
          unten_neu <=480;
28
          oben_neu <=460;
29
        end if;  
30
      end if;
31
      if (key(3) ='0') then
32
        unten_neu <= unten_neu-1;
33
        oben_neu <= oben_neu-1;
34
        if oben_neu = 0 then
35
          unten_neu <=20;
36
          oben_neu <=0;
37
        end if;  
38
      end if;
39
      c <= 0;  
40
    end if;  
41
  end if;
42
end process;

von Lattice User (Gast)


Lesenswert?

Peter Bierbach schrieb:
> Warum gibt es bei "c" keine Fehlermeldung, obwohl "c" nicht in der
> Empfindlichkeitsliste steht?
>
> Danke.
>

Weil für einen getakten Prozess (wie chon mal angemerkt) ohne Reset nur 
die
Clock da rein muss
1
process(clk50_in)

von Mar B. (sepp12)


Lesenswert?

Hallo nochmal,

hätte da noch ne frage, wenn ich jetzt zuällig ein objekt am monitor 
ausgeben möchte ohne vorher festzulegen bei welcher x und y position es 
sich befindet, könnte man das mit einem pseudo random noise generator 
machen oder nicht?

falls es möglich ist, wie begrenzt man zum beispiel das objekt auf den 
rechten oder linken bildschirmteil, wenn ich in mittig teilen würde.


mfg

sepp12

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


Lesenswert?

Mar B. schrieb:
> hätte da noch ne frage, wenn ich jetzt zuällig ein objekt am monitor
> ausgeben möchte ohne vorher festzulegen bei welcher x und y position es
> sich befindet, könnte man das mit einem pseudo random noise generator
> machen oder nicht?
Ja. Stichwort LFSR.
Ein LFSR mit 64Bit Breite wäre toll für die nachfolgende Strategie.

> falls es möglich ist, wie begrenzt man zum beispiel das objekt auf den
> rechten oder linken bildschirmteil, wenn ich in mittig teilen würde.
Man begrenzt für die linke Bildschirmhälfte den Wertebereich auf 0..299 
(bei einer Objektbreite von 20 Pixeln) und addiert für die rechte Hälfte 
auf diesen Wert noch 320 drauf.
Weil aber eine  modulo-300 Rechnung auf einem FPGA umständlich ist, 
würde ich eine Zufallszahl mit 64 Bit Breite ermitteln, daraus dann 
einzelne Bitmuster "ausschneiden": 1x 0..255 (8 Bit), 1x 0..31 (5 Bit), 
1x 0..7 (3 Bit), 2x 0..3 (je 2 Bit) und dann alle zusammenaddieren: 
fertig ist die Zufallszahl von 0..255+31+7+3+3 = 0..299

Hier sieht man schon, dass eine geschickte Auswahl der Obergrenze (bzw. 
"Quadratbreite") die Anzahl der nötigen Berechnungen signifikant 
reduzieren kann. Mit einer Breite von 18 wäre eine Zufallszahl von 
0..301 nötig, die sich aus drei kleineren Werten zusammenaddieren lässt: 
255+31+15

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.