diff --git a/library/axi_hdmi_rx/axi_hdmi_rx.v b/library/axi_hdmi_rx/axi_hdmi_rx.v new file mode 100644 index 000000000..aa0c12083 --- /dev/null +++ b/library/axi_hdmi_rx/axi_hdmi_rx.v @@ -0,0 +1,268 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2011(c) Analog Devices, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// - Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// - Neither the name of Analog Devices, Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// - The use of this software may or may not infringe the patent rights +// of one or more patent holders. This license does not release you +// from the requirement that you obtain separate licenses from these +// patent holders to use this software. +// - Use of the software either in source or binary form, must be run +// on or directly connected to an Analog Devices Inc. component. +// +// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. +// +// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +// RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; Loos OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE PoosIBILITY OF SUCH DAMAGE. +// *************************************************************************** +// *************************************************************************** +// *************************************************************************** +// *************************************************************************** + +module axi_hdmi_rx ( + + // hdmi interface + + hdmi_clk, + hdmi_data, + + // vdma interface + video_clk, + video_valid, + video_data, + video_overflow, + video_sync, + + // processor interface + + s_axi_aclk, + s_axi_aresetn, + + s_axi_awvalid, + s_axi_awaddr, + s_axi_awready, + s_axi_wvalid, + s_axi_wdata, + s_axi_wstrb, + s_axi_wready, + s_axi_bvalid, + s_axi_bresp, + s_axi_bready, + s_axi_arvalid, + s_axi_araddr, + s_axi_arready, + s_axi_rvalid, + s_axi_rresp, + s_axi_rdata, + s_axi_rready, + + // debug interface (chipscope) + + hdmi_dbg_data, + hdmi_dbg_trigger); + + // parameters + + parameter PCORE_ID = 0; + + // hdmi interface + + input hdmi_clk; + input [15:0] hdmi_data; + + // vdma interface + + output video_clk; + output video_valid; + output [63:0] video_data; + input video_overflow; + output video_sync; + + // processor interface + + input s_axi_aresetn; + input s_axi_aclk; + input s_axi_awvalid; + input [31:0] s_axi_awaddr; + output s_axi_awready; + input s_axi_wvalid; + input [31:0] s_axi_wdata; + input [ 3:0] s_axi_wstrb; + output s_axi_wready; + output s_axi_bvalid; + output [ 1:0] s_axi_bresp; + input s_axi_bready; + input s_axi_arvalid; + input [31:0] s_axi_araddr; + output s_axi_arready; + output s_axi_rvalid; + output [ 1:0] s_axi_rresp; + output [31:0] s_axi_rdata; + input s_axi_rready; + + // debug interface (chipscope) + + output [61:0] hdmi_dbg_data; + output [ 7:0] hdmi_dbg_trigger; + + reg [31:0] up_scratch = 'h0; + reg up_packed = 'd0; + reg up_bgr = 'd0; + reg up_tpg_enable = 'd0; + reg up_csc_bypass = 'd0; + reg up_edge_sel = 'd0; + reg up_enable = 'd0; + reg [15:0] up_vs_count = 'd0; + reg [15:0] up_hs_count = 'd0; + reg [ 3:0] up_status = 'd0; + reg [31:0] up_rdata = 'd0; + + wire [31:0] up_rdata_s; + wire [31:0] up_wdata_s; + wire [13:0] up_waddr_s; + wire [13:0] up_raddr_s; + wire up_wreq_s; + wire up_rreq_s; + wire up_wack_s; + wire up_rack_s; + + wire up_hdmi_hs_mismatch; + wire up_hdmi_vs_mismatch; + wire [15:0] up_hdmi_hs; + wire [15:0] up_hdmi_vs; + wire hdmi_hs_count_mismatch_s; + wire hdmi_hs_count_update; + wire [15:0] hdmi_hs_count_s; + wire hdmi_vs_count_mismatch_s; + wire hdmi_vs_count_update; + wire [15:0] hdmi_vs_count_s; + wire hdmi_tpm_oos_s; + wire hdmi_oos_s; + wire hdmi_soos_hs_s; + wire hdmi_oos_vs_s; + wire hdmi_wr_s; + wire [64:0] hdmi_wdata_s; + wire up_hdmi_tpm_oos; + wire up_hdmi_oos; + wire up_hdmi_oos_hs; + wire up_hdmi_oos_vs; + + wire hdmi_up_edge_sel; + wire [15:0] hdmi_up_hs_count; + wire [15:0] hdmi_up_vs_count; + wire hdmi_up_csc_bypass; + wire hdmi_up_tpg_enable; + wire hdmi_up_packed; + wire hdmi_rst; + wire hdmi_up_bgr; + + up_axi i_up_axi ( + .up_rstn(s_axi_aresetn), + .up_clk(s_axi_aclk), + .up_axi_awvalid(s_axi_awvalid), + .up_axi_awaddr(s_axi_awaddr), + .up_axi_awready(s_axi_awready), + .up_axi_wvalid(s_axi_wvalid), + .up_axi_wdata(s_axi_wdata), + .up_axi_wstrb(s_axi_wstrb), + .up_axi_wready(s_axi_wready), + .up_axi_bvalid(s_axi_bvalid), + .up_axi_bresp(s_axi_bresp), + .up_axi_bready(s_axi_bready), + .up_axi_arvalid(s_axi_arvalid), + .up_axi_araddr(s_axi_araddr), + .up_axi_arready(s_axi_arready), + .up_axi_rvalid(s_axi_rvalid), + .up_axi_rresp(s_axi_rresp), + .up_axi_rdata(s_axi_rdata), + .up_axi_rready(s_axi_rready), + .up_rreq(up_rreq_s), + .up_wreq(up_wreq_s), + .up_raddr(up_raddr_s), + .up_waddr(up_waddr_s), + .up_wdata(up_wdata_s), + .up_rdata(up_rdata_s), + .up_rack(up_rack_s), + .up_wack(up_wack_s)); + + up_hdmi_rx i_up_hdmi_rx ( + .hdmi_clk (hdmi_clk), + .hdmi_rst (hdmi_rst), + .hdmi_up_hs_count (hdmi_up_hs_count), + .hdmi_up_vs_count (hdmi_up_vs_count), + .hdmi_up_edge_sel (hdmi_up_edge_sel), + .hdmi_up_csc_bypass (hdmi_up_csc_bypass), + .hdmi_up_tpg_enable (hdmi_up_tpg_enable), + .hdmi_up_packed (hdmi_up_packed), + .hdmi_up_bgr (hdmi_up_bgr), + .hdmi_hs_mismatch (hdmi_hs_count_mismatch_s), + .hdmi_hs (hdmi_hs_count_s), + .hdmi_vs_mismatch (hdmi_vs_count_mismatch_s), + .hdmi_vs (hdmi_vs_count_s), + .hdmi_oos_hs (hdmi_oos_hs_s), + .hdmi_oos_vs (hdmi_oos_vs_s), + .hdmi_tpm_oos (hdmi_tpm_oos_s), + .video_overflow (video_overflow), + .up_clk (s_axi_aclk), + .up_rstn (s_axi_aresetn), + .up_rdata (up_rdata_s), + .up_wdata (up_wdata_s), + .up_waddr (up_waddr_s), + .up_raddr (up_raddr_s), + .up_wreq (up_wreq_s), + .up_rreq (up_rreq_s), + .up_wack (up_wack_s), + .up_rack (up_rack_s)); + + assign video_clk = hdmi_clk; + assign video_data = hdmi_wdata_s[63:0]; + assign video_sync = hdmi_wdata_s[64]; + assign video_valid = hdmi_wr_s; + + // hdmi interface + + axi_hdmi_rx_core i_hdmi_rx_core ( + .hdmi_clk(hdmi_clk), + .hdmi_rst (hdmi_rst), + .hdmi_data(hdmi_data), + .hdmi_hs_count_mismatch(hdmi_hs_count_mismatch_s), + .hdmi_hs_count_update(hdmi_hs_count_update), + .hdmi_hs_count(hdmi_hs_count_s), + .hdmi_vs_count_mismatch(hdmi_vs_count_mismatch_s), + .hdmi_vs_count_update(hdmi_vs_count_update), + .hdmi_vs_count(hdmi_vs_count_s), + .hdmi_tpm_oos(hdmi_tpm_oos_s), + .hdmi_oos_hs(hdmi_oos_hs_s), + .hdmi_oos_vs(hdmi_oos_vs_s), + .hdmi_wr(hdmi_wr_s), + .hdmi_wdata(hdmi_wdata_s), + .hdmi_up_edge_sel(hdmi_up_edge_sel), + .hdmi_up_hs_count(hdmi_up_hs_count), + .hdmi_up_vs_count(hdmi_up_vs_count), + .hdmi_up_csc_bypass(hdmi_up_csc_bypass), + .hdmi_up_tpg_enable(hdmi_up_tpg_enable), + .hdmi_up_packed(hdmi_up_packed), + .hdmi_up_bgr(hdmi_up_bgr), + .debug_data(hdmi_dbg_data), + .debug_trigger(hdmi_dbg_trigger) + ); + +endmodule diff --git a/library/axi_hdmi_rx/axi_hdmi_rx_constr.xdc b/library/axi_hdmi_rx/axi_hdmi_rx_constr.xdc new file mode 100644 index 000000000..5f351e0d8 --- /dev/null +++ b/library/axi_hdmi_rx/axi_hdmi_rx_constr.xdc @@ -0,0 +1,4 @@ + +set_clock_groups -asynchronous -group [get_clocks -of_objects [get_ports hdmi_clk]] +set_clock_groups -asynchronous -group [get_clocks -of_objects [get_ports s_axi_aclk]] +set_clock_groups -asynchronous -group [get_clocks -of_objects [get_ports video_clk]] diff --git a/library/axi_hdmi_rx/axi_hdmi_rx_core.v b/library/axi_hdmi_rx/axi_hdmi_rx_core.v new file mode 100644 index 000000000..25e5f9e34 --- /dev/null +++ b/library/axi_hdmi_rx/axi_hdmi_rx_core.v @@ -0,0 +1,378 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2011-2013(c) Analog Devices, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// - Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// - Neither the name of Analog Devices, Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// - The use of this software may or may not infringe the patent rights +// of one or more patent holders. This license does not release you +// from the requirement that you obtain separate licenses from these +// patent holders to use this software. +// - Use of the software either in source or binary form, must be run +// on or directly connected to an Analog Devices Inc. component. +// +// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. +// +// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +// RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// *************************************************************************** +// *************************************************************************** +// *************************************************************************** +// *************************************************************************** +// Receive HDMI, hdmi embedded syncs data in, video dma data out. + +module axi_hdmi_rx_core ( + + // hdmi interface + + hdmi_clk, + hdmi_rst, + hdmi_data, + hdmi_hs_count_mismatch, // indicates receive hs mismatch against programmed + hdmi_hs_count_update, // high for one hdmi_clk cycle when count and count_mismatch are update + hdmi_hs_count, // received hs count + hdmi_vs_count_mismatch, // indicates receive vs mismatch against programmed + hdmi_vs_count_update, // high for one hdmi_clk cycle when count and count_mismatch are update + hdmi_vs_count, // received vs count + hdmi_tpm_oos, // test pattern monitor out of sync + hdmi_oos_hs, // horizontal HDMI receive resolution mismatch against programmed + hdmi_oos_vs, // vertical HDMI receive resolution mismatch against programmed + hdmi_wr, // write interface + hdmi_wdata, + + // processor interface + hdmi_up_edge_sel, + hdmi_up_hs_count, + hdmi_up_vs_count, + hdmi_up_csc_bypass, + hdmi_up_tpg_enable, + hdmi_up_packed, + hdmi_up_bgr, + + // debug interface (chipscope) + + debug_data, + debug_trigger); + + // hdmi interface + + input hdmi_clk; + input hdmi_rst; + input [15:0] hdmi_data; + output hdmi_hs_count_mismatch; + output hdmi_hs_count_update; + output [15:0] hdmi_hs_count; + output hdmi_vs_count_mismatch; + output hdmi_vs_count_update; + output [15:0] hdmi_vs_count; + output hdmi_tpm_oos; + output hdmi_oos_hs; + output hdmi_oos_vs; + output hdmi_wr; + output [64:0] hdmi_wdata; + + // control interface + + input hdmi_up_edge_sel; + input [15:0] hdmi_up_hs_count; + input [15:0] hdmi_up_vs_count; + input hdmi_up_csc_bypass; + input hdmi_up_tpg_enable; + input hdmi_up_packed; + input hdmi_up_bgr; + + // debug interface (chipscope) + + output [61:0] debug_data; + output [ 7:0] debug_trigger; + + reg hdmi_wr = 'd0; + reg [64:0] hdmi_wdata = 'd0; + reg [23:0] hdmi_tpm_data = 'd0; + reg hdmi_tpm_oos = 'd0; + reg hdmi_fs_422 = 'd0; + reg hdmi_de_422 = 'd0; + reg [15:0] hdmi_data_422 = 'd0; + reg hdmi_fs_444 = 'd0; + reg hdmi_de_444 = 'd0; + reg [23:0] hdmi_data_444 = 'd0; + reg hdmi_fs_444_d = 'd0; + reg hdmi_de_444_d = 'd0; + reg [23:0] hdmi_data_444_d = 'd0; + reg [23:0] hdmi_data_444_2d = 'd0; + reg [23:0] hdmi_data_444_3d = 'd0; + reg hdmi_oos_hs = 'd0; + reg hdmi_oos_vs = 'd0; + reg hdmi_sof = 'd0; + reg hdmi_hs_de_d = 'd0; + reg hdmi_vs_de_d = 'd0; + reg [15:0] hdmi_hs_run_count = 'd0; + reg [15:0] hdmi_vs_run_count = 'd0; + reg hdmi_hs_count_mismatch = 'd0; + reg hdmi_hs_count_update = 'd0; + reg [15:0] hdmi_hs_count = 'd0; + reg hdmi_vs_count_mismatch = 'd0; + reg hdmi_vs_count_update = 'd0; + reg [15:0] hdmi_vs_count = 'd0; + reg hdmi_enable = 'd0; + reg [15:0] hdmi_data_neg_p = 'd0; + reg [15:0] hdmi_data_pos_p = 'd0; + reg [15:0] hdmi_data_p = 'd0; + reg [15:0] hdmi_data_neg = 'd0; + reg [ 2:0] hdmi_wr_count = 'd0; + + wire hdmi_tpm_mismatch_s; + wire [15:0] hdmi_tpm_data_s; + wire hdmi_sof_s; + wire hdmi_oos_hs_s; + wire hdmi_oos_vs_s; + wire hdmi_fs_444_s; + wire hdmi_de_444_s; + wire [23:0] hdmi_data_444_s; + wire ss_fs_s; + wire ss_de_s; + wire [23:0] ss_data_s; + wire [15:0] hdmi_data_de; + wire hdmi_hs_de; + wire hdmi_vs_de; + + // debug signals + + assign debug_data[61:61] = hdmi_tpm_oos; + assign debug_data[60:60] = hdmi_tpm_mismatch_s; + assign debug_data[59:59] = hdmi_de_422; + assign debug_data[58:43] = hdmi_data_422; + assign debug_data[42:42] = hdmi_oos_hs | hdmi_oos_vs; + assign debug_data[41:41] = hdmi_sof; + assign debug_data[40:40] = hdmi_hs_count_mismatch; + assign debug_data[39:39] = hdmi_vs_count_mismatch; + assign debug_data[38:38] = hdmi_enable; + assign debug_data[37:37] = hdmi_vs_de; + assign debug_data[36:36] = hdmi_hs_de; + assign debug_data[35:20] = hdmi_data_de; + assign debug_data[15: 0] = hdmi_data_p; + + assign debug_trigger[7] = hdmi_tpm_mismatch_s; + assign debug_trigger[6] = hdmi_tpm_oos; + assign debug_trigger[5] = hdmi_enable; + assign debug_trigger[4] = hdmi_hs_de; + assign debug_trigger[3] = hdmi_vs_de; + assign debug_trigger[2] = hdmi_sof; + + + always @(posedge hdmi_clk) begin + if (hdmi_de_444_d == 1'b1) begin + hdmi_wr_count <= hdmi_wr_count + 1'b1; + end else begin + hdmi_wr_count <= 3'b0; + end + if (hdmi_up_packed == 1'b0) begin + hdmi_wr <= hdmi_wr_count[0]; + hdmi_wdata[63:32] <= {8'hff,hdmi_data_444_d[23:0]}; + hdmi_wdata[31:0] <= hdmi_wdata[63:32]; + end else begin + if (hdmi_up_csc_bypass) begin + hdmi_wr <= hdmi_wr_count[1] & hdmi_wr_count[0]; + hdmi_wdata[63:48] <= hdmi_data_444_d[15:0]; + hdmi_wdata[47:0] <= hdmi_wdata[63:16]; + end else begin + hdmi_wr <= 1'b0; + case(hdmi_wr_count) + 3'h1: begin + hdmi_wdata[23:0] <= hdmi_data_444_2d; + hdmi_wdata[47:24] <= hdmi_data_444_d; + hdmi_wdata[63:48] <= hdmi_data_444[15:0]; + end + 3'h2: begin + hdmi_wr <= 1'b1; + end + 3'h4: begin + hdmi_wdata[7:0] <= hdmi_data_444_3d[23:16]; + hdmi_wdata[31:8] <= hdmi_data_444_2d; + hdmi_wdata[55:32] <= hdmi_data_444_d; + hdmi_wdata[63:56] <= hdmi_data_444[7:0]; + end + 3'h5: begin + hdmi_wr <= 1'b1; + end + 3'h6: begin + hdmi_wdata[15:0] <= hdmi_data_444_2d[23:8]; + hdmi_wdata[39:16] <= hdmi_data_444_d; + hdmi_wdata[63:40] <= hdmi_data_444; + end + 3'h7: begin + hdmi_wr <= 1'b1; + end + endcase + end +end + + if (hdmi_fs_444) + hdmi_wdata[64:64] <= 1'b1; + else if (hdmi_wr) + hdmi_wdata[64:64] <= 1'b0; + end + + // TPM on 422 data (the data must be passed through the cable as it is transmitted + // by the v2h module. Any csc conversions must be disabled on info frame + + assign hdmi_tpm_mismatch_s = (hdmi_data_422 == hdmi_tpm_data_s) ? 1'b0 : hdmi_de_422; + assign hdmi_tpm_data_s = {hdmi_tpm_data[3:2], 6'h20, hdmi_tpm_data[1:0], 6'h20}; + + always @(posedge hdmi_clk) begin + if (hdmi_fs_422 == 1'b1) begin + hdmi_tpm_data <= 'd0; + end else if (hdmi_de_422 == 1'b1) begin + hdmi_tpm_data <= hdmi_tpm_data + 1'b1; + end + hdmi_tpm_oos <= hdmi_tpm_mismatch_s; + end + + // fs, enable and data on 422 and 444 domains + always @(posedge hdmi_clk) begin + hdmi_fs_422 <= hdmi_sof & hdmi_enable; + hdmi_de_422 <= hdmi_hs_de & hdmi_vs_de & hdmi_enable; + hdmi_data_422 <= hdmi_data_de; + + hdmi_fs_444_d <= hdmi_fs_444; + hdmi_de_444_d <= hdmi_de_444; + hdmi_data_444_d <= hdmi_data_444; + hdmi_data_444_2d <= hdmi_data_444_d; + hdmi_data_444_3d <= hdmi_data_444_2d; + end + + // Select output data depending on the control setting + always @(posedge hdmi_clk) begin + if (hdmi_up_csc_bypass == 1'b1) begin + hdmi_fs_444 <= hdmi_fs_422; + hdmi_de_444 <= hdmi_de_422; + end else begin + hdmi_fs_444 <= hdmi_fs_444_s; + hdmi_de_444 <= hdmi_de_444_s; + end + if (hdmi_up_tpg_enable == 1'b1) begin + hdmi_data_444 <= hdmi_tpm_data; + end else if (hdmi_up_csc_bypass == 1'b1) begin + hdmi_data_444 <= {8'd0, hdmi_data_422}; + end else if (hdmi_up_bgr == 1'b1) begin + hdmi_data_444 <= {hdmi_data_444_s[7:0], hdmi_data_444_s[15:8], hdmi_data_444_s[23:16]}; + end else begin + hdmi_data_444 <= hdmi_data_444_s; + end + end + + // start of frame + + assign hdmi_sof_s = hdmi_vs_de & ~hdmi_vs_de_d; + assign hdmi_oos_hs_s = hdmi_hs_count == hdmi_up_hs_count ? hdmi_hs_count_mismatch : 1'b1; + assign hdmi_oos_vs_s = hdmi_vs_count == hdmi_up_vs_count ? hdmi_vs_count_mismatch : 1'b1; + + // hdmi side of the interface, horizontal and vertical sync counters. + // capture active video size and report mismatch + + always @(posedge hdmi_clk) begin + hdmi_oos_hs <= hdmi_oos_hs_s; + hdmi_oos_vs <= hdmi_oos_vs_s; + hdmi_sof <= hdmi_sof_s; + hdmi_hs_de_d <= hdmi_hs_de; + hdmi_vs_de_d <= hdmi_vs_de; + if ((hdmi_hs_de == 1'b1) && (hdmi_hs_de_d == 1'b0)) begin + hdmi_hs_run_count <= 'd1; + end else if (hdmi_hs_de == 1'b1) begin + hdmi_hs_run_count <= hdmi_hs_run_count + 1'b1; + end + if ((hdmi_vs_de == 1'b1) && (hdmi_vs_de_d == 1'b0)) begin + hdmi_vs_run_count <= 'd0; + end else if ((hdmi_vs_de == 1'b1) && (hdmi_hs_de == 1'b1) && (hdmi_hs_de_d == 1'b0)) begin + hdmi_vs_run_count <= hdmi_vs_run_count + 1'b1; + end + if ((hdmi_hs_de == 1'b0) && (hdmi_hs_de_d == 1'b1)) begin + hdmi_hs_count_mismatch <= (hdmi_hs_count == hdmi_hs_run_count) ? 1'b0 : 1'b1; + hdmi_hs_count <= hdmi_hs_run_count; + hdmi_hs_count_update <= 1'b1; + end else begin + hdmi_hs_count_update <= 1'b0; + end + if ((hdmi_vs_de == 1'b0) && (hdmi_vs_de_d == 1'b1)) begin + hdmi_vs_count_mismatch <= (hdmi_vs_count == hdmi_vs_run_count) ? 1'b0 : 1'b1; + hdmi_vs_count <= hdmi_vs_run_count; + hdmi_vs_count_update <= 1'b1; + end else begin + hdmi_vs_count_update <= 1'b0; + end + if (hdmi_sof_s == 1'b1) begin + hdmi_enable <= ~hdmi_rst & ~hdmi_oos_hs_s & ~hdmi_oos_vs_s; + end + end + + // hdmi input data registers + + always @(posedge hdmi_clk) begin + hdmi_data_neg_p <= hdmi_data_neg; + hdmi_data_pos_p <= hdmi_data; + if (hdmi_up_edge_sel == 1'b1) begin + hdmi_data_p <= hdmi_data_neg_p; + end else begin + hdmi_data_p <= hdmi_data_pos_p; + end + end + + always @(negedge hdmi_clk) begin + hdmi_data_neg <= hdmi_data; + end + + embedded_sync_decoder es_decoder ( + .clk (hdmi_clk), + .data_in (hdmi_data_p), + .hs_de (hdmi_hs_de), + .vs_de (hdmi_vs_de), + .data_out (hdmi_data_de) + ); + + // super sampling, 422 to 444 + + ad_ss_422to444 #( + .Cr_Cb_N(0), + .DELAY_DATA_WIDTH(2) + ) i_ss ( + .clk (hdmi_clk), + .s422_de (hdmi_de_422), + .s422_sync ({hdmi_fs_422,hdmi_de_422}), + .s422_data (hdmi_data_422), + .s444_sync ({ss_fs_s,ss_de_s}), + .s444_data (ss_data_s) + ); + + // color space conversion, CrYCb to RGB + + ad_csc_CrYCb2RGB #( + .DELAY_DATA_WIDTH(2) + ) i_csc ( + .clk (hdmi_clk), + .CrYCb_sync ({ss_fs_s, ss_de_s}), + .CrYCb_data (ss_data_s), + .RGB_sync ({hdmi_fs_444_s, hdmi_de_444_s}), + .RGB_data (hdmi_data_444_s) + ); + +endmodule + +// *************************************************************************** +// *************************************************************************** diff --git a/library/axi_hdmi_rx/axi_hdmi_rx_ip.tcl b/library/axi_hdmi_rx/axi_hdmi_rx_ip.tcl new file mode 100644 index 000000000..8b648f29c --- /dev/null +++ b/library/axi_hdmi_rx/axi_hdmi_rx_ip.tcl @@ -0,0 +1,28 @@ +#ip + +source ../scripts/adi_env.tcl +source $ad_hdl_dir/library/scripts/adi_ip.tcl + +adi_ip_create axi_hdmi_rx +adi_ip_files axi_hdmi_rx [list \ + "$ad_hdl_dir/library/common/ad_mem.v" \ + "$ad_hdl_dir/library/common/ad_csc_1.v" \ + "$ad_hdl_dir/library/common/ad_csc_1_mul.v" \ + "$ad_hdl_dir/library/common/ad_csc_1_add.v" \ + "$ad_hdl_dir/library/common/up_axi.v" \ + "$ad_hdl_dir/library/common/up_hdmi_rx.v" \ + "$ad_hdl_dir/library/common/up_xfer_status.v" \ + "$ad_hdl_dir/library/common/up_xfer_cntrl.v" \ + "$ad_hdl_dir/library/common/ad_rst.v" \ + "$ad_hdl_dir/library/common/ad_ss_422to444.v" \ + "$ad_hdl_dir/library/common/ad_csc_CrYCb2RGB.v" \ + "axi_hdmi_rx.v" \ + "axi_hdmi_rx_core.v" \ + "embedded_sync_decoder.v" ] + +adi_ip_properties axi_hdmi_rx +adi_ip_constraints axi_hdmi_rx [list \ + "axi_hdmi_rx_constr.xdc" ] + +ipx::save_core [ipx::current_core] + diff --git a/library/axi_hdmi_rx/embedded_sync_decoder.v b/library/axi_hdmi_rx/embedded_sync_decoder.v new file mode 100644 index 000000000..2fb14632e --- /dev/null +++ b/library/axi_hdmi_rx/embedded_sync_decoder.v @@ -0,0 +1,104 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2011-2013(c) Analog Devices, Inc. +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// - Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// - Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// - Neither the name of Analog Devices, Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// - The use of this software may or may not infringe the patent rights +// of one or more patent holders. This license does not release you +// from the requirement that you obtain separate licenses from these +// patent holders to use this software. +// - Use of the software either in source or binary form, must be run +// on or directly connected to an Analog Devices Inc. component. +// +// THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. +// +// IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, INTELLECTUAL PROPERTY +// RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// *************************************************************************** +// *************************************************************************** +// *************************************************************************** +// *************************************************************************** + +module embedded_sync_decoder( + input clk, + input [15:0] data_in, + output reg hs_de, + output reg vs_de, + output reg [15:0] data_out +); + + reg [15:0] data_d = 'd0; + reg hs_de_rcv_d = 'd0; + reg vs_de_rcv_d = 'd0; + reg [15:0] data_2d = 'd0; + reg hs_de_rcv_2d = 'd0; + reg vs_de_rcv_2d = 'd0; + reg [15:0] data_3d = 'd0; + reg hs_de_rcv_3d = 'd0; + reg vs_de_rcv_3d = 'd0; + reg [15:0] data_4d = 'd0; + reg hs_de_rcv_4d = 'd0; + reg vs_de_rcv_4d = 'd0; + reg hs_de_rcv = 'd0; + reg vs_de_rcv = 'd0; + + // delay to get rid of eav's 4 bytes + always @(posedge clk) begin + data_d <= data_in; + data_2d <= data_d; + data_3d <= data_2d; + data_4d <= data_3d; + data_out <= data_4d; + + hs_de_rcv_d <= hs_de_rcv; + vs_de_rcv_d <= vs_de_rcv; + hs_de_rcv_2d <= hs_de_rcv_d; + vs_de_rcv_2d <= vs_de_rcv_d; + hs_de_rcv_3d <= hs_de_rcv_2d; + vs_de_rcv_3d <= vs_de_rcv_2d; + hs_de_rcv_4d <= hs_de_rcv_3d; + vs_de_rcv_4d <= vs_de_rcv_3d; + hs_de <= hs_de_rcv & hs_de_rcv_4d; + vs_de <= vs_de_rcv & vs_de_rcv_4d; + end + + reg [1:0] preamble_cnt = 'd0; + + // check for sav and eav and generate the corresponding enables + always @(posedge clk) begin + if ((data_in == 16'hffff) || (data_in == 16'h0000)) begin + preamble_cnt <= preamble_cnt + 1'b1; + end else begin + preamble_cnt <= 'd0; + end + + if (preamble_cnt == 3'h3) begin + if ((data_in == 16'hb6b6) || (data_in == 16'h9d9d)) begin + hs_de_rcv <= 1'b0; + vs_de_rcv <= ~data_in[13]; + end else if ((data_in == 16'habab) || (data_in == 16'h8080)) begin + hs_de_rcv <= 1'b1; + vs_de_rcv <= ~data_in[13]; + end + end + end + +endmodule