1
\$\begingroup\$

I'm trying to get VGA working on my Altera DE0 board using Verilog, but haven't had much luck. It has the same pins as a normal VGA interface except red, green, and blue are all 4 bits each. Here is the logic I've been trying to use to get a solid color to display:

module solid_color (clk, vga_h_sync, vga_v_sync, R, G, B);

input clk;
output vga_h_sync;
output vga_v_sync;
output [3:0] R;
output [3:0] G;
output [3:0] B;

reg [9:0] CounterX;
reg [8:0] CounterY;
wire CounterXmaxed = (CounterX==767);

always @(posedge clk)
if(CounterXmaxed)
  CounterX <= 0;
else
  CounterX <= CounterX + 1;

always @(posedge clk)
if(CounterXmaxed)
    CounterY <= CounterY + 1;

reg vga_HS, vga_VS;
always @(posedge clk)
begin
  vga_HS <= (CounterX[9:4]==0);   // active for 16 clocks
  vga_VS <= (CounterY==0);   // active for 768 clocks
end

assign vga_h_sync = ~vga_HS;
assign vga_v_sync = ~vga_VS;

assign R = 15;
assign G = 15;
assign B = 15;

endmodule

When I try running it, I just get a message on the monitor saying that this display mode is not supported.

This is adapted from http://www.fpga4fun.com/PongGame.html. However, this version claims to be designed for 640x480 displays whereas my monitor is 1280x1024. Is this the issue? If so, how would I adapt this to fit the increased monitor size? (the clock I'm using is 50 MHz)

EDIT: I added in a clock divider module as follows to change the initial clock signal to 25 MHz:

module divide_clock_by_two(in_clk, out_clk);

input in_clk;
output out_clk;
reg out_clk;

always @(posedge in_clk)
out_clk <= ~out_clk;

endmodule

However, the monitor now just shows a black screen, no message about an incorrect mode.

\$\endgroup\$
9
  • \$\begingroup\$ That page says "Using a 25MHz clock", so you need to halve the clock or double all your timings. \$\endgroup\$
    – pjc50
    Oct 19, 2014 at 15:48
  • \$\begingroup\$ The clk input to that module is a "pixel" clock, not a system clock. You need to provide the right frequency clock for the resolution you are using. \$\endgroup\$
    – Majenko
    Oct 19, 2014 at 15:56
  • \$\begingroup\$ I tried changing CounterX==767 to CounterX==1535 and CounterX[9:4] to CounterX[9:5] to double the timings, but this did not work. \$\endgroup\$
    – aftrumpet
    Oct 19, 2014 at 17:11
  • \$\begingroup\$ Majenko, would this mean changing the timings or changing the input clock itself? According to this page with pixel clock timings: tinyvga.com/vga-timing, I would need to have at least a 108 MHz clock to drive my display, but this can't be correct because I have seen the board driving the display with just its 50 MHz clock in demos. \$\endgroup\$
    – aftrumpet
    Oct 19, 2014 at 17:13
  • \$\begingroup\$ I don't know what you're reading, but I see: "VGA 640x480@60 Hz Industry standard (pixel clock 25.175 MHz)" - that's the speed of clock you should be passing to clk - or thereabouts (most monitors allow a bit of leeway). \$\endgroup\$
    – Majenko
    Oct 19, 2014 at 17:23

1 Answer 1

3
\$\begingroup\$

Most VGA monitors will "calibrate out the DC offset" if you drive the RGB signals outside of the viewable area.

While it may not be your only or even most serious problem, this looks to be an issue in your implementation (you drive constants), so try adding logic to drive your color signals to black when outside the intended display rectangle.

\$\endgroup\$
8
  • \$\begingroup\$ I was about to comment that the R G and B must be "off", i.e., set to black, during all blanking periods. Then I read your answer :P \$\endgroup\$
    – Majenko
    Oct 19, 2014 at 21:06
  • \$\begingroup\$ That was the issue. I changed the assignments of R, G, and B and now I have a pattern. Also credit to Majenko though for the 25 MHz clock, as that was also necessary. \$\endgroup\$
    – aftrumpet
    Oct 20, 2014 at 13:40
  • \$\begingroup\$ Although, how would I change this for a constant display of colors? In other words, with these counters, how would I recognize from the clock signals to stop driving RGB signals? \$\endgroup\$
    – aftrumpet
    Oct 20, 2014 at 13:52
  • \$\begingroup\$ Use logic on each count value to determine when that axis is within the display region. \$\endgroup\$ Oct 20, 2014 at 15:13
  • \$\begingroup\$ But how do I determine what the display region is? I was under the impression that the x and y counters already took care of that by looping back when they hit the maximum value. \$\endgroup\$
    – aftrumpet
    Oct 21, 2014 at 2:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.