After doing plenty of research on how to generate VGA signals and looking at a few code examples, I attempted to write my a simple VGA signal generator that just displays a single solid color on the screen. When viewing the simulation, the timing appears to be correct. When connected to a monitor, the monitor does not even acknowledge that a signal is being generated. This has got me stumped, any help would be appreciated.
I am using timing information found here: http://tinyvga.com/vga-timing/640×480@60Hz
Sync pulse generator:
module VGASyncPulseGenerator(
input clk, //50Mhz input clock
input rst,
output HS, VS, //Sync Pulses
output active //High when active area is being drawn
);
localparam HS_START = 16; // hSync start (end of front porch)
localparam HS_END = 16 + 96; // hSync end (start of back porch)
localparam HA_START = 16 + 96 + 48; // end of back porch
localparam LINE = 800; // Length of entire line;
localparam VS_START = 480 + 10; // vSync start (end of front porch)
localparam VS_END = 6480 + 10 + 2; // vSync end (start of back porck)
localparam VA_START = 0;
localparam FRAME = 525; // Length of entire frame
reg [10:0] hPos = 0;
reg [10:0] vPos = 0;
reg pixelStrobe = 0;
assign HS = ~((hPos >= HS_START) & (hPos < HS_END));
assign VS = ~((vPos >= VS_START) & (vPos < VS_END));
assign active = (hPos >= HA_START) & (vPos >= VA_START);
always @(posedge clk) begin //generate pixel clock at 25MHz
pixelStrobe = ~pixelStrobe;
end
always @(posedge clk) begin
if (pixelStrobe) begin
if (hPos == LINE) begin
hPos <= 0;
vPos <= vPos + 1;
end else hPos <= hPos + 1;
if (vPos == FRAME) vPos <= 0;
end
end
endmodule
Top module:
module VGATest(
input clk, rst,
output HS, VS,
output [4:0] B,
output [5:0] R,
output [4:0] G
);
wire active;
assign R = (active) ? 5'd1 : 5'b0;
assign G = (active) ? 4'd16 : 4'b0;
assign B = (active) ? 4'd1 : 4'b0;
VGASyncPulseGenerator pulseGen(clk, rst, HS, VS, active);
endmodule
Best Answer
Problems I see in your code:
640x480@60 uses a pixel clock of 25.175 MHz, not 25 MHz. The difference may be enough to keep some monitors from synchronizing. Consider using a PLL to generate the appropriate clock (50 MHz x72÷143 gives 25.1748 MHz, which is within 9 ppm), or targeting 800x600@72 instead, which uses a pixel clock of exactly 50 MHz.
The polarity of your sync pulses is wrong. 640x480@60 uses negative sync pulses --
HS
andVS
need to be low during sync, not high.There's a typo in the definition of
VS_END
. You probably want to use the constant 480, not 6480.Possible problems outside your code:
Do you have an appropriate constraints file? Are the signals being mapped to the right pins to reach the DAC?
Make sure your levels are correct. R/G/B are 0 to 0.7V; sync voltages aren't critical but should probably be 3.3V.