ZYBO Zync-7000 Development Board Work

HDMI/DVI-D Implemented on Programming Logic

Introduction

In this section, I will cover how you would go about implementing an HDMI controller on Digilent's ZYNQ development board (the ZYBO). There is a seperate and completely different tutorial for the ZedBoard. The ZYBO does not have the HDMI Transmitter IC (ADV7511) that the ZedBoard has. Therefore, the differential signals need to be generated by some other means.

Things you will need

Step 1: Understanding DVI-D and seeing how it relates to HDMI

Firstly, DVI stands for Digital Visual Interface and was the very next development of display cable technology from the previous VGA (Video Graphcs Array) format. VGA was introduced in 1987 and quickly became a universal video interface. Back then, computer monitors and televisions weren't as thin or as mountable as they are today. Then, liquid-crystal display technology was not advanced enough to become uniersally adopted. Instead, many monitors utilized cathode ray tube technology. This technology was not digitally driven, but instead utilized analog signals to sweep an electron gun across the horizontal and vertical portions of the screen.

VGA (and many different iterations of VGA) is still used today by many different monitors, projectors, and televisions because of how easy it is to interface with. However, with a little more complexity, we are able to access high resolution display formats and many more color options. Below is an image of a DVI-D single-link display interface. In addition to DVI-D, there is DVI-I and DVI-A. DVI-A interfaces are capable of supporting high-quality analog signals. DVI-D interfaces carry digital signals and DVI-I is capable of supporting both analog and digital signals. I will continue to go into detail about the many different display formats, interfaces, and methods of implementing them throughout this tutorial.

A male DVI-D (single link) connector

Information About Different DVI Versions

If you're still somewhat confused about these different interfaces, don't be. After a little practice and some research on Wikipedia, you'll be up and running in no time! I will not begin to discuss to compare and contrast DVI and HDMI. First, let's take a look at the below figure in order to identify a couple of important pins.



DVI Pin Layout

The important pins to identify from the above diagram are TMDS Data (+/- 1, 2, 3) in Link 1 and the TMDS clock (+/-). These are the primary pins that are associated with transmitting signals via DVI-D. In the HDMI figure below, it is clear that the HDMI interface also shares these same differential signal pins. TMDS stands for Transition Minimized Differential Signalling and more can be read about it here.



HDMI Pin Layout

From the above figures on DVI-D and HDMI, it is apparent that there is some overlap. HDMI was originally created to be backwards compatible with DVI-D. Besides additional HDMI control signals, we are only lacking the audio transfer capabilities.

Step 2: Implementing DVI-D on the ZYBO

The best way to demonstrate DVI-D implementation on the ZYBO is to walk you through the necessary code. The files for this project can be found below.

TOP PROJECT FILE (zybo_dvi.vhd)
The first file represents the top level for a simple HDMI reference project that has the resolution of 640 x 480.

----------------------------------------------------------------------------------
-- Company:     DBRSS
-- Engineer:    Daniel Barcklow
-- Module:      TOP level DVI-D
----------------------------------------------------------------------------------
library ieee;
library unisim;
use ieee.std_logic_1164.all;
use unisim.vcomponents.all;

entity zybo_dvi is
    Port ( clk_125      :       in  std_logic;
           tmds         :       out  std_logic_vector(3 downto 0);
           tmdsb        :       out  std_logic_vector(3 downto 0);
           hdmi_cec     :       in   std_logic;
           hdmi_hpd     :       in  std_logic;
           hdmi_out_en  :       out std_logic
           );
end zybo_dvi;

architecture x of zybo_dvi is

   signal clk_dvi  : std_logic := '0';
   signal clk_dvin : std_logic := '0';
   signal clk_vga  : std_logic := '0';

   signal red     : std_logic_vector(7 downto 0) := (others => '0');
   signal green   : std_logic_vector(7 downto 0) := (others => '0');
   signal blue    : std_logic_vector(7 downto 0) := (others => '0');
   signal hsync   : std_logic := '0';
   signal vsync   : std_logic := '0';
   signal video_on   : std_logic := '0';
   signal red_s   : std_logic;
   signal green_s : std_logic;
   signal blue_s  : std_logic;
   signal clock_s : std_logic;
   signal clk_25 : std_logic;
