---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2008
--
-- Filename: DPRam32.vhd
-- Language: VHDL '93
-- Project:  NDTS2100
--
-- Design Description:
-- Module to to generate dual-port Xilinx Distributed RAMs - 32 deep
-- With output FFs
---------------------------------------------------------------------------

library IEEE;
use IEEE.Std_Logic_1164.all;

library UNISIM;
use UNISIM.vcomponents.all;

entity DPRam32 is
  generic(gDataWidth:    integer range 1 to 32 := 32);
  port(Clk     : in  std_ulogic;
       WrEn    : in  std_ulogic;
       WrAddr  : in  std_logic_vector(4 downto 0);
       RdAddr  : in  std_logic_vector(4 downto 0);
       WrData  : in  std_logic_vector(gDataWidth-1 downto 0);
       RdData  : out std_logic_vector(gDataWidth-1 downto 0);
       DataOut : out std_logic_vector(gDataWidth-1 downto 0));
end entity DPRam32;


architecture Rtl of DPRam32 is

  signal Wr0: std_ulogic;
  signal Wr1: std_ulogic;
  signal Data0: std_logic_vector(gDataWidth-1 downto 0);
  signal Data1: std_logic_vector(gDataWidth-1 downto 0);
  signal DataMux: std_logic_vector(gDataWidth-1 downto 0);
  signal RdData0: std_logic_vector(gDataWidth-1 downto 0);
  signal RdData1: std_logic_vector(gDataWidth-1 downto 0);
begin

  Wr0 <= not WrAddr(4) and WrEn;
  Wr1 <= WrAddr(4) and WrEn;

  GenDPRam: for i in 0 to gDataWidth-1 generate
    Ram0 : RAM16X1D
    port map (DPO => Data0(i),
              SPO => RdData0(i),
              A0 => WrAddr(0),
              A1 => WrAddr(1),
              A2 => WrAddr(2),
              A3 => WrAddr(3),
              D =>  WrData(i),
              DPRA0 => RdAddr(0),
              DPRA1 => RdAddr(1),
              DPRA2 => RdAddr(2),
              DPRA3 => RdAddr(3),
              WCLK => Clk,
              WE => Wr0);

    Ram1 : RAM16X1D
    port map (DPO => Data1(i),
              SPO => RdData1(i),
              A0 => WrAddr(0),
              A1 => WrAddr(1),
              A2 => WrAddr(2),
              A3 => WrAddr(3),
              D =>  WrData(i),
              DPRA0 => RdAddr(0),
              DPRA1 => RdAddr(1),
              DPRA2 => RdAddr(2),
              DPRA3 => RdAddr(3),
              WCLK => Clk,
              WE => Wr1);

    RdData(i) <= RdData0(i) when WrAddr(4) = '0' else RdData1(i);

    DataMux(i) <= Data0(i) when RdAddr(4) = '0' else Data1(i);

    OpFF: process(Clk)
    begin
    	if Clk'event and Clk = '1' then
        DataOut(i) <= DataMux(i);
    	end if;
    end process OpFF;

  end generate;
  
end Rtl;
