Here we go, I cleaned up your sync generator. You had a few bugs. Now, I don't have Quartus installed anymore and I just typed it in a text editor, so please bear with possible errors. Once you understand my changes, you may remove anything you don't like:
// (default 640x480) 60Hz VGA Driver
// but can take parameters when initialised
// to output sync signals for any screen
// resolution
//
// |- LINE
// __________________________ ____|
// | | |
// | | |
// | | |
// | | |
// | DISPLAY AREA | |
// | | |
// | | |
// | | |
// --------------------------------- V_RES
// | |
// | |
// ---------------------------- SCANLINES
module sync_generator(
// inputs
input wire pclk, // base pixel clock
input wire reset, // reset: restarts frame
// outputs
output reg pc_ena // ***** New pixel clock enable ... For now, you will use pc_ena[0] which divides the clock by 2.
output reg hde, // Horizontal Display Enable - high when in display area (valid drawing area)
output reg vde, // Vertical Display Enable - high when in display area (valid drawing area)
output reg hsync, // horizontal sync
output reg vsync, // vertical sync
output reg [9:0] h_count, // current pixel x position
output reg [9:0] v_count // current line y position
);
// default resolution if no parameters are passed
parameter H_RES = 640; // horizontal display resolution
parameter V_RES = 480; // vertical display resolution
// no-draw area definitions
// ***** switched to parameters so you can edit these on quartus' block diagram editor.
parameter H_FRONT_PORCH = 16;
parameter HSYNC_WIDTH = 96;
parameter H_BACK_PORCH = 48;
parameter V_FRONT_PORCH = 10;
parameter VSYNC_HEIGHT = 2;
parameter V_BACK_PORCH = 33;
// total screen resolution
localparam LINE = H_RES + H_FRONT_PORCH + HSYNC_WIDTH + H_BACK_PORCH; // complete line (inc. horizontal blanking area)
localparam SCANLINES = V_RES + V_FRONT_PORCH + VSYNC_HEIGHT + V_BACK_PORCH; // total scan lines (inc. vertical blanking area)
// useful trigger points
localparam HS_STA = H_RES + H_FRONT_PORCH - 1; // horizontal sync ON (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam HS_END = H_RES + H_FRONT_PORCH + HSYNC_WIDTH - 1;// horizontal sync OFF (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam VS_STA = V_RES + V_FRONT_PORCH; // vertical sync ON
localparam VS_END = V_RES + V_FRONT_PORCH + VSYNC_HEIGHT; // vertical sync OFF
/* moved above
reg [9:0] h_count; // line position
reg [9:0] v_count; // SCANLINES position
reg [9:0] z_count; // Frame counter for CPU animation
*/
// keep x and y bound within the display area
/* obsolete
assign x = (h_count < H_RES) ? h_count : (H_RES - 1'b1); // x = H_RES-1 if current pixel is after display area
assign y = (v_count < V_RES) ? v_count : (V_RES - 1'b1); // y = VS_END-1 if v_count is outside display area
*/
// generate a 25 MHz pixel strobe
//reg [15:0] cnt;
//reg pix_en;
always @(posedge clk)
pc_ena <= pc_ena + 1'b1; // This is tempoary
// handle signal generation
always @(posedge clk) // I removed ', posedge reset)', since it adds a gate to the CLK input of all the registers in your design slowing down that trigger edge
begin
if (reset) // reset to start of frame
begin
h_count <= 1'b0;
v_count <= 1'b0;
hsync <= 1'b0;
vsync <= 1'b0;
vde <= 1'b0;
hde <= 1'b0;
end
else
begin
if (pc_ena) // once per pixel
begin
if (h_count == H_RES - 1)
begin
HDE <= 1'b0;
end
// check for generation of HSYNC pulse
if (h_count == HS_STA)
begin
hsync <= 1'b1; // turn on HSYNC pulse
end
else if (h_count == HS_END)
hsync <= 1'b0; // turn off HSYNC pulse
// check for generation of VSYNC pulse
if (v_count == VS_STA)
begin
vsync <= 1'b1; // turn on VSYNC pulse
end
else if (v_count == VS_END)
vsync <= 1'b0; // turn off VSYNC pulse
// reset h_count & increment v_count at end of scanline
if (h_count == LINE - 1) // end of line
begin
h_count <= 1'b0;
HDE <= 1'b1; // Turn on horizontal video data enable
if (v_count == SCANLINES - 1) // ****** Now that it's time to increment the H count, this is when you would check if the V-count should be cleared. End of SCANLINES
begin
v_count <= 1'b0;
VDE <= 1'b1; // Turn on vertical video data enable
end
else
begin // ****** If the v_count isn't being cleared, you go ahead and add 1 to the v_count
v_count <= v_count + 1'b1; // increment v_count to next scanline
if (v_count == V_RES - 1) VDE <= 1'b0 ; // Turn off vertical video data enable
end
end
else
h_count <= h_count + 1'b1; // otherwise, just increment horizontal counter
if (h_count == H_RES - 1) HDE <= 1'b0 ; // Turn off vertical video data enable
/* ****** BUG ***** Moved into the correct place at the the end of a horizontal line, where you increment the v_count increment, or clear it. see 16 lines above
// reset v_count and blanking at bottom of screen
if (v_count == SCANLINES - 1) // end of SCANLINES
begin
v_count <= 1'b0;
end
*/ ***** End of bug ******
end
end
end
/******* Error ****** this must synchronous with you video clock, however, I recognize this was probably just a last minute patch.
always @(posedge clk)
begin
DE <= (h_count < H_RES) && (v_count < V_RES);
end
/********
endmodule
Now, here is a new module to add to your project. It mutes the RGB data values when the raster is outside the active display area. (Once again, I just typed it in notepad.) It belongs just before your output pins. Again, read comments inside it.
// This module will force mute mute the RGB video output data outside the active video display area
// This module will also generate the vid_de_out use by many DVI transmiters
// This module, as an example, also has all the inputs and outputs used along the pixel pipe
// it illustrates since there is a pixel delay in the video switch, the syncs and video enables are also delayed
// making the output picture window perfectly parallel with the vidoe coming in, then being fed out.
module vid_out_stencil(
input wire pclk,
input wire reset,
input wire pc_ena, // Pixel clock enable
input wire hde_in, // Horizontal Display Enable - high when in display area (valid drawing area)
input wire vde_in, // Vertical Display Enable - high when in display area (valid drawing area)
input wire hs_in, // horizontal sync
input wire vs_in, // vertical sync
input wire [RGB_hbit:0] r_in,
input wire [RGB_hbit:0] g_in,
input wire [RGB_hbit:0] b_in,
output reg hde_out,
output reg vde_out,
output reg hs_out,
output reg vs_out,
output reg [RGB_hbit:0] r_out,
output reg [RGB_hbit:0] g_out,
output reg [RGB_hbit:0] b_out,
output reg vid_de_out // Actual H&V data enable required by some DVI encoders/serializers
);
parameter RGB_hbit = 1; // 1 will make the RGB ports go from 1 to 0, eg [1:0]. I know others prefer a '2' here for 2 bits
parameter HS_invert = 0; // use a 1 to invert the HS output, the invert feature is only for this video output module
parameter VS_invert = 0; // use a 1 to invert the VS output, the invert feature is only for this video output module
always @(posedge clk)
begin
if (reset) // global reset
begin
// not in use for this module
end
else
begin
if (pc_ena) // once per pixel
begin
hde_out <= hde_in; // since the this video muting switch algorythm delays the output by 1 pixel clock,
vde_out <= vde_in; // all the video timing reference signals will also get the 1 pixel delay treatment to keep the output aligned perfectly.
hs_out <= hs_in ^ HS_invert ; // the invert feature is only for this video output module
vs_out <= vs_in ^ VS_invert ; // the invert feature is only for this video output module
if ( hde_in && vde_in )
begin
de_out <= 1'b1 ; // turn on video enable for DVI transmitters
r_out <= r_in ; // copy video input to output
g_out <= g_in ; // copy video input to output
b_out <= b_in ; // copy video input to output
end
else
begin
de_out <= 1'b0 ; // turn off video enable for DVI transmitters
r_out <= 0 ; // Mute video output to black
g_out <= 0 ; // Mute video output to black
b_out <= 0 ; // Mute video output to black
end
end
end
end
endmodule
Now, the next thing you need to do is use the IOs from this example, and make a new picture pattern generator which does not use the sync generators H&V counters, but, generates it's own internally using this example IO port setup:
module vid_pattern_generator(
input wire pclk,
input wire reset,
input wire pc_ena, // Pixel clock enable
input wire hde_in, // Horizontal Display Enable - high when in display area (valid drawing area)
input wire vde_in, // Vertical Display Enable - high when in display area (valid drawing area)
input wire hs_in, // horizontal sync
input wire vs_in, // vertical sync
output reg hde_out,
output reg vde_out,
output reg hs_out,
output reg vs_out,
output reg [RGB_hbit:0] r_out,
output reg [RGB_hbit:0] g_out,
output reg [RGB_hbit:0] b_out
);
parameter RGB_hbit = 1; // 1 will make the RGB ports go from 1 to 0, eg [1:0]. I know others prefer a '2' here for 2 bits
always @(posedge clk)
begin
if (reset) // global reset
begin
end
else
begin
if (pc_ena) // once per pixel
begin
// *************** insert generator code here
// *************** also remember to pass through the hde,vde,hs_out,vs_out
// *************** in the future, numerous delay sizes may be needed if you are performing functions which take multiple clocks before a true pixel becomes valid
end
end
end // always @clk
endmodule
Let me know when you are done, because, after I've gone over your new pattern generator, your next step is to place either your first text, or, graphics.
Additional: Please place you quartus screenshots on this forum, I'm having trouble with your picture server & since this thread may last long on the forum, it is a good idea to have the photos here. (If you want a compact picture file size, lossless, use the .png file format...)
***** DON'T forget to update the graphic symbol for the changes I made to you sync generator. The order of the IO pins have been changes and I changed the available parameters on the block diagram symbol.