It's a common pattern to use a rgb-to-dvi ip core to recieve VGA signals and transform them to HDMI signals. So you don't need too much knowledge about HDMI. Remember our design pattern, which is shown below. Our rgb-to-dvi instance just lies in "Video Out".
I don't know the details about HDMI, I just list the key points.
Key points
Connector
A standard HDMI connector has 19 pins. Out of the 19 pins, 8 are of particular interest as they form 4 TMDS differential pairs to transport the actual high-speed video info.
TMDS clock+ and clock-
TMDS data0+ and data0-
TMDS data1+ and data1-
TMDS data2+ and data2-
HDMI output enable is occasionally necessary, but most of the time it is not.
Does HDMI needs synchronization signals? If answer is yes, where? If answer is no, why? (answered in later sections)
TMDS
Video data travels on the Transition Minimised Differential Signalling (TMDS) physical layer in HDMI, same as DVI. TMDS signalling standard encodes 8 bits of each colour (RGB) into 10 bits. The information is then transmitted at 10x the speed of the pixel clock. This format is called 8b/10b.
Control data
C0 and C1 are control bits. We map HSYNC and VSYNC signals to the C0 and C1 ports of blue encoder. We set other control bits in green and red encoder 0.
Why we only map the control signals to blue encoder?
Don't leave it at the default settings. That will not work!
signal_480p.sv
module signal_480p (
input wire logic clk_pix, // pixel clock
input wire logic rst_pix, // reset in pixel clock domain
output logic [9:0] sx, // horizontal screen position
output logic [9:0] sy, // vertical screen position
output logic hsync, // horizontal sync
output logic vsync, // vertical sync
output logic de // data enable (low in blanking interval)
);
// horizontal timings
parameter HA_END = 639; // end of active pixels
parameter HS_STA = HA_END + 16; // sync starts after front porch
parameter HS_END = HS_STA + 96; // sync ends
parameter LINE = 799; // last pixel on line (after back porch)
// vertical timings
parameter VA_END = 479; // end of active pixels
parameter VS_STA = VA_END + 10; // sync starts after front porch
parameter VS_END = VS_STA + 2; // sync ends
parameter SCREEN = 524; // last line on screen (after back porch)
always_comb begin
hsync = ~(sx >= HS_STA && sx < HS_END); // invert: negative polarity
vsync = ~(sy >= VS_STA && sy < VS_END); // invert: negative polarity
de = (sx <= HA_END && sy <= VA_END);
end
// calculate horizontal and vertical screen position
always_ff @(posedge clk_pix) begin
if (sx == LINE) begin // last pixel on line?
sx <= 0;
sy <= (sy == SCREEN) ? 0 : sy + 1; // last line on screen?
end else begin
sx <= sx + 1;
end
if (rst_pix) begin
sx <= 0;
sy <= 0;
end
end
endmodule