Lab: 2

Lab 2 - Signal Display to HDMI

In this lab, you will write a HDMI Video controller in VHDL and implement it on your FPGA development board. You will be provided a VGA-to-HDMI module that will automatically format your output for the HDMI output port on your development board. This HDMI video controller will be tasked to generate the display portion of an oscilloscope as shown in the figure below. The scope face consists of a white grid, used to measure the signals, two trigger markers, and the waveforms. In this lab the waveforms will be artificially generated by your code, but in later labs, the waveforms will be generated by incoming audio waveforms.
Figure 3

Architecture

The design of the lab is broken down into separate modules, some of which are provided for you and some which you will need to create. The interconnection of the modules is illustrated in the following schematic. When a signal name appears just inside a box, that should should correspond to the name of that signal in the entity description. Please note there are a few omissions in the diagram that you should correct as part of your documentation (see Turn-In section).


VHDL Code

In order to get you going in this lab, some of the VHDL code has been provided for you. In most cases, you should refrain from changing the modules given. In order to get a better understanding how these modules interact with one another, the following section provides a schematic and the input, output and behavior of some of the modules. There are two modules which will constitute the majority of your work, videoSignalGenerator and scopeFace. The following two subsections details the behavior of these two modules.

The videoSignalGenerator module

The videoSignalGenerator component generates the signals to sweep the display beam across the display from left to right, and from top to bottom. The scopeFace component will take the pixelHorz and pixelVert values and determine what color pixel to place at that location.
entity videoSignalGenerator is
    PORT(
	 clk: in  STD_LOGIC;
         resetn : in  STD_LOGIC;
         hs: out STD_LOGIC;
         vs: out STD_LOGIC;
         de: out STD_LOGIC;
         pixelHorz: out STD_LOGIC_VECTOR(VIDEO_WIDTH_IN_BITS-1 downto 0);
         pixelVert: out STD_LOGIC_VECTOR(VIDEO_WIDTH_IN_BITS-1 downto 0));
end videoSignalGenerator;
clk This is the 74.25Mhz videoClk generated by the video_clk component.
resetn This is the same active low reset signal passed into the top level Lab1 module.
hs The h_synch signal for the current row,column position.
vs The v_synch signal for the current row,column position.
de The blank signal for the current row,column position. Its the logical and of the h_blank and v_blank signals.
pixelHorzThe current row on the display that needs a RGB value from this component.
pixelVertThe current column on the display that needs a RGB value from this component.
The behavior of the videoSignalGenerator component contains counters which generate:

The scopeFace module

This component takes in the horizontal and vertical pixel location from the videoSignalGenerator component and determines the R,G,B value of the pixel that should be drawn at that location.
entity scopeFace is
    PORT (
  	 clk: in  STD_LOGIC;
         resetn : in  STD_LOGIC;
         pixelHorz : in  STD_LOGIC_VECTOR(VIDEO_WIDTH_IN_BITS-1 downto 0);
         pixelVert : in  STD_LOGIC_VECTOR(VIDEO_WIDTH_IN_BITS-1 downto 0);
         triggerVolt: in STD_LOGIC_VECTOR (VIDEO_WIDTH_IN_BITS-1 downto 0);
         triggerTime: in STD_LOGIC_VECTOR (VIDEO_WIDTH_IN_BITS-1 downto 0);
         red : out  STD_LOGIC_VECTOR(7 downto 0);
         green : out  STD_LOGIC_VECTOR(7 downto 0);
         blue : out  STD_LOGIC_VECTOR(7 downto 0);
         ch1: in STD_LOGIC;
         ch1Enb: in STD_LOGIC;
         ch2: in STD_LOGIC;
         ch2Enb: in STD_LOGIC);
