master 8fd6a5add930 cached
34 files
356.9 KB
92.8k tokens
1 requests
Download .txt
Showing preview only (372K chars total). Download the full file or copy to clipboard to get everything.
Repository: hamsternz/Artix-7-HDMI-processing
Branch: master
Commit: 8fd6a5add930
Files: 34
Total size: 356.9 KB

Directory structure:
gitextract_5_dt_ehf/

├── Artix-7-HDMI-processing.xpr
├── README.txt
├── constraints/
│   └── NexysVideo.xdc
├── src/
│   ├── alignment_detect.vhd
│   ├── audio_meters.vhd
│   ├── audio_to_db.vhd
│   ├── conversion_to_RGB.vhd
│   ├── deserialiser_1_to_10.vhd
│   ├── detect_interlace.vhd
│   ├── dvid_output.vhd
│   ├── edge_enhance.vhd
│   ├── edid_rom.vhd
│   ├── expand_422_to_444.vhd
│   ├── extract_audio_samples.vhd
│   ├── extract_video_infopacket_data.vhd
│   ├── guidelines.vhd
│   ├── hdmi_design.vhd
│   ├── hdmi_input.vhd
│   ├── hdmi_io.vhd
│   ├── input_channel.vhd
│   ├── line_delay.vhd
│   ├── pixel_processing.vhd
│   ├── serialiser_10_to_1.vhd
│   ├── symbol_dump.vhd
│   ├── tmds_decoder.vhd
│   └── tmds_encoder.vhd
└── test_bench/
    ├── hdmi_test_generator/
    │   ├── hdmi_ouput_test.vhd
    │   ├── minimal_hdmi_symbols.vhd
    │   ├── serializers.vhd
    │   ├── vga_clocking.vhd
    │   └── vga_gen.vhd
    ├── tb_audio_to_db.vhd
    ├── tb_convert_yCbCr_to_RGB.vhd
    └── tb_hdmi_decode.vhd

================================================
FILE CONTENTS
================================================

================================================
FILE: Artix-7-HDMI-processing.xpr
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!-- Product Version: Vivado v2017.4 (64-bit)              -->
<!--                                                         -->
<!-- Copyright 1986-2017 Xilinx, Inc. All Rights Reserved.   -->

<Project Version="7" Minor="35" Path="C:/Users/Hamster/Desktop/a7/Artix-7-HDMI-processing/Artix-7-HDMI-processing.xpr">
  <DefaultLaunch Dir="$PRUNDIR"/>
  <Configuration>
    <Option Name="Id" Val="487e6670b2224898a3f8937139078585"/>
    <Option Name="Part" Val="xc7a200tfbg484-1"/>
    <Option Name="CompiledLibDir" Val="$PCACHEDIR/compile_simlib"/>
    <Option Name="CompiledLibDirXSim" Val=""/>
    <Option Name="CompiledLibDirModelSim" Val="$PCACHEDIR/compile_simlib/modelsim"/>
    <Option Name="CompiledLibDirQuesta" Val="$PCACHEDIR/compile_simlib/questa"/>
    <Option Name="CompiledLibDirIES" Val="$PCACHEDIR/compile_simlib/ies"/>
    <Option Name="CompiledLibDirXcelium" Val="$PCACHEDIR/compile_simlib/xcelium"/>
    <Option Name="CompiledLibDirVCS" Val="$PCACHEDIR/compile_simlib/vcs"/>
    <Option Name="CompiledLibDirRiviera" Val="$PCACHEDIR/compile_simlib/riviera"/>
    <Option Name="CompiledLibDirActivehdl" Val="$PCACHEDIR/compile_simlib/activehdl"/>
    <Option Name="TargetLanguage" Val="VHDL"/>
    <Option Name="BoardPart" Val=""/>
    <Option Name="ActiveSimSet" Val="sim_1"/>
    <Option Name="DefaultLib" Val="xil_defaultlib"/>
    <Option Name="ProjectType" Val="Default"/>
    <Option Name="IPCachePermission" Val="disable"/>
    <Option Name="EnableCoreContainer" Val="FALSE"/>
    <Option Name="CreateRefXciForCoreContainers" Val="FALSE"/>
    <Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
    <Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
    <Option Name="EnableBDX" Val="FALSE"/>
    <Option Name="DSAVendor" Val="xilinx"/>
    <Option Name="DSANumComputeUnits" Val="60"/>
    <Option Name="WTXSimLaunchSim" Val="0"/>
    <Option Name="WTModelSimLaunchSim" Val="0"/>
    <Option Name="WTQuestaLaunchSim" Val="0"/>
    <Option Name="WTIesLaunchSim" Val="0"/>
    <Option Name="WTVcsLaunchSim" Val="0"/>
    <Option Name="WTRivieraLaunchSim" Val="0"/>
    <Option Name="WTActivehdlLaunchSim" Val="0"/>
    <Option Name="WTXSimExportSim" Val="0"/>
    <Option Name="WTModelSimExportSim" Val="0"/>
    <Option Name="WTQuestaExportSim" Val="0"/>
    <Option Name="WTIesExportSim" Val="0"/>
    <Option Name="WTVcsExportSim" Val="0"/>
    <Option Name="WTRivieraExportSim" Val="0"/>
    <Option Name="WTActivehdlExportSim" Val="0"/>
    <Option Name="GenerateIPUpgradeLog" Val="TRUE"/>
    <Option Name="XSimRadix" Val="hex"/>
    <Option Name="XSimTimeUnit" Val="ns"/>
    <Option Name="XSimArrayDisplayLimit" Val="1024"/>
    <Option Name="XSimTraceLimit" Val="65536"/>
    <Option Name="SimTypes" Val="rtl"/>
  </Configuration>
  <FileSets Version="1" Minor="31">
    <FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1">
      <Filter Type="Srcs"/>
      <File Path="$PPRDIR/src/alignment_detect.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/audio_meters.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/audio_to_db.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/conversion_to_RGB.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/deserialiser_1_to_10.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/detect_interlace.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/dvid_output.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/edge_enhance.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/edid_rom.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/expand_422_to_444.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/extract_audio_samples.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/extract_video_infopacket_data.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/guidelines.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/hdmi_input.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/hdmi_io.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/input_channel.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/line_delay.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/pixel_processing.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/serialiser_10_to_1.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/symbol_dump.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/tmds_decoder.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/tmds_encoder.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/src/hdmi_design.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <Config>
        <Option Name="DesignMode" Val="RTL"/>
        <Option Name="TopModule" Val="hdmi_design"/>
        <Option Name="TopAutoSet" Val="TRUE"/>
      </Config>
    </FileSet>
    <FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR/constrs_1">
      <Filter Type="Constrs"/>
      <File Path="$PPRDIR/constraints/NexysVideo.xdc">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="implementation"/>
        </FileInfo>
      </File>
      <Config>
        <Option Name="TargetConstrsFile" Val="$PPRDIR/constraints/NexysVideo.xdc"/>
        <Option Name="ConstrsType" Val="XDC"/>
      </Config>
    </FileSet>
    <FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1">
      <Filter Type="Srcs"/>
      <File Path="$PPRDIR/test_bench/hdmi_test_generator/hdmi_ouput_test.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/test_bench/hdmi_test_generator/minimal_hdmi_symbols.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/test_bench/hdmi_test_generator/serializers.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/test_bench/hdmi_test_generator/vga_clocking.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/test_bench/hdmi_test_generator/vga_gen.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/test_bench/tb_hdmi_decode.vhd">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/test_bench/tb_convert_yCbCr_to_RGB.vhd">
        <FileInfo>
          <Attr Name="AutoDisabled" Val="1"/>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <File Path="$PPRDIR/test_bench/tb_audio_to_db.vhd">
        <FileInfo>
          <Attr Name="AutoDisabled" Val="1"/>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
      <Config>
        <Option Name="DesignMode" Val="RTL"/>
        <Option Name="TopModule" Val="tb_hdmi_decode"/>
        <Option Name="TopLib" Val="xil_defaultlib"/>
        <Option Name="TopAutoSet" Val="TRUE"/>
        <Option Name="TransportPathDelay" Val="0"/>
        <Option Name="TransportIntDelay" Val="0"/>
        <Option Name="SrcSet" Val="sources_1"/>
        <Option Name="XSimWcfgFile" Val="$PPRDIR/tb_hdmi_decode_behav.wcfg"/>
      </Config>
    </FileSet>
  </FileSets>
  <Simulators>
    <Simulator Name="XSim">
      <Option Name="Description" Val="Vivado Simulator"/>
      <Option Name="CompiledLib" Val="0"/>
    </Simulator>
    <Simulator Name="ModelSim">
      <Option Name="Description" Val="ModelSim Simulator"/>
    </Simulator>
    <Simulator Name="Questa">
      <Option Name="Description" Val="Questa Advanced Simulator"/>
    </Simulator>
    <Simulator Name="Riviera">
      <Option Name="Description" Val="Riviera-PRO Simulator"/>
    </Simulator>
    <Simulator Name="ActiveHDL">
      <Option Name="Description" Val="Active-HDL Simulator"/>
    </Simulator>
  </Simulators>
  <Runs Version="1" Minor="10">
    <Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a200tfbg484-1" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/synth_1" IncludeInArchive="true">
      <Strategy Version="1" Minor="2">
        <StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2014"/>
        <Step Id="synth_design"/>
      </Strategy>
      <GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
      <ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2017"/>
      <Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
    </Run>
    <Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a200tfbg484-1" ConstrsSet="constrs_1" Description="Vivado Implementation Defaults" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true">
      <Strategy Version="1" Minor="2">
        <StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2014"/>
        <Step Id="init_design"/>
        <Step Id="opt_design"/>
        <Step Id="power_opt_design"/>
        <Step Id="place_design"/>
        <Step Id="post_place_power_opt_design"/>
        <Step Id="phys_opt_design"/>
        <Step Id="route_design"/>
        <Step Id="post_route_phys_opt_design"/>
        <Step Id="write_bitstream"/>
      </Strategy>
      <GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
      <ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2017"/>
      <Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
    </Run>
  </Runs>
  <Board/>
</Project>


================================================
FILE: README.txt
================================================
README file for Artix 7 HDMI processing
=======================================
Hi! 

This is my design for receiving HDMI input, then extracting the video data, the
Video Inforframe and audio samples, then using that to display audio db meters 
on the top corner of the screen. Currently for simplicity the output is only DVID.

Features
--------
Supports HDMI formats:
  -720p@50
 - 720p@60, 
 - 1080i (with a bug)
 - 1080p@50
 - 1080p@60
 and others....

Colourspaces / formats:
 - RGB 444
 - YCbCr 444
 - YCbCr 422

New feature 10-AUG-2015!
-----------------------
Switch 0 will turn real-time edge detect off and on.

New feature 6-AUG-2015!
-----------------------
Switch 1 will turn guidelines off and on. Will only show in 1080p 1080i and 720p resolutions.

Supported Boards
----------------
 - Digilent Nexys Video 

Sources tested with:
 - Western Digital HD Live
 - HP Laptop

Sinks tested with:
 - Viewsonic Monitor
 - AOC Monitor
 - Vivo TV
 
Known issues:
 - Currently extracts only two channels of audio 

 - Does not adjust PLL settings for input clock, so the PLL is run slightly out
   of spec.

 - Image may re-sync once after a few seconds if symbol errors are seen.

 - There are timings errors, as generating 148.5MHz HDMI using the Artix-7 chip
   is actually out of spec. Expect seven failing paths and about 20ns of negative 
   slack.

------------------------------------------------------------------------------------
-- 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!)
--
----------------------------------------------------------------------------------


================================================
FILE: constraints/NexysVideo.xdc
================================================
#------------------------------------------------------------------------------------ 
# HDMI and clock Constraints for the Digilent Nexys Video FPGA development board.
#------------------------------------------------------------------------------------ 

##Clock Signal
set_property -dict { PACKAGE_PIN R4    IOSTANDARD LVCMOS33 } [get_ports { clk100 }];
    create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk100]
    
##HDMI in
create_clock -add -name hdmi_clk -period 6.7 -waveform {0 5} [get_ports hdmi_rx_clk_p]

set_property -dict { PACKAGE_PIN AA5   IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_cec }]; #IO_L10P_T1_34 Sch=hdmi_rx_cec
set_property -dict { PACKAGE_PIN W4    IOSTANDARD TMDS_33  } [get_ports { hdmi_rx_clk_n }]; #IO_L12N_T1_MRCC_34 Sch=hdmi_rx_clk_n
set_property -dict { PACKAGE_PIN V4    IOSTANDARD TMDS_33  } [get_ports { hdmi_rx_clk_p }]; #IO_L12P_T1_MRCC_34 Sch=hdmi_rx_clk_p
set_property -dict { PACKAGE_PIN AB12  IOSTANDARD LVCMOS25 } [get_ports { hdmi_rx_hpa }]; #IO_L7N_T1_13 Sch=hdmi_rx_hpa
set_property -dict { PACKAGE_PIN Y4    IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_scl }]; #IO_L11P_T1_SRCC_34 Sch=hdmi_rx_scl
set_property -dict { PACKAGE_PIN AB5   IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_sda }]; #IO_L10N_T1_34 Sch=hdmi_rx_sda
set_property -dict { PACKAGE_PIN R3    IOSTANDARD LVCMOS33 } [get_ports { hdmi_rx_txen }]; #IO_L3P_T0_DQS_34 Sch=hdmi_rx_txen
set_property -dict { PACKAGE_PIN AA3   IOSTANDARD TMDS_33  } [get_ports { hdmi_rx_n[0] }]; #IO_L9N_T1_DQS_34 Sch=hdmi_rx_n[0]
set_property -dict { PACKAGE_PIN Y3    IOSTANDARD TMDS_33  } [get_ports { hdmi_rx_p[0] }]; #IO_L9P_T1_DQS_34 Sch=hdmi_rx_p[0]
set_property -dict { PACKAGE_PIN Y2    IOSTANDARD TMDS_33  } [get_ports { hdmi_rx_n[1] }]; #IO_L4N_T0_34 Sch=hdmi_rx_n[1]
set_property -dict { PACKAGE_PIN W2    IOSTANDARD TMDS_33  } [get_ports { hdmi_rx_p[1] }]; #IO_L4P_T0_34 Sch=hdmi_rx_p[1]
set_property -dict { PACKAGE_PIN V2    IOSTANDARD TMDS_33  } [get_ports { hdmi_rx_n[2] }]; #IO_L2N_T0_34 Sch=hdmi_rx_n[2]
set_property -dict { PACKAGE_PIN U2    IOSTANDARD TMDS_33  } [get_ports { hdmi_rx_p[2] }]; #IO_L2P_T0_34 Sch=hdmi_rx_p[2]


##HDMI out
set_property -dict { PACKAGE_PIN AA4   IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_cec }]; #IO_L11N_T1_SRCC_34 Sch=hdmi_tx_cec
set_property -dict { PACKAGE_PIN U1    IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_clk_n }]; #IO_L1N_T0_34 Sch=hdmi_tx_clk_n
set_property -dict { PACKAGE_PIN T1    IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_clk_p }]; #IO_L1P_T0_34 Sch=hdmi_tx_clk_p
set_property -dict { PACKAGE_PIN AB13  IOSTANDARD LVCMOS25 } [get_ports { hdmi_tx_hpd }]; #IO_L3N_T0_DQS_13 Sch=hdmi_tx_hpd
set_property -dict { PACKAGE_PIN U3    IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_rscl }]; #IO_L6P_T0_34 Sch=hdmi_tx_rscl
set_property -dict { PACKAGE_PIN V3    IOSTANDARD LVCMOS33 } [get_ports { hdmi_tx_rsda }]; #IO_L6N_T0_VREF_34 Sch=hdmi_tx_rsda
set_property -dict { PACKAGE_PIN Y1    IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_n[0] }]; #IO_L5N_T0_34 Sch=hdmi_tx_n[0]
set_property -dict { PACKAGE_PIN W1    IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_p[0] }]; #IO_L5P_T0_34 Sch=hdmi_tx_p[0]
set_property -dict { PACKAGE_PIN AB1   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_n[1] }]; #IO_L7N_T1_34 Sch=hdmi_tx_n[1]
set_property -dict { PACKAGE_PIN AA1   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_p[1] }]; #IO_L7P_T1_34 Sch=hdmi_tx_p[1]
set_property -dict { PACKAGE_PIN AB2   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_n[2] }]; #IO_L8N_T1_34 Sch=hdmi_tx_n[2]
set_property -dict { PACKAGE_PIN AB3   IOSTANDARD TMDS_33  } [get_ports { hdmi_tx_p[2] }]; #IO_L8P_T1_34 Sch=hdmi_tx_p[2]

