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


-- The column machine manages the dq bus.  Since there is a single DQ
-- bus, and the column part of the DRAM is tightly coupled to this DQ
-- bus, conceptually, the DQ bus and all of the column hardware in
-- a multi rank DRAM array are managed as a single unit.
--
--
-- The column machine does not "enforce" the column timing directly.
-- It generates information and sends it to the bank machines.  If the
-- bank machines incorrectly make a request, the column machine will
-- simply overwrite the existing request with the new request even
-- if this would result in a timing or protocol violation.
--
-- The column machine
-- hosts the block that controls read and write data transfer
-- to and from the dq bus.
--
-- And if configured, there is provision for tracking the address
-- of a command as it moves through the column pipeline.  This
-- address will be logged for detected ECC errors.

entity col_mach is
   generic (
      TCQ                    : integer := 100;
      BANK_WIDTH             : integer := 3;
      BURST_MODE             : string := "8";
      COL_WIDTH              : integer := 12;
      CS_WIDTH               : integer := 4;
      DATA_BUF_ADDR_WIDTH    : integer := 8;
      DATA_BUF_OFFSET_WIDTH  : integer := 1;
      DELAY_WR_DATA_CNTRL    : integer := 0;
      DQS_WIDTH              : integer := 8;
      DRAM_TYPE              : string := "DDR3";
      EARLY_WR_DATA_ADDR     : string := "OFF";
      ECC                    : string := "OFF";
      MC_ERR_ADDR_WIDTH      : integer := 31;
      nCK_PER_CLK            : integer := 2;
      nPHY_WRLAT             : integer := 0;
      nRD_EN2CNFG_WR         : integer := 6;
      nWR_EN2CNFG_RD         : integer := 4;
      nWR_EN2CNFG_WR         : integer := 4;
      RANK_WIDTH             : integer := 2;
      ROW_WIDTH              : integer := 16
   );
   port (
      -- Outputs
      -- Inputs
      
      dq_busy_data           : out std_logic;           -- = 1'b0;
      
      -- The following generates a column command disable based mostly on the type
      -- of DRAM and the fabric to DRAM CK ratio.
      
      -- This generates a data offset based on fabric clock to DRAM CK ratio and
      -- the size bit.  Note that this is different that the dq_busy_data signal
      -- generated above.
      
      wr_data_offset         : out std_logic_vector(DATA_BUF_OFFSET_WIDTH - 1 downto 0);
      
      dfi_wrdata_en          : out std_logic_vector(DQS_WIDTH - 1 downto 0);
      
      wr_data_en             : out std_logic;
      
    
      wr_data_addr           : out std_logic_vector(DATA_BUF_ADDR_WIDTH - 1 downto 0);
      dfi_rddata_en          : out std_logic_vector(DQS_WIDTH - 1 downto 0);
      inhbt_wr_config        : out std_logic;     
      inhbt_rd_config        : out std_logic;
      
      rd_rmw                 : out std_logic;
      ecc_err_addr           : out std_logic_vector(MC_ERR_ADDR_WIDTH - 1 downto 0);
      ecc_status_valid       : out std_logic;
      wr_ecc_buf             : out std_logic;
      rd_data_end            : out std_logic;
 
      rd_data_addr           : out std_logic_vector(DATA_BUF_ADDR_WIDTH - 1 downto 0);
      rd_data_offset         : out std_logic_vector(DATA_BUF_OFFSET_WIDTH - 1 downto 0);
      rd_data_en             : out std_logic;

      clk                    : in std_logic;
      rst                    : in std_logic;
      sent_col               : in std_logic;
      col_size               : in std_logic;
      io_config              : in std_logic_vector(RANK_WIDTH downto 0);
      col_wr_data_buf_addr   : in std_logic_vector(DATA_BUF_ADDR_WIDTH - 1 downto 0);

      dfi_rddata_valid       : in std_logic;      
      col_periodic_rd        : in std_logic;
      col_data_buf_addr      : in std_logic_vector(DATA_BUF_ADDR_WIDTH - 1 downto 0);
      col_rmw                : in std_logic;

      col_ra                 : in std_logic_vector(RANK_WIDTH - 1 downto 0);
      col_ba                 : in std_logic_vector(BANK_WIDTH - 1 downto 0);
      col_row                : in std_logic_vector(ROW_WIDTH - 1 downto 0);
      col_a                  : in std_logic_vector(ROW_WIDTH - 1 downto 0)
   );