begin

    -- Enable HDMI enable out signal, as stated in reference
    hdmi_out_en <= '1';

   -- Generate clk for VGA
   GEN25MHZ : entity work.modN(x)
        generic map(N=>5)
        port map(d=>clk_125,reset=>'0',q=>clk_25);
                             
    -- DVI-D module                         
    DVID : entity work.dvid(x) 
        port map(
          clk       => clk_dvi,
          clk_n     => clk_dvin, 
          clk_pixel => clk_vga,
          red_p     => red,
          green_p   => green,
          blue_p    => blue,
          video_on  => video_on,
          hsync     => hsync,
          vsync     => vsync,
          
          -- outputs to TMDS drivers
          red_s     => red_s,
          green_s   => green_s,
          blue_s    => blue_s,
          clock_s   => clock_s
        );
   
    OBUFDS_blue  : OBUFDS PORT MAP ( O  => TMDS(0), OB => TMDSB(0), I  => blue_s  );
    OBUFDS_red   : OBUFDS PORT MAP ( O  => TMDS(1), OB => TMDSB(1), I  => green_s );
    OBUFDS_green : OBUFDS PORT MAP ( O  => TMDS(2), OB => TMDSB(2), I  => red_s   );
    OBUFDS_clock : OBUFDS PORT MAP ( O  => TMDS(3), OB => TMDSB(3), I  => clock_s );
    -- generic map ( IOSTANDARD => "DEFAULT")    
    
    -- VGA module     
    VGA : entity work.vga(x) 
        port map(
            clk_25          => clk_vga,
            reset           => '0',
            hsync           => hsync,
            vsync           => vsync,
            video_on        => video_on,
            red             => red,
            green           => green,
            blue            => blue
        );
      
    clk_dvi  <= clk_125;        -- DVI clk (pos)
    clk_dvin <= not clk_125;    -- DVI clk (neg)
    clk_vga  <= clk_25;         -- VGA clk
      
end x;


DVI-D (dvid.vhd)
This is the most important module. This is where most of the complicated portions of the hardware exists. Within dvid.vhd, the top level inputs RGB into this module so that they may be eventually converted into differential signals TMDS(0,1,2,3). There are two clocks inputted. Generally, "clk_pixel" should be equal to "clk"/5. "clk" is the faster of the two clocks and, in this design, it is equal to 125 MHz. Additionally, VGA clock is equal to 800[pixels]*525[pixels]*60[Refreshes/Second] = ~25M => 25MHz.

library ieee;
library unisim;
use ieee.std_logic_1164.all;
use unisim.vcomponents.all;

entity dvid is
    Port ( clk          : in  std_logic;
           clk_n        : in  std_logic;
           clk_pixel    : in  std_logic;
           red_p        : in  std_logic_vector(7 downto 0);
           green_p      : in  std_logic_vector(7 downto 0);
           blue_p       : in  std_logic_vector(7 downto 0);
           video_on     : in  std_logic;
           hsync        : in  std_logic;
           vsync        : in  std_logic;
           red_serial   : out std_logic;
           green_serial : out std_logic;
           blue_serial  : out std_logic;
           clock_serial : out std_logic);
end dvid;

architecture x of dvid is

   signal encoded_red, encoded_green, encoded_blue : std_logic_vector(9 downto 0);
   signal shift_red,   shift_green,   shift_blue   : std_logic_vector(9 downto 0) := (others => '0');
   signal shift_clock   : std_logic_vector(9 downto 0) := "0000011111";
      
   constant c_red       : std_logic_vector(1 downto 0) := (others => '0');  -- "00"
   constant c_green     : std_logic_vector(1 downto 0) := (others => '0');  -- "00"
   signal   c_blue      : std_logic_vector(1 downto 0);                     -- variable based on vsync and hsync