end scopeFace;
clk This is the 25Mhz pixel clock generated by the DCM in the video module.
resetn This is the same active low reset signal passed into the top level component.
pixelVert The current row on the display that needs a RGB value from this component.
pixelHorz The current column on the display that needs a RGB value from this component.
triggerVolt This is a 12-bit value representing the trigger voltage. This value is passed to the scopeFace module so that a yellow arrow (see Trigger Level Marker in the screen show) on the vertical axis.
triggerTime This is a 12-bit value representing the trigger time. This value is passed to the scopeFace module so that a yellow arrow (see Trigger Time Marker in the screen show) on the horizontal axis.
red The 8-bit red intensity for this row,column pixel on the screen.
green The 8-bit green intensity for this row,column pixel on the screen.
blue The 8-bit blue intensity for this row,column pixel on the screen.
ch1 This 1-bit signal causes a yellow channel 1 trace to be drawn on the display at the current pixel location. When this signal is 0, no channel 1 pixel is drawn.
ch1enb This 1-bit signal enable the ch1 signal to be drawn.
ch2 This 1-bit signal causes a green channel 2 trace to be drawn on the display at the current pixel location. When this signal is 0, no channel 2 pixel is drawn.
ch2enb This 1-bit signal enable the ch2 signal to be drawn.
The scopeFace component takes in the current row,column coordinates of the display and generates the R,G,B values at that screen coordinate. For example, if row,column = 20,20 then the R,G,B output should be 0xFF,0xFF,0xFF (white) because the upper left corner of the O'scope grid display is white.

The video_clk module

You will need to generate an IP core for this module usin the instructions in the "howTo 05 Instantiate Clock and HDMI IP" document posted on the main web page.

The hdmi_tx_0 module

You will need to generate an IP core for this module using the instructions in the "howTo 05 Instantiate Clock and HDMI IP" document posted on the main web page.

The scopeToHdmi package

You will need to complete the scopeToHdmi package linked above. Include this package in this lab's files and in later labs that use these components.

Required Functionality

  1. You will be asked to show the following simulation results,
    • Show a image of your simulation from 0 to 1.2us. This should show the first line of video with proper hs, h_activeArea, h_cnt and pixelHorz.
    • Show a image of your simulation from 0 to 550us. This should show the first 34 line of video with proper vs, v_activeArea, v_cnt and pixelVert.
    • Show a image of your simulation from 0 to 2ms. This should show the first non-zero RGB values being sent to the display.
  2. Your code must generate the thick white outline that defines the border of the oscilloscope. Draw grid in grey (R,G,B) = (0x40, 0x40, 0x40) so that you have 10 horizontal and 10 vertical divisions. Draw 4 hatch marks in grey so they evenly split each vertical and horizontal division. Draw the markers as triangles in cyan (R,G,B) = (0x00, 0xFF, 0xFF).
  3. The ALINX board has four buttons that you are able to associate with your design. One of these buttons (PL Key 1) is dedicated to the resetn function. Use the remaining three keys to manipulate the Trigger Volt Mark and the Trigger Time Mark as follows:
    • Pressing PL_KEY3 decreases the Trigger Volt Mark
    • Pressing PL_KEY3 while holding PL_KEY2 increases the Trigger Volt Mark
    • Pressing PL_KEY4 increases the Trigger Time Mark
    • Pressing PL_KEY4 while holding PL_KEY2 decreases the Trigger Time Mark
  4. Test the channel functions by:
    • Drawing the channel 1 trace (yellow) along a diagonal where (row = column).
    • Drawing the channel 2 trace (green) along a horizontal at the same level as the voltage trigger.

Simulation

You will need to run simulations to make sure that all your videoSignalGenerator is producing the correct waveforms. I've included a testbench file and TCL setup script to help you setup the testbench. The images below are from my simulation output. You signals may differ slightly in their timing and your videoSignalGenerator will function just fine. The RGB signal output really depends on your scopeFace and may differ quite a bit from what my setup generated.
Signal Color Radix
clk Green binary
resetn Green binary
h_cnt Yellow unsigned
pixelHorz Yellow unsigned
h_activeArea Yellow binary
hs Yellow binary
v_cnt Yellow unsigned
pixelVert Yellow unsigned
v_activeArea Yellow binary
vs Yellow binary
de Green binary
red Red Hexadecimal
green Green Hexadecimal
blue Blue Hexadecimal
To help you in debugging, I've provided some excerpts from my testbench simulation. If you right-click on the images and open in a new window, they will enlarge.
At 10us This shows the clock starting up and the first few hcounts.
At 11.5us This shows the horizontal synch dropping low at h_cnt = 110 and rising high at ih_cnt = 150.
At 32.5us This shows h_cnt starting over after counting up to 1649.
Up to 700us This shows the first few rows of video with a proper vsynch and v_active area.
At 3ms This shows the top border of scopeFace being displayed.
Show a image of your simulation from 0 to 2ms. This should show the first non-zero RGB values being sent to the display.

Connecting

Your ALINX board will need to connect to the HDMI port, the JTAG programming port and the power supply. The image below shows how I made these connections. The reset and trigger control buttons assigned in the XDC file are also shown.