

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

library work;
use work.common_interface.all;
--use work.ddrii_if_parameters_0.all;

entity dram2if is
  generic (
    chipscope : boolean := false);
  port (
    lclk            : in    std_logic;
    rst             : in    std_logic;
    sysclk          : in    std_logic;
    -- SYSGEN Port Interface
    dram_out        : in    extmem_type;
    dram_in         : out   extmem_type;
    -- Local Bus Interface
    ld_i            : in    std_logic_vector(63 downto 0);
    ld_o            : out   std_logic_vector(63 downto 0);
    la_q            : in    std_logic_vector(27 downto 0);
    lwrite          : in    std_logic;
    lblast          : in    std_logic;
    lbterm          : in    std_logic;
    ds_xfer         : in    std_logic;
    lads            : in    std_logic;
    ready           : out   std_logic;
    stop            : out   std_logic;
    lb_request      : out   std_logic;
    lb_grant        : in    std_logic;
    lb_rskip        : in    std_logic_vector(4 downto 0);
    lb_roffset      : in    std_logic_vector(4 downto 0);
    status          : out   std_logic_vector(31 downto 0);
    debug           : out   std_logic_vector(63 downto 0);
    -- Connections to DDRII Clocking and Infrastructure modules
    clk_0           : in    std_logic;
    clk_90          : in    std_logic;
    CNTL_CLK_ID1    : in    std_logic;
    CNTL_CLK_ID2    : in    std_logic;
    CNTL_CLK_ID3    : in    std_logic;
    CNTL_CLK_ID4    : in    std_logic;
    sys_rst         : in    std_logic;
    sys_rst90       : in    std_logic;
    SYS_RST_ID      : in    std_logic;
    idelay_ctrl_rdy : in    std_logic;
    online          : out   std_logic;
    -- RAM Interface
    DDR2_RAS_N      : out   std_logic;
    DDR2_CAS_N      : out   std_logic;
    DDR2_WE_N       : out   std_logic;
    DDR2_ODT        : out   std_logic;
    DDR2_CKE        : out   std_logic;
    DDR2_CS_N       : out   std_logic;
    DDR2_DQ         : inout std_logic_vector(31 downto 0);
    DDR2_DQS        : inout std_logic_vector(3 downto 0);
    DDR2_DQS_N      : inout std_logic_vector(3 downto 0);
    DDR2_DM         : out   std_logic_vector(3 downto 0);
    DDR2_CK         : out   std_logic_vector(1 downto 0);
    DDR2_CK_N       : out   std_logic_vector(1 downto 0);
    DDR2_BA         : out   std_logic_vector(2 downto 0);
    DDR2_A          : out   std_logic_vector(12 downto 0)
    );
end dram2if;