begin   
   c_blue <= vsync & hsync;
   
   -- implement TDMS Algorithms for all d_in channels (red, green, blue)
   TMDS_encoder_RED     :  entity work.TMDS_encoder(x) PORT MAP(clk => clk_pixel, d_in => red_p,   c => c_red,   video_on => video_on, encoded => encoded_red);
   TMDS_encoder_GREEN   :  entity work.TMDS_encoder(x) PORT MAP(clk => clk_pixel, d_in => green_p, c => c_green, video_on => video_on, encoded => encoded_green);
   TMDS_encoder_BLUE    :  entity work.TMDS_encoder(x) PORT MAP(clk => clk_pixel, d_in => blue_p,  c => c_blue,  video_on => video_on, encoded => encoded_blue);

   -- Output at DOUBLE RATE (updated by clock at 125MHz, typically)
   ODDR2_RED    : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC") 
      port map (D0 => shift_red(0), D1 => shift_red(1), C0 => clk, C1 => clk_n, CE => '1', R => '0', S => '0', Q => red_serial);
   ODDR2_GREEN  : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC") 
      port map (D0 => shift_green(0), D1 => shift_green(1), C0 => clk, C1 => clk_n, CE => '1', R => '0', S => '0', Q => green_serial);
   ODDR2_BLUE   : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC") 
      port map (D0 => shift_blue(0),  D1 => shift_blue(1),  C0 => clk, C1 => clk_n, CE => '1', R => '0', S => '0', Q => blue_serial);
   ODDR2_CLK    : ODDR2 generic map( DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC") 
      port map (D0 => shift_clock(0), D1 => shift_clock(1), C0 => clk, C1 => clk_n, CE => '1', R => '0', S => '0', Q => clock_serial);

   feed_data: process(clk)
   begin
      if rising_edge(clk) then 
         if shift_clock = "0000011111" then     -- occurs at rate of 25MHz
            shift_red   <= encoded_red;
            shift_green <= encoded_green;
            shift_blue  <= encoded_blue;
         else
            -- shift last two bits outs
            shift_red   <= "00" & shift_red  (9 downto 2);
            shift_green <= "00" & shift_green(9 downto 2);
            shift_blue  <= "00" & shift_blue (9 downto 2); 
         end if;
         shift_clock <= shift_clock(1 downto 0) & shift_clock(9 downto 2);  -- clk (div by 5) ROTATE RIGHT
      end if;
   end process feed_data;
end x;


MODN - CLK Divider (modN.vhd)
This module is used to divide the primary clock in order to generate a VGA sync. clock.

----------------------------------------------------------------------------------
-- Company:     DBRSS
-- Engineer:    Daniel Barcklow
-- Module:      MOD-N module
----------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity modN is
    generic(N : integer := 5);
    port(   d           : in std_logic;               
            reset       : in std_logic;
            q           : out std_logic);
end modN;

architecture x of modN is
    signal reg_out : unsigned(9 downto 0);
    signal q_sig   : std_logic; 
begin

    modN : process(d,reset)
    begin
        if(reset = '1' or q_sig = '1') then
            reg_out <= (others => '0');
        elsif(rising_edge(d)) then
            reg_out <= reg_out + 1;
        end if;
    end process modN;

    q_sig   <= '1' when reg_out = to_unsigned(N,10) else '0';
    q       <= q_sig;
    
end x;


TMDS ENCODER (TMDS_encoder.vhd)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity TMDS_encoder is
    Port ( clk      : in  std_logic;
           d_in     : in  std_logic_vector(7 downto 0);     -- 8 bit d_in to be encoded
           C        : in  std_logic_vector(1 downto 0);     -- control bits (2)
           video_on : in  std_logic;                        -- BLANKING, is video on?
           encoded  : out  std_logic_vector(9 downto 0));   -- output encoded
end TMDS_encoder;

architecture x of TMDS_encoder is
   signal xored  : std_logic_vector(8 downto 0);
   signal xnored : std_logic_vector(8 downto 0);
   
   signal ones                : std_logic_vector(3 downto 0);
   signal q_m           : std_logic_vector(8 downto 0);
   signal q_m_inv       : std_logic_vector(8 downto 0);
   signal data_word_disparity : std_logic_vector(3 downto 0);
   signal dc_bias             : std_logic_vector(3 downto 0) := (others => '0');
begin
   -- Perform FALSE<1> computations
   xored(0) <= d_in(0);
   xored(1) <= d_in(1) xor xored(0);
   xored(2) <= d_in(2) xor xored(1);
   xored(3) <= d_in(3) xor xored(2);
   xored(4) <= d_in(4) xor xored(3);
   xored(5) <= d_in(5) xor xored(4);
   xored(6) <= d_in(6) xor xored(5);
   xored(7) <= d_in(7) xor xored(6);
   xored(8) <= '1';

   -- Perform TRUE<1> computations
   xnored(0) <= d_in(0);
   xnored(1) <= d_in(1) xnor xnored(0);
   xnored(2) <= d_in(2) xnor xnored(1);
   xnored(3) <= d_in(3) xnor xnored(2);
   xnored(4) <= d_in(4) xnor xnored(3);
   xnored(5) <= d_in(5) xnor xnored(4);
   xnored(6) <= d_in(6) xnor xnored(5);
   xnored(7) <= d_in(7) xnor xnored(6);
   xnored(8) <= '0';
   
   -- count all 1's by adding them (0 won't contribute)
   ones <= "0000" + d_in(0) + d_in(1) + d_in(2) + d_in(3)
                  + d_in(4) + d_in(5) + d_in(6) + d_in(7);
 
   -- decide on encoding
   decision0: process(ones, d_in(0), xnored, xored)
   begin
      -- FIRST CHOICE DIAMOND (https://www.eewiki.net/pages/viewpage.action?pageId=36569119) <1>
      if ones > 4 or (ones = 4 and d_in(0) = '0') then
         q_m     <= xnored;
         q_m_inv <= NOT(xnored);
      else
         q_m     <= xored;
         q_m_inv <= NOT(xored);
      end if;
   end process decision0;                                          

   -- Work out the DC bias of the dataword;
   data_word_disparity  <= "1100" + q_m(0) + q_m(1) + q_m(2) + q_m(3) 
                                    + q_m(4) + q_m(5) + q_m(6) + q_m(7);
   
   -- Now work out what the output should be
   process(clk)
   begin
      -- "DISPLAY ENABLE = 1"
      if rising_edge(clk) then
         if video_on = '0' then 
            -- In the control periods, all values have and have balanced bit count
            case C is            
               when "00"   => encoded <= "1101010100";
               when "01"   => encoded <= "0010101011";
               when "10"   => encoded <= "0101010100";
               when others => encoded <= "1010101011";
            end case;
            dc_bias <= (others => '0');
         else
            -- Ones#(d) = 4 OR disparity = 0
            if dc_bias = "00000" or data_word_disparity = 0 then
               -- dataword has no disparity
               if q_m(8) = '0' then
                  encoded <= "10" & q_m_inv(7 downto 0);
                  dc_bias <= dc_bias - data_word_disparity;
               else
                  encoded <= "01" & q_m(7 downto 0);
                  dc_bias <= dc_bias + data_word_disparity;
               end if;
            elsif (dc_bias(3) = '0' and data_word_disparity(3) = '0') or 
                  (dc_bias(3) = '1' and data_word_disparity(3) = '1') then
               encoded <= '1' & q_m(8) & q_m_inv(7 downto 0);
               dc_bias <= dc_bias + q_m(8) - data_word_disparity;
            else
               encoded <= '0' & q_m;
               dc_bias <= dc_bias - q_m_inv(8) + data_word_disparity;
            end if;
         end if;
      end if;
   end process;      
end x;


VGA TOP (vga.vhd)

----------------------------------------------------------------------------------
-- Company:     DBRSS
-- Engineer:    Daniel Barcklow
-- Module:      Generate Bits for program
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity vga is
    port(
        clk_25:     in std_logic;
        reset:      in std_logic;
        hsync:      out std_logic;
        vsync:      out std_logic;
        video_off:  out std_logic;
        red:        out std_logic_vector(7 downto 0);
        green:      out std_logic_vector(7 downto 0);
        blue:       out std_logic_vector(7 downto 0)
    );
end vga;

architecture x of vga is
    signal p_tick:   std_logic;
    signal pixel_x:  std_logic_vector(9 downto 0);
    signal pixel_y:  std_logic_vector(9 downto 0);
    signal v_on_sig: std_logic;
begin

    red <= (others => '1') when v_on_sig = '1' else (others => '0');
    green <= (others => '0') when v_on_sig = '1' else (others => '0');
    blue <= (others => '1') when v_on_sig = '1' else (others => '0');
        
    VGA_pg: entity work.vga_sync(arch)
        port map(
            clk_25      => clk_25,
            reset       => reset,
            hsync       => hsync,
            vsync       => vsync,
            video_on    => v_on_sig,
            p_tick      => p_tick,
            pixel_x     => pixel_x,
            pixel_y     => pixel_y
        );
        
    video_off <= not v_on_sig;

end x;


VGA SYNC (vga_sync.vhd)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity vga_sync is
   port(
      clk_25:   in std_logic;
      reset:    in std_logic;
      hsync:    out std_logic :='0';
      vsync:    out std_logic :='0';
      video_on: out std_logic :='0';
      p_tick:   out std_logic :='0';
      pixel_x:  out std_logic_vector(9 downto 0);
      pixel_y:  out std_logic_vector(9 downto 0));
end vga_sync;

architecture arch of vga_sync is
   -- VGA 640-by-480 sync parameters
   constant HD: integer:=640; --horizontal display area
   constant HF: integer:=16 ; --h. front porch
   constant HB: integer:=48 ; --h. back porch
   constant HR: integer:=96 ; --h. retrace
   constant VD: integer:=480; --vertical display area
   constant VF: integer:=10;  --v. front porch
   constant VB: integer:=33;  --v. back porch
   constant VR: integer:=2;   --v. retrace
      
   -- sync counters
   signal v_count_reg, v_count_next: std_logic_vector(9 downto 0);
   signal h_count_reg, h_count_next: std_logic_vector(9 downto 0);
   
   -- output buffer
   signal v_sync_reg, h_sync_reg: std_logic;
   signal v_sync_next, h_sync_next: std_logic;
   
   -- status signal
   signal h_end, v_end, pixel_tick: std_logic;
     
begin
   pixel_tick <= clk_25;

   -- registers
   process (clk_25,reset)
   begin
      if reset='1' then
         v_count_reg <= (others=>'0');
         h_count_reg <= (others=>'0');
         v_sync_reg <= '1';
         h_sync_reg <= '1';
      elsif (rising_edge(clk_25)) then
         v_count_reg <= v_count_next;
         h_count_reg <= h_count_next;
         v_sync_reg <= v_sync_next;
         h_sync_reg <= h_sync_next;
      end if;
   end process;
      
   -- status
   h_end <=  -- end of horizontal counter
      '1' when h_count_reg=(HD+HF+HB+HR-1) else --799
      '0';
      
   v_end <=  -- end of vertical counter
      '1' when v_count_reg=(VD+VF+VB+VR-1) else --524
      '0';
      
   -- mod-800 horizontal sync counter
   process (h_count_reg,h_end)
   begin
         h_count_next <= h_count_reg;
         if h_end='1' then
            h_count_next <= (others=>'0');
         else
            h_count_next <= h_count_reg + 1;
         end if;
   end process;
   
   -- mod-525 vertical sync counter
   process (v_count_reg,h_end,v_end)
   begin
      if h_end='1' then
         if (v_end='1') then
            v_count_next <= (others=>'0');
         else
            v_count_next <= v_count_reg + 1;
         end if;
      else
         v_count_next <= v_count_reg;
      end if;
   end process;
   
   -- horizontal and vertical sync, buffered to avoid glitch
   h_sync_next <=
      '1' when (h_count_reg>=(HD+HF))           --656
           and (h_count_reg<=(HD+HF+HR-1)) else --751
      '0';
   v_sync_next <=
      '1' when (v_count_reg>=(VD+VF))           --490
           and (v_count_reg<=(VD+VF+VR-1)) else --491
      '0';
   
   -- video on/off
   video_on <=
      '1' when (h_count_reg < HD) and (v_count_reg < VD) else
      '0';
   
   -- output signal
   hsync <= h_sync_reg;
   vsync <= v_sync_reg;
   pixel_x <= std_logic_vector(h_count_reg);
   pixel_y <= std_logic_vector(v_count_reg);
   p_tick <= pixel_tick;
end arch;


VGA DRAW (vga_draw.vhd)

----------------------------------------------------------------------------------
-- Company:     DBRSS
-- Engineer:    Daniel Barcklow
-- Module:      VGA drawing module
----------------------------------------------------------------------------------


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity VGA_draw is
    port(
        clk_25   : in std_logic;
        pixel_x  : in std_logic_vector(9 downto 0);
        pixel_y  : in std_logic_vector(9 downto 0);
        video_on : in std_logic;
        rgb      : out std_logic_vector(23 downto 0)
    );
end VGA_draw;
    
architecture x of VGA_draw is
    signal px,py: unsigned(9 downto 0);
    signal border,grid,background,button,side_menu,btn0,btn1,btn2,btn3: std_logic_vector(23 downto 0);
    signal b0_row,b1_row,b2_row,b3_row: std_logic_vector(79 downto 0);
    signal b0_reg,b1_reg,b2_reg,b3_reg: std_logic_vector(79 downto 0);
    
    -- COLORS
    constant BLACK  : std_logic_vector(23 downto 0) := x"000000";
    constant WHITE  : std_logic_vector(23 downto 0) := x"FFFFFF";
    constant GREY   : std_logic_vector(23 downto 0) := x"808080";
    constant DARK_GREY   : std_logic_vector(23 downto 0) := x"202020";
    constant NONE   : std_logic_vector(23 downto 0) := x"010101";
    constant NAVY   : std_logic_vector(23 downto 0) := x"000080";
    constant RED   : std_logic_vector(23 downto 0) := x"F70000";
    
    constant BORDER_SIZE : integer := 40; -- pixels
    
    -- define ROM type
    type rom_type is array (0 to 59) of std_logic_vector(79 downto 0);


    constant B0_ROM: rom_type:=( -- 80-by-15
     "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 1
     "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 2
     "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 3
     "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 4
     "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 5
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 6
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 7
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 8
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 9
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 0 - 10
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 1
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 2
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 3
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 4
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 5
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 6
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 7
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 8
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 9
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 0 - 20
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 1
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 2
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 3
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 4
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 5
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 6
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 7
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 8
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 9
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 0 - 30
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 1
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 2
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 3
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 4
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 5
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 6
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 7
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 8
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 9
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 0 - 40
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 1
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 2
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 3
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 4
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 5
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 6
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 7
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 8
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 9
     "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 0 - 50
     "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 1
     "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 2
     "1100000011111111111111111111111111111111111111111111111111111111111111000000011", -- 3
     "1100000001111111111111111111111111111111111111111111111111111111111110000000011", -- 4
     "1100000000111111111111111111111111111111111111111111111111111111111000000000011", -- 5
     "1100000000001111111111111111111111111111111111111111111111111111110000000000011", -- 6
     "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 7
     "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 8
     "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 9
     "1111111111111111111111111111111111111111111111111111111111111111111111111111111"  -- 0 - 60
     );
    
    constant B1_ROM: rom_type:=( -- 80-by-15
      "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 1
      "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 2
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 3
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 4
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 5
      "1100000111111111111111111111111111111111111111111111111111111110000000000000011", -- 6
      "1100000111111111111111111111111111111111111111111111111111111111100000000000011", -- 7
      "1100000111111111111111111111111111111111111111111111111111111111110000000000011", -- 8
      "1100000111111111111111111111111111111111111111111111111111111111110000000000011", -- 9
      "1100000111111111111111111111111111111111111111111111111111111111111100000000011", -- 0 - 10
      "1100000111111111111111111111111111111111111111111111111111111111111111000000011", -- 1
      "1100000111111111000000000000000000000000000000000000000000000001111111100000011", -- 2
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 3
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 4
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 5
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 6
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 7
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 8
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 9
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 0 - 20
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 1
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 2
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 3
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 4
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 5
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 6
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 7
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 8
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 9
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 0 - 30
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 1
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 2
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 3
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 4
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 5
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 6
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 7
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 8
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 9
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 0 - 40
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 1
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 2
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 3
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 4
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 5
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 6
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 7
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 8
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 9
      "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 0 - 50
      "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 1
      "1100000111111111111111111111111111111111111111111111111111111111111111100000011", -- 2
      "1100000111111111111111111111111111111111111111111111111111111111111111000000011", -- 3
      "1100000111111111111111111111111111111111111111111111111111111111111100000000011", -- 4
      "1100000111111111111111111111111111111111111111111111111111111111110000000000011", -- 5
      "1100000111111111111111111111111111111111111111111111111111111110000000000000011", -- 6
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 7
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 8
      "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 9
      "1111111111111111111111111111111111111111111111111111111111111111111111111111111"  -- 0 - 60
      );    
    
    constant B2_ROM: rom_type:=( -- 80-by-15
       "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 1
       "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 2
       "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 3
       "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 4
       "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 5
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 6
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 7
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 8
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 9
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 0 - 10
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 1
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 2
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 3
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 4
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 5
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 6
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 7
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 8
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 9
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 0 - 20
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 1
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 2
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 3
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 4
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 5
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 6
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 7
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 8
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 9
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 0 - 30
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 1
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 2
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 3
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 4
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 5
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 6
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 7
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 8
       "1100000111111111000000000000000000000000000000000000000000000000000000000000011", -- 9
       "1100000111111111000000000000000000000000000000000000000000000000000000010000011", -- 0 - 40
       "1100000111111111000000000000000000000000000000000000000000000000000001110000011", -- 1
       "1100000111111111000000000000000000000000000000000000000000000000000111110000011", -- 2
       "1100000111111111000000000000000000000000000000000000000000000000011111110000011", -- 3
       "1100000111111111000000000000000000000000000000000000000000000001111111110000011", -- 4
       "1100000111111111000000000000000000000000000000000000000000000011111111110000011", -- 5
       "1100000111111111000000000000000000000000000000000000000000000111111111110000011", -- 6
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 7
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 8
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 9
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 0 - 50
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 1
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 2
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 3
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 4
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 5
       "1100000111111111111111111111111111111111111111111111111111111111111111110000011", -- 6
       "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 7
       "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 8
       "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 9
       "1111111111111111111111111111111111111111111111111111111111111111111111111111111"  -- 0 - 60
       );
    
       constant B3_ROM: rom_type:=( -- 80-by-15
      "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 1
      "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 2
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 3
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 4
      "1100000000000011111111111111111111111111111111111111111100000000000000000000011", -- 5
      "1100000000000011111111111111111111111111111111111111111110000000000000000000011", -- 6
      "1100000000000011111111111111111111111111111111111111111111000000000000000000011", -- 7
      "1100000000000011111111111111111111111111111111111111111111110000000000000000011", -- 8
      "1100000000000011111111111000000000000000000000000011111111111110000000000000011", -- 9
      "1100000000000011111111111000000000000000000000000001111111111110000000000000011", -- 10
      "1100000000000011111111111000000000000000000000000000111111111111000000000000011", -- 11
      "1100000000000011111111111000000000000000000000000000111111111111000000000000011", -- 12
      "1100000000000011111111111000000000000000000000000000111111111111000000000000011", -- 13
      "1100000000000011111111111000000000000000000000000000111111111111000000000000011", -- 14
      "1100000000000011111111111000000000000000000000000001111111111111000000000000011", -- 15
      "1100000000000011111111111000000000000000000000000011111111111111000000000000011", -- 16
      "1100000000000011111111111000000000000000000000001111111111111111000000000000011", -- 17
      "1100000000000011111111111000000000000000000000011111111111111110000000000000011", -- 18
      "1100000000000011111111111000000000000000000000111111111111111100000000000000011", -- 19
      "1100000000000011111111111000000000000000000011111111111111110000000000000000011", -- 20
      "1100000000000011111111111000000000000000000111111111111111100000000000000000011", -- 21
      "1100000000000011111111111000000000000000001111111111111110000000000000000000011", -- 22
      "1100000000000011111111111100000000000000111111111111110000000000000000000000011", -- 23
      "1100000000000011111111111111111111111111111111111110000000000000000000000000011", -- 24
      "1100000000000011111111111111111111111111111111110000000000000000000000000000011", -- 25
      "1100000000000011111111111111111111111111111111110000000000000000000000000000011", -- 26
      "1100000000000011111111111111111111111111111111110000000000000000000000000000011", -- 27
      "1100000000000011111111111111111111111111111111111000000000000000000000000000011", -- 28
      "1100000000000011111111111111111111111111111111111100000000000000000000000000011", -- 29
      "1100000000000011111111111111111111111111111111111110000000000000000000000000011", -- 30
      "1100000000000011111111111100000000000000011111111111100000000000000000000000011", -- 31
      "1100000000000011111111111100000000000000000111111111111000000000000000000000011", -- 32
      "1100000000000011111111111100000000000000000001111111111110000000000000000000011", -- 33
      "1100000000000011111111111100000000000000000000011111111110000000000000000000011", -- 34
      "1100000000000011111111111100000000000000000000000111111111000000000000000000011", -- 35
      "1100000000000011111111111100000000000000000000000011111111100000000000000000011", -- 36
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 37
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 38
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 39
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 40
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 41
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 42
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 43
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 4
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 5
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 6
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 7
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 8
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 9
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 0 - 50
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 1
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 2
      "1100000000000011111111111100000000000000000000000011111111110000000000000000011", -- 3
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 4
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 5
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 6
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 7
      "1100000000000000000000000000000000000000000000000000000000000000000000000000011", -- 8
      "1111111111111111111111111111111111111111111111111111111111111111111111111111111", -- 9
      "1111111111111111111111111111111111111111111111111111111111111111111111111111111"  -- 0 - 60
      );
    
begin

    px <= unsigned(pixel_x);
    py <= unsigned(pixel_y);

    b0_row <= B0_ROM(to_integer(py)-40) when py >= 40 and py <= 100 else (others => '0');
    b1_row <= B1_ROM(to_integer(py)-120) when py >= 120 and py <= 180 else (others => '0');
    b2_row <= B2_ROM(to_integer(py)-200) when py >= 200 and py <= 260 else (others => '0');
    b3_row <= B3_ROM(to_integer(py)-280) when py >= 280 and py <= 340 else (others => '0');
    
    -- read all ROM images
    read_rom : process(clk_25)
    begin
        if rising_edge(clk_25) then
            b0_reg <= b0_row;
            b1_reg <= b1_row;
            b2_reg <= b2_row;
            b3_reg <= b3_row;
        end if;
    end process read_rom;

    background <= BLACK;

    btn0 <= BLACK when px > 635-80 and px < 635 and py > 40 and py < 100 and b0_reg(79 - (to_integer(px) - (635-80))) = '1' else
            GREY when px > 635-80 and px < 635 and py > 40 and py < 100 and b0_reg(79 - (to_integer(px) - (635-80))) = '0' else
            NONE;

    btn1 <= BLACK when px > 635-80 and px < 635 and py > 120 and py < 180 and b1_reg(79 - (to_integer(px) - (635-80))) = '1' else
            GREY when px > 635-80 and px < 635 and py > 120 and py < 180 and b1_reg(79 - (to_integer(px) - (635-80))) = '0' else
            NONE;
    
    btn2 <= BLACK when px > 635-80 and px < 635 and py > 200 and py < 260 and b2_reg(79 - (to_integer(px) - (635-80))) = '1' else
            GREY when px > 635-80 and px < 635 and py > 200 and py < 260 and b2_reg(79 - (to_integer(px) - (635-80))) = '0' else
            NONE;
            
    btn3 <= BLACK when px > 635-80 and px < 635 and py > 280 and py < 340 and b3_reg(79 - (to_integer(px) - (635-80))) = '1' else
            GREY when px > 635-80 and px < 635 and py > 280 and py < 340 and b3_reg(79 - (to_integer(px) - (635-80))) = '0' else
            NONE;
    
    side_menu <= DARK_GREY when px >= 639-90 else
                 NONE;
    
    border <=   DARK_GREY when px <= BORDER_SIZE and px >= 0 else
                DARK_GREY when px <= 639 and px >= 639-BORDER_SIZE else
                DARK_GREY when py <= BORDER_SIZE and py >= 0 else
                DARK_GREY when py <= 479 and py >= 479-BORDER_SIZE else
                NONE;
                
    grid <=     NAVY when to_integer(px) mod 40 = 1 else
                NAVY when to_integer(py) mod 40 = 1 else
                NONE;
                   
    rgb  <=     btn3 when btn3 /= NONE and video_on = '1' else
                btn2 when btn2 /= NONE and video_on = '1' else
                btn1 when btn1 /= NONE and video_on = '1' else
                btn0 when btn0 /= NONE and video_on = '1' else
                side_menu when side_menu /= NONE and video_on = '1' else
                border when border /= NONE and video_on = '1' else
                grid when grid /= NONE and video_on = '1' else
                background when video_on = '1' else
                NONE;                           

end x;


CONSTRAINT FILE (ZYBO_BREAKOUT.xdc)

##
##  ZYBO
##  DANIEL BARCKLOW's BREAKOUT BOARD
##

##Clock signal
##IO_L11P_T1_SRCC_35	
set_property PACKAGE_PIN L16 [get_ports clk_125]
set_property IOSTANDARD LVCMOS33 [get_ports clk_125]
create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 4} [get_ports clk_125]