# DEBUG on JA
set_property -dict { PACKAGE_PIN AB22  IOSTANDARD LVCMOS33 } [get_ports { debug_pmod[0] }]; #IO_L10N_T1_D15_14 Sch=ja[1]
set_property -dict { PACKAGE_PIN AB21  IOSTANDARD LVCMOS33 } [get_ports { debug_pmod[1] }]; #IO_L10P_T1_D14_14 Sch=ja[2]
set_property -dict { PACKAGE_PIN AB20  IOSTANDARD LVCMOS33 } [get_ports { debug_pmod[2] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=ja[3]
set_property -dict { PACKAGE_PIN AB18  IOSTANDARD LVCMOS33 } [get_ports { debug_pmod[3] }]; #IO_L17N_T2_A13_D29_14 Sch=ja[4]
set_property -dict { PACKAGE_PIN Y21   IOSTANDARD LVCMOS33 } [get_ports { debug_pmod[4] }]; #IO_L9P_T1_DQS_14 Sch=ja[7]
set_property -dict { PACKAGE_PIN AA21  IOSTANDARD LVCMOS33 } [get_ports { debug_pmod[5] }]; #IO_L8N_T1_D12_14 Sch=ja[8]
set_property -dict { PACKAGE_PIN AA20  IOSTANDARD LVCMOS33 } [get_ports { debug_pmod[6] }]; #IO_L8P_T1_D11_14 Sch=ja[9]
set_property -dict { PACKAGE_PIN AA18  IOSTANDARD LVCMOS33 } [get_ports { debug_pmod[7] }]; #IO_L17P_T2_A14_D30_14 Sch=ja[10

##Switches
set_property -dict { PACKAGE_PIN E22  IOSTANDARD LVCMOS25 } [get_ports { sw[0] }]; #IO_L22P_T3_16 Sch=sw[0]
set_property -dict { PACKAGE_PIN F21  IOSTANDARD LVCMOS25 } [get_ports { sw[1] }]; #IO_25_16 Sch=sw[1]
set_property -dict { PACKAGE_PIN G21  IOSTANDARD LVCMOS25 } [get_ports { sw[2] }]; #IO_L24P_T3_16 Sch=sw[2]
set_property -dict { PACKAGE_PIN G22  IOSTANDARD LVCMOS25 } [get_ports { sw[3] }]; #IO_L24N_T3_16 Sch=sw[3]
set_property -dict { PACKAGE_PIN H17  IOSTANDARD LVCMOS25 } [get_ports { sw[4] }]; #IO_L6P_T0_15 Sch=sw[4]
set_property -dict { PACKAGE_PIN J16  IOSTANDARD LVCMOS25 } [get_ports { sw[5] }]; #IO_0_15 Sch=sw[5]
set_property -dict { PACKAGE_PIN K13  IOSTANDARD LVCMOS25 } [get_ports { sw[6] }]; #IO_L19P_T3_A22_15 Sch=sw[6]
set_property -dict { PACKAGE_PIN M17  IOSTANDARD LVCMOS25 } [get_ports { sw[7] }]; #IO_25_15 Sch=sw[7]

##LEDs
set_property -dict { PACKAGE_PIN T14   IOSTANDARD LVCMOS25 } [get_ports { led[0] }]; #IO_L15P_T2_DQS_13 Sch=led[0]
set_property -dict { PACKAGE_PIN T15   IOSTANDARD LVCMOS25 } [get_ports { led[1] }]; #IO_L15N_T2_DQS_13 Sch=led[1]
set_property -dict { PACKAGE_PIN T16   IOSTANDARD LVCMOS25 } [get_ports { led[2] }]; #IO_L17P_T2_13 Sch=led[2]
set_property -dict { PACKAGE_PIN U16   IOSTANDARD LVCMOS25 } [get_ports { led[3] }]; #IO_L17N_T2_13 Sch=led[3]
set_property -dict { PACKAGE_PIN V15   IOSTANDARD LVCMOS25 } [get_ports { led[4] }]; #IO_L14N_T2_SRCC_13 Sch=led[4]
set_property -dict { PACKAGE_PIN W16   IOSTANDARD LVCMOS25 } [get_ports { led[5] }]; #IO_L16N_T2_13 Sch=led[5]
set_property -dict { PACKAGE_PIN W15   IOSTANDARD LVCMOS25 } [get_ports { led[6] }]; #IO_L16P_T2_13 Sch=led[6]
set_property -dict { PACKAGE_PIN Y13   IOSTANDARD LVCMOS25 } [get_ports { led[7] }]; #IO_L5P_T0_13 Sch=led[7]

##UART
set_property -dict { PACKAGE_PIN AA19  IOSTANDARD LVCMOS33 } [get_ports { rs232_tx }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=uart_rx_out


================================================
FILE: src/alignment_detect.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz< 
-- 
-- Module Name: alignment_detect - Behavioral
--
-- Description: Manage the dealy and bitslipping of the SERDES based on invald 
--              symbols being received.  
-- 
------------------------------------------------------------------------------------
-- 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 alignment_detect is
    Port ( clk            : in  STD_LOGIC;
           invalid_symbol : in  STD_LOGIC;
           delay_count    : out std_logic_vector(4 downto 0);
           delay_ce       : out STD_LOGIC;
           bitslip        : out STD_LOGIC;
           symbol_sync    : out STD_LOGIC);
end alignment_detect;

architecture Behavioral of alignment_detect is
    --------------------------------------
    -- Signals for controlling the bitslip 
    -- and delay so we can sync symbols
    --------------------------------------
    signal count          : unsigned(19 downto 0) := (others => '0');
    signal signal_quality : unsigned(27 downto 0) := (others => '0');
    signal holdoff        : unsigned(9 downto 0)  := (others => '0');
    signal error_seen     : std_logic := '0';
    signal idelay_ce      : std_logic                    := '0';
    signal idelay_count   : std_logic_vector(4 downto 0) := (others => '0');
    signal symbol_sync_i  : std_logic                    := '0';

begin
    delay_count <= idelay_count;
    delay_ce    <= idelay_ce;
 
detect_alignment_proc: process(clk)
    begin
        -------------------------------------------------------------
        -- If there are a dozen or so symbol errors in at a rate of 
        -- greater than 1 in a million then advance the delay and
        -- if that wraps then assert the bitslip signal
        -------------------------------------------------------------
        if rising_edge(clk) then
            -----------------------------------
            -- See if an error has been seen
            --
            -- Holdoff gives a few cycles for 
            -- bitslips and delay changes to 
            -- take effect.
            -----------------------------------
            error_seen <= '0';
            if holdoff = 0 then
                if invalid_symbol = '1' then
                    error_seen <= '1';
                end if;
            else 
                holdoff <= holdoff-1;
            end if;
            ---------------------------------------------
            -- Keep track of valid symbol count vs errors
            -- 
            -- Each error increase the count by a million, 
            -- each valid sysmbol decreases the count by 
            -- one. So after 12 errors it will cause us to
            -- change bitslip or delay settings, but it will
            -- take 7 million cycles until the high four 
            -- bits are zeros (and the link considered OK)
            -----------------------------------------------
            bitslip <= '0';
            idelay_ce <= '0';
            if error_seen = '1' then
                if signal_quality(27 downto 24) = x"F" then
                    ------------------------------------------
                    -- Enough errors to cause us to loose sync 
                    -- (if we had it!) 
                    ------------------------------------------
                    symbol_sync_i         <= '0';
                    --------------------------------------                    
                    -- Hold off acting on any more errors
                    -- while we adjust the delay or bitslip
                    --------------------------------------                    
                    holdoff <= (others => '1');                    
                    -----------------------
                    -- Bitslip if required
                    -----------------------
                    if unsigned(idelay_count) = 31 then   
                        bitslip <= '1';
                    end if;
                    -------------------------------------------------------------------
                    -- And adjust the delay setting (will wrap to 0 when bitslipping)
                    -------------------------------------------------------------------
                    idelay_count  <= std_logic_vector(unsigned(idelay_count)+1);
                    idelay_ce <= '1';   
                    -------------------------------------------------------------------
                    -- It will need 4M good symbols to avoid adjusting the timing again 
                    -------------------------------------------------------------------
                    signal_quality(27 downto 24) <= x"4";
                else
                    signal_quality <= signal_quality + x"100000";   -- add a million if there is a symbol error
                end if;
            else 
                -----------------------------------------------
                -- Count down by one, as we are one symbol 
                -- closer to having a valid stream
                -----------------------------------------------
                if signal_quality(27 downto 24) > 0 then
                    signal_quality <= signal_quality - 1;   -- add a million if there is a symvole error;
                end if;        
            end if;
            ------------------------------------
            -- if we have counted down about 3M
            -- symbols without any symbol errors
            -- being seen then we are in sync
            ------------------------------------
            if signal_quality(27 downto 24) = "0000" then 
                symbol_sync <= '1';
            end if;
        end if;        
    end process;

end Behavioral;


================================================
FILE: src/audio_meters.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: audio_meters - Behavioral
--
-- Description: Insert audio level meters on a video stream. 
-- 
-- Will need to make allowances for interlaced sources!
------------------------------------------------------------------------------------
-- 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 audio_meters is
    Port ( clk : in STD_LOGIC;
           -------------------------------
           -- VGA data recovered from HDMI
           -------------------------------
           in_blank  : in std_logic;
           in_hsync  : in std_logic;
           in_vsync  : in std_logic;
           in_red    : in std_logic_vector(7 downto 0);
           in_green  : in std_logic_vector(7 downto 0);
           in_blue   : in std_logic_vector(7 downto 0);
           is_interlaced   : in std_logic;
           is_second_field : in std_logic;
            
           -----------------------------------
           -- VGA data to be converted to HDMI
           -----------------------------------
           out_blank : out std_logic;
           out_hsync : out std_logic;
           out_vsync : out std_logic;
           out_red   : out std_logic_vector(7 downto 0);
           out_green : out std_logic_vector(7 downto 0);
           out_blue  : out std_logic_vector(7 downto 0);
           
           -------------------------------------
           -- Audio Levels
           -------------------------------------
           signal audio_channel : in std_logic_vector(2 downto 0);
           signal audio_de      : in std_logic;
           signal audio_level   : in std_logic_vector(5 downto 0)
     );
end audio_meters;

architecture Behavioral of audio_meters is
    signal col_count  : unsigned(11 downto 0);
    signal line_count : unsigned(11 downto 0);
    signal last_hsync : std_logic := '0';
    signal last_vsync : std_logic := '0';
    signal last_blank : std_logic := '0';

    signal mid_blank : std_logic;
    signal mid_hsync : std_logic;
    signal mid_vsync : std_logic;
    signal mid_red   : std_logic_vector(7 downto 0);
    signal mid_green : std_logic_vector(7 downto 0);
    signal mid_blue  : std_logic_vector(7 downto 0);
    signal bar_draw : std_logic;
    signal bar_col  : unsigned(6 downto 0); -- 0-127
    signal bar_line : unsigned(5 downto 0); -- 0-63
   
    type a_level is array (0 to 7) of unsigned(5 downto 0);
    signal levels : a_level;

    type a_peak is array (0 to 7) of unsigned(7 downto 0);
    signal peaks : a_peak;

    signal pending_drop : std_logic := '0';
	signal drop_index   : unsigned(2 downto 0) := (others => '0');

    signal u_sample     : unsigned(5 downto 0) := (others => '0');
    signal level        : unsigned(5 downto 0);
    signal peak         : unsigned(5 downto 0);

begin
    
level_proc: process(clk)
    begin
        if rising_edge(clk) then
            -------------------------------------------------
            -- Update the peak level, or if pending_drop is 
            -- set then drop the peak and level by 1 every
			-- frame.
			--
		    -- This causes 'peak' to fall at 1/4th the speed
		    -- of 'level', but makes for inconsistent
			-- behaviour depending on frame rate :-(
            -------------------------------------------------
            if audio_de = '1' then 
                if levels(to_integer(unsigned(audio_channel))) < unsigned(audio_level) then
                    levels(to_integer(unsigned(audio_channel))) <= unsigned(audio_level);
                end if;     
                if peaks(to_integer(unsigned(audio_channel))) < unsigned(audio_level &"00") then
                    peaks(to_integer(unsigned(audio_channel))) <= unsigned(audio_level & "00");
                end if;
            else
                if pending_drop = '1' then
                    if levels(to_integer(drop_index)) > 0 then
                        levels(to_integer(drop_index)) <= levels(to_integer(drop_index))-1;
                    end if;
                    if peaks(to_integer(drop_index)) > 0 then
                        peaks(to_integer(drop_index))  <= peaks(to_integer(drop_index))-1;
                    end if;
                    if drop_index = "000" then
                       pending_drop <= '0';    
                    end if;
                    drop_index <= drop_index-1;
                end if;
            end if;

            -- Signal to reduce (drop' the levels of the meters once each frame (of field for interlaced sources
            if last_vsync = '0'  and in_vsync = '1' then
                pending_drop <= '1';
                drop_index <= (others => '1');
            end if;
        end if;
    end process;

video_proc: process(clk)
    begin
        if rising_edge(clk) then
            out_blank <= mid_blank;
            out_hsync <= mid_hsync;
            out_vsync <= mid_vsync;
            out_red   <= mid_red;
            out_green <= mid_green;
            out_blue  <= mid_blue;

            if bar_draw = '1' then
                if bar_col(3 downto 1) /= "000" and bar_col(3 downto 1) /= "111" then
                    if peak > bar_line then
                        if peak > 60 then
                            out_red(out_red'high) <= '1';
                        else
                            out_green(out_green'high) <= '1';
                        end if;
                    end if;
                    
                    if level = bar_line then
                        out_red   <= (others => '1');
                        out_green <= (others => '1');
                        out_blue  <= (others => '1');
                    end if;
                end if; 
            end if;

            -----------------------------------------------------------------------------
            -- the mid_* signals contain the video with the box drawn to house the meters
            -----------------------------------------------------------------------------
            mid_blank <= in_blank;
            mid_hsync <= in_hsync;
            mid_vsync <= in_vsync;
            mid_red   <= in_red;
            mid_green <= in_green;
            mid_blue  <= in_blue;
            --------------------------------------------------
            -- For working out if we need to draw colour bars
            --------------------------------------------------
            bar_draw <= '0';
            bar_col   <= unsigned(col_count(6 downto 0))-1;
            bar_line  <= to_unsigned(64,6)-unsigned(line_count(5 downto 0));
            
            -----------------------------------------------------------------------------
            -- Retreive the levels for the bar. There is an 
            -- off-by-one error hidden by the bar boarder.
            -----------------------------------------------------------------------------
            level <= levels(to_integer(col_count(6 downto 4)));
            peak  <= peaks(to_integer(col_count(6 downto 4)))(7 downto 2);
            
            -------------------------------------------------------
            -- Halve the intensity of the area where the meters are.
            -------------------------------------------------------
            if col_count > 0 and  col_count < 129 and line_count > 0 and line_count < 65 then
                bar_draw <= '1';
            end if;   

            if col_count > 0 and col_count < 129 and line_count > 0 and line_count < 65 then
                mid_red   <= "0" & in_red(in_red'high downto 1);
                mid_green <= "0" & in_green(in_green'high downto 1);
                mid_blue  <= "0" & in_blue(in_blue'high downto 1);
            end if;

            -- Draw bounding box left/right sides
            if (col_count = 0 or col_count = 129) and line_count < 66 then
                mid_red   <= (others => '1');
                mid_green <= (others => '1');
                mid_blue  <= (others => '1');
            end if; 
            -- Draw bounding box top/bottom sides
            if (line_count = 0 or line_count = 65) and col_count < 130 then
                mid_red   <= (others => '1');
                mid_green <= (others => '1');
                mid_blue  <= (others => '1');
            end if; 
            

            -- Increment the column count on when active pixels are seen 
            if in_blank = '0' then
                col_count <= col_count + 1;
            end if;

            -- The end of active video is used to increment the line count           
            if last_blank = '0' and in_blank = '1' then
                if is_interlaced = '1' then
                    line_count <= line_count + 2;
                else
                    line_count <= line_count + 1;
                end if;
                col_count <= (others => '0');
            end if; 
                        
            -- Reset the line count on falling vsync
            if last_vsync = '1'  and in_vsync = '0' then
                if is_interlaced = '1' and is_second_field = '1' then
                    line_count <= (0 => '1', others => '0');
                else
                    line_count <= (others => '0');
                end if;
            end if;
            -- remember the hsync and vsync values
            last_vsync <= in_vsync;
            last_hsync <= in_hsync;
            last_blank <= in_blank;
        end if;
    end process;
end Behavioral;


================================================
FILE: src/audio_to_db.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name: audio_to_db - Behavioral
--
-- Description: Calcuate the approximate DB level of an audio signal, with a 
--              return of 63 indicating 0db, (e.g. 3 = -60fb)
-- 
------------------------------------------------------------------------------------
-- 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 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 audio_to_db;

architecture Behavioral of audio_to_db is

    signal s7_sample  : unsigned (23 downto 0);
    signal s7_de      : STD_LOGIC;
    signal s7_channel : STD_LOGIC_VECTOR (2 downto 0);
    signal s7_level   : unsigned( 7 downto 0);

    signal s6_sample  : unsigned (23 downto 0);
    signal s6_de      : STD_LOGIC;
    signal s6_channel : STD_LOGIC_VECTOR (2 downto 0);
    signal s6_level   : unsigned( 7 downto 0);

    signal s5_sample  : unsigned (23 downto 0);
    signal s5_de      : STD_LOGIC;
    signal s5_channel : STD_LOGIC_VECTOR (2 downto 0);
    signal s5_level   : unsigned( 7 downto 0);

    signal s4_sample  : unsigned (23 downto 0);
    signal s4_de      : STD_LOGIC;
    signal s4_channel : STD_LOGIC_VECTOR (2 downto 0);
    signal s4_level   : unsigned( 7 downto 0);

    signal s3_sample  : unsigned (23 downto 0);
    signal s3_de      : STD_LOGIC;
    signal s3_channel : STD_LOGIC_VECTOR (2 downto 0);
    signal s3_level   : unsigned( 7 downto 0);

    signal s2_sample  : unsigned (23 downto 0);
    signal s2_de      : STD_LOGIC;
    signal s2_channel : STD_LOGIC_VECTOR (2 downto 0);
    signal s2_level   : unsigned( 7 downto 0);

    signal s1_sample  : unsigned (23 downto 0);
    signal s1_de      : STD_LOGIC;
    signal s1_channel : STD_LOGIC_VECTOR (2 downto 0);
begin

process(clk)
    begin
        if rising_edge(clk) then
            out_channel <= s7_channel;
            out_de      <= s7_de;
            if s7_level(7 downto 6) = "00" then
                out_level <= std_logic_vector(to_unsigned(63,6)-s7_level(5 downto 0));
            else
                out_level <= (others => '0');
            end if;
            
            -- Finally the last stage to get a db level
            s7_channel <= s6_channel;
            s7_de      <= s6_de;
            if s6_sample(22 downto 15) < 72 then
                s7_level <= s6_level + 5;
            elsif s6_sample(22 downto 15) < 81 then
                s7_level <= s6_level + 4;
            elsif s6_sample(22 downto 15) < 91 then
                s7_level <= s6_level + 3;
            elsif s6_sample(22 downto 15) < 102 then
                s7_level <= s6_level + 2;
            elsif s6_sample(22 downto 15) < 114 then
                s7_level <= s6_level + 1;
            else
                s7_level <= s6_level + 1;
            end if;
                        
            -- Stage 5 - shift up 2 bits if needed(bit 23 of sample will be 0)
            s6_channel <= s5_channel;
            s6_de      <= s5_de;
            if s5_sample(23 downto 22) = "00" then
                s6_sample <= s5_sample(22 downto 0) & "0";
                s6_level  <= s5_level + to_unsigned(6,8);
            else
                s6_sample <= s5_sample;
                s6_level  <= s5_level;
            end if; 
    
            -- Stage 5 - shift up 2 bits if needed(bit 23 of sample will be 0)
            s5_channel <= s4_channel;
            s5_de      <= s4_de;
            if s4_sample(23 downto 21) = "000" then
                s5_sample <= s4_sample(21 downto 0) & "00";
                s5_level  <= s4_level + to_unsigned(12,8);
            else
                s5_sample <= s4_sample;
                s5_level  <= s4_level;
            end if; 
        
            -- Stage 4 - shift up 4 bits if needed(bit 23 of sample will be 0)
            s4_channel <= s3_channel;
            s4_de      <= s3_de;
            if s3_sample(23 downto 19) = "00000" then
                s4_sample <= s3_sample(19 downto 0) & "0000";
                s4_level  <= s3_level + to_unsigned(24,8);
            else
                s4_sample <= s3_sample;
                s4_level  <= s3_level;
            end if; 

            -- Stage 3 - shift up 4 bits if needed(bit 23 of sample will be 0)
            s3_channel <= s2_channel;
            s3_de      <= s2_de;
            if s2_sample(23 downto 19) = "00000" then
                s3_sample <= s2_sample(19 downto 0) & "0000";
                s3_level  <= s2_level + to_unsigned(24,8);
            else
                s3_sample <= s2_sample;
                s3_level  <= s2_level;
            end if; 

            -- Stage 2 - shift up 4 bits if needed(bit 23 of sample will be 0)
            s2_channel <= s1_channel;
            s2_de      <= s1_de;
            if s1_sample(23 downto 19) = "00000" then
                s2_sample <= s1_sample(19 downto 0) & "0000";
                s2_level  <= to_unsigned(24,8);
            else
                s2_sample <= s1_sample;
                s2_level  <= to_unsigned(0,8);
            end if; 
             
            --- Stage 1 - remove any sign.
            s1_channel <= in_channel;
            s1_de      <= in_de;
            if in_sample(23) = '1' then
                s1_sample  <= to_unsigned(0,24) - unsigned(in_sample);
            else
                s1_sample  <= unsigned(in_sample);
            end if;
        end if;
    end process;

end Behavioral;


================================================
FILE: src/conversion_to_RGB.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: conversion_YCbCr_to_RGB - Behavioral
--
-- Description: Convert from RGB, studio level RGB or YCbCr to full range RGB
-- 
--              Designed to take the same amount of time regardless of conversion 
--              being performed.  
----------------------------------------------------------------------------------
-- When using 12-bit studio range inputs and the HD colourspace
--
-- R = (Y-64)*1.164 + (Cb-2048) *0.090 + (Cr-2048)*1.793
-- G = (Y-64)*1.164 - (Cb-2048) *0.213 - (Cr-2048)*0.533
-- B = (Y-64)*1.164 + (Cb-2048) *2.112 + (Cr-2048)*0.000
--
-- To avoid the problems with signed/unsigned multiplication this
-- has been rearranged to 
--
-- R = Y*1.164 + Cb*0.090 + Cr*1.793 - 64*1.164 - 2048*0.090 - 2048*1.793
-- G = Y*1.164 - Cb*0.213 - Cr*0.533 - 64*1.164 + 2048*0.213 + 2048*0.533
-- B = Y*1.164 + Cb*2.112 + Cr*0.000 - 64*1.164 - 2048*2.112 - 2048*0.000
--
-- And then all the decimals have been scaled by 4096 This then only requires   
-- five multipliers (as two are zero and three others are identical.
------------------------------------------------------------------------------------
-- 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 conversion_to_RGB is
    port ( clk      : in std_Logic;
           input_is_YCbCr : in std_Logic;
           input_is_sRGB  : 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 entity;

architecture Behavioral of conversion_to_RGB is
    ------------------------------
    -- For the pipeline 
    ------------------------------
    signal s1_blank : std_logic;
    signal s1_hsync : std_logic;
    signal s1_vsync : std_logic;
    signal s1_U     : std_logic_vector(12 downto 0);  -- B or Cb, plus underflow guard bit
    signal s1_V     : std_logic_vector(12 downto 0);  -- G or Y, plus underflow guard bit
    signal s1_W     : std_logic_vector(12 downto 0);  -- R or Cr, plus underflow guard bit

    signal s2_blank : std_logic;
    signal s2_hsync : std_logic;
    signal s2_vsync : std_logic;
    signal s2_U     : std_logic_vector(12 downto 0);  -- B or Cb, plus overflow guard bit
    signal s2_V     : std_logic_vector(12 downto 0);  -- G or Y, plus overflow guard bit
    signal s2_W     : std_logic_vector(12 downto 0);  -- R or Cr, plus overflow guard bit

    ------------------------------
    -- For Calculation
    ------------------------------
    signal a     : unsigned(26 downto 0) := (others => '0');
    signal b     : unsigned(26 downto 0) := (others => '0');
    signal c     : unsigned(26 downto 0) := (others => '0');
    signal d     : unsigned(26 downto 0) := (others => '0');
    signal e     : unsigned(26 downto 0) := (others => '0');
    signal R_raw : unsigned(26 downto 0) := (others => '0');
    signal G_raw : unsigned(26 downto 0) := (others => '0');
    signal B_raw : unsigned(26 downto 0) := (others => '0');
begin
clk_proc: process(clk)
   begin
      if rising_edge(clk) then
         -----------------------------------------------
         -- Step 3: clamp the result
         -----------------------------------------------
         out_blank <= s2_blank;
         out_hsync <= s2_hsync;
         out_vsync <= s2_vsync;
         if input_is_YCbCr = '0' then
            -- trap overflows form prior stage
            if s2_U(s2_U'high) = '0' then
                out_B     <= s2_U(s2_U'high-1 downto 0);
            else 
                out_B     <= (others => '1');
            end if;
            
            if s2_V(s2_V'high) = '0' then
                out_G     <= s2_V(s2_V'high-1 downto 0); 
            else 
                out_G     <= (others => '1');
            end if;
            
            if s2_W(s2_W'high) = '0' then
                out_R     <= s2_W(s2_W'high-1 downto 0); 
            else 
                out_R     <= (others => '1');
            end if;
         else   
            case R_raw(R_raw'high-1 downto R_raw'high-2) is
                when "00"   => out_R <= std_logic_vector(R_raw(R_raw'high-3 downto R_raw'high-14)); -- In range
                when "01"   => out_R <= (others => '1');                          -- Overflow
                when others => out_R <= (others => '0');                          -- Underflow
             end case;
                
            case G_raw(G_raw'high-1 downto G_raw'high-2) is
                when "00"   => out_G <= std_logic_vector(G_raw(G_raw'high-3 downto G_raw'high-14)); -- In range
                when "01"   => out_G <= (others => '1');                          -- Overflow
                when others => out_G <= (others => '0');                          -- Underflow
             end case;
                
            case B_raw(B_raw'high-1 downto B_raw'high-2) is
                when "00"   => out_B <= std_logic_vector(B_raw(B_raw'high-3 downto B_raw'high-14)); -- In range
                when "01"   => out_B <= (others => '1');                          -- Overflow
                when others => out_B <= (others => '0');                          -- Underflow
             end case;
         end if;
         -------------------------------------------------
         -- Step 2: Add the partial results and remove the
         -- offset introduced by the use of studio range
         -------------------------------------------------
         s2_blank <= s1_blank;
         s2_hsync <= s1_hsync;
         s2_vsync <= s1_vsync;
         if input_is_sRGB = '1' then
            -- Trap underflows from prior stage
            if s1_U(s1_U'high) = '0' then
                s2_U     <= std_logic_vector(unsigned(s1_U) + unsigned(s1_U(s1_U'high downto 5)));
            else
                s2_U  <= (others => '0');
            end if; 

            if s1_V(s1_V'high) = '0' then
                s2_V     <= std_logic_vector(unsigned(s1_V) + unsigned(s1_V(s1_V'high downto 5)));   
            else
                s2_V  <= (others => '0');
            end if;
             
            if s1_W(s1_W'high) = '0' then
                s2_W     <= std_logic_vector(unsigned(s1_W) + unsigned(s1_W(s1_W'high downto 5)));
            else
                s2_W  <= (others => '0');
            end if; 
         else
            s2_U <= s1_U;
            s2_V <= s1_V;
            s2_W <= s1_W;
         end if;  
         R_raw <= a + d     - to_unsigned(4767*256 +    0*2048 + 7344*2048, 27);
         G_raw <= a - b - e + to_unsigned(-4767*256 +  872*2048 + 2183*2048, 27);
         B_raw <= a + c     - to_unsigned(4767*256 + 8650*2048 +    0*2048, 27);
  
         -------------------------------------------------
         -- Step 1: Multiply the incoming values by the   
         -- Conversion coefficients
         -------------------------------------------------
         s1_blank <= in_blank;
         s1_hsync <= in_hsync;
         s1_vsync <= in_vsync;
         if input_is_sRGB = '1' then
             s1_U     <= std_logic_vector(unsigned('0' & in_U) - 256); 
             s1_V     <= std_logic_vector(unsigned('0' & in_V) - 256);
             s1_W     <= std_logic_vector(unsigned('0' & in_W) - 256);
         else
             s1_U     <= '0' & in_U; 
             s1_V     <= '0' & in_V; 
             s1_W     <= '0' & in_W;
         end if; 
         a <= unsigned(in_V) * to_unsigned(4767,15); -- 1.164 * 2^12
         b <= unsigned(in_U) * to_unsigned( 872,15); -- 0.213 * 2^12
         c <= unsigned(in_U) * to_unsigned(8650,15); -- 2.112 * 2^12
         d <= unsigned(in_W) * to_unsigned(7344,15); -- 1.793 * 2^12
         e <= unsigned(in_W) * to_unsigned(2183,15); -- 0.533 * 2^12
      end if;
   end process;
end architecture;


================================================
FILE: src/deserialiser_1_to_10.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: deserialiser_1_to_10 - Behavioral
--
-- Description: A 10-to-1 deserialiser for the Artix 7   
-- 
------------------------------------------------------------------------------------
-- 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 deserialiser_1_to_10 is
    Port ( clk_mgmt    : in  std_logic;
           delay_ce    : in  std_logic;
           delay_count : in  std_logic_vector (4 downto 0);
           
           ce          : in  STD_LOGIC;
           clk         : in  std_logic;
           clk_x1      : in  std_logic;
           bitslip     : in  std_logic;
           clk_x5      : in  std_logic;
           serial      : in  std_logic;
           reset       : in  std_logic;
           data        : out std_logic_vector (9 downto 0));
end deserialiser_1_to_10;

architecture Behavioral of deserialiser_1_to_10 is
    signal delayed : std_logic := '0';
    signal shift1  : std_logic := '0';
    signal shift2  : std_logic := '0';
    signal clkb    : std_logic := '1';
    attribute IODELAY_GROUP : STRING;
    attribute IODELAY_GROUP of IDELAYE2_inst: label is "idelay_group";

begin

IDELAYE2_inst : IDELAYE2
    generic map (
          CINVCTRL_SEL          => "FALSE",
          DELAY_SRC             => "DATAIN",
          HIGH_PERFORMANCE_MODE => "TRUE",
          IDELAY_TYPE           => "VAR_LOAD",
          IDELAY_VALUE          => 0,
          PIPE_SEL              => "FALSE",
          REFCLK_FREQUENCY      => 200.0,
          SIGNAL_PATTERN        => "DATA"
    )
    port map (
          DATAIN      => serial,
          IDATAIN     => '0',
          DATAOUT     => delayed,
          --
          CNTVALUEOUT => open,
          C           => clk,
          CE          => delay_ce,
          CINVCTRL    => '0',
          CNTVALUEIN  => delay_count,
          INC         => '0',
          LD          => '1',
          LDPIPEEN    => '0',
          REGRST      => '0'
    );
    clkb <= not clk_x5;

ISERDESE2_master : ISERDESE2
   generic map (
      DATA_RATE         => "DDR",
      DATA_WIDTH        => 10,
      DYN_CLKDIV_INV_EN => "FALSE",
      DYN_CLK_INV_EN    => "FALSE",
      INIT_Q1 => '0', INIT_Q2 => '0', INIT_Q3 => '0', INIT_Q4 => '0',
      INTERFACE_TYPE    => "NETWORKING",
      IOBDELAY          => "IFD",
      NUM_CE            => 1,
      OFB_USED          => "FALSE",
      SERDES_MODE       => "MASTER",
      SRVAL_Q1 => '0', SRVAL_Q2 => '0', SRVAL_Q3 => '0', SRVAL_Q4 => '0' 
   )
   port map (
      O => open,
      Q1 => data(9), Q2 => data(8), Q3 => data(7), Q4 => data(6),
      Q5 => data(5), Q6 => data(4), Q7 => data(3), Q8 => data(2),
      SHIFTOUT1 => shift1, SHIFTOUT2 => shift2,
      BITSLIP   => bitslip,
      CE1 => ce, CE2 => '1',
      CLKDIVP      => '0',
      CLK          => clk_x5,
      CLKB         => clkb,
      CLKDIV       => clk_x1,
      OCLK         => '0', 
      DYNCLKDIVSEL => '0',
      DYNCLKSEL    => '0',
      D            => '0',
      DDLY         => delayed,
      OFB          => '0',
      OCLKB        => '0',
      RST          => reset,
      SHIFTIN1     => '0',
      SHIFTIN2     => '0' 
   );
               
ISERDESE2_slave : ISERDESE2
   generic map (
      DATA_RATE         => "DDR",
      DATA_WIDTH        => 10,
      DYN_CLKDIV_INV_EN => "FALSE",
      DYN_CLK_INV_EN    => "FALSE",
      INIT_Q1 => '0', INIT_Q2 => '0', INIT_Q3 => '0', INIT_Q4 => '0',
      INTERFACE_TYPE    => "NETWORKING",
      IOBDELAY          => "IFD",
      NUM_CE            => 1,
      OFB_USED          => "FALSE",
      SERDES_MODE       => "SLAVE",  
      SRVAL_Q1 => '0', SRVAL_Q2 => '0', SRVAL_Q3 => '0', SRVAL_Q4 => '0' 
   )
   port map (
      O => open,
      Q1 => open, Q2 => open, Q3 => data(1), Q4 => data(0),
      Q5 => open, Q6 => open, Q7 => open,    Q8 => open,
      SHIFTOUT1 => open, SHIFTOUT2 => open,
      BITSLIP   => bitslip,
      CE1 => ce, CE2 => '1',
      CLKDIVP      => '0',
      CLK          => CLK_x5,
      CLKB         => clkb,
      CLKDIV       => clk_x1,
      OCLK         => '0', 
      DYNCLKDIVSEL => '0',
      DYNCLKSEL    => '0',
      D            => '0',
      DDLY         => '0',
      OFB          => '0',
      OCLKB        => '0',
      RST          => reset,
      SHIFTIN1     => shift1,
      SHIFTIN2     => shift2 
   );
end Behavioral;

================================================
FILE: src/detect_interlace.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: detect_interlace - Behavioral
--
-- Description: Detect if the source is interlaced, and report what field is 
--              being processed
-- 
-- Will need to make allowances for interlaced sources!
------------------------------------------------------------------------------------
-- 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 detect_interlace is
    Port ( clk             : in STD_LOGIC;
           hsync           : in std_logic;
           vsync           : in std_logic;
    	   is_interlaced   : out std_logic;
	   	   is_second_field : out std_logic);
end entity;

architecture Behavioral of detect_interlace is
	signal last_vsync     : std_logic := '0';
	signal last_hsync     : std_logic := '0';
	signal first_quarter  : unsigned(11 downto 0) := (others => '0');
	signal last_quarter   : unsigned(11 downto 0) := (others => '0');
	signal hcount         : unsigned(11 downto 0) := (others => '0');
	signal last_vsync_pos : unsigned(11 downto 0) := (others => '0');
	signal second_field   : std_logic := '0';
begin
clk_proc: process(clk)
	begin
		if rising_edge(clk) then
			if last_vsync = '0' and vsync = '1' then
				is_second_field <= '0';
				if hcount > first_quarter and hcount < last_quarter then
					-- The second field of an interlaced 
                           -- frame is indicated when the vsync is
	                      -- asserted in the middle of the scan line.
					--
					-- Also add a little check for a misbehaving source
					if last_vsync_pos /= hcount then
						is_interlaced   <= '1';
						is_second_field <= '1';
						second_field    <= '1';
					else
						is_interlaced   <= '1';
						is_second_field <= '1';
						second_field    <= '1';
					end if;

				else
					-- If we see two 'field 1's in a row we 
					-- switch back to indicating an 
                    -- uninterlaced source
					if second_field = '0' then
						is_interlaced <= '0';
					end if;									
					is_second_field <= '0';
					second_field    <= '0';
				end if;
				last_vsync_pos <= hcount;
			else
			end if;

			if last_hsync = '0' and hsync = '1' then
				hcount <= (others => '0');
				first_quarter <= "00" & hcount(11 downto 2);
				last_quarter <= hcount+1-hcount(11 downto 2);
			else
				hcount <= hcount +1;
			end if;
			last_vsync <= vsync;
			last_hsync <= hsync;
		end if;
	end process;
end architecture;
		

================================================
FILE: src/dvid_output.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name: DVID_output - Behavioral
--
-- Description: Convert a stream of pixels into a DVID output 
-- 
------------------------------------------------------------------------------------
-- 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;

library UNISIM;
use UNISIM.VComponents.all;

entity DVID_output is
    Port ( 
        pixel_clk       : in std_logic;  -- Driven by BUFG
        pixel_io_clk_x1 : in std_logic;  -- Driven by BUFIO
        pixel_io_clk_x5 : in std_logic;  -- Driven by BUFIO
        
        -- VGA Signals
        vga_blank    : in  std_logic;
        vga_hsync    : in  std_logic;
        vga_vsync    : in  std_logic;
        vga_red      : in  std_logic_vector(7 downto 0);
        vga_blue     : in  std_logic_vector(7 downto 0);
        vga_green    : in  std_logic_vector(7 downto 0);
        data_valid   : in  std_logic;
        
        --- DVI-D out
        tmds_out_clk    : out   std_logic;
        tmds_out_ch0    : out   std_logic;
        tmds_out_ch1    : out   std_logic;
        tmds_out_ch2    : out   std_logic
    );
end DVID_output;

architecture Behavioral of DVID_output is

   component tmds_encoder is
   Port ( clk     : in  std_logic;
          data    : in  std_logic_vector (7 downto 0);
          c       : in  std_logic_vector (1 downto 0);
          blank   : in  std_logic;
          encoded : out std_logic_vector (9 downto 0));
    end component;

    component serialiser_10_to_1 is
    Port ( clk    : in  std_logic;
           clk_x5 : in  std_logic;
           reset  : in  std_logic;
           data   : in  std_logic_vector (9 downto 0);
           serial : out std_logic);
    end component;

    signal c0_tmds_symbol : std_logic_vector (9 downto 0);
    signal c1_tmds_symbol : std_logic_vector (9 downto 0);
    signal c2_tmds_symbol : std_logic_vector (9 downto 0);

    signal reset_sr       : std_logic_vector (2 downto 0) := (others => '1');
    signal reset          : std_logic := '1';
    
begin
    reset <= reset_sr(0);
    
process(pixel_clk, data_valid)
    begin
        if data_valid = '0' then
           reset_sr <= (others => '1');
        elsif rising_edge(pixel_clk) then
            reset_sr <= '0' & reset_sr(reset_sr'high downto 1); 
        end if;
    end process;
    ---------------------
    -- TMDS Encoders
    ---------------------
c0_tmds: tmds_encoder port map (
        clk     => pixel_clk,
        data    => vga_blue,
        c(1)    => vga_vsync,
        c(0)    => vga_hsync,
        blank   => vga_blank,
        encoded => c0_tmds_symbol);

c1_tmds: tmds_encoder port map (
        clk     => pixel_clk,
        data    => vga_green,
        c       => (others => '0'),
        blank   => vga_blank,
        encoded => c1_tmds_symbol);
        
c2_tmds: tmds_encoder port map (
        clk     => pixel_clk,
        data    => vga_red,
        c       => (others => '0'),
        blank   => vga_blank,
        encoded => c2_tmds_symbol);
    ---------------------
    -- Output serializers
    ---------------------
ser_ch0: serialiser_10_to_1 port map ( 
        clk    => pixel_io_clk_x1,
        clk_x5 => pixel_io_clk_x5,
        reset  => reset,
        data   => c0_tmds_symbol,
        serial => tmds_out_ch0);
        
ser_ch1: serialiser_10_to_1 port map ( 
        clk    => pixel_io_clk_x1,
        clk_x5 => pixel_io_clk_x5,
        reset  => reset,
        data   => c1_tmds_symbol,
        serial => tmds_out_ch1);

ser_ch2: serialiser_10_to_1 port map (
        clk    => pixel_io_clk_x1,
        clk_x5 => pixel_io_clk_x5,
        reset  => reset,
        data   => c2_tmds_symbol,
        serial => tmds_out_ch2);

ser_clk: serialiser_10_to_1 Port map (
        clk    => pixel_io_clk_x1,
        clk_x5 => pixel_io_clk_x5,
        reset  => reset,
        data   => "0000011111",
        serial => tmds_out_clk);

end Behavioral;


================================================
FILE: src/edge_enhance.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hasmter@snap.net.nz> 
-- 
-- Module Name: edge_enhance - Behavioral
--
-- Description: Video edge enhancement 
--
------------------------------------------------------------------------------------
-- 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 edge_enhance is
    Port (  clk            : in STD_LOGIC;
            enable_feature : in std_logic;
            -------------------------------
            -- VGA data recovered from HDMI
            -------------------------------
            in_blank  : in std_logic;
            in_hsync  : in std_logic;
            in_vsync  : in std_logic;
            in_red    : in std_logic_vector(7 downto 0);
            in_green  : in std_logic_vector(7 downto 0);
            in_blue   : in std_logic_vector(7 downto 0);
            
            -----------------------------------
            -- VGA data to be converted to HDMI
            -----------------------------------
            out_blank : out std_logic;
            out_hsync : out std_logic;
            out_vsync : out std_logic;
            out_red   : out std_logic_vector(7 downto 0);
            out_green : out std_logic_vector(7 downto 0);
            out_blue  : out std_logic_vector(7 downto 0));
end edge_enhance;

architecture Behavioral of edge_enhance is
    component line_delay is
    Port ( clk : in STD_LOGIC;
           -------------------------------
           -- VGA data recovered from HDMI
           -------------------------------
           in_blank  : in std_logic;
           in_hsync  : in std_logic;
           in_vsync  : in std_logic;
           in_red    : in std_logic_vector(7 downto 0);
           in_green  : in std_logic_vector(7 downto 0);
           in_blue   : in std_logic_vector(7 downto 0);
     
           -----------------------------------
           -- VGA data to be converted to HDMI
           -----------------------------------
           out_blank : out std_logic;
           out_hsync : out std_logic;
           out_vsync : out std_logic;
           out_red   : out std_logic_vector(7 downto 0);
           out_green : out std_logic_vector(7 downto 0);
           out_blue  : out std_logic_vector(7 downto 0));
    end component;
    type a_bits is array(0 to 8) of std_logic;
    type a_component is array(0 to 8) of std_logic_vector(7 downto 0);
    signal blanks : a_bits;
    signal hsyncs : a_bits;
    signal vsyncs : a_bits;
    signal reds   : a_component;
    signal greens : a_component;
    signal blues  : a_component;

    signal bypass_1_blank : std_logic := '0';
    signal bypass_1_hsync : std_logic := '0';
    signal bypass_1_vsync : std_logic := '0';
    signal bypass_1_red   : std_logic_vector(7 downto 0) := (others => '0');
    signal bypass_1_blue  : std_logic_vector(7 downto 0) := (others => '0');
    signal bypass_1_green : std_logic_vector(7 downto 0) := (others => '0');

    signal bypass_2_blank : std_logic := '0';
    signal bypass_2_hsync : std_logic := '0';
    signal bypass_2_vsync : std_logic := '0';
    signal bypass_2_red   : std_logic_vector(7 downto 0) := (others => '0');
    signal bypass_2_blue  : std_logic_vector(7 downto 0) := (others => '0');
    signal bypass_2_green : std_logic_vector(7 downto 0) := (others => '0');
    
    signal bypass_3_blank : std_logic := '0';
    signal bypass_3_hsync : std_logic := '0';
    signal bypass_3_vsync : std_logic := '0';
    signal bypass_3_red   : std_logic_vector(7 downto 0) := (others => '0');
    signal bypass_3_blue  : std_logic_vector(7 downto 0) := (others => '0');
    signal bypass_3_green : std_logic_vector(7 downto 0) := (others => '0');

    signal sobel_3_hsync  : std_logic := '0';
    signal sobel_3_blank  : std_logic := '0';
    signal sobel_3_vsync  : std_logic := '0';
    signal sobel_3_red    : unsigned(12 downto 0) := (others => '0');
    signal sobel_3_green  : unsigned(12 downto 0) := (others => '0');
    signal sobel_3_blue   : unsigned(12 downto 0) := (others => '0');
    
    signal sobel_2_hsync   : std_logic := '0';
    signal sobel_2_blank   : std_logic := '0';
    signal sobel_2_vsync   : std_logic := '0';
    signal sobel_2_red_x   : unsigned(11 downto 0) := (others => '0');
    signal sobel_2_red_y   : unsigned(11 downto 0) := (others => '0');
    signal sobel_2_green_x : unsigned(11 downto 0) := (others => '0');
    signal sobel_2_green_y : unsigned(11 downto 0) := (others => '0');
    signal sobel_2_blue_x  : unsigned(11 downto 0) := (others => '0');
    signal sobel_2_blue_y  : unsigned(11 downto 0) := (others => '0');

    signal sobel_1_hsync        : std_logic := '0';
    signal sobel_1_blank        : std_logic := '0';
    signal sobel_1_vsync        : std_logic := '0';
    signal sobel_1_red_left     : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_red_right    : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_red_top      : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_red_bottom   : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_green_left   : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_green_right  : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_green_top    : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_green_bottom : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_blue_left    : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_blue_right   : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_blue_top     : unsigned(11 downto 0) := (others => '0');
    signal sobel_1_blue_bottom  : unsigned(11 downto 0) := (others => '0');
begin
    blanks(0)  <= in_blank;
    hsyncs(0)  <= in_hsync;
    vsyncs(0)  <= in_vsync;
    reds(0)    <= in_red;
    greens(0)  <= in_green;
    blues(0)   <= in_blue;

i_line_delay_1: line_delay  Port map ( 
        clk       => clk,
        in_blank  => blanks(0),
        in_hsync  => hsyncs(0),
        in_vsync  => vsyncs(0),
        in_red    => reds(0),
        in_green  => greens(0),
        in_blue   => blues(0),

        out_blank => blanks(3), 
        out_hsync => hsyncs(3),
        out_vsync => vsyncs(3), 
        out_red   => reds(3),
        out_green => greens(3), 
        out_blue  => blues(3)  
    );

i_line_delay_2: line_delay  Port map ( 
        clk       => clk,
        in_blank  => blanks(3),
        in_hsync  => hsyncs(3),
        in_vsync  => vsyncs(3),
        in_red    => reds(3),
        in_green  => greens(3),
        in_blue   => blues(3),

        out_blank => blanks(6), 
        out_hsync => hsyncs(6),
        out_vsync => vsyncs(6), 
        out_red   => reds(6),
        out_green => greens(6), 
        out_blue  => blues(6)  
    );

process(clk)
    begin
        if rising_edge(clk) then
            if enable_feature = '1' then
                out_hsync <= sobel_3_hsync;
                out_blank <= sobel_3_blank;
                out_vsync <= sobel_3_vsync;

                if sobel_3_red(12 downto 12) = "0" then
                    out_red   <= std_logic_vector(sobel_3_red(11 downto 4));
                else
                    out_red   <= (others => '1');
                end if;

                if sobel_3_green(12 downto 12) = "0" then
                    out_green   <= std_logic_vector(sobel_3_green(11 downto 4));
                else
                    out_green   <= (others => '1');
                end if;

                if sobel_3_blue(12 downto 12) = "0" then
                    out_blue   <= std_logic_vector(sobel_3_blue(11 downto 4));
                else
                    out_blue   <= (others => '1');
                end if;
            else
                out_hsync <= bypass_3_hsync;
                out_blank <= bypass_3_blank;
                out_vsync <= bypass_3_vsync;
                out_red   <= bypass_3_red;
                out_blue  <= bypass_3_blue;
                out_green <= bypass_3_green;
            end if;

            --------------------------------------
            -- For if we eed to bypass the feature
            --------------------------------------
            bypass_3_blank <= bypass_2_blank;
            bypass_3_hsync <= bypass_2_hsync;
            bypass_3_vsync <= bypass_2_vsync;
            bypass_3_red   <= bypass_2_red;
            bypass_3_blue  <= bypass_2_blue;
            bypass_3_green <= bypass_2_green;

            bypass_2_blank <= bypass_1_blank;
            bypass_2_hsync <= bypass_1_hsync;
            bypass_2_vsync <= bypass_1_vsync;
            bypass_2_red   <= bypass_1_red;
            bypass_2_blue  <= bypass_1_blue;
            bypass_2_green <= bypass_1_green;

            bypass_1_blank <= blanks(4);
            bypass_1_hsync <= hsyncs(4);
            bypass_1_vsync <= vsyncs(4);
            bypass_1_red   <= reds(4);
            bypass_1_blue  <= blues(4);
            bypass_1_green <= greens(4);

            ----------------------------------
            --- Calculating the Sobel operator
            ----------------------------------
            sobel_3_blank <= sobel_2_blank;
            sobel_3_hsync <= sobel_2_hsync;
            sobel_3_vsync <= sobel_2_vsync;
            sobel_3_red   <= ("0" & sobel_2_red_x)   +  sobel_2_red_y;
            sobel_3_green <= ("0" & sobel_2_green_x) +  sobel_2_green_y;
            sobel_3_blue  <= ("0" & sobel_2_blue_x)  +  sobel_2_blue_y;
             
            -- For the red channel
            sobel_2_blank <= sobel_1_blank;
            sobel_2_hsync <= sobel_1_hsync;
            sobel_2_vsync <= sobel_1_vsync;

            if sobel_1_red_left > sobel_1_red_right then
                sobel_2_red_x <= sobel_1_red_left - sobel_1_red_right;
            else
                sobel_2_red_x <= sobel_1_red_right - sobel_1_red_left;
            end if;            
            if sobel_1_red_top > sobel_1_red_bottom then
                sobel_2_red_y <= sobel_1_red_top - sobel_1_red_bottom;
            else
                sobel_2_red_y <= sobel_1_red_bottom - sobel_1_red_top;
            end if;
            
            -- For the green channel
            if sobel_1_green_left > sobel_1_green_right then
                sobel_2_green_x <= sobel_1_green_left - sobel_1_green_right;
            else
                sobel_2_green_x <= sobel_1_green_right - sobel_1_green_left;
            end if;
            if sobel_1_green_top > sobel_1_green_bottom then
                sobel_2_green_y <= sobel_1_green_top - sobel_1_green_bottom;
            else
                sobel_2_green_y <= sobel_1_green_bottom - sobel_1_green_top;
            end if;
            
            -- For the blue channel
            if sobel_1_blue_left > sobel_1_blue_right then
                sobel_2_blue_x <= sobel_1_blue_left - sobel_1_blue_right;
            else
                sobel_2_blue_x <= sobel_1_blue_right - sobel_1_blue_left;
            end if;            
            if sobel_1_blue_top > sobel_1_blue_bottom then
                sobel_2_blue_y <= sobel_1_blue_top - sobel_1_blue_bottom;
            else
                sobel_2_blue_y <= sobel_1_blue_bottom - sobel_1_blue_top;
            end if;

            -- Now for the first stage;            
            sobel_1_blank <= blanks(4);
            sobel_1_hsync <= hsyncs(4);
            sobel_1_vsync <= vsyncs(4);
            -- For the red channel
            sobel_1_red_left   <= ("000" & unsigned(reds(0)) & "0") + ("0000" & unsigned(reds(0))) 
                                + ("000" & unsigned(reds(3)) & "0") + ("0"    & unsigned(reds(3)) & "000")
                                + ("000" & unsigned(reds(6)) & "0") + ("0000" & unsigned(reds(6)));

            sobel_1_red_right  <= ("000" & unsigned(reds(2)) & "0") + ("0000" & unsigned(reds(2))) 
                                + ("000" & unsigned(reds(5)) & "0") + ("0"    & unsigned(reds(5)) & "000") 
                                + ("000" & unsigned(reds(8)) & "0") + ("0000" & unsigned(reds(8)));

            sobel_1_red_top    <= ("000" & unsigned(reds(2)) & "0") + ("0000" & unsigned(reds(2)))       
                                + ("000" & unsigned(reds(1)) & "0") + ("0"    & unsigned(reds(1)) & "000") 
                                + ("000" & unsigned(reds(0)) & "0") + ("0000" & unsigned(reds(0)));

            sobel_1_red_bottom <= ("000" & unsigned(reds(6)) & "0") + ("0000" & unsigned(reds(6)))
                                + ("000" & unsigned(reds(7)) & "0") + ("0"    & unsigned(reds(7)) & "000") 
                                + ("000" & unsigned(reds(8)) & "0") + ("0000" & unsigned(reds(8)));

            -- For the green channel
            sobel_1_green_left   <= ("000" & unsigned(greens(0)) & "0") + ("0000" & unsigned(greens(0))) 
                                  + ("000" & unsigned(greens(3)) & "0") + ("0"    & unsigned(greens(3)) & "000")
                                  + ("000" & unsigned(greens(6)) & "0") + ("0000" & unsigned(greens(6)));

            sobel_1_green_right  <= ("000" & unsigned(greens(2)) & "0") + ("0000" & unsigned(greens(2))) 
                                  + ("000" & unsigned(greens(5)) & "0") + ("0"    & unsigned(greens(5)) & "000") 
                                  + ("000" & unsigned(greens(8)) & "0") + ("0000" & unsigned(greens(8)));

            sobel_1_green_top    <= ("000" & unsigned(greens(2)) & "0") + ("0000" & unsigned(greens(2)))       
                                  + ("000" & unsigned(greens(1)) & "0") + ("0"    & unsigned(greens(1)) & "000") 
                                  + ("000" & unsigned(greens(0)) & "0") + ("0000" & unsigned(greens(0)));

            sobel_1_green_bottom <= ("000" & unsigned(greens(6)) & "0") + ("0000" & unsigned(greens(6)))
                                  + ("000" & unsigned(greens(7)) & "0") + ("0"    & unsigned(greens(7)) & "000") 
                                  + ("000" & unsigned(greens(8)) & "0") + ("0000" & unsigned(greens(8)));
                    
            -- For the blue channel
            sobel_1_blue_left   <= ("000" & unsigned(blues(0)) & "0") + ("0000" & unsigned(blues(0))) 
                                 + ("000" & unsigned(blues(3)) & "0") + ("0"    & unsigned(blues(3)) & "000")
                                 + ("000" & unsigned(blues(6)) & "0") + ("0000" & unsigned(blues(6)));

            sobel_1_blue_right  <= ("000" & unsigned(blues(2)) & "0") + ("0000" & unsigned(blues(2))) 
                                 + ("000" & unsigned(blues(5)) & "0") + ("0"    & unsigned(blues(5)) & "000") 
                                 + ("000" & unsigned(blues(8)) & "0") + ("0000" & unsigned(blues(8)));

            sobel_1_blue_top    <= ("000" & unsigned(blues(2)) & "0") + ("0000" & unsigned(blues(2)))       
                                 + ("000" & unsigned(blues(1)) & "0") + ("0"    & unsigned(blues(1)) & "000") 
                                 + ("000" & unsigned(blues(0)) & "0") + ("0000" & unsigned(blues(0)));

            sobel_1_blue_bottom <= ("000" & unsigned(blues(6)) & "0") + ("0000" & unsigned(blues(6)))
                                 + ("000" & unsigned(blues(7)) & "0") + ("0"    & unsigned(blues(7)) & "000") 
                                 + ("000" & unsigned(blues(8)) & "0") + ("0000" & unsigned(blues(8)));
                    
            --------------------------------------------------------------------
            -- Copy over the short chains that gives us a 3x3 matrix to work with
            ---------------------------------------------------------------------
            -- The bottom row
            blanks(1) <= blanks(0);
            hsyncs(1) <= hsyncs(0);
            vsyncs(1) <= vsyncs(0);
            reds(1)   <= reds(0);
            greens(1) <= greens(0);
            blues(1)  <= blues(0);
        
            blanks(2) <= blanks(1);
            hsyncs(2) <= hsyncs(1);
            vsyncs(2) <= vsyncs(1);
            reds(2)   <= reds(1);
            greens(2) <= greens(1);
            blues(2)  <= blues(1);
            -- The middle row
            blanks(4) <= blanks(3);
            hsyncs(4) <= hsyncs(3);
            vsyncs(4) <= vsyncs(3);
            reds(4)   <= reds(3);
            greens(4) <= greens(3);
            blues(4)  <= blues(3);
        
            blanks(5) <= blanks(4);
            hsyncs(5) <= hsyncs(4);
            vsyncs(5) <= vsyncs(4);
            reds(5)   <= reds(4);
            greens(5) <= greens(4);
            blues(5)  <= blues(4);
        
            -- The top row
            blanks(7) <= blanks(6);
            hsyncs(7) <= hsyncs(6);
            vsyncs(7) <= vsyncs(6);
            reds(7)   <= reds(6);
            greens(7) <= greens(6);
            blues(7)  <= blues(6);
        
            blanks(8) <= blanks(7);
            hsyncs(8) <= hsyncs(7);
            vsyncs(8) <= vsyncs(7);
            reds(8)   <= reds(7);
            greens(8) <= greens(7);
            blues(8)  <= blues(7);
        end if;
    end process;

end Behavioral;


================================================
FILE: src/edid_rom.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Module Name: edid_rom - Behavioral
--
-- Description: A simple EDID ROM, configured for 1920x1080@60Hz, HDMI format.
--
------------------------------------------------------------------------------------
-- 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;

library UNISIM;
use UNISIM.VComponents.all;

entity edid_rom is
   port ( clk      : in    std_logic;
          sclk_raw : in    std_logic;
          sdat_raw : inout std_logic := 'Z';
          edid_debug : out std_logic_vector(2 downto 0) := (others => '0')
  );
end entity;

architecture Behavioral of edid_rom is

   type a_edid_rom is array (0 to 255) of std_logic_vector(7 downto 0);

   signal edid_rom : a_edid_rom := (
      ------- BASE EDID Bytes 0 to 35 -----------------------------
      -- Header
      x"00",x"FF",x"FF",x"FF",x"FF",x"FF",x"FF",x"00",
      -- EISA ID - Manufacturer, Product,
      x"04",x"43", x"07",x"f2", 
      -- EISA ID -Serial
      x"01",x"00",x"00",x"00",
      -- Model/year
      x"FF", x"11",
      -- EDID Version
      x"01", x"04",
      ------------------------------------
      ------------------------------------
      -- Digital Video using DVI, 8 bits
      --- x"81",   -- Checksum 0xB6 
      ------------------------------------
      -- Digital Video using HDMI, 8 bits
      x"A2", -- Checksum 0x95 
      ------------------------------------
      -- Aspect ratio, flag, gamma
      x"4f", x"00", x"78", 
      ------------------------------------      
      -- Features 
      x"3E",
      -- Display x,y Chromaticity V Breaks here!
      x"EE", x"91", x"a3", x"54", x"4c", x"99", x"26", x"0f", x"50", x"54",
      -- Established timings
      x"20", x"00", x"00",
      -- Standard timings
      x"01", x"01", x"01", x"01", x"01", x"01", x"01", x"01", 
      x"01", x"01", x"01", x"01", x"01", x"01", x"01", x"01", 
      ------- End of BASE EDID ---------------------------------

      ----- 18 byte data block 1080p --------
      -- Pixel clock
      x"02",x"3A",
      -- Horizontal 1920 with 280 blanking
      x"80", x"18", x"71",
      -- Vertical 1080 with 45 lines blanking
      x"38", x"2D", x"40",
      -- Horizontal front porch
      x"58",x"2C",
      -- Vertical front porch
      x"04",x"05",
      -- Horizontal and vertical image size
      x"0f", x"48", x"42",
      -- Horizontal and vertical boarder
      x"00", x"00",
      -- Options (non-interlaces, not 3D, syncs...)
      x"1E",

      ----- 18 byte data block 1080i --------
      -- Pixel clock
      x"01",x"1D",
      -- Horizontal 1920 with 280 blanking
      x"80", x"18", x"71",
      -- Vertical 1080 with 45 lines blanking
      x"1C", x"16", x"20",
      -- Horizontal front porch
      x"58",x"2C",
      -- Vertical front porch -- SEEMS WRONG!
      x"25",x"00",
      -- Horizontal and vertical image size
      x"0f", x"48", x"42",
      -- Horizontal and vertical boarder
      x"00", x"00",
      -- Options (non-interlaces, not 3D, syncs...)
      x"9E",

      ----- 18 byte data block 720p --------
      -- Pixel clock
      x"01",x"1D",
      -- Horizontal 1920 with 280 blanking
      x"00", x"72", x"51",
      -- Vertical 1080 with 45 lines blanking
      x"D0", x"1E", x"20",
      -- Horizontal front porch
      x"6E",x"28",
      -- Vertical front porch -- SEEMS WRONG!
      x"55",x"00",
      -- Horizontal and vertical image size
      x"0f", x"48", x"42",
      -- Horizontal and vertical boarder
      x"00", x"00",
      -- Options (non-interlaces, not 3D, syncs...)
      x"1E",

      ----- 18 byte data block 720p --------
      -- Monitor name ASCII descriptor
      x"00", x"00", x"00", x"FC", x"00",
      -- ASCII name - "ABC LCD47w[lf] "
      x"48", x"61", x"6D", x"73", x"74", x"65", x"72", x"6B",
      x"73", x"0A", x"20", x"20", x"20",

      ----- End of EDID block
      -- Extension flag & checksum
      x"01", x"74",
      
       x"02", x"03", x"18", x"72", x"47", x"90", x"85", x"04", x"03", x"02", x"07", x"06", x"23", x"09", x"07", x"07",
       x"83", x"01", x"00", x"00", x"65", x"03", x"0C", x"00", x"10", x"00", x"8E", x"0A", x"D0", x"8A", x"20", x"E0",
       x"2d", x"10", x"10", x"3E", x"96", x"00", x"1F", x"09", x"00", x"00", x"00", x"18", x"8E", x"0A", x"D0", x"8A",
       x"20", x"E0", x"2D", x"10", x"10", x"3E", x"96", x"00", x"04", x"03", x"00", x"00", x"00", x"18", x"8E", x"0A",
       x"A0", x"14", x"51", x"F0", x"16", x"00", x"26", x"7C", x"43", x"00", x"1F", x"09", x"00", x"00", x"00", x"98",
       x"8E", x"0A", x"A0", x"14", x"51", x"F0", x"16", x"00", x"26", x"7C", x"43", x"00", x"04", x"03", x"00", x"00",
       x"00", x"98", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00",
       x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"00", x"C9"
      
      );

   signal sclk_delay  : std_logic_vector(2 downto 0);
   signal sdat_delay  : unsigned(6 downto 0);
   
   type t_state is (   state_idle, 
                     -- States to support writing the device's address
                     state_start,
                     state_dev7,
                     state_dev6,
                     state_dev5,
                     state_dev4,
                     state_dev3,
                     state_dev2,
                     state_dev1,
                     state_dev0,
                     -- States to support writing the address
                     state_ack_device_write,
                     state_addr7,
                     state_addr6,
                     state_addr5,
                     state_addr4,
                     state_addr3,
                     state_addr2,
                     state_addr1,
                     state_addr0,
                     state_addr_ack,
                     -- States to support the selector device 
                     state_selector_ack_device_write,
                     state_selector_addr7,
                     state_selector_addr6,
                     state_selector_addr5,
                     state_selector_addr4,
                     state_selector_addr3,
                     state_selector_addr2,
                     state_selector_addr1,
                     state_selector_addr0,
                     state_selector_addr_ack,
                     -- States to support reading from the the EDID ROM
                     state_ack_device_read,
                     state_read7,
                     state_read6,
                     state_read5,
                     state_read4,
                     state_read3,
                     state_read2,
                     state_read1,
                     state_read0,
                     state_read_ack);

   signal state           : t_state := state_idle;
   signal data_out_sr     : std_logic_vector(7 downto 0) := (others => '1');
   signal data_shift_reg  : std_logic_vector(7 downto 0) := (others => '0');
   signal addr_reg        : unsigned(7 downto 0) := (others => '0');
   signal selector_reg    : unsigned(7 downto 0) := (others => '0');
   signal data_to_send    : std_logic_vector(7 downto 0) := (others => '0');
   signal data_out_delay  : std_logic_vector(7 downto 0) := (others => '0');
   signal PULL_LOW        : std_logic := '0';
   signal sdat_input      : std_logic := '0';
   signal sdat_delay_last : std_logic := '0';
begin

i_IOBUF: IOBUF
    generic map (
       DRIVE => 12,
       IOSTANDARD => "DEFAULT",
       SLEW => "SLOW")
    port map (
       O  => sdat_input, -- Buffer output
       IO => sdat_raw,   -- Buffer inout port (connect directly to top-level port)
       I  => '0',        -- Buffer input
       T  => data_out_sr(data_out_sr'high)      -- 3-state enable input, high=input, low=output 
    );
    edid_debug(0) <= std_logic(sdat_delay(sdat_delay'high));
    edid_debug(1) <= sclk_raw; 

process(clk)
   begin   
      if rising_edge(clk) then
         
         -- falling edge on SDAT while sclk is held high = START condition
         if sclk_delay(1) = '1' and sclk_delay(0) = '1' and sdat_delay_last  = '1' and sdat_delay(sdat_delay'high) = '0' then
            state <= state_start;
            edid_debug(2) <= '1';
         end if;
         
         -- rising edge on SDAT while sclk is held high = STOP condition
         if sclk_delay(1) = '1' and sclk_delay(0) = '1' and sdat_delay_last = '0' and sdat_delay(sdat_delay'high) = '1' then
            state <= state_idle;
            selector_reg <= (others => '0');
            edid_debug(2) <= '0';
         end if;

         -- rising edge on SCLK - usually a data bit 
         if sclk_delay(1) = '1' and sclk_delay(0) = '0' then
            -- Move data into a shift register
            data_shift_reg <= data_shift_reg(data_shift_reg'high-1 downto 0) & std_logic(sdat_delay(sdat_delay'high));
         end if;
         
         -- falling edge on SCLK - time to change state
         if sclk_delay(1) = '0' and sclk_delay(0) = '1' then
            data_out_sr <= data_out_sr(data_out_sr'high-1 downto 0) & '1'; -- Add Pull up   
            case state is 
               when state_start            => state <= state_dev7;
               when state_dev7             => state <= state_dev6;
               when state_dev6             => state <= state_dev5;
               when state_dev5             => state <= state_dev4;
               when state_dev4             => state <= state_dev3;
               when state_dev3             => state <= state_dev2;
               when state_dev2             => state <= state_dev1;
               when state_dev1             => state <= state_dev0;
               when state_dev0             => if data_shift_reg = x"A1" then
                                                 state <= state_ack_device_read;
                                                 data_out_sr(data_out_sr'high) <= '0'; -- Send Slave ACK
                                              elsif data_shift_reg = x"A0" then
                                                 state <= state_ack_device_write;
                                                 data_out_sr(data_out_sr'high) <= '0'; -- Send Slave ACK
                                              elsif data_shift_reg = x"60" then
                                                 state <= state_selector_ack_device_write;
                                                 data_out_sr(data_out_sr'high) <= '0'; -- Send Slave ACK
                                              else
                                                 state <= state_idle;
                                              end if;               
               when state_ack_device_write => state <= state_addr7;
               when state_addr7            => state <= state_addr6;
               when state_addr6            => state <= state_addr5;
               when state_addr5            => state <= state_addr4;
               when state_addr4            => state <= state_addr3;
               when state_addr3            => state <= state_addr2;
               when state_addr2            => state <= state_addr1;
               when state_addr1            => state <= state_addr0;
               when state_addr0            => state <= state_addr_ack;
                                              addr_reg  <= unsigned(data_shift_reg);
                                              data_out_sr(data_out_sr'high) <= '0'; -- Send Slave ACK
               when state_addr_ack         => state <= state_idle;   -- SLave ACK and ignore any written data
                ------------------------------------
                -- Process the write to the selector
                ------------------------------------
               when state_selector_ack_device_write => state <= state_selector_addr7;
               when state_selector_addr7            => state <= state_selector_addr6;
               when state_selector_addr6            => state <= state_selector_addr5;
               when state_selector_addr5            => state <= state_selector_addr4;
               when state_selector_addr4            => state <= state_selector_addr3;
               when state_selector_addr3            => state <= state_selector_addr2;
               when state_selector_addr2            => state <= state_selector_addr1;
               when state_selector_addr1            => state <= state_selector_addr0;
               when state_selector_addr0            => state <= state_selector_addr_ack;
                                              selector_reg  <= unsigned(data_shift_reg(7 downto 0));
                                              data_out_sr(data_out_sr'high) <= '0'; -- Send Slave ACK
               when state_selector_addr_ack         => state <= state_idle;   -- SLave ACK and ignore any written data
               -------------------------

               when state_ack_device_read  => state <= state_read7;
                                              data_out_sr <=  edid_rom(to_integer(addr_reg));
               when state_read7            => state <= state_read6;
               when state_read6            => state <= state_read5;
               when state_read5            => state <= state_read4;
               when state_read4            => state <= state_read3;
               when state_read3            => state <= state_read2;
               when state_read2            => state <= state_read1;
               when state_read1            => state <= state_read0;
               when state_read0            => state <= state_read_ack; 
               when state_read_ack         => if sdat_delay(sdat_delay'high) = '0' then 
                                                 state <= state_read7;
                                                 data_out_sr <=  edid_rom(to_integer(addr_reg+1));
                                              else 
                                                 state <= state_idle;
                                              end if;                     
                                              addr_reg <= addr_reg+1;
               when others                 => state <= state_idle;
            end case;
         end if;
        sdat_delay_last <= sdat_delay(sdat_delay'high);
         -- Synchronisers for SCLK and SDAT
         sclk_delay <= sclk_raw & sclk_delay(sclk_delay'high downto 1);
         -- Resolve any 'Z' state in simulation - make it pull up. 
         if sdat_input = '0'  then 
            if sdat_delay(sdat_delay'high) = '1' then 
                sdat_delay <= sdat_delay - 1;
            else
                sdat_delay <= (others => '0');
            end if; 
         else
            if sdat_delay(sdat_delay'high) = '0' then 
                 sdat_delay <= sdat_delay + 1;
             else
                 sdat_delay <= (others => '1');
             end if; 
         end if;
      end if;
   end process;
end architecture;

================================================
FILE: src/expand_422_to_444.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: expand_422_to_444 - Behavioral
--
-- Description: Convert incoming 422 data to 444 
-- 
------------------------------------------------------------------------------------
-- 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 expand_422_to_444 is
    Port ( clk : in STD_LOGIC;
        input_is_422 : in std_logic;
        ------------------
        -- Incoming pixels
        ------------------
        in_blank  : in std_logic;
        in_hsync  : in std_logic;
        in_vsync  : in std_logic;
        in_ch2    : in std_logic_vector(7 downto 0);
        in_ch1    : in std_logic_vector(7 downto 0);
        in_ch0    : in std_logic_vector(7 downto 0);
    
        -------------------
        -- Processed pixels
        -------------------
        out_blank : out std_logic;
        out_hsync : out std_logic;
        out_vsync : out std_logic;
        out_U     : out std_logic_vector(11 downto 0);  -- B or Cb
        out_V     : out std_logic_vector(11 downto 0);  -- G or Y
        out_W     : out std_logic_vector(11 downto 0)   -- R or Cr
    );
end expand_422_to_444;

architecture Behavioral of expand_422_to_444 is

    signal in_blank_1 : std_logic := '0';
    signal in_hsync_1 : std_logic := '0';
    signal in_vsync_1 : std_logic := '0';
    signal in_ch0_1   : std_logic_vector(7 downto 0) := (others => '0');
    signal in_ch1_1   : std_logic_vector(7 downto 0) := (others => '0');
    signal in_ch2_1   : std_logic_vector(7 downto 0) := (others => '0');

    signal in_blank_2 : std_logic := '0';
    signal in_hsync_2 : std_logic := '0';
    signal in_vsync_2 : std_logic := '0';
    signal in_ch0_2   : std_logic_vector(7 downto 0) := (others => '0');
    signal in_ch1_2   : std_logic_vector(7 downto 0) := (others => '0');
    signal in_ch2_2   : std_logic_vector(7 downto 0) := (others => '0');

    signal first_of_pair : std_logic := '0';
begin

process(clk) 
    begin
        if rising_edge(clk) then
            if input_is_422 = '1' then
                ------------------------------------------------------
                -- For 422, copy the chroma values between pixel pairs 
                ------------------------------------------------------                
                out_blank <= in_blank_1;
                out_hsync <= in_hsync_1;
                out_vsync <= in_vsync_1;
                if in_blank_1 = '1' then
                    first_of_pair <= '1';
                    out_U     <= in_ch2_1 & in_ch0_1(7 downto 4); -- Cb
                    out_V     <= in_ch1_1 & in_ch0_1(3 downto 0); -- Y
                    out_W     <= in_ch2_1 & in_ch0_1(7 downto 4); -- Cr
                else
                    if first_of_pair = '1' then
                        -- Take Cr from the next pixel
                        first_of_pair <= '0';
                        out_U     <= in_ch2_1 & in_ch0_1(7 downto 4); -- Cb
                        out_V     <= in_ch1_1 & in_ch0_1(3 downto 0); -- Y
                        out_W     <= in_ch2   & in_ch0  (7 downto 4); -- Cr
                    else
                        -- Take Cb from the prior pixel
                        first_of_pair <= '1';
                        out_U     <= in_ch2_2 & in_ch0_2(7 downto 4); -- Cb
                        out_V     <= in_ch1_1 & in_ch0_1(3 downto 0); -- Y
                        out_W     <= in_ch2_1 & in_ch0_1(7 downto 4); -- Cr
                    end if;
                end if;
            else
                ------------------------------------------------------
                -- Minimal processing for 422 (either RGB or YCbCr)
                ------------------------------------------------------
                out_blank <= in_blank_1;
                out_hsync <= in_hsync_1;
                out_vsync <= in_vsync_1;
                out_U     <= in_ch0_1 & "0000";  -- B or Cb  
                out_V     <= in_ch1_1 & "0000";  -- G or Y
                out_W     <= in_ch2_1 & "0000";  -- R or Cr
            end if;
            
            -- Remember the pixel for two cycles
            in_blank_1 <= in_blank;
            in_hsync_1 <= in_hsync;
            in_vsync_1 <= in_vsync;
            in_ch0_1   <= in_ch0;
            in_ch1_1   <= in_ch1;
            in_ch2_1   <= in_ch2;
            
            in_blank_2 <= in_blank_1;
            in_hsync_2 <= in_hsync_1;
            in_vsync_2 <= in_vsync_1;
            in_ch0_2   <= in_ch0_1;
            in_ch1_2   <= in_ch1_1;
            in_ch2_2   <= in_ch2_1;
        end if;    
    end process;
end Behavioral;


================================================
FILE: src/extract_audio_samples.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name: extract_audio_samples - Behavioral
--
-- Description: Extract audio data from the HDMI ADP data 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 extract_audio_samples is
    Port ( clk                 : in STD_LOGIC;
           adp_data_valid      : in STD_LOGIC;
           adp_header_bit      : in STD_LOGIC;
           adp_frame_bit       : in STD_LOGIC;
           adp_subpacket0_bits : in STD_LOGIC_VECTOR (1 downto 0);
           adp_subpacket1_bits : in STD_LOGIC_VECTOR (1 downto 0);
           adp_subpacket2_bits : in STD_LOGIC_VECTOR (1 downto 0);
           adp_subpacket3_bits : in STD_LOGIC_VECTOR (1 downto 0);
           audio_de            : out STD_LOGIC;
           audio_channel       : out STD_LOGIC_VECTOR (2 downto 0);
           audio_sample        : out STD_LOGIC_VECTOR (23 downto 0)
    );
end extract_audio_samples;

architecture Behavioral of extract_audio_samples is
    signal header_bits        : STD_LOGIC_VECTOR (31 downto 0);
    signal frame_bits         : STD_LOGIC_VECTOR (31 downto 0);
    signal subpacket0_bits    : STD_LOGIC_VECTOR (63 downto 0);
    signal subpacket1_bits    : STD_LOGIC_VECTOR (63 downto 0);
    signal subpacket2_bits    : STD_LOGIC_VECTOR (63 downto 0);
    signal subpacket3_bits    : STD_LOGIC_VECTOR (63 downto 0);
    signal grab_other_channel : std_logic := '0';
begin

process(clk)
    begin
        if rising_edge(clk) then
            -----------------------------------------------
            -- Move the incoming bits into a shift register
            -----------------------------------------------
            header_bits     <= adp_header_bit      & header_bits(header_bits'high downto 1);
            frame_bits      <= (adp_frame_bit and adp_data_valid) & frame_bits(frame_bits'high   downto 1);
            subpacket0_bits <= adp_subpacket0_bits & subpacket0_bits(subpacket0_bits'high downto 2);
            subpacket1_bits <= adp_subpacket1_bits & subpacket1_bits(subpacket1_bits'high downto 2);
            subpacket2_bits <= adp_subpacket2_bits & subpacket2_bits(subpacket2_bits'high downto 2);
            subpacket3_bits <= adp_subpacket3_bits & subpacket3_bits(subpacket3_bits'high downto 2);
            
            audio_de      <= '0';

            if grab_other_channel = '1' then
                audio_de           <= header_bits(7);
                audio_channel      <= "001";
                audio_sample       <= subpacket0_bits(45 downto 22);
                grab_other_channel <= '0';
            end if;
            if frame_bits = x"FFFFFFFE" then
                ------------------------------------------------
                -- Check the packet type as being audio samples
                ------------------------------------------------
                if header_bits(7 downto 0) = x"02" then
                    audio_de      <= header_bits(8);
                    audio_channel <= "000";
                    audio_sample  <= subpacket0_bits(23 downto 0);
                    grab_other_channel <= '1';                      
                end if;
            end if;
        end if;
    end process;
    
end Behavioral;


================================================
FILE: src/extract_video_infopacket_data.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: extract_video_infopacket_data - Behavioral
--
-- Description: Extract a couple of fields from the video infopacket, allowin use
--              to correctly convert the incoming pixels into RGB 444 for internal
--              processing.  
-- 
--              Bits 14:13 indicate the colour space and 444 vs 422.
--              Bits 27:26 indicate if the pixels are studio level (16-240) 
--              or full range (0-255)  
-- 
------------------------------------------------------------------------------------
-- 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 extract_video_infopacket_data is
    Port ( clk                 : in STD_LOGIC;
           adp_data_valid      : in STD_LOGIC;
           adp_header_bit      : in STD_LOGIC;
           adp_frame_bit       : in STD_LOGIC;
           adp_subpacket0_bits : in STD_LOGIC_VECTOR (1 downto 0);
           adp_subpacket1_bits : in STD_LOGIC_VECTOR (1 downto 0);
           adp_subpacket2_bits : in STD_LOGIC_VECTOR (1 downto 0);
           adp_subpacket3_bits : in STD_LOGIC_VECTOR (1 downto 0);
           input_is_YCbCr      : out STD_LOGIC;
           input_is_422        : out STD_LOGIC;
           input_is_sRGB       : out STD_LOGIC);
end extract_video_infopacket_data;

architecture Behavioral of extract_video_infopacket_data is
    -- For this usage, we are only interested in four bits that are all in the first
    -- 16 transfers of the 32-bit packets
    signal header_bits     : STD_LOGIC_VECTOR (15 downto 0);
    signal frame_bits      : STD_LOGIC_VECTOR (15 downto 0);
    signal subpacket0_bits : STD_LOGIC_VECTOR (31 downto 0);
    signal updated         : std_logic := '0';
begin

process(clk)
    begin
        if rising_edge(clk) then
            if adp_data_valid = '1' then
                -----------------------------------------------
                -- Move the incoming bits into a shift register
                -----------------------------------------------
                header_bits     <= adp_header_bit      & header_bits(header_bits'high downto 1);
                frame_bits      <= adp_frame_bit       & frame_bits(frame_bits'high   downto 1);
                subpacket0_bits <= adp_subpacket0_bits & subpacket0_bits(subpacket0_bits'high downto 2);
                updated         <= '1';  
            end if;

            ----------------------------------------------------
            -- The 0 in frame bits indicates the start of packet
            ----------------------------------------------------
            if updated = '1' and frame_bits = x"FFFE" then
                -- 82 is the type of packet, 02 is the version
                if header_bits = x"0282" then
                    case subpacket0_bits(14 downto 13) is
                        when "00"   => input_is_YCbCr <= '0'; input_is_422 <= '0';
                        when "01"   => input_is_YCbCr <= '1'; input_is_422 <= '1';
                        when "10"   => input_is_YCbCr <= '1'; input_is_422 <= '0';
                        when others => NULL;
                    end case; 

                    case subpacket0_bits(27 downto 26) is
                        when "01"   => input_is_sRGB <= '1';
                        when others => input_is_sRGB <= '0';
                    end case; 

                end if;
            end if; 
        end if;
    end process;

end Behavioral;


================================================
FILE: src/guidelines.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- Module Name: guidelines - Behavioral
--
-- Description: When enabled, put guidelines on the screen  
-- 
-- 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 guidelines is
    Port ( clk : in STD_LOGIC;
       enable_feature   : in std_logic;
       -------------------------------
       -- VGA data recovered from HDMI
       -------------------------------
       in_blank  : in std_logic;
       in_hsync  : in std_logic;
       in_vsync  : in std_logic;
       in_red    : in std_logic_vector(7 downto 0);
       in_green  : in std_logic_vector(7 downto 0);
       in_blue   : in std_logic_vector(7 downto 0);
       is_interlaced   : in std_logic;
       is_second_field : in std_logic;
        
       -----------------------------------
       -- VGA data to be converted to HDMI
       -----------------------------------
       out_blank : out std_logic;
       out_hsync : out std_logic;
       out_vsync : out std_logic;
       out_red   : out std_logic_vector(7 downto 0);
       out_green : out std_logic_vector(7 downto 0);
       out_blue  : out std_logic_vector(7 downto 0));
end guidelines;

architecture Behavioral of guidelines is
    signal hcount : unsigned(11 downto 0) := (others => '0');
    signal vcount : unsigned(11 downto 0) := (others => '0');
    signal h_size : unsigned(11 downto 0) := (others => '0');
    signal v_size : unsigned(11 downto 0) := (others => '0');
    signal last_blank : std_logic := '0';
    signal last_vsync : std_logic := '0';
begin

process(clk)
    begin
        if rising_edge(clk) then
            out_blank  <= in_blank;
            out_hsync  <= in_hsync;
            out_vsync  <= in_vsync;
            out_red    <= in_red;
            out_green  <= in_green;
            out_blue   <= in_blue;

            if enable_feature = '1' then
                if h_size = 1280 then
                    if hcount = 426 or hcount = 854 then
                        out_red   <= (others => '1');
                        out_green <= (others => '1');
                        out_blue  <= (others => '1');
                    end if; 
                end if; 

                if h_size = 1920 then
                    if hcount = 640 or hcount = 1280 then
                        out_red   <= (others => '1');
                        out_green <= (others => '1');
                        out_blue  <= (others => '1');
                    end if; 
                end if;

                if v_size = 720 then
                    if vcount = 240 or vcount = 480 then
                        out_red   <= (others => '1');
                        out_green <= (others => '1');
                        out_blue  <= (others => '1');
                    end if;
                end if;

                if v_size = 1080 then
                    if is_interlaced = '0' and (vcount = 360 or vcount = 720) then
                        out_red   <= (others => '1');
                        out_green <= (others => '1');
                        out_blue  <= (others => '1');
                    end if;
                    
                    if is_interlaced = '1' and (vcount = 180 or vcount = 360) then
                        out_red   <= (others => '1');
                        out_green <= (others => '1');
                        out_blue  <= (others => '1');
                    end if;
                end if;
            end if;
                            
            -------------------------------------------------------------
            -- Count the number of lines in a frame (not field!!!)
            -------------------------------------------------------------
            if last_blank = '0' and in_blank = '1' then
                vcount <= vcount + 1;
            end if;
            
            -------------------------------------------------------------
            -- Use the falling edge of VSYNC to to capture the number of 
            -- lines on the screen, as the rising edge is where the 
            -- interaced field is detected and can be a bit unstable.
            -------------------------------------------------------------
            if in_vsync = '0' and last_vsync = '1' and is_second_field = '0'then
                vcount <= (others => '0');
                v_size <= vcount;
            end if;

            -------------------------------------------------------------
            -- Count the width of the frame
            -------------------------------------------------------------
            if in_blank = '1' then
                if hcount /= 0 then
                    h_size <= hcount;
                end if;
                hcount <= (others => '0');
            else
                hcount <= hcount + 1;
            end if;
            last_blank <= in_blank;
            last_vsync <= in_vsync;
            if enable_feature = '1' and in_blank = '0' then
            end if; 
        end if;
    end process;
end Behavioral;


================================================
FILE: src/hdmi_design.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer:    Mike Field <hamster@snap.net.nz> 
-- 
-- Create Date: 22.07.2015 21:10:34
-- Module Name: hdmi_design - Behavioral
-- Project Name: 
--
-- Description: Top level of a video processing design 
-- 
------------------------------------------------------------------------------------
-- 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 hdmi_design is
    Port ( 
        clk100    : in STD_LOGIC;
        -- Control signals
        led           : out   std_logic_vector(7 downto 0) :=(others => '0');
        sw            : in    std_logic_vector(7 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);
        -- For dumping symbols
        rs232_tx     : out std_logic      
    );
end hdmi_design;

architecture Behavioral of hdmi_design is
    component hdmi_io is
    Port ( 
        clk100    : in STD_LOGIC;
        -------------------------------
        -- Control signals
        -------------------------------
        clock_locked  : out std_logic;
        data_synced   : out std_logic;
        debug         : out std_logic_vector(7 downto 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);

        pixel_clk     : out std_logic;
        -------------------------------
        -- VGA data recovered from HDMI
        -------------------------------
        in_hdmi_detected : out std_logic;
        in_blank        : out std_logic;
        in_hsync        : out std_logic;
        in_vsync        : out std_logic;
        in_red          : out std_logic_vector(7 downto 0);
        in_green        : out std_logic_vector(7 downto 0);
        in_blue         : out std_logic_vector(7 downto 0);
        is_interlaced   : out std_logic;
        is_second_field : out std_logic;
            
        -------------------------------------
        -- Audio Levels
        -------------------------------------
        audio_channel : out std_logic_vector(2 downto 0);
        audio_de      : out std_logic;
        audio_sample  : out std_logic_vector(23 downto 0);
        
        -----------------------------------
        -- VGA data to be converted to HDMI
        -----------------------------------
        out_blank     : in  std_logic;
        out_hsync     : in  std_logic;
        out_vsync     : in  std_logic;
        out_red       : in  std_logic_vector(7 downto 0);
        out_green     : in  std_logic_vector(7 downto 0);
        out_blue      : in  std_logic_vector(7 downto 0);
        -----------------------------------
        -- For symbol dump or retransmit
        -----------------------------------
        symbol_sync  : out std_logic; -- indicates a fixed reference point in the frame.
        symbol_ch0   : out std_logic_vector(9 downto 0);
        symbol_ch1   : out std_logic_vector(9 downto 0);
        symbol_ch2   : out std_logic_vector(9 downto 0)
    );
    end component;
    signal symbol_sync  : std_logic;
    signal symbol_ch0   : std_logic_vector(9 downto 0);
    signal symbol_ch1   : std_logic_vector(9 downto 0);
    signal symbol_ch2   : std_logic_vector(9 downto 0);
    
    component pixel_processing is
        Port ( clk : in STD_LOGIC;
            switches  : in std_logic_vector(7 downto 0);
            ------------------
            -- Incoming pixels
            ------------------
            in_blank  : in std_logic;
            in_hsync  : in std_logic;
            in_vsync  : in std_logic;
            in_red    : in std_logic_vector(7 downto 0);
            in_green  : in std_logic_vector(7 downto 0);
            in_blue   : in std_logic_vector(7 downto 0);
            is_interlaced   : in  std_logic;
            is_second_field : in  std_logic;
        
            -------------------
            -- Processed pixels
            -------------------
            out_blank : out std_logic;
            out_hsync : out std_logic;
            out_vsync : out std_logic;
            out_red   : out std_logic_vector(7 downto 0);
            out_green : out std_logic_vector(7 downto 0);
            out_blue  : out std_logic_vector(7 downto 0);
                       
            -------------------------------------
            -- Audio samples for metering
            -------------------------------------
            audio_channel : in std_logic_vector(2 downto 0);
            audio_de      : in std_logic;
            audio_sample  : in std_logic_vector(23 downto 0)
    );
    end component;

    component symbol_dump is
        port ( 
            clk          : in std_logic;
            clk100       : in std_logic;
            symbol_sync  : in std_logic; -- indicates a fixed reference point in the frame.
            symbol_ch0   : in std_logic_vector(9 downto 0);
            symbol_ch1   : in std_logic_vector(9 downto 0);
            symbol_ch2   : in std_logic_vector(9 downto 0);
            rs232_tx     : out std_logic);        
    end component;

    signal pixel_clk : std_logic;
    signal in_blank  : std_logic;
    signal in_hsync  : std_logic;
    signal in_vsync  : std_logic;
    signal in_red    : std_logic_vector(7 downto 0);
    signal in_green  : std_logic_vector(7 downto 0);
    signal in_blue   : std_logic_vector(7 downto 0);
    signal is_interlaced   : std_logic;
    signal is_second_field : std_logic;
    signal out_blank : std_logic;
    signal out_hsync : std_logic;
    signal out_vsync : std_logic;
    signal out_red   : std_logic_vector(7 downto 0);
    signal out_green : std_logic_vector(7 downto 0);
    signal out_blue  : std_logic_vector(7 downto 0);

    signal audio_channel : std_logic_vector(2 downto 0);
    signal audio_de      : std_logic;
    signal audio_sample  : std_logic_vector(23 downto 0);

    signal debug : std_logic_vector(7 downto 0);
begin
    debug_pmod <= debug;    
    led        <= debug;
    
i_hdmi_io: hdmi_io port map ( 
        clk100        => clk100,
        ---------------------
        -- Control signals
        ---------------------
        clock_locked     => open,
        data_synced      => open,
        debug            => debug,
        ---------------------
        -- HDMI input signals
        ---------------------
        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_p     => hdmi_rx_p,
        hdmi_rx_n     => hdmi_rx_n,

        ----------------------
        -- HDMI output signals
        ----------------------
        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,     

        
        pixel_clk => pixel_clk,
        -------------------------------
        -- VGA data recovered from HDMI
        -------------------------------
        in_blank        => in_blank,
        in_hsync        => in_hsync,
        in_vsync        => in_vsync,
        in_red          => in_red,
        in_green        => in_green,
        in_blue         => in_blue,
        is_interlaced   => is_interlaced,
        is_second_field => is_second_field,

        -----------------------------------
        -- For symbol dump or retransmit
        -----------------------------------
        audio_channel => audio_channel,
        audio_de      => audio_de,
        audio_sample  => audio_sample,
        
        -----------------------------------
        -- VGA data to be converted to HDMI
        -----------------------------------
        out_blank => out_blank,
        out_hsync => out_hsync,
        out_vsync => out_vsync,
        out_red   => out_red,
        out_green => out_green,
        out_blue  => out_blue,
        
        symbol_sync  => symbol_sync, 
        symbol_ch0   => symbol_ch0,
        symbol_ch1   => symbol_ch1,
        symbol_ch2   => symbol_ch2
    );
    
i_processing: pixel_processing Port map ( 
        clk => pixel_clk,
        switches => sw,
        ------------------
        -- Incoming pixels
        ------------------
        in_blank        => in_blank,
        in_hsync        => in_hsync,
        in_vsync        => in_vsync,
        in_red          => in_red,
        in_green        => in_green,
        in_blue         => in_blue,    
        is_interlaced   => is_interlaced,
        is_second_field => is_second_field,
        audio_channel   => audio_channel,
        audio_de        => audio_de,
        audio_sample    => audio_sample,
        -------------------
        -- Processed pixels
        -------------------
        out_blank => out_blank,
        out_hsync => out_hsync,
        out_vsync => out_vsync,
        out_red   => out_red,
        out_green => out_green,
        out_blue  => out_blue
    );

    -- Swap to this if you want to capture the HDMI symbols
    -- and send them up the RS232 port
    --rs232_tx <= '1';
i_symbol_dump: symbol_dump port map (
            clk         => pixel_clk,
            clk100      => clk100,
            symbol_sync => symbol_sync,
            symbol_ch0  => symbol_ch0,
            symbol_ch1  => symbol_ch1,
            symbol_ch2  => symbol_ch2, 
            rs232_tx    => rs232_tx);        
    
end Behavioral;

================================================
FILE: src/hdmi_input.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name: hdmi_input - Behavioral
--
-- Description: Decode the video data out of an incoming HDMI data 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;

library UNISIM;
use UNISIM.VComponents.all;

entity hdmi_input is
    Port (
        system_clk      : in  std_logic;

        debug           : out std_logic_vector(5 downto 0);        
        hdmi_detected   : out std_logic;
    
        pixel_clk       : out std_logic;  -- Driven by BUFG
        pixel_io_clk_x1 : out std_logic;  -- Driven by BUFFIO
        pixel_io_clk_x5 : out std_logic;  -- Driven by BUFFIO
    
        -- HDMI input signals
        hdmi_in_clk   : in    std_logic;
        hdmi_in_ch0   : in    std_logic;
        hdmi_in_ch1   : in    std_logic;
        hdmi_in_ch2   : in    std_logic;
    
        -- Status
        pll_locked   : out std_logic;
        symbol_sync  : out std_logic;
    
        -- Raw data signals
        raw_blank : out std_logic;
        raw_hsync : out std_logic;
        raw_vsync : out std_logic;
        raw_ch0   : out std_logic_vector(7 downto 0);
        raw_ch1   : out std_logic_vector(7 downto 0);
        raw_ch2   : out std_logic_vector(7 downto 0);
        -- ADP data
        adp_data_valid      : out std_logic;
        adp_header_bit      : out std_logic;
        adp_frame_bit       : out std_logic;
        adp_subpacket0_bits : out std_logic_vector(1 downto 0);
        adp_subpacket1_bits : out std_logic_vector(1 downto 0);
        adp_subpacket2_bits : out std_logic_vector(1 downto 0);
        adp_subpacket3_bits : out std_logic_vector(1 downto 0);
        -- For later reuse
        symbol_ch0   : out std_logic_vector(9 downto 0);
        symbol_ch1   : out std_logic_vector(9 downto 0);
        symbol_ch2   : out std_logic_vector(9 downto 0)
        
    );
end hdmi_input;

architecture Behavioral of hdmi_input is

    component input_channel is
    Port ( clk_mgmt        : in STD_LOGIC;
           clk             : in  STD_LOGIC;
           clk_x1          : in  STD_LOGIC;
           clk_x5          : in  STD_LOGIC;
           serial          : in  STD_LOGIC;
           reset           : in  STD_LOGIC;
           ce              : in  STD_LOGIC;
           invalid_symbol  : out std_logic;
           symbol          : out std_logic_vector (9 downto 0);
           ctl_valid       : out std_logic;
           ctl             : out std_logic_vector (1 downto 0);
           terc4_valid     : out std_logic;
           terc4           : out std_logic_vector (3 downto 0);
           guardband_valid : out std_logic;
           guardband       : out std_logic_vector (0 downto 0);
           data_valid      : out std_logic;
           data            : out std_logic_vector (7 downto 0);
           symbol_sync     : out STD_LOGIC);
    end component;
    
    signal clk_pixel_raw     : std_logic;
    
    component alignment_detect is
        Port ( clk            : in STD_LOGIC;
               invalid_symbol : in STD_LOGIC;
               delay_count    : out STD_LOGIC_VECTOR(4 downto 0);
               delay_ce       : out STD_LOGIC;
               bitslip        : out STD_LOGIC;
               symbol_sync    : out STD_LOGIC);
    end component;
    
    signal clk_pixel         : std_logic;
    signal clk_pixel_x1      : std_logic;
    signal clk_pixel_x5      : std_logic;
    signal clk_pixel_x1_raw  : std_logic;
    signal clk_pixel_x5_raw  : std_logic;
    signal clk_200_raw       : std_logic;
    signal clk_200           : std_logic;
    signal clkfb_1           : std_logic;
    signal clkfb_2           : std_logic;
    signal locked            : std_logic;
    signal reset             : std_logic;
    signal ser_reset         : std_logic;
    signal ser_ce            : std_logic;
    -------------------------------------------------------------
    -- The raw 10-bit received symbols
    -------------------------------------------------------------
    signal ch0_symbol  : std_logic_vector(9 downto 0);
    signal ch1_symbol  : std_logic_vector(9 downto 0);
    signal ch2_symbol  : std_logic_vector(9 downto 0);
    
    -------------------------------------------------------------
    -- For the decoded TMDS data
    -------------------------------------------------------------
    signal ch0_invalid_symbol  : std_logic;
    signal ch0_ctl_valid       : std_logic;
    signal ch0_ctl             : std_logic_vector(1 downto 0);
    signal ch0_terc4_valid     : std_logic;
    signal ch0_terc4           : std_logic_vector (3 downto 0);
    signal ch0_data_valid      : std_logic;
    signal ch0_data            : std_logic_vector(7 downto 0);
    signal ch0_guardband_valid : std_logic;
    signal ch0_guardband       : std_logic_vector (0 downto 0);
    signal ch0_delay_count     : std_logic_vector (4 downto 0);
    signal ch0_delay_ce        : STD_LOGIC;
    signal ch0_bitslip         : STD_LOGIC;
    signal ch0_symbol_sync     : STD_LOGIC;

    signal ch0_invalid_symbol_1  : std_logic;
    signal ch0_ctl_valid_1       : std_logic;
    signal ch0_ctl_1             : std_logic_vector(1 downto 0);
    signal ch0_terc4_valid_1     : std_logic;
    signal ch0_terc4_1           : std_logic_vector (3 downto 0);
    signal ch0_data_valid_1      : std_logic;
    signal ch0_data_1            : std_logic_vector(7 downto 0);
    
    signal ch1_invalid_symbol  : std_logic;
    signal ch1_ctl_valid       : std_logic;
    signal ch1_ctl             : std_logic_vector(1 downto 0);
    signal ch1_terc4_valid     : std_logic;
    signal ch1_terc4           : std_logic_vector (3 downto 0);
    signal ch1_data_valid      : std_logic;
    signal ch1_data            : std_logic_vector(7 downto 0);
    signal ch1_guardband_valid : std_logic;
    signal ch1_guardband       : std_logic_vector (0 downto 0);
    signal ch1_delay_count     : std_logic_vector (4 downto 0);
    signal ch1_delay_ce        : STD_LOGIC;
    signal ch1_bitslip         : STD_LOGIC;
    signal ch1_symbol_sync     : STD_LOGIC;

    signal ch1_invalid_symbol_1  : std_logic;
    signal ch1_ctl_valid_1       : std_logic;
    signal ch1_ctl_1             : std_logic_vector(1 downto 0);
    signal ch1_terc4_valid_1     : std_logic;
    signal ch1_terc4_1           : std_logic_vector (3 downto 0);
    signal ch1_data_valid_1      : std_logic;
    signal ch1_data_1            : std_logic_vector(7 downto 0);
    
    signal ch2_invalid_symbol  : std_logic;
    signal ch2_ctl_valid       : std_logic;
    signal ch2_ctl             : std_logic_vector(1 downto 0);
    signal ch2_terc4_valid     : std_logic;
    signal ch2_terc4           : std_logic_vector (3 downto 0);
    signal ch2_data_valid      : std_logic;
    signal ch2_data            : std_logic_vector(7 downto 0);
    signal ch2_guardband_valid : std_logic;
    signal ch2_guardband       : std_logic_vector (0 downto 0);
    signal ch2_delay_count     : std_logic_vector (4 downto 0);
    signal ch2_delay_ce        : STD_LOGIC;
    signal ch2_bitslip         : STD_LOGIC;
    signal ch2_symbol_sync     : STD_LOGIC;

    signal ch2_invalid_symbol_1  : std_logic;
    signal ch2_ctl_valid_1       : std_logic;
    signal ch2_ctl_1             : std_logic_vector(1 downto 0);
    signal ch2_terc4_valid_1     : std_logic;
    signal ch2_terc4_1           : std_logic_vector (3 downto 0);
    signal ch2_data_valid_1      : std_logic;
    signal ch2_data_1            : std_logic_vector(7 downto 0);
    
    
    signal reset_counter  : unsigned(7 downto 0) := (others => '1');

    signal vdp_prefix_detect    : std_logic_vector(7 downto 0) := (others => '0');
    signal vdp_guardband_detect : std_logic := '0';
    signal vdp_prefix_seen      : std_logic := '0';
    signal in_vdp               : std_logic := '0';

    signal adp_prefix_detect    : std_logic_vector(7 downto 0) := (others => '0');
    signal adp_guardband_detect : std_logic := '0'; 
    signal adp_prefix_seen      : std_logic := '0';
    signal in_adp               : std_logic := '0';
    signal dvid_mode            : std_logic := '0';
    signal last_was_ctl         : std_logic := '0';
    
    signal in_dvid              : std_logic := '0';
    signal symbol_sync_i        : std_logic := '0';
begin
    pll_locked  <= locked;
    symbol_sync <= symbol_sync_i;
    reset       <= std_logic(reset_counter(reset_counter'high));    
    symbol_ch0  <= ch0_symbol;
    symbol_ch1  <= ch1_symbol;
    symbol_ch2  <= ch2_symbol;

    
    debug       <= ch2_invalid_symbol & ch1_invalid_symbol & ch0_invalid_symbol & dvid_mode & locked & symbol_sync_i;         

    --------------------------------------------
    -- a 200MHz clock for the IDELAY reference
    --------------------------------------------
clk_MMCME2_BASE_inst : MMCME2_BASE
   generic map (
      BANDWIDTH => "OPTIMIZED",      -- Jitter programming (OPTIMIZED, HIGH, LOW)
      DIVCLK_DIVIDE   => 1,          -- Master division value (1-106)
      CLKFBOUT_MULT_F => 8.0,        -- Multiply value for all CLKOUT (2.000-64.000).
      CLKFBOUT_PHASE => 0.0,         -- Phase offset in degrees of CLKFB (-360.000-360.000).
      CLKIN1_PERIOD => 10.0, -- Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
      -- CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
      CLKOUT0_DIVIDE_F => 4.0,       -- Divide amount for CLKOUT0 (1.000-128.000).
      CLKOUT1_DIVIDE   => 1,
      CLKOUT2_DIVIDE   => 1,
      CLKOUT3_DIVIDE   => 1,
      CLKOUT4_DIVIDE   => 1,
      CLKOUT5_DIVIDE   => 1,
      CLKOUT6_DIVIDE   => 1,
      -- CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99).
      CLKOUT0_DUTY_CYCLE => 0.5,
      CLKOUT1_DUTY_CYCLE => 0.5,
      CLKOUT2_DUTY_CYCLE => 0.5,
      CLKOUT3_DUTY_CYCLE => 0.5,
      CLKOUT4_DUTY_CYCLE => 0.5,
      CLKOUT5_DUTY_CYCLE => 0.5,
      CLKOUT6_DUTY_CYCLE => 0.5,
      -- CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
      CLKOUT0_PHASE => 0.0,
      CLKOUT1_PHASE => 0.0,
      CLKOUT2_PHASE => 0.0,
      CLKOUT3_PHASE => 0.0,
      CLKOUT4_PHASE => 0.0,
      CLKOUT5_PHASE => 0.0,
      CLKOUT6_PHASE => 0.0,
      CLKOUT4_CASCADE => FALSE,  -- Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)
      REF_JITTER1 => 0.0,        -- Reference input jitter in UI (0.000-0.999).
      STARTUP_WAIT => FALSE      -- Delays DONE until MMCM is locked (FALSE, TRUE)
   )
   port map (
      -- Clock Outputs: 1-bit (each) output: User configurable clock outputs
      CLKOUT0   => clk_200_raw,  -- 1-bit output: CLKOUT0
      CLKOUT0B  => open,         -- 1-bit output: Inverted CLKOUT0
      CLKOUT1   => open,         -- 1-bit output: CLKOUT1
      CLKOUT1B  => open,         -- 1-bit output: Inverted CLKOUT1
      CLKOUT2   => open,         -- 1-bit output: CLKOUT2
      CLKOUT2B  => open,         -- 1-bit output: Inverted CLKOUT2
      CLKOUT3   => open,         -- 1-bit output: CLKOUT3
      CLKOUT3B  => open,         -- 1-bit output: Inverted CLKOUT3
      CLKOUT4   => open,         -- 1-bit output: CLKOUT4
      CLKOUT5   => open,         -- 1-bit output: CLKOUT5
      CLKOUT6   => open,         -- 1-bit output: CLKOUT6
      -- Feedback Clocks: 1-bit (each) output: Clock feedback ports
      CLKFBOUT  => clkfb_1,      -- 1-bit output: Feedback clock
      CLKFBOUTB => open,         -- 1-bit output: Inverted CLKFBOUT
      -- Status Ports: 1-bit (each) output: MMCM status ports
      LOCKED    => open,         -- 1-bit output: LOCK
      -- Clock Inputs: 1-bit (each) input: Clock input
      CLKIN1    => system_clk,   -- 1-bit input: Clock
      -- Control Ports: 1-bit (each) input: MMCM control ports
      PWRDWN    => '0',          -- 1-bit input: Power-down
      RST       => '0',          -- 1-bit input: Reset
      -- Feedback Clocks: 1-bit (each) input: Clock feedback ports
      CLKFBIN   => clkfb_1       -- 1-bit input: Feedback clock
   );

i_BUFG: BUFG PORT MAP (
        I => clk_200_raw,
        O => clk_200
    );
   ------------------------------
   -- Input Delay reference
   --
   -- These are tied to the delay instances  
   -- by the IODELAY_GROUP attribute.
   --------------------------------------------    
IDELAYCTRL_inst : IDELAYCTRL
    port map (
        RDY    => open,    -- 1-bit output: Ready output
        REFCLK => clk_200, -- 1-bit input:  Reference clock input
        RST    => '0'      -- 1-bit input:  Active high reset input
    );

   --------------------------------
   -- MMCM driven by the HDMI clock
   --------------------------------
hdmi_MMCME2_BASE_inst : MMCME2_BASE
   generic map (
      BANDWIDTH => "OPTIMIZED",      -- Jitter programming (OPTIMIZED, HIGH, LOW)
      DIVCLK_DIVIDE   => 1,          -- Master division value (1-106)
      CLKFBOUT_MULT_F => 5.0,        -- Multiply value for all CLKOUT (2.000-64.000).
      CLKFBOUT_PHASE => 0.0,         -- Phase offset in degrees of CLKFB (-360.000-360.000).
      CLKIN1_PERIOD => 12.5, --1000.0/148.5, -- Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
      -- CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
      CLKOUT0_DIVIDE_F => 5.0,       -- Divide amount for CLKOUT0 (1.000-128.000).
      CLKOUT1_DIVIDE   => 5,
      CLKOUT2_DIVIDE   => 1,
      CLKOUT3_DIVIDE   => 1,
      CLKOUT4_DIVIDE   => 1,
      CLKOUT5_DIVIDE   => 1,
      CLKOUT6_DIVIDE   => 1,
      -- CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99).
      CLKOUT0_DUTY_CYCLE => 0.5,
      CLKOUT1_DUTY_CYCLE => 0.5,
      CLKOUT2_DUTY_CYCLE => 0.5,
      CLKOUT3_DUTY_CYCLE => 0.5,
      CLKOUT4_DUTY_CYCLE => 0.5,
      CLKOUT5_DUTY_CYCLE => 0.5,
      CLKOUT6_DUTY_CYCLE => 0.5,
      -- CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
      CLKOUT0_PHASE => 0.0,
      CLKOUT1_PHASE => 0.0,
      CLKOUT2_PHASE => 0.0,
      CLKOUT3_PHASE => 0.0,
      CLKOUT4_PHASE => 0.0,
      CLKOUT5_PHASE => 0.0,
      CLKOUT6_PHASE => 0.0,
      CLKOUT4_CASCADE => FALSE,  -- Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)
      REF_JITTER1 => 0.0,        -- Reference input jitter in UI (0.000-0.999).
      STARTUP_WAIT => FALSE      -- Delays DONE until MMCM is locked (FALSE, TRUE)
   )
   port map (
      -- Clock Outputs: 1-bit (each) output: User configurable clock outputs
      CLKOUT0   => clk_pixel_raw,    -- 1-bit output: CLKOUT0
      CLKOUT0B  => open,         -- 1-bit output: Inverted CLKOUT0
      CLKOUT1   => clk_pixel_x1_raw, -- 1-bit output: CLKOUT1
      CLKOUT1B  => open,         -- 1-bit output: Inverted CLKOUT1
      CLKOUT2   => clk_pixel_x5_raw, -- 1-bit output: CLKOUT2
      CLKOUT2B  => open,         -- 1-bit output: Inverted CLKOUT2
      CLKOUT3   => open,         -- 1-bit output: CLKOUT3
      CLKOUT3B  => open,         -- 1-bit output: Inverted CLKOUT3
      CLKOUT4   => open,         -- 1-bit output: CLKOUT4
      CLKOUT5   => open,         -- 1-bit output: CLKOUT5
      CLKOUT6   => open,         -- 1-bit output: CLKOUT6
      -- Feedback Clocks: 1-bit (each) output: Clock feedback ports
      CLKFBOUT  => clkfb_2,       -- 1-bit output: Feedback clock
      CLKFBOUTB => open,          -- 1-bit output: Inverted CLKFBOUT
      -- Status Ports: 1-bit (each) output: MMCM status ports
      LOCKED    => locked,        -- 1-bit output: LOCK
      -- Clock Inputs: 1-bit (each) input: Clock input
      CLKIN1    => hdmi_in_clk, -- 1-bit input: Clock
      -- Control Ports: 1-bit (each) input: MMCM control ports
      PWRDWN    => '0',           -- 1-bit input: Power-down
      RST       => '0',           -- 1-bit input: Reset
      -- Feedback Clocks: 1-bit (each) input: Clock feedback ports
      CLKFBIN   => clkfb_2        -- 1-bit input: Feedback clock
   );

   ----------------------------------
   -- Force the highest speed clock 
   -- through the IO clock buffer
   -- (this is only rated for 600MHz!)
   -----------------------------------  
BUFIO_x5_inst : BUFIO
   port map (
      I => clk_pixel_x5_raw, -- 1-bit input: Clock input (connect to an IBUF or BUFMR).
      O => clk_pixel_x5      -- 1-bit output: Clock output (connect to I/O clock loads).
   );

BUFIO_x1_inst : BUFG
      port map (
         I => clk_pixel_x1_raw, -- 1-bit input: Clock input (connect to an IBUF or BUFMR).
         O => clk_pixel_x1      -- 1-bit output: Clock output (connect to I/O clock loads).
      );

BUFIO_inst : BUFG
      port map (
         I => clk_pixel_raw, -- 1-bit input: Clock input (connect to an IBUF or BUFMR).
         O => clk_pixel      -- 1-bit output: Clock output (connect to I/O clock loads).
      );
      pixel_clk       <= clk_pixel;
      pixel_io_clk_x1 <= clk_pixel_x1;
      pixel_io_clk_x5 <= clk_pixel_x5;

ch0: input_channel Port map ( 
        clk_mgmt        => system_clk,
        clk             => clk_pixel,
        ce              => ser_ce,
        clk_x1          => clk_pixel_x1,
        clk_x5          => clk_pixel_x5,
        serial          => hdmi_in_ch0,
        invalid_symbol  => ch0_invalid_symbol,
        symbol          => ch0_symbol,
        ctl_valid       => ch0_ctl_valid,
        ctl             => ch0_ctl,
        terc4_valid     => ch0_terc4_valid,
        terc4           => ch0_terc4,
        guardband_valid => ch0_guardband_valid,
        guardband       => ch0_guardband,
        data_valid      => ch0_data_valid,
        data            => ch0_data,
        reset           => ser_reset,
        symbol_sync     => ch0_symbol_sync);

ch1: input_channel Port map ( 
        clk_mgmt        => system_clk,
        clk             => clk_pixel,
        ce              => ser_ce,
        clk_x1          => clk_pixel_x1,
        clk_x5          => clk_pixel_x5,
        serial          => hdmi_in_ch1,
        symbol          => ch1_symbol,
        invalid_symbol  => ch1_invalid_symbol,
        ctl_valid       => ch1_ctl_valid,
        ctl             => ch1_ctl,
        terc4_valid     => ch1_terc4_valid,
        terc4           => ch1_terc4,
        guardband_valid => ch1_guardband_valid,
        guardband       => ch1_guardband,
        data_valid      => ch1_data_valid,
        data            => ch1_data,
        reset           => ser_reset,
        symbol_sync     => ch1_symbol_sync);

ch2: input_channel Port map ( 
        clk_mgmt        => system_clk,
        clk             => clk_pixel,
        ce              => ser_ce,
        clk_x1          => clk_pixel_x1,
        clk_x5          => clk_pixel_x5,
        serial          => hdmi_in_ch2,
        invalid_symbol  => ch2_invalid_symbol,
        symbol          => ch2_symbol,
        ctl_valid       => ch2_ctl_valid,
        ctl             => ch2_ctl,
        terc4_valid     => ch2_terc4_valid,
        terc4           => ch2_terc4,
        guardband_valid => ch2_guardband_valid,
        guardband       => ch2_guardband,
        data_valid      => ch2_data_valid,
        data            => ch2_data,
        reset           => ser_reset,
        symbol_sync     => ch2_symbol_sync);

    symbol_sync_i <= ch0_symbol_sync and ch1_symbol_sync and ch2_symbol_sync;
    
    hdmi_detected <= not dvid_mode;
hdmi_section_decode: process(clk_pixel)
    begin
        if rising_edge(clk_pixel) then
            -------------------------------------------------------------------
            -- Output the values depending on what sort of data block we are in
            -------------------------------------------------------------------
            if ch0_ctl_valid = '1' and ch1_ctl_valid = '1' and ch2_ctl_valid = '1' then
                -------------------------------------------------------------------
                -- As soon as we see avalid CTL symbols we are no longer in the   
                -- video or aux data period it doesn't have any trailing guard band
                -------------------------------------------------------------------
                in_vdp    <= '0';
                in_adp    <= '0';
                in_dvid   <= '0';
                raw_vsync <= ch0_ctl(1);
                raw_hsync <= ch0_ctl(0);
                raw_blank <= '1';            
                raw_ch2   <= (others => '0');
                raw_ch1   <= (others => '0');
                raw_ch0   <= (others => '0');
                last_was_ctl   <= '1';
                adp_data_valid <= '0';
            else
                last_was_ctl <= '0';
                adp_data_valid <= '0';
                if in_vdp = '1' then
                    raw_vsync <= '0';
                    raw_hsync <= '0';
                    raw_blank <= '0';            
                    raw_ch2   <= ch2_data;
                    raw_ch1   <= ch1_data;
                    raw_ch0   <= ch0_data;
                    if ch2_invalid_symbol = '1' or ch2_invalid_symbol = '1' or ch2_invalid_symbol = '1' then
                        raw_ch2   <= x"EF";
                        raw_ch1   <= x"16";
                        raw_ch0   <= x"16";
                    end if;
            
                elsif in_dvid = '1' then
                    -- In the Video data period
                    raw_vsync <= '0';
                    raw_hsync <= '0';
                    raw_blank <= '0';            
                    raw_ch2   <= ch2_data;
                    raw_ch1   <= ch1_data;
                    raw_ch0   <= ch0_data;
                elsif in_adp = '1' then
                    -- In the Aux Data Period Period
                    raw_vsync <= ch0_terc4(1);
                    raw_hsync <= ch0_terc4(0);
                    raw_blank <= '1';            
                    raw_ch0   <= (others => '0');
                    raw_ch1   <= (others => '0');
                    raw_ch2   <= (others => '0');
                    -- ADP data extraction
                    adp_data_valid      <= '1';
                    adp_header_bit      <= ch0_terc4(2);
                    adp_frame_bit       <= ch0_terc4(3);
                    adp_subpacket0_bits <= ch2_terc4(0) & ch1_terc4(0);
                    adp_subpacket1_bits <= ch2_terc4(1) & ch1_terc4(1);
                    adp_subpacket2_bits <= ch2_terc4(2) & ch1_terc4(2);
                    adp_subpacket3_bits <= ch2_terc4(3) & ch1_terc4(3);
                end if;
            end if;
               
            ------------------------------------------------------------
            -- We need to detect 8 ADP or VDP prefix characters in a row
            ------------------------------------------------------------
            vdp_prefix_detect <= vdp_prefix_detect(6 downto 0) & '0';
            vdp_prefix_seen <= '0';
            if ch0_ctl_valid = '1' and ch1_ctl_valid = '1' and ch1_ctl_valid = '1' then
                if ch1_ctl = "01" and ch2_ctl = "00" then
                    vdp_prefix_detect(0) <=  '1';
                    if vdp_prefix_detect = "01111111" then
                        vdp_prefix_seen <= '1';
                    end if;
                end if;
            end if;
                
            ---------------------------------------------
            -- See if we can detect the ADP guardband
            --
            -- The ADP guardband includes HSYNC and VSYNC
            -- encoded in TERC4 coded in Ch0.
            ---------------------------------------------
            adp_prefix_detect <= adp_prefix_detect(6 downto 0) & '0';
            adp_prefix_seen <= '0';
            if ch0_ctl_valid = '1' and ch1_ctl_valid = '1' and ch1_ctl_valid = '1' then
                if ch1_ctl = "01" and ch2_ctl = "01" then
                    adp_prefix_detect(0) <= '1';
                    if adp_prefix_detect = "01111111" then
                        adp_prefix_seen <= '1';
                    end if;
                end if;
            end if;
            ---------------------------------------------
            -- See if we can detect the ADP guardband
            --
            -- The ADP guardband includes HSYNC and VSYNC
            -- encoded in TERC4 coded in Ch0 - annoying!
            ---------------------------------------------
            adp_guardband_detect <= '0';
            if in_vdp = '0' and ch0_terc4_valid = '1' and ch1_guardband_valid = '1' and ch1_guardband_valid = '1' then
                if ch0_terc4(3 downto 2) = "11" and ch1_guardband = "0" and ch2_guardband = "0" then
                    raw_vsync <= ch0_terc4(1);
                    raw_hsync <= ch0_terc4(0);
                    adp_guardband_detect <= adp_prefix_seen;
                    in_adp <= adp_guardband_detect AND (not in_adp) and (not in_vdp);
                end if;
            end if;
            -----------------------------------------
            -- See if we can detect the VDP guardband
            -- This is pretty nices as the guard
            -----------------------------------------
            vdp_guardband_detect <= '0';                        
            if ch0_guardband_valid = '1' and ch1_guardband_valid = '1' and ch2_guardband_valid = '1' then
                -- TERC Coded for the VDP guard band.
                if ch0_guardband = "1" and ch1_guardband = "0" and ch2_guardband = "1" then
                   vdp_guardband_detect <= vdp_prefix_seen;
                   in_vdp <= vdp_guardband_detect AND (not in_adp) and (not in_vdp);
                   dvid_mode <= '0';
                end if;
            end if;
            --------------------------------
            -- Is this some DVID video data?
            --------------------------------
            if dvid_mode = '1' and last_was_ctl = '1' and ch0_data_valid = '1' and ch1_data_valid = '1' and ch2_data_valid = '1' then
                in_dvid <= '1';
            end if;
            -------------------------------------------------------------
            -- Is this an un-announced video data? If so we receiving 
            -- DVI-D data, and not HDMI 
            -------------------------------------------------------------
            if ch0_data_valid = '1' and ch1_data_valid = '1' and ch2_data_valid = '1' 
                and last_was_ctl = '1' and vdp_prefix_seen = '0' and adp_prefix_seen = '0' then
               dvid_mode <= '1';
            end if;

            ch0_invalid_symbol_1 <= ch0_invalid_symbol;
            ch0_ctl_valid_1      <= ch0_ctl_valid;
            ch0_ctl_1            <= ch0_ctl;
            ch0_terc4_valid_1    <= ch0_terc4_valid;
            ch0_terc4_1          <= ch0_terc4;
            ch0_data_1           <= ch0_data;

            ch1_invalid_symbol_1 <= ch1_invalid_symbol;
            ch1_ctl_valid_1      <= ch1_ctl_valid;
            ch1_ctl_1            <= ch1_ctl;
            ch1_terc4_valid_1    <= ch1_terc4_valid;
            ch1_terc4_1          <= ch1_terc4;
            ch1_data_1           <= ch1_data;

            ch2_invalid_symbol_1 <= ch2_invalid_symbol;
            ch2_ctl_valid_1      <= ch2_ctl_valid;
            ch2_ctl_1            <= ch2_ctl;
            ch2_terc4_valid_1    <= ch2_terc4_valid;
            ch2_terc4_1          <= ch2_terc4;
            ch2_data_valid_1     <= ch2_data_valid;
            ch2_data_1           <= ch2_data;
        end if;
    end process;
    
------------------------------------------
-- Reset the receivers if PLL lock is lost
------------------------------------------
reset_proc: process(system_clk)
    begin
        if rising_edge(system_clk) then
            if locked = '1' then
                if reset_counter > 0 then
                    reset_counter <= reset_counter-1;
                end if;
            else
                reset_counter <= (others => '1');
            end if;
        end if;
    end process;

reset_proc2: process(clk_pixel)
    begin
        if rising_edge(clk_pixel) then
            ser_reset <= reset_counter(reset_counter'high);
            ser_ce    <= not ser_reset; 
        end if;
    end process;
end Behavioral;


================================================
FILE: src/hdmi_io.vhd
================================================
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz<
-- 
-- Module Name: hdmi_io - Behavioral
--
-- Description: Wrapper for input and output components of HDMI data 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;
library UNISIM;
use UNISIM.VComponents.all;

entity hdmi_io is
    port (
        clk100        : in STD_LOGIC;
        -------------------------------
        -- Control signals
        -------------------------------
        clock_locked   : out std_logic;
        data_synced    : out std_logic;
        debug          : out std_logic_vector(7 downto 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);
        
        pixel_clk : out std_logic;
        -------------------------------
        -- VGA data recovered from HDMI
        -------------------------------
        in_hdmi_detected : out std_logic;
        in_blank  : out std_logic;
        in_hsync  : out std_logic;
        in_vsync  : out std_logic;
        in_red    : out std_logic_vector(7 downto 0);
        in_green  : out std_logic_vector(7 downto 0);
        in_blue   : out std_logic_vector(7 downto 0);
        is_interlaced   : out std_logic;
        is_second_field : out std_logic;
        
        -----------------------------------
        -- VGA data to be converted to HDMI
        -----------------------------------
        out_blank : in  std_logic;
        out_hsync : in  std_logic;
        out_vsync : in  std_logic;
        out_red   : in  std_logic_vector(7 downto 0);
        out_green : in  std_logic_vector(7 downto 0);
        out_blue  : in  std_logic_vector(7 downto 0);
       -------------------------------------
        -- Audio Levels
        -------------------------------------
        audio_channel : out std_logic_vector(2 downto 0);
        audio_de      : out std_logic;
        audio_sample  : out std_logic_vector(23 downto 0);
        
        -----------------------------------
        -- For symbol dump or retransmit
        -----------------------------------
        symbol_sync  : out std_logic; -- indicates a fixed reference point in the frame.
        symbol_ch0   : out std_logic_vector(9 downto 0);
        symbol_ch1   : out std_logic_vector(9 downto 0);
        symbol_ch2   : out std_logic_vector(9 downto 0)
    );
end entity;

architecture Behavioral of hdmi_io is
    component edid_rom is
    port ( clk      : in    std_logic;
           sclk_raw : in    std_logic;
           sdat_raw : inout std_logic;
           edid_debug : out std_logic_vector(2 downto 0));
    end component;

    component hdmi_input is 
    port (
        system_clk      : in  std_logic;

        debug           : out std_logic_vector(5 downto 0);        
        hdmi_detected : out std_logic;
        
        pixel_clk       : out std_logic;  -- Driven by BUFG
        pixel_io_clk_x1 : out std_logic;  -- Driven by BUFFIO
        pixel_io_clk_x5 : out std_logic;  -- Driven by BUFFIO
    
        -- HDMI input signals
        hdmi_in_clk   : in    std_logic;
        hdmi_in_ch0   : in    std_logic;
        hdmi_in_ch1   : in    std_logic;
        hdmi_in_ch2   : in    std_logic;
    
        -- Status
        pll_locked   : out std_logic;
        symbol_sync  : out std_logic;
    
        -- Raw data signals
        raw_blank : out std_logic;
        raw_hsync : out std_logic;
        raw_vsync : out std_logic;
        raw_ch0   : out std_logic_vector(7 downto 0);
        raw_ch1   : out std_logic_vector(7 downto 0);
        raw_ch2   : out std_logic_vector(7 downto 0);
        -- ADP data
        adp_data_valid      : out std_logic;
        adp_header_bit      : out std_logic;
        adp_frame_bit       : out std_logic;
        adp_subpacket0_bits : out std_logic_vector(1 downto 0);
        adp_subpacket1_bits : out std_logic_vector(1 downto 0);
        adp_subpacket2_bits : out std_logic_vector(1 downto 0);
        adp_subpacket3_bits : out std_logic_vector(1 downto 0);
        -- For later reuse
        symbol_ch0   : out std_logic_vector(9 downto 0);
        symbol_ch1   : out std_logic_vector(9 downto 0);
        symbol_ch2   : out std_logic_vector(9 downto 0)
        
    );
    end component;
    
    -----------------------------------------------------
    -- This is a half-baked solution to extracting data
    -- from ADP packets - just pipe the data thorugh and 
    -- extract bits on the fly. A 'real' solution would
    -- first verify the ECC codes and recover any errors
    ------------------------------------------------------
    component extract_video_infopacket_data is 
    port (
        clk                 : in  std_logic;
        -- ADP data
        adp_data_valid      : in  std_logic;
        adp_header_bit      : in  std_logic;
        adp_frame_bit       : in  std_logic;
        adp_subpacket0_bits : in  std_logic_vector(1 downto 0);
        adp_subpacket1_bits : in  std_logic_vector(1 downto 0);
        adp_subpacket2_bits : in  std_logic_vector(1 downto 0);
        adp_subpacket3_bits : in  std_logic_vector(1 downto 0);
        -- The stuff we need
        input_is_YCbCr      : out std_Logic;
        input_is_422        : out std_logic;
        input_is_sRGB       : out std_Logic        
    );
    end component;
    
    signal adp_data_valid      : std_logic;
    signal adp_header_bit      : std_logic;
    signal adp_frame_bit       : std_logic;
    signal adp_subpacket0_bits : std_logic_vector(1 downto 0);
    signal adp_subpacket1_bits : std_logic_vector(1 downto 0);
    signal adp_subpacket2_bits : std_logic_vector(1 downto 0);
    signal adp_subpacket3_bits : std_logic_vector(1 downto 0);
    signal is_interlaced_i     : std_logic;
    signal is_second_field_i   : std_logic;

    component extract_audio_samples is
    Port ( clk                 : in STD_LOGIC;
           adp_data_valid      : in STD_LOGIC;
           adp_header_bit      : in STD_LOGIC;
           adp_frame_bit       : in STD_LOGIC;
           adp_subpacket0_bits : in STD_LOGIC_VECTOR (1 downto 0);
           adp_subpacket1_bits : in STD_LOGIC_VECTOR (1 downto 0);
           adp_subpacket2_bits : in STD_LOGIC_VECTOR (1 downto 0);
           adp_subpacket3_bits : in STD_LOGIC_VECTOR (1 downto 0);
           audio_de            : out STD_LOGIC;
           audio_channel       : out STD_LOGIC_VECTOR (2 downto 0);
           audio_sample        : out STD_LOGIC_VECTOR (23 downto 0));
    end component;


    signal input_is_YCbCr      : std_Logic;
    signal input_is_422        : std_logic;
    signal input_is_sRGB       : std_Logic;

    signal raw_blank : std_logic;
    signal raw_hsync : std_logic;
    signal raw_vsync : std_logic;
    signal raw_ch2   : std_logic_vector(7 downto 0);  -- B or Cb
    signal raw_ch1   : std_logic_vector(7 downto 0);  -- G or Y
    signal raw_ch0   : std_logic_vector(7 downto 0);   -- R or Cr

    component detect_interlace is
        Port ( clk : in STD_LOGIC;
               hsync           : in  std_logic;
               vsync           : in  std_logic;
               is_interlaced   : out std_logic;
               is_second_field : out std_logic);
    end component;

    component expand_422_to_444 is
    Port ( clk : in STD_LOGIC;
        input_is_422 : in std_logic;
        ------------------
        -- Incoming pixels
        ------------------
        in_blank  : in std_logic;
        in_hsync  : in std_logic;
        in_vsync  : in std_logic;
        in_ch2    : in std_logic_vector(7 downto 0);
        in_ch1    : in std_logic_vector(7 downto 0);
        in_ch0    : in std_logic_vector(7 downto 0);
    
        -------------------
        -- Processed pixels
        -------------------
        out_blank : out std_logic;
        out_hsync : out std_logic;
Download .txt
gitextract_5_dt_ehf/

├── Artix-7-HDMI-processing.xpr
├── README.txt
├── constraints/
│   └── NexysVideo.xdc
├── src/
│   ├── alignment_detect.vhd
│   ├── audio_meters.vhd
│   ├── audio_to_db.vhd
│   ├── conversion_to_RGB.vhd
│   ├── deserialiser_1_to_10.vhd
│   ├── detect_interlace.vhd
│   ├── dvid_output.vhd
│   ├── edge_enhance.vhd
│   ├── edid_rom.vhd
│   ├── expand_422_to_444.vhd
│   ├── extract_audio_samples.vhd
│   ├── extract_video_infopacket_data.vhd
│   ├── guidelines.vhd
│   ├── hdmi_design.vhd
│   ├── hdmi_input.vhd
│   ├── hdmi_io.vhd
│   ├── input_channel.vhd
│   ├── line_delay.vhd
│   ├── pixel_processing.vhd
│   ├── serialiser_10_to_1.vhd
│   ├── symbol_dump.vhd
│   ├── tmds_decoder.vhd
│   └── tmds_encoder.vhd
└── test_bench/
    ├── hdmi_test_generator/
    │   ├── hdmi_ouput_test.vhd
    │   ├── minimal_hdmi_symbols.vhd
    │   ├── serializers.vhd
    │   ├── vga_clocking.vhd
    │   └── vga_gen.vhd
    ├── tb_audio_to_db.vhd
    ├── tb_convert_yCbCr_to_RGB.vhd
    └── tb_hdmi_decode.vhd
Condensed preview — 34 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (388K chars).
[
  {
    "path": "Artix-7-HDMI-processing.xpr",
    "chars": 13351,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<!-- Product Version: Vivado v2017.4 (64-bit)              -->\r\n<!--            "
  },
  {
    "path": "README.txt",
    "chars": 3597,
    "preview": "README file for Artix 7 HDMI processing\r\n=======================================\r\nHi! \r\n\r\nThis is my design for receivin"
  },
  {
    "path": "constraints/NexysVideo.xdc",
    "chars": 6634,
    "preview": "#------------------------------------------------------------------------------------ \r\n# HDMI and clock Constraints for"
  },
  {
    "path": "src/alignment_detect.vhd",
    "chars": 8032,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/audio_meters.vhd",
    "chars": 11843,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/audio_to_db.vhd",
    "chars": 8097,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/conversion_to_RGB.vhd",
    "chars": 10666,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/deserialiser_1_to_10.vhd",
    "chars": 6731,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/detect_interlace.vhd",
    "chars": 4707,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/dvid_output.vhd",
    "chars": 6241,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/edge_enhance.vhd",
    "chars": 19162,
    "preview": "----------------------------------------------------------------------------------\n-- Engineer: Mike Field <hasmter@snap"
  },
  {
    "path": "src/edid_rom.vhd",
    "chars": 17455,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/expand_422_to_444.vhd",
    "chars": 6893,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/extract_audio_samples.vhd",
    "chars": 5570,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/extract_video_infopacket_data.vhd",
    "chars": 5692,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/guidelines.vhd",
    "chars": 7157,
    "preview": "----------------------------------------------------------------------------------\n-- Engineer: Mike Field <hamster@snap"
  },
  {
    "path": "src/hdmi_design.vhd",
    "chars": 13725,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer:    Mike Field <hamster@"
  },
  {
    "path": "src/hdmi_input.vhd",
    "chars": 30874,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/hdmi_io.vhd",
    "chars": 23271,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/input_channel.vhd",
    "chars": 6660,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/line_delay.vhd",
    "chars": 7355,
    "preview": "----------------------------------------------------------------------------------\n-- Engineer: Mike Field <hamster@snap"
  },
  {
    "path": "src/pixel_processing.vhd",
    "chars": 10796,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hasmter@sna"
  },
  {
    "path": "src/serialiser_10_to_1.vhd",
    "chars": 8023,
    "preview": "----------------------------------------------------------------------------------\r\n-- File: serialiser_10_to_1.vhd\r\n--\r"
  },
  {
    "path": "src/symbol_dump.vhd",
    "chars": 8812,
    "preview": "----------------------------------------------------------------------------------\n-- Engineer: Mike Field <hamster@snap"
  },
  {
    "path": "src/tmds_decoder.vhd",
    "chars": 44823,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "src/tmds_encoder.vhd",
    "chars": 6320,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "test_bench/hdmi_test_generator/hdmi_ouput_test.vhd",
    "chars": 5513,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "test_bench/hdmi_test_generator/minimal_hdmi_symbols.vhd",
    "chars": 16530,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "test_bench/hdmi_test_generator/serializers.vhd",
    "chars": 7773,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "test_bench/hdmi_test_generator/vga_clocking.vhd",
    "chars": 4160,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "test_bench/hdmi_test_generator/vga_gen.vhd",
    "chars": 5660,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "test_bench/tb_audio_to_db.vhd",
    "chars": 4311,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "test_bench/tb_convert_yCbCr_to_RGB.vhd",
    "chars": 5637,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  },
  {
    "path": "test_bench/tb_hdmi_decode.vhd",
    "chars": 13373,
    "preview": "----------------------------------------------------------------------------------\r\n-- Engineer: Mike Field <hamster@sna"
  }
]

About this extraction

This page contains the full source code of the hamsternz/Artix-7-HDMI-processing GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 34 files (356.9 KB), approximately 92.8k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!