architecture rtl of dram2if is

  
  signal dram_d, dram_q                             : std_logic_vector(63 downto 0);
  signal dram_a                                     : std_logic_vector(27 downto 0);
  signal dram_r, dram_w, dram_req, dram_gnt, dram_v : std_logic;
  signal lbus_busy                                  : std_logic;

  signal d_dram                     : std_logic_vector(63 downto 0);
  signal a_dram                     : std_logic_vector(27 downto 0);
  signal r_dram, w_dram, dram_valid : std_logic;

  signal reading : std_logic;

  component async_fifo1
    generic (
      width : natural);
    port (
      wclk    : in  std_logic;
      rst     : in  std_logic;
      wadv    : in  std_logic;
      wdata   : in  std_logic_vector(width-1 downto 0);
      wfull   : out std_logic;
      wnfull  : out std_logic;
      rclk    : in  std_logic;
      radv    : in  std_logic;
      rdata   : out std_logic_vector(width-1 downto 0);
      rdw_out : out std_logic_vector(width-1 downto 0);
      rempty  : out std_logic;
      rnempty : out std_logic);
  end component;

  component xlreqgrantmanager_ad
    port (hw_req     : in  std_logic;
          sw_req     : out std_logic;
          hw_grant   : out std_logic;
          sw_grant   : in  std_logic;
          ram_active : in  std_logic;
          clk        : in  std_logic);
  end component;
  signal ram_active : std_logic;


  component wrapper_sync_fifo
    generic (
      width : natural := 32);
    port (
      clk     : in  std_logic;
      rst     : in  std_logic;
      wadv    : in  std_logic;
      wdata   : in  std_logic_vector(width-1 downto 0);
      wnfull  : out std_logic;
      wfull   : out std_logic;
      radv    : in  std_logic;
      rdata   : out std_logic_vector(width-1 downto 0);
      rdw_out : out std_logic_vector(width-1 downto 0);
      rempty  : out std_logic;
      rnempty : out std_logic
      );
  end component;

  component sync_fifo_bram
    generic (
      width : natural := 32);
    port (
      clk     : in  std_logic;
      rst     : in  std_logic;
      wadv    : in  std_logic;
      wdata   : in  std_logic_vector(width-1 downto 0);
      wnfull  : out std_logic;
      wfull   : out std_logic;
      radv    : in  std_logic;
      rdata   : out std_logic_vector(width-1 downto 0);
      rdw_out : out std_logic_vector(width-1 downto 0);
      rempty  : out std_logic;
      rnempty : out std_logic
      );
  end component;


  -- Component Declaration for the DDR2 Memory Controller
  component ddr2_ad_wrap_small
    port (
      -- User Interface --
      clk              : in    std_logic;
      flush            : in    std_logic;
      w                : in    std_logic;
      r                : in    std_logic;
      a                : in    std_logic_vector (27 downto 0);
      d                : in    std_logic_vector (63 downto 0);
      dm               : in    std_logic_vector (7 downto 0);
      q                : out   std_logic_vector (63 downto 0);
      qv               : out   std_logic;
      rd_en            : in    std_logic;
      rd_ready         : out   std_logic;
      full             : out   std_logic;
      empty            : out   std_logic;
      error            : out   std_logic;
      -- DDR2 Interface --
      cntrl_DDR2_DQ    : inout std_logic_vector(31 downto 0);
      cntrl_DDR2_A     : out   std_logic_vector(12 downto 0);
      cntrl_DDR2_BA    : out   std_logic_vector(2 downto 0);
      cntrl_DDR2_RAS_N : out   std_logic;
      cntrl_DDR2_CAS_N : out   std_logic;
      cntrl_DDR2_WE_N  : out   std_logic;
      cntrl_DDR2_CS_N  : out   std_logic;
      cntrl_DDR2_ODT   : out   std_logic;
      cntrl_DDR2_CKE   : out   std_logic;
      cntrl_DDR2_DM    : out   std_logic_vector(3 downto 0);
      cntrl_DDR2_DQS   : inout std_logic_vector(3 downto 0);
      cntrl_DDR2_DQS_N : inout std_logic_vector(3 downto 0);
      cntrl_DDR2_CK    : out   std_logic_vector(1 downto 0);
      cntrl_DDR2_CK_N  : out   std_logic_vector(1 downto 0);
      -- Infrastructure Interface --
      CNTL_CLK         : in    std_logic;
      CNTL_CLK90       : in    std_logic;
      CNTL_CLK_ID1     : in    std_logic;
      CNTL_CLK_ID2     : in    std_logic;
      CNTL_CLK_ID3     : in    std_logic;
      CNTL_CLK_ID4     : in    std_logic;
      idelay_ctrl_rdy  : in    std_logic;
      SYS_RST          : in    std_logic;
      SYS_RST_90       : in    std_logic;
      SYS_RST_ID       : in    std_logic;
      control1         : in    std_logic_vector(35 downto 0);
      control2         : in    std_logic_vector(35 downto 0);
      status           : out   std_logic_vector(31 downto 0)
      );
  end component;



  signal ctrl_fifo_wadv, ctrl_fifo_radv, ctrl_fifo_empty : std_logic;
  signal ctrl_fifo_wdata, ctrl_fifo_rdata                : std_logic_vector(25 downto 0);
  signal ctrl_fifo_wnfull, ctrl_fifo_wfull               : std_logic;

  signal write_fifo_radv, write_fifo_wadv, write_fifo_empty, write_fifo_empty0 : std_logic;
  signal read_fifo_empty                                                       : std_logic;

  signal ctrl_fifo1_wadv, ctrl_fifo1_radv, ctrl_fifo1_empty : std_logic;
  signal ctrl_fifo1_wdata, ctrl_fifo1_rdata                 : std_logic_vector(30 downto 0);
  signal ctrl_fifo1_nempty                                  : std_logic;
  signal ctrl_fifo_nempty                                   : std_logic;
  signal ctrl_fifo_empty_q, ctrl_fifo1_empty_q              : std_logic;

  signal write_fifo1_radv, write_fifo1_wadv, write_fifo1_empty, write_fifo1_empty_q, write_fifo1_nempty : std_logic;

  signal read_fifo1_empty, read_fifo1_nempty, read_fifo1_radv : std_logic;
  signal read_fifo1_nfull                                     : std_logic;

  signal lads_ddr, lblast_ddr, lwrite_ddr : std_logic;
  signal lb_addr_ddr                      : std_logic_vector(27 downto 0);
  signal ld_i_ddr                         : std_logic_vector(63 downto 0);
  signal lb_valid                         : std_logic;

  signal lb_reading, lb_writing : std_logic;
  signal lb_active              : std_logic;
  signal lads_ignore            : std_logic;
  signal lb_reading_burst       : std_logic;

  signal read_fifo2_empty, read_fifo1_full, read_fifo2_nfull, read_fifo2_radv : std_logic;
  signal read_fifo2_data                                                      : std_logic_vector(63 downto 0);
  signal read_fifo1_rdw_out                                                   : std_logic_vector(63 downto 0);
  signal ld_o_reg_full                                                        : std_logic;
  signal ld_o_reg                                                             : std_logic_vector(63 downto 0);

  signal rst_fifos      : std_logic;
  signal rst_fifos_lclk : std_logic;
  signal rst_fifo_count : std_logic_vector(5 downto 0);
  signal ready_sig      : std_logic;

  signal prefetch_count : std_logic_vector(7 downto 0);

  signal dram_busy_reg      : std_logic;
  signal ctrl_fifo1_wnfull  : std_logic;
  signal write_fifo1_wnfull : std_logic;

  signal write_fifo1_empty_reg : std_logic;

  signal ctrl_active, data_active : std_logic;

  signal write_ready                     : std_logic;
  signal lads_reg, lw_reg1, lw_reg2      : std_logic;
  signal ready_sig180, last_ready_sig180 : std_logic;

  signal lblast_reg : std_logic;

  signal q        : std_logic_vector(63 downto 0);
  signal qv       : std_logic;
  signal r, w, r1 : std_logic;
  signal d        : std_logic_vector(63 downto 0);
  signal dm       : std_logic_vector(7 downto 0);
  signal a        : std_logic_vector(27 downto 0);

  signal lb_r, lb_w                                : std_logic;
  signal lb_addr                                   : std_logic_vector(27 downto 0);
  signal lb_data                                   : std_logic_vector(63 downto 0);
  signal lb_addr1, lb_addr2, lb_addr3, lb_addr_reg : std_logic_vector(27 downto 0);
  signal lb_r1, lb_r2, lb_r3                       : std_logic;
  signal lb_rskip_reg, lb_roffset_reg              : std_logic_vector(4 downto 0);


  signal ctrl_fifo_radv1, a_reg_plus1_eq_a_dram, fifo_reg_empty : std_logic;
  signal nfull, nfull_reg                                       : std_logic;
  signal flush                                                  : std_logic;
  signal flush1                                                 : std_logic;
  signal flush2                                                 : std_logic;
  signal rfl                                                    : std_logic;
  signal online_i                                               : std_logic;
  signal stop_i                                                 : std_logic;
  signal pre_ds_xfer                                            : std_logic;
  signal ready_sig_reg                                          : std_logic;

  signal error_i  : std_logic;
  signal rd_ready : std_logic;

  signal rdfifo_empty_pipe : std_logic_vector(5 downto 0);

  signal dram_empty : std_logic;

  signal dram_wait_count : std_logic_vector(7 downto 0);

  -------------------------------------------------------------------
  component icon
    port
      (
        control0 : out std_logic_vector(35 downto 0);
        control1 : out std_logic_vector(35 downto 0)
        );
  end component;

  -------------------------------------------------------------------
  --
  --  ILA core component declaration
  --
  -------------------------------------------------------------------
  component ila
    port
      (
        control : in std_logic_vector(35 downto 0);
        clk     : in std_logic;
        data    : in std_logic_vector(31 downto 0);
        trig0   : in std_logic_vector(31 downto 0)
        );
  end component;


  -------------------------------------------------------------------
  --
  --  ILA core signal declarations
  --
  -------------------------------------------------------------------
  signal control0 : std_logic_vector(35 downto 0);
  signal control1 : std_logic_vector(35 downto 0);

  signal trig0 : std_logic_vector(31 downto 0);
  signal trig1 : std_logic_vector(31 downto 0);

  signal timeout_counter     : std_logic_vector(8 downto 0);
  signal timeout_ready       : std_logic;
  signal lb_reading_reg      : std_logic;
  signal ctrl_fifo1_wadv_reg : std_logic;

  signal ddr_debug_state : std_logic_vector(7 downto 0);

  attribute syn_black_box         : boolean;
  attribute syn_black_box of icon : component is true;
  attribute syn_noprune           : boolean;
  attribute syn_noprune of icon   : component is true;
  attribute syn_black_box of ila  : component is true;
  attribute syn_noprune of ila    : component is true;


  signal sneak_wadv, sneak_radv, sneak_nfull, sneak_empty : std_logic;
  signal sneak_wd, sneak_rd                               : std_logic_vector(64+25-1 downto 0);

  signal flush_reg : std_logic_vector(7 downto 0);

  signal ds_xfer_reg : std_logic;
  signal eob         : std_logic;

  signal ld_o_expected : std_logic_vector(7 downto 0);
  signal ld_o_nomatch : std_logic;
  signal ld_o_nomatch_sclk : std_logic;
  