##HDMI Signals
##IO_L13N_T2_MRCC_35 HDMI_clk_n
set_property PACKAGE_PIN H17 [get_ports tmdsb[3]]
set_property IOSTANDARD TMDS_33 [get_ports tmdsb[3]]

##IO_L13P_T2_MRCC_35 HDMI_clk_p
set_property PACKAGE_PIN H16 [get_ports tmds[3]]
set_property IOSTANDARD TMDS_33 [get_ports tmds[3]]

##IO_L4N_T0_35 HDMI_d_n0
set_property PACKAGE_PIN D20 [get_ports {tmdsb[0]}]
set_property IOSTANDARD TMDS_33 [get_ports {tmdsb[0]}]

##IO_L4P_T0_35 HDMI_d_0
set_property PACKAGE_PIN D19 [get_ports {tmds[0]}]
set_property IOSTANDARD TMDS_33 [get_ports {tmds[0]}]

##IO_L1N_T0_AD0N_35 HDMI_d_n1
set_property PACKAGE_PIN B20 [get_ports {tmdsb[1]}]
set_property IOSTANDARD TMDS_33 [get_ports {tmdsb[1]}]

##IO_L1P_T0_AD0P_35 HDMI_d_1
set_property PACKAGE_PIN C20 [get_ports {tmds[1]}]
set_property IOSTANDARD TMDS_33 [get_ports {tmds[1]}]

##IO_L2N_T0_AD8N_35 HDMI_d_n2
set_property PACKAGE_PIN A20 [get_ports {tmdsb[2]}]
set_property IOSTANDARD TMDS_33 [get_ports {tmdsb[2]}]

##IO_L2P_T0_AD8P_35 HDMI_d_2
set_property PACKAGE_PIN B19 [get_ports {tmds[2]}]
set_property IOSTANDARD TMDS_33 [get_ports {tmds[2]}]

##IO_L5N_T0_AD9N_35
set_property PACKAGE_PIN E19 [get_ports hdmi_cec]
set_property IOSTANDARD LVCMOS33 [get_ports hdmi_cec]

##IO_L5P_T0_AD9P_35
set_property PACKAGE_PIN E18 [get_ports hdmi_hpd]
set_property IOSTANDARD LVCMOS33 [get_ports hdmi_hpd]

##IO_L6N_T0_VREF_35
set_property PACKAGE_PIN F17 [get_ports hdmi_out_en]
set_property IOSTANDARD LVCMOS33 [get_ports hdmi_out_en]


The Final Display!