Initial version

This commit is contained in:
Mike Field 2015-08-04 22:27:00 +12:00
commit 89ee75121b
31 changed files with 6824 additions and 0 deletions

View file

@ -0,0 +1,148 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Top level design for my minimal HDMI output project
--
------------------------------------------------------------------------------------
-- The MIT License (MIT)
--
-- Copyright (c) 2015 Michael Alan Field
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
------------------------------------------------------------------------------------
----- Want to say thanks? ----------------------------------------------------------
------------------------------------------------------------------------------------
--
-- This design has taken many hours - with the industry metric of 30 lines
-- per day, it is equivalent to about 6 months of work. I'm more than happy
-- to share it if you can make use of it. It is released under the MIT license,
-- so you are not under any onus to say thanks, but....
--
-- If you what to say thanks for this design how about trying PayPal?
-- Educational use - Enough for a beer
-- Hobbyist use - Enough for a pizza
-- Research use - Enough to take the family out to dinner
-- Commercial use - A weeks pay for an engineer (I wish!)
--
----------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity hdmi_output_test is
Port ( clk50 : in STD_LOGIC;
hdmi_out_p : out STD_LOGIC_VECTOR(3 downto 0);
hdmi_out_n : out STD_LOGIC_VECTOR(3 downto 0);
leds : out std_logic_vector(7 downto 0));
end hdmi_output_test;
architecture Behavioral of hdmi_output_test is
COMPONENT vga_gen
PORT(
clk50 : IN std_logic;
pixel_clock : OUT std_logic;
red_p : OUT std_logic_vector(7 downto 0);
green_p : OUT std_logic_vector(7 downto 0);
blue_p : OUT std_logic_vector(7 downto 0);
blank : OUT std_logic;
hsync : OUT std_logic;
vsync : OUT std_logic
);
END COMPONENT;
COMPONENT Minimal_hdmi_symbols
PORT(
clk : IN std_logic;
blank : IN std_logic;
hsync : IN std_logic;
vsync : IN std_logic;
red : IN std_logic;
green : IN std_logic;
blue : IN std_logic;
c0 : OUT std_logic_vector(9 downto 0);
c1 : OUT std_logic_vector(9 downto 0);
c2 : OUT std_logic_vector(9 downto 0)
);
END COMPONENT;
COMPONENT serializers
PORT(
clk : IN std_logic;
c0 : IN std_logic_vector(9 downto 0);
c1 : IN std_logic_vector(9 downto 0);
c2 : IN std_logic_vector(9 downto 0);
hdmi_p : OUT std_logic_vector(3 downto 0);
hdmi_n : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
signal pixel_clock : std_logic;
signal red_p : std_logic_vector(7 downto 0);
signal green_p : std_logic_vector(7 downto 0);
signal blue_p : std_logic_vector(7 downto 0);
signal blank : std_logic;
signal hsync : std_logic;
signal vsync : std_logic;
signal c0, c1, c2 : std_logic_vector(9 downto 0);
begin
leds <= x"AA";
---------------------------------------
-- Generate a 1280x720 VGA test pattern
---------------------------------------
Inst_vga_gen: vga_gen PORT MAP(
clk50 => clk50,
pixel_clock => pixel_clock,
red_p => red_p,
green_p => green_p,
blue_p => blue_p,
blank => blank,
hsync => hsync,
vsync => vsync
);
---------------------------------------------------
-- Convert 9 bits of the VGA signals to the DVI-D/TMDS output
---------------------------------------------------
i_Minimal_hdmi_symbols: Minimal_hdmi_symbols PORT MAP(
clk => pixel_clock,
blank => blank,
hsync => hsync,
vsync => vsync,
red => red_p(7),
green => green_p(7),
blue => blue_p(7),
c0 => c0,
c1 => c1,
c2 => c2
);
i_serializers : serializers PORT MAP (
clk => pixel_clock,
c0 => c0,
c1 => c1,
c2 => c2,
hdmi_p => hdmi_out_p,
hdmi_n => hdmi_out_n);
end Behavioral;

View file

@ -0,0 +1,282 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz<
--
-- Description: A minimal set of TMDS symbols - just enough to send a valid
-- HDMI stream
--
------------------------------------------------------------------------------------
-- The MIT License (MIT)
--
-- Copyright (c) 2015 Michael Alan Field
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
------------------------------------------------------------------------------------
----- Want to say thanks? ----------------------------------------------------------
------------------------------------------------------------------------------------
--
-- This design has taken many hours - with the industry metric of 30 lines
-- per day, it is equivalent to about 6 months of work. I'm more than happy
-- to share it if you can make use of it. It is released under the MIT license,
-- so you are not under any onus to say thanks, but....
--
-- If you what to say thanks for this design how about trying PayPal?
-- Educational use - Enough for a beer
-- Hobbyist use - Enough for a pizza
-- Research use - Enough to take the family out to dinner
-- Commercial use - A weeks pay for an engineer (I wish!)
--
----------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity minimal_hdmi_symbols is
Port ( clk : in STD_LOGIC;
hsync, vsync, blank : in STD_LOGIC;
red, green, blue : in STD_LOGIC;
c0, c1, c2 : out STD_LOGIC_VECTOR (9 downto 0));
end minimal_hdmi_symbols;
architecture Behavioral of minimal_hdmi_symbols is
type a_symbol_queue is array (0 to 10) of STD_LOGIC_VECTOR (4 downto 0);
signal symbol_queue : a_symbol_queue := (others => (others => '0'));
signal symbols : STD_LOGIC_VECTOR (29 downto 0) := (others => '0');
signal last_blank : std_logic := '0';
signal last_vsync : std_logic := '0';
signal last_hsync : std_logic := '0';
signal data_island_armed : std_logic := '0';
signal data_island_index : unsigned(5 downto 0) := (others => '1');
begin
c0 <= symbols(29 downto 20);
c1 <= symbols(19 downto 10);
c2 <= symbols( 9 downto 0);
process(clk)
begin
if rising_edge(clk) then
case symbol_queue(0) is
---------------------------------------------------------------
-- Eight TMDS encoded colours for testing
---------------------------------------------------------------
when "00000" => symbols <= "0111110000" & "0111110000" & "0111110000"; -- RGB 0x101010 - Black
when "00001" => symbols <= "0111110000" & "0111110000" & "1011110000"; -- RGB 0xEF1010 - Red
when "00010" => symbols <= "0111110000" & "1011110000" & "0111110000"; -- RGB 0x10EF10 - Green
when "00011" => symbols <= "0111110000" & "1011110000" & "1011110000"; -- RGB 0xEFEF10 - Cyan
when "00100" => symbols <= "1011110000" & "0111110000" & "0111110000"; -- RGB 0x1010EF - Blue
when "00101" => symbols <= "1011110000" & "0111110000" & "1011110000"; -- RGB 0xEF10EF - Magenta
when "00110" => symbols <= "1011110000" & "1011110000" & "0111110000"; -- RGB 0x10EFEF - Yellow
when "00111" => symbols <= "1011110000" & "1011110000" & "1011110000"; -- RGB 0xEFEFEF - White
---------------------------------------------------------------
-- control symbols from 5.4.2 - part of the DVI-D standard
---------------------------------------------------------------
when "01000" => symbols <= "1101010100" & "1101010100" & "1101010100"; -- CTL periods
when "01001" => symbols <= "0010101011" & "1101010100" & "1101010100"; -- Hsync
when "01010" => symbols <= "0101010100" & "1101010100" & "1101010100"; -- vSync
when "01011" => symbols <= "1010101011" & "1101010100" & "1101010100"; -- vSync+hSync
---------------------------------------------------------------
-- Symbols to signal the start of a HDMI feature
---------------------------------------------------------------
when "01100" => symbols <= "0101010100" & "0010101011" & "0010101011"; -- DataIslandPeamble, with VSYNC - 5.2.1.1
when "01101" => symbols <= "0101100011" & "0100110011" & "0100110011"; -- DataIslandGuardBand, with VSYNC - 5.2.3.3
when "01110" => symbols <= "1101010100" & "0010101011" & "1101010100"; -- VideoPramble 5.2.1.1
when "01111" => symbols <= "1011001100" & "0100110011" & "1011001100"; -- VideoGuardBand 5.2.2.1
---------------------------------------------------------------
-- From TERC4 codes in 5.4.3, and data data layout from 5.2.3.1
--
-- First nibble is used for the nFirstWordOfPacket (MSB) Header Bit, VSYNC, HSYNC (LSB).
-- The packet is sent where VSYNC = '1' and HSYNC = '0', so we are left with 4 options
-- Second nibble is used for the odd bits the four data sub-packets
-- Third nibble is used for the even bits the four data sub-packets
--
-- These can be used to contruct a data island with any header
-- and any data in subpacket 0, but all other subpackets
-- must be 0s.
---------------------------------------------------------------
when "10000" => symbols <= "1011100100" & "1010011100" & "1010011100"; -- 0010 0000 0000, TERC4 coded
when "10001" => symbols <= "1011100100" & "1010011100" & "1001100011"; -- 0010 0000 0001, TERC4 coded
when "10010" => symbols <= "1011100100" & "1001100011" & "1010011100"; -- 0010 0000 0000, TERC4 coded
when "10011" => symbols <= "1011100100" & "1001100011" & "1001100011"; -- 0010 0001 0001, TERC4 coded
when "10100" => symbols <= "0110001110" & "1010011100" & "1010011100"; -- 0110 0000 0000, TERC4 coded
when "10101" => symbols <= "0110001110" & "1010011100" & "1001100011"; -- 0110 0000 0001, TERC4 coded
when "10110" => symbols <= "0110001110" & "1001100011" & "1010011100"; -- 0110 0001 0000, TERC4 coded
when "10111" => symbols <= "0110001110" & "1001100011" & "1001100011"; -- 0110 0001 0001, TERC4 coded
when "11000" => symbols <= "0110011100" & "1010011100" & "1010011100"; -- 1010 0000 0000, TERC4 coded
when "11001" => symbols <= "0110011100" & "1010011100" & "1001100011"; -- 1010 0000 0001, TERC4 coded
when "11010" => symbols <= "0110011100" & "1001100011" & "1010011100"; -- 1010 0001 0000, TERC4 coded
when "11011" => symbols <= "0110011100" & "1001100011" & "1001100011"; -- 1010 0001 0001, TERC4 coded
when "11100" => symbols <= "0101100011" & "1010011100" & "1010011100"; -- 1110 0000 0000, TERC4 coded
when "11101" => symbols <= "0101100011" & "1010011100" & "1001100011"; -- 1110 0000 0001, TERC4 coded
when "11110" => symbols <= "0101100011" & "1001100011" & "1010011100"; -- 1110 0001 0000, TERC4 coded
when "11111" => symbols <= "0101100011" & "1001100011" & "1001100011"; -- 1110 0001 0001, TERC4 coded
when others => symbols <= (others => '0');
end case;
if blank = '0' then
-- Are we being asked to send video data? If so we need to send a peramble
if last_blank = '1' then
symbol_queue(10) <= "00" & blue & green & red;
symbol_queue(9) <= "01111"; -- Video Guard Band
symbol_queue(8) <= "01111";
symbol_queue(7) <= "01110"; -- Video Preamble
symbol_queue(6) <= "01110";
symbol_queue(5) <= "01110";
symbol_queue(4) <= "01110";
symbol_queue(3) <= "01110";
symbol_queue(2) <= "01110";
symbol_queue(1) <= "01110";
symbol_queue(0) <= "01110";
else
symbol_queue(0 to 9) <= symbol_queue(1 to 10);
symbol_queue(10) <= "00" & blue & green & red;
end if;
else
-- Just merge in the syncs into the control period
case data_island_index is
when "000000" => symbol_queue(10) <= "01100"; -- Data island preamble
when "000001" => symbol_queue(10) <= "01100"; -- Data island preamble
when "000010" => symbol_queue(10) <= "01100"; -- Data island preamble
when "000011" => symbol_queue(10) <= "01100"; -- Data island preamble
when "000100" => symbol_queue(10) <= "01100"; -- Data island preamble
when "000101" => symbol_queue(10) <= "01100"; -- Data island preamble
when "000110" => symbol_queue(10) <= "01100"; -- Data island preamble
when "000111" => symbol_queue(10) <= "01100"; -- Data island preamble
when "001000" => symbol_queue(10) <= "01101"; -- Data island Guard Band
when "001001" => symbol_queue(10) <= "01101"; -- Data island Guard Band
-------------------------
-- For a YCC mode AVI Infoframe Data Island
-------------------------
-- Data Island (0-7)
when "001010" => symbol_queue(10) <= "10011"; -- First word
when "001011" => symbol_queue(10) <= "11111";
when "001100" => symbol_queue(10) <= "11001";
when "001101" => symbol_queue(10) <= "11000";
when "001110" => symbol_queue(10) <= "11000";
when "001111" => symbol_queue(10) <= "11000";
when "010000" => symbol_queue(10) <= "11000";
when "010001" => symbol_queue(10) <= "11110";
-- Data Island (8-15)
when "010010" => symbol_queue(10) <= "11000";
when "010011" => symbol_queue(10) <= "11100";
when "010100" => symbol_queue(10) <= "11000";
when "010101" => symbol_queue(10) <= "11000";
when "010110" => symbol_queue(10) <= "11000";
when "010111" => symbol_queue(10) <= "11000";
when "011000" => symbol_queue(10) <= "11000";
when "011001" => symbol_queue(10) <= "11000";
-- Data Island (16-23)
when "011010" => symbol_queue(10) <= "11100";
when "011011" => symbol_queue(10) <= "11000";
when "011100" => symbol_queue(10) <= "11100";
when "011101" => symbol_queue(10) <= "11100";
when "011110" => symbol_queue(10) <= "11000";
when "011111" => symbol_queue(10) <= "11000";
when "100000" => symbol_queue(10) <= "11000";
when "100001" => symbol_queue(10) <= "11000";
-- Data Island (24-31)
when "100010" => symbol_queue(10) <= "11000";
when "100011" => symbol_queue(10) <= "11000";
when "100100" => symbol_queue(10) <= "11100";
when "100101" => symbol_queue(10) <= "11000";
when "100110" => symbol_queue(10) <= "11010";
when "100111" => symbol_queue(10) <= "11100";
when "101000" => symbol_queue(10) <= "11111";
when "101001" => symbol_queue(10) <= "11110";
-------------------------
-- For a NULL Data Island
-------------------------
-- Data Island (0-7)
-- when "001010" => symbol_queue(10) <= "10000"; -- First word
-- when "001011" => symbol_queue(10) <= "11000";
-- when "001100" => symbol_queue(10) <= "11000";
-- when "001101" => symbol_queue(10) <= "11000";
-- when "001110" => symbol_queue(10) <= "11000";
-- when "001111" => symbol_queue(10) <= "11000";
-- when "010000" => symbol_queue(10) <= "11000";
-- when "010001" => symbol_queue(10) <= "11000";
-- Data Island (8-15)
-- when "010010" => symbol_queue(10) <= "11000";
-- when "010011" => symbol_queue(10) <= "11000";
-- when "010100" => symbol_queue(10) <= "11000";
-- when "010101" => symbol_queue(10) <= "11000";
-- when "010110" => symbol_queue(10) <= "11000";
-- when "010111" => symbol_queue(10) <= "11000";
-- when "011000" => symbol_queue(10) <= "11000";
-- when "011001" => symbol_queue(10) <= "11000";
-- Data Island (16-23)
-- when "011010" => symbol_queue(10) <= "11000";
-- when "011011" => symbol_queue(10) <= "11000";
-- when "011100" => symbol_queue(10) <= "11000";
-- when "011101" => symbol_queue(10) <= "11000";
-- when "011110" => symbol_queue(10) <= "11000";
-- when "011111" => symbol_queue(10) <= "11000";
-- when "100000" => symbol_queue(10) <= "11000";
-- when "100001" => symbol_queue(10) <= "11000";
-- Data Island (24-31)
-- when "100010" => symbol_queue(10) <= "11000";
-- when "100011" => symbol_queue(10) <= "11000";
-- when "100100" => symbol_queue(10) <= "11000";
-- when "100101" => symbol_queue(10) <= "11000";
-- when "100110" => symbol_queue(10) <= "11000";
-- when "100111" => symbol_queue(10) <= "11000";
-- when "101000" => symbol_queue(10) <= "11000";
-- when "101001" => symbol_queue(10) <= "11000";
-- Trailing guard band
when "101010" => symbol_queue(10) <= "01101"; -- Data island Guard Band
when "101011" => symbol_queue(10) <= "01101"; -- Data island Guard Band
-- There has to be four CTL symbols before the next block of video our data,
-- But that won't be a problem for us, we will have the rest of the vertical
-- Blanking interval
when others => symbol_queue(10) <= "010" & Vsync & Hsync;
end case;
symbol_queue(0 to 9) <= symbol_queue(1 to 10);
end if;
if data_island_index /= "111111" then
data_island_index <= data_island_index + 1;
end if;
-- If we see the rising edge of vsync we need to send
-- a data island the next time we see the hsync signal
-- drop.
if last_vsync = '0' and vsync = '1' then
data_island_armed <= '1';
end if;
if data_island_armed = '1' and last_hsync = '1' and hsync = '0' then
data_island_index <= (others => '0');
data_island_armed <= '0';
end if;
last_blank <= blank;
last_hsync <= hsync;
last_vsync <= vsync;
end if;
end process;
end Behavioral;

View file

@ -0,0 +1,165 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Convert 3x 10-bit symbols to three serial channels and the clock channel.
--
------------------------------------------------------------------------------------
-- The MIT License (MIT)
--
-- Copyright (c) 2015 Michael Alan Field
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
------------------------------------------------------------------------------------
----- Want to say thanks? ----------------------------------------------------------
------------------------------------------------------------------------------------
--
-- This design has taken many hours - with the industry metric of 30 lines
-- per day, it is equivalent to about 6 months of work. I'm more than happy
-- to share it if you can make use of it. It is released under the MIT license,
-- so you are not under any onus to say thanks, but....
--
-- If you what to say thanks for this design how about trying PayPal?
-- Educational use - Enough for a beer
-- Hobbyist use - Enough for a pizza
-- Research use - Enough to take the family out to dinner
-- Commercial use - A weeks pay for an engineer (I wish!)
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library UNISIM;
use UNISIM.VComponents.all;
entity serializers is
Port ( clk : in STD_LOGIC;
c0 : in STD_LOGIC_VECTOR (9 downto 0);
c1 : in STD_LOGIC_VECTOR (9 downto 0);
c2 : in STD_LOGIC_VECTOR (9 downto 0);
hdmi_p : out STD_LOGIC_VECTOR (3 downto 0);
hdmi_n : out STD_LOGIC_VECTOR (3 downto 0));
end serializers;
architecture Behavioral of serializers is
-- For holding the outward bound TMDS symbols in the slow and fast domain
signal c0_high_speed : std_logic_vector(9 downto 0) := (others => '0');
signal c1_high_speed : std_logic_vector(9 downto 0) := (others => '0');
signal c2_high_speed : std_logic_vector(9 downto 0) := (others => '0');
signal clk_high_speed : std_logic_vector(9 downto 0) := (others => '0');
signal c2_output_bits : std_logic_vector(1 downto 0) := "00";
signal c1_output_bits : std_logic_vector(1 downto 0) := "00";
signal c0_output_bits : std_logic_vector(1 downto 0) := "00";
signal clk_output_bits : std_logic_vector(1 downto 0) := "00";
-- Controlling the transfers into the high speed domain
signal latch_high_speed : std_logic_vector(4 downto 0) := "00001";
-- From the DDR outputs to the output buffers
signal c0_serial, c1_serial, c2_serial, clk_serial : std_logic;
-- For generating the x5 clocks
signal clk_x5, clk_x5_n, clk_x5_unbuffered : std_logic;
signal clk_feedback : std_logic;
-- To glue the HSYNC and VSYNC into the control character.
signal syncs : std_logic_vector(1 downto 0);
begin
process(clk_x5)
begin
---------------------------------------------------------------
-- Now take the 10-bit words and take it into the high-speed
-- clock domain once every five cycles.
--
-- Then send out two bits every clock cycle using DDR output
-- registers.
---------------------------------------------------------------
if rising_edge(clk_x5) then
c0_output_bits <= c0_high_speed(1 downto 0);
c1_output_bits <= c1_high_speed(1 downto 0);
c2_output_bits <= c2_high_speed(1 downto 0);
clk_output_bits <= clk_high_speed(1 downto 0);
if latch_high_speed(0) = '1' then
c0_high_speed <= c0;
c1_high_speed <= c1;
c2_high_speed <= c2;
clk_high_speed <= "0000011111";
else
c0_high_speed <= "00" & c0_high_speed(9 downto 2);
c1_high_speed <= "00" & c1_high_speed(9 downto 2);
c2_high_speed <= "00" & c2_high_speed(9 downto 2);
clk_high_speed <= "00" & clk_high_speed(9 downto 2);
end if;
latch_high_speed <= latch_high_speed(0) & latch_high_speed(4 downto 1);
end if;
end process;
------------------------------------------------------------------
-- Convert the TMDS codes into a serial stream, two bits at a time
------------------------------------------------------------------
clk_x5_n <= not clk_x5;
c0_to_serial: ODDR2
generic map(DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
port map (C0 => clk_x5, C1 => clk_x5_n, CE => '1', R => '0', S => '0',
D0 => C0_output_bits(0), D1 => C0_output_bits(1), Q => c0_serial);
OBUFDS_c0 : OBUFDS port map ( O => hdmi_p(0), OB => hdmi_n(0), I => c0_serial);
c1_to_serial: ODDR2
generic map(DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
port map (C0 => clk_x5, C1 => clk_x5_n, CE => '1', R => '0', S => '0',
D0 => C1_output_bits(0), D1 => C1_output_bits(1), Q => c1_serial);
OBUFDS_c1 : OBUFDS port map ( O => hdmi_p(1), OB => hdmi_n(1), I => c1_serial);
c2_to_serial: ODDR2
generic map(DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
port map (C0 => clk_x5, C1 => clk_x5_n, CE => '1', R => '0', S => '0',
D0 => C2_output_bits(0), D1 => C2_output_bits(1), Q => c2_serial);
OBUFDS_c2 : OBUFDS port map ( O => hdmi_p(2), OB => hdmi_n(2), I => c2_serial);
clk_to_serial: ODDR2
generic map(DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
port map (C0 => clk_x5, C1 => clk_x5_n, CE => '1', R => '0', S => '0',
D0 => Clk_output_bits(0), D1 => Clk_output_bits(1), Q => clk_serial);
OBUFDS_clk : OBUFDS port map ( O => hdmi_p(3), OB => hdmi_n(3), I => clk_serial);
------------------------------------------------------------------
-- Use a PLL to generate a x5 clock, which is used to drive
-- the DDR registers.This allows 10 bits to be sent for every
-- pixel clock
------------------------------------------------------------------
PLL_BASE_inst : PLL_BASE
generic map (
CLKFBOUT_MULT => 10,
CLKOUT0_DIVIDE => 2, CLKOUT0_PHASE => 0.0, -- Output 5x original frequency
CLK_FEEDBACK => "CLKFBOUT",
CLKIN_PERIOD => 13.33,
DIVCLK_DIVIDE => 1
)
port map (
CLKFBOUT => clk_feedback,
CLKOUT0 => clk_x5_unbuffered,
CLKFBIN => clk_feedback,
CLKIN => clk,
RST => '0'
);
BUFG_pclkx5 : BUFG port map ( I => clk_x5_unbuffered, O => clk_x5);
end Behavioral;

View file

@ -0,0 +1,89 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz<
--
-- Description: Generate a 40Mhz Pixel clock from the 50Mhz input
--
------------------------------------------------------------------------------------
-- The MIT License (MIT)
--
-- Copyright (c) 2015 Michael Alan Field
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
------------------------------------------------------------------------------------
----- Want to say thanks? ----------------------------------------------------------
------------------------------------------------------------------------------------
--
-- This design has taken many hours - with the industry metric of 30 lines
-- per day, it is equivalent to about 6 months of work. I'm more than happy
-- to share it if you can make use of it. It is released under the MIT license,
-- so you are not under any onus to say thanks, but....
--
-- If you what to say thanks for this design how about trying PayPal?
-- Educational use - Enough for a beer
-- Hobbyist use - Enough for a pizza
-- Research use - Enough to take the family out to dinner
-- Commercial use - A weeks pay for an engineer (I wish!)
--
----------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library UNISIM;
use UNISIM.VComponents.all;
entity vga_clocking is
Port ( clk50 : in STD_LOGIC;
pixel_clock : out STD_LOGIC);
end vga_clocking;
architecture Behavioral of vga_clocking is
signal clock_x1 : std_logic;
signal clock_x1_unbuffered : std_logic;
signal clk_feedback : std_logic;
signal clk50_buffered : std_logic;
signal pll_locked : std_logic;
begin
pixel_clock <= clock_x1;
-- Multiply clk50m by 15, then divide by 10 for the 75 MHz pixel clock
-- Because the all come from the same PLL the will all be in phase
PLL_BASE_inst : PLL_BASE
generic map (
CLKFBOUT_MULT => 16,
CLKOUT0_DIVIDE => 20, CLKOUT0_PHASE => 0.0, -- Output pixel clock, 1.5x original frequency
CLK_FEEDBACK => "CLKFBOUT", -- Clock source to drive CLKFBIN ("CLKFBOUT" or "CLKOUT0")
CLKIN_PERIOD => 20.0, -- IMPORTANT! 20.00 => 50MHz
DIVCLK_DIVIDE => 1 -- Division value for all output clocks (1-52)
)
port map (
CLKFBOUT => clk_feedback,
CLKOUT0 => clock_x1_unbuffered,
CLKOUT1 => open,
CLKOUT2 => open,
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
LOCKED => pll_locked,
CLKFBIN => clk_feedback,
CLKIN => clk50_buffered,
RST => '0' -- 1-bit input: Reset input
);
BUFG_clk : BUFG port map ( I => clk50, O => clk50_buffered);
BUFG_pclock : BUFG port map ( I => clock_x1_unbuffered, O => clock_x1);
end Behavioral;

View file

@ -0,0 +1,142 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Description: Generates a test 1280x720 signal
--
------------------------------------------------------------------------------------
-- The MIT License (MIT)
--
-- Copyright (c) 2015 Michael Alan Field
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
------------------------------------------------------------------------------------
----- Want to say thanks? ----------------------------------------------------------
------------------------------------------------------------------------------------
--
-- This design has taken many hours - with the industry metric of 30 lines
-- per day, it is equivalent to about 6 months of work. I'm more than happy
-- to share it if you can make use of it. It is released under the MIT license,
-- so you are not under any onus to say thanks, but....
--
-- If you what to say thanks for this design how about trying PayPal?
-- Educational use - Enough for a beer
-- Hobbyist use - Enough for a pizza
-- Research use - Enough to take the family out to dinner
-- Commercial use - A weeks pay for an engineer (I wish!)
--
----------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity vga_gen is
Port ( clk50 : in STD_LOGIC;
pixel_clock : out std_logic;
red_p : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
green_p : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
blue_p : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
blank : out STD_LOGIC := '0';
hsync : out STD_LOGIC := '0';
vsync : out STD_LOGIC := '0');
end vga_gen;
architecture Behavioral of vga_gen is
COMPONENT vga_clocking
PORT( clk50 : IN std_logic;
pixel_clock : OUT std_logic);
END COMPONENT;
constant h_rez : natural := 800;
constant h_sync_start : natural := 800+40;
constant h_sync_end : natural := 800+40+128;
constant h_max : natural := 1056;
signal h_count : unsigned(11 downto 0) := (others => '0');
signal h_offset : unsigned(7 downto 0) := (others => '0');
constant v_rez : natural := 600;
constant v_sync_start : natural := 600+1;
constant v_sync_end : natural := 600+1+4;
constant v_max : natural := 628;
signal v_count : unsigned(11 downto 0) := x"250";
signal v_offset : unsigned(7 downto 0) := (others => '0');
signal clk40 : std_logic;
begin
Inst_clocking: vga_clocking PORT MAP(
clk50 => clk50,
pixel_clock => clk40
);
pixel_clock <= clk40;
process(clk40)
begin
if rising_edge(clk40) then
if h_count < h_rez and v_count < v_rez then
red_p <= std_logic_vector(h_count(7 downto 0)+h_offset);
green_p <= std_logic_vector(v_count(7 downto 0)+v_offset);
blue_p <= std_logic_vector(h_count(7 downto 0)+v_count(7 downto 0));
blank <= '0';
if h_count = 0 or h_count = h_rez-1 then
red_p <= (others => '1');
green_p <= (others => '1');
blue_p <= (others => '1');
end if;
if v_count = 0 or v_count = v_rez-1 then
red_p <= (others => '1');
green_p <= (others => '0');
blue_p <= (others => '0');
end if;
else
red_p <= (others => '0');
green_p <= (others => '0');
blue_p <= (others => '0');
blank <= '1';
end if;
if h_count >= h_sync_start and h_count < h_sync_end then
hsync <= '1';
else
hsync <= '0';
end if;
if v_count >= v_sync_start and v_count < v_sync_end then
vsync <= '1';
else
vsync <= '0';
end if;
if h_count = h_max then
h_count <= (others => '0');
if v_count = v_max then
h_offset <= h_offset + 1;
v_offset <= v_offset + 1;
v_count <= (others => '0');
else
v_count <= v_count+1;
end if;
else
h_count <= h_count+1;
end if;
end if;
end process;
end Behavioral;

View file

@ -0,0 +1,110 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Module Name: tb_audio_to_db - Behavioral
--
-- Description: A testbench for the audio sample to db level calculation
--
----------------------------------------------------------------------------------
-- The MIT License (MIT)
--
-- Copyright (c) 2015 Michael Alan Field
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
----------------------------------------------------------------------------------
----- Want to say thanks? --------------------------------------------------------
----------------------------------------------------------------------------------
--
-- This design has taken many hours - with the industry metric of 30 lines
-- per day, it is equivalent to about 6 months of work. I'm more than happy
-- to share it if you can make use of it. It is released under the MIT license,
-- so you are not under any onus to say thanks, but....
--
-- If you what to say thanks for this design how about trying PayPal?
-- Educational use - Enough for a beer
-- Hobbyist use - Enough for a pizza
-- Research use - Enough to take the family out to dinner
-- Commercial use - A weeks pay for an engineer (I wish!)
------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity tb_audio_to_db is
end tb_audio_to_db;
architecture Behavioral of tb_audio_to_db is
component audio_to_db is
Port ( clk : in STD_LOGIC;
in_channel : in STD_LOGIC_VECTOR (2 downto 0);
in_de : in STD_LOGIC;
in_sample : in STD_LOGIC_VECTOR (23 downto 0);
out_channel : out STD_LOGIC_VECTOR (2 downto 0);
out_de : out STD_LOGIC;
out_level : out STD_LOGIC_VECTOR (5 downto 0));
end component;
signal clk : STD_LOGIC := '0';
signal in_channel : STD_LOGIC_VECTOR (2 downto 0) := (others => '0');
signal in_de : STD_LOGIC := '1';
signal in_sample : STD_LOGIC_VECTOR (23 downto 0) := (others => '0');
signal out_channel : STD_LOGIC_VECTOR (2 downto 0);
signal out_de : STD_LOGIC;
signal out_level : STD_LOGIC_VECTOR (5 downto 0);
begin
process
begin
wait for 5 ns;
clk <= '1';
wait for 5 ns;
clk <= '0';
end process;
process
begin
wait until rising_edge(clk);
in_de <= '1';
in_sample <= in_sample(in_sample'high-1 downto 0) & not in_sample(in_sample'high);
wait until rising_edge(clk);
in_de <= '0';
wait until rising_edge(clk);
wait until rising_edge(clk);
wait until rising_edge(clk);
wait until rising_edge(clk);
end process;
uut: audio_to_db port map (
clk => clk,
in_channel => in_channel,
in_de => in_de,
in_sample => in_sample,
out_channel => out_channel,
out_de => out_de,
out_level => out_level);
end Behavioral;

View file

@ -0,0 +1,147 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Description: A testbench for YCbCr to RGB decoding
--
------------------------------------------------------------------------------------
-- The MIT License (MIT)
--
-- Copyright (c) 2015 Michael Alan Field
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
------------------------------------------------------------------------------------
----- Want to say thanks? ----------------------------------------------------------
------------------------------------------------------------------------------------
--
-- This design has taken many hours - with the industry metric of 30 lines
-- per day, it is equivalent to about 6 months of work. I'm more than happy
-- to share it if you can make use of it. It is released under the MIT license,
-- so you are not under any onus to say thanks, but....
--
-- If you what to say thanks for this design how about trying PayPal?
-- Educational use - Enough for a beer
-- Hobbyist use - Enough for a pizza
-- Research use - Enough to take the family out to dinner
-- Commercial use - A weeks pay for an engineer (I wish!)
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity tb_convert_yCbCr_to_RGB is
end tb_convert_yCbCr_to_RGB;
architecture Behavioral of tb_convert_yCbCr_to_RGB is
component conversion_YCbCr_to_RGB is
port ( clk : in std_Logic;
input_is_YCbCr : in std_Logic;
------------------------
in_blank : in std_logic;
in_hsync : in std_logic;
in_vsync : in std_logic;
in_U : in std_logic_vector(11 downto 0); -- B or Cb
in_V : in std_logic_vector(11 downto 0); -- G or Y
in_W : in std_logic_vector(11 downto 0); -- R or Cr
------------------------
out_blank : out std_logic;
out_hsync : out std_logic;
out_vsync : out std_logic;
out_R : out std_logic_vector(11 downto 0);
out_G : out std_logic_vector(11 downto 0);
out_B : out std_logic_vector(11 downto 0));
end component;
signal clk : std_Logic := '0';
signal input_is_YCbCr : std_Logic := '0';
signal in_blank : std_logic := '0';
signal in_hsync : std_logic := '0';
signal in_vsync : std_logic := '0';
signal in_U : std_logic_vector(11 downto 0) := x"800"; -- B or Cb
signal in_V : std_logic_vector(11 downto 0) := x"800"; -- G or Y
signal in_W : std_logic_vector(11 downto 0) := x"800"; -- R or Cr
signal out_blank : std_logic := '0';
signal out_hsync : std_logic := '0';
signal out_vsync : std_logic := '0';
signal out_R : std_logic_vector(11 downto 0);
signal out_G : std_logic_vector(11 downto 0);
signal out_B : std_logic_vector(11 downto 0);
begin
process
begin
wait for 5 ns;
clk <= not clk;
end process;
stim: process
begin
wait for 100 ns;
in_U <= x"100";
wait for 100 ns;
in_U <= x"EFF";
wait for 100 ns;
in_U <= x"800";
wait for 100 ns;
in_V <= x"100";
wait for 100 ns;
in_V <= x"EFF";
wait for 100 ns;
in_V <= x"800";
wait for 100 ns;
in_W <= x"100";
wait for 100 ns;
in_W <= x"EFF";
wait for 100 ns;
in_W <= x"800";
end process;
uut: conversion_YCbCr_to_RGB port map (
clk => clk,
input_is_YCbCr => '1',
------------------------
in_blank => in_blank,
in_hsync => in_hsync,
in_vsync => in_vsync,
in_U => in_U,
in_V => in_V,
in_W => in_W,
------------------------
out_blank => out_blank,
out_hsync => out_hsync,
out_vsync => out_vsync,
out_R => out_R,
out_G => out_G,
out_B => out_B);
end Behavioral;

View file

@ -0,0 +1,308 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Module Name: tb_hdmi_decode - Behavioral
--
-- Description: A testbench for testing HDMI decoding
--
------------------------------------------------------------------------------------
-- The MIT License (MIT)
--
-- Copyright (c) 2015 Michael Alan Field
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-- THE SOFTWARE.
----------------------------------------------------------------------------------
----- Want to say thanks? ----------------------------------------------------------
------------------------------------------------------------------------------------
--
-- This design has taken many hours - with the industry metric of 30 lines
-- per day, it is equivalent to about 6 months of work. I'm more than happy
-- to share it if you can make use of it. It is released under the MIT license,
-- so you are not under any onus to say thanks, but....
--
-- If you what to say thanks for this design how about trying PayPal?
-- Educational use - Enough for a beer
-- Hobbyist use - Enough for a pizza
-- Research use - Enough to take the family out to dinner
-- Commercial use - A weeks pay for an engineer (I wish!)
------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tb_hdmi_decode is
end tb_hdmi_decode;
architecture Behavioral of tb_hdmi_decode is
component hdmi_design is
Port (
clk100 : in STD_LOGIC;
-- Control signals
led : out std_logic_vector(7 downto 0);
sw : in std_logic_vector(2 downto 0) :=(others => '0');
debug_pmod : out std_logic_vector(7 downto 0) :=(others => '0');
--HDMI input signals
hdmi_rx_cec : inout std_logic;
hdmi_rx_hpa : out std_logic;
hdmi_rx_scl : in std_logic;
hdmi_rx_sda : inout std_logic;
hdmi_rx_txen : out std_logic;
hdmi_rx_clk_n : in std_logic;
hdmi_rx_clk_p : in std_logic;
hdmi_rx_n : in std_logic_vector(2 downto 0);
hdmi_rx_p : in std_logic_vector(2 downto 0);
--- HDMI out
hdmi_tx_cec : inout std_logic;
hdmi_tx_clk_n : out std_logic;
hdmi_tx_clk_p : out std_logic;
hdmi_tx_hpd : in std_logic;
hdmi_tx_rscl : inout std_logic;
hdmi_tx_rsda : inout std_logic;
hdmi_tx_p : out std_logic_vector(2 downto 0);
hdmi_tx_n : out std_logic_vector(2 downto 0)
);
end component;
component hdmi_output_test is
Port ( clk50 : in STD_LOGIC;
hdmi_out_p : out STD_LOGIC_VECTOR(3 downto 0);
hdmi_out_n : out STD_LOGIC_VECTOR(3 downto 0);
leds : out std_logic_vector(7 downto 0));
end component;
signal clk : std_logic := '0';
signal clk50 : std_logic := '1';
signal led : std_logic_vector(7 downto 0);
signal hdmi_rx_cec : std_logic;
signal hdmi_rx_hpa : std_logic;
signal hdmi_rx_scl : std_logic;
signal hdmi_rx_sda : std_logic;
signal hdmi_rx_txen : std_logic;
signal hdmi_rx_clk_n : std_logic;
signal hdmi_rx_clk_p : std_logic;
signal hdmi2_rx_clk_n : std_logic := '1';
signal hdmi2_rx_clk_p : std_logic := '0';
signal hdmi_out_n : std_logic_vector(3 downto 0);
signal hdmi_out_p : std_logic_vector(3 downto 0);
signal hdmi_rx_n : std_logic_vector(2 downto 0);
signal hdmi_rx_p : std_logic_vector(2 downto 0);
signal hdmi_tx_cec : std_logic;
signal hdmi_tx_clk_n : std_logic;
signal hdmi_tx_clk_p : std_logic;
signal hdmi_tx_hpd : std_logic;
signal hdmi_tx_rscl : std_logic;
signal hdmi_tx_rsda : std_logic;
signal hdmi_tx_p : std_logic_vector(2 downto 0);
signal hdmi_tx_n : std_logic_vector(2 downto 0);
signal sdat_drive : std_logic := '1';
begin
hdmi_rx_sda <= '0' when sdat_drive = '0' else 'H';
hdmi_rx_p <= transport hdmi_out_p(2 downto 0) after 5.00 ns;
hdmi_rx_n <= transport hdmi_out_n(2 downto 0) after 5.00 ns;
hdmi_rx_clk_p <= transport hdmi_out_p(3) after 1.25 ns;
hdmi_rx_clk_n <= transport hdmi_out_n(3) after 1.25 ns;
clk_proc: process
begin
wait for 7.0 ns;
while 1 = 1 loop
wait for 5.0 ns;
clk <= not clk;
end loop;
end process;
clk50_proc: process
begin
wait for 7.0 ns;
while 1 = 1 loop
wait for 5.0 ns;
clk50 <= not clk50;
end loop;
end process;
i_gen_signal: hdmi_output_test port map (
clk50 => clk50,
hdmi_out_p => hdmi_out_p,
hdmi_out_n => hdmi_out_n,
leds => open);
uut: hdmi_design Port map (
clk100 => clk,
led => open,
sw => (others => '0'),
debug_pmod => open,
--HDMI in
hdmi_rx_cec => hdmi_rx_cec,
hdmi_rx_hpa => hdmi_rx_hpa,
hdmi_rx_scl => hdmi_rx_scl,
hdmi_rx_sda => hdmi_rx_sda,
hdmi_rx_txen => hdmi_rx_txen,
hdmi_rx_clk_n => hdmi_rx_clk_n,
hdmi_rx_clk_p => hdmi_rx_clk_p,
hdmi_rx_n => hdmi_rx_n,
hdmi_rx_p => hdmi_rx_p,
--- HDMI out
hdmi_tx_cec => hdmi_tx_cec,
hdmi_tx_clk_n => hdmi_tx_clk_n,
hdmi_tx_clk_p => hdmi_tx_clk_p,
hdmi_tx_hpd => hdmi_tx_hpd,
hdmi_tx_rscl => hdmi_tx_rscl,
hdmi_tx_rsda => hdmi_tx_rsda,
hdmi_tx_p => hdmi_tx_p,
hdmi_tx_n => hdmi_tx_n
);
edid_test_proc: process
begin
hdmi_rx_scl <= '1';
wait for 1 us;
-- START condition
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- DEVICE ADDRESS FOR WRITE
-- dev bit 7
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 6
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 6
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 4
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 3
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 2
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 1
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 0
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- Slave ACK
-- Device to ack
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- SEND WRITE ADDRESS
-- addr bit 7
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- addr bit 6
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- addr bit 6
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- addr bit 4
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- addr bit 3
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- addr bit 2
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- addr bit 1
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- addr bit 0
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- Slave ACK
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- repeated START condition
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1';
wait for 400 ns; sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- DEVICE ADDRESS / READ -
-- dev bit 7
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 6
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 6
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 4
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 3
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 2
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 1
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- dev bit 0 - READ!
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- ACK????
-- Device to ack
sdat_drive <= '1';
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
for i in 1 to 127 loop
-- READ First byte
-- read bit 7
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 6
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 6
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 4
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 3
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 2
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 1
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 0
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
sdat_drive <= '1';
-- Host to ack
sdat_drive <= '0';
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
sdat_drive <= '1';
end loop;
-- READ Second
-- read bit 7
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 6
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 6
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 4
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 3
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 2
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 1
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
-- read bit 0
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
sdat_drive <= '1';
-- Master NACK
sdat_drive <= '1';
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
sdat_drive <= '1';
-- STOP
sdat_drive <= '1';
wait for 200 ns;
hdmi_rx_scl <= '1';
wait for 200 ns;
wait;
end process;
end Behavioral;