----------------------------------------------------------------------------------------------
--
-- Generated by X-HDL Verilog Translator - Version 4.0.0 Apr. 30, 2006
-- Wed Jun 17 2009 01:00:41
--
--      Input file      : /home/samsonn/SandBox_LBranch_11.2/env/Databases/ip/src2/L/mig_v3_2/data/dlib/virtex6/ddr3_sdram/verilog/rtl/ecc/ecc_buf.v
--      Component name  : ecc_buf
--      Author          : 
--      Company         : 
--
--      Description     : 
--
--
----------------------------------------------------------------------------------------------
library UNISIM;
library ieee;
   use ieee.std_logic_1164.all;
   use ieee.std_logic_unsigned.all;
   use ieee.std_logic_arith.all;
--   use UNISIM.VCOMPONENTS.all;


entity ecc_buf is
   generic (
      TCQ                        : integer := 100;
      PAYLOAD_WIDTH              : integer := 64;
      DATA_BUF_ADDR_WIDTH        : integer := 4;
      DATA_BUF_OFFSET_WIDTH      : integer := 1;
      DATA_WIDTH                 : integer := 64
   );
   port (
      -- Outputs
      -- Inputs
      
      -- RMW architecture supports only 16 data buffer entries.
      -- Allow DATA_BUF_ADDR_WIDTH to be greater than 4, but
      -- assume the upper bits are used for tagging.
      
      -- block: rd_buffer_ram
      
      rd_merge_data              : out std_logic_vector(4 * DATA_WIDTH - 1 downto 0);
      clk                        : in std_logic;
      rst                        : in std_logic;
      rd_data_addr               : in std_logic_vector(DATA_BUF_ADDR_WIDTH - 1 downto 0);
      rd_data_offset             : in std_logic_vector(DATA_BUF_OFFSET_WIDTH - 1 downto 0);
      wr_data_addr               : in std_logic_vector(DATA_BUF_ADDR_WIDTH - 1 downto 0);
      wr_data_offset             : in std_logic_vector(DATA_BUF_OFFSET_WIDTH - 1 downto 0);
      rd_data                    : in std_logic_vector(4 * PAYLOAD_WIDTH - 1 downto 0);
      wr_ecc_buf                 : in std_logic
   );
end entity ecc_buf;

architecture trans of ecc_buf is

component RAM32M
  generic (
     INIT_A : bit_vector(63 downto 0) := X"0000000000000000";
     INIT_B : bit_vector(63 downto 0) := X"0000000000000000";
     INIT_C : bit_vector(63 downto 0) := X"0000000000000000";
     INIT_D : bit_vector(63 downto 0) := X"0000000000000000"
  );
  port (
     DOA : out std_logic_vector (1 downto 0);
     DOB : out std_logic_vector (1 downto 0);
     DOC : out std_logic_vector (1 downto 0);
     DOD : out std_logic_vector (1 downto 0);
     ADDRA : in std_logic_vector(4 downto 0);
     ADDRB : in std_logic_vector(4 downto 0);
     ADDRC : in std_logic_vector(4 downto 0);
     ADDRD : in std_logic_vector(4 downto 0);
     DIA : in std_logic_vector (1 downto 0);
     DIB : in std_logic_vector (1 downto 0);
     DIC : in std_logic_vector (1 downto 0);
     DID : in std_logic_vector (1 downto 0);
     WCLK : in std_ulogic;
     WE : in std_ulogic
  );
end component;

function f_RAM_CNT (FULL_RAM_CNT: integer; REMAINDER : integer)
return integer is
begin

if (REMAINDER = 0) then
    return FULL_RAM_CNT ;
else 
    return FULL_RAM_CNT  + 1 ;
end if;
end  f_RAM_CNT;
 

function nCOPY (A : in std_logic; B : in integer) return std_logic_vector is
variable tmp : std_logic_vector(B - 1 downto 0);
begin
    for i in 0 to B - 1  loop
      tmp(i) := A;
    end loop;
    return tmp;
