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;
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.