end entity col_mach;

architecture trans of col_mach 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 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;

function clogb2(size: integer) return integer is
   variable tmp : integer := 1;
   variable tmp_size : std_logic_vector (31 downto 0);
begin
  tmp_size := std_logic_vector(TO_UNSIGNED((size - 1),32));
  while ( to_integer(UNSIGNED(tmp_size)) > 1 ) loop
    tmp_size := std_logic_vector(UNSIGNED(tmp_size) srl 1);
    tmp := tmp + 1;
  end loop;
  return tmp;
  --for i in 23 downto 0 loop  
  --  if( size <= 2** i) then 
  --  tmp := i; 
  --  end if;
  --end loop;
  --return tmp;
end function clogb2;

function BOOLEAN_TO_STD_LOGIC(A : in BOOLEAN) return std_logic is
begin
   if A = true then
       return '1';
   else
       return '0';
   end if;
end function BOOLEAN_TO_STD_LOGIC;


function f_FIFO_WIDTH (DATA_BUF_ADDR_WIDTH: integer; DATA_BUF_OFFSET_WIDTH : integer ;MC_ERR_LINE_WIDTH : integer; ECC : string)
return integer is
begin

   if (ECC = "OFF") then
        return ( 1 + 1 + DATA_BUF_ADDR_WIDTH + DATA_BUF_OFFSET_WIDTH );
   else
        return (1 + 1 + DATA_BUF_ADDR_WIDTH + DATA_BUF_OFFSET_WIDTH + 1 + MC_ERR_LINE_WIDTH);
   end if;
    