end function nCOPY;

   constant BUF_WIDTH            : integer := 4 * DATA_WIDTH;
   constant FULL_RAM_CNT         : integer := (BUF_WIDTH / 6);
   constant REMAINDER            : integer := BUF_WIDTH mod 6;
   constant RAM_CNT              : integer := f_RAM_CNT(FULL_RAM_CNT ,REMAINDER );
   constant RAM_WIDTH            : integer := (RAM_CNT * 6);



   signal buf_wr_addr            : std_logic_vector(4 downto 0);
   signal buf_rd_addr_r          : std_logic_vector(4 downto 0);
   signal payload                : std_logic_vector(4 * DATA_WIDTH - 1 downto 0);
   signal h                      : integer;
   signal buf_out_data           : std_logic_vector(RAM_WIDTH - 1 downto 0);
   signal buf_in_data            : std_logic_vector(RAM_WIDTH - 1 downto 0);
begin
   int0 : if (DATA_BUF_ADDR_WIDTH >= 4) generate
      process (clk)
      begin
         if (clk'event and clk = '1') then
            buf_rd_addr_r <= (wr_data_addr(3 downto 0) & wr_data_offset) after (TCQ)*1 ps;
         end if;
      end process;
      
      buf_wr_addr <= (rd_data_addr(3 downto 0) & rd_data_offset);
   end generate;
   int1 : if (not(DATA_BUF_ADDR_WIDTH >= 4)) generate
      process (clk)
      begin
         if (clk'event and clk = '1') then
            buf_rd_addr_r <= ( nCOPY('0',4 - DATA_BUF_ADDR_WIDTH) & wr_data_addr(DATA_BUF_ADDR_WIDTH - 1 downto 0) & wr_data_offset) after (TCQ)*1 ps;
            
         end if;
      end process;
      
      buf_wr_addr <= ( nCOPY('0',4 - DATA_BUF_ADDR_WIDTH) & rd_data_addr(DATA_BUF_ADDR_WIDTH - 1 downto 0) & rd_data_offset);
   end generate;
   process (rd_data)
   begin
      for h in 0 to 3 loop
         payload((DATA_WIDTH*h)+DATA_WIDTH-1 downto h * DATA_WIDTH) <= rd_data((PAYLOAD_WIDTH*h)+DATA_WIDTH-1 downto h * PAYLOAD_WIDTH);
      end loop;
   end process;
   
   int2 : if (REMAINDER = 0) generate
      buf_in_data <=  payload;
   end generate;
   int3 : if (not(REMAINDER = 0)) generate
      buf_in_data <= nCOPY('0',6 - REMAINDER) & payload;
   end generate;
   rd_buffer_ram : for i in 0 to  RAM_CNT - 1 generate
      
      
      RAM32M0 : RAM32M
         generic map (
            INIT_A  => "0000000000000000000000000000000000000000000000000000000000000000",
            INIT_B  => "0000000000000000000000000000000000000000000000000000000000000000",
            INIT_C  => "0000000000000000000000000000000000000000000000000000000000000000",
            INIT_D  => "0000000000000000000000000000000000000000000000000000000000000000"
         )
         port map (
            DOA    => buf_out_data((i * 6) + 4 + 1 downto (i * 6) + 4),
            DOB    => buf_out_data((i * 6) + 2 + 1 downto (i * 6) + 2),
            DOC    => buf_out_data((i * 6) + 0 + 1 downto (i * 6) + 0),
            DOD    => open,
            DIA    => buf_in_data((i * 6) + 4 + 1 downto (i * 6) + 4),
            DIB    => buf_in_data((i * 6) + 2 + 1 downto (i * 6) + 2),
            DIC    => buf_in_data((i * 6) + 0 + 1 downto (i * 6) + 0),
            DID    => "00",
            ADDRA  => buf_rd_addr_r,
            ADDRB  => buf_rd_addr_r,
            ADDRC  => buf_rd_addr_r,
            ADDRD  => buf_wr_addr,
            WE     => wr_ecc_buf,
            WCLK   => clk
         );
   end generate;
   rd_merge_data <= buf_out_data(4 * DATA_WIDTH - 1 downto 0);
   
end architecture trans;



