Display output#
We will use the FPGA to generate graphics on an HDMI display.
Steps:
Create a project
Clone hdmi-util/hdmi and add all the Systemverilog files under
src/
to your projectAdd board’s constraint file. This example uses the standard constraint file of the Boolean board.
Use
Clocking Wizard
from theIP Catalog
to generate an clock generator with the following properties. Do not use block design.:name the module
hdmi_pll
select
MMCM
(PLL
cannot generate the clock frequency that we require)clock input: 100 MHz named
clk
pixel clock: 74.25 MHz named
clk_pixel
5x pixel clock: 371.25 MHz named
clk_pixel_x5
Use the template
top.sv
below and synthesize. Connect the board to a monitor with an HDMI cable. It should show a white screen.
Problems:
Analyze
top.sv
. What are theclk_pixel
,tmds
,hdmi_tx_{p,n}
,c{x,y}
for? What does the parameterVIDEO_ID_CODE(4)
do?Display only green.
Display three vertical stripes with red, green and blue.
Display a left to right red gradient, leftmost side should be black and rightmost side should be red.
Display a white ball and make it move with a constant velocity. It should bounce back at the edges.
Project files#
module top (
input clk,
output [2:0] hdmi_tx_p, hdmi_tx_n,
output hdmi_clk_p, hdmi_clk_n
);
logic clk_pixel_x5, clk_pixel, tmds_clock;
logic [23:0] rgb;
logic [2:0] tmds;
logic [10:0] cx;
logic [9:0] cy;
hdmi #(
.DVI_OUTPUT(1),
.VIDEO_ID_CODE(4),
.VIDEO_REFRESH_RATE(60.0)
) hdmi(
.clk_pixel_x5, .clk_pixel, .tmds_clock, .rgb, .tmds, .cx, .cy);
hdmi_pll hdmi_pll(.clk, .clk_pixel, .clk_pixel_x5);
localparam COLOR_CHANNEL_COUNT = 3;
genvar i;
generate
for (i = 0; i < COLOR_CHANNEL_COUNT; ++i) begin: obufds_gen
OBUFDS obufds_hdmi_tx(.I(tmds[i]), .O(hdmi_tx_p[i]), .OB(hdmi_tx_n[i]));
end
OBUFDS obufds_hdmi_clk(.I(tmds_clock), .O(hdmi_clk_p), .OB(hdmi_clk_n));
endgenerate
assign rgb = '1;
endmodule
from PIL import Image
img = Image.open('image.jpg')
img.thumbnail((320, 240))
with open('image.memh', 'w') as f:
f.writelines(
hex(
(pixel[0]>>4 <<8) + (pixel[1]>>4 <<4) + (pixel[2]>>4)
)[2:] + '\n'
for pixel in img.getdata()
)
include vsyn.mk
# hdmi should be made before vivctrl.tcl to account for hdmi/src/*.sv
# boolean.xdc for *.xdc
vivctrl.tcl: |hdmi boolean.xdc
hdmi:
git clone https://github.com/hdl-util/hdmi
@echo
@echo hdmi project cloned. Exiting with error. Rerun make!
@exit 1
@# Otherwise $(wildcard ...) in the makefile does not work
out/post_syn.dcp: image.memh
image.memh: image.jpg
python image2memh.py
hdmi_pll/hdmi_pll.v hdmi_pll/hdmi_pll_clk_wiz.v &: hdmi_pll-create.tcl
vivado -tempDir /tmp -nojournal -nolog -mode batch -source hdmi_pll-create.tcl
image.jpg:
curl 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Siebenpunkt-Marienk%C3%A4fer_%28Coccinella_septempunctata%29_auf_Bl%C3%BCte_im_FFH-Gebiet_%22Viernheimer_Waldheide_und_angrenzende_Fl%C3%A4chen%22.jpg/1280px-Siebenpunkt-Marienk%C3%A4fer_%28Coccinella_septempunctata%29_auf_Bl%C3%BCte_im_FFH-Gebiet_%22Viernheimer_Waldheide_und_angrenzende_Fl%C3%A4chen%22.jpg' -o $@
clean::
$(RM) -r hdmi hdmi_pll
$(RM) image.{jpg,memh}
create_project -in_memory -part xc7s50csga324-1
create_ip -name clk_wiz -dir . -module_name hdmi_pll
set_property -dict [list \
CONFIG.PRIMITIVE {MMCM} \
CONFIG.PRIMARY_PORT {clk} \
CONFIG.CLKOUT1_USED {true} \
CONFIG.CLKOUT2_USED {true} \
CONFIG.CLK_OUT1_PORT {clk_pixel} \
CONFIG.CLK_OUT2_PORT {clk_pixel_x5} \
CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {74.25} \
CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {371.25} \
] [get_ips hdmi_pll]
generate_target synthesis [get_ips hdmi_pll]