----------------------------------------------------------------------------------------------
--
-- Generated by X-HDL Verilog Translator - Version 4.0.0 Apr. 30, 2006
-- Wed Jun 17 2009 01:02:04
--
--      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_merge_enc.v
--      Component name  : ecc_merge_enc
--      Author          : 
--      Company         : 
--
--      Description     : 
--
--
----------------------------------------------------------------------------------------------

library ieee;
   use ieee.std_logic_1164.all;
   use ieee.std_logic_unsigned.all;


entity ecc_merge_enc is
   generic (
      TCQ                        : integer := 100;
      PAYLOAD_WIDTH              : integer := 64;
      CODE_WIDTH                 : integer := 72;
      DATA_BUF_ADDR_WIDTH        : integer := 4;
      DATA_BUF_OFFSET_WIDTH      : integer := 1;
      DATA_WIDTH                 : integer := 64;
      DQ_WIDTH                   : integer := 72;
      ECC_WIDTH                  : integer := 8
   );
   port (
      -- Outputs
      -- Inputs
      
      -- Merge new data with memory read data.
      
      -- Generate ECC and overlay onto dfi_wrdata.
      dfi_wrdata                 : out std_logic_vector(4 * DQ_WIDTH - 1 downto 0);
      
      -- Set all DRAM masks to zero.
      dfi_wrdata_mask            : out std_logic_vector(4 * DQ_WIDTH / 8 - 1 downto 0);
      clk                        : in std_logic;
      rst                        : in std_logic;
      wr_data                    : in std_logic_vector(4 * PAYLOAD_WIDTH - 1 downto 0);
      wr_data_mask               : in std_logic_vector(4 * DATA_WIDTH / 8 - 1 downto 0);
      rd_merge_data              : in std_logic_vector(4 * DATA_WIDTH - 1 downto 0);
      h_rows                     : in std_logic_vector(CODE_WIDTH * ECC_WIDTH - 1 downto 0);
      raw_not_ecc                : in std_logic_vector(3 downto 0)
   );
end entity ecc_merge_enc;

architecture trans of ecc_merge_enc is

function REDUCTION_XOR( A: in std_logic_vector) return std_logic is
  variable tmp : std_logic := '0';
begin
  for i in A'range loop
       tmp := tmp xor A(i);
  end loop;
  return tmp;
end function REDUCTION_XOR;

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;

   signal merged_data            : std_logic_vector(4 * PAYLOAD_WIDTH - 1 downto 0);
   signal k                      : integer;
   signal raw_not_ecc_r          : std_logic_vector(3 downto 0);
   signal wr_data_r              : std_logic_vector(4 * PAYLOAD_WIDTH - 1 downto 0);
   signal wr_data_mask_r         : std_logic_vector(4 * DATA_WIDTH / 8 - 1 downto 0);
   signal rd_merge_data_r        : std_logic_vector(4 * DATA_WIDTH - 1 downto 0);
begin

   process (clk)
   begin
      if (clk'event and clk = '1') then
	  	wr_data_r <= wr_data after (TCQ)*1 ps;
      end if;
   end process;

   process (clk)
   begin
      if (clk'event and clk = '1') then
	  	wr_data_mask_r <= wr_data_mask after (TCQ)*1 ps;
      end if;
   end process;

   process (clk)
   begin
      if (clk'event and clk = '1') then
	  	rd_merge_data_r <= rd_merge_data after (TCQ)*1 ps;
      end if;
   end process;
	
   merge_data_outer : for h in 0 to 3 generate
      merge_data_inner : for i in 0 to  DATA_WIDTH / 8 - 1 generate
         merged_data((h*PAYLOAD_WIDTH+i*8)+7 downto (h*PAYLOAD_WIDTH+i*8)) <= 
		         rd_merge_data_r((h*DATA_WIDTH+i*8)+7 downto (h*DATA_WIDTH+i*8)) when (wr_data_mask_r(h*DATA_WIDTH/8+i) = '1') 
		         else wr_data_r((h*PAYLOAD_WIDTH+i*8)+7 downto (h*PAYLOAD_WIDTH+i*8));
		 
      end generate;
      int0 : if (PAYLOAD_WIDTH > DATA_WIDTH) generate
         merged_data((h + 1)*PAYLOAD_WIDTH-1 downto ((h +1)*PAYLOAD_WIDTH)-PAYLOAD_WIDTH+DATA_WIDTH) <=
		         wr_data_r((h + 1)*PAYLOAD_WIDTH-1 downto ((h +1)*PAYLOAD_WIDTH)-PAYLOAD_WIDTH+DATA_WIDTH);
      end generate;
   end generate;


   process (clk)
   begin
      if (clk'event and clk = '1') then
	  	raw_not_ecc_r <= raw_not_ecc after (TCQ)*1 ps;
      end if;
   end process;
   
   ecc_word : for j in 0 to 3 generate
      process (h_rows, merged_data, raw_not_ecc_r)
      variable dfi_wrdata_tmp : std_logic_vector(DQ_WIDTH-1 downto 0);
      begin
         dfi_wrdata_tmp(  DQ_WIDTH - 1 downto 0) := nCOPY('0',DQ_WIDTH-PAYLOAD_WIDTH)  & merged_data(j * PAYLOAD_WIDTH + PAYLOAD_WIDTH - 1 downto j * PAYLOAD_WIDTH);
         for k in 0 to  ECC_WIDTH - 1 loop
            if (raw_not_ecc_r(j) = '0') then
               dfi_wrdata_tmp(  CODE_WIDTH - k - 1) := REDUCTION_XOR((merged_data(j * PAYLOAD_WIDTH + DATA_WIDTH - 1 downto j * PAYLOAD_WIDTH) 
                                                                and h_rows(k * CODE_WIDTH + DATA_WIDTH - 1 downto k * CODE_WIDTH)));
            end if;
         end loop;
         
         dfi_wrdata(j * DQ_WIDTH + DQ_WIDTH - 1 downto j * DQ_WIDTH) <= dfi_wrdata_tmp;
      end process;
      
   end generate;
   dfi_wrdata_mask <= nCOPY('0',4*DQ_WIDTH/8);
   
end architecture trans;