begin  -- rtl

  -- Map signals to USER DRAM Port
  dram_d       <= dram_out.d;
  dram_a       <= dram_out.a(27 downto 0);
  dram_r       <= dram_out.r;
  dram_w       <= dram_out.w;
  dram_req     <= dram_out.req;
  dram_in.q    <= dram_q;
  dram_in.qv   <= dram_v;
  dram_in.gnt  <= dram_gnt;
  dram_in.full <= dram_busy_reg;

  dbr : process (sysclk, rst)
  begin  -- process dbr
    if rst = '1' then                         -- asynchronous reset 
      dram_busy_reg <= '0';
    elsif sysclk'event and sysclk = '1' then  -- rising clock edge
      dram_busy_reg <= nfull or sneak_nfull;
    end if;
  end process dbr;

  -- Arbitration Process
  shmem_rgmanger_0 : xlreqgrantmanager_ad
    port map (
      hw_req     => dram_req,
      sw_req     => lb_request,
      hw_grant   => dram_gnt,
      sw_grant   => lb_grant,
      ram_active => ram_active,
      clk        => lclk
      );



  -- User Application, directly connected to SDRAM interface
  
  dram_v <= qv and not lb_active;
  dram_q <= q;



  -- Async FIFO Interface to Local Bus
  ctrl_fifo1 : async_fifo1
    generic map (
      width => 31)
    port map (
      wclk    => lclk,
      rst     => rst,
      wadv    => ctrl_fifo1_wadv,
      wdata   => ctrl_fifo1_wdata,
      wnfull  => ctrl_fifo1_wnfull,
      rclk    => sysclk,
      radv    => ctrl_fifo1_radv,
      rdw_out => ctrl_fifo1_rdata,
      rempty  => ctrl_fifo1_empty,
      rnempty => ctrl_fifo1_nempty);

  process (sysclk)
  begin  -- process
    if sysclk'event and sysclk = '1' then  -- rising clock edge
      ctrl_fifo1_empty_q  <= ctrl_fifo1_empty or (ctrl_fifo1_nempty and ctrl_fifo1_radv);
      write_fifo1_empty_q <= write_fifo1_empty or (write_fifo1_nempty and write_fifo1_radv);
    end if;
  end process;

  process (lclk)
  begin  -- process
    if lclk'event and lclk = '1' then   -- rising clock edge
      ctrl_fifo1_wdata <= lads & ((lblast and ds_xfer)) & lwrite & la_q;
      ctrl_fifo1_wadv  <= (lads or ((lblast and ds_xfer)) or (lwrite and ds_xfer)) and not dram_gnt;
    end if;
  end process;



  ctrl_fifo1_radv <= lads_ddr or lblast_ddr or
                     (lwrite_ddr and lb_writing and not nfull_reg and not write_fifo1_empty_q);
  
  lb_addr_ddr <= ctrl_fifo1_rdata(27 downto 0);
  lads_ddr    <= ctrl_fifo1_rdata(30) and not ctrl_fifo1_empty_q and not lads_ignore;
  lblast_ddr  <= ctrl_fifo1_rdata(29) and not ctrl_fifo1_empty_q;
  lwrite_ddr  <= ctrl_fifo1_rdata(28) and not ctrl_fifo1_empty_q;

  -- Reset read FIFOs on LADS or BLAST
  -- Hold Reset for 15 cycles on BLAST
  rst_fifos_p0 : process (sysclk, rst)
  begin  -- process rst_fifos_p0
    if rst = '1' then                   -- asynchronous reset (active low)
      rst_fifo_count    <= "000010";
      rst_fifos         <= '1';
      ready_sig180      <= '0';
      last_ready_sig180 <= '0';

    elsif sysclk'event and sysclk = '1' then  -- rising clock edge
      ready_sig180      <= ready_sig;
      last_ready_sig180 <= ready_sig180;

      if (lblast_ddr = '1' and lb_reading_burst = '1') or (ready_sig180 = '0' and last_ready_sig180 = '1') then
        rst_fifo_count <= "001111";
--      elsif rst_fifo_count = "000001" and (data_active = '1' or ctrl_active = '1') then
--        rst_fifo_count <= "000001";
--        flush <= '1';
      elsif OR_reduce(rst_fifo_count) = '1' then
        rst_fifo_count <= rst_fifo_count-1;
      end if;
      rst_fifos <= OR_reduce(rst_fifo_count);
    end if;
  end process rst_fifos_p0;

  flush <= OR_reduce(flush_reg(3 downto 0));

  write_fifo1 : async_fifo1
    generic map (
      width => 64)
    port map (
      wclk    => lclk,
      rst     => rst,
      wadv    => write_fifo1_wadv,
      wdata   => ld_i,
      wnfull  => write_fifo1_wnfull,
      rclk    => sysclk,
      radv    => write_fifo1_radv,
      rdw_out => ld_i_ddr,
      rempty  => write_fifo1_empty,
      rnempty => write_fifo1_nempty);

  write_fifo1_wadv <= ds_xfer and lwrite;

  -- Extra SYNC FIFO in the read path to capture data
  -- read after the async fifo goes nearly full
  read_fifo2 : wrapper_sync_fifo
    generic map (
      width => 64)
    port map (
      clk     => sysclk,
      rst     => rst_fifos,
      wadv    => lb_valid,
      wdata   => q,
      wnfull  => read_fifo2_nfull,
      wfull   => open,
      radv    => read_fifo2_radv,
      rdata   => open,
      rdw_out => read_fifo2_data,
      rempty  => read_fifo2_empty,
      rnempty => open);

  read_fifo2_radv <= not read_fifo2_empty and not read_fifo1_nfull and not rst_fifos;

  read_fifo1 : async_fifo1
    generic map (
      width => 64)
    port map (
      wclk    => sysclk,
      rst     => rst_fifos,
      wadv    => read_fifo2_radv,
      wdata   => read_fifo2_data,
      wnfull  => read_fifo1_nfull,
      wfull   => read_fifo1_full,
      rclk    => lclk,
      radv    => read_fifo1_radv,
      rdw_out => read_fifo1_rdw_out,
      rempty  => read_fifo1_empty,
      rnempty => read_fifo1_nempty);

  lb_valid <= qv and lb_active;


  ready  <= ready_sig or ((write_ready or (lwrite and lads)) and not ctrl_fifo1_wnfull) or timeout_ready;
  stop_i <= (ready_sig and read_fifo1_nempty) or ctrl_fifo1_wnfull or write_fifo1_wnfull;
  stop   <= stop_i;
  online <= online_i;


  read_fifo1_radv <= ((ds_xfer or pre_ds_xfer) and not lwrite) or (not ld_o_reg_full and not read_fifo1_empty);
  --ld_o            <= read_fifo1_rdw_out when ds_xfer = '1' else ld_o_reg;
  ld_o            <= ld_o_reg;

  gen_ready : process (lclk, rst)
  begin  -- process gen_reday_stop
    if rst_fifos = '1' then
      ready_sig           <= '0';
      ld_o_reg_full       <= '0';
      ld_o_reg            <= (others => '0');
      timeout_counter     <= (others => '0');
      ctrl_fifo1_wadv_reg <= '0';
      timeout_ready       <= '0';
      lb_reading_reg      <= '0';
      pre_ds_xfer         <= '0';
      ready_sig_reg       <= '0';
      lblast_reg          <= '0';
      rdfifo_empty_pipe   <= (others => '1');
      rst_fifos_lclk      <= '1';
      ld_o_expected <= (others => '0');
      ld_o_nomatch <= '0';
    elsif lclk'event and lclk = '1' then  -- rising clock edge
      rst_fifos_lclk <= rst_fifos;
      if rst_fifos_lclk = '1' then
        ready_sig           <= '0';
        ld_o_reg_full       <= '0';
        ld_o_reg            <= (others => '0');
        timeout_counter     <= (others => '0');
        ctrl_fifo1_wadv_reg <= '0';
        timeout_ready       <= '0';
        lb_reading_reg      <= '0';
        pre_ds_xfer         <= '0';
        ready_sig_reg       <= '0';
        lblast_reg          <= '0';
        rdfifo_empty_pipe   <= (others => '1');
      else
        rdfifo_empty_pipe   <= rdfifo_empty_pipe(4 downto 0) & read_fifo1_empty;
        lblast_reg          <= lblast and ds_xfer;
        lb_reading_reg      <= lb_reading_burst;
        ctrl_fifo1_wadv_reg <= ctrl_fifo1_wadv;
        timeout_ready       <= (AND_reduce(timeout_counter(8 downto 1)) and not timeout_counter(0)) or not online_i;
        if lb_reading_reg = '1' then
          if rdfifo_empty_pipe(5) = '0' and read_fifo1_empty = '0' and read_fifo1_nempty = '0' and ld_o_reg_full = '1' then
            ready_sig <= '1';
          end if;
          if lblast_reg = '1' then
            ready_sig <= '0';
          end if;
        else
          ready_sig <= '0';
        end if;
        if lads = '1' and lwrite = '0' then
          timeout_counter <= (others => '0');
        elsif lblast_reg = '1' or eob = '1' then
          timeout_counter <= (others => '1');
        else
          if AND_reduce(timeout_counter) = '0' then
            timeout_counter <= timeout_counter+1;
          end if;
        end if;
        ld_o_nomatch <= '0';
        ready_sig_reg <= ready_sig;
        pre_ds_xfer   <= ready_sig and not ready_sig_reg;

        if read_fifo1_empty = '0' and ld_o_reg_full = '0' then
          ld_o_reg_full <= '1';
          ld_o_reg      <= read_fifo1_rdw_out;
          ld_o_expected  <= ld_o_expected +2;
          if read_fifo1_rdw_out = ld_o_expected then
            ld_o_nomatch <= '0';
          else
            ld_o_nomatch <= '1';
          end if;
        else
          if (ds_xfer = '1' or pre_ds_xfer = '1') and lwrite = '0' then
            ld_o_reg <= read_fifo1_rdw_out;
            ld_o_expected <= ld_o_expected +2;
            if read_fifo1_rdw_out = ld_o_expected then
              ld_o_nomatch <= '0';
            else
              ld_o_nomatch <= '1';
            end if;
          end if;
          if lb_reading_burst = '0' then
            ld_o_reg_full <= '0';
          end if;
        end if;
      end if;
    end if;
  end process gen_ready;

  gen_write_ready : process (lclk, rst)
  begin  -- process gen_write_ready
    if rst = '1' then                     -- asynchronous reset (active low)
      write_ready <= '0';
      lads_reg    <= '0';
      ds_xfer_reg <= '0';
      eob         <= '0';
    elsif lclk'event and lclk = '1' then  -- rising clock edge
      if lads_reg = '1' and lwrite = '1' then
        write_ready <= '1';
      elsif (lblast = '1' and lwrite = '1' and ds_xfer = '1') or (eob = '1') then
        write_ready <= '0';
      elsif lads_reg = '1' and lwrite = '0' then
        write_ready <= '0';
      elsif lw_reg1 = '1' and lw_reg2 = '0' then
        write_ready <= '0';
      end if;
      lads_reg    <= lads;
      lw_reg1     <= lw_reg2;
      lw_reg2     <= lb_writing;
      ds_xfer_reg <= ds_xfer;
      eob         <= stop_i;
    end if;
  end process gen_write_ready;


  --eob <= ds_xfer_reg and ds_xfer and (not lblast) and lb_writing;


  --
  -- Process for starting and stopping read and write bursts from the
  -- local bus or system generator module
  --
  burst_ctrl : process (sysclk, rst)
    variable lb_addr_t1, lb_addr_t2, lb_addr_t4, lb_addr_t8, lb_addr_t16 : std_logic_vector(27 downto 0);
  begin  -- process burst_ctrl
    if rst = '1' then
      lb_reading     <= '0';
      lb_writing     <= '0';
      lb_active      <= '1';
      prefetch_count <= (others => '0');

      lb_r             <= '0';
      lb_addr          <= (others => '0');
      lb_addr_reg      <= (others => '0');
      lb_rskip_reg     <= (others => '0');
      lb_roffset_reg   <= (others => '0');
      lb_r1            <= '0';
      lb_addr1         <= (others => '0');
      lb_r2            <= '0';
      lb_addr2         <= (others => '0');
      lb_r3            <= '0';
      lb_addr3         <= (others => '0');
      lads_ignore      <= '0';
      lb_reading_burst <= '0';
      dram_wait_count  <= (others => '0');
      flush_reg        <= (others => '0');
    elsif sysclk'event and sysclk = '1' then  -- rising clock edge
      nfull_reg             <= nfull;
      lb_active             <= not dram_gnt;  -- Clock arbitartion bit in DDR_CLK domain
      lb_rskip_reg          <= lb_rskip;
      lb_roffset_reg        <= lb_roffset;
      flush_reg(7 downto 1) <= flush_reg(6 downto 0);
      if lb_active = '1' then
        -- DRAM controlled by Local Bus
        if lb_reading = '0' and lb_writing = '0' then
          if lads_ddr = '1' then
            lb_reading     <= not lwrite_ddr;
            lb_writing     <= lwrite_ddr;
            prefetch_count <= (others => '0');
            lb_addr        <= lb_addr_ddr;
            lb_addr3       <= lb_addr_ddr;
            lads_ignore    <= '1';
          else
            lads_ignore <= rst_fifos;
          end if;

          lb_r             <= '0';
          lb_r1            <= '0';
          lb_r2            <= '0';
          lb_r3            <= '0';
          lb_reading_burst <= '0';
          dram_wait_count  <= (others => '0');
          flush_reg(0)     <= '0';
        else
          if lb_writing = '1' then
            -- lbwriting = '1'             
            if lb_w = '1' then
              lb_addr  <= lb_addr+1;
              lb_addr3 <= lb_addr3+1;
            end if;

            if lblast_ddr = '1' then
              lb_writing <= '0';
            end if;
            lb_reading_burst <= '0';
            flush_reg(0)     <= '0';
          else
            -- lb_reading = '1'

            
            if dram_empty = '1' then
              -- Don't start pre-fetch until DRAM controller is empty
              lb_reading_burst <= '1';
            else
              dram_wait_count <= dram_wait_count+1;
            end if;

            if lblast_ddr = '1' or (ready_sig = '1' and read_fifo1_nempty = '1') then
              lb_reading_burst <= '0';
              lb_reading       <= '0';
              flush_reg(0)     <= '1';
              lb_r             <= '0';
              lb_r1            <= '0';
              lb_r2            <= '0';
              lb_r3            <= '0';
            elsif read_fifo2_nfull = '1' or read_fifo1_nfull = '1' then
              lb_r  <= '0';
              lb_r1 <= lb_r;
              lb_r2 <= lb_r1;
              lb_r3 <= lb_r2;
            else
              if (prefetch_count(5) = '0') and (nfull_reg = '0') and lb_reading_burst = '1' then
                lb_r <= '1';
              else
                lb_r <= '0';
              end if;
              lb_r1 <= lb_r;
              lb_r2 <= lb_r1;
              lb_r3 <= lb_r2;
            end if;
            if lb_r = '1' and qv = '0' then
              prefetch_count <= prefetch_count+1;
            elsif qv = '1' and lb_r = '0' then
              prefetch_count <= prefetch_count-1;
            end if;
            if lb_r = '1' then
              lb_addr <= lb_addr+1;
            end if;

            lb_addr_reg <= lb_addr;
            -- Multiply lb_addr by 5 bit lb_rskip
            if lb_rskip_reg(0) = '1' then
              lb_addr_t1 := lb_addr;
            else
              lb_addr_t1 := (others => '0');
            end if;
            if lb_rskip_reg(1) = '1' then
              lb_addr_t2 := lb_addr(26 downto 0) & '0';
            else
              lb_addr_t2 := (others => '0');
            end if;
            if lb_rskip_reg(2) = '1' then
              lb_addr_t4 := lb_addr(25 downto 0) & "00";
            else
              lb_addr_t4 := (others => '0');
            end if;
            if lb_rskip_reg(3) = '1' then
              lb_addr_t8 := lb_addr_reg(24 downto 0) & "000";
            else
              lb_addr_t8 := (others => '0');
            end if;
            if lb_rskip_reg(4) = '1' then
              lb_addr_t16 := lb_addr_reg(23 downto 0) & "0000";
            else
              lb_addr_t16 := (others => '0');
            end if;
            lb_addr1 <= lb_addr_t1+ lb_addr_t2+ lb_addr_t4;
            lb_addr2 <= lb_addr1 + lb_addr_t8+ lb_addr_t16;
            lb_addr3 <= lb_addr2+EXT(lb_roffset_reg, 28);
          end if;
        end if;
      else
        lb_r  <= '0';
        lb_r1 <= '0';
        lb_r2 <= '0';
        lb_r3 <= '0';
      end if;
    end if;
  end process burst_ctrl;

  write_fifo1_radv <= not write_fifo1_empty_q and not nfull_reg and lwrite_ddr and lb_writing;
  lb_w             <= not write_fifo1_empty_q and not nfull_reg and lb_writing and lwrite_ddr;
  lb_data          <= ld_i_ddr;

  dm <= (others => '0');
  -- register memory inputs : possible because RAM has nfull flag
  reg_mem_inputs0 : process (sysclk)
  begin  -- process reg_mem_inputs0
    if sysclk'event and sysclk = '1' then  -- rising clock edge
      if lb_active = '1' then
        if lb_r3 = '1' or lb_w = '1' or flush = '1' then
          a <= lb_addr3(24 downto 0) & "000";
          r <= lb_r3 and online_i;
          d <= lb_data;
          w <= lb_w and online_i;
        else
          r <= '0';
          a <= sneak_rd(64+24 downto 64) & "000";
          d <= sneak_rd(63 downto 0);
          w <= not sneak_empty and not nfull and not lb_reading;
        end if;
        sneak_wadv <= dram_w;
        
      else
        sneak_wadv <= '0';
        a          <= dram_a(24 downto 0) & "000";
        r          <= dram_r and online_i;
        d          <= dram_d;
        w          <= dram_w and online_i;
      end if;
      sneak_wd <= dram_a(24 downto 0) & dram_d;
    end if;
  end process reg_mem_inputs0;

  r1 <= r or flush_reg(0);


  -- FIFO to allow writes to be posted by the FPGA,
  -- even if lb_active = '1'
  sneak_write_fifo : sync_fifo_bram
    generic map (
      width => 64+25)
    port map (
      clk     => sysclk,
      rst     => rst,
      wadv    => sneak_wadv,
      wdata   => sneak_wd,
      wnfull  => sneak_nfull,
      wfull   => open,
      radv    => sneak_radv,
      rdata   => open,
      rdw_out => sneak_rd,
      rempty  => sneak_empty,
      rnempty => open);

  sneak_radv <= lb_active and not (lb_r3 or lb_w or sneak_empty or nfull or lb_reading or flush);



  -- DDR II SDRAM interface
  --
  -- Instantiate the memory controllers
  --
  ddr2_cntl0 : ddr2_ad_wrap_small
    port map(
      clk              => sysclk,
      flush            => flush_reg(0),
      w                => w,
      r                => r1,
      a                => a,
      d                => d,
      dm               => dm,
      q                => q,
      qv               => qv,
      rd_en            => rd_ready,
      rd_ready         => rd_ready,
      full             => nfull,
      empty            => dram_empty,
      error            => error_i,
      cntrl_DDR2_DQ    => DDR2_DQ,
      cntrl_DDR2_A     => DDR2_A,
      cntrl_DDR2_BA    => DDR2_BA,
      cntrl_DDR2_RAS_N => DDR2_RAS_N,
      cntrl_DDR2_CAS_N => DDR2_CAS_N,
      cntrl_DDR2_WE_N  => DDR2_WE_N,
      cntrl_DDR2_CS_N  => DDR2_CS_N,
      cntrl_DDR2_ODT   => DDR2_ODT,
      cntrl_DDR2_CKE   => DDR2_CKE,
      cntrl_DDR2_DM    => DDR2_DM,
      cntrl_DDR2_DQS   => DDR2_DQS,
      cntrl_DDR2_DQS_N => DDR2_DQS_N,
      cntrl_DDR2_CK    => DDR2_CK,
      cntrl_DDR2_CK_N  => DDR2_CK_N,
      CNTL_CLK         => clk_0,
      CNTL_CLK90       => clk_90,
      CNTL_CLK_ID1     => CNTL_CLK_ID1,
      CNTL_CLK_ID2     => CNTL_CLK_ID2,
      CNTL_CLK_ID3     => CNTL_CLK_ID3,
      CNTL_CLK_ID4     => CNTL_CLK_ID4,
      idelay_ctrl_rdy  => idelay_ctrl_rdy,
      SYS_RST          => SYS_RST,
      SYS_RST_90       => SYS_RST90,
      SYS_RST_ID       => SYS_RST_ID,
      control1         => X"000000000",
      control2         => X"000000000",
      status           => status);

  online_i <= not error_i;

  cscope0 : if chipscope generate

    process (sysclk)
    begin  -- process
      if sysclk'event and sysclk = '1' then  -- rising clock edge
        ld_o_nomatch_sclk <= ld_o_nomatch;
      end if;
    end process;
    

    trig0(7 downto 0)   <= lbterm & write_ready & timeout_ready & ready_sig & lwrite & ds_xfer & lblast & lads;
    trig0(15 downto 8)  <= la_q(7 downto 0);
    trig0(31 downto 24) <= ld_o_reg(7 downto 0);

    trig0(23 downto 16) <= EXT(ld_o_nomatch & ctrl_fifo1_wadv & stop_i & ready_sig & read_fifo1_nempty & ctrl_fifo1_wnfull & write_fifo1_wnfull, 8);

    trig1(7 downto 0) <= ctrl_fifo1_empty_q & dram_empty & lb_reading_burst & lb_reading
                         & sneak_radv & lwrite_ddr & lblast_ddr & lads_ddr;

    trig1(15 downto 8) <= qv & ld_o_nomatch_sclk & ctrl_fifo1_radv & lads_ignore & r1 & r & w & flush;

    trig1(23 downto 16) <= a(10 downto 3);
    trig1(31 downto 24) <= q(7 downto 0);  --d(7 downto 0);

    i_ila : ila
      port map
      (
        control => control0,
        clk     => lclk,
        data    => trig0,
        trig0   => trig0
        );
    i_ila2 : ila
      port map
      (
        control => control1,
        clk     => sysclk,
        data    => trig1,
        trig0   => trig1
        );
    i_icon : icon
      port map
      (
        control0 => control0,
        control1 => control1
        );

    process (sysclk)
    begin  -- process
      if sysclk'event and sysclk = '1' then  -- rising clock edge
        debug <= trig1 & trig0;
      end if;
    end process;
    
    
  end generate cscope0;

  
  
end rtl;
