Forum: FPGA, VHDL & Co. VGA an 50MHZ anpassen, wie geht das?


von bernd (Gast)


Lesenswert?

Wie kann man diese VGA-CLK bitte für ein Board mit 50MHZ anpassen?

Danke.
1
`default_nettype none      //disable implicit definitions by Verilog
2
3
module top(        //top module and signals wired to FPGA pins
4
  CLK100MHz,
5
  vga_r,
6
  vga_g,
7
  vga_b,
8
  vga_hs,
9
  vga_vs,
10
  ps2_clk,
11
  ps2_data
12
);
13
14
input      CLK100MHz;  // Oscillator input 100Mhz
15
output  [2:0]     vga_r;    // VGA Red 3 bit
16
output  [2:0]     vga_g;    // VGA Green 3 bit
17
output  [2:0]     vga_b;    // VGA Blue 3 bit
18
output            vga_hs;    // H-sync pulse 
19
output            vga_vs;    // V-sync pulse
20
input      ps2_clk;  // PS2 clock
21
input      ps2_data;  // PS2 data
22
23
24
parameter h_pulse   = 96;  //H-SYNC pulse width 96 * 40 ns (25 Mhz) = 3.84 uS
25
parameter h_bp      = 48;  //H-BP back porch pulse width
26
parameter h_pixels  = 640;  //H-PIX Number of pixels horisontally
27
parameter h_fp      = 16;  //H-FP front porch pulse width
28
parameter h_pol     = 1'b0;  //H-SYNC polarity
29
parameter h_frame   = 800;  //800 = 96 (H-SYNC) + 48 (H-BP) + 640 (H-PIX) + 16 (H-FP)
30
parameter v_pulse   = 2;  //V-SYNC pulse width
31
parameter v_bp      = 33;  //V-BP back porch pulse width
32
parameter v_pixels  = 480;  //V-PIX Number of pixels vertically
33
parameter v_fp      = 10;  //V-FP front porch pulse width
34
parameter v_pol     = 1'b1;  //V-SYNC polarity
35
parameter v_frame   = 525;  // 525 = 2 (V-SYNC) + 33 (V-BP) + 480 (V-PIX) + 10 (V-FP)
36
37
parameter square_size = 10;  //size of the square we will move
38
parameter init_x = 320;    //initial square position X
39
parameter init_y = 240;    //initial square position Y
40
41
reg  [1:0]    clk_div;  // 2 bit counter
42
wire      vga_clk;  
43
44
assign   vga_clk   = clk_div[1];    // 25Mhz clock = 100Mhz divided by 2-bit counter
45
46
always @ (posedge CLK100MHz) begin    // 2-bt counter ++ on each positive edge of 100Mhz clock
47
  clk_div <= clk_div + 2'b1;
48
end
49
50
reg     [2:0]     vga_r_r;  //VGA color registers R,G,B x 3 bit
51
reg     [2:0]     vga_g_r;
52
reg     [2:0]     vga_b_r;
53
reg               vga_hs_r;  //H-SYNC register
54
reg               vga_vs_r;  //V-SYNC register
55
56
assign   vga_r     = vga_r_r;    //assign the output signals for VGA to the VGA registers
57
assign   vga_g     = vga_g_r;
58
assign   vga_b     = vga_b_r;
59
assign   vga_hs     = vga_hs_r;
60
assign   vga_vs     = vga_vs_r;
61
62
reg     [7:0]    timer_t = 8'b0;  // 8 bit timer with 0 initialization
63
reg               reset = 1;  
64
reg     [9:0]     c_row;    //complete frame register row
65
reg     [9:0]     c_col;    //complete frame register colum
66
reg     [9:0]     c_hor;    //visible frame register horisontally
67
reg     [9:0]     c_ver;    //visible  frame register vertically
68
69
reg      disp_en;  //display enable flag
70
71
reg  [9:0]    sq_pos_x;  //position of square center X, Y
72
reg  [9:0]    sq_pos_y;
73
74
wire  [9:0]    l_sq_pos_x;  //upper left and down right corners of the square
75
wire  [9:0]    r_sq_pos_x;
76
wire  [9:0]    u_sq_pos_y;
77
wire  [9:0]    d_sq_pos_y;
78
79
assign   l_sq_pos_x   = sq_pos_x - square_size;
80
assign   r_sq_pos_x   = sq_pos_x + square_size;
81
assign   u_sq_pos_y   = sq_pos_y - square_size;
82
assign   d_sq_pos_y   = sq_pos_y + square_size;
83
84
reg  [3:0]    ps2_cntr;    // 4-bit PS2 clock counter
85
reg  [7:0]    ps2_data_reg;    // 8-bit PS2 data register
86
reg  [7:0]    ps2_data_reg_prev;  // previous 8-bit PS data register
87
reg  [7:0]    ps2_data_reg_prev1;  // previous previous 8-bit data register
88
reg  [10:0]    ps2_dat_r;    // 11-bit complete PS2 frame register
89
90
reg  [1:0]    ps2_clk_buf;    // PS2 clock buffer
91
wire      ps2_clk_pos;    // PS2 positive edge detected signal
92
93
reg      u_arr = 0;    //PS2 arrow keys detect flags
94
reg      l_arr = 0;
95
reg      d_arr = 0;
96
reg      r_arr = 0;
97
98
reg  [20:0]  arr_timer;  // delay between key service
99
100
reg  [19:0]  sq_figure  [0:19];
101
102
wire  [4:0]  sq_fig_x;
103
wire  [4:0]  sq_fig_y;
104
105
assign sq_fig_x = c_col - l_sq_pos_x;      // our figure's x axis when in square boundary
106
assign sq_fig_y = c_row - u_sq_pos_y;      // our figure's y axis when in square boundary
107
108
assign ps2_clk_pos = (ps2_clk_buf == 2'b01);  // edge detector positive edge is when the buffer is '10'
109
110
always @ (posedge vga_clk) begin        //25Mhz clock
111
112
  if(timer_t > 250) begin          // generate 10 uS RESET signal 
113
    reset <= 0;
114
  end
115
  else begin
116
    reset <= 1;          //while in reset display is disabled, suare is set to initial position
117
    timer_t <= timer_t + 1;
118
    disp_en <= 0;      
119
    sq_pos_x <= init_x;        
120
    sq_pos_y <= init_y;
121
  end
122
  
123
  if(reset == 1) begin          //while RESET is high init counters
124
  
125
  
126
    sq_figure[0][19:0] <=  20'b00000000000000000000;
127
    sq_figure[1][19:0] <=  20'b00000001111100000000;
128
    sq_figure[2][19:0] <=  20'b00000111111111000000;
129
    sq_figure[3][19:0] <=  20'b00011111111111110000;
130
    sq_figure[4][19:0] <=  20'b00111111111111111000;
131
    sq_figure[5][19:0] <=  20'b00111111111111111000;
132
    sq_figure[6][19:0] <=  20'b01111111111111111100;
133
    sq_figure[7][19:0] <=  20'b01111111111111111100;
134
    sq_figure[8][19:0] <=  20'b11111111111111111110;
135
    sq_figure[9][19:0] <=  20'b11111111111111111110;
136
    sq_figure[10][19:0] <=  20'b11111111111111111110;
137
    sq_figure[11][19:0] <=  20'b11111111111111111110;
138
    sq_figure[12][19:0] <=  20'b11111111111111111110;
139
    sq_figure[13][19:0] <=  20'b01111111111111111100;
140
    sq_figure[14][19:0] <=  20'b01111111111111111100;
141
    sq_figure[15][19:0] <=  20'b00111111111111111000;
142
    sq_figure[16][19:0] <=  20'b00111111111111111000;
143
    sq_figure[17][19:0] <=  20'b00011111111111110000;
144
    sq_figure[18][19:0] <=  20'b00000111111111000000;
145
    sq_figure[19][19:0] <=  20'b00000001111100000000;
146
  
147
    c_hor <= 0;
148
    c_ver <= 0;
149
    vga_hs_r <= 1;
150
    vga_vs_r <= 0;
151
    c_row <= 0;
152
    c_col <= 0;
153
  end
154
  else begin            // update current beam position
155
    if(c_hor < h_frame - 1) begin
156
      c_hor <= c_hor + 1;
157
    end
158
    else begin
159
      c_hor <= 0;
160
      if(c_ver < v_frame - 1) begin
161
        c_ver <= c_ver + 1;
162
      end
163
      else begin
164
        c_ver <= 0;
165
      end
166
    end
167
  end
168
  if(c_hor < h_pixels + h_fp + 1 || c_hor > h_pixels + h_fp + h_pulse) begin  // H-SYNC generator
169
    vga_hs_r <= ~h_pol;
170
  end
171
  else begin
172
    vga_hs_r <= h_pol;
173
  end
174
  if(c_ver < v_pixels + v_fp || c_ver > v_pixels + v_fp + v_pulse) begin    //V-SYNC generator
175
    vga_vs_r <= ~v_pol;
176
  end
177
  else begin
178
    vga_vs_r <= v_pol;
179
  end
180
  if(c_hor < h_pixels) begin    //c_col and c_row counters are updated only in the visible time-frame
181
    c_col <= c_hor;
182
  end
183
  if(c_ver < v_pixels) begin
184
    c_row <= c_ver;
185
  end
186
  if(c_hor < h_pixels && c_ver < v_pixels) begin    //VGA color signals are enabled only in the visible time frame
187
    disp_en <= 1;
188
  end
189
  else begin
190
    disp_en <= 0;
191
  end
192
  if(disp_en == 1 && reset == 0) begin
193
    if(c_row == 0 || c_col == 0 || c_row == v_pixels-1 || c_col == h_pixels-1) begin  //generate red frame with size 640x480
194
      vga_r_r <= 7;
195
      vga_g_r <= 0;
196
      vga_b_r <= 0;
197
    end
198
    else if(c_col > l_sq_pos_x && c_col < r_sq_pos_x && c_row > u_sq_pos_y && c_row < d_sq_pos_y) begin  //generate blue square
199
      //vga_r_r <= 7;
200
      //vga_g_r <= 0;
201
      //vga_b_r <= 7;
202
      if(sq_figure[sq_fig_y][sq_fig_x] == 1) begin
203
      vga_r_r <= 7;
204
      vga_g_r <= 0;
205
      vga_b_r <= 7;
206
      end
207
      else begin
208
      vga_r_r <= 0;
209
      vga_g_r <= 0;
210
      vga_b_r <= 0;
211
      end
212
    end
213
    else begin      //everything else is black
214
      vga_r_r <= 0;
215
      vga_g_r <= 0;
216
      vga_b_r <= 0;
217
    end
218
  end
219
  else begin      //when display is not enabled everything is black
220
    vga_r_r <= 0;
221
    vga_g_r <= 0;
222
    vga_b_r <= 0;
223
  end
224
  
225
  if(c_row == 1 && c_col == 1) begin    //once per video frame
226
    if(u_arr) begin
227
      if (sq_pos_y > square_size) begin
228
        sq_pos_y <= sq_pos_y - 1;
229
      end
230
      else begin
231
        u_arr <= 0;
232
        d_arr <= 1;
233
      end
234
    end;
235
236
    if(d_arr) begin
237
      if (sq_pos_y < (v_pixels - 1 - square_size)) begin
238
        sq_pos_y <= sq_pos_y + 1;
239
      end
240
      else begin
241
        d_arr <= 0;
242
        u_arr <= 1;
243
      end
244
    end;
245
246
    if(l_arr) begin
247
      if (sq_pos_x > square_size) begin
248
        sq_pos_x <= sq_pos_x - 1;
249
      end
250
      else begin
251
        l_arr <= 0;
252
        r_arr <= 1;
253
      end
254
    end;
255
256
    if(r_arr) begin
257
      if (sq_pos_x < (h_pixels - 1 - square_size)) begin
258
        sq_pos_x <= sq_pos_x + 1;
259
      end
260
      else begin
261
        r_arr <= 0;
262
        l_arr <= 1;
263
      end
264
    end;
265
266
  end
267
268
  ps2_clk_buf[1:0] <= {ps2_clk_buf[0], ps2_clk};  // shift old value left and get current value of ps2_clk
269
  if(ps2_clk_pos == 1) begin      // on positive edge
270
    ps2_cntr <= ps2_cntr + 1;
271
    if(ps2_cntr == 10) begin    // when we got 10 clocks save the PS2 data to ps2_data_reg, ps2_data_reg_prev and ps2_data_reg_prev1 
272
      ps2_cntr <= 0;      // so we have last 3 data values captured from PS2 keyboard
273
      ps2_data_reg[7] <= ps2_dat_r[0];
274
      ps2_data_reg[6] <= ps2_dat_r[1];
275
      ps2_data_reg[5] <= ps2_dat_r[2];
276
      ps2_data_reg[4] <= ps2_dat_r[3];
277
      ps2_data_reg[3] <= ps2_dat_r[4];
278
      ps2_data_reg[2] <= ps2_dat_r[5];
279
      ps2_data_reg[1] <= ps2_dat_r[6];
280
      ps2_data_reg[0] <= ps2_dat_r[7];
281
      ps2_data_reg_prev <= ps2_data_reg;
282
      ps2_data_reg_prev1 <= ps2_data_reg_prev;
283
    end
284
    ps2_dat_r <= {ps2_dat_r[9:0], ps2_data};  // data shift left
285
  end
286
287
/*  if(ps2_data_reg_prev1 == 8'he0 && ps2_data_reg_prev == 8'hf0) begin  // 0xE0 0xF0 sequaence means key released
288
    if(ps2_data_reg == 8'h75) begin
289
      u_arr <= 0;        //0x75 up key
290
    end
291
    else if(ps2_data_reg == 8'h6b) begin
292
      l_arr <= 0;        //0x6B left key
293
    end
294
    else if(ps2_data_reg == 8'h72) begin
295
      d_arr <= 0;        //0x72 down key
296
    end
297
    else if(ps2_data_reg == 8'h74) begin
298
      r_arr <= 0;        //0x74 right key
299
    end
300
  end
301
*/  
302
  arr_timer <= arr_timer + 1;
303
  
304
  if(arr_timer == 0) begin
305
306
    sq_figure[8][19:0] <=  sq_figure[8][19:0] ^ 20'b00000001111000000000;
307
    sq_figure[9][19:0] <=  sq_figure[9][19:0] ^ 20'b00000001111000000000;
308
    sq_figure[10][19:0] <=  sq_figure[10][19:0] ^ 20'b00000001111000000000;
309
    sq_figure[11][19:0] <=  sq_figure[11][19:0] ^ 20'b00000001111000000000;
310
311
312
    if(ps2_data_reg_prev == 8'he0) begin      //0xE0  means key pressed
313
      if(ps2_data_reg == 8'h75) begin    
314
        if(u_arr == 1) begin
315
          u_arr <= 1;        //0x75 up key  
316
          d_arr <= 0;
317
          l_arr <= 0;
318
          r_arr <= 0;
319
        end
320
        else begin
321
          u_arr <= 1;        //0x75 up key  
322
          d_arr <= 0;
323
        end
324
        ps2_data_reg <= 0;
325
      end
326
      if(ps2_data_reg == 8'h6b) begin    
327
        if(l_arr == 1) begin
328
          l_arr <= 1;        //0x6B left key
329
          r_arr <= 0;
330
          u_arr <= 0;
331
          d_arr <= 0;
332
        end
333
        else begin
334
          l_arr <= 1;        //0x6B left key
335
          r_arr <= 0;
336
        end
337
        ps2_data_reg <= 0;
338
      end
339
      if(ps2_data_reg == 8'h72) begin
340
        if(d_arr == 1) begin
341
          d_arr <= 1;        //0x72 down key
342
          u_arr <= 0;
343
          l_arr <= 0;
344
          r_arr <= 0;
345
        end
346
        else begin
347
          d_arr <= 1;        //0x72 down key
348
          u_arr <= 0;
349
        end
350
        ps2_data_reg <= 0;
351
      end
352
      if(ps2_data_reg == 8'h74) begin
353
        if(r_arr == 1) begin
354
          r_arr <= 1;        //0x74 right key
355
          l_arr <= 0;
356
          u_arr <= 0;
357
          d_arr <= 0;
358
        end
359
        else begin
360
          r_arr <= 1;        //0x74 right key
361
          l_arr <= 0;
362
        end
363
        ps2_data_reg <= 0;
364
      end
365
    end  
366
  end
367
368
369
end
370
371
endmodule

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


Lesenswert?

bernd schrieb:
> Wie kann man diese VGA-CLK bitte für ein Board mit 50MHZ anpassen?
Nimm eine PLL/DLL/DCM und mach aus den 50Mhz die 100MHz, die das Design 
wil...


> Wie kann man diese VGA-CLK bitte für ein Board mit 50MHZ anpassen?
Wo ist der "Taktteiler"?
1
assign   vga_clk   = clk_div[1];    // 25Mhz clock = 100Mhz divided by 2-bit counter
2
3
always @ (posedge CLK100MHz) begin    // 2-bt counter ++ on each positive edge of 100Mhz clock
4
  clk_div <= clk_div + 2'b1;
5
end
6
7
always @ (posedge vga_clk) begin        //25Mhz clock
8
  ...

BTW:
Das ist ein offensichtlich hingebasteltes, zurechtgemurkstes 
Anfängerdesign, denn per Zähler werden in FPGAs keine Takte erzeugt. Ein 
brauchbares synchrones Design arbeitet mit Clock-Enables. Etwa so:
1
reg  vga_clken;  
2
3
always @ (posedge CLK50MHz) begin    // generate clock enable for 25 MHz
4
  vga_clken <= not vga_clken;
5
end
6
7
always @ (posedge CLK50MHz) begin    // the one and only clock!
8
  if (vga_clken==1) begin            // 25MHz VGA
9
    ...

: Bearbeitet durch Moderator
von bernd (Gast)


Lesenswert?

Danke für die Info.

Gruss

von bernd (Gast)


Lesenswert?

Wie bindet man hier bitte eine PLL ein?
Habe sie jetzt angelegt mit Quartus.

Danke.

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


Lesenswert?

bernd schrieb:
> Wie bindet man hier bitte eine PLL ein?
Mit Altera/Intel habe ich keine Erfahrung, aber die PLL ist hier auch 
schlecht, weil (wie erklärt) das Design schlecht ist. Die gute und 
einfache Lösung (zudem ohne PLL) habe ich doch gezeigt. Warum nimmst du 
die nicht?

: Bearbeitet durch Moderator
von Gustl B. (-gb-)


Lesenswert?

In dem schon älteren Quartus hier heißt die Komponente "ALTPLL", die 
kann man sich generieren lassen und als Komponente einbinden.

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.