end function f_FIFO_WIDTH;


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 function f_RAM_CNT;

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


   constant ONE                  : integer := 1;
   constant nRD_EN2CNFG_WR_LOCAL : integer := nRD_EN2CNFG_WR - 2;
   constant nWR_EN2CNFG_WR_LOCAL : integer := nWR_EN2CNFG_WR - 2;
   constant WR_WAIT_CNT_WIDTH    : integer := clogb2(nRD_EN2CNFG_WR_LOCAL + 1);

   constant nWR_EN2CNFG_RD_LOCAL : integer := nWR_EN2CNFG_RD - 2;
   constant RD_WAIT_CNT_WIDTH    : integer := clogb2(nWR_EN2CNFG_RD_LOCAL + 1);

   constant MC_ERR_LINE_WIDTH    : integer := MC_ERR_ADDR_WIDTH - DATA_BUF_OFFSET_WIDTH;
   constant FIFO_WIDTH           : integer := f_FIFO_WIDTH(DATA_BUF_ADDR_WIDTH ,DATA_BUF_OFFSET_WIDTH ,MC_ERR_LINE_WIDTH,ECC );
   
   constant FULL_RAM_CNT         : integer := (FIFO_WIDTH / 6);
   constant REMAINDER            : integer := FIFO_WIDTH mod 6;
   constant RAM_CNT              : integer := f_RAM_CNT(FULL_RAM_CNT ,REMAINDER ) ;
   constant RAM_WIDTH            : integer := (RAM_CNT * 6);

   signal ecc_err_addr_ns        : std_logic_vector(MC_ERR_ADDR_WIDTH - 1 downto 0);
   signal offset_r               : std_logic_vector(1 downto 0) := "00";
   signal offset_ns              : std_logic_vector(1 downto 0) := "00";
   signal data_end               : std_logic;
   signal offset_r1              : std_logic_vector(DATA_BUF_OFFSET_WIDTH - 1 downto 0) := (others => '0' );
   signal sent_col_r1            : std_logic;
   signal wrdata_en              : std_logic;
   signal read_data_valid        : std_logic;
   signal cnfg_wr_wait_r         : std_logic_vector(WR_WAIT_CNT_WIDTH - 1 downto 0);
   signal cnfg_wr_wait_ns        : std_logic_vector(WR_WAIT_CNT_WIDTH - 1 downto 0);
   signal cnfg_rd_wait_r         : std_logic_vector(RD_WAIT_CNT_WIDTH - 1 downto 0);
   signal cnfg_rd_wait_ns        : std_logic_vector(RD_WAIT_CNT_WIDTH - 1 downto 0);
   signal inhbt_wr_config_ns     : std_logic;
   signal inhbt_wr_config_r      : std_logic;
   signal inhbt_rd_config_ns     : std_logic;
   signal inhbt_rd_config_r      : std_logic;
   signal col_a_full             : std_logic_vector(11 downto 0);
   signal col_a_extracted        : std_logic_vector(COL_WIDTH - 1 downto 0);
   signal granted_col_d_r        : std_logic_vector(1 downto 0);
   signal granted_col_d_ns        : std_logic_vector(1 downto 0);
   signal col_wr_data_buf_addr_r  : std_logic_vector(DATA_BUF_ADDR_WIDTH - 1 downto 0);
   signal ecc_line                : std_logic_vector(MC_ERR_LINE_WIDTH  downto 0);
   signal rd_data_en_ns           : std_logic;
   signal real_fifo_data          : std_logic_vector(FIFO_WIDTH - 1 downto 0);
   signal fifo_in_data            : std_logic_vector(RAM_WIDTH - 1 downto 0);
   signal fifo_in_data_r          : std_logic_vector(RAM_WIDTH - 1 downto 0);
   signal fifo_out_data           : std_logic_vector(RAM_WIDTH - 1 downto 0);
   signal fifo_out_data_ns           : std_logic_vector(RAM_WIDTH - 1 downto 0);
   signal fifo_out_data_r           : std_logic_vector(RAM_WIDTH - 1 downto 0);
   
   signal rd_data_end_ns          : std_logic;
   signal periodic_rd             : std_logic;
   signal rd_data_addr_ns         : std_logic_vector(DATA_BUF_ADDR_WIDTH - 1 downto 0);
   signal rd_data_offset_ns       : std_logic_vector(DATA_BUF_OFFSET_WIDTH - 1 downto 0);
   signal ecc_status_valid_ns     : std_logic;
   signal wr_ecc_buf_ns     : std_logic;

   
   signal head_ns,head_r          : std_logic_vector(4 downto 0);
   signal head_r1                 : std_logic_vector(4 downto 0);
   signal tail_ns,tail_r          : std_logic_vector(4 downto 0);
   
   signal int8 : std_logic;
   
   -- Declare intermediate signals for referenced outputs
   signal rd_rmw_int3            : std_logic;
   signal rd_data_end_int1       : std_logic;
   signal rd_data_addr_int0      : std_logic_vector(DATA_BUF_ADDR_WIDTH - 1 downto 0);
   signal rd_data_offset_int2    : std_logic_vector(DATA_BUF_OFFSET_WIDTH - 1 downto 0);
   --this signal is defined to initialize the dq_busy_data with a value of 0. for conditions where none of the generate block is triggered.
   signal dq_busy_data_temp      : std_logic := '0';
