summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy.green@linaro.org>2015-10-25 12:12:35 +0800
committerAndy Green <andy.green@linaro.org>2015-10-25 12:12:35 +0800
commit9cbf12551e97539c0b265f0c7f9ba80fa4273a65 (patch)
tree4a28844721ac787d9ec4908a07a6739f6b050c26
-rwxr-xr-xhdmicap_v1_0_S00_AXI.vhd1790
1 files changed, 1790 insertions, 0 deletions
diff --git a/hdmicap_v1_0_S00_AXI.vhd b/hdmicap_v1_0_S00_AXI.vhd
new file mode 100755
index 0000000..6857ea6
--- /dev/null
+++ b/hdmicap_v1_0_S00_AXI.vhd
@@ -0,0 +1,1790 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity hdmicap_v1_0_S00_AXI is
+ generic (
+ -- Users to add parameters here
+
+ -- User parameters ends
+ -- Do not modify the parameters beyond this line
+
+ -- Width of S_AXI data bus
+ C_S_AXI_DATA_WIDTH : integer := 32;
+ -- Width of S_AXI address bus
+ C_S_AXI_ADDR_WIDTH : integer := 7
+ );
+ port (
+ -- Users to add ports here
+ s_hdmi_clk : in std_logic;
+ s_hdmi_lane : in std_logic_vector (5 downto 0);
+ s_hdmi_pll_locked : in std_logic;
+ s_hdmi_pll_psen : out std_logic;
+ s_hdmi_pll_ps_inc : out std_logic;
+ s_hdmi_pll_ps_done : in std_logic;
+ s_hdmi_hsync : out std_logic;
+ s_hdmi_vsync : out std_logic;
+ s_hdmi_de : out std_logic;
+
+ s_hdmi_out_we : out std_logic;
+ s_hdmi_out_last : out std_logic;
+ s_hdmi_out_valid : out std_logic;
+ s_hdmi_in_ready : in std_logic;
+ s_hdmi_tkeep : out std_logic_vector(3 downto 0);
+ s_hdmi_out_data : out std_logic_vector(31 downto 0);
+ s_hdmi_pixel_clock : out std_logic;
+
+ s_hdmi_irq : out std_logic;
+
+ -- User ports ends
+ -- Do not modify the ports beyond this line
+
+ -- Global Clock Signal
+ S_AXI_ACLK : in std_logic;
+ -- Global Reset Signal. This Signal is Active LOW
+ S_AXI_ARESETN : in std_logic;
+ -- Write address (issued by master, acceped by Slave)
+ S_AXI_AWADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
+ -- Write channel Protection type. This signal indicates the
+ -- privilege and security level of the transaction, and whether
+ -- the transaction is a data access or an instruction access.
+ S_AXI_AWPROT : in std_logic_vector(2 downto 0);
+ -- Write address valid. This signal indicates that the master signaling
+ -- valid write address and control information.
+ S_AXI_AWVALID : in std_logic;
+ -- Write address ready. This signal indicates that the slave is ready
+ -- to accept an address and associated control signals.
+ S_AXI_AWREADY : out std_logic;
+ -- Write data (issued by master, acceped by Slave)
+ S_AXI_WDATA : in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
+ -- Write strobes. This signal indicates which byte lanes hold
+ -- valid data. There is one write strobe bit for each eight
+ -- bits of the write data bus.
+ S_AXI_WSTRB : in std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0);
+ -- Write valid. This signal indicates that valid write
+ -- data and strobes are available.
+ S_AXI_WVALID : in std_logic;
+ -- Write ready. This signal indicates that the slave
+ -- can accept the write data.
+ S_AXI_WREADY : out std_logic;
+ -- Write response. This signal indicates the status
+ -- of the write transaction.
+ S_AXI_BRESP : out std_logic_vector(1 downto 0);
+ -- Write response valid. This signal indicates that the channel
+ -- is signaling a valid write response.
+ S_AXI_BVALID : out std_logic;
+ -- Response ready. This signal indicates that the master
+ -- can accept a write response.
+ S_AXI_BREADY : in std_logic;
+ -- Read address (issued by master, acceped by Slave)
+ S_AXI_ARADDR : in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
+ -- Protection type. This signal indicates the privilege
+ -- and security level of the transaction, and whether the
+ -- transaction is a data access or an instruction access.
+ S_AXI_ARPROT : in std_logic_vector(2 downto 0);
+ -- Read address valid. This signal indicates that the channel
+ -- is signaling valid read address and control information.
+ S_AXI_ARVALID : in std_logic;
+ -- Read address ready. This signal indicates that the slave is
+ -- ready to accept an address and associated control signals.
+ S_AXI_ARREADY : out std_logic;
+ -- Read data (issued by slave)
+ S_AXI_RDATA : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
+ -- Read response. This signal indicates the status of the
+ -- read transfer.
+ S_AXI_RRESP : out std_logic_vector(1 downto 0);
+ -- Read valid. This signal indicates that the channel is
+ -- signaling the required read data.
+ S_AXI_RVALID : out std_logic;
+ -- Read ready. This signal indicates that the master can
+ -- accept the read data and response information.
+ S_AXI_RREADY : in std_logic
+ );
+end hdmicap_v1_0_S00_AXI;
+
+architecture arch_imp of hdmicap_v1_0_S00_AXI is
+
+component fifo_generator_0 is
+ port (
+ rst : in std_logic;
+ wr_clk : in std_logic;
+ rd_clk : in std_logic;
+ din : in std_logic_vector(31 downto 0);
+ wr_en : in std_logic;
+ rd_en : in std_logic;
+ dout : out std_logic_vector(31 downto 0);
+ full : out std_logic;
+ empty : out std_logic
+ );
+end component fifo_generator_0;
+
+ signal pixel_fifo_reset :std_logic;
+ signal axi_fifo_read_select : std_logic;
+ signal axi_fifo_read_select_reg : std_logic;
+
+ signal ss_hdmi_out_data : std_logic_vector(31 downto 0);
+ signal pixel_fifo_axi_side : std_logic_vector(31 downto 0);
+ signal pixel_fifo_empty : std_logic;
+ signal pixel_fifo_full : std_logic;
+ signal s_hdmi_out_last_sig : std_logic;
+
+ -- AXI4LITE signals
+ signal axi_awaddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
+ signal axi_awready : std_logic;
+ signal axi_wready : std_logic;
+ signal axi_bresp : std_logic_vector(1 downto 0);
+ signal axi_bvalid : std_logic;
+ signal axi_araddr : std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
+ signal axi_arready : std_logic;
+ signal axi_rdata : std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
+ signal axi_rresp : std_logic_vector(1 downto 0);
+ signal axi_rvalid : std_logic;
+
+ -- Example-specific design signals
+ -- local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
+ -- ADDR_LSB is used for addressing 32/64 bit registers/memories
+ -- ADDR_LSB = 2 for 32 bits (n downto 2)
+ -- ADDR_LSB = 3 for 64 bits (n downto 3)
+ constant ADDR_LSB : integer := (C_S_AXI_DATA_WIDTH/32)+ 1;
+ constant OPT_MEM_ADDR_BITS : integer := 4;
+ ------------------------------------------------
+ ---- Signals for user logic register space example
+ --------------------------------------------------
+
+ signal hdmi_clk_counter :std_logic_vector(31 downto 0);
+ signal hdmi_lane :std_logic_vector(3 downto 0);
+ signal hdmi_reset :std_logic;
+ signal s_hdmi_pll_ps_ctr : std_logic_vector(7 downto 0);
+ signal s_hdmi_pll_ps_target : std_logic_vector(7 downto 0);
+ signal s_hdmi_pll_ps_pending : std_logic;
+
+ signal lane_shifter : std_logic_vector((3 * 12) - 1 downto 0);
+ signal lane_sample : std_logic_vector((3 * 10) - 1 downto 0);
+ signal dlane_sample : std_logic_vector((3 * 10) - 1 downto 0);
+ signal lane_sample_old : std_logic_vector((3 * 10) - 1 downto 0);
+ signal s_pixel_clk : std_logic;
+ signal s_pixel_clk_high : std_logic_vector(1 downto 0);
+
+ signal ctr_vert_total : std_logic_vector(12 downto 0);
+ signal meas_vert_total : std_logic_vector(12 downto 0);
+ signal ctr_vert_sync : std_logic_vector(12 downto 0);
+ signal meas_vert_sync : std_logic_vector(12 downto 0);
+ signal ctr_vert_fp : std_logic_vector(12 downto 0);
+ signal meas_vert_fp : std_logic_vector(12 downto 0);
+ signal ctr_vert_bp : std_logic_vector(12 downto 0);
+ signal meas_vert_bp : std_logic_vector(12 downto 0);
+
+ signal ctr_horz_total : std_logic_vector(12 downto 0);
+ signal meas_horz_total : std_logic_vector(12 downto 0);
+ signal ctr_horz_sync : std_logic_vector(12 downto 0);
+ signal meas_horz_sync : std_logic_vector(12 downto 0);
+ signal ctr_horz_fp : std_logic_vector(12 downto 0);
+ signal meas_horz_fp : std_logic_vector(12 downto 0);
+ signal ctr_horz_bp : std_logic_vector(12 downto 0);
+ signal meas_horz_bp : std_logic_vector(12 downto 0);
+ signal meas_horz_data_sample_line : std_logic_vector(12 downto 0);
+ signal meas_vsync_h_pos : std_logic_vector(12 downto 0);
+
+ signal ctr_pixels_in_frame : std_logic_vector(25 downto 0);
+ signal meas_pixels_in_frame : std_logic_vector(25 downto 0);
+ signal ctr_data_clocks_in_frame : std_logic_vector(25 downto 0);
+ signal meas_data_clocks_in_frame : std_logic_vector(25 downto 0);
+ signal ctr_data_clocks_in_line : std_logic_vector(25 downto 0);
+ signal ctr_data_clocks_in_vb : std_logic_vector(25 downto 0);
+ signal meas_data_clocks_in_vb : std_logic_vector(25 downto 0);
+ signal ctr_control_clocks_in_frame : std_logic_vector(25 downto 0);
+ signal meas_control_clocks_in_frame : std_logic_vector(25 downto 0);
+ signal ctr_control_clocks_in_line : std_logic_vector(25 downto 0);
+ signal ctr_control_clocks_in_vb : std_logic_vector(25 downto 0);
+ signal meas_control_clocks_in_vb : std_logic_vector(25 downto 0);
+
+ signal ctr_hdmi_perr_control_pre_preamble : std_logic_vector(12 downto 0);
+ signal meas_hdmi_perr_control_pre_preamble : std_logic_vector(12 downto 0);
+
+ signal ctr_hdmi_control_pre_preamble : std_logic_vector(2 downto 0);
+
+ signal ctr_vsyncs : std_logic_vector(15 downto 0);
+ signal meas_vsync_stamp : std_logic_vector(15 downto 0);
+
+ signal hold_measurement_updates : std_logic;
+ signal hold_measurement_updates_px : std_logic;
+
+ signal ctr_escapes : std_logic_vector((32 * 3) - 1 downto 0); -- for each of the 3 channels
+ signal meas_escapes : std_logic_vector((32 * 3) -1 downto 0);
+ signal clear_escapes_tog : std_logic;
+ signal clear_escapes_sen : std_logic;
+ signal timestamp_escapes_captured : std_logic_vector(31 downto 0);
+
+ signal c : std_logic_vector(5 downto 0);
+ signal hsync : std_logic;
+ signal vsync : std_logic;
+ signal hsync_old : std_logic;
+ signal vsync_old : std_logic;
+ signal is_back : std_logic;
+ signal is_back_v : std_logic;
+ signal hsync_active_level : std_logic;
+ signal vsync_active_level : std_logic;
+ signal soft_reset_tog : std_logic;
+ signal soft_reset_sen_px : std_logic;
+
+ constant IRQ_SOURCE_TRIG_COMPLETED : integer := 0;
+ constant IRQ_SOURCE_PLL_LOCK_CHANGE : integer := 1;
+
+ signal a_irq_sources_tog : std_logic_vector(1 downto 0);
+ signal a_irq_sources_sen : std_logic_vector(1 downto 0);
+ signal a_irq_sources_status : std_logic_vector(1 downto 0);
+
+ constant DM_CONTROL : std_logic_vector := "000";
+ constant DM_VIDEO : std_logic_vector := "001";
+ constant DM_DATA : std_logic_vector := "010";
+ constant DM_PRE_GUARD1 : std_logic_vector := "011";
+ constant DM_PRE_GUARD2 : std_logic_vector := "100";
+ constant DM_POST_DATA_GUARD2 : std_logic_vector := "101";
+
+ signal tmds_decode_mode : std_logic_vector(2 downto 0);
+ signal control_preamble_count : std_logic_vector(3 downto 0);
+ signal control_pattern_seen : std_logic;
+
+ -- [ delayed nad (1) ] [ cc (2) ] [ dout 8 ]
+ constant lane_state_width : integer := 11;
+ signal lane_state : std_logic_vector((3 * lane_state_width) - 1 downto 0);
+ signal dlane_state : std_logic_vector((3 * lane_state_width) - 1 downto 0);
+
+ signal sync_ctr : std_logic_vector(2 downto 0);
+ -- b3..b1 = 0..4 pair sample, b0 = 1=offset shift inside pair
+ signal sync_offset : std_logic_vector(3 downto 0);
+ signal sync_offset_axi : std_logic_vector(3 downto 0);
+ signal sync_offset_manual : std_logic;
+ signal sync_offset_changed_tog : std_logic;
+ signal sync_offset_changed_sen : std_logic;
+ signal capture_only_raw : std_logic;
+ signal capture_only_data : std_logic;
+ signal capture_continuous : std_logic;
+ signal pixel_fifo_empty_axi : std_logic;
+
+ signal since_last_sync : std_logic_vector(15 downto 0);
+ signal coding_sync_ctr : std_logic_vector(31 downto 0);
+ signal terc4 : std_logic_vector(11 downto 0);
+ signal terc4_illegal : std_logic;
+ signal ctr_terc4_illegals_in_frame : std_logic_vector(15 downto 0);
+ signal meas_terc4_illegals_in_frame : std_logic_vector(15 downto 0);
+
+ signal data_header : std_logic_vector(31 downto 0);
+ signal ctr_packet : std_logic_vector(5 downto 0);
+
+ signal ctr_axi_clocks : std_logic_vector(15 downto 0);
+ signal shifter_pixel_ctr_samples : std_logic_vector((4 * 32) -1 downto 0);
+ signal hdmi_clk_counter_start : std_logic_vector(31 downto 0);
+ signal guard_ch1_133 : std_logic;
+ signal guard_ch2_2cc : std_logic;
+
+ signal slv_reg_rden : std_logic;
+ signal slv_reg_wren : std_logic;
+ signal reg_data_out :std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
+ signal byte_index : integer;
+
+ signal armed_tog : std_logic;
+ signal armed_sen : std_logic;
+
+ signal s_hdmi_in_ready_axi : std_logic;
+
+ signal armed: std_logic;
+ signal triggered : std_logic;
+ signal filtered_trigger : std_logic;
+ signal completed : std_logic;
+ signal showed_last : std_logic;
+ signal dma_length_px : std_logic_vector(31 downto 0);
+ signal dma_ctr_px : std_logic_vector(31 downto 0);
+ signal dma_ctr_used : std_logic_vector(31 downto 0);
+ signal dma_ctr_read_from_fifo : std_logic_vector(31 downto 0);
+
+ signal clear_irq_tog : std_logic;
+ signal clear_irq_sen : std_logic;
+ signal irq : std_logic;
+ signal s_hdmi_pll_locked_old : std_logic;
+
+begin
+
+streamfifo : component fifo_generator_0
+ port map (
+ rst => pixel_fifo_reset,
+ wr_clk => s_pixel_clk,
+ rd_clk => S_AXI_ACLK,
+ din => ss_hdmi_out_data,
+ wr_en => filtered_trigger,
+ rd_en => s_hdmi_in_ready, --axi_fifo_read_select_reg,
+ dout => s_hdmi_out_data, -- pixel_fifo_axi_side,
+ full => pixel_fifo_full,
+ empty => pixel_fifo_empty
+ );
+
+ -- I/O Connections assignments
+
+ S_AXI_AWREADY <= axi_awready;
+ S_AXI_WREADY <= axi_wready;
+ S_AXI_BRESP <= axi_bresp;
+ S_AXI_BVALID <= axi_bvalid;
+ S_AXI_ARREADY <= axi_arready;
+ S_AXI_RDATA <= axi_rdata;
+ S_AXI_RRESP <= axi_rresp;
+ S_AXI_RVALID <= axi_rvalid;
+ -- Implement axi_awready generation
+ -- axi_awready is asserted for one S_AXI_ACLK clock cycle when both
+ -- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
+ -- de-asserted when reset is low.
+
+ s_hdmi_tkeep <= "1111";
+ s_hdmi_out_valid <= not pixel_fifo_empty;
+ s_hdmi_out_last <= s_hdmi_out_last_sig;
+
+ process (S_AXI_ACLK)
+ begin
+ if rising_edge(S_AXI_ACLK) then
+ if S_AXI_ARESETN = '0' then
+ axi_awready <= '0';
+ else
+ if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1') then
+ -- slave is ready to accept write address when
+ -- there is a valid write address and write data
+ -- on the write address and data bus. This design
+ -- expects no outstanding transactions.
+ axi_awready <= '1';
+ else
+ axi_awready <= '0';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- Implement axi_awaddr latching
+ -- This process is used to latch the address when both
+ -- S_AXI_AWVALID and S_AXI_WVALID are valid.
+
+ process (S_AXI_ACLK)
+ begin
+ if rising_edge(S_AXI_ACLK) then
+ if S_AXI_ARESETN = '0' then
+ axi_awaddr <= (others => '0');
+ else
+ if (axi_awready = '0' and S_AXI_AWVALID = '1' and S_AXI_WVALID = '1') then
+ -- Write Address latching
+ axi_awaddr <= S_AXI_AWADDR;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- Implement axi_wready generation
+ -- axi_wready is asserted for one S_AXI_ACLK clock cycle when both
+ -- S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is
+ -- de-asserted when reset is low.
+
+ process (S_AXI_ACLK)
+ begin
+ if rising_edge(S_AXI_ACLK) then
+ if S_AXI_ARESETN = '0' then
+ axi_wready <= '0';
+ else
+ if (axi_wready = '0' and S_AXI_WVALID = '1' and S_AXI_AWVALID = '1') then
+ -- slave is ready to accept write data when
+ -- there is a valid write address and write data
+ -- on the write address and data bus. This design
+ -- expects no outstanding transactions.
+ axi_wready <= '1';
+ else
+ axi_wready <= '0';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- Implement memory mapped register select and write logic generation
+ -- The write data is accepted and written to memory mapped registers when
+ -- axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
+ -- select byte enables of slave registers while writing.
+ -- These registers are cleared when reset (active low) is applied.
+ -- Slave register write enable is asserted when valid address and data are available
+ -- and the slave is ready to accept the write address and write data.
+ slv_reg_wren <= axi_wready and S_AXI_WVALID and axi_awready and S_AXI_AWVALID ;
+
+ process (S_AXI_ACLK)
+ variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
+ begin
+ if rising_edge(S_AXI_ACLK) then
+ if S_AXI_ARESETN = '0' then
+ s_hdmi_pll_psen <= '0';
+ s_hdmi_pll_ps_inc <= '0';
+ s_hdmi_pll_ps_ctr <= (others => '0');
+ s_hdmi_pll_ps_target <= (others => '0');
+ s_hdmi_pll_ps_pending <= '0';
+ armed_tog <= '0';
+ soft_reset_tog <= '0';
+ clear_irq_tog <= '0';
+ capture_only_raw <= '0';
+ showed_last <= '0';
+ dma_length_px <= (others => '0');
+ hold_measurement_updates <= '0';
+ dma_ctr_read_from_fifo <= (others => '0');
+ else
+ loc_addr := axi_awaddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
+ if (slv_reg_wren = '1') then
+ case loc_addr is
+ when b"00000" =>
+
+ if (S_AXI_WSTRB(0) = '1') then
+ s_hdmi_pll_ps_target <= S_AXI_WDATA(7 downto 0);
+ end if;
+
+ -- start full data capture next vsync
+ when b"00001" =>
+ if (S_AXI_WSTRB(0) = '1') then
+ if S_AXI_WDATA(1) = '1' then
+ sync_offset_axi <= S_AXI_WDATA(7 downto 4);
+ sync_offset_manual <= S_AXI_WDATA(3);
+ sync_offset_changed_tog <= not sync_offset_changed_tog;
+ end if;
+ if S_AXI_WDATA(0) = '1' then
+ showed_last <= '0';
+ armed_tog <= not armed_tog;
+ dma_ctr_used <= dma_length_px;
+ dma_ctr_read_from_fifo <= (others => '0');
+ end if;
+ end if;
+
+ when b"00010" =>
+ if (S_AXI_WSTRB(0) = '1') then
+ capture_only_data <= S_AXI_WDATA(6); -- only capture data content
+ capture_continuous <= S_AXI_WDATA(5); -- 0 = begin and end on vsync, 1 = begin anywhere
+ pixel_fifo_reset <= S_AXI_WDATA(4);
+ capture_only_raw <= S_AXI_WDATA(3);
+ if S_AXI_WDATA(2) = '1' then
+ soft_reset_tog <= not soft_reset_tog;
+ end if;
+ vsync_active_level <= S_AXI_WDATA(1);
+ hsync_active_level <= S_AXI_WDATA(0);
+ end if;
+
+ when b"00011" =>
+ if (S_AXI_WSTRB(0) = '1') then
+ -- inform async sources they are cleared
+ clear_irq_tog <= not clear_irq_tog;
+ a_irq_sources_status <= (others => '0');
+ irq <= '0';
+ end if;
+
+ when b"00100" =>
+ if (S_AXI_WSTRB(0) = '1') then
+ dma_length_px <= S_AXI_WDATA;
+ end if;
+
+ when b"00101" =>
+ if (S_AXI_WSTRB(0) = '1') then
+ if S_AXI_WDATA(0) = '1' then
+ -- transfers escapes counters into meas and clears escape counters
+ clear_escapes_tog <= not clear_escapes_tog;
+ end if;
+ end if;
+
+ when b"00110" =>
+ if (S_AXI_WSTRB(0) = '1') then
+ hold_measurement_updates <= S_AXI_WDATA(0);
+ end if;
+
+ when others =>
+ end case;
+ end if;
+
+ -- dma completion signal... in AXI clock domain
+
+ pixel_fifo_empty_axi <= pixel_fifo_empty;
+ s_hdmi_in_ready_axi <= s_hdmi_in_ready;
+ if s_hdmi_in_ready_axi = '1' and pixel_fifo_empty_axi = '0' then
+ dma_ctr_read_from_fifo <= std_logic_vector(unsigned(dma_ctr_read_from_fifo) + 1);
+ if dma_ctr_used /= "00000000000000000000000000000000" then
+ dma_ctr_used <= std_logic_vector(unsigned(dma_ctr_used) - 1);
+ end if;
+ end if;
+
+ s_hdmi_out_last_sig <= '0';
+ if dma_ctr_used = "00000000000000000000000000000001" or completed = '1' then
+ s_hdmi_out_last_sig <= '1';
+ end if;
+
+ -- can't do this on pixel clock domain as no clock when unlocked
+
+ s_hdmi_pll_locked_old <= s_hdmi_pll_locked;
+ if (s_hdmi_pll_locked /= s_hdmi_pll_locked_old) then
+ a_irq_sources_tog(IRQ_SOURCE_PLL_LOCK_CHANGE) <=
+ not a_irq_sources_tog(IRQ_SOURCE_PLL_LOCK_CHANGE);
+ end if;
+
+ -- async irq management
+
+ a_irq_sources_sen <= a_irq_sources_tog;
+ for n in 0 to 1 loop
+ if a_irq_sources_sen(n) /= a_irq_sources_tog(n) then
+ a_irq_sources_status(n) <= '1';
+ irq <= '1';
+ end if;
+ end loop;
+
+ -- he is a 1-clock strobe
+ s_hdmi_pll_psen <= '0';
+
+ if s_hdmi_pll_ps_target /= s_hdmi_pll_ps_ctr then
+ if s_hdmi_pll_ps_pending = '0' then
+ s_hdmi_pll_psen <= '1';
+ s_hdmi_pll_ps_pending <= '1';
+ if s_hdmi_pll_ps_target < s_hdmi_pll_ps_ctr then
+ s_hdmi_pll_ps_inc <= '0';
+ else
+ s_hdmi_pll_ps_inc <= '1';
+ end if;
+ end if;
+
+ if s_hdmi_pll_ps_pending = '1' and s_hdmi_pll_ps_done = '1' then
+ if s_hdmi_pll_ps_target < s_hdmi_pll_ps_ctr then
+ s_hdmi_pll_ps_ctr <= std_logic_vector(unsigned(s_hdmi_pll_ps_ctr) - 1);
+ else
+ s_hdmi_pll_ps_ctr <= std_logic_vector(unsigned(s_hdmi_pll_ps_ctr) + 1);
+ end if;
+ s_hdmi_pll_ps_pending <= '0';
+ end if;
+ end if;
+ end if;
+
+ dlane_sample <= lane_sample;
+ dlane_state <= lane_state;
+ end if;
+ end process;
+
+ -- Implement write response logic generation
+ -- The write response and response valid signals are asserted by the slave
+ -- when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
+ -- This marks the acceptance of address and indicates the status of
+ -- write transaction.
+
+ process (S_AXI_ACLK)
+ begin
+ if rising_edge(S_AXI_ACLK) then
+ if S_AXI_ARESETN = '0' then
+ axi_bvalid <= '0';
+ axi_bresp <= "00"; --need to work more on the responses
+ else
+ if (axi_awready = '1' and S_AXI_AWVALID = '1' and axi_wready = '1' and S_AXI_WVALID = '1' and axi_bvalid = '0' ) then
+ axi_bvalid <= '1';
+ axi_bresp <= "00";
+ elsif (S_AXI_BREADY = '1' and axi_bvalid = '1') then --check if bready is asserted while bvalid is high)
+ axi_bvalid <= '0'; -- (there is a possibility that bready is always asserted high)
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- Implement axi_arready generation
+ -- axi_arready is asserted for one S_AXI_ACLK clock cycle when
+ -- S_AXI_ARVALID is asserted. axi_awready is
+ -- de-asserted when reset (active low) is asserted.
+ -- The read address is also latched when S_AXI_ARVALID is
+ -- asserted. axi_araddr is reset to zero on reset assertion.
+
+ process (S_AXI_ACLK)
+ begin
+ if rising_edge(S_AXI_ACLK) then
+ if S_AXI_ARESETN = '0' then
+ axi_arready <= '0';
+ axi_araddr <= (others => '1');
+ else
+ if (axi_arready = '0' and S_AXI_ARVALID = '1') then
+ -- indicates that the slave has acceped the valid read address
+ axi_arready <= '1';
+ -- Read Address latching
+ axi_araddr <= S_AXI_ARADDR;
+ else
+ axi_arready <= '0';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- Implement axi_arvalid generation
+ -- axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
+ -- S_AXI_ARVALID and axi_arready are asserted. The slave registers
+ -- data are available on the axi_rdata bus at this instance. The
+ -- assertion of axi_rvalid marks the validity of read data on the
+ -- bus and axi_rresp indicates the status of read transaction.axi_rvalid
+ -- is deasserted on reset (active low). axi_rresp and axi_rdata are
+ -- cleared to zero on reset (active low).
+ process (S_AXI_ACLK)
+ begin
+ if rising_edge(S_AXI_ACLK) then
+ if S_AXI_ARESETN = '0' then
+ axi_rvalid <= '0';
+ axi_rresp <= "00";
+ else
+ if (axi_arready = '1' and S_AXI_ARVALID = '1' and axi_rvalid = '0') then
+ -- Valid read data is available at the read data bus
+ axi_rvalid <= '1';
+ axi_rresp <= "00"; -- 'OKAY' response
+ elsif (axi_rvalid = '1' and S_AXI_RREADY = '1') then
+ -- Read data is accepted by the master
+ axi_rvalid <= '0';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- simulate the serdes at 10 x pixel rate (no serdes on zynq7z20)
+ -- 270MHz at 576p
+
+ process (s_hdmi_clk)
+ begin
+ if rising_edge(s_hdmi_clk) then
+ if hdmi_reset = '0' or s_hdmi_pll_locked = '0' then
+ sync_ctr <= (others => '0');
+ s_pixel_clk <= '0';
+ else
+ if (sync_ctr = "100") then
+ sync_ctr <= "000";
+ else
+ sync_ctr <= std_logic_vector(unsigned(sync_ctr) + 1);
+ end if;
+
+ -- first level shifter needs to hold 12 bits so we can select the 10 we want
+ -- n1 -> b11 -> b9 -> b7 -> b5 -> b3 -> b1 ->
+ -- n0 -> b10 -> b8 -> b6 -> b4 -> b2 -> b0 ->
+
+ for n in 0 to 2 loop
+ for m in 0 to 4 loop
+ lane_shifter((n * 12) + (m * 2) + 1) <= lane_shifter((n * 12) + (m * 2) + 3);
+ lane_shifter((n * 12) + (m * 2)) <= lane_shifter((n * 12) + (m * 2) + 2);
+-- lane_shifter((n * 12) + (m * 2) + 3) <= lane_shifter((n * 12) + (m * 2) + 1);
+-- lane_shifter((n * 12) + (m * 2) + 2) <= lane_shifter((n * 12) + (m * 2) + 0);
+ end loop;
+ lane_shifter((n * 12) + 11) <= s_hdmi_lane(n + 3);
+ lane_shifter((n * 12) + 10) <= s_hdmi_lane(n);
+-- lane_shifter((n * 12) + 1) <= s_hdmi_lane(n + 3);
+-- lane_shifter((n * 12) + 0) <= s_hdmi_lane(n);
+ end loop;
+
+ -- sample the tmds 10-bit data at the sync point
+ -- because they come in pairs due to needing DDR clock, the LSB
+ -- of the sync offset selects whether to offset by one bit inside the pairs
+ --
+ -- also synthesize the locked pixel clock with 50% duty
+
+ if (sync_ctr = sync_offset(3 downto 1)) then
+ if (sync_offset(0) = '0') then
+ lane_sample(9 downto 0) <= lane_shifter(9 downto 0);
+ lane_sample(19 downto 10) <= lane_shifter(21 downto 12);
+ lane_sample(29 downto 20) <= lane_shifter(33 downto 24);
+ else
+ lane_sample(9 downto 0) <= lane_shifter(10 downto 1);
+ lane_sample(19 downto 10) <= lane_shifter(22 downto 13);
+ lane_sample(29 downto 20) <= lane_shifter(34 downto 25);
+ end if;
+ lane_sample_old <= lane_sample;
+ s_pixel_clk <= '1';
+ s_pixel_clk_high <= "10";
+ end if;
+
+ if s_pixel_clk = '1' then
+ if s_pixel_clk_high = "00" then
+ s_pixel_clk <= '0';
+ else
+ s_pixel_clk_high <= std_logic_vector(unsigned(s_pixel_clk_high) - 1);
+ end if;
+ end if;
+ end if;
+ hdmi_reset <= S_AXI_ARESETN;
+ end if;
+ end process;
+
+ process(s_pixel_clk, completed, irq, hsync, vsync)
+ begin
+ s_hdmi_pixel_clock <= s_pixel_clk;
+ s_hdmi_irq <= irq;
+ s_hdmi_hsync <= hsync;
+ s_hdmi_vsync <= vsync;
+ end process;
+
+-- everything else can happen at the pixel rate
+-- 27MHz at 576p
+
+ process (s_pixel_clk)
+ variable o : std_logic_vector(11 downto 0);
+ variable d : std_logic_vector(8 downto 0);
+ variable hsync_now : std_logic;
+ variable vsync_now : std_logic;
+ variable bump_esc : std_logic;
+ begin
+ if rising_edge(s_pixel_clk) then
+ soft_reset_sen_px <= soft_reset_tog;
+ if hdmi_reset = '0' or (soft_reset_sen_px /= soft_reset_tog) then
+ since_last_sync <= (others => '0');
+ sync_offset <= (others => '0');
+ coding_sync_ctr <= (others => '0');
+ hdmi_clk_counter <= (others => '0');
+ is_back <= '0';
+ is_back_v <= '0';
+ triggered <= '0';
+ completed <= '0';
+ armed_sen <= '0';
+ armed <= '0';
+ meas_horz_total <= (others => '0');
+ meas_horz_sync <= (others => '0');
+ meas_horz_fp <= (others => '0');
+ meas_horz_bp <= (others => '0');
+ meas_vert_total <= (others => '0');
+ meas_vert_sync <= (others => '0');
+ meas_vert_fp <= (others => '0');
+ meas_vert_bp <= (others => '0');
+ ctr_pixels_in_frame <= (others => '0');
+ ctr_data_clocks_in_line <= (others => '0');
+ ctr_data_clocks_in_frame <= (others => '0');
+ tmds_decode_mode <= DM_CONTROL;
+ control_preamble_count <= (others => '0');
+ ctr_hdmi_control_pre_preamble <= (others => '0');
+ ctr_hdmi_perr_control_pre_preamble <= (others => '0');
+ hsync <= '0';
+ vsync <= '0';
+ c <= (others => '0');
+ guard_ch1_133 <= '0';
+ guard_ch2_2cc <= '0';
+ else
+ ctr_pixels_in_frame <= std_logic_vector(unsigned(ctr_pixels_in_frame) + 1);
+ hdmi_clk_counter <= std_logic_vector(unsigned (hdmi_clk_counter) + 1);
+
+ -- perform all the possible interpretations
+ -- EVERY OUTPUT IS REGISTERED
+
+ control_pattern_seen <= '0';
+ guard_ch1_133 <= '0';
+ guard_ch2_2cc <= '0';
+
+ clear_escapes_sen <= clear_escapes_tog;
+ if clear_escapes_sen /= clear_escapes_tog then
+ timestamp_escapes_captured <= hdmi_clk_counter;
+ end if;
+
+ filtered_trigger <= (triggered and (not capture_only_data)) or
+ (capture_only_data and completed and (not showed_last));
+
+ -- control coding
+ for n in 0 to 2 loop
+
+ bump_esc := '0';
+
+ case lane_sample((n * 10) + 9 downto (n * 10) + 0) is
+ when "1011001100" => -- video guard band ch0/2
+ if n = 2 then
+ guard_ch2_2cc <= '1';
+ end if;
+ bump_esc := '1';
+
+ when "0100110011" => -- video ch1, or data island guard band ch 1/2
+ if n = 1 then
+ guard_ch1_133 <= '1';
+ end if;
+ bump_esc := '1';
+
+ when "1101010100" =>
+ c((n * 2) + 1 downto (n * 2)) <= "00";
+ control_pattern_seen <= '1';
+ bump_esc := '1';
+ when "0010101011" => -- yes
+ c((n * 2) + 1 downto (n * 2)) <= "01";
+ control_pattern_seen <= '1';
+ bump_esc := '1';
+ when "0101010100" =>
+ c((n * 2) + 1 downto (n * 2)) <= "10";
+ control_pattern_seen <= '1';
+ bump_esc := '1';
+ when "1010101011" => -- yes
+ c((n * 2) + 1 downto (n * 2)) <= "11";
+ control_pattern_seen <= '1';
+ bump_esc := '1';
+ when others =>
+ end case;
+
+ if clear_escapes_sen = clear_escapes_tog then
+ if bump_esc = '1' then
+ ctr_escapes((n * 32) + 31 downto (n * 32)) <=
+ std_logic_vector(unsigned (ctr_escapes((n * 32) + 31 downto (n * 32))) + 1);
+ end if;
+ else
+ meas_escapes((n * 32) + 31 downto (n * 32)) <=
+ ctr_escapes((n * 32) + 31 downto (n * 32));
+ ctr_escapes((n * 32) + 31 downto (n * 32)) <= (others => '0');
+ end if;
+
+ -- TERC4 (data island) coding
+
+ terc4_illegal <= '0';
+ case lane_sample((n * 10) + 9 downto (n * 10) + 0) is
+ when "1010011100" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "0000";
+ when "1001100011" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "0001";
+ when "1011100100" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "0010";
+ when "1011100010" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "0011";
+ when "0101110001" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "0100";
+ when "0100011110" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "0101";
+ when "0110001110" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "0110";
+ when "0100111100" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "0111";
+ when "1011001100" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "1000";
+ when "0100111001" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "1001";
+ when "0110011100" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "1010";
+ when "1011000110" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "1011";
+ when "1010001110" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "1100";
+ when "1001110001" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "1101";
+ when "0101100011" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "1110";
+ when "1011000011" =>
+ terc4((n * 4) + 3 downto (n * 4)) <= "1111";
+ when others =>
+ terc4_illegal <= '1';
+ end case;
+
+ -- video coding
+ -- data one sample delayed from _old, d is not registered here
+
+ if lane_sample_old((n * 10) + 9) = '1' then
+ d := lane_sample_old((n * 10) + 8 downto (n * 10)) xor "011111111";
+ else
+ d := lane_sample_old((n * 10) + 8 downto (n * 10));
+ end if;
+
+ if tmds_decode_mode /= DM_VIDEO and
+ (tmds_decode_mode /= DM_PRE_GUARD2 or guard_ch2_2cc /= '1')
+ then
+ o := (
+ 9 => vsync,
+ 8 => hsync,
+ others => '0');
+ elsif lane_sample_old((n * 10) + 8) = '1' then
+ o := (
+ 9 => vsync,
+ 8 => hsync,
+ 7 => d(7) XOR d(6),
+ 6 => d(6) XOR d(5),
+ 5 => d(5) XOR d(4),
+ 4 => d(4) XOR d(3),
+ 3 => d(3) XOR d(2),
+ 2 => d(2) XOR d(1),
+ 1 => d(1) XOR d(0),
+ 0 => d(0),
+ others => '0');
+ else
+ o := (
+ 9 => vsync,
+ 8 => hsync,
+ 7 => d(7) XNOR d(6),
+ 6 => d(6) XNOR d(5),
+ 5 => d(5) XNOR d(4),
+ 4 => d(4) XNOR d(3),
+ 3 => d(3) XNOR d(2),
+ 2 => d(2) XNOR d(1),
+ 1 => d(1) XNOR d(0),
+ 0 => d(0),
+ others => '0');
+ end if;
+
+ lane_state((n * lane_state_width) + 10 downto n * lane_state_width) <= o(10 downto 0);
+
+ end loop;
+
+ -- by default, issue the raw 10-bit data
+
+ ss_hdmi_out_data <= (
+ 31 => '1',
+ 30 => '0', -- raw 10-bit data
+ 29 => lane_sample(29),
+ 28 => lane_sample(28),
+ 27 => lane_sample(27),
+ 26 => lane_sample(26),
+ 25 => lane_sample(25),
+ 24 => lane_sample(24),
+ 23 => lane_sample(23),
+ 22 => lane_sample(22),
+ 21 => lane_sample(21),
+ 20 => lane_sample(20),
+ 19 => lane_sample(19),
+ 18 => lane_sample(18),
+ 17 => lane_sample(17),
+ 16 => lane_sample(16),
+ 15 => lane_sample(15),
+ 14 => lane_sample(14),
+ 13 => lane_sample(13),
+ 12 => lane_sample(12),
+ 11 => lane_sample(11),
+ 10 => lane_sample(10),
+ 9 => lane_sample(9),
+ 8 => lane_sample(8),
+ 7 => lane_sample(7),
+ 6 => lane_sample(6),
+ 5 => lane_sample(5),
+ 4 => lane_sample(4),
+ 3 => lane_sample(3),
+ 2 => lane_sample(2),
+ 1 => lane_sample(1),
+ 0 => lane_sample(0),
+ others => '0'
+ );
+
+ -- process the registered information from the previous clock
+ s_hdmi_de <= '0';
+
+ case tmds_decode_mode is
+ when DM_CONTROL =>
+ ctr_control_clocks_in_frame <= std_logic_vector(unsigned(ctr_control_clocks_in_frame) + 1);
+ ctr_control_clocks_in_line <= std_logic_vector(unsigned(ctr_control_clocks_in_line) + 1);
+ if c(5 downto 2) = "0001" or c(5 downto 2) = "0101" then -- video or data
+ if control_preamble_count = "0111" then -- he sends exactly 8 to warn us
+ tmds_decode_mode <= DM_PRE_GUARD1; -- then he will send 2 x guard band
+ ctr_hdmi_control_pre_preamble <= (others => '0');
+ if ctr_hdmi_control_pre_preamble < "100" then
+ ctr_hdmi_perr_control_pre_preamble <=
+ std_logic_vector(unsigned(ctr_hdmi_perr_control_pre_preamble));
+ end if;
+ control_preamble_count <= (others => '0');
+ else
+ control_preamble_count <=
+ std_logic_vector(unsigned(control_preamble_count) + 1);
+ end if;
+ else
+ if (ctr_hdmi_control_pre_preamble /= "111") then
+ ctr_hdmi_control_pre_preamble <= std_logic_vector(unsigned(ctr_hdmi_control_pre_preamble) + 1);
+ end if;
+ control_preamble_count <= (others => '0');
+ end if;
+ hsync <= c(0);
+ vsync <= c(1);
+ if guard_ch1_133 = '1' then -- data or video guard
+ tmds_decode_mode <= DM_PRE_GUARD2;
+ hsync <= terc4(0);
+ vsync <= terc4(1);
+ end if;
+
+ when DM_VIDEO => -- no postamble on video he just starts sending ctrl data when done
+ if control_pattern_seen = '1' then
+ tmds_decode_mode <= DM_CONTROL;
+ hsync <= c(0);
+ vsync <= c(1);
+ else
+ s_hdmi_de <= '1';
+ -- override the output to be the decoded RGB data
+ if capture_only_raw = '0' then
+ ss_hdmi_out_data <= (
+ 31 => '1', -- decoded data (A)
+ 30 => '1', --
+ 29 => '1', -- rgba pixel data
+ 28 => '1',
+ 27 => '1',
+ 26 => '1',
+ 25 => '1',
+ 24 => '1',
+ 23 => lane_state(7), -- B
+ 22 => lane_state(6),
+ 21 => lane_state(5),
+ 20 => lane_state(4),
+ 19 => lane_state(3),
+ 18 => lane_state(2),
+ 17 => lane_state(1),
+ 16 => lane_state(0),
+ 15 => lane_state(18), -- G
+ 14 => lane_state(17),
+ 13 => lane_state(16),
+ 12 => lane_state(15),
+ 11 => lane_state(14),
+ 10 => lane_state(13),
+ 9 => lane_state(12),
+ 8 => lane_state(11),
+ 7 => lane_state(29), -- R
+ 6 => lane_state(28),
+ 5 => lane_state(27),
+ 4 => lane_state(26),
+ 3 => lane_state(25),
+ 2 => lane_state(24),
+ 1 => lane_state(23),
+ 0 => lane_state(22),
+ others => '0');
+ end if;
+ end if;
+
+ when DM_DATA => -- 2 clock postamble on data on ch1 + 2 only (ch0 has TERC4 syncs)
+ -- override the output to be the decoded RGB data
+ if capture_only_raw = '0' then
+ ss_hdmi_out_data <= (
+ 31 => '1', -- decoded data
+ 30 => '1',
+ 29 => '1',
+ 28 => '1',
+ 27 => '1',
+ 26 => '1',
+ 25 => '1',
+ 24 => '0', -- data island
+ 23 => terc4(11),
+ 22 => terc4(10),
+ 21 => terc4(9),
+ 20 => terc4(8),
+ 15 => terc4(7),
+ 14 => terc4(6),
+ 13 => terc4(5),
+ 12 => terc4(4),
+ 7 => terc4(3),
+ 6 => terc4(2),
+ 5 => terc4(1),
+ 4 => terc4(0),
+ others => '0');
+ end if;
+
+ ctr_packet <= std_logic_vector(unsigned(ctr_packet) + 1);
+
+ filtered_trigger <= triggered;
+
+ if terc4_illegal = '1' and ctr_terc4_illegals_in_frame /= "1111111111111111" then
+ ctr_terc4_illegals_in_frame <= std_logic_vector(unsigned(ctr_terc4_illegals_in_frame) + 1);
+ end if;
+
+ ctr_data_clocks_in_frame <= std_logic_vector(unsigned(ctr_data_clocks_in_frame) + 1);
+ ctr_data_clocks_in_line <= std_logic_vector(unsigned(ctr_data_clocks_in_line) + 1);
+ if guard_ch1_133 = '1' then --postamble
+ tmds_decode_mode <= DM_POST_DATA_GUARD2;
+ end if;
+ if control_pattern_seen = '1' then
+ tmds_decode_mode <= DM_CONTROL;
+
+ end if;
+ hsync <= terc4(0);
+ vsync <= terc4(1);
+
+ when DM_PRE_GUARD1 =>
+ if guard_ch2_2cc = '0' then -- data
+ hsync <= terc4(0);
+ vsync <= terc4(1);
+ end if;
+ -- video guard has no sync info since imples both syncs OFF
+ tmds_decode_mode <= DM_PRE_GUARD2;
+
+ when DM_PRE_GUARD2 =>
+ if guard_ch2_2cc = '1' then --video
+ tmds_decode_mode <= DM_VIDEO;
+ else
+ tmds_decode_mode <= DM_DATA;
+ hsync <= terc4(0);
+ vsync <= terc4(1);
+ end if;
+
+ when DM_POST_DATA_GUARD2 =>
+ tmds_decode_mode <= DM_CONTROL;
+ hsync <= terc4(0);
+ vsync <= terc4(1);
+
+ when others =>
+ tmds_decode_mode <= DM_CONTROL;
+ end case;
+
+ hsync_old <= hsync;
+ vsync_old <= vsync;
+ hold_measurement_updates_px <= hold_measurement_updates;
+
+ -- frame capture management
+
+ s_hdmi_out_we <= filtered_trigger;
+ armed_sen <= armed_tog;
+ if armed_sen /= armed_tog then
+ completed <= '0';
+ dma_ctr_px <= (others => '0');
+ if capture_continuous = '1' then
+ armed <= '0'; -- armed is never high during continuous capture
+ triggered <= '1';
+ else
+ armed <= '1'; -- ie, set triggered at next vsync
+ triggered <= '0';
+ end if;
+ end if;
+
+ if filtered_trigger = '1' then
+ dma_ctr_px <= std_logic_vector(unsigned(dma_ctr_px) + 1);
+ end if;
+
+ -- continuous capture ends when we do the set amount
+
+ if capture_continuous = '1' and dma_ctr_px = dma_length_px and triggered = '1' then
+ a_irq_sources_tog(IRQ_SOURCE_TRIG_COMPLETED) <=
+ not a_irq_sources_tog(IRQ_SOURCE_TRIG_COMPLETED);
+ completed <= '1';
+ triggered <= '0';
+ end if;
+
+ -- H counters
+
+ ctr_horz_total <= std_logic_vector(unsigned(ctr_horz_total) + 1);
+ if (hsync = hsync_active_level) then
+ ctr_horz_sync <= std_logic_vector(unsigned(ctr_horz_sync) + 1);
+ end if;
+ -- no hsync, no active video
+ if (hsync /= hsync_active_level and tmds_decode_mode /= DM_VIDEO) then
+ if is_back = '0' then -- no active seen yet -> bp (left margin)
+ ctr_horz_bp <= std_logic_vector(unsigned(ctr_horz_bp) + 1);
+ else -- active seen -> fp (right margin)
+ ctr_horz_fp <= std_logic_vector(unsigned(ctr_horz_fp) + 1);
+ end if;
+ end if;
+
+ if tmds_decode_mode = DM_VIDEO then
+ is_back <= '1'; -- line has seen any active video
+ is_back_v <= '1'; -- frame has ever seen any active video
+ end if;
+
+ -- per-line processing (done at point hsync starts)
+
+ if (hsync = hsync_active_level and hsync_old /= hsync_active_level) then -- hsync begins
+ ctr_horz_total <= (others => '0');
+ ctr_horz_bp <= (others => '0');
+ ctr_horz_fp <= (others => '0');
+ ctr_horz_sync <= (others => '0');
+ ctr_data_clocks_in_line <= (others => '0');
+ ctr_control_clocks_in_line <= (others => '0');
+ -- only store info for lines with active video (or fp/bp will be wrong)
+ if hold_measurement_updates_px = '0' and is_back = '1' then
+ meas_horz_total <= ctr_horz_total;
+ meas_horz_sync <= ctr_horz_sync;
+ meas_horz_fp <= ctr_horz_fp;
+ meas_horz_bp <= ctr_horz_bp;
+ meas_horz_data_sample_line <= ctr_vert_total;
+ else -- vertical blanking
+
+ ctr_data_clocks_in_vb <= std_logic_vector(unsigned(ctr_data_clocks_in_line) +
+ unsigned(ctr_data_clocks_in_vb));
+ ctr_control_clocks_in_vb <= std_logic_vector(unsigned(ctr_control_clocks_in_line) +
+ unsigned(ctr_control_clocks_in_vb));
+ end if;
+ is_back <= '0';
+
+ ctr_vert_total <= std_logic_vector(unsigned(ctr_vert_total) + 1);
+ if (vsync = vsync_active_level) then
+ ctr_vert_sync <= std_logic_vector(unsigned(ctr_vert_sync) + 1);
+ end if;
+ -- no vsync, no active video on this line
+ if vsync /= vsync_active_level and is_back = '0' then
+ if is_back_v = '0' then -- no active lines seen yet -> bp (top margin)
+ ctr_vert_bp <= std_logic_vector(unsigned(ctr_vert_bp) + 1);
+ else -- active has been seen this field -> fp (bottom margin)
+ ctr_vert_fp <= std_logic_vector(unsigned(ctr_vert_fp) + 1);
+ end if;
+ end if;
+ end if;
+
+ -- per field processing
+
+ if (vsync = vsync_active_level and vsync_old /= vsync_active_level) then -- vsync begins
+ ctr_vsyncs <= std_logic_vector(unsigned(ctr_vsyncs) + 1);
+ ctr_vert_total <= (others => '0');
+ ctr_vert_bp <= (others => '0');
+ ctr_vert_fp <= (others => '0');
+ ctr_vert_sync <= (others => '0');
+ ctr_pixels_in_frame <= (others => '0');
+ ctr_data_clocks_in_frame <= (others => '0');
+ ctr_data_clocks_in_vb <= (others => '0');
+ ctr_control_clocks_in_frame <= (others => '0');
+ ctr_control_clocks_in_vb <= (others => '0');
+ ctr_terc4_illegals_in_frame <= (others => '0');
+ if hold_measurement_updates_px = '0' then
+ meas_vert_total <= ctr_vert_total;
+ meas_vert_sync <= ctr_vert_sync;
+ meas_vert_fp <= ctr_vert_fp;
+ meas_vert_bp <= ctr_vert_bp;
+ meas_pixels_in_frame <= ctr_pixels_in_frame;
+ meas_data_clocks_in_frame <= ctr_data_clocks_in_frame;
+ meas_data_clocks_in_vb <= ctr_data_clocks_in_vb;
+ meas_control_clocks_in_frame <= ctr_control_clocks_in_frame;
+ meas_control_clocks_in_vb <= ctr_control_clocks_in_vb;
+ meas_vsync_stamp <= ctr_vsyncs;
+ meas_vsync_h_pos <= ctr_horz_total;
+ meas_hdmi_perr_control_pre_preamble <= ctr_hdmi_perr_control_pre_preamble;
+ meas_terc4_illegals_in_frame <= ctr_terc4_illegals_in_frame;
+ end if;
+ is_back_v <= '0';
+
+ if capture_continuous = '0' then -- stop and start on a vsync
+ triggered <= armed;
+ armed <= '0';
+ completed <= triggered; -- high for one vsync...
+ if triggered = '1' then
+ a_irq_sources_tog(IRQ_SOURCE_TRIG_COMPLETED) <=
+ not a_irq_sources_tog(IRQ_SOURCE_TRIG_COMPLETED);
+ end if;
+ end if;
+ end if;
+
+ -- notification of clear IRQ from AXI domain
+
+ -- clear_irq_sen <= clear_irq_tog;
+ -- if clear_irq_sen /= clear_irq_tog then
+ --
+ -- end if;
+
+ -- auto bit slip
+
+ if sync_offset_manual = '1' then
+ sync_offset <= sync_offset_axi;
+ sync_offset_changed_sen <= sync_offset_changed_tog;
+ if sync_offset_changed_tog /= sync_offset_changed_sen then
+ coding_sync_ctr <= (others => '0');
+ else
+ if control_pattern_seen = '1' then
+ coding_sync_ctr <= std_logic_vector(unsigned(coding_sync_ctr) + 1);
+ end if;
+ end if;
+ else
+ if control_pattern_seen = '1' then -- sync seen
+ since_last_sync <= (others => '0');
+ coding_sync_ctr <= std_logic_vector(unsigned(coding_sync_ctr) + 1);
+ else
+ if since_last_sync = "1111111111111111" then
+ if sync_offset = "1001" then
+ sync_offset <= "0000";
+ else
+ sync_offset <= std_logic_vector(unsigned(sync_offset) + 1);
+ end if;
+ end if;
+ since_last_sync <= std_logic_vector(unsigned(since_last_sync) + 1);
+ end if;
+ end if;
+ end if; -- reset
+ end if; -- clock edge
+ end process;
+
+ -- Implement memory mapped register select and read logic generation
+ -- Slave register read enable is asserted when valid address is available
+ -- and the slave is ready to accept the read address.
+ slv_reg_rden <= axi_arready and S_AXI_ARVALID and (not axi_rvalid) ;
+
+ process (axi_araddr, S_AXI_ARESETN, slv_reg_rden,
+ s_hdmi_pll_locked, sync_offset, lane_sample, hdmi_clk_counter,
+ s_hdmi_pll_ps_ctr, s_hdmi_pll_ps_target, coding_sync_ctr,
+ meas_vert_sync, meas_vert_total, meas_horz_sync, meas_horz_total,
+ meas_vert_fp, meas_vert_bp, meas_horz_fp, meas_horz_bp,
+ triggered, armed, dlane_sample, dlane_state,
+ shifter_pixel_ctr_samples, irq, c,
+ meas_data_clocks_in_frame, meas_data_clocks_in_vb,
+ meas_control_clocks_in_frame, meas_control_clocks_in_vb,
+ meas_pixels_in_frame,
+ a_irq_sources_status, dma_ctr_read_from_fifo)
+ variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
+ begin
+ -- Address decoding for reading registers
+ loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
+
+ axi_fifo_read_select <= '0';
+
+ case loc_addr is
+ when b"00000" =>
+ if (s_hdmi_pll_locked = '0') then
+ reg_data_out <= (others => '0');
+ else
+ reg_data_out <= hdmi_clk_counter;
+ end if;
+ when b"00001" =>
+ if (s_hdmi_pll_locked = '0') then
+ reg_data_out <= (others => '0');
+ else
+ reg_data_out <= (
+ 31 => s_hdmi_pll_ps_ctr(7),
+ 30 => s_hdmi_pll_ps_ctr(6),
+ 29 => s_hdmi_pll_ps_ctr(5),
+ 28 => s_hdmi_pll_ps_ctr(4),
+ 27 => s_hdmi_pll_ps_ctr(3),
+ 26 => s_hdmi_pll_ps_ctr(2),
+ 25 => s_hdmi_pll_ps_ctr(1),
+ 24 => s_hdmi_pll_ps_ctr(0),
+ 23 => s_hdmi_pll_ps_target(7),
+ 22 => s_hdmi_pll_ps_target(6),
+ 21 => s_hdmi_pll_ps_target(5),
+ 20 => s_hdmi_pll_ps_target(4),
+ 19 => s_hdmi_pll_ps_target(3),
+ 18 => s_hdmi_pll_ps_target(2),
+ 17 => s_hdmi_pll_ps_target(1),
+ 16 => s_hdmi_pll_ps_target(0),
+ 15 => sync_offset(3),
+ 14 => sync_offset(2),
+ 13 => sync_offset(1),
+ 12 => sync_offset(0),
+ 7 => c(5),
+ 6 => c(4),
+ 5 => c(3),
+ 4 => c(2),
+ 2 => tmds_decode_mode(2),
+ 1 => tmds_decode_mode(1),
+ 0 => tmds_decode_mode(0),
+ others => '0');
+ end if;
+ when b"00010" =>
+ reg_data_out <= (31 => s_hdmi_pll_locked,
+ 30 => irq,
+ 29 => a_irq_sources_status(IRQ_SOURCE_PLL_LOCK_CHANGE),
+ 28 => a_irq_sources_status(IRQ_SOURCE_TRIG_COMPLETED),
+ 27 => pixel_fifo_full,
+ 26 => pixel_fifo_empty,
+ 25 => triggered,
+ 24 => armed,
+ 17 => vsync,
+ 16 => hsync,
+ 9 => dlane_sample(9),
+ 8 => dlane_sample(8),
+ 7 => dlane_sample(7),
+ 6 => dlane_sample(6),
+ 5 => dlane_sample(5),
+ 4 => dlane_sample(4),
+ 3 => dlane_sample(3),
+ 2 => dlane_sample(2),
+ 1 => dlane_sample(1),
+ 0 => dlane_sample(0),
+ others => '0');
+ when b"00011" =>
+ reg_data_out <= coding_sync_ctr;
+
+ when b"00100" =>
+ reg_data_out <= (28 => meas_vert_total(12),
+ 27 => meas_vert_total(11),
+ 26 => meas_vert_total(10),
+ 25 => meas_vert_total(9),
+ 24 => meas_vert_total(8),
+ 23 => meas_vert_total(7),
+ 22 => meas_vert_total(6),
+ 21 => meas_vert_total(5),
+ 20 => meas_vert_total(4),
+ 19 => meas_vert_total(3),
+ 18 => meas_vert_total(2),
+ 17 => meas_vert_total(1),
+ 16 => meas_vert_total(0),
+ 12 => meas_vert_sync(12),
+ 11 => meas_vert_sync(11),
+ 10 => meas_vert_sync(10),
+ 9 => meas_vert_sync(9),
+ 8 => meas_vert_sync(8),
+ 7 => meas_vert_sync(7),
+ 6 => meas_vert_sync(6),
+ 5 => meas_vert_sync(5),
+ 4 => meas_vert_sync(4),
+ 3 => meas_vert_sync(3),
+ 2 => meas_vert_sync(2),
+ 1 => meas_vert_sync(1),
+ 0 => meas_vert_sync(0),
+ others => '0');
+ when b"00101" =>
+ reg_data_out <= (28 => meas_vert_fp(12),
+ 27 => meas_vert_fp(11),
+ 26 => meas_vert_fp(10),
+ 25 => meas_vert_fp(9),
+ 24 => meas_vert_fp(8),
+ 23 => meas_vert_fp(7),
+ 22 => meas_vert_fp(6),
+ 21 => meas_vert_fp(5),
+ 20 => meas_vert_fp(4),
+ 19 => meas_vert_fp(3),
+ 18 => meas_vert_fp(2),
+ 17 => meas_vert_fp(1),
+ 16 => meas_vert_fp(0),
+ 12 => meas_vert_bp(12),
+ 11 => meas_vert_bp(11),
+ 10 => meas_vert_bp(10),
+ 9 => meas_vert_bp(9),
+ 8 => meas_vert_bp(8),
+ 7 => meas_vert_bp(7),
+ 6 => meas_vert_bp(6),
+ 5 => meas_vert_bp(5),
+ 4 => meas_vert_bp(4),
+ 3 => meas_vert_bp(3),
+ 2 => meas_vert_bp(2),
+ 1 => meas_vert_bp(1),
+ 0 => meas_vert_bp(0),
+ others => '0');
+ when b"00110" =>
+ reg_data_out <= (28 => meas_horz_total(12),
+ 27 => meas_horz_total(11),
+ 26 => meas_horz_total(10),
+ 25 => meas_horz_total(9),
+ 24 => meas_horz_total(8),
+ 23 => meas_horz_total(7),
+ 22 => meas_horz_total(6),
+ 21 => meas_horz_total(5),
+ 20 => meas_horz_total(4),
+ 19 => meas_horz_total(3),
+ 18 => meas_horz_total(2),
+ 17 => meas_horz_total(1),
+ 16 => meas_horz_total(0),
+
+ 12 => meas_horz_sync(12),
+ 11 => meas_horz_sync(11),
+ 10 => meas_horz_sync(10),
+ 9 => meas_horz_sync(9),
+ 8 => meas_horz_sync(8),
+ 7 => meas_horz_sync(7),
+ 6 => meas_horz_sync(6),
+ 5 => meas_horz_sync(5),
+ 4 => meas_horz_sync(4),
+ 3 => meas_horz_sync(3),
+ 2 => meas_horz_sync(2),
+ 1 => meas_horz_sync(1),
+ 0 => meas_horz_sync(0),
+ others => '0');
+ when b"00111" =>
+ reg_data_out <= (28 => meas_horz_fp(12),
+ 27 => meas_horz_fp(11),
+ 26 => meas_horz_fp(10),
+ 25 => meas_horz_fp(9),
+ 24 => meas_horz_fp(8),
+ 23 => meas_horz_fp(7),
+ 22 => meas_horz_fp(6),
+ 21 => meas_horz_fp(5),
+ 20 => meas_horz_fp(4),
+ 19 => meas_horz_fp(3),
+ 18 => meas_horz_fp(2),
+ 17 => meas_horz_fp(1),
+ 16 => meas_horz_fp(0),
+
+ 12 => meas_horz_bp(12),
+ 11 => meas_horz_bp(11),
+ 10 => meas_horz_bp(10),
+ 9 => meas_horz_bp(9),
+ 8 => meas_horz_bp(8),
+ 7 => meas_horz_bp(7),
+ 6 => meas_horz_bp(6),
+ 5 => meas_horz_bp(5),
+ 4 => meas_horz_bp(4),
+ 3 => meas_horz_bp(3),
+ 2 => meas_horz_bp(2),
+ 1 => meas_horz_bp(1),
+ 0 => meas_horz_bp(0),
+ others => '0');
+
+ when b"01000" =>
+ reg_data_out <= (
+ 25 => meas_data_clocks_in_vb(25),
+ 24 => meas_data_clocks_in_vb(24),
+ 23 => meas_data_clocks_in_vb(23),
+ 22 => meas_data_clocks_in_vb(22),
+ 21 => meas_data_clocks_in_vb(21),
+ 20 => meas_data_clocks_in_vb(20),
+ 19 => meas_data_clocks_in_vb(19),
+ 18 => meas_data_clocks_in_vb(18),
+ 17 => meas_data_clocks_in_vb(17),
+ 16 => meas_data_clocks_in_vb(16),
+ 15 => meas_data_clocks_in_vb(15),
+ 14 => meas_data_clocks_in_vb(14),
+ 13 => meas_data_clocks_in_vb(13),
+ 12 => meas_data_clocks_in_vb(12),
+ 11 => meas_data_clocks_in_vb(11),
+ 10 => meas_data_clocks_in_vb(10),
+ 9 => meas_data_clocks_in_vb(9),
+ 8 => meas_data_clocks_in_vb(8),
+ 7 => meas_data_clocks_in_vb(7),
+ 6 => meas_data_clocks_in_vb(6),
+ 5 => meas_data_clocks_in_vb(5),
+ 4 => meas_data_clocks_in_vb(4),
+ 3 => meas_data_clocks_in_vb(3),
+ 2 => meas_data_clocks_in_vb(2),
+ 1 => meas_data_clocks_in_vb(1),
+ 0 => meas_data_clocks_in_vb(0),
+ others => '0');
+ when b"01001" =>
+ reg_data_out <= (
+ 25 => meas_pixels_in_frame(25),
+ 24 => meas_pixels_in_frame(24),
+ 23 => meas_pixels_in_frame(23),
+ 22 => meas_pixels_in_frame(22),
+ 21 => meas_pixels_in_frame(21),
+ 20 => meas_pixels_in_frame(20),
+ 19 => meas_pixels_in_frame(19),
+ 18 => meas_pixels_in_frame(18),
+ 17 => meas_pixels_in_frame(17),
+ 16 => meas_pixels_in_frame(16),
+ 15 => meas_pixels_in_frame(15),
+ 14 => meas_pixels_in_frame(14),
+ 13 => meas_pixels_in_frame(13),
+ 12 => meas_pixels_in_frame(12),
+ 11 => meas_pixels_in_frame(11),
+ 10 => meas_pixels_in_frame(10),
+ 9 => meas_pixels_in_frame(9),
+ 8 => meas_pixels_in_frame(8),
+ 7 => meas_pixels_in_frame(7),
+ 6 => meas_pixels_in_frame(6),
+ 5 => meas_pixels_in_frame(5),
+ 4 => meas_pixels_in_frame(4),
+ 3 => meas_pixels_in_frame(3),
+ 2 => meas_pixels_in_frame(2),
+ 1 => meas_pixels_in_frame(1),
+ 0 => meas_pixels_in_frame(0),
+ others => '0');
+ when b"01010" =>
+ reg_data_out <= (
+ 25 => meas_data_clocks_in_frame(25),
+ 24 => meas_data_clocks_in_frame(24),
+ 23 => meas_data_clocks_in_frame(23),
+ 22 => meas_data_clocks_in_frame(22),
+ 21 => meas_data_clocks_in_frame(21),
+ 20 => meas_data_clocks_in_frame(20),
+ 19 => meas_data_clocks_in_frame(19),
+ 18 => meas_data_clocks_in_frame(18),
+ 17 => meas_data_clocks_in_frame(17),
+ 16 => meas_data_clocks_in_frame(16),
+ 15 => meas_data_clocks_in_frame(15),
+ 14 => meas_data_clocks_in_frame(14),
+ 13 => meas_data_clocks_in_frame(13),
+ 12 => meas_data_clocks_in_frame(12),
+ 11 => meas_data_clocks_in_frame(11),
+ 10 => meas_data_clocks_in_frame(10),
+ 9 => meas_data_clocks_in_frame(9),
+ 8 => meas_data_clocks_in_frame(8),
+ 7 => meas_data_clocks_in_frame(7),
+ 6 => meas_data_clocks_in_frame(6),
+ 5 => meas_data_clocks_in_frame(5),
+ 4 => meas_data_clocks_in_frame(4),
+ 3 => meas_data_clocks_in_frame(3),
+ 2 => meas_data_clocks_in_frame(2),
+ 1 => meas_data_clocks_in_frame(1),
+ 0 => meas_data_clocks_in_frame(0),
+ others => '0');
+ -- last 4 clock samples
+ when b"01011" =>
+ reg_data_out <= pixel_fifo_axi_side;
+ axi_fifo_read_select <= '1';
+
+ -- these sample the number of pixel clocks coming in the last 4 fixed period
+ -- from this we can know the pixel clock rate and estimate stability
+
+ when b"01100" =>
+ reg_data_out <= shifter_pixel_ctr_samples(31 downto 0);
+ when b"01101" =>
+ reg_data_out <= shifter_pixel_ctr_samples(63 downto 32);
+ when b"01110" =>
+ reg_data_out <= shifter_pixel_ctr_samples(95 downto 64);
+ when b"01111" =>
+ reg_data_out <= shifter_pixel_ctr_samples(127 downto 96);
+
+ when b"10000" =>
+ reg_data_out <= timestamp_escapes_captured;
+
+
+ -- these are aimed at detecting badly connected channels,
+ -- ie only one polarity connected / driven,,, the stats for
+ -- escapes on that channel should become wrong
+
+ when b"10001" => -- escapes on ch0
+ reg_data_out <= meas_escapes(31 downto 0);
+
+ when b"10010" => -- escapes on ch1
+ reg_data_out <= meas_escapes(63 downto 32);
+
+ when b"10011" => -- escapes on ch2
+ reg_data_out <= meas_escapes(95 downto 64);
+
+ when b"10100" => -- detect data freshness
+ reg_data_out <= (
+ 31 => meas_vsync_stamp(15), -- frame # the vertical measurements were taken on
+ 30 => meas_vsync_stamp(14),
+ 29 => meas_vsync_stamp(13),
+ 28 => meas_vsync_stamp(12),
+ 27 => meas_vsync_stamp(11),
+ 26 => meas_vsync_stamp(10),
+ 25 => meas_vsync_stamp(9),
+ 24 => meas_vsync_stamp(8),
+ 23 => meas_vsync_stamp(7),
+ 22 => meas_vsync_stamp(6),
+ 21 => meas_vsync_stamp(5),
+ 20 => meas_vsync_stamp(4),
+ 19 => meas_vsync_stamp(3),
+ 18 => meas_vsync_stamp(2),
+ 17 => meas_vsync_stamp(1),
+ 16 => meas_vsync_stamp(0),
+
+ 12 => meas_horz_data_sample_line(12), -- line # the horizontal measurements were taken on
+ 11 => meas_horz_data_sample_line(11),
+ 10 => meas_horz_data_sample_line(10),
+ 9 => meas_horz_data_sample_line(9),
+ 8 => meas_horz_data_sample_line(8),
+ 7 => meas_horz_data_sample_line(7),
+ 6 => meas_horz_data_sample_line(6),
+ 5 => meas_horz_data_sample_line(5),
+ 4 => meas_horz_data_sample_line(4),
+ 3 => meas_horz_data_sample_line(3),
+ 2 => meas_horz_data_sample_line(2),
+ 1 => meas_horz_data_sample_line(1),
+ 0 => meas_horz_data_sample_line(0),
+ others => '0');
+
+ when b"10101" =>
+ reg_data_out <= (
+ 25 => meas_control_clocks_in_frame(25),
+ 24 => meas_control_clocks_in_frame(24),
+ 23 => meas_control_clocks_in_frame(23),
+ 22 => meas_control_clocks_in_frame(22),
+ 21 => meas_control_clocks_in_frame(21),
+ 20 => meas_control_clocks_in_frame(20),
+ 19 => meas_control_clocks_in_frame(19),
+ 18 => meas_control_clocks_in_frame(18),
+ 17 => meas_control_clocks_in_frame(17),
+ 16 => meas_control_clocks_in_frame(16),
+ 15 => meas_control_clocks_in_frame(15),
+ 14 => meas_control_clocks_in_frame(14),
+ 13 => meas_control_clocks_in_frame(13),
+ 12 => meas_control_clocks_in_frame(12),
+ 11 => meas_control_clocks_in_frame(11),
+ 10 => meas_control_clocks_in_frame(10),
+ 9 => meas_control_clocks_in_frame(9),
+ 8 => meas_control_clocks_in_frame(8),
+ 7 => meas_control_clocks_in_frame(7),
+ 6 => meas_control_clocks_in_frame(6),
+ 5 => meas_control_clocks_in_frame(5),
+ 4 => meas_control_clocks_in_frame(4),
+ 3 => meas_control_clocks_in_frame(3),
+ 2 => meas_control_clocks_in_frame(2),
+ 1 => meas_control_clocks_in_frame(1),
+ 0 => meas_control_clocks_in_frame(0),
+ others => '0');
+ when b"10110" =>
+ reg_data_out <= (
+ 25 => meas_control_clocks_in_vb(25),
+ 24 => meas_control_clocks_in_vb(24),
+ 23 => meas_control_clocks_in_vb(23),
+ 22 => meas_control_clocks_in_vb(22),
+ 21 => meas_control_clocks_in_vb(21),
+ 20 => meas_control_clocks_in_vb(20),
+ 19 => meas_control_clocks_in_vb(19),
+ 18 => meas_control_clocks_in_vb(18),
+ 17 => meas_control_clocks_in_vb(17),
+ 16 => meas_control_clocks_in_vb(16),
+ 15 => meas_control_clocks_in_vb(15),
+ 14 => meas_control_clocks_in_vb(14),
+ 13 => meas_control_clocks_in_vb(13),
+ 12 => meas_control_clocks_in_vb(12),
+ 11 => meas_control_clocks_in_vb(11),
+ 10 => meas_control_clocks_in_vb(10),
+ 9 => meas_control_clocks_in_vb(9),
+ 8 => meas_control_clocks_in_vb(8),
+ 7 => meas_control_clocks_in_vb(7),
+ 6 => meas_control_clocks_in_vb(6),
+ 5 => meas_control_clocks_in_vb(5),
+ 4 => meas_control_clocks_in_vb(4),
+ 3 => meas_control_clocks_in_vb(3),
+ 2 => meas_control_clocks_in_vb(2),
+ 1 => meas_control_clocks_in_vb(1),
+ 0 => meas_control_clocks_in_vb(0),
+ others => '0');
+
+
+ when b"10111" => -- where the VSYNC appears in terms of h pixels
+ reg_data_out <= (
+ 31 => meas_terc4_illegals_in_frame(15), -- illegal terc4 codes this frame
+ 30 => meas_terc4_illegals_in_frame(14),
+ 29 => meas_terc4_illegals_in_frame(13),
+ 28 => meas_terc4_illegals_in_frame(12),
+ 27 => meas_terc4_illegals_in_frame(11),
+ 26 => meas_terc4_illegals_in_frame(10),
+ 25 => meas_terc4_illegals_in_frame(9),
+ 24 => meas_terc4_illegals_in_frame(8),
+ 23 => meas_terc4_illegals_in_frame(7),
+ 22 => meas_terc4_illegals_in_frame(6),
+ 21 => meas_terc4_illegals_in_frame(5),
+ 20 => meas_terc4_illegals_in_frame(4),
+ 19 => meas_terc4_illegals_in_frame(3),
+ 18 => meas_terc4_illegals_in_frame(2),
+ 17 => meas_terc4_illegals_in_frame(1),
+ 16 => meas_terc4_illegals_in_frame(0),
+
+ 12 => meas_vsync_h_pos(12),
+ 11 => meas_vsync_h_pos(11),
+ 10 => meas_vsync_h_pos(10),
+ 9 => meas_vsync_h_pos(9),
+ 8 => meas_vsync_h_pos(8),
+ 7 => meas_vsync_h_pos(7),
+ 6 => meas_vsync_h_pos(6),
+ 5 => meas_vsync_h_pos(5),
+ 4 => meas_vsync_h_pos(4),
+ 3 => meas_vsync_h_pos(3),
+ 2 => meas_vsync_h_pos(2),
+ 1 => meas_vsync_h_pos(1),
+ 0 => meas_vsync_h_pos(0),
+ others => '0');
+ when b"11000" => -- must be 4 non-preamble control cycles before preamble
+ reg_data_out <= (
+ 12 => meas_hdmi_perr_control_pre_preamble(12),
+ 11 => meas_hdmi_perr_control_pre_preamble(11),
+ 10 => meas_hdmi_perr_control_pre_preamble(10),
+ 9 => meas_hdmi_perr_control_pre_preamble(9),
+ 8 => meas_hdmi_perr_control_pre_preamble(8),
+ 7 => meas_hdmi_perr_control_pre_preamble(7),
+ 6 => meas_hdmi_perr_control_pre_preamble(6),
+ 5 => meas_hdmi_perr_control_pre_preamble(5),
+ 4 => meas_hdmi_perr_control_pre_preamble(4),
+ 3 => meas_hdmi_perr_control_pre_preamble(3),
+ 2 => meas_hdmi_perr_control_pre_preamble(2),
+ 1 => meas_hdmi_perr_control_pre_preamble(1),
+ 0 => meas_hdmi_perr_control_pre_preamble(0),
+ others => '0');
+ when b"11001" => -- words actually read from fifo by DMA
+ reg_data_out <= dma_ctr_read_from_fifo(31 downto 0);
+ when b"11010" => -- words actually read from fifo by DMA
+ reg_data_out <= dma_ctr_used;
+ when others =>
+ reg_data_out <= (others => '1');
+ end case;
+ end process;
+
+ -- Output register or memory read data
+ process( S_AXI_ACLK ) is
+ begin
+ if (rising_edge (S_AXI_ACLK)) then
+ if ( S_AXI_ARESETN = '0' ) then
+ axi_rdata <= (others => '0');
+ else
+
+ -- sample the pixel clock counter every 64K AXI clocks (655us @ 100MHz, shifter replaced 2.4ms)
+ -- AXI clock shouldn't be spread-spectrum for this
+
+ axi_fifo_read_select_reg <= '0';
+
+ ctr_axi_clocks <= std_logic_vector(unsigned(ctr_axi_clocks) + 1);
+ if (ctr_axi_clocks = "1111111111111111") then
+ for n in 0 to 2 loop
+ shifter_pixel_ctr_samples(((n + 1) * 32) + 31 downto ((n + 1) * 32)) <=
+ shifter_pixel_ctr_samples((n * 32) + 31 downto (n * 32));
+ end loop;
+ shifter_pixel_ctr_samples(31 downto 0) <= std_logic_vector(
+ unsigned(hdmi_clk_counter) - unsigned(hdmi_clk_counter_start));
+ hdmi_clk_counter_start <= hdmi_clk_counter;
+ end if;
+ if (slv_reg_rden = '1') then
+ axi_fifo_read_select_reg <= axi_fifo_read_select;
+
+ -- When there is a valid read address (S_AXI_ARVALID) with
+ -- acceptance of read address by the slave (axi_arready),
+ -- output the read dada
+ -- Read address mux
+ axi_rdata <= reg_data_out; -- register read data
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+ -- Add user logic here
+
+ -- User logic ends
+
+end arch_imp;