I am trying to get started with implementing a basic display (i.e a simple red screen) onto a VGA monitor by programming a Xilinx spartan3a fpga for the same. I have studied about the signal timings for a 640x480 @ 60hz display and implemented the same,however it turns out, The monitor does not recognize it.I tried using a sample test file (it was a bit file so couldn't reverse engineer it), and it worked perfectly so i think there's no issue with the hardware.
module main(
clk,
Hsync,
Vsync,
Red,
Green,
Blue,
led
);
//inputs:
input clk;
//outputs:
output Hsync;
output Vsync;
output[2:0] Red;
output[2:0] Green;
output [1:0] Blue;
output [7:0] led;
//wire
wire[9:0] hcounter;
wire[9:0] vcounter;
wire PixClk;
wire locked;
//regs:
reg reset;
clkgen inst(
.CLKIN_IN(clk),
.RST_IN(1'b0),
.CLKIN_IBUFG_OUT(),
.CLK0_OUT(PixClk),
.LOCKED_OUT(locked)
);
VGAcontroller controller1(
.locked(locked),
.pixel_clk(PixClk),
.hsync(Hsync),
.vsync(Vsync),
.hcounter(hcounter),
.vcounter(vcounter)
);
generateRGB RedScreen(
.RedPix(Red),
.GreenPix(Green),
.BluePix(Blue),
.Hcount(hcounter),
.Vcount(hcounter)
);
assign led[0]=locked;
assign led[7:1]=7'b0;
endmodule
the clockgen module generates a 25mhz signal, and led[0] goes "ON" when the dcm-pll has a locked onto the frequency.(works in the implementation).
'VGAcontroller' module is responsible for the 'Hsync' and 'Vsync' signal generation taking in 'Pixelclk' and locked as inputs with the rest as outputs. The 'generateRGB' module takes in the 'Hcounter' and 'Vcounter' values to provide the necessary analog values via 3 registers.
VGAcontroller.v
//800 horizontal counts
//525 vertical counts
module VGAcontroller(
locked,
pixel_clk,
hsync,
vsync,
hcounter,
vcounter
);
input locked;
input pixel_clk;
output hsync;
output vsync;
output[9:0] hcounter;
output[9:0] vcounter;
reg hsync;
reg vsync;
reg[9:0] hcounter;
reg[9:0] vcounter;
always @(posedge pixel_clk or posedge locked)
begin
if(locked)
begin
hcounter=hcounter+1'b1;
case(hcounter)
10'b0: hsync=1'b1; //d<0>
10'b1010010000: hsync=1'b0; //d<656>
10'b1011110000: hsync=1'b1; //d<752>
10'b1100100000: //d<800>
begin
hcounter=10'b0;
vcounter=vcounter+1'b1;
end
endcase
case(vcounter)
10'b0: vsync=1'b1; //d<0>
10'b0111101010: vsync=1'b0; //d<490>
10'b0111101100: vsync=1'b1; //d<492>
10'b1000001101: vcounter=10'b0; //d<525>
endcase
end else begin
hcounter=10'b0;
vcounter=10'b0;
end
end
endmodule
the timing sequence is as follows : [visible range]->[front porch]->[Sync pulse]->[back porch]
the reason for starting the counter with visible range is that the values of counters correspond to the location of the pixel on the screen. As of now , the 'generateRGB' simply assigns the register responsible for the red color to have full voltage while green and blue to be 0 i.e to print a red screen.
P.S. I am not exactly sure whether this question is valid for this forum or whether tags do good justice but if there is a better one, kindly recommend.thank you!