begin
   -- Drive referenced outputs
   rd_rmw <= rd_rmw_int3;
   rd_data_end <= rd_data_end_int1;
   rd_data_addr <= rd_data_addr_int0;
   rd_data_offset <= rd_data_offset_int2;
   dq_busy_data <= dq_busy_data_temp ;
   int4 : if ((nCK_PER_CLK = 1) and ((BURST_MODE = "8") or (DRAM_TYPE = "DDR3"))) generate
      granted_col_d_ns <= (sent_col & granted_col_d_r(1));
      process (clk)
      begin
         if (clk'event and clk = '1') then
            granted_col_d_r <= granted_col_d_ns after (TCQ)*1 ps;
         end if;
      end process;
      
      process (granted_col_d_r, sent_col)
      begin
         dq_busy_data_temp <= sent_col or REDUCTION_OR(granted_col_d_r);
      end process;
      
   end generate;
   int5 : if (((nCK_PER_CLK = 2) and ((BURST_MODE = "8") or (DRAM_TYPE = "DDR3"))) or ((nCK_PER_CLK = 1) and ((BURST_MODE = "4") or (DRAM_TYPE = "DDR2")))) generate
      process (sent_col)
      begin
         dq_busy_data_temp <= sent_col;
      end process;
      
   end generate;
   data_valid_1_1 : if (DATA_BUF_OFFSET_WIDTH = 2) generate
      process (col_size, offset_r, rst, sent_col)
      begin
         if (rst = '1') then
            offset_ns <= (others => '0');
         else
            offset_ns <= offset_r;
            if (sent_col = '1') then
               offset_ns <= "01";
            elsif ((REDUCTION_OR(offset_r)) = '1' and (offset_r /= (col_size  & '1'))) then
               offset_ns <= offset_r + '1';
            else
               offset_ns <= "00";
            end if;
         end if;
      end process;
      
      process (clk)
      begin
         if (clk'event and clk = '1') then
            offset_r <= offset_ns after (TCQ)*1 ps;
         end if;
      end process;
      
      data_end <= BOOLEAN_TO_STD_LOGIC(offset_r = "11") when (col_size = '1') else
                  offset_r(0);
   end generate;
   
   --
   data_valid_2_1 : if (not(DATA_BUF_OFFSET_WIDTH = 2)) generate
 --     int8 <= '0' when (rst = '1') else
 --                 sent_col and col_size;
      process (col_size, rst, sent_col)
      begin
        if (rst = '1') then
        
           offset_ns(0) <= '0';
        else
          offset_ns(0) <=  sent_col and col_size;
        end if;
      end process;
      
      process (clk)
      begin
         if (clk'event and clk = '1') then
            offset_r(0) <= offset_ns(0) after (TCQ)*1 ps;
         end if;
      end process;
      
      data_end <= offset_r(0) when (col_size = '1') else
                  '1';
   end generate;
   offset_pipe : if ((nPHY_WRLAT = 1) or (DELAY_WR_DATA_CNTRL = 1)) generate
      process (clk)
      begin
         if (clk'event and clk = '1') then
            offset_r1 <= offset_r(DATA_BUF_OFFSET_WIDTH - 1 downto 0) after (TCQ)*1 ps;
         end if;
      end process;
      
   end generate;
   wr_data_offset <= offset_r1(DATA_BUF_OFFSET_WIDTH - 1 downto 0) when (DELAY_WR_DATA_CNTRL = 1) else
                     offset_r(DATA_BUF_OFFSET_WIDTH - 1 downto 0) when (EARLY_WR_DATA_ADDR = "OFF") else
                     offset_ns(DATA_BUF_OFFSET_WIDTH - 1 downto 0);
   process (clk)
   begin
      if (clk'event and clk = '1') then
         sent_col_r1 <= sent_col after (TCQ)*1 ps;
      end if;
   end process;
   
   wrdata_en <= ((sent_col or REDUCTION_OR(offset_r)) and io_config(RANK_WIDTH)) when (nPHY_WRLAT = 0) else
                ((sent_col_r1 or REDUCTION_OR(offset_r1)) and io_config(RANK_WIDTH));
                
   dfi_wrdata_en <= nCOPY(wrdata_en,DQS_WIDTH);
   
                                              -- BAD
   wr_data_en <= ((sent_col_r1 or REDUCTION_OR(offset_r1)) and io_config(RANK_WIDTH)) when (DELAY_WR_DATA_CNTRL = 1) else
                 ((sent_col or REDUCTION_OR(offset_r)) and io_config(RANK_WIDTH));
  
  delay_wr_data_cntrl_eq_1 : if (DELAY_WR_DATA_CNTRL = 1) generate
      process (clk)
      begin
         if (clk'event and clk = '1') then
            col_wr_data_buf_addr_r <= col_wr_data_buf_addr after (TCQ)*1 ps;
         end if;
      end process;
      
      wr_data_addr <= col_wr_data_buf_addr_r;
   end generate;
   int11 : if (not(DELAY_WR_DATA_CNTRL = 1)) generate
      wr_data_addr <= col_wr_data_buf_addr;
   end generate;
   read_data_valid <= (sent_col or REDUCTION_OR(offset_r)) and not(io_config(RANK_WIDTH));
   
   process (read_data_valid)
   begin
    for i in dfi_rddata_en'range loop
        dfi_rddata_en(i) <= read_data_valid;
    end loop;
   end process;

   process (cnfg_wr_wait_r, read_data_valid, rst, wrdata_en)
   variable cnfg_wr_wait_ns_tmp : std_logic_vector(WR_WAIT_CNT_WIDTH - 1 downto 0);
   begin
      if (rst = '1') then
         cnfg_wr_wait_ns_tmp := (others => '0' );
      else
         cnfg_wr_wait_ns_tmp :=  cnfg_wr_wait_r;
         if (wrdata_en = '1') then
            cnfg_wr_wait_ns_tmp :=  std_logic_vector(TO_UNSIGNED(nWR_EN2CNFG_WR_LOCAL, WR_WAIT_CNT_WIDTH));
         elsif (read_data_valid = '1') then
            cnfg_wr_wait_ns_tmp :=  std_logic_vector(TO_UNSIGNED(nRD_EN2CNFG_WR_LOCAL, WR_WAIT_CNT_WIDTH));
         elsif ((REDUCTION_OR(cnfg_wr_wait_r)) = '1') then
            cnfg_wr_wait_ns_tmp :=  cnfg_wr_wait_r - '1';
         end if;
      end if;
      
      cnfg_wr_wait_ns <= cnfg_wr_wait_ns_tmp;
      
   end process;
   
   process (clk)
   begin
      if (clk'event and clk = '1') then
         cnfg_wr_wait_r <= cnfg_wr_wait_ns after (TCQ)*1 ps;
      end if;
   end process;
   
   process (cnfg_rd_wait_r, rst, wrdata_en)
   variable cnfg_rd_wait_ns_tmp : std_logic_vector(RD_WAIT_CNT_WIDTH - 1 downto 0);
   begin
      if (rst = '1') then
         cnfg_rd_wait_ns_tmp := (others => '0' );
      else
         cnfg_rd_wait_ns_tmp := cnfg_rd_wait_r;
         if (wrdata_en = '1') then
            cnfg_rd_wait_ns_tmp := std_logic_vector(TO_UNSIGNED(nWR_EN2CNFG_RD_LOCAL, RD_WAIT_CNT_WIDTH));
         elsif ((REDUCTION_OR(cnfg_rd_wait_r)) = '1') then
            cnfg_rd_wait_ns_tmp := cnfg_rd_wait_r - '1';
         end if;
      end if;
      
      cnfg_rd_wait_ns <= cnfg_rd_wait_ns_tmp;
      
   end process;
   
   process (clk)
   begin
      if (clk'event and clk = '1') then
         cnfg_rd_wait_r <= cnfg_rd_wait_ns after (TCQ)*1 ps;
      end if;
   end process;
   
   inhbt_wr_config_ns <= BOOLEAN_TO_STD_LOGIC(cnfg_wr_wait_ns /=  nCOPY('0', WR_WAIT_CNT_WIDTH));
   process (clk)
   begin
      if (clk'event and clk = '1') then
         inhbt_wr_config_r <= inhbt_wr_config_ns after (TCQ)*1 ps;
      end if;
   end process;
   
   inhbt_wr_config <= sent_col or wrdata_en or inhbt_wr_config_r;
   inhbt_rd_config_ns <= BOOLEAN_TO_STD_LOGIC(cnfg_rd_wait_ns /=  nCOPY('0',RD_WAIT_CNT_WIDTH));
   process (clk)
   begin
      if (clk'event and clk = '1') then
         inhbt_rd_config_r <= inhbt_rd_config_ns after (TCQ)*1 ps;
      end if;
   end process;
   
   inhbt_rd_config <= sent_col or wrdata_en or inhbt_rd_config_r;

   COL_SEL_0_13 : if ( ROW_WIDTH <= 13 ) generate
   col_a_full <= ('0' & col_a(11) & col_a(9 downto 0));
   end generate;
   COL_SEL : if ( ROW_WIDTH > 13 ) generate
   col_a_full <= (col_a(13) & col_a(11) & col_a(9 downto 0));
   end generate;

   col_a_extracted <= col_a_full(COL_WIDTH - 1 downto 0);
   
   
   int12 : if (CS_WIDTH = 1) generate
      ecc_line <= (col_rmw & col_ba & col_row & col_a_extracted);
   end generate;
   int13 : if (not(CS_WIDTH = 1)) generate
      ecc_line <= (col_rmw & col_ra & col_ba & col_row & col_a_extracted);
      
   end generate;
   int14 : if (ECC = "OFF") generate
      real_fifo_data <= (data_end & col_periodic_rd & col_data_buf_addr & offset_r(DATA_BUF_OFFSET_WIDTH - 1 downto 0));
   end generate;
   int15 : if (not(ECC = "OFF")) generate
      real_fifo_data <= (data_end & col_periodic_rd & col_data_buf_addr & offset_r(DATA_BUF_OFFSET_WIDTH - 1 downto 0) & ecc_line);
      
   end generate;
   int16 : if (REMAINDER = 0) generate
      fifo_in_data <= ( real_fifo_data);
   end generate;
   int17 : if (not(REMAINDER = 0)) generate
      fifo_in_data <= nCOPY('0',6-REMAINDER) & real_fifo_data;
      
   end generate;

   process (clk)
   begin
      if (clk'event and clk = '1') then
         fifo_in_data_r <= fifo_in_data after (TCQ)*1 ps;
      end if;
   end process;
   
   head_ns <= (others => '0' ) when (rst = '1') else
              (head_r + "00001") when (read_data_valid = '1') else
              head_r;
   process (clk)
   begin
      if (clk'event and clk = '1') then
         
         head_r <= head_ns after (TCQ)*1 ps;
      end if;
   end process;

   process (clk)
   begin
      if (clk'event and clk = '1') then
         head_r1 <= head_r after (TCQ)*1 ps;
      end if;
   end process;
   
   tail_ns <= (others => '0' ) when (rst = '1') else
              (tail_r + "00001") when (dfi_rddata_valid = '1') else
              tail_r;
   process (clk)
   begin
      if (clk'event and clk = '1') then
         
         tail_r <= tail_ns after (TCQ)*1 ps;
      end if;
   end process;
   
   fifo_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    => fifo_out_data_ns((i * 6) + 6 - 1 downto (i * 6) + 4),
            dob    => fifo_out_data_ns((i * 6) + 4 - 1 downto (i * 6) + 2),
            doc    => fifo_out_data_ns((i * 6) + 2 - 1 downto (i * 6) + 0),
            dod    => open,
            dia    => fifo_in_data_r((i * 6) + 6 - 1 downto (i * 6) + 4),
            dib    => fifo_in_data_r((i * 6) + 4 - 1 downto (i * 6) + 2),
            dic    => fifo_in_data_r((i * 6) + 2 - 1 downto (i * 6) + 0),
            did    => "00",
            addra  => tail_ns,
            addrb  => tail_ns,
            addrc  => tail_ns,
            addrd  => head_r1,
            we     => '1',
            wclk   => clk
         );
      
   end generate;
      process (clk)
      begin
         if (clk'event and clk = '1') then
            fifo_out_data_r <= fifo_out_data_ns after (TCQ)*1 ps;
         end if;
      end process;
      
      
      -- When ECC is ON, most of the FIFO output is delayed
      -- by one state.
   int18 : if (ECC = "OFF") generate
      process (dfi_rddata_valid, fifo_out_data_r,periodic_rd)
      begin
      
         rd_data_offset_int2 <= fifo_out_data_r(DATA_BUF_OFFSET_WIDTH-1 downto 0);
         rd_data_addr_int0  <= fifo_out_data_r(DATA_BUF_ADDR_WIDTH + DATA_BUF_OFFSET_WIDTH -1 downto DATA_BUF_OFFSET_WIDTH );
         periodic_rd        <= fifo_out_data_r(DATA_BUF_ADDR_WIDTH + DATA_BUF_OFFSET_WIDTH );
         rd_data_end_int1   <= fifo_out_data_r(DATA_BUF_ADDR_WIDTH + DATA_BUF_OFFSET_WIDTH + 1  );
         
         ecc_err_addr <= (others => '0' );
         rd_data_en <= dfi_rddata_valid and not(periodic_rd);
         ecc_status_valid <= '0';
         wr_ecc_buf <= '0';
      end process;
      
      rd_rmw_int3 <= '0';
   end generate;
   int19 : if (not(ECC = "OFF")) generate
      rd_data_end_ns         <=  fifo_out_data_r( DATA_BUF_OFFSET_WIDTH +  MC_ERR_LINE_WIDTH + DATA_BUF_ADDR_WIDTH + 2);
      periodic_rd            <=  fifo_out_data_r( DATA_BUF_OFFSET_WIDTH +  MC_ERR_LINE_WIDTH + DATA_BUF_ADDR_WIDTH + 1);
      rd_data_addr_ns        <=  fifo_out_data_r( DATA_BUF_OFFSET_WIDTH +  MC_ERR_LINE_WIDTH + DATA_BUF_ADDR_WIDTH   downto DATA_BUF_OFFSET_WIDTH +  MC_ERR_LINE_WIDTH + 1);
      rd_data_offset_ns      <=  fifo_out_data_r(DATA_BUF_OFFSET_WIDTH  +  MC_ERR_LINE_WIDTH  downto MC_ERR_LINE_WIDTH + 1);
      rd_rmw_int3            <=  fifo_out_data_r(MC_ERR_LINE_WIDTH);
      ecc_err_addr_ns(DATA_BUF_OFFSET_WIDTH + MC_ERR_LINE_WIDTH - 1 downto DATA_BUF_OFFSET_WIDTH) <=  fifo_out_data_r(MC_ERR_LINE_WIDTH - 1 downto 0);
      ecc_err_addr_ns(DATA_BUF_OFFSET_WIDTH - 1 downto 0) <=  rd_data_offset_ns;
      process (clk)
      begin
         if (clk'event and clk = '1') then
            rd_data_end_int1 <= rd_data_end_ns after (TCQ)*1 ps;
         end if;
      end process;
      
      process (clk)
      begin
         if (clk'event and clk = '1') then
            rd_data_addr_int0 <= rd_data_addr_ns after (TCQ)*1 ps;
         end if;
      end process;
      
      process (clk)
      begin
         if (clk'event and clk = '1') then
            rd_data_offset_int2 <= rd_data_offset_ns after (TCQ)*1 ps;
         end if;
      end process;
      
      process (clk)
      begin
         if (clk'event and clk = '1') then
            ecc_err_addr <= ecc_err_addr_ns after (TCQ)*1 ps;
         end if;
      end process;
      
      rd_data_en_ns <= dfi_rddata_valid and not((periodic_rd or rd_rmw_int3));
      process (clk)
      begin
         if (clk'event and clk = '1') then
            rd_data_en <= rd_data_en_ns;
         end if;
      end process;
      
      ecc_status_valid_ns <= dfi_rddata_valid and not(periodic_rd);
      process (clk)
      begin
         if (clk'event and clk = '1') then
            ecc_status_valid <= ecc_status_valid_ns after (TCQ)*1 ps;
         end if;
      end process;
      
      wr_ecc_buf_ns <= dfi_rddata_valid and not(periodic_rd) and rd_rmw_int3;
      process (clk)
      begin
         if (clk'event and clk = '1') then
            wr_ecc_buf <= wr_ecc_buf_ns after (TCQ)*1 ps;
         end if;
      end process;
      
   end generate;
   
   
end architecture trans;


