Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions rtl/video/VGA_timing_op.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
The purpose of the VGA timing module is to generate the horizontal and vertical synchronization pulses and pixel coordinate signals required for standard VGA resolutions (e.g., 640×480 @ 60 Hz). It defines when each pixel should be drawn, when blanking intervals occur, and when sync pulses are active essentially acting as the heartbeat of the display pipeline. Other video blocks, such as the framebuffer controller or DAC driver, use these timing signals to know when to fetch and output video data.

Parameters

| Name | Default | Description |
| ----------| ------- | --------------------------------------------|
| H_RES | 640 | Active horizontal pixels per line |
| V_RES | 480 | Active vertical pixels per frame |
| H_FP | 16 | Horizontal front porch (pixels) |
| H_SYNC | 96 | Horizontal sync pulse width (pixels) |
| H_BP | 48 | Horizontal back porch (pixels) |
| V_FP | 10 | Vertical front porch (lines) |
| V_SYNC | 2 | Vertical sync pulse width (lines) |
| V_BP | 2 | Vertical back porch (lines) |
| PIXEL_CLK | 25*10^6 | Pixel clock frequency for 640 by 480 @ 60Hz |

Interfaces (Ports)

| Signal | Dir | Width | Description |
| ---- | ---- | ---- |-------------------------------------------------------------------------------------------------------------|
| clk | Input | 1 | Main pixel clock. Ensures timing logic and display pipeline stay synchronized |
| reset | Input | 1 | Active-low synchronous reset |
| hsync | Output | 1 | Horizontal sync pulse. Signals the end of a frame (start of new refresh) |
| vsync | Output | 1 | Vertical sync pulse. Signals the end of a frame (start of new fresh) |
| x | Output | 10 | Horizontal pixel counter (0-639 during active display) |
| y | Output | 10 | Vertical pixel counter (0-479 during active display) |
| active_video | Output | 1 | High during visible display time; low during blanking intervals (used to gate pixel output or blank screen) |

Reset/Initialization

- On reset (reset = 0), all internal counters (x,y) reset to zero and both sync outputs (hsync, vsync) are deserted
- The module begins normal operation as soon as reset is released and a valid clk is present
- No external configuration sequence is required timing parameters are static or parametrized at synthesis

Behavior and Timing

- The module implements two nested counters:
- The horizontal counter (x) increments every clock cycle
- When x reaches the total pixels per line, it resets to zero and increments the vertical counter (y)
- hsync is asserted low for H_SYNC cycles after the active + front porch interval
- vsync is asserted low for V_SYNC lines after the active + front porch period
- The signal active_video is high only when both x and y are within the active display area
- The structure guarantees a 60 Hz refresh at 640 \* 480 with a 25 MHz pixel clock

Errors / IRQs

- This module does not generate interrupts or error signals
- It operates continuously as long as a valid clock is provided
- Any display synchronization or VSYNC interrupt is usually handled by the framebuffer controller

Dependencies

- Clock: Requires a stable pixel clock (typically 25 MHz).
- Reset: Synchronous, active-low (reset).
- Upstream IP: Clock generation block (PLL or divider).
- Downstream IP: Framebuffer controller or video DAC/encoder that consumes timing signals.

Summary

- The VGA timing generator defines the temporal structure of a video frame by driving sync pulses, counters, and valid video windows. It forms the foundation for raster-scan display logic and provides synchronization for all downstream video pipeline modules
79 changes: 79 additions & 0 deletions rtl/video/vga_timing.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
module VGA_timing(
input clk_i, //clock to control porject
input rst_ni, //active low reset
output hsync, //horizotal sync
output vsync, //vertical sync

/****/
//not in ond pager added after fact
output reg [9:0] pos_in_row, //current position in row
output reg [9:0] pos_in_col, //current position in col
/****/

output reg [9:0] x, //x coordinate to display pixel data
output reg [9:0] y, //y coordinate to display pixel data
output reg active_video //determines whether we have active video or not
);

//parameters for VGA window
localparam H_RES = 640,
V_RES = 480,
H_FP = 16,
H_SYNC = 98,
H_BP = 48,
V_FP = 10,
V_SYNC = 2,
V_BP = 2,
H_ACTIVE_START = H_SYNC + H_BP, //this parameter list the start of the valid horizontal output
H_ACTIVE_END = H_ACTIVE_START + H_RES, //this parameter contains when to stop output data
V_ACTIVE_START = V_SYNC + V_BP,
V_ACTIVE_END = V_SYNC + 480;


/* STUFF TO CONTROL and MAKE VGA CLOCK */
reg [2:0] counter;
reg pixel_clk;
initial begin
counter = 0;
end

always@ (posedge clk_i) begin
if (counter == 2'd2) begin
pixel_clk <= ~pixel_clk;
counter <= 0;
end
else begin
counter <= counter + 1;
end
end
Comment on lines +36 to +48
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionality Issue: For the counter, initial blocks usually are not synthesizable and reset signals are preferred. For the internal clock pixel_clk, you need to have an initial value or simulations won't have a definite signal (1 or 0) to show it as. Please use a reset signal instead as follows:

always @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
        pixel_clk <= 0;
        counter <= 0;
    end
    // Rest of logic goes here
end


/* clock end */



/* STUFF TO CONTROL VGA DISPLAY */
assign hsync = (x < H_SYNC) ? 1'b0 : 1'b1; //while this is less than the HSYNC value (98) it is going to not write valid data (black)
assign vsync = (y < V_SYNC) ? 1'b0 : 1'b1; //while this is less than the VSYNC value (2) it is going to not write valid data (black)


always@ (posedge pixel_clk) begin
if (rst_ni) begin
x <= 0;
y <= 0;
active_video <= 0;
end
Comment on lines +59 to +64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionality Issue: To match other subsystems, please treat rst_ni as an asynchronous (independent of clock) reset (see previous comment for example).


if (active_video == 1'b1) begin
if ((pos_in_row >= H_ACTIVE_START) && (pos_in_row < H_ACTIVE_END) &&
(pos_in_col >= V_ACTIVE_START) && (pos_in_col < V_ACTIVE_END)) begin
x <= pos_in_row - H_ACTIVE_START;
y <= pos_in_col - V_ACTIVE_START;
end
end
else begin //not within valid data window
x <= 0;
y <= 0;
end
end
/* VGA STUFF */
endmodule