hdmi/convert_30to15_fifo.vhd

165 lines
6.4 KiB
VHDL

-- -----------------------------------------------------------------------------
-- Copyright (c) 2013 Benjamin Krill <benjamin@krll.de>
--
-- 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.
-- -----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.dvi_package.all;
library UNISIM;
use UNISIM.Vcomponents.all;
entity convert_30to15_fifo is
port (
rst : in std_logic;
clk : in std_logic;
clkx2 : in std_logic;
data_i : in std_logic_vector(29 downto 0); -- input data for 2:1 serialisation
data_o : out std_logic_vector(14 downto 0) -- 5-bit data out
);
end convert_30to15_fifo;
architecture convert_30to15_fifo of convert_30to15_fifo is
signal wa : std_logic_vector( 3 downto 0);
signal wa_q : std_logic_vector( 3 downto 0);
signal ra : std_logic_vector( 3 downto 0);
signal ra_q : std_logic_vector( 3 downto 0);
signal data_int : std_logic_vector(29 downto 0);
signal rstsync_q : std_logic;
signal rstsync : std_logic;
signal rstp : std_logic;
signal sync : std_logic;
signal syncn : std_logic;
signal db : std_logic_vector(29 downto 0);
signal mux : std_logic_vector(14 downto 0);
constant ADDR0 : std_logic_vector( 3 downto 0) := "0000";
constant ADDR1 : std_logic_vector( 3 downto 0) := "0001";
constant ADDR2 : std_logic_vector( 3 downto 0) := "0010";
constant ADDR3 : std_logic_vector( 3 downto 0) := "0011";
constant ADDR4 : std_logic_vector( 3 downto 0) := "0100";
constant ADDR5 : std_logic_vector( 3 downto 0) := "0101";
constant ADDR6 : std_logic_vector( 3 downto 0) := "0110";
constant ADDR7 : std_logic_vector( 3 downto 0) := "0111";
constant ADDR8 : std_logic_vector( 3 downto 0) := "1000";
constant ADDR9 : std_logic_vector( 3 downto 0) := "1001";
constant ADDR10 : std_logic_vector( 3 downto 0) := "1010";
constant ADDR11 : std_logic_vector( 3 downto 0) := "1011";
constant ADDR12 : std_logic_vector( 3 downto 0) := "1100";
constant ADDR13 : std_logic_vector( 3 downto 0) := "1101";
constant ADDR14 : std_logic_vector( 3 downto 0) := "1110";
constant ADDR15 : std_logic_vector( 3 downto 0) := "1111";
begin
-- --------------------------------------------------
-- Here we instantiate a 16x10 Dual Port RAM
-- and fill first it with data aligned to
-- clk domain
-- --------------------------------------------------
fdc_wa0: FDC port map (C => clk, D => wa_q(0), CLR => rst, Q => wa(0));
fdc_wa1: FDC port map (C => clk, D => wa_q(1), CLR => rst, Q => wa(1));
fdc_wa2: FDC port map (C => clk, D => wa_q(2), CLR => rst, Q => wa(2));
fdc_wa3: FDC port map (C => clk, D => wa_q(3), CLR => rst, Q => wa(3));
process (wa)
begin
case wa is
when ADDR0 => wa_q <= ADDR1;
when ADDR1 => wa_q <= ADDR2;
when ADDR2 => wa_q <= ADDR3;
when ADDR3 => wa_q <= ADDR4;
when ADDR4 => wa_q <= ADDR5;
when ADDR5 => wa_q <= ADDR6;
when ADDR6 => wa_q <= ADDR7;
when ADDR7 => wa_q <= ADDR8;
when ADDR8 => wa_q <= ADDR9;
when ADDR9 => wa_q <= ADDR10;
when ADDR10 => wa_q <= ADDR11;
when ADDR11 => wa_q <= ADDR12;
when ADDR12 => wa_q <= ADDR13;
when ADDR13 => wa_q <= ADDR14;
when ADDR14 => wa_q <= ADDR15;
when others => wa_q <= ADDR0;
end case;
end process;
fifo_u: entity work.DRAM16XN
generic map (data_width => 30)
port map (
DATA_IN => data_i,
ADDRESS => wa,
ADDRESS_DP => ra,
WRITE_EN => '1',
CLK => clk,
O_DATA_OUT => open,
O_DATA_OUT_DP => data_int
);
-- --------------------------------------------------
-- Here starts clk2x domain for fifo read out
-- FIFO read is set to be once every 2 cycles of clk2x in order
-- to keep up pace with the fifo write speed
-- Also FIFO read reset is delayed a bit in order to avoid
-- underflow.
-- --------------------------------------------------
fdc_ra0: FDRE port map (C => clkx2, D => ra_q(0), R => rstp, CE => sync, Q => ra(0));
fdc_ra1: FDRE port map (C => clkx2, D => ra_q(1), R => rstp, CE => sync, Q => ra(1));
fdc_ra2: FDRE port map (C => clkx2, D => ra_q(2), R => rstp, CE => sync, Q => ra(2));
fdc_ra3: FDRE port map (C => clkx2, D => ra_q(3), R => rstp, CE => sync, Q => ra(3));
process (ra)
begin
case ra is
when ADDR0 => ra_q <= ADDR1;
when ADDR1 => ra_q <= ADDR2;
when ADDR2 => ra_q <= ADDR3;
when ADDR3 => ra_q <= ADDR4;
when ADDR4 => ra_q <= ADDR5;
when ADDR5 => ra_q <= ADDR6;
when ADDR6 => ra_q <= ADDR7;
when ADDR7 => ra_q <= ADDR8;
when ADDR8 => ra_q <= ADDR9;
when ADDR9 => ra_q <= ADDR10;
when ADDR10 => ra_q <= ADDR11;
when ADDR11 => ra_q <= ADDR12;
when ADDR12 => ra_q <= ADDR13;
when ADDR13 => ra_q <= ADDR14;
when ADDR14 => ra_q <= ADDR15;
when others => ra_q <= ADDR0;
end case;
end process;
fdp_rst: FDP port map (C => clkx2, D => rst, PRE => rst, Q => rstsync);
fd_rstsync: FD port map (C => clkx2, D => rstsync, Q => rstsync_q);
fd_rstp: FD port map (C => clkx2, D => rstsync_q, Q => rstp);
sync_gen: FDR port map (Q => sync, C => clkx2, R => rstp, D => syncn);
syncn <= not sync;
fd_db: for I in 0 to 29 generate
fd_db_I: FDE port map (C => clkx2, D => data_int(I), CE => sync, Q => db(I));
end generate;
mux <= db(14 downto 0) when sync = '0' else db(29 downto 15);
fd_out: for I in 0 to 14 generate
fd_outI: FD port map (C => clkx2, D => mux(I), Q => data_o(I));
end generate;
end convert_30to15_fifo;