Initial version
This commit is contained in:
commit
89ee75121b
31 changed files with 6824 additions and 0 deletions
|
|
@ -0,0 +1,3 @@
|
|||
version:1
|
||||
70726f6a656374:706c616e5f61686561645f75736167655c6a6176615f636f6d6d616e645f68616e646c657273:6e657770726f6a656374:2d31:00:00
|
||||
eof:625436222
|
||||
29
Artix-7-HDMI-processing.cache/wt/webtalk_pa.xml
Normal file
29
Artix-7-HDMI-processing.cache/wt/webtalk_pa.xml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<document>
|
||||
<!--The data in this file is primarily intended for consumption by Xilinx tools.
|
||||
The structure and the elements are likely to change over the next few releases.
|
||||
This means code written to parse this file will need to be revisited each subsequent release.-->
|
||||
<application name="pa" timeStamp="Tue Aug 04 21:42:27 2015">
|
||||
<section name="Project Information" visible="false">
|
||||
<property name="ProjectID" value="1b5c2076c55343a1a76449823623e509" type="ProjectID"/>
|
||||
<property name="ProjectIteration" value="1" type="ProjectIteration"/>
|
||||
</section>
|
||||
<section name="PlanAhead Usage" visible="true">
|
||||
<item name="Project Data">
|
||||
<property name="SrcSetCount" value="1" type="SrcSetCount"/>
|
||||
<property name="ConstraintSetCount" value="1" type="ConstraintSetCount"/>
|
||||
<property name="DesignMode" value="RTL" type="DesignMode"/>
|
||||
<property name="SynthesisStrategy" value="Vivado Synthesis Defaults" type="SynthesisStrategy"/>
|
||||
<property name="ImplStrategy" value="Vivado Implementation Defaults" type="ImplStrategy"/>
|
||||
</item>
|
||||
<item name="Java Command Handlers">
|
||||
<property name="NewProject" value="-1" type="JavaHandler"/>
|
||||
</item>
|
||||
<item name="Other">
|
||||
<property name="GuiMode" value="103" type="GuiMode"/>
|
||||
<property name="BatchMode" value="0" type="BatchMode"/>
|
||||
<property name="TclMode" value="76" type="TclMode"/>
|
||||
</item>
|
||||
</section>
|
||||
</application>
|
||||
</document>
|
||||
265
Artix-7-HDMI-processing.xpr
Normal file
265
Artix-7-HDMI-processing.xpr
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Product Version: Vivado v2014.4 (64-bit) -->
|
||||
<!-- -->
|
||||
<!-- Copyright 1986-2014 Xilinx, Inc. All Rights Reserved. -->
|
||||
|
||||
<Project Version="7" Minor="2" Path="C:/repos/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="BoardPart" Val=""/>
|
||||
<Option Name="ActiveSimSet" Val="sim_1"/>
|
||||
<Option Name="DefaultLib" Val="xil_defaultlib"/>
|
||||
</Configuration>
|
||||
<FileSets Version="1" Minor="31">
|
||||
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1">
|
||||
<Filter Type="Srcs"/>
|
||||
<File Path="$PPRDIR/src/tmds_decoder.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/hdmi_input.vhd">
|
||||
<FileInfo>
|
||||
<Attr Name="UsedIn" Val="synthesis"/>
|
||||
<Attr Name="UsedIn" Val="simulation"/>
|
||||
</FileInfo>
|
||||
</File>
|
||||
<File Path="$PPRDIR/src/hdmi_input_wip.vhd">
|
||||
<FileInfo>
|
||||
<Attr Name="UsedIn" Val="synthesis"/>
|
||||
<Attr Name="UsedIn" Val="simulation"/>
|
||||
</FileInfo>
|
||||
</File>
|
||||
<File Path="$PPRDIR/src/atmds_encoder.vhd">
|
||||
<FileInfo>
|
||||
<Attr Name="UsedIn" Val="synthesis"/>
|
||||
<Attr Name="UsedIn" Val="simulation"/>
|
||||
</FileInfo>
|
||||
</File>
|
||||
<File Path="$PPRDIR/src/alingment_detect.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/input_channel.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/conversion_to_RGB.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/extract_audio_samples.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/extract_video_infopacket_data.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/expand_422_to_444.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/hdmi_io.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/hdmi_design.vhd">
|
||||
<FileInfo>
|
||||
<Attr Name="UsedIn" Val="synthesis"/>
|
||||
<Attr Name="UsedIn" Val="simulation"/>
|
||||
</FileInfo>
|
||||
</File>
|
||||
<File Path="$PPRDIR/src/conversion_YCbCr_to_RGB.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_input"/>
|
||||
<Option Name="TopLib" Val="xil_defaultlib"/>
|
||||
<Option Name="TopArchitecture" Val="Behavioral"/>
|
||||
<Option Name="TopRTLFile" Val="$PPRDIR/src/hdmi_input_wip.vhd"/>
|
||||
<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="ConstrsType" Val="XDC"/>
|
||||
</Config>
|
||||
</FileSet>
|
||||
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1">
|
||||
<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/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/hdmi_ouput_test.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="UsedIn" Val="synthesis"/>
|
||||
<Attr Name="UsedIn" Val="simulation"/>
|
||||
</FileInfo>
|
||||
</File>
|
||||
<File Path="$PPRDIR/test_bench/tb_audio_to_db.vhd">
|
||||
<FileInfo>
|
||||
<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="SrcSet" Val="sources_1"/>
|
||||
</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="QuestaSim/ModelSim Simulator"/>
|
||||
</Simulator>
|
||||
<Simulator Name="IES">
|
||||
<Option Name="Description" Val="Incisive Enterprise Simulator (IES)"/>
|
||||
</Simulator>
|
||||
<Simulator Name="VCS">
|
||||
<Option Name="Description" Val="Verilog Compiler Simulator (VCS)"/>
|
||||
</Simulator>
|
||||
</Simulators>
|
||||
<Runs Version="1" Minor="9">
|
||||
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a200tfbg484-1" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" State="current">
|
||||
<Strategy Version="1" Minor="2">
|
||||
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2014">
|
||||
<Desc>Vivado Synthesis Defaults</Desc>
|
||||
</StratHandle>
|
||||
<Step Id="synth_design"/>
|
||||
</Strategy>
|
||||
</Run>
|
||||
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a200tfbg484-1" ConstrsSet="constrs_1" Description="Vivado Implementation Defaults" State="current" SynthRun="synth_1">
|
||||
<Strategy Version="1" Minor="2">
|
||||
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2014">
|
||||
<Desc>Vivado Implementation Defaults</Desc>
|
||||
</StratHandle>
|
||||
<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>
|
||||
</Run>
|
||||
</Runs>
|
||||
</Project>
|
||||
82
README.txt
Normal file
82
README.txt
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
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
|
||||
|
||||
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 after a few seconds if it receives errors.
|
||||
- The audio meters are drawn twice as tall in interlaced modes
|
||||
- A false VSYNC pulse is causing the meters to be displayed more than once.
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
-- 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!)
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
69
constraints/NexysVideo.xdc
Normal file
69
constraints/NexysVideo.xdc
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#------------------------------------------------------------------------------------
|
||||
# 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 { switches[3] }]; #IO_L24N_T3_16 Sch=sw[3]
|
||||
#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS25 } [get_ports { switches[4] }]; #IO_L6P_T0_15 Sch=sw[4]
|
||||
#set_property -dict { PACKAGE_PIN J16 } [get_ports { sw[5] }]; #IO_0_15 Sch=sw[5]
|
||||
#set_property -dict { PACKAGE_PIN K13 } [get_ports { sw[6] }]; #IO_L19P_T3_A22_15 Sch=sw[6]
|
||||
#set_property -dict { PACKAGE_PIN M17 } [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]
|
||||
163
src/alingment_detect.vhd
Normal file
163
src/alingment_detect.vhd
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz<
|
||||
--
|
||||
-- Module Name: alingment_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 alingment_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 alingment_detect;
|
||||
|
||||
architecture Behavioral of alingment_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;
|
||||
257
src/audio_meters.vhd
Normal file
257
src/audio_meters.vhd
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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);
|
||||
|
||||
-----------------------------------
|
||||
-- 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;
|
||||
|
||||
-- Drop the levels once each frame
|
||||
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
|
||||
line_count <= line_count + 1;
|
||||
col_count <= (others => '0');
|
||||
end if;
|
||||
|
||||
-- Reset the line count on falling vsync
|
||||
if last_vsync = '0' and in_vsync = '1' then
|
||||
line_count <= (others => '0');
|
||||
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;
|
||||
194
src/audio_to_db.vhd
Normal file
194
src/audio_to_db.vhd
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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;
|
||||
226
src/conversion_to_RGB.vhd
Normal file
226
src/conversion_to_RGB.vhd
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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;
|
||||
178
src/deserialiser_1_to_10.vhd
Normal file
178
src/deserialiser_1_to_10.vhd
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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;
|
||||
168
src/dvid_output.vhd
Normal file
168
src/dvid_output.vhd
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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;
|
||||
363
src/edid_rom.vhd
Normal file
363
src/edid_rom.vhd
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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;
|
||||
152
src/expand_422_to_444.vhd
Normal file
152
src/expand_422_to_444.vhd
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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;
|
||||
111
src/extract_audio_samples.vhd
Normal file
111
src/extract_audio_samples.vhd
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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;
|
||||
115
src/extract_video_infopacket_data.vhd
Normal file
115
src/extract_video_infopacket_data.vhd
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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;
|
||||
292
src/hdmi_design.vhd
Normal file
292
src/hdmi_design.vhd
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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(2 downto 0) :=(others => '0');
|
||||
debug_pmod : out std_logic_vector(7 downto 0) :=(others => '0');
|
||||
|
||||
--HDMI input signals
|
||||
hdmi_rx_cec : inout std_logic;
|
||||
hdmi_rx_hpa : out std_logic;
|
||||
hdmi_rx_scl : in std_logic;
|
||||
hdmi_rx_sda : inout std_logic;
|
||||
hdmi_rx_txen : out std_logic;
|
||||
hdmi_rx_clk_n : in std_logic;
|
||||
hdmi_rx_clk_p : in std_logic;
|
||||
hdmi_rx_n : in std_logic_vector(2 downto 0);
|
||||
hdmi_rx_p : in std_logic_vector(2 downto 0);
|
||||
|
||||
--- HDMI out
|
||||
hdmi_tx_cec : inout std_logic;
|
||||
hdmi_tx_clk_n : out std_logic;
|
||||
hdmi_tx_clk_p : out std_logic;
|
||||
hdmi_tx_hpd : in std_logic;
|
||||
hdmi_tx_rscl : inout std_logic;
|
||||
hdmi_tx_rsda : inout std_logic;
|
||||
hdmi_tx_p : out std_logic_vector(2 downto 0);
|
||||
hdmi_tx_n : out std_logic_vector(2 downto 0)
|
||||
);
|
||||
end 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);
|
||||
|
||||
-------------------------------------
|
||||
-- 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)
|
||||
);
|
||||
end component;
|
||||
|
||||
component pixel_processing is
|
||||
Port ( clk : in STD_LOGIC;
|
||||
------------------
|
||||
-- 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);
|
||||
|
||||
-------------------
|
||||
-- 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;
|
||||
|
||||
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 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,
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
i_processing: pixel_processing Port map (
|
||||
clk => pixel_clk,
|
||||
------------------
|
||||
-- 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,
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
end Behavioral;
|
||||
683
src/hdmi_input.vhd
Normal file
683
src/hdmi_input.vhd
Normal file
|
|
@ -0,0 +1,683 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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)
|
||||
);
|
||||
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;
|
||||
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 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);
|
||||
clk : in std_logic;
|
||||
clk_x1 : in std_logic;
|
||||
bitslip : in std_logic;
|
||||
clk_x5 : in std_logic;
|
||||
reset : in std_logic;
|
||||
serial : in std_logic;
|
||||
data : out std_logic_vector (9 downto 0));
|
||||
end component;
|
||||
|
||||
component TMDS_decoder is
|
||||
Port ( clk : in std_logic;
|
||||
symbol : in std_logic_vector (9 downto 0);
|
||||
invalid_symbol : out std_logic;
|
||||
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));
|
||||
end component;
|
||||
|
||||
component alingment_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));
|
||||
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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 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;
|
||||
531
src/hdmi_io.vhd
Normal file
531
src/hdmi_io.vhd
Normal file
|
|
@ -0,0 +1,531 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- 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);
|
||||
|
||||
-----------------------------------
|
||||
-- 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)
|
||||
);
|
||||
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)
|
||||
);
|
||||
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);
|
||||
|
||||
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 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 component;
|
||||
|
||||
signal fourfourfour_blank : std_logic;
|
||||
signal fourfourfour_hsync : std_logic;
|
||||
signal fourfourfour_vsync : std_logic;
|
||||
signal fourfourfour_U : std_logic_vector(11 downto 0);
|
||||
signal fourfourfour_V : std_logic_vector(11 downto 0);
|
||||
signal fourfourfour_W : std_logic_vector(11 downto 0);
|
||||
|
||||
component 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);
|
||||
in_V : in std_logic_vector(11 downto 0);
|
||||
in_W : in std_logic_vector(11 downto 0);
|
||||
------------------------
|
||||
out_blank : out std_logic;
|
||||
out_hsync : out std_logic;
|
||||
out_vsync : out std_logic;
|
||||
out_R : out std_logic_vector(11 downto 0);
|
||||
out_G : out std_logic_vector(11 downto 0);
|
||||
out_B : out std_logic_vector(11 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
signal rgb_blank : std_logic;
|
||||
signal rgb_hsync : std_logic;
|
||||
signal rgb_vsync : std_logic;
|
||||
signal rgb_R : std_logic_vector(11 downto 0);
|
||||
signal rgb_G : std_logic_vector(11 downto 0); -- G or Y
|
||||
signal rgb_B : std_logic_vector(11 downto 0); -- R or Cr
|
||||
|
||||
component 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;
|
||||
|
||||
--- HDMI 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 component;
|
||||
|
||||
-- Clocks for the pixel clock domain
|
||||
signal pixel_clk_i : std_logic;
|
||||
signal pixel_io_clk_x1 : std_logic;
|
||||
signal pixel_io_clk_x5 : std_logic;
|
||||
|
||||
-- The serial data
|
||||
signal tmds_in_clk : std_logic;
|
||||
signal tmds_in_ch0 : std_logic;
|
||||
signal tmds_in_ch1 : std_logic;
|
||||
signal tmds_in_ch2 : std_logic;
|
||||
|
||||
signal tmds_out_clk : std_logic;
|
||||
signal tmds_out_ch0 : std_logic;
|
||||
signal tmds_out_ch1 : std_logic;
|
||||
signal tmds_out_ch2 : std_logic;
|
||||
|
||||
begin
|
||||
pixel_clk <= pixel_clk_i;
|
||||
hdmi_rx_hpa <= '1';
|
||||
hdmi_rx_txen <= '1';
|
||||
hdmi_rx_cec <= 'Z';
|
||||
|
||||
debug(7) <= input_is_YCbCr;
|
||||
debug(6) <= input_is_422;
|
||||
debug(5) <= input_is_sRGB;
|
||||
debug(4 downto 3) <= (others => '0');
|
||||
|
||||
i_edid_rom: edid_rom port map (
|
||||
clk => clk100,
|
||||
sclk_raw => hdmi_rx_scl,
|
||||
sdat_raw => hdmi_rx_sda,
|
||||
edid_debug => debug(2 downto 0));
|
||||
|
||||
---------------------
|
||||
-- Input buffers
|
||||
---------------------
|
||||
in_clk_buf: IBUFDS generic map ( IOSTANDARD => "TMDS_33")
|
||||
port map ( I => hdmi_rx_clk_p, IB => hdmi_rx_clk_n, O => tmds_in_clk);
|
||||
|
||||
in_rx0_buf: IBUFDS generic map ( IOSTANDARD => "TMDS_33")
|
||||
port map ( I => hdmi_rx_p(0), IB => hdmi_rx_n(0), O => tmds_in_ch0);
|
||||
|
||||
in_rx1_buf: IBUFDS generic map ( IOSTANDARD => "TMDS_33")
|
||||
port map ( I => hdmi_rx_p(1), IB => hdmi_rx_n(1), O => tmds_in_ch1);
|
||||
|
||||
in_rx2_buf: IBUFDS generic map ( IOSTANDARD => "TMDS_33")
|
||||
port map ( I => hdmi_rx_p(2), IB => hdmi_rx_n(2), O => tmds_in_ch2);
|
||||
|
||||
i_hdmi_input : hdmi_input port map (
|
||||
system_clk => clk100,
|
||||
debug => open,
|
||||
-- Pixel and serializer clocks
|
||||
pixel_clk => pixel_clk_i,
|
||||
pixel_io_clk_x1 => pixel_io_clk_x1,
|
||||
pixel_io_clk_x5 => pixel_io_clk_x5,
|
||||
--- HDMI input signals
|
||||
hdmi_in_clk => tmds_in_clk,
|
||||
hdmi_in_ch0 => tmds_in_ch0,
|
||||
hdmi_in_ch1 => tmds_in_ch1,
|
||||
hdmi_in_ch2 => tmds_in_ch2,
|
||||
-- are the HDMI symbols in sync?
|
||||
symbol_sync => data_synced,
|
||||
pll_locked => clock_locked,
|
||||
-- VGA internal Signals
|
||||
hdmi_detected => in_hdmi_detected,
|
||||
raw_blank => raw_blank,
|
||||
raw_hsync => raw_hsync,
|
||||
raw_vsync => raw_vsync,
|
||||
raw_ch2 => raw_ch2,
|
||||
raw_ch1 => raw_ch1,
|
||||
raw_ch0 => raw_ch0,
|
||||
-- ADP data
|
||||
adp_data_valid => adp_data_valid,
|
||||
adp_header_bit => adp_header_bit,
|
||||
adp_frame_bit => adp_frame_bit,
|
||||
adp_subpacket0_bits => adp_subpacket0_bits,
|
||||
adp_subpacket1_bits => adp_subpacket1_bits,
|
||||
adp_subpacket2_bits => adp_subpacket2_bits,
|
||||
adp_subpacket3_bits => adp_subpacket3_bits
|
||||
);
|
||||
|
||||
-------------------------------------
|
||||
-- If the input data is in 422 format
|
||||
-- then convert it to 12-bit 444 data
|
||||
-------------------------------------
|
||||
i_expand_422_to_444: expand_422_to_444 Port map (
|
||||
clk => pixel_clk_i,
|
||||
input_is_422 => input_is_422,
|
||||
------------------
|
||||
-- Incoming raw data
|
||||
------------------
|
||||
in_blank => raw_blank,
|
||||
in_hsync => raw_hsync,
|
||||
in_vsync => raw_vsync,
|
||||
in_ch2 => raw_ch2,
|
||||
in_ch1 => raw_ch1,
|
||||
in_ch0 => raw_ch0,
|
||||
|
||||
-------------------
|
||||
-- Processed pixels
|
||||
-------------------
|
||||
out_blank => fourfourfour_blank,
|
||||
out_hsync => fourfourfour_hsync,
|
||||
out_vsync => fourfourfour_vsync,
|
||||
out_U => fourfourfour_U,
|
||||
out_V => fourfourfour_V,
|
||||
out_W => fourfourfour_W
|
||||
);
|
||||
|
||||
i_conversion_to_RGB: conversion_to_RGB
|
||||
port map (
|
||||
clk => pixel_clk_i,
|
||||
------------------------
|
||||
input_is_YCbCr => input_is_YCbCr,
|
||||
input_is_sRGB => input_is_sRGB,
|
||||
in_blank => fourfourfour_blank,
|
||||
in_hsync => fourfourfour_hsync,
|
||||
in_vsync => fourfourfour_vsync,
|
||||
in_U => fourfourfour_U,
|
||||
in_V => fourfourfour_V,
|
||||
in_W => fourfourfour_W,
|
||||
------------------------
|
||||
out_blank => rgb_blank,
|
||||
out_hsync => rgb_hsync,
|
||||
out_vsync => rgb_vsync,
|
||||
out_R => rgb_R,
|
||||
out_G => rgb_G,
|
||||
out_B => rgb_B
|
||||
);
|
||||
|
||||
-----------------------------------------
|
||||
-- Colour space conversion yet to be done
|
||||
-----------------------------------------
|
||||
in_blank <= rgb_blank;
|
||||
in_hsync <= rgb_hsync;
|
||||
in_vsync <= rgb_vsync;
|
||||
in_blue <= rgb_B(11 downto 4);
|
||||
in_green <= rgb_G(11 downto 4);
|
||||
in_red <= rgb_R(11 downto 4);
|
||||
|
||||
------------------------------------------------
|
||||
-- Processing the non-video data #1
|
||||
-- Extracting the Video Infopacket data we need
|
||||
-- to correctly convert the video data
|
||||
------------------------------------------------
|
||||
i_extract_video_infopacket_data: extract_video_infopacket_data port map (
|
||||
clk => pixel_clk_i,
|
||||
-- ADP data
|
||||
adp_data_valid => adp_data_valid,
|
||||
adp_header_bit => adp_header_bit,
|
||||
adp_frame_bit => adp_frame_bit,
|
||||
adp_subpacket0_bits => adp_subpacket0_bits,
|
||||
adp_subpacket1_bits => adp_subpacket1_bits,
|
||||
adp_subpacket2_bits => adp_subpacket2_bits,
|
||||
adp_subpacket3_bits => adp_subpacket3_bits,
|
||||
-- The stuff we need
|
||||
input_is_YCbCr => input_is_YCbCr,
|
||||
input_is_422 => input_is_422,
|
||||
input_is_sRGB => input_is_sRGB
|
||||
);
|
||||
------------------------------------------------
|
||||
-- Processing the non-video data #2
|
||||
-- Extracting the Audio samples so we can display
|
||||
-- level menters on the screen
|
||||
------------------------------------------------
|
||||
i_extract_audio_samples: extract_audio_samples PORT MAP (
|
||||
clk => pixel_clk_i,
|
||||
-- ADP data
|
||||
adp_data_valid => adp_data_valid,
|
||||
adp_header_bit => adp_header_bit,
|
||||
adp_frame_bit => adp_frame_bit,
|
||||
adp_subpacket0_bits => adp_subpacket0_bits,
|
||||
adp_subpacket1_bits => adp_subpacket1_bits,
|
||||
adp_subpacket2_bits => adp_subpacket2_bits,
|
||||
adp_subpacket3_bits => adp_subpacket3_bits,
|
||||
-- The stuff we need
|
||||
audio_de => audio_de,
|
||||
audio_channel => audio_channel,
|
||||
audio_sample => audio_sample);
|
||||
|
||||
------------------------------------------------
|
||||
-- Outputting video data
|
||||
-----------------------------------------------
|
||||
i_DVID_output: DVID_output port map (
|
||||
pixel_clk => pixel_clk_i,
|
||||
pixel_io_clk_x1 => pixel_io_clk_x1,
|
||||
pixel_io_clk_x5 => pixel_io_clk_x5,
|
||||
|
||||
data_valid => '1',
|
||||
-- VGA Signals
|
||||
vga_blank => out_blank,
|
||||
vga_hsync => out_hsync,
|
||||
vga_vsync => out_vsync,
|
||||
vga_red => out_red,
|
||||
vga_blue => out_blue,
|
||||
vga_green => out_green,
|
||||
|
||||
--- HDMI out
|
||||
tmds_out_clk => tmds_out_clk,
|
||||
tmds_out_ch0 => tmds_out_ch0,
|
||||
tmds_out_ch1 => tmds_out_ch1,
|
||||
tmds_out_ch2 => tmds_out_ch2
|
||||
);
|
||||
|
||||
-----------------------------
|
||||
-- Other HDMI control signals
|
||||
-----------------------------
|
||||
hdmi_tx_rsda <= 'Z';
|
||||
hdmi_tx_cec <= 'Z';
|
||||
hdmi_tx_rscl <= '1';
|
||||
|
||||
-----------------
|
||||
-- Output buffers
|
||||
-----------------
|
||||
out_clk_buf: OBUFDS generic map ( IOSTANDARD => "TMDS_33", SLEW => "FAST")
|
||||
port map ( O => hdmi_tx_clk_p, OB => hdmi_tx_clk_n, I => tmds_out_clk);
|
||||
|
||||
out_tx0_buf: OBUFDS generic map ( IOSTANDARD => "TMDS_33", SLEW => "FAST")
|
||||
port map ( O => hdmi_tx_p(0), OB => hdmi_tx_n(0), I => tmds_out_ch0);
|
||||
|
||||
out_tx1_buf: OBUFDS generic map ( IOSTANDARD => "TMDS_33", SLEW => "FAST")
|
||||
port map ( O => hdmi_tx_p(1), OB => hdmi_tx_n(1), I => tmds_out_ch1);
|
||||
|
||||
out_tx2_buf: OBUFDS generic map ( IOSTANDARD => "TMDS_33", SLEW => "FAST")
|
||||
port map ( O => hdmi_tx_p(2), OB => hdmi_tx_n(2), I => tmds_out_ch2);
|
||||
|
||||
end Behavioral;
|
||||
155
src/input_channel.vhd
Normal file
155
src/input_channel.vhd
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Create Date: 30.07.2015 23:11:34
|
||||
-- Module Name: input_channel - Behavioral
|
||||
--
|
||||
-- Description: Receiving one of the three HDMI input channels. and decoding
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- The MIT License (MIT)
|
||||
--
|
||||
-- Copyright (c) 2015 Michael Alan Field
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
-- THE SOFTWARE.
|
||||
------------------------------------------------------------------------------------
|
||||
----- Want to say thanks? ----------------------------------------------------------
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- This design has taken many hours - with the industry metric of 30 lines
|
||||
-- per day, it is equivalent to about 6 months of work. I'm more than happy
|
||||
-- to share it if you can make use of it. It is released under the MIT license,
|
||||
-- so you are not under any onus to say thanks, but....
|
||||
--
|
||||
-- If you what to say thanks for this design how about trying PayPal?
|
||||
-- Educational use - Enough for a beer
|
||||
-- Hobbyist use - Enough for a pizza
|
||||
-- Research use - Enough to take the family out to dinner
|
||||
-- Commercial use - A weeks pay for an engineer (I wish!)
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
entity 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;
|
||||
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 input_channel;
|
||||
|
||||
architecture Behavioral of input_channel is
|
||||
component 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;
|
||||
reset : in std_logic;
|
||||
serial : in std_logic;
|
||||
data : out std_logic_vector (9 downto 0));
|
||||
end component;
|
||||
|
||||
component TMDS_decoder is
|
||||
Port ( clk : in std_logic;
|
||||
symbol : in std_logic_vector (9 downto 0);
|
||||
invalid_symbol : out std_logic;
|
||||
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));
|
||||
end component;
|
||||
|
||||
component alingment_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 delay_count : std_logic_vector (4 downto 0);
|
||||
signal delay_ce : STD_LOGIC;
|
||||
signal bitslip : STD_LOGIC;
|
||||
signal symbol_sync_i : STD_LOGIC;
|
||||
signal symbol : std_logic_vector (9 downto 0);
|
||||
signal invalid_symbol_i: STD_LOGIC;
|
||||
|
||||
begin
|
||||
|
||||
i_deser: deserialiser_1_to_10 port map (
|
||||
clk_mgmt => clk_mgmt,
|
||||
delay_ce => delay_ce,
|
||||
delay_count => delay_count,
|
||||
ce => ce,
|
||||
clk => clk,
|
||||
clk_x1 => clk_x1,
|
||||
bitslip => bitslip,
|
||||
clk_x5 => clk_x5,
|
||||
reset => reset,
|
||||
serial => serial,
|
||||
data => symbol);
|
||||
|
||||
i_decoder: tmds_decoder port map (
|
||||
clk => clk,
|
||||
symbol => symbol,
|
||||
invalid_symbol => invalid_symbol_i,
|
||||
ctl_valid => ctl_valid,
|
||||
ctl => ctl,
|
||||
terc4_valid => terc4_valid,
|
||||
terc4 => terc4,
|
||||
guardband_valid => guardband_valid,
|
||||
guardband => guardband,
|
||||
data_valid => data_valid,
|
||||
data => data
|
||||
);
|
||||
|
||||
invalid_symbol <= invalid_symbol_i;
|
||||
|
||||
i_alignment_detect: alingment_detect port map (
|
||||
clk => clk,
|
||||
invalid_symbol => invalid_symbol_i,
|
||||
delay_count => delay_count,
|
||||
delay_ce => delay_ce,
|
||||
bitslip => bitslip,
|
||||
symbol_sync => symbol_sync);
|
||||
|
||||
end Behavioral;
|
||||
162
src/pixel_processing.vhd
Normal file
162
src/pixel_processing.vhd
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hasmter@snap.net.nz>
|
||||
--
|
||||
-- Module Name: pixel_processing - Behavioral
|
||||
--
|
||||
-- Description: Where you can do processing on the raw pixel data
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- 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 pixel_processing 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);
|
||||
------------------------------------
|
||||
-- Audio only comes in..
|
||||
------------------------------------
|
||||
audio_channel : in std_logic_vector(2 downto 0);
|
||||
audio_de : in std_logic;
|
||||
audio_sample : in std_logic_vector(23 downto 0)
|
||||
|
||||
);
|
||||
end pixel_processing;
|
||||
|
||||
architecture Behavioral of pixel_processing is
|
||||
component audio_to_db is
|
||||
Port ( clk : in STD_LOGIC;
|
||||
in_channel : in STD_LOGIC_VECTOR (2 downto 0);
|
||||
in_de : in STD_LOGIC;
|
||||
in_sample : in STD_LOGIC_VECTOR (23 downto 0);
|
||||
out_channel : out STD_LOGIC_VECTOR (2 downto 0);
|
||||
out_de : out STD_LOGIC;
|
||||
out_level : out STD_LOGIC_VECTOR (5 downto 0));
|
||||
end component;
|
||||
|
||||
signal level_channel : std_logic_vector(2 downto 0);
|
||||
signal level_de : std_logic;
|
||||
signal level : std_logic_vector(5 downto 0);
|
||||
|
||||
component 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);
|
||||
|
||||
-----------------------------------
|
||||
-- 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 component;
|
||||
|
||||
begin
|
||||
|
||||
i_audio_to_db: audio_to_db port map (
|
||||
clk => clk,
|
||||
|
||||
in_channel => audio_channel,
|
||||
in_de => audio_de,
|
||||
in_sample => audio_sample,
|
||||
|
||||
out_channel => level_channel,
|
||||
out_de => level_de,
|
||||
out_level => level
|
||||
);
|
||||
|
||||
i_audio_meters: audio_meters Port map (
|
||||
clk => clk,
|
||||
in_blank => in_blank,
|
||||
in_hsync => in_hsync,
|
||||
in_vsync => in_vsync,
|
||||
in_red => in_red,
|
||||
in_green => in_green,
|
||||
in_blue => in_blue,
|
||||
|
||||
out_blank => out_blank,
|
||||
out_hsync => out_hsync,
|
||||
out_vsync => out_vsync,
|
||||
out_red => out_red,
|
||||
out_green => out_green,
|
||||
out_blue => out_blue,
|
||||
|
||||
audio_channel => level_channel,
|
||||
audio_de => level_de,
|
||||
audio_level => level
|
||||
);
|
||||
|
||||
end Behavioral;
|
||||
176
src/serialiser_10_to_1.vhd
Normal file
176
src/serialiser_10_to_1.vhd
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- File: serialiser_10_to_1.vhd
|
||||
--
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Module Name: serialiser_10_to_1 - Behavioral
|
||||
--
|
||||
-- Description: Using the OSERDESE2 as a 10:1 serialiser, using a x1 and x5
|
||||
-- clocks (using DDR outputs).
|
||||
--
|
||||
-- The tricky bit is that reset needs to be asserted, and then CE asserted
|
||||
-- after the reset or it will not simulate correctly (outputs show as 'X')
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- 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 serialiser_10_to_1 is
|
||||
Port ( clk : in STD_LOGIC;
|
||||
clk_x5 : in STD_LOGIC;
|
||||
data : in STD_LOGIC_VECTOR (9 downto 0);
|
||||
reset : in std_logic;
|
||||
serial : out STD_LOGIC);
|
||||
end serialiser_10_to_1;
|
||||
|
||||
architecture Behavioral of serialiser_10_to_1 is
|
||||
signal shift1 : std_logic := '0';
|
||||
signal shift2 : std_logic := '0';
|
||||
signal ce_delay : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal reset_delay : std_logic_vector(7 downto 0) := (others => '0');
|
||||
begin
|
||||
|
||||
master_serdes : OSERDESE2
|
||||
generic map (
|
||||
DATA_RATE_OQ => "DDR", -- DDR, SDR
|
||||
DATA_RATE_TQ => "DDR", -- DDR, BUF, SDR
|
||||
DATA_WIDTH => 10, -- Parallel data width (2-8,10,14)
|
||||
INIT_OQ => '1', -- Initial value of OQ output (1'b0,1'b1)
|
||||
INIT_TQ => '1', -- Initial value of TQ output (1'b0,1'b1)
|
||||
SERDES_MODE => "MASTER", -- MASTER, SLAVE
|
||||
SRVAL_OQ => '0', -- OQ output value when SR is used (1'b0,1'b1)
|
||||
SRVAL_TQ => '0', -- TQ output value when SR is used (1'b0,1'b1)
|
||||
TBYTE_CTL => "FALSE", -- Enable tristate byte operation (FALSE, TRUE)
|
||||
TBYTE_SRC => "FALSE", -- Tristate byte source (FALSE, TRUE)
|
||||
TRISTATE_WIDTH => 1 -- 3-state converter width (1,4)
|
||||
)
|
||||
port map (
|
||||
OFB => open, -- 1-bit output: Feedback path for data
|
||||
OQ => serial, -- 1-bit output: Data path output
|
||||
-- SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
|
||||
SHIFTOUT1 => open,
|
||||
SHIFTOUT2 => open,
|
||||
TBYTEOUT => open, -- 1-bit output: Byte group tristate
|
||||
TFB => open, -- 1-bit output: 3-state control
|
||||
TQ => open, -- 1-bit output: 3-state control
|
||||
CLK => clk_x5, -- 1-bit input: High speed clock
|
||||
CLKDIV => clk, -- 1-bit input: Divided clock
|
||||
-- D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
|
||||
D1 => data(0),
|
||||
D2 => data(1),
|
||||
D3 => data(2),
|
||||
D4 => data(3),
|
||||
D5 => data(4),
|
||||
D6 => data(5),
|
||||
D7 => data(6),
|
||||
D8 => data(7),
|
||||
OCE => '1', --ce_delay(0), -- 1-bit input: Output data clock enable
|
||||
RST => reset, -- 1-bit input: Reset
|
||||
-- SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
|
||||
SHIFTIN1 => SHIFT1,
|
||||
SHIFTIN2 => SHIFT2,
|
||||
-- T1 - T4: 1-bit (each) input: Parallel 3-state inputs
|
||||
T1 => '0',
|
||||
T2 => '0',
|
||||
T3 => '0',
|
||||
T4 => '0',
|
||||
TBYTEIN => '0', -- 1-bit input: Byte group tristate
|
||||
TCE => '0' -- 1-bit input: 3-state clock enable
|
||||
);
|
||||
|
||||
slave_serdes : OSERDESE2
|
||||
generic map (
|
||||
DATA_RATE_OQ => "DDR", -- DDR, SDR
|
||||
DATA_RATE_TQ => "DDR", -- DDR, BUF, SDR
|
||||
DATA_WIDTH => 10, -- Parallel data width (2-8,10,14)
|
||||
INIT_OQ => '1', -- Initial value of OQ output (1'b0,1'b1)
|
||||
INIT_TQ => '1', -- Initial value of TQ output (1'b0,1'b1)
|
||||
SERDES_MODE => "SLAVE", -- MASTER, SLAVE
|
||||
SRVAL_OQ => '0', -- OQ output value when SR is used (1'b0,1'b1)
|
||||
SRVAL_TQ => '0', -- TQ output value when SR is used (1'b0,1'b1)
|
||||
TBYTE_CTL => "FALSE", -- Enable tristate byte operation (FALSE, TRUE)
|
||||
TBYTE_SRC => "FALSE", -- Tristate byte source (FALSE, TRUE)
|
||||
TRISTATE_WIDTH => 1 -- 3-state converter width (1,4)
|
||||
)
|
||||
port map (
|
||||
OFB => open, -- 1-bit output: Feedback path for data
|
||||
OQ => open, -- 1-bit output: Data path output
|
||||
-- SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
|
||||
SHIFTOUT1 => shift1,
|
||||
SHIFTOUT2 => shift2,
|
||||
|
||||
TBYTEOUT => open, -- 1-bit output: Byte group tristate
|
||||
TFB => open, -- 1-bit output: 3-state control
|
||||
TQ => open, -- 1-bit output: 3-state control
|
||||
CLK => clk_x5, -- 1-bit input: High speed clock
|
||||
CLKDIV => clk, -- 1-bit input: Divided clock
|
||||
-- D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
|
||||
D1 => '0',
|
||||
D2 => '0',
|
||||
D3 => data(8),
|
||||
D4 => data(9),
|
||||
D5 => '0',
|
||||
D6 => '0',
|
||||
D7 => '0',
|
||||
D8 => '0',
|
||||
OCE => '1', --ce_delay(0), -- 1-bit input: Output data clock enable
|
||||
RST => reset, -- 1-bit input: Reset
|
||||
-- SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
|
||||
SHIFTIN1 => '0',
|
||||
SHIFTIN2 => '0',
|
||||
-- T1 - T4: 1-bit (each) input: Parallel 3-state inputs
|
||||
T1 => '0',
|
||||
T2 => '0',
|
||||
T3 => '0',
|
||||
T4 => '0',
|
||||
TBYTEIN => '0', -- 1-bit input: Byte group tristate
|
||||
TCE => '0' -- 1-bit input: 3-state clock enable
|
||||
);
|
||||
|
||||
delay_ce: process(clk_x5)
|
||||
begin
|
||||
if rising_edge(clk_x5) then
|
||||
ce_delay <= not reset & ce_delay(ce_delay'high downto 1);
|
||||
end if;
|
||||
end process;
|
||||
end Behavioral;
|
||||
915
src/tmds_decoder.vhd
Normal file
915
src/tmds_decoder.vhd
Normal file
|
|
@ -0,0 +1,915 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Create Date: 10.07.2015 20:06:49
|
||||
-- Design Name:
|
||||
-- Module Name: TMDS_decoder - Behavioral
|
||||
--
|
||||
-- Description: Decoding for TMDS encoded symbols. This performs the conversion
|
||||
-- using a table lookup for simplicity
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- 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 TMDS_decoder is
|
||||
Port ( clk : in std_logic;
|
||||
symbol : in std_logic_vector (9 downto 0);
|
||||
invalid_symbol : out std_logic;
|
||||
|
||||
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));
|
||||
end TMDS_decoder;
|
||||
|
||||
architecture Behavioral of TMDS_decoder is
|
||||
signal lookup : std_logic_vector (8 downto 0);
|
||||
begin
|
||||
|
||||
decode_ctl: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
------------------
|
||||
-- TMDS data bytes
|
||||
if lookup(8) = '1' then
|
||||
data_valid <= '1';
|
||||
data <= lookup(7 downto 0);
|
||||
else
|
||||
data_valid <= '0';
|
||||
end if;
|
||||
|
||||
------------
|
||||
-- CTL codes
|
||||
if lookup(8 downto 7) = "01" then
|
||||
ctl_valid <= '1';
|
||||
ctl <= lookup(1 downto 0);
|
||||
else
|
||||
ctl_valid <= '0';
|
||||
end if;
|
||||
|
||||
------------------------------
|
||||
-- All other codes are invalid
|
||||
------------------------------
|
||||
if lookup(8 downto 7) = "00" then
|
||||
invalid_symbol <= '1';
|
||||
else
|
||||
invalid_symbol <= '0';
|
||||
end if;
|
||||
|
||||
terc4_valid <= '0';
|
||||
guardband_valid <= '0';
|
||||
if lookup(8) = '1' then
|
||||
-------------------------
|
||||
-- Decode the guard bands
|
||||
-------------------------
|
||||
case lookup(7 downto 0) is
|
||||
when x"55" => guardband_valid <= '1'; guardband <= "0";
|
||||
when x"AB" => guardband_valid <= '1'; guardband <= "1";
|
||||
when others => null;
|
||||
end case;
|
||||
|
||||
-------------------------
|
||||
-- Decode TERC4 data
|
||||
-------------------------
|
||||
case lookup(7 downto 0) is
|
||||
when x"5B" => terc4_valid <= '1'; terc4 <= "0000";-- "1010011100" TERC4 0000
|
||||
when x"5A" => terc4_valid <= '1'; terc4 <= "0001"; -- "1001100011" TERC4 0001
|
||||
when x"D3" => terc4_valid <= '1'; terc4 <= "0010"; -- "1011100100" TERC4 0010
|
||||
when x"D9" => terc4_valid <= '1'; terc4 <= "0011"; -- "1011100010" TERC4 0011
|
||||
when x"93" => terc4_valid <= '1'; terc4 <= "0100"; -- "0101110001" TERC4 0100
|
||||
when x"22" => terc4_valid <= '1'; terc4 <= "0101"; -- "0100011110" TERC4 0101
|
||||
when x"92" => terc4_valid <= '1'; terc4 <= "0110"; -- "0110001110" TERC4 0110
|
||||
when x"44" => terc4_valid <= '1'; terc4 <= "0110"; -- "0100111100" TERC4 0111
|
||||
when x"AB" => terc4_valid <= '1'; terc4 <= "1000"; -- "1011001100" TERC4 1000 & HDMI Guard band (video C0 and Video C2)
|
||||
when x"4B" => terc4_valid <= '1'; terc4 <= "1001"; -- "0100111001" TERC4 1001
|
||||
when x"A4" => terc4_valid <= '1'; terc4 <= "1010"; -- "0110011100" TERC4 1010
|
||||
when x"D5" => terc4_valid <= '1'; terc4 <= "1011"; -- "1011000110" TERC4 1011
|
||||
when x"6D" => terc4_valid <= '1'; terc4 <= "1100"; -- "1010001110" TERC4 1100
|
||||
when x"6C" => terc4_valid <= '1'; terc4 <= "1101"; -- "1001110001" TERC4 1101
|
||||
when x"A5" => terc4_valid <= '1'; terc4 <= "1110"; -- "0101100011" TERC4 1110
|
||||
when x"BA" => terc4_valid <= '1'; terc4 <= "1111"; -- "1011000011" TERC4 1111
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
|
||||
-------------------------------------------------------------
|
||||
-- Convert the incoming signal to something we can decode
|
||||
--
|
||||
-- For data symbols
|
||||
-- ----------------
|
||||
-- bit 8 - 1 -- Data word flage
|
||||
-- bits 7:0 - xxxxxxxx - Data value
|
||||
--
|
||||
-- For CTL symbols
|
||||
-- ---------------
|
||||
-- bit 8 - 0 - Data word flage
|
||||
-- bit 7 - 1 - CTL Indicator
|
||||
-- bits 6:2 - X - Ignored
|
||||
-- bits 1:0 - xx - CTL value
|
||||
--
|
||||
-- For Invalid symbols
|
||||
-- -------------------
|
||||
-- bit 8 - 0 - Data word flage
|
||||
-- bit 7 - 0 - TERC4 Inicated
|
||||
-- bit 6 - 0 - CTL Indicator
|
||||
-- bit 5 - 0 - Guard band indicator
|
||||
-- bits 4:0 - X - Unused
|
||||
--
|
||||
-------------------------------------------------------------
|
||||
case symbol is
|
||||
-- DVI-D Data sybmols
|
||||
-- Data 00
|
||||
when "1111111111" => lookup <= "100000000";
|
||||
when "0100000000" => lookup <= "100000000";
|
||||
-- Data 01
|
||||
when "0111111111" => lookup <= "100000001";
|
||||
when "1100000000" => lookup <= "100000001";
|
||||
-- Data 02
|
||||
when "0111111110" => lookup <= "100000010";
|
||||
when "1100000001" => lookup <= "100000010";
|
||||
-- Data 03
|
||||
when "1111111110" => lookup <= "100000011";
|
||||
when "0100000001" => lookup <= "100000011";
|
||||
-- Data 04
|
||||
when "0111111100" => lookup <= "100000100";
|
||||
when "1100000011" => lookup <= "100000100";
|
||||
-- Data 05
|
||||
when "1111111100" => lookup <= "100000101";
|
||||
when "0100000011" => lookup <= "100000101";
|
||||
-- Data 06
|
||||
when "1111111101" => lookup <= "100000110";
|
||||
when "0100000010" => lookup <= "100000110";
|
||||
-- Data 07
|
||||
when "0111111101" => lookup <= "100000111";
|
||||
when "1100000010" => lookup <= "100000111";
|
||||
-- Data 08
|
||||
when "0111111000" => lookup <= "100001000";
|
||||
when "1100000111" => lookup <= "100001000";
|
||||
-- Data 09
|
||||
when "1111111000" => lookup <= "100001001";
|
||||
when "0100000111" => lookup <= "100001001";
|
||||
-- Data 0a
|
||||
when "1111111001" => lookup <= "100001010";
|
||||
when "0100000110" => lookup <= "100001010";
|
||||
-- Data 0b
|
||||
when "0111111001" => lookup <= "100001011";
|
||||
when "1100000110" => lookup <= "100001011";
|
||||
-- Data 0c
|
||||
when "1111111011" => lookup <= "100001100";
|
||||
when "0100000100" => lookup <= "100001100";
|
||||
-- Data 0d
|
||||
when "0111111011" => lookup <= "100001101";
|
||||
when "1100000100" => lookup <= "100001101";
|
||||
-- Data 0e
|
||||
when "0111111010" => lookup <= "100001110";
|
||||
when "1100000101" => lookup <= "100001110";
|
||||
-- Data 0f
|
||||
when "1111111010" => lookup <= "100001111";
|
||||
when "0100000101" => lookup <= "100001111";
|
||||
-- Data 10
|
||||
when "0111110000" => lookup <= "100010000";
|
||||
-- Data 11
|
||||
when "0100001111" => lookup <= "100010001";
|
||||
-- Data 12
|
||||
when "1111110001" => lookup <= "100010010";
|
||||
when "0100001110" => lookup <= "100010010";
|
||||
-- Data 13
|
||||
when "0111110001" => lookup <= "100010011";
|
||||
when "1100001110" => lookup <= "100010011";
|
||||
-- Data 14
|
||||
when "1111110011" => lookup <= "100010100";
|
||||
when "0100001100" => lookup <= "100010100";
|
||||
-- Data 15
|
||||
when "0111110011" => lookup <= "100010101";
|
||||
when "1100001100" => lookup <= "100010101";
|
||||
-- Data 16
|
||||
when "0111110010" => lookup <= "100010110";
|
||||
when "1100001101" => lookup <= "100010110";
|
||||
-- Data 17
|
||||
when "1111110010" => lookup <= "100010111";
|
||||
when "0100001101" => lookup <= "100010111";
|
||||
-- Data 18
|
||||
when "1111110111" => lookup <= "100011000";
|
||||
when "0100001000" => lookup <= "100011000";
|
||||
-- Data 19
|
||||
when "0111110111" => lookup <= "100011001";
|
||||
when "1100001000" => lookup <= "100011001";
|
||||
-- Data 1a
|
||||
when "0111110110" => lookup <= "100011010";
|
||||
when "1100001001" => lookup <= "100011010";
|
||||
-- Data 1b
|
||||
when "1111110110" => lookup <= "100011011";
|
||||
when "0100001001" => lookup <= "100011011";
|
||||
-- Data 1c
|
||||
when "0111110100" => lookup <= "100011100";
|
||||
when "1100001011" => lookup <= "100011100";
|
||||
-- Data 1d
|
||||
when "1111110100" => lookup <= "100011101";
|
||||
when "0100001011" => lookup <= "100011101";
|
||||
-- Data 1e
|
||||
when "1001011111" => lookup <= "100011110";
|
||||
when "0010100000" => lookup <= "100011110";
|
||||
-- Data 1f
|
||||
when "0001011111" => lookup <= "100011111";
|
||||
when "1010100000" => lookup <= "100011111";
|
||||
-- Data 20
|
||||
when "1100011111" => lookup <= "100100000";
|
||||
when "0111100000" => lookup <= "100100000";
|
||||
-- Data 21
|
||||
when "0100011111" => lookup <= "100100001";
|
||||
when "1111100000" => lookup <= "100100001";
|
||||
-- Data 22
|
||||
when "0100011110" => lookup <= "100100010"; -- TERC4 0101
|
||||
-- Data 23
|
||||
when "0111100001" => lookup <= "100100011";
|
||||
-- Data 24
|
||||
when "1111100011" => lookup <= "100100100";
|
||||
when "0100011100" => lookup <= "100100100";
|
||||
-- Data 25
|
||||
when "0111100011" => lookup <= "100100101";
|
||||
when "1100011100" => lookup <= "100100101";
|
||||
-- Data 26
|
||||
when "0111100010" => lookup <= "100100110";
|
||||
-- Data 27
|
||||
when "0100011101" => lookup <= "100100111";
|
||||
-- Data 28
|
||||
when "1111100111" => lookup <= "100101000";
|
||||
when "0100011000" => lookup <= "100101000";
|
||||
-- Data 29
|
||||
when "0111100111" => lookup <= "100101001";
|
||||
when "1100011000" => lookup <= "100101001";
|
||||
-- Data 2a
|
||||
when "0111100110" => lookup <= "100101010";
|
||||
when "1100011001" => lookup <= "100101010";
|
||||
-- Data 2b
|
||||
when "1111100110" => lookup <= "100101011";
|
||||
when "0100011001" => lookup <= "100101011";
|
||||
-- Data 2c
|
||||
when "0111100100" => lookup <= "100101100";
|
||||
-- Data 2d
|
||||
when "0100011011" => lookup <= "100101101";
|
||||
-- Data 2e
|
||||
when "1001001111" => lookup <= "100101110";
|
||||
when "0010110000" => lookup <= "100101110";
|
||||
-- Data 2f
|
||||
when "0001001111" => lookup <= "100101111";
|
||||
when "1010110000" => lookup <= "100101111";
|
||||
-- Data 30
|
||||
when "1111101111" => lookup <= "100110000";
|
||||
when "0100010000" => lookup <= "100110000";
|
||||
-- Data 31
|
||||
when "0111101111" => lookup <= "100110001";
|
||||
when "1100010000" => lookup <= "100110001";
|
||||
-- Data 32
|
||||
when "0111101110" => lookup <= "100110010";
|
||||
when "1100010001" => lookup <= "100110010";
|
||||
-- Data 33
|
||||
when "1111101110" => lookup <= "100110011";
|
||||
when "0100010001" => lookup <= "100110011";
|
||||
-- Data 34
|
||||
when "0111101100" => lookup <= "100110100";
|
||||
when "1100010011" => lookup <= "100110100";
|
||||
-- Data 35
|
||||
when "1111101100" => lookup <= "100110101";
|
||||
when "0100010011" => lookup <= "100110101";
|
||||
-- Data 36
|
||||
when "1001000111" => lookup <= "100110110";
|
||||
-- Data 37
|
||||
when "1010111000" => lookup <= "100110111";
|
||||
-- Data 38
|
||||
when "0111101000" => lookup <= "100111000";
|
||||
-- Data 39
|
||||
when "0100010111" => lookup <= "100111001";
|
||||
-- Data 3a
|
||||
when "0010111100" => lookup <= "100111010";
|
||||
when "1001000011" => lookup <= "100111010";
|
||||
-- Data 3b
|
||||
when "1010111100" => lookup <= "100111011";
|
||||
when "0001000011" => lookup <= "100111011";
|
||||
-- Data 3c
|
||||
when "0010111110" => lookup <= "100111100";
|
||||
when "1001000001" => lookup <= "100111100";
|
||||
-- Data 3d
|
||||
when "1010111110" => lookup <= "100111101";
|
||||
when "0001000001" => lookup <= "100111101";
|
||||
-- Data 3e
|
||||
when "1010111111" => lookup <= "100111110";
|
||||
when "0001000000" => lookup <= "100111110";
|
||||
-- Data 3f
|
||||
when "0010111111" => lookup <= "100111111";
|
||||
when "1001000000" => lookup <= "100111111";
|
||||
-- Data 40
|
||||
when "1100111111" => lookup <= "101000000";
|
||||
when "0111000000" => lookup <= "101000000";
|
||||
-- Data 41
|
||||
when "0100111111" => lookup <= "101000001";
|
||||
when "1111000000" => lookup <= "101000001";
|
||||
-- Data 42
|
||||
when "0100111110" => lookup <= "101000010";
|
||||
when "1111000001" => lookup <= "101000010";
|
||||
-- Data 43
|
||||
when "1100111110" => lookup <= "101000011";
|
||||
when "0111000001" => lookup <= "101000011";
|
||||
-- Data 44
|
||||
when "0100111100" => lookup <= "101000100"; -- TERC4 0111
|
||||
-- Data 45
|
||||
when "0111000011" => lookup <= "101000101";
|
||||
-- Data 46
|
||||
when "1100111101" => lookup <= "101000110";
|
||||
when "0111000010" => lookup <= "101000110";
|
||||
-- Data 47
|
||||
when "0100111101" => lookup <= "101000111";
|
||||
when "1111000010" => lookup <= "101000111";
|
||||
-- Data 48
|
||||
when "1111000111" => lookup <= "101001000";
|
||||
when "0100111000" => lookup <= "101001000";
|
||||
-- Data 49
|
||||
when "0111000111" => lookup <= "101001001";
|
||||
when "1100111000" => lookup <= "101001001";
|
||||
-- Data 4a
|
||||
when "0111000110" => lookup <= "101001010";
|
||||
-- Data 4b
|
||||
when "0100111001" => lookup <= "101001011"; -- TERC4 1001
|
||||
-- Data 4c
|
||||
when "1100111011" => lookup <= "101001100";
|
||||
when "0111000100" => lookup <= "101001100";
|
||||
-- Data 4d
|
||||
when "0100111011" => lookup <= "101001101";
|
||||
when "1111000100" => lookup <= "101001101";
|
||||
-- Data 4e
|
||||
when "1001101111" => lookup <= "101001110";
|
||||
when "0010010000" => lookup <= "101001110";
|
||||
-- Data 4f
|
||||
when "0001101111" => lookup <= "101001111";
|
||||
when "1010010000" => lookup <= "101001111";
|
||||
-- Data 50
|
||||
when "1111001111" => lookup <= "101010000";
|
||||
when "0100110000" => lookup <= "101010000";
|
||||
-- Data 51
|
||||
when "0111001111" => lookup <= "101010001";
|
||||
when "1100110000" => lookup <= "101010001";
|
||||
-- Data 52
|
||||
when "0111001110" => lookup <= "101010010";
|
||||
when "1100110001" => lookup <= "101010010";
|
||||
-- Data 53
|
||||
when "1111001110" => lookup <= "101010011";
|
||||
when "0100110001" => lookup <= "101010011";
|
||||
-- Data 54
|
||||
when "0111001100" => lookup <= "101010100";
|
||||
-- Data 55
|
||||
when "0100110011" => lookup <= "101010101"; -- HDMI Guard band (video C1, data C1 & C2)
|
||||
-- Data 56
|
||||
when "1001100111" => lookup <= "101010110";
|
||||
when "0010011000" => lookup <= "101010110";
|
||||
-- Data 57
|
||||
when "0001100111" => lookup <= "101010111";
|
||||
when "1010011000" => lookup <= "101010111";
|
||||
-- Data 58
|
||||
when "1100110111" => lookup <= "101011000";
|
||||
when "0111001000" => lookup <= "101011000";
|
||||
-- Data 59
|
||||
when "0100110111" => lookup <= "101011001";
|
||||
when "1111001000" => lookup <= "101011001";
|
||||
-- Data 5a
|
||||
when "1001100011" => lookup <= "101011010"; -- TERC4 0001
|
||||
-- Data 5b
|
||||
when "1010011100" => lookup <= "101011011"; -- TERC4 0000
|
||||
-- Data 5c
|
||||
when "0010011110" => lookup <= "101011100";
|
||||
when "1001100001" => lookup <= "101011100";
|
||||
-- Data 5d
|
||||
when "1010011110" => lookup <= "101011101";
|
||||
when "0001100001" => lookup <= "101011101";
|
||||
-- Data 5e
|
||||
when "1010011111" => lookup <= "101011110";
|
||||
when "0001100000" => lookup <= "101011110";
|
||||
-- Data 5f
|
||||
when "0010011111" => lookup <= "101011111";
|
||||
when "1001100000" => lookup <= "101011111";
|
||||
-- Data 60
|
||||
when "1111011111" => lookup <= "101100000";
|
||||
when "0100100000" => lookup <= "101100000";
|
||||
-- Data 61
|
||||
when "0111011111" => lookup <= "101100001";
|
||||
when "1100100000" => lookup <= "101100001";
|
||||
-- Data 62
|
||||
when "0111011110" => lookup <= "101100010";
|
||||
when "1100100001" => lookup <= "101100010";
|
||||
-- Data 63
|
||||
when "1111011110" => lookup <= "101100011";
|
||||
when "0100100001" => lookup <= "101100011";
|
||||
-- Data 64
|
||||
when "0111011100" => lookup <= "101100100";
|
||||
when "1100100011" => lookup <= "101100100";
|
||||
-- Data 65
|
||||
when "1111011100" => lookup <= "101100101";
|
||||
when "0100100011" => lookup <= "101100101";
|
||||
-- Data 66
|
||||
when "1001110111" => lookup <= "101100110";
|
||||
when "0010001000" => lookup <= "101100110";
|
||||
-- Data 67
|
||||
when "0001110111" => lookup <= "101100111";
|
||||
when "1010001000" => lookup <= "101100111";
|
||||
-- Data 68
|
||||
when "0111011000" => lookup <= "101101000";
|
||||
-- Data 69
|
||||
when "0100100111" => lookup <= "101101001";
|
||||
-- Data 6a
|
||||
when "1001110011" => lookup <= "101101010";
|
||||
when "0010001100" => lookup <= "101101010";
|
||||
-- Data 6b
|
||||
when "0001110011" => lookup <= "101101011";
|
||||
when "1010001100" => lookup <= "101101011";
|
||||
-- Data 6c
|
||||
when "1001110001" => lookup <= "101101100"; -- TERC4 1101
|
||||
-- Data 6d
|
||||
when "1010001110" => lookup <= "101101101"; -- TERC4 1100
|
||||
-- Data 6e
|
||||
when "1010001111" => lookup <= "101101110";
|
||||
when "0001110000" => lookup <= "101101110";
|
||||
-- Data 6f
|
||||
when "0010001111" => lookup <= "101101111";
|
||||
when "1001110000" => lookup <= "101101111";
|
||||
-- Data 70
|
||||
when "1100101111" => lookup <= "101110000";
|
||||
when "0111010000" => lookup <= "101110000";
|
||||
-- Data 71
|
||||
when "0100101111" => lookup <= "101110001";
|
||||
when "1111010000" => lookup <= "101110001";
|
||||
-- Data 72
|
||||
when "1001111011" => lookup <= "101110010";
|
||||
when "0010000100" => lookup <= "101110010";
|
||||
-- Data 73
|
||||
when "0001111011" => lookup <= "101110011";
|
||||
when "1010000100" => lookup <= "101110011";
|
||||
-- Data 74
|
||||
when "1001111001" => lookup <= "101110100";
|
||||
when "0010000110" => lookup <= "101110100";
|
||||
-- Data 75
|
||||
when "0001111001" => lookup <= "101110101";
|
||||
when "1010000110" => lookup <= "101110101";
|
||||
-- Data 76
|
||||
when "1010000111" => lookup <= "101110110";
|
||||
-- Data 77
|
||||
when "1001111000" => lookup <= "101110111";
|
||||
-- Data 78
|
||||
when "1001111101" => lookup <= "101111000";
|
||||
when "0010000010" => lookup <= "101111000";
|
||||
-- Data 79
|
||||
when "0001111101" => lookup <= "101111001";
|
||||
when "1010000010" => lookup <= "101111001";
|
||||
-- Data 7a
|
||||
when "0001111100" => lookup <= "101111010";
|
||||
when "1010000011" => lookup <= "101111010";
|
||||
-- Data 7b
|
||||
when "1001111100" => lookup <= "101111011";
|
||||
when "0010000011" => lookup <= "101111011";
|
||||
-- Data 7c
|
||||
when "0001111110" => lookup <= "101111100";
|
||||
when "1010000001" => lookup <= "101111100";
|
||||
-- Data 7d
|
||||
when "1001111110" => lookup <= "101111101";
|
||||
when "0010000001" => lookup <= "101111101";
|
||||
-- Data 7e
|
||||
when "1001111111" => lookup <= "101111110";
|
||||
when "0010000000" => lookup <= "101111110";
|
||||
-- Data 7f
|
||||
when "0001111111" => lookup <= "101111111";
|
||||
when "1010000000" => lookup <= "101111111";
|
||||
-- Data 80
|
||||
when "1101111111" => lookup <= "110000000";
|
||||
when "0110000000" => lookup <= "110000000";
|
||||
-- Data 81
|
||||
when "0101111111" => lookup <= "110000001";
|
||||
when "1110000000" => lookup <= "110000001";
|
||||
-- Data 82
|
||||
when "0101111110" => lookup <= "110000010";
|
||||
when "1110000001" => lookup <= "110000010";
|
||||
-- Data 83
|
||||
when "1101111110" => lookup <= "110000011";
|
||||
when "0110000001" => lookup <= "110000011";
|
||||
-- Data 84
|
||||
when "0101111100" => lookup <= "110000100";
|
||||
when "1110000011" => lookup <= "110000100";
|
||||
-- Data 85
|
||||
when "1101111100" => lookup <= "110000101";
|
||||
when "0110000011" => lookup <= "110000101";
|
||||
-- Data 86
|
||||
when "1101111101" => lookup <= "110000110";
|
||||
when "0110000010" => lookup <= "110000110";
|
||||
-- Data 87
|
||||
when "0101111101" => lookup <= "110000111";
|
||||
when "1110000010" => lookup <= "110000111";
|
||||
-- Data 88
|
||||
when "0101111000" => lookup <= "110001000";
|
||||
-- Data 89
|
||||
when "0110000111" => lookup <= "110001001";
|
||||
-- Data 8a
|
||||
when "1101111001" => lookup <= "110001010";
|
||||
when "0110000110" => lookup <= "110001010";
|
||||
-- Data 8b
|
||||
when "0101111001" => lookup <= "110001011";
|
||||
when "1110000110" => lookup <= "110001011";
|
||||
-- Data 8c
|
||||
when "1101111011" => lookup <= "110001100";
|
||||
when "0110000100" => lookup <= "110001100";
|
||||
-- Data 8d
|
||||
when "0101111011" => lookup <= "110001101";
|
||||
when "1110000100" => lookup <= "110001101";
|
||||
-- Data 8e
|
||||
when "1000101111" => lookup <= "110001110";
|
||||
when "0011010000" => lookup <= "110001110";
|
||||
-- Data 8f
|
||||
when "0000101111" => lookup <= "110001111";
|
||||
when "1011010000" => lookup <= "110001111";
|
||||
-- Data 90
|
||||
when "1110001111" => lookup <= "110010000";
|
||||
when "0101110000" => lookup <= "110010000";
|
||||
-- Data 91
|
||||
when "0110001111" => lookup <= "110010001";
|
||||
when "1101110000" => lookup <= "110010001";
|
||||
-- Data 92
|
||||
when "0110001110" => lookup <= "110010010"; -- TERC4 0110
|
||||
-- Data 93
|
||||
when "0101110001" => lookup <= "110010011"; -- TERC4 0100
|
||||
-- Data 94
|
||||
when "1101110011" => lookup <= "110010100";
|
||||
when "0110001100" => lookup <= "110010100";
|
||||
-- Data 95
|
||||
when "0101110011" => lookup <= "110010101";
|
||||
when "1110001100" => lookup <= "110010101";
|
||||
-- Data 96
|
||||
when "1000100111" => lookup <= "110010110";
|
||||
-- Data 97
|
||||
when "1011011000" => lookup <= "110010111";
|
||||
-- Data 98
|
||||
when "1101110111" => lookup <= "110011000";
|
||||
when "0110001000" => lookup <= "110011000";
|
||||
-- Data 99
|
||||
when "0101110111" => lookup <= "110011001";
|
||||
when "1110001000" => lookup <= "110011001";
|
||||
-- Data 9a
|
||||
when "0011011100" => lookup <= "110011010";
|
||||
when "1000100011" => lookup <= "110011010";
|
||||
-- Data 9b
|
||||
when "1011011100" => lookup <= "110011011";
|
||||
when "0000100011" => lookup <= "110011011";
|
||||
-- Data 9c
|
||||
when "0011011110" => lookup <= "110011100";
|
||||
when "1000100001" => lookup <= "110011100";
|
||||
-- Data 9d
|
||||
when "1011011110" => lookup <= "110011101";
|
||||
when "0000100001" => lookup <= "110011101";
|
||||
-- Data 9e
|
||||
when "1011011111" => lookup <= "110011110";
|
||||
when "0000100000" => lookup <= "110011110";
|
||||
-- Data 9f
|
||||
when "0011011111" => lookup <= "110011111";
|
||||
when "1000100000" => lookup <= "110011111";
|
||||
-- Data a0
|
||||
when "1110011111" => lookup <= "110100000";
|
||||
when "0101100000" => lookup <= "110100000";
|
||||
-- Data a1
|
||||
when "0110011111" => lookup <= "110100001";
|
||||
when "1101100000" => lookup <= "110100001";
|
||||
-- Data a2
|
||||
when "0110011110" => lookup <= "110100010";
|
||||
when "1101100001" => lookup <= "110100010";
|
||||
-- Data a3
|
||||
when "1110011110" => lookup <= "110100011";
|
||||
when "0101100001" => lookup <= "110100011";
|
||||
-- Data a4
|
||||
when "0110011100" => lookup <= "110100100"; -- TERC4 1010
|
||||
-- Data a5
|
||||
when "0101100011" => lookup <= "110100101"; -- TERC4 1110
|
||||
-- Data a6
|
||||
when "1000110111" => lookup <= "110100110";
|
||||
when "0011001000" => lookup <= "110100110";
|
||||
-- Data a7
|
||||
when "0000110111" => lookup <= "110100111";
|
||||
when "1011001000" => lookup <= "110100111";
|
||||
-- Data a8
|
||||
when "1101100111" => lookup <= "110101000";
|
||||
when "0110011000" => lookup <= "110101000";
|
||||
-- Data a9
|
||||
when "0101100111" => lookup <= "110101001";
|
||||
when "1110011000" => lookup <= "110101001";
|
||||
-- Data aa
|
||||
when "1000110011" => lookup <= "110101010";
|
||||
-- Data ab
|
||||
when "1011001100" => lookup <= "110101011"; -- TERC4 1000 & HDMI Guard band (video C0 and Video C2)
|
||||
-- Data ac
|
||||
when "0011001110" => lookup <= "110101100";
|
||||
when "1000110001" => lookup <= "110101100";
|
||||
-- Data ad
|
||||
when "1011001110" => lookup <= "110101101";
|
||||
when "0000110001" => lookup <= "110101101";
|
||||
-- Data ae
|
||||
when "1011001111" => lookup <= "110101110";
|
||||
when "0000110000" => lookup <= "110101110";
|
||||
-- Data af
|
||||
when "0011001111" => lookup <= "110101111";
|
||||
when "1000110000" => lookup <= "110101111";
|
||||
-- Data b0
|
||||
when "1101101111" => lookup <= "110110000";
|
||||
when "0110010000" => lookup <= "110110000";
|
||||
-- Data b1
|
||||
when "0101101111" => lookup <= "110110001";
|
||||
when "1110010000" => lookup <= "110110001";
|
||||
-- Data b2
|
||||
when "1000111011" => lookup <= "110110010";
|
||||
when "0011000100" => lookup <= "110110010";
|
||||
-- Data b3
|
||||
when "0000111011" => lookup <= "110110011";
|
||||
when "1011000100" => lookup <= "110110011";
|
||||
-- Data b4
|
||||
when "1000111001" => lookup <= "110110100";
|
||||
-- Data b5
|
||||
when "1011000110" => lookup <= "110110101"; -- TERC4 1011
|
||||
-- Data b6
|
||||
when "1011000111" => lookup <= "110110110";
|
||||
when "0000111000" => lookup <= "110110110";
|
||||
-- Data b7
|
||||
when "0011000111" => lookup <= "110110111";
|
||||
when "1000111000" => lookup <= "110110111";
|
||||
-- Data b8
|
||||
when "1000111101" => lookup <= "110111000";
|
||||
when "0011000010" => lookup <= "110111000";
|
||||
-- Data b9
|
||||
when "0000111101" => lookup <= "110111001";
|
||||
when "1011000010" => lookup <= "110111001";
|
||||
-- Data ba
|
||||
when "1011000011" => lookup <= "110111010"; -- TERC4 1111
|
||||
-- Data bb
|
||||
when "1000111100" => lookup <= "110111011";
|
||||
-- Data bc
|
||||
when "0000111110" => lookup <= "110111100";
|
||||
when "1011000001" => lookup <= "110111100";
|
||||
-- Data bd
|
||||
when "1000111110" => lookup <= "110111101";
|
||||
when "0011000001" => lookup <= "110111101";
|
||||
-- Data be
|
||||
when "1000111111" => lookup <= "110111110";
|
||||
when "0011000000" => lookup <= "110111110";
|
||||
-- Data bf
|
||||
when "0000111111" => lookup <= "110111111";
|
||||
when "1011000000" => lookup <= "110111111";
|
||||
-- Data c0
|
||||
when "1110111111" => lookup <= "111000000";
|
||||
when "0101000000" => lookup <= "111000000";
|
||||
-- Data c1
|
||||
when "0110111111" => lookup <= "111000001";
|
||||
when "1101000000" => lookup <= "111000001";
|
||||
-- Data c2
|
||||
when "0110111110" => lookup <= "111000010";
|
||||
when "1101000001" => lookup <= "111000010";
|
||||
-- Data c3
|
||||
when "1110111110" => lookup <= "111000011";
|
||||
when "0101000001" => lookup <= "111000011";
|
||||
-- Data c4
|
||||
when "0110111100" => lookup <= "111000100";
|
||||
when "1101000011" => lookup <= "111000100";
|
||||
-- Data c5
|
||||
when "1110111100" => lookup <= "111000101";
|
||||
when "0101000011" => lookup <= "111000101";
|
||||
-- Data c6
|
||||
when "1000010111" => lookup <= "111000110";
|
||||
-- Data c7
|
||||
when "1011101000" => lookup <= "111000111";
|
||||
-- Data c8
|
||||
when "0110111000" => lookup <= "111001000";
|
||||
-- Data c9
|
||||
when "0101000111" => lookup <= "111001001";
|
||||
-- Data ca
|
||||
when "0011101100" => lookup <= "111001010";
|
||||
when "1000010011" => lookup <= "111001010";
|
||||
-- Data cb
|
||||
when "1011101100" => lookup <= "111001011";
|
||||
when "0000010011" => lookup <= "111001011";
|
||||
-- Data cc
|
||||
when "0011101110" => lookup <= "111001100";
|
||||
when "1000010001" => lookup <= "111001100";
|
||||
-- Data cd
|
||||
when "1011101110" => lookup <= "111001101";
|
||||
when "0000010001" => lookup <= "111001101";
|
||||
-- Data ce
|
||||
when "1011101111" => lookup <= "111001110";
|
||||
when "0000010000" => lookup <= "111001110";
|
||||
-- Data cf
|
||||
when "0011101111" => lookup <= "111001111";
|
||||
when "1000010000" => lookup <= "111001111";
|
||||
-- Data d0
|
||||
when "1101001111" => lookup <= "111010000";
|
||||
when "0110110000" => lookup <= "111010000";
|
||||
-- Data d1
|
||||
when "0101001111" => lookup <= "111010001";
|
||||
when "1110110000" => lookup <= "111010001";
|
||||
-- Data d2
|
||||
when "1000011011" => lookup <= "111010010";
|
||||
-- Data d3
|
||||
when "1011100100" => lookup <= "111010011"; -- TERC4 0010
|
||||
-- Data d4
|
||||
when "0011100110" => lookup <= "111010100";
|
||||
when "1000011001" => lookup <= "111010100";
|
||||
-- Data d5
|
||||
when "1011100110" => lookup <= "111010101";
|
||||
when "0000011001" => lookup <= "111010101";
|
||||
-- Data d6
|
||||
when "1011100111" => lookup <= "111010110";
|
||||
when "0000011000" => lookup <= "111010110";
|
||||
-- Data d7
|
||||
when "0011100111" => lookup <= "111010111";
|
||||
when "1000011000" => lookup <= "111010111";
|
||||
-- Data d8
|
||||
when "1000011101" => lookup <= "111011000";
|
||||
-- Data d9
|
||||
when "1011100010" => lookup <= "111011001"; -- TERC4 0011
|
||||
-- Data da
|
||||
when "1011100011" => lookup <= "111011010";
|
||||
when "0000011100" => lookup <= "111011010";
|
||||
-- Data db
|
||||
when "0011100011" => lookup <= "111011011";
|
||||
when "1000011100" => lookup <= "111011011";
|
||||
-- Data dc
|
||||
when "1011100001" => lookup <= "111011100";
|
||||
-- Data dd
|
||||
when "1000011110" => lookup <= "111011101";
|
||||
-- Data de
|
||||
when "1000011111" => lookup <= "111011110";
|
||||
when "0011100000" => lookup <= "111011110";
|
||||
-- Data df
|
||||
when "0000011111" => lookup <= "111011111";
|
||||
when "1011100000" => lookup <= "111011111";
|
||||
-- Data e0
|
||||
when "1101011111" => lookup <= "111100000";
|
||||
when "0110100000" => lookup <= "111100000";
|
||||
-- Data e1
|
||||
when "0101011111" => lookup <= "111100001";
|
||||
when "1110100000" => lookup <= "111100001";
|
||||
-- Data e2
|
||||
when "0011110100" => lookup <= "111100010";
|
||||
when "1000001011" => lookup <= "111100010";
|
||||
-- Data e3
|
||||
when "1011110100" => lookup <= "111100011";
|
||||
when "0000001011" => lookup <= "111100011";
|
||||
-- Data e4
|
||||
when "0011110110" => lookup <= "111100100";
|
||||
when "1000001001" => lookup <= "111100100";
|
||||
-- Data e5
|
||||
when "1011110110" => lookup <= "111100101";
|
||||
when "0000001001" => lookup <= "111100101";
|
||||
-- Data e6
|
||||
when "1011110111" => lookup <= "111100110";
|
||||
when "0000001000" => lookup <= "111100110";
|
||||
-- Data e7
|
||||
when "0011110111" => lookup <= "111100111";
|
||||
when "1000001000" => lookup <= "111100111";
|
||||
-- Data e8
|
||||
when "0011110010" => lookup <= "111101000";
|
||||
when "1000001101" => lookup <= "111101000";
|
||||
-- Data e9
|
||||
when "1011110010" => lookup <= "111101001";
|
||||
when "0000001101" => lookup <= "111101001";
|
||||
-- Data ea
|
||||
when "1011110011" => lookup <= "111101010";
|
||||
when "0000001100" => lookup <= "111101010";
|
||||
-- Data eb
|
||||
when "0011110011" => lookup <= "111101011";
|
||||
when "1000001100" => lookup <= "111101011";
|
||||
-- Data ec
|
||||
when "1011110001" => lookup <= "111101100";
|
||||
when "0000001110" => lookup <= "111101100";
|
||||
-- Data ed
|
||||
when "0011110001" => lookup <= "111101101";
|
||||
when "1000001110" => lookup <= "111101101";
|
||||
-- Data ee
|
||||
when "1000001111" => lookup <= "111101110";
|
||||
-- Data ef
|
||||
when "1011110000" => lookup <= "111101111";
|
||||
-- Data f0
|
||||
when "0011111010" => lookup <= "111110000";
|
||||
when "1000000101" => lookup <= "111110000";
|
||||
-- Data f1
|
||||
when "1011111010" => lookup <= "111110001";
|
||||
when "0000000101" => lookup <= "111110001";
|
||||
-- Data f2
|
||||
when "1011111011" => lookup <= "111110010";
|
||||
when "0000000100" => lookup <= "111110010";
|
||||
-- Data f3
|
||||
when "0011111011" => lookup <= "111110011";
|
||||
when "1000000100" => lookup <= "111110011";
|
||||
-- Data f4
|
||||
when "1011111001" => lookup <= "111110100";
|
||||
when "0000000110" => lookup <= "111110100";
|
||||
-- Data f5
|
||||
when "0011111001" => lookup <= "111110101";
|
||||
when "1000000110" => lookup <= "111110101";
|
||||
-- Data f6
|
||||
when "0011111000" => lookup <= "111110110";
|
||||
when "1000000111" => lookup <= "111110110";
|
||||
-- Data f7
|
||||
when "1011111000" => lookup <= "111110111";
|
||||
when "0000000111" => lookup <= "111110111";
|
||||
-- Data f8
|
||||
when "1011111101" => lookup <= "111111000";
|
||||
when "0000000010" => lookup <= "111111000";
|
||||
-- Data f9
|
||||
when "0011111101" => lookup <= "111111001";
|
||||
when "1000000010" => lookup <= "111111001";
|
||||
-- Data fa
|
||||
when "0011111100" => lookup <= "111111010";
|
||||
when "1000000011" => lookup <= "111111010";
|
||||
-- Data fb
|
||||
when "1011111100" => lookup <= "111111011";
|
||||
when "0000000011" => lookup <= "111111011";
|
||||
-- Data fc
|
||||
when "0011111110" => lookup <= "111111100";
|
||||
when "1000000001" => lookup <= "111111100";
|
||||
-- Data fd
|
||||
when "1011111110" => lookup <= "111111101";
|
||||
when "0000000001" => lookup <= "111111101";
|
||||
-- Data fe
|
||||
when "1011111111" => lookup <= "111111110";
|
||||
when "0000000000" => lookup <= "111111110";
|
||||
-- Data ff
|
||||
when "0011111111" => lookup <= "111111111";
|
||||
when "1000000000" => lookup <= "111111111";
|
||||
|
||||
-- DVI-D CTL symbols
|
||||
when "0010101011" => lookup <= "01" & "00000" & "01"; -- CTL1
|
||||
when "0101010100" => lookup <= "01" & "00000" & "10"; -- CTL2
|
||||
when "1010101011" => lookup <= "01" & "00000" & "11"; -- CTL3
|
||||
when "1101010100" => lookup <= "01" & "00000" & "00"; -- CTL0
|
||||
|
||||
-- Invalid symbols
|
||||
when others => lookup <= "0000" & "00000";
|
||||
end case;
|
||||
end if;
|
||||
end process;
|
||||
end Behavioral;
|
||||
|
||||
-- For Guard band and TERC4 decoding (to be done later!)
|
||||
-- when x"55" => -- "0100110011" HDMI Guard band (video C1, data C1 & C2)
|
||||
-- when x"5B" => -- "1010011100" TERC4 0000
|
||||
-- when x"5A" => -- "1001100011" TERC4 0001
|
||||
-- when x"D3" => -- "1011100100" TERC4 0010
|
||||
-- when x"D9" => -- "1011100010" TERC4 0011
|
||||
-- when x"93" => -- "0101110001" TERC4 0100
|
||||
-- when x"22" => -- "0100011110" TERC4 0101
|
||||
-- when x"92" => -- "0110001110" TERC4 0110
|
||||
-- when x"44" => -- "0100111100" TERC4 0111
|
||||
-- when x"AB" => -- "1011001100" TERC4 1000 & HDMI Guard band (video C0 and Video C2)
|
||||
-- when x"4B" => -- "0100111001" TERC4 1001
|
||||
-- when x"A4" => -- "0110011100" TERC4 1010
|
||||
-- when x"B5" => -- "1011000110" TERC4 1011
|
||||
-- when x"6D" => -- "1010001110" TERC4 1100
|
||||
-- when x"6C" => -- "1001110001" TERC4 1101
|
||||
-- when x"A5" => -- "0101100011" TERC4 1110
|
||||
-- when x"BA" => -- "1011000011" TERC4 1111
|
||||
144
src/tmds_encoder.vhd
Normal file
144
src/tmds_encoder.vhd
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Module Name: tmds_encoder - Behavioral
|
||||
--
|
||||
-- Description: 8b/10b TMDS encoder
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- 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.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
entity 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 entity;
|
||||
|
||||
architecture Behavioral of tmds_encoder is
|
||||
signal xored : STD_LOGIC_VECTOR (8 downto 0);
|
||||
signal xnored : STD_LOGIC_VECTOR (8 downto 0);
|
||||
|
||||
signal ones : STD_LOGIC_VECTOR (3 downto 0);
|
||||
signal data_word : STD_LOGIC_VECTOR (8 downto 0);
|
||||
signal data_word_inv : STD_LOGIC_VECTOR (8 downto 0);
|
||||
signal data_word_disparity : STD_LOGIC_VECTOR (3 downto 0);
|
||||
signal dc_bias : STD_LOGIC_VECTOR (3 downto 0) := (others => '0');
|
||||
begin
|
||||
-- Work our the two different encodings for the byte
|
||||
xored(0) <= data(0);
|
||||
xored(1) <= data(1) xor xored(0);
|
||||
xored(2) <= data(2) xor xored(1);
|
||||
xored(3) <= data(3) xor xored(2);
|
||||
xored(4) <= data(4) xor xored(3);
|
||||
xored(5) <= data(5) xor xored(4);
|
||||
xored(6) <= data(6) xor xored(5);
|
||||
xored(7) <= data(7) xor xored(6);
|
||||
xored(8) <= '1';
|
||||
|
||||
xnored(0) <= data(0);
|
||||
xnored(1) <= data(1) xnor xnored(0);
|
||||
xnored(2) <= data(2) xnor xnored(1);
|
||||
xnored(3) <= data(3) xnor xnored(2);
|
||||
xnored(4) <= data(4) xnor xnored(3);
|
||||
xnored(5) <= data(5) xnor xnored(4);
|
||||
xnored(6) <= data(6) xnor xnored(5);
|
||||
xnored(7) <= data(7) xnor xnored(6);
|
||||
xnored(8) <= '0';
|
||||
|
||||
-- Count how many ones are set in data
|
||||
ones <= "0000" + data(0) + data(1) + data(2) + data(3)
|
||||
+ data(4) + data(5) + data(6) + data(7);
|
||||
|
||||
-- Decide which encoding to use
|
||||
process(ones, data(0), xnored, xored)
|
||||
begin
|
||||
if ones > 4 or (ones = 4 and data(0) = '0') then
|
||||
data_word <= xnored;
|
||||
data_word_inv <= NOT(xnored);
|
||||
else
|
||||
data_word <= xored;
|
||||
data_word_inv <= NOT(xored);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- Work out the DC bias of the dataword;
|
||||
data_word_disparity <= "1100" + data_word(0) + data_word(1) + data_word(2) + data_word(3)
|
||||
+ data_word(4) + data_word(5) + data_word(6) + data_word(7);
|
||||
|
||||
-- Now work out what the output should be
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if blank = '1' then
|
||||
-- In the control periods, all values have and have balanced bit count
|
||||
case c is
|
||||
when "00" => encoded <= "1101010100";
|
||||
when "01" => encoded <= "0010101011";
|
||||
when "10" => encoded <= "0101010100";
|
||||
when others => encoded <= "1010101011";
|
||||
end case;
|
||||
dc_bias <= (others => '0');
|
||||
else
|
||||
if dc_bias = "00000" or data_word_disparity = 0 then
|
||||
-- dataword has no disparity
|
||||
if data_word(8) = '1' then
|
||||
encoded <= "01" & data_word(7 downto 0);
|
||||
dc_bias <= dc_bias + data_word_disparity;
|
||||
else
|
||||
encoded <= "10" & data_word_inv(7 downto 0);
|
||||
dc_bias <= dc_bias - data_word_disparity;
|
||||
end if;
|
||||
elsif (dc_bias(3) = '0' and data_word_disparity(3) = '0') or
|
||||
(dc_bias(3) = '1' and data_word_disparity(3) = '1') then
|
||||
encoded <= '1' & data_word(8) & data_word_inv(7 downto 0);
|
||||
dc_bias <= dc_bias + data_word(8) - data_word_disparity;
|
||||
else
|
||||
encoded <= '0' & data_word;
|
||||
dc_bias <= dc_bias - data_word_inv(8) + data_word_disparity;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end Behavioral;
|
||||
148
test_bench/hdmi_test_generator/hdmi_ouput_test.vhd
Normal file
148
test_bench/hdmi_test_generator/hdmi_ouput_test.vhd
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Top level design for my minimal HDMI output project
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- The MIT License (MIT)
|
||||
--
|
||||
-- Copyright (c) 2015 Michael Alan Field
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
-- THE SOFTWARE.
|
||||
------------------------------------------------------------------------------------
|
||||
----- Want to say thanks? ----------------------------------------------------------
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- This design has taken many hours - with the industry metric of 30 lines
|
||||
-- per day, it is equivalent to about 6 months of work. I'm more than happy
|
||||
-- to share it if you can make use of it. It is released under the MIT license,
|
||||
-- so you are not under any onus to say thanks, but....
|
||||
--
|
||||
-- If you what to say thanks for this design how about trying PayPal?
|
||||
-- Educational use - Enough for a beer
|
||||
-- Hobbyist use - Enough for a pizza
|
||||
-- Research use - Enough to take the family out to dinner
|
||||
-- Commercial use - A weeks pay for an engineer (I wish!)
|
||||
--
|
||||
----------------------------------------------------------------------------------library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
entity hdmi_output_test is
|
||||
Port ( clk50 : in STD_LOGIC;
|
||||
|
||||
hdmi_out_p : out STD_LOGIC_VECTOR(3 downto 0);
|
||||
hdmi_out_n : out STD_LOGIC_VECTOR(3 downto 0);
|
||||
|
||||
leds : out std_logic_vector(7 downto 0));
|
||||
end hdmi_output_test;
|
||||
|
||||
architecture Behavioral of hdmi_output_test is
|
||||
|
||||
COMPONENT vga_gen
|
||||
PORT(
|
||||
clk50 : IN std_logic;
|
||||
pixel_clock : OUT std_logic;
|
||||
red_p : OUT std_logic_vector(7 downto 0);
|
||||
green_p : OUT std_logic_vector(7 downto 0);
|
||||
blue_p : OUT std_logic_vector(7 downto 0);
|
||||
blank : OUT std_logic;
|
||||
hsync : OUT std_logic;
|
||||
vsync : OUT std_logic
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
COMPONENT Minimal_hdmi_symbols
|
||||
PORT(
|
||||
clk : IN std_logic;
|
||||
blank : IN std_logic;
|
||||
hsync : IN std_logic;
|
||||
vsync : IN std_logic;
|
||||
red : IN std_logic;
|
||||
green : IN std_logic;
|
||||
blue : IN std_logic;
|
||||
c0 : OUT std_logic_vector(9 downto 0);
|
||||
c1 : OUT std_logic_vector(9 downto 0);
|
||||
c2 : OUT std_logic_vector(9 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
COMPONENT serializers
|
||||
PORT(
|
||||
clk : IN std_logic;
|
||||
c0 : IN std_logic_vector(9 downto 0);
|
||||
c1 : IN std_logic_vector(9 downto 0);
|
||||
c2 : IN std_logic_vector(9 downto 0);
|
||||
hdmi_p : OUT std_logic_vector(3 downto 0);
|
||||
hdmi_n : OUT std_logic_vector(3 downto 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
signal pixel_clock : std_logic;
|
||||
|
||||
signal red_p : std_logic_vector(7 downto 0);
|
||||
signal green_p : std_logic_vector(7 downto 0);
|
||||
signal blue_p : std_logic_vector(7 downto 0);
|
||||
signal blank : std_logic;
|
||||
signal hsync : std_logic;
|
||||
signal vsync : std_logic;
|
||||
|
||||
signal c0, c1, c2 : std_logic_vector(9 downto 0);
|
||||
begin
|
||||
leds <= x"AA";
|
||||
|
||||
---------------------------------------
|
||||
-- Generate a 1280x720 VGA test pattern
|
||||
---------------------------------------
|
||||
Inst_vga_gen: vga_gen PORT MAP(
|
||||
clk50 => clk50,
|
||||
pixel_clock => pixel_clock,
|
||||
red_p => red_p,
|
||||
green_p => green_p,
|
||||
blue_p => blue_p,
|
||||
blank => blank,
|
||||
hsync => hsync,
|
||||
vsync => vsync
|
||||
);
|
||||
|
||||
---------------------------------------------------
|
||||
-- Convert 9 bits of the VGA signals to the DVI-D/TMDS output
|
||||
---------------------------------------------------
|
||||
i_Minimal_hdmi_symbols: Minimal_hdmi_symbols PORT MAP(
|
||||
clk => pixel_clock,
|
||||
blank => blank,
|
||||
hsync => hsync,
|
||||
vsync => vsync,
|
||||
red => red_p(7),
|
||||
green => green_p(7),
|
||||
blue => blue_p(7),
|
||||
c0 => c0,
|
||||
c1 => c1,
|
||||
c2 => c2
|
||||
);
|
||||
|
||||
i_serializers : serializers PORT MAP (
|
||||
clk => pixel_clock,
|
||||
c0 => c0,
|
||||
c1 => c1,
|
||||
c2 => c2,
|
||||
hdmi_p => hdmi_out_p,
|
||||
hdmi_n => hdmi_out_n);
|
||||
|
||||
end Behavioral;
|
||||
|
||||
282
test_bench/hdmi_test_generator/minimal_hdmi_symbols.vhd
Normal file
282
test_bench/hdmi_test_generator/minimal_hdmi_symbols.vhd
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz<
|
||||
--
|
||||
-- Description: A minimal set of TMDS symbols - just enough to send a valid
|
||||
-- HDMI stream
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- The MIT License (MIT)
|
||||
--
|
||||
-- Copyright (c) 2015 Michael Alan Field
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
-- THE SOFTWARE.
|
||||
------------------------------------------------------------------------------------
|
||||
----- Want to say thanks? ----------------------------------------------------------
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- This design has taken many hours - with the industry metric of 30 lines
|
||||
-- per day, it is equivalent to about 6 months of work. I'm more than happy
|
||||
-- to share it if you can make use of it. It is released under the MIT license,
|
||||
-- so you are not under any onus to say thanks, but....
|
||||
--
|
||||
-- If you what to say thanks for this design how about trying PayPal?
|
||||
-- Educational use - Enough for a beer
|
||||
-- Hobbyist use - Enough for a pizza
|
||||
-- Research use - Enough to take the family out to dinner
|
||||
-- Commercial use - A weeks pay for an engineer (I wish!)
|
||||
--
|
||||
----------------------------------------------------------------------------------library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
entity minimal_hdmi_symbols is
|
||||
Port ( clk : in STD_LOGIC;
|
||||
hsync, vsync, blank : in STD_LOGIC;
|
||||
red, green, blue : in STD_LOGIC;
|
||||
c0, c1, c2 : out STD_LOGIC_VECTOR (9 downto 0));
|
||||
end minimal_hdmi_symbols;
|
||||
|
||||
architecture Behavioral of minimal_hdmi_symbols is
|
||||
type a_symbol_queue is array (0 to 10) of STD_LOGIC_VECTOR (4 downto 0);
|
||||
|
||||
signal symbol_queue : a_symbol_queue := (others => (others => '0'));
|
||||
signal symbols : STD_LOGIC_VECTOR (29 downto 0) := (others => '0');
|
||||
|
||||
signal last_blank : std_logic := '0';
|
||||
signal last_vsync : std_logic := '0';
|
||||
signal last_hsync : std_logic := '0';
|
||||
|
||||
signal data_island_armed : std_logic := '0';
|
||||
signal data_island_index : unsigned(5 downto 0) := (others => '1');
|
||||
begin
|
||||
c0 <= symbols(29 downto 20);
|
||||
c1 <= symbols(19 downto 10);
|
||||
c2 <= symbols( 9 downto 0);
|
||||
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
case symbol_queue(0) is
|
||||
---------------------------------------------------------------
|
||||
-- Eight TMDS encoded colours for testing
|
||||
---------------------------------------------------------------
|
||||
when "00000" => symbols <= "0111110000" & "0111110000" & "0111110000"; -- RGB 0x101010 - Black
|
||||
when "00001" => symbols <= "0111110000" & "0111110000" & "1011110000"; -- RGB 0xEF1010 - Red
|
||||
when "00010" => symbols <= "0111110000" & "1011110000" & "0111110000"; -- RGB 0x10EF10 - Green
|
||||
when "00011" => symbols <= "0111110000" & "1011110000" & "1011110000"; -- RGB 0xEFEF10 - Cyan
|
||||
when "00100" => symbols <= "1011110000" & "0111110000" & "0111110000"; -- RGB 0x1010EF - Blue
|
||||
when "00101" => symbols <= "1011110000" & "0111110000" & "1011110000"; -- RGB 0xEF10EF - Magenta
|
||||
when "00110" => symbols <= "1011110000" & "1011110000" & "0111110000"; -- RGB 0x10EFEF - Yellow
|
||||
when "00111" => symbols <= "1011110000" & "1011110000" & "1011110000"; -- RGB 0xEFEFEF - White
|
||||
---------------------------------------------------------------
|
||||
-- control symbols from 5.4.2 - part of the DVI-D standard
|
||||
---------------------------------------------------------------
|
||||
when "01000" => symbols <= "1101010100" & "1101010100" & "1101010100"; -- CTL periods
|
||||
when "01001" => symbols <= "0010101011" & "1101010100" & "1101010100"; -- Hsync
|
||||
when "01010" => symbols <= "0101010100" & "1101010100" & "1101010100"; -- vSync
|
||||
when "01011" => symbols <= "1010101011" & "1101010100" & "1101010100"; -- vSync+hSync
|
||||
---------------------------------------------------------------
|
||||
-- Symbols to signal the start of a HDMI feature
|
||||
---------------------------------------------------------------
|
||||
when "01100" => symbols <= "0101010100" & "0010101011" & "0010101011"; -- DataIslandPeamble, with VSYNC - 5.2.1.1
|
||||
when "01101" => symbols <= "0101100011" & "0100110011" & "0100110011"; -- DataIslandGuardBand, with VSYNC - 5.2.3.3
|
||||
when "01110" => symbols <= "1101010100" & "0010101011" & "1101010100"; -- VideoPramble 5.2.1.1
|
||||
when "01111" => symbols <= "1011001100" & "0100110011" & "1011001100"; -- VideoGuardBand 5.2.2.1
|
||||
|
||||
---------------------------------------------------------------
|
||||
-- From TERC4 codes in 5.4.3, and data data layout from 5.2.3.1
|
||||
--
|
||||
-- First nibble is used for the nFirstWordOfPacket (MSB) Header Bit, VSYNC, HSYNC (LSB).
|
||||
-- The packet is sent where VSYNC = '1' and HSYNC = '0', so we are left with 4 options
|
||||
-- Second nibble is used for the odd bits the four data sub-packets
|
||||
-- Third nibble is used for the even bits the four data sub-packets
|
||||
--
|
||||
-- These can be used to contruct a data island with any header
|
||||
-- and any data in subpacket 0, but all other subpackets
|
||||
-- must be 0s.
|
||||
---------------------------------------------------------------
|
||||
when "10000" => symbols <= "1011100100" & "1010011100" & "1010011100"; -- 0010 0000 0000, TERC4 coded
|
||||
when "10001" => symbols <= "1011100100" & "1010011100" & "1001100011"; -- 0010 0000 0001, TERC4 coded
|
||||
when "10010" => symbols <= "1011100100" & "1001100011" & "1010011100"; -- 0010 0000 0000, TERC4 coded
|
||||
when "10011" => symbols <= "1011100100" & "1001100011" & "1001100011"; -- 0010 0001 0001, TERC4 coded
|
||||
when "10100" => symbols <= "0110001110" & "1010011100" & "1010011100"; -- 0110 0000 0000, TERC4 coded
|
||||
when "10101" => symbols <= "0110001110" & "1010011100" & "1001100011"; -- 0110 0000 0001, TERC4 coded
|
||||
when "10110" => symbols <= "0110001110" & "1001100011" & "1010011100"; -- 0110 0001 0000, TERC4 coded
|
||||
when "10111" => symbols <= "0110001110" & "1001100011" & "1001100011"; -- 0110 0001 0001, TERC4 coded
|
||||
when "11000" => symbols <= "0110011100" & "1010011100" & "1010011100"; -- 1010 0000 0000, TERC4 coded
|
||||
when "11001" => symbols <= "0110011100" & "1010011100" & "1001100011"; -- 1010 0000 0001, TERC4 coded
|
||||
when "11010" => symbols <= "0110011100" & "1001100011" & "1010011100"; -- 1010 0001 0000, TERC4 coded
|
||||
when "11011" => symbols <= "0110011100" & "1001100011" & "1001100011"; -- 1010 0001 0001, TERC4 coded
|
||||
when "11100" => symbols <= "0101100011" & "1010011100" & "1010011100"; -- 1110 0000 0000, TERC4 coded
|
||||
when "11101" => symbols <= "0101100011" & "1010011100" & "1001100011"; -- 1110 0000 0001, TERC4 coded
|
||||
when "11110" => symbols <= "0101100011" & "1001100011" & "1010011100"; -- 1110 0001 0000, TERC4 coded
|
||||
when "11111" => symbols <= "0101100011" & "1001100011" & "1001100011"; -- 1110 0001 0001, TERC4 coded
|
||||
|
||||
when others => symbols <= (others => '0');
|
||||
end case;
|
||||
|
||||
if blank = '0' then
|
||||
-- Are we being asked to send video data? If so we need to send a peramble
|
||||
if last_blank = '1' then
|
||||
symbol_queue(10) <= "00" & blue & green & red;
|
||||
symbol_queue(9) <= "01111"; -- Video Guard Band
|
||||
symbol_queue(8) <= "01111";
|
||||
symbol_queue(7) <= "01110"; -- Video Preamble
|
||||
symbol_queue(6) <= "01110";
|
||||
symbol_queue(5) <= "01110";
|
||||
symbol_queue(4) <= "01110";
|
||||
symbol_queue(3) <= "01110";
|
||||
symbol_queue(2) <= "01110";
|
||||
symbol_queue(1) <= "01110";
|
||||
symbol_queue(0) <= "01110";
|
||||
else
|
||||
symbol_queue(0 to 9) <= symbol_queue(1 to 10);
|
||||
symbol_queue(10) <= "00" & blue & green & red;
|
||||
end if;
|
||||
else
|
||||
-- Just merge in the syncs into the control period
|
||||
case data_island_index is
|
||||
when "000000" => symbol_queue(10) <= "01100"; -- Data island preamble
|
||||
when "000001" => symbol_queue(10) <= "01100"; -- Data island preamble
|
||||
when "000010" => symbol_queue(10) <= "01100"; -- Data island preamble
|
||||
when "000011" => symbol_queue(10) <= "01100"; -- Data island preamble
|
||||
when "000100" => symbol_queue(10) <= "01100"; -- Data island preamble
|
||||
when "000101" => symbol_queue(10) <= "01100"; -- Data island preamble
|
||||
when "000110" => symbol_queue(10) <= "01100"; -- Data island preamble
|
||||
when "000111" => symbol_queue(10) <= "01100"; -- Data island preamble
|
||||
when "001000" => symbol_queue(10) <= "01101"; -- Data island Guard Band
|
||||
when "001001" => symbol_queue(10) <= "01101"; -- Data island Guard Band
|
||||
|
||||
|
||||
-------------------------
|
||||
-- For a YCC mode AVI Infoframe Data Island
|
||||
-------------------------
|
||||
-- Data Island (0-7)
|
||||
when "001010" => symbol_queue(10) <= "10011"; -- First word
|
||||
when "001011" => symbol_queue(10) <= "11111";
|
||||
when "001100" => symbol_queue(10) <= "11001";
|
||||
when "001101" => symbol_queue(10) <= "11000";
|
||||
when "001110" => symbol_queue(10) <= "11000";
|
||||
when "001111" => symbol_queue(10) <= "11000";
|
||||
when "010000" => symbol_queue(10) <= "11000";
|
||||
when "010001" => symbol_queue(10) <= "11110";
|
||||
-- Data Island (8-15)
|
||||
when "010010" => symbol_queue(10) <= "11000";
|
||||
when "010011" => symbol_queue(10) <= "11100";
|
||||
when "010100" => symbol_queue(10) <= "11000";
|
||||
when "010101" => symbol_queue(10) <= "11000";
|
||||
when "010110" => symbol_queue(10) <= "11000";
|
||||
when "010111" => symbol_queue(10) <= "11000";
|
||||
when "011000" => symbol_queue(10) <= "11000";
|
||||
when "011001" => symbol_queue(10) <= "11000";
|
||||
-- Data Island (16-23)
|
||||
when "011010" => symbol_queue(10) <= "11100";
|
||||
when "011011" => symbol_queue(10) <= "11000";
|
||||
when "011100" => symbol_queue(10) <= "11100";
|
||||
when "011101" => symbol_queue(10) <= "11100";
|
||||
when "011110" => symbol_queue(10) <= "11000";
|
||||
when "011111" => symbol_queue(10) <= "11000";
|
||||
when "100000" => symbol_queue(10) <= "11000";
|
||||
when "100001" => symbol_queue(10) <= "11000";
|
||||
-- Data Island (24-31)
|
||||
when "100010" => symbol_queue(10) <= "11000";
|
||||
when "100011" => symbol_queue(10) <= "11000";
|
||||
when "100100" => symbol_queue(10) <= "11100";
|
||||
when "100101" => symbol_queue(10) <= "11000";
|
||||
when "100110" => symbol_queue(10) <= "11010";
|
||||
when "100111" => symbol_queue(10) <= "11100";
|
||||
when "101000" => symbol_queue(10) <= "11111";
|
||||
when "101001" => symbol_queue(10) <= "11110";
|
||||
|
||||
-------------------------
|
||||
-- For a NULL Data Island
|
||||
-------------------------
|
||||
-- Data Island (0-7)
|
||||
-- when "001010" => symbol_queue(10) <= "10000"; -- First word
|
||||
-- when "001011" => symbol_queue(10) <= "11000";
|
||||
-- when "001100" => symbol_queue(10) <= "11000";
|
||||
-- when "001101" => symbol_queue(10) <= "11000";
|
||||
-- when "001110" => symbol_queue(10) <= "11000";
|
||||
-- when "001111" => symbol_queue(10) <= "11000";
|
||||
-- when "010000" => symbol_queue(10) <= "11000";
|
||||
-- when "010001" => symbol_queue(10) <= "11000";
|
||||
-- Data Island (8-15)
|
||||
-- when "010010" => symbol_queue(10) <= "11000";
|
||||
-- when "010011" => symbol_queue(10) <= "11000";
|
||||
-- when "010100" => symbol_queue(10) <= "11000";
|
||||
-- when "010101" => symbol_queue(10) <= "11000";
|
||||
-- when "010110" => symbol_queue(10) <= "11000";
|
||||
-- when "010111" => symbol_queue(10) <= "11000";
|
||||
-- when "011000" => symbol_queue(10) <= "11000";
|
||||
-- when "011001" => symbol_queue(10) <= "11000";
|
||||
-- Data Island (16-23)
|
||||
-- when "011010" => symbol_queue(10) <= "11000";
|
||||
-- when "011011" => symbol_queue(10) <= "11000";
|
||||
-- when "011100" => symbol_queue(10) <= "11000";
|
||||
-- when "011101" => symbol_queue(10) <= "11000";
|
||||
-- when "011110" => symbol_queue(10) <= "11000";
|
||||
-- when "011111" => symbol_queue(10) <= "11000";
|
||||
-- when "100000" => symbol_queue(10) <= "11000";
|
||||
-- when "100001" => symbol_queue(10) <= "11000";
|
||||
-- Data Island (24-31)
|
||||
-- when "100010" => symbol_queue(10) <= "11000";
|
||||
-- when "100011" => symbol_queue(10) <= "11000";
|
||||
-- when "100100" => symbol_queue(10) <= "11000";
|
||||
-- when "100101" => symbol_queue(10) <= "11000";
|
||||
-- when "100110" => symbol_queue(10) <= "11000";
|
||||
-- when "100111" => symbol_queue(10) <= "11000";
|
||||
-- when "101000" => symbol_queue(10) <= "11000";
|
||||
-- when "101001" => symbol_queue(10) <= "11000";
|
||||
|
||||
-- Trailing guard band
|
||||
when "101010" => symbol_queue(10) <= "01101"; -- Data island Guard Band
|
||||
when "101011" => symbol_queue(10) <= "01101"; -- Data island Guard Band
|
||||
-- There has to be four CTL symbols before the next block of video our data,
|
||||
-- But that won't be a problem for us, we will have the rest of the vertical
|
||||
-- Blanking interval
|
||||
when others => symbol_queue(10) <= "010" & Vsync & Hsync;
|
||||
end case;
|
||||
|
||||
symbol_queue(0 to 9) <= symbol_queue(1 to 10);
|
||||
end if;
|
||||
|
||||
if data_island_index /= "111111" then
|
||||
data_island_index <= data_island_index + 1;
|
||||
end if;
|
||||
|
||||
-- If we see the rising edge of vsync we need to send
|
||||
-- a data island the next time we see the hsync signal
|
||||
-- drop.
|
||||
if last_vsync = '0' and vsync = '1' then
|
||||
data_island_armed <= '1';
|
||||
end if;
|
||||
|
||||
if data_island_armed = '1' and last_hsync = '1' and hsync = '0' then
|
||||
data_island_index <= (others => '0');
|
||||
data_island_armed <= '0';
|
||||
end if;
|
||||
|
||||
last_blank <= blank;
|
||||
last_hsync <= hsync;
|
||||
last_vsync <= vsync;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end Behavioral;
|
||||
|
||||
165
test_bench/hdmi_test_generator/serializers.vhd
Normal file
165
test_bench/hdmi_test_generator/serializers.vhd
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Convert 3x 10-bit symbols to three serial channels and the clock channel.
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- The MIT License (MIT)
|
||||
--
|
||||
-- Copyright (c) 2015 Michael Alan Field
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
-- THE SOFTWARE.
|
||||
------------------------------------------------------------------------------------
|
||||
----- Want to say thanks? ----------------------------------------------------------
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- This design has taken many hours - with the industry metric of 30 lines
|
||||
-- per day, it is equivalent to about 6 months of work. I'm more than happy
|
||||
-- to share it if you can make use of it. It is released under the MIT license,
|
||||
-- so you are not under any onus to say thanks, but....
|
||||
--
|
||||
-- If you what to say thanks for this design how about trying PayPal?
|
||||
-- Educational use - Enough for a beer
|
||||
-- Hobbyist use - Enough for a pizza
|
||||
-- Research use - Enough to take the family out to dinner
|
||||
-- Commercial use - A weeks pay for an engineer (I wish!)
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
library UNISIM;
|
||||
use UNISIM.VComponents.all;
|
||||
|
||||
entity serializers is
|
||||
Port ( clk : in STD_LOGIC;
|
||||
c0 : in STD_LOGIC_VECTOR (9 downto 0);
|
||||
c1 : in STD_LOGIC_VECTOR (9 downto 0);
|
||||
c2 : in STD_LOGIC_VECTOR (9 downto 0);
|
||||
hdmi_p : out STD_LOGIC_VECTOR (3 downto 0);
|
||||
hdmi_n : out STD_LOGIC_VECTOR (3 downto 0));
|
||||
end serializers;
|
||||
|
||||
architecture Behavioral of serializers is
|
||||
-- For holding the outward bound TMDS symbols in the slow and fast domain
|
||||
signal c0_high_speed : std_logic_vector(9 downto 0) := (others => '0');
|
||||
signal c1_high_speed : std_logic_vector(9 downto 0) := (others => '0');
|
||||
signal c2_high_speed : std_logic_vector(9 downto 0) := (others => '0');
|
||||
signal clk_high_speed : std_logic_vector(9 downto 0) := (others => '0');
|
||||
signal c2_output_bits : std_logic_vector(1 downto 0) := "00";
|
||||
signal c1_output_bits : std_logic_vector(1 downto 0) := "00";
|
||||
signal c0_output_bits : std_logic_vector(1 downto 0) := "00";
|
||||
signal clk_output_bits : std_logic_vector(1 downto 0) := "00";
|
||||
|
||||
-- Controlling the transfers into the high speed domain
|
||||
signal latch_high_speed : std_logic_vector(4 downto 0) := "00001";
|
||||
|
||||
-- From the DDR outputs to the output buffers
|
||||
signal c0_serial, c1_serial, c2_serial, clk_serial : std_logic;
|
||||
|
||||
-- For generating the x5 clocks
|
||||
signal clk_x5, clk_x5_n, clk_x5_unbuffered : std_logic;
|
||||
signal clk_feedback : std_logic;
|
||||
|
||||
-- To glue the HSYNC and VSYNC into the control character.
|
||||
signal syncs : std_logic_vector(1 downto 0);
|
||||
begin
|
||||
|
||||
process(clk_x5)
|
||||
begin
|
||||
---------------------------------------------------------------
|
||||
-- Now take the 10-bit words and take it into the high-speed
|
||||
-- clock domain once every five cycles.
|
||||
--
|
||||
-- Then send out two bits every clock cycle using DDR output
|
||||
-- registers.
|
||||
---------------------------------------------------------------
|
||||
if rising_edge(clk_x5) then
|
||||
c0_output_bits <= c0_high_speed(1 downto 0);
|
||||
c1_output_bits <= c1_high_speed(1 downto 0);
|
||||
c2_output_bits <= c2_high_speed(1 downto 0);
|
||||
clk_output_bits <= clk_high_speed(1 downto 0);
|
||||
|
||||
if latch_high_speed(0) = '1' then
|
||||
c0_high_speed <= c0;
|
||||
c1_high_speed <= c1;
|
||||
c2_high_speed <= c2;
|
||||
clk_high_speed <= "0000011111";
|
||||
else
|
||||
c0_high_speed <= "00" & c0_high_speed(9 downto 2);
|
||||
c1_high_speed <= "00" & c1_high_speed(9 downto 2);
|
||||
c2_high_speed <= "00" & c2_high_speed(9 downto 2);
|
||||
clk_high_speed <= "00" & clk_high_speed(9 downto 2);
|
||||
end if;
|
||||
latch_high_speed <= latch_high_speed(0) & latch_high_speed(4 downto 1);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Convert the TMDS codes into a serial stream, two bits at a time
|
||||
------------------------------------------------------------------
|
||||
clk_x5_n <= not clk_x5;
|
||||
c0_to_serial: ODDR2
|
||||
generic map(DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
|
||||
port map (C0 => clk_x5, C1 => clk_x5_n, CE => '1', R => '0', S => '0',
|
||||
D0 => C0_output_bits(0), D1 => C0_output_bits(1), Q => c0_serial);
|
||||
OBUFDS_c0 : OBUFDS port map ( O => hdmi_p(0), OB => hdmi_n(0), I => c0_serial);
|
||||
|
||||
c1_to_serial: ODDR2
|
||||
generic map(DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
|
||||
port map (C0 => clk_x5, C1 => clk_x5_n, CE => '1', R => '0', S => '0',
|
||||
D0 => C1_output_bits(0), D1 => C1_output_bits(1), Q => c1_serial);
|
||||
OBUFDS_c1 : OBUFDS port map ( O => hdmi_p(1), OB => hdmi_n(1), I => c1_serial);
|
||||
|
||||
c2_to_serial: ODDR2
|
||||
generic map(DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
|
||||
port map (C0 => clk_x5, C1 => clk_x5_n, CE => '1', R => '0', S => '0',
|
||||
D0 => C2_output_bits(0), D1 => C2_output_bits(1), Q => c2_serial);
|
||||
OBUFDS_c2 : OBUFDS port map ( O => hdmi_p(2), OB => hdmi_n(2), I => c2_serial);
|
||||
|
||||
clk_to_serial: ODDR2
|
||||
generic map(DDR_ALIGNMENT => "C0", INIT => '0', SRTYPE => "ASYNC")
|
||||
port map (C0 => clk_x5, C1 => clk_x5_n, CE => '1', R => '0', S => '0',
|
||||
D0 => Clk_output_bits(0), D1 => Clk_output_bits(1), Q => clk_serial);
|
||||
OBUFDS_clk : OBUFDS port map ( O => hdmi_p(3), OB => hdmi_n(3), I => clk_serial);
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- Use a PLL to generate a x5 clock, which is used to drive
|
||||
-- the DDR registers.This allows 10 bits to be sent for every
|
||||
-- pixel clock
|
||||
------------------------------------------------------------------
|
||||
PLL_BASE_inst : PLL_BASE
|
||||
generic map (
|
||||
CLKFBOUT_MULT => 10,
|
||||
CLKOUT0_DIVIDE => 2, CLKOUT0_PHASE => 0.0, -- Output 5x original frequency
|
||||
CLK_FEEDBACK => "CLKFBOUT",
|
||||
CLKIN_PERIOD => 13.33,
|
||||
DIVCLK_DIVIDE => 1
|
||||
)
|
||||
port map (
|
||||
CLKFBOUT => clk_feedback,
|
||||
CLKOUT0 => clk_x5_unbuffered,
|
||||
CLKFBIN => clk_feedback,
|
||||
CLKIN => clk,
|
||||
RST => '0'
|
||||
);
|
||||
|
||||
BUFG_pclkx5 : BUFG port map ( I => clk_x5_unbuffered, O => clk_x5);
|
||||
|
||||
end Behavioral;
|
||||
|
||||
89
test_bench/hdmi_test_generator/vga_clocking.vhd
Normal file
89
test_bench/hdmi_test_generator/vga_clocking.vhd
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz<
|
||||
--
|
||||
-- Description: Generate a 40Mhz Pixel clock from the 50Mhz input
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- The MIT License (MIT)
|
||||
--
|
||||
-- Copyright (c) 2015 Michael Alan Field
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
-- THE SOFTWARE.
|
||||
------------------------------------------------------------------------------------
|
||||
----- Want to say thanks? ----------------------------------------------------------
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- This design has taken many hours - with the industry metric of 30 lines
|
||||
-- per day, it is equivalent to about 6 months of work. I'm more than happy
|
||||
-- to share it if you can make use of it. It is released under the MIT license,
|
||||
-- so you are not under any onus to say thanks, but....
|
||||
--
|
||||
-- If you what to say thanks for this design how about trying PayPal?
|
||||
-- Educational use - Enough for a beer
|
||||
-- Hobbyist use - Enough for a pizza
|
||||
-- Research use - Enough to take the family out to dinner
|
||||
-- Commercial use - A weeks pay for an engineer (I wish!)
|
||||
--
|
||||
----------------------------------------------------------------------------------library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
library UNISIM;
|
||||
use UNISIM.VComponents.all;
|
||||
|
||||
entity vga_clocking is
|
||||
Port ( clk50 : in STD_LOGIC;
|
||||
pixel_clock : out STD_LOGIC);
|
||||
end vga_clocking;
|
||||
|
||||
architecture Behavioral of vga_clocking is
|
||||
signal clock_x1 : std_logic;
|
||||
signal clock_x1_unbuffered : std_logic;
|
||||
signal clk_feedback : std_logic;
|
||||
signal clk50_buffered : std_logic;
|
||||
signal pll_locked : std_logic;
|
||||
begin
|
||||
pixel_clock <= clock_x1;
|
||||
|
||||
-- Multiply clk50m by 15, then divide by 10 for the 75 MHz pixel clock
|
||||
-- Because the all come from the same PLL the will all be in phase
|
||||
PLL_BASE_inst : PLL_BASE
|
||||
generic map (
|
||||
CLKFBOUT_MULT => 16,
|
||||
CLKOUT0_DIVIDE => 20, CLKOUT0_PHASE => 0.0, -- Output pixel clock, 1.5x original frequency
|
||||
CLK_FEEDBACK => "CLKFBOUT", -- Clock source to drive CLKFBIN ("CLKFBOUT" or "CLKOUT0")
|
||||
CLKIN_PERIOD => 20.0, -- IMPORTANT! 20.00 => 50MHz
|
||||
DIVCLK_DIVIDE => 1 -- Division value for all output clocks (1-52)
|
||||
)
|
||||
port map (
|
||||
CLKFBOUT => clk_feedback,
|
||||
CLKOUT0 => clock_x1_unbuffered,
|
||||
CLKOUT1 => open,
|
||||
CLKOUT2 => open,
|
||||
CLKOUT3 => open,
|
||||
CLKOUT4 => open,
|
||||
CLKOUT5 => open,
|
||||
LOCKED => pll_locked,
|
||||
CLKFBIN => clk_feedback,
|
||||
CLKIN => clk50_buffered,
|
||||
RST => '0' -- 1-bit input: Reset input
|
||||
);
|
||||
|
||||
BUFG_clk : BUFG port map ( I => clk50, O => clk50_buffered);
|
||||
BUFG_pclock : BUFG port map ( I => clock_x1_unbuffered, O => clock_x1);
|
||||
|
||||
end Behavioral;
|
||||
142
test_bench/hdmi_test_generator/vga_gen.vhd
Normal file
142
test_bench/hdmi_test_generator/vga_gen.vhd
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Description: Generates a test 1280x720 signal
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- The MIT License (MIT)
|
||||
--
|
||||
-- Copyright (c) 2015 Michael Alan Field
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
-- THE SOFTWARE.
|
||||
------------------------------------------------------------------------------------
|
||||
----- Want to say thanks? ----------------------------------------------------------
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- This design has taken many hours - with the industry metric of 30 lines
|
||||
-- per day, it is equivalent to about 6 months of work. I'm more than happy
|
||||
-- to share it if you can make use of it. It is released under the MIT license,
|
||||
-- so you are not under any onus to say thanks, but....
|
||||
--
|
||||
-- If you what to say thanks for this design how about trying PayPal?
|
||||
-- Educational use - Enough for a beer
|
||||
-- Hobbyist use - Enough for a pizza
|
||||
-- Research use - Enough to take the family out to dinner
|
||||
-- Commercial use - A weeks pay for an engineer (I wish!)
|
||||
--
|
||||
----------------------------------------------------------------------------------library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
entity vga_gen is
|
||||
Port ( clk50 : in STD_LOGIC;
|
||||
pixel_clock : out std_logic;
|
||||
|
||||
red_p : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
|
||||
green_p : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
|
||||
blue_p : out STD_LOGIC_VECTOR (7 downto 0) := (others => '0');
|
||||
blank : out STD_LOGIC := '0';
|
||||
hsync : out STD_LOGIC := '0';
|
||||
vsync : out STD_LOGIC := '0');
|
||||
end vga_gen;
|
||||
|
||||
architecture Behavioral of vga_gen is
|
||||
COMPONENT vga_clocking
|
||||
PORT( clk50 : IN std_logic;
|
||||
pixel_clock : OUT std_logic);
|
||||
END COMPONENT;
|
||||
|
||||
constant h_rez : natural := 800;
|
||||
constant h_sync_start : natural := 800+40;
|
||||
constant h_sync_end : natural := 800+40+128;
|
||||
constant h_max : natural := 1056;
|
||||
signal h_count : unsigned(11 downto 0) := (others => '0');
|
||||
signal h_offset : unsigned(7 downto 0) := (others => '0');
|
||||
|
||||
constant v_rez : natural := 600;
|
||||
constant v_sync_start : natural := 600+1;
|
||||
constant v_sync_end : natural := 600+1+4;
|
||||
constant v_max : natural := 628;
|
||||
signal v_count : unsigned(11 downto 0) := x"250";
|
||||
signal v_offset : unsigned(7 downto 0) := (others => '0');
|
||||
signal clk40 : std_logic;
|
||||
begin
|
||||
|
||||
Inst_clocking: vga_clocking PORT MAP(
|
||||
clk50 => clk50,
|
||||
pixel_clock => clk40
|
||||
);
|
||||
pixel_clock <= clk40;
|
||||
|
||||
|
||||
process(clk40)
|
||||
begin
|
||||
if rising_edge(clk40) then
|
||||
if h_count < h_rez and v_count < v_rez then
|
||||
red_p <= std_logic_vector(h_count(7 downto 0)+h_offset);
|
||||
green_p <= std_logic_vector(v_count(7 downto 0)+v_offset);
|
||||
blue_p <= std_logic_vector(h_count(7 downto 0)+v_count(7 downto 0));
|
||||
blank <= '0';
|
||||
if h_count = 0 or h_count = h_rez-1 then
|
||||
red_p <= (others => '1');
|
||||
green_p <= (others => '1');
|
||||
blue_p <= (others => '1');
|
||||
end if;
|
||||
if v_count = 0 or v_count = v_rez-1 then
|
||||
red_p <= (others => '1');
|
||||
green_p <= (others => '0');
|
||||
blue_p <= (others => '0');
|
||||
end if;
|
||||
else
|
||||
red_p <= (others => '0');
|
||||
green_p <= (others => '0');
|
||||
blue_p <= (others => '0');
|
||||
blank <= '1';
|
||||
end if;
|
||||
|
||||
if h_count >= h_sync_start and h_count < h_sync_end then
|
||||
hsync <= '1';
|
||||
else
|
||||
hsync <= '0';
|
||||
end if;
|
||||
|
||||
if v_count >= v_sync_start and v_count < v_sync_end then
|
||||
vsync <= '1';
|
||||
else
|
||||
vsync <= '0';
|
||||
end if;
|
||||
|
||||
if h_count = h_max then
|
||||
h_count <= (others => '0');
|
||||
if v_count = v_max then
|
||||
h_offset <= h_offset + 1;
|
||||
v_offset <= v_offset + 1;
|
||||
v_count <= (others => '0');
|
||||
else
|
||||
v_count <= v_count+1;
|
||||
end if;
|
||||
else
|
||||
h_count <= h_count+1;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end Behavioral;
|
||||
|
||||
110
test_bench/tb_audio_to_db.vhd
Normal file
110
test_bench/tb_audio_to_db.vhd
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Module Name: tb_audio_to_db - Behavioral
|
||||
--
|
||||
-- Description: A testbench for the audio sample to db level calculation
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
-- The MIT License (MIT)
|
||||
--
|
||||
-- Copyright (c) 2015 Michael Alan Field
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
-- THE SOFTWARE.
|
||||
----------------------------------------------------------------------------------
|
||||
----- Want to say thanks? --------------------------------------------------------
|
||||
----------------------------------------------------------------------------------
|
||||
--
|
||||
-- This design has taken many hours - with the industry metric of 30 lines
|
||||
-- per day, it is equivalent to about 6 months of work. I'm more than happy
|
||||
-- to share it if you can make use of it. It is released under the MIT license,
|
||||
-- so you are not under any onus to say thanks, but....
|
||||
--
|
||||
-- If you what to say thanks for this design how about trying PayPal?
|
||||
-- Educational use - Enough for a beer
|
||||
-- Hobbyist use - Enough for a pizza
|
||||
-- Research use - Enough to take the family out to dinner
|
||||
-- Commercial use - A weeks pay for an engineer (I wish!)
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
entity tb_audio_to_db is
|
||||
end tb_audio_to_db;
|
||||
|
||||
architecture Behavioral of tb_audio_to_db is
|
||||
component audio_to_db is
|
||||
Port ( clk : in STD_LOGIC;
|
||||
|
||||
in_channel : in STD_LOGIC_VECTOR (2 downto 0);
|
||||
in_de : in STD_LOGIC;
|
||||
in_sample : in STD_LOGIC_VECTOR (23 downto 0);
|
||||
|
||||
out_channel : out STD_LOGIC_VECTOR (2 downto 0);
|
||||
out_de : out STD_LOGIC;
|
||||
out_level : out STD_LOGIC_VECTOR (5 downto 0));
|
||||
end component;
|
||||
|
||||
signal clk : STD_LOGIC := '0';
|
||||
|
||||
signal in_channel : STD_LOGIC_VECTOR (2 downto 0) := (others => '0');
|
||||
signal in_de : STD_LOGIC := '1';
|
||||
signal in_sample : STD_LOGIC_VECTOR (23 downto 0) := (others => '0');
|
||||
|
||||
signal out_channel : STD_LOGIC_VECTOR (2 downto 0);
|
||||
signal out_de : STD_LOGIC;
|
||||
signal out_level : STD_LOGIC_VECTOR (5 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
process
|
||||
begin
|
||||
wait for 5 ns;
|
||||
clk <= '1';
|
||||
wait for 5 ns;
|
||||
clk <= '0';
|
||||
end process;
|
||||
|
||||
process
|
||||
begin
|
||||
wait until rising_edge(clk);
|
||||
in_de <= '1';
|
||||
in_sample <= in_sample(in_sample'high-1 downto 0) & not in_sample(in_sample'high);
|
||||
wait until rising_edge(clk);
|
||||
in_de <= '0';
|
||||
wait until rising_edge(clk);
|
||||
wait until rising_edge(clk);
|
||||
wait until rising_edge(clk);
|
||||
wait until rising_edge(clk);
|
||||
end process;
|
||||
|
||||
uut: audio_to_db port map (
|
||||
clk => clk,
|
||||
in_channel => in_channel,
|
||||
in_de => in_de,
|
||||
in_sample => in_sample,
|
||||
|
||||
out_channel => out_channel,
|
||||
out_de => out_de,
|
||||
out_level => out_level);
|
||||
|
||||
end Behavioral;
|
||||
147
test_bench/tb_convert_yCbCr_to_RGB.vhd
Normal file
147
test_bench/tb_convert_yCbCr_to_RGB.vhd
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Description: A testbench for YCbCr to RGB decoding
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- The MIT License (MIT)
|
||||
--
|
||||
-- Copyright (c) 2015 Michael Alan Field
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
-- THE SOFTWARE.
|
||||
------------------------------------------------------------------------------------
|
||||
----- Want to say thanks? ----------------------------------------------------------
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- This design has taken many hours - with the industry metric of 30 lines
|
||||
-- per day, it is equivalent to about 6 months of work. I'm more than happy
|
||||
-- to share it if you can make use of it. It is released under the MIT license,
|
||||
-- so you are not under any onus to say thanks, but....
|
||||
--
|
||||
-- If you what to say thanks for this design how about trying PayPal?
|
||||
-- Educational use - Enough for a beer
|
||||
-- Hobbyist use - Enough for a pizza
|
||||
-- Research use - Enough to take the family out to dinner
|
||||
-- Commercial use - A weeks pay for an engineer (I wish!)
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
-- Uncomment the following library declaration if using
|
||||
-- arithmetic functions with Signed or Unsigned values
|
||||
--use IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
-- Uncomment the following library declaration if instantiating
|
||||
-- any Xilinx leaf cells in this code.
|
||||
--library UNISIM;
|
||||
--use UNISIM.VComponents.all;
|
||||
|
||||
entity tb_convert_yCbCr_to_RGB is
|
||||
end tb_convert_yCbCr_to_RGB;
|
||||
|
||||
architecture Behavioral of tb_convert_yCbCr_to_RGB is
|
||||
component conversion_YCbCr_to_RGB is
|
||||
port ( clk : in std_Logic;
|
||||
input_is_YCbCr : in std_Logic;
|
||||
|
||||
------------------------
|
||||
in_blank : in std_logic;
|
||||
in_hsync : in std_logic;
|
||||
in_vsync : in std_logic;
|
||||
in_U : in std_logic_vector(11 downto 0); -- B or Cb
|
||||
in_V : in std_logic_vector(11 downto 0); -- G or Y
|
||||
in_W : in std_logic_vector(11 downto 0); -- R or Cr
|
||||
|
||||
------------------------
|
||||
out_blank : out std_logic;
|
||||
out_hsync : out std_logic;
|
||||
out_vsync : out std_logic;
|
||||
out_R : out std_logic_vector(11 downto 0);
|
||||
out_G : out std_logic_vector(11 downto 0);
|
||||
out_B : out std_logic_vector(11 downto 0));
|
||||
end component;
|
||||
|
||||
signal clk : std_Logic := '0';
|
||||
signal input_is_YCbCr : std_Logic := '0';
|
||||
signal in_blank : std_logic := '0';
|
||||
signal in_hsync : std_logic := '0';
|
||||
signal in_vsync : std_logic := '0';
|
||||
signal in_U : std_logic_vector(11 downto 0) := x"800"; -- B or Cb
|
||||
signal in_V : std_logic_vector(11 downto 0) := x"800"; -- G or Y
|
||||
signal in_W : std_logic_vector(11 downto 0) := x"800"; -- R or Cr
|
||||
signal out_blank : std_logic := '0';
|
||||
signal out_hsync : std_logic := '0';
|
||||
signal out_vsync : std_logic := '0';
|
||||
signal out_R : std_logic_vector(11 downto 0);
|
||||
signal out_G : std_logic_vector(11 downto 0);
|
||||
signal out_B : std_logic_vector(11 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
process
|
||||
begin
|
||||
wait for 5 ns;
|
||||
clk <= not clk;
|
||||
end process;
|
||||
|
||||
stim: process
|
||||
begin
|
||||
wait for 100 ns;
|
||||
in_U <= x"100";
|
||||
wait for 100 ns;
|
||||
in_U <= x"EFF";
|
||||
wait for 100 ns;
|
||||
in_U <= x"800";
|
||||
|
||||
wait for 100 ns;
|
||||
in_V <= x"100";
|
||||
wait for 100 ns;
|
||||
in_V <= x"EFF";
|
||||
wait for 100 ns;
|
||||
in_V <= x"800";
|
||||
|
||||
wait for 100 ns;
|
||||
in_W <= x"100";
|
||||
wait for 100 ns;
|
||||
in_W <= x"EFF";
|
||||
wait for 100 ns;
|
||||
in_W <= x"800";
|
||||
|
||||
end process;
|
||||
uut: conversion_YCbCr_to_RGB port map (
|
||||
clk => clk,
|
||||
input_is_YCbCr => '1',
|
||||
------------------------
|
||||
in_blank => in_blank,
|
||||
in_hsync => in_hsync,
|
||||
in_vsync => in_vsync,
|
||||
in_U => in_U,
|
||||
in_V => in_V,
|
||||
in_W => in_W,
|
||||
------------------------
|
||||
out_blank => out_blank,
|
||||
out_hsync => out_hsync,
|
||||
out_vsync => out_vsync,
|
||||
out_R => out_R,
|
||||
out_G => out_G,
|
||||
out_B => out_B);
|
||||
|
||||
end Behavioral;
|
||||
308
test_bench/tb_hdmi_decode.vhd
Normal file
308
test_bench/tb_hdmi_decode.vhd
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
----------------------------------------------------------------------------------
|
||||
-- Engineer: Mike Field <hamster@snap.net.nz>
|
||||
--
|
||||
-- Module Name: tb_hdmi_decode - Behavioral
|
||||
--
|
||||
-- Description: A testbench for testing HDMI decoding
|
||||
--
|
||||
------------------------------------------------------------------------------------
|
||||
-- The MIT License (MIT)
|
||||
--
|
||||
-- Copyright (c) 2015 Michael Alan Field
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
-- of this software and associated documentation files (the "Software"), to deal
|
||||
-- in the Software without restriction, including without limitation the rights
|
||||
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
-- copies of the Software, and to permit persons to whom the Software is
|
||||
-- furnished to do so, subject to the following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in
|
||||
-- all copies or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
-- THE SOFTWARE.
|
||||
----------------------------------------------------------------------------------
|
||||
----- Want to say thanks? ----------------------------------------------------------
|
||||
------------------------------------------------------------------------------------
|
||||
--
|
||||
-- This design has taken many hours - with the industry metric of 30 lines
|
||||
-- per day, it is equivalent to about 6 months of work. I'm more than happy
|
||||
-- to share it if you can make use of it. It is released under the MIT license,
|
||||
-- so you are not under any onus to say thanks, but....
|
||||
--
|
||||
-- If you what to say thanks for this design how about trying PayPal?
|
||||
-- Educational use - Enough for a beer
|
||||
-- Hobbyist use - Enough for a pizza
|
||||
-- Research use - Enough to take the family out to dinner
|
||||
-- Commercial use - A weeks pay for an engineer (I wish!)
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
entity tb_hdmi_decode is
|
||||
end tb_hdmi_decode;
|
||||
|
||||
architecture Behavioral of tb_hdmi_decode is
|
||||
component hdmi_design is
|
||||
Port (
|
||||
clk100 : in STD_LOGIC;
|
||||
-- Control signals
|
||||
led : out std_logic_vector(7 downto 0);
|
||||
sw : in std_logic_vector(2 downto 0) :=(others => '0');
|
||||
debug_pmod : out std_logic_vector(7 downto 0) :=(others => '0');
|
||||
|
||||
--HDMI input signals
|
||||
hdmi_rx_cec : inout std_logic;
|
||||
hdmi_rx_hpa : out std_logic;
|
||||
hdmi_rx_scl : in std_logic;
|
||||
hdmi_rx_sda : inout std_logic;
|
||||
hdmi_rx_txen : out std_logic;
|
||||
hdmi_rx_clk_n : in std_logic;
|
||||
hdmi_rx_clk_p : in std_logic;
|
||||
hdmi_rx_n : in std_logic_vector(2 downto 0);
|
||||
hdmi_rx_p : in std_logic_vector(2 downto 0);
|
||||
|
||||
--- HDMI out
|
||||
hdmi_tx_cec : inout std_logic;
|
||||
hdmi_tx_clk_n : out std_logic;
|
||||
hdmi_tx_clk_p : out std_logic;
|
||||
hdmi_tx_hpd : in std_logic;
|
||||
hdmi_tx_rscl : inout std_logic;
|
||||
hdmi_tx_rsda : inout std_logic;
|
||||
hdmi_tx_p : out std_logic_vector(2 downto 0);
|
||||
hdmi_tx_n : out std_logic_vector(2 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
component hdmi_output_test is
|
||||
Port ( clk50 : in STD_LOGIC;
|
||||
|
||||
hdmi_out_p : out STD_LOGIC_VECTOR(3 downto 0);
|
||||
hdmi_out_n : out STD_LOGIC_VECTOR(3 downto 0);
|
||||
|
||||
leds : out std_logic_vector(7 downto 0));
|
||||
end component;
|
||||
|
||||
|
||||
signal clk : std_logic := '0';
|
||||
signal clk50 : std_logic := '1';
|
||||
signal led : std_logic_vector(7 downto 0);
|
||||
signal hdmi_rx_cec : std_logic;
|
||||
signal hdmi_rx_hpa : std_logic;
|
||||
signal hdmi_rx_scl : std_logic;
|
||||
signal hdmi_rx_sda : std_logic;
|
||||
signal hdmi_rx_txen : std_logic;
|
||||
signal hdmi_rx_clk_n : std_logic;
|
||||
signal hdmi_rx_clk_p : std_logic;
|
||||
signal hdmi2_rx_clk_n : std_logic := '1';
|
||||
signal hdmi2_rx_clk_p : std_logic := '0';
|
||||
signal hdmi_out_n : std_logic_vector(3 downto 0);
|
||||
signal hdmi_out_p : std_logic_vector(3 downto 0);
|
||||
signal hdmi_rx_n : std_logic_vector(2 downto 0);
|
||||
signal hdmi_rx_p : std_logic_vector(2 downto 0);
|
||||
signal hdmi_tx_cec : std_logic;
|
||||
signal hdmi_tx_clk_n : std_logic;
|
||||
signal hdmi_tx_clk_p : std_logic;
|
||||
signal hdmi_tx_hpd : std_logic;
|
||||
signal hdmi_tx_rscl : std_logic;
|
||||
signal hdmi_tx_rsda : std_logic;
|
||||
signal hdmi_tx_p : std_logic_vector(2 downto 0);
|
||||
signal hdmi_tx_n : std_logic_vector(2 downto 0);
|
||||
|
||||
signal sdat_drive : std_logic := '1';
|
||||
begin
|
||||
hdmi_rx_sda <= '0' when sdat_drive = '0' else 'H';
|
||||
|
||||
hdmi_rx_p <= transport hdmi_out_p(2 downto 0) after 5.00 ns;
|
||||
hdmi_rx_n <= transport hdmi_out_n(2 downto 0) after 5.00 ns;
|
||||
hdmi_rx_clk_p <= transport hdmi_out_p(3) after 1.25 ns;
|
||||
hdmi_rx_clk_n <= transport hdmi_out_n(3) after 1.25 ns;
|
||||
|
||||
clk_proc: process
|
||||
begin
|
||||
wait for 7.0 ns;
|
||||
while 1 = 1 loop
|
||||
wait for 5.0 ns;
|
||||
clk <= not clk;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
clk50_proc: process
|
||||
begin
|
||||
wait for 7.0 ns;
|
||||
while 1 = 1 loop
|
||||
wait for 5.0 ns;
|
||||
clk50 <= not clk50;
|
||||
end loop;
|
||||
end process;
|
||||
|
||||
i_gen_signal: hdmi_output_test port map (
|
||||
clk50 => clk50,
|
||||
hdmi_out_p => hdmi_out_p,
|
||||
hdmi_out_n => hdmi_out_n,
|
||||
leds => open);
|
||||
|
||||
uut: hdmi_design Port map (
|
||||
clk100 => clk,
|
||||
led => open,
|
||||
sw => (others => '0'),
|
||||
debug_pmod => open,
|
||||
--HDMI in
|
||||
hdmi_rx_cec => hdmi_rx_cec,
|
||||
hdmi_rx_hpa => hdmi_rx_hpa,
|
||||
hdmi_rx_scl => hdmi_rx_scl,
|
||||
hdmi_rx_sda => hdmi_rx_sda,
|
||||
hdmi_rx_txen => hdmi_rx_txen,
|
||||
hdmi_rx_clk_n => hdmi_rx_clk_n,
|
||||
hdmi_rx_clk_p => hdmi_rx_clk_p,
|
||||
hdmi_rx_n => hdmi_rx_n,
|
||||
hdmi_rx_p => hdmi_rx_p,
|
||||
|
||||
--- HDMI out
|
||||
hdmi_tx_cec => hdmi_tx_cec,
|
||||
hdmi_tx_clk_n => hdmi_tx_clk_n,
|
||||
hdmi_tx_clk_p => hdmi_tx_clk_p,
|
||||
hdmi_tx_hpd => hdmi_tx_hpd,
|
||||
hdmi_tx_rscl => hdmi_tx_rscl,
|
||||
hdmi_tx_rsda => hdmi_tx_rsda,
|
||||
hdmi_tx_p => hdmi_tx_p,
|
||||
hdmi_tx_n => hdmi_tx_n
|
||||
);
|
||||
|
||||
edid_test_proc: process
|
||||
begin
|
||||
hdmi_rx_scl <= '1';
|
||||
wait for 1 us;
|
||||
-- START condition
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- DEVICE ADDRESS FOR WRITE
|
||||
-- dev bit 7
|
||||
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 6
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 6
|
||||
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 4
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 3
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 2
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 1
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 0
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- Slave ACK
|
||||
-- Device to ack
|
||||
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- SEND WRITE ADDRESS
|
||||
-- addr bit 7
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- addr bit 6
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- addr bit 6
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- addr bit 4
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- addr bit 3
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- addr bit 2
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- addr bit 1
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- addr bit 0
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- Slave ACK
|
||||
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- repeated START condition
|
||||
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1';
|
||||
wait for 400 ns; sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- DEVICE ADDRESS / READ -
|
||||
-- dev bit 7
|
||||
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 6
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 6
|
||||
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 4
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 3
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 2
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 1
|
||||
sdat_drive <= '0'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- dev bit 0 - READ!
|
||||
sdat_drive <= '1'; wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
|
||||
-- ACK????
|
||||
-- Device to ack
|
||||
sdat_drive <= '1';
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
|
||||
for i in 1 to 127 loop
|
||||
-- READ First byte
|
||||
-- read bit 7
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 6
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 6
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 4
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 3
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 2
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 1
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 0
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
sdat_drive <= '1';
|
||||
|
||||
-- Host to ack
|
||||
sdat_drive <= '0';
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
sdat_drive <= '1';
|
||||
end loop;
|
||||
-- READ Second
|
||||
-- read bit 7
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 6
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 6
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 4
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 3
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 2
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 1
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
-- read bit 0
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
sdat_drive <= '1';
|
||||
|
||||
-- Master NACK
|
||||
sdat_drive <= '1';
|
||||
wait for 200 ns; hdmi_rx_scl <= '1'; wait for 400 ns; hdmi_rx_scl <= '0'; wait for 200 ns;
|
||||
sdat_drive <= '1';
|
||||
|
||||
-- STOP
|
||||
sdat_drive <= '1';
|
||||
wait for 200 ns;
|
||||
hdmi_rx_scl <= '1';
|
||||
wait for 200 ns;
|
||||
|
||||
wait;
|
||||
end process;
|
||||
|
||||
end Behavioral;
|
||||
Loading…
Add table
Add a link
Reference in a new issue