Question about DDR2 ALTERA IP Controller

Status
Not open for further replies.

flote21

Advanced Member level 1
Joined
Jan 22, 2014
Messages
411
Helped
1
Reputation
2
Reaction score
3
Trophy points
1,298
Visit site
Activity points
5,595
Hello People,

I am trying to understand the VHDL code of a third-party to control a Micron DDR2 MT47H64M8 – 16 Meg. And after reading in the Datasheet, I can´t understand very well what is the meaning of Write Burst and Read Burst. What does it mean when it says: "The burst length determines the maximum number of column locations
that can be accessed for a given READ or WRITE command". DDR2 is not structured like a RAM? I have been searching in internet a good explanation about DDR2 controlling and working and I was not able to find anything good. Anyone can give me some advice?

On the other hand in the VHDL coding which is in charge to control the w/r accesses to the DDR2 I don`t know how to do a relation between the burst length and the burst vhdl signals. Here is the code:

Writting into DDR2:
Code:
use WORK.CEVISCAM_PACK.all;
library IEEE;
  use IEEE.std_logic_1164.all;
  use IEEE.numeric_std.all;

library ALTERA_MF;

----------------------------------
entity DMA_WRITE is
----------------------------------
  generic (   
    ADDR_BITS : positive range 20 to 32;     -- DMA Write Address Size
    DATA_BITS : positive range 32 to 64;     -- DMA Write Data Bus Size
    SIZE_BITS : positive range 1 to 16;      -- DMA Write Size Bits
--	 WR_SIZE   : positive range 1 to 64;      -- Write Burst Size for Memory Write Requests	 
    WR_WAIT   : natural  range 0 to 16 := 4  -- Wait Cycles between two Bursts
  );
  port (	 
    -- Source VIDEO RGB Input Flux (sync'ed on CLK)
    SRC_CLK     : in  std_logic;                                 -- Source Clock
    SRC_RST     : in  std_logic;                                 -- Source Reset (async active high)
    SRC_V       : in  std_logic;                                 -- Source New Image
    SRC_DARK    : in  std_logic;                                 -- Source Dark '1' / Bright '0'
    SRC_H       : in  std_logic;                                 -- Source New Line
    SRC_DAV     : in  std_logic;                                 -- Source New Data
    SRC_DATA    : in  std_logic_vector(63 downto 0);             -- Source Data
    SRC_XSIZE   : in  std_logic_vector(11 downto 0);             -- Source X Size
    SRC_YSIZE   : in  std_logic_vector(11 downto 0);             -- Source Y Size
	 -- Memory Image Info (sync'ed on DMA_CLK)
    MEM_INIT_OK : in  std_logic;                                 -- Memory Init Done
	 -- Misc
	 RAW_DATA      : in std_logic;                                -- Binning?
 	 WR_SIZE       : in positive range 1 to 64;                   -- Write Burst Size for Memory Write Requests	 
	 FPGA_MODE     : in  std_logic_vector(2 downto 0);            -- FPGA data processing modes    
	 FIFO_FUL_ERR  : out std_logic;                               -- Fifo Full Error (sync'ed on DMA_CLK)
    -- Avalon-MM Master Write Interface to Memory Controller (sync'ed on DMA_CLK)
    DMA_CLK     : in  std_logic;                                 -- DMA Clock
    DMA_RST     : in  std_logic;                                 -- DMA Reset active high (sync'ed on DMA_CLK)
    DMA_WRREADY : in  std_logic;                                 -- DMA Write Wait Request
    DMA_WRREQ   : out std_logic;                                 -- DMA Write Request
    DMA_WRBURST : out std_logic;                                 -- DMA Write Start of Burst
    DMA_WRSIZE  : out std_logic_vector(SIZE_BITS-1   downto 0);  -- DMA Write Request Size
    DMA_WRADDR  : out std_logic_vector(ADDR_BITS-1   downto 0);  -- DMA Write Address
    DMA_WRDATA  : out std_logic_vector(DATA_BITS-1   downto 0);  -- DMA Write Data
    DMA_WRBE    : out std_logic_vector(DATA_BITS/8-1 downto 0)   -- DMA Write Data Byte enable
  );
----------------------------------
end entity DMA_WRITE;
----------------------------------


---------------------------------------
architecture RTL of DMA_WRITE is
---------------------------------------

  component DCFIFO is
    generic (
      CLOCKS_ARE_SYNCHRONIZED : string;
      INTENDED_DEVICE_FAMILY  : string;
      LPM_NUMWORDS            : natural;
      LPM_SHOWAHEAD           : string;
      LPM_TYPE                : string;
      LPM_WIDTH               : natural;
      LPM_WIDTHU              : natural;
      OVERFLOW_CHECKING       : string;
      UNDERFLOW_CHECKING      : string;
      USE_EAB                 : string;
      WRSYNC_DELAYPIPE        : natural;
      RDSYNC_DELAYPIPE        : natural;
      READ_ACLR_SYNCH         : string;
      WRITE_ACLR_SYNCH        : string
    );
    port (
      ACLR    : in  std_logic ;
      WRCLK   : in  std_logic ;
      WRREQ   : in  std_logic ;
      DATA    : in  std_logic_vector(LPM_WIDTH-1 downto 0);
      WRFULL  : out std_logic ;
      WRUSEDW : out std_logic_vector(LPM_WIDTHU-1 downto 0);
      RDCLK   : in  std_logic ;
      RDREQ   : in  std_logic ;
      RDEMPTY : out std_logic ;
      Q       : out std_logic_vector(LPM_WIDTH-1 downto 0);
      RDUSEDW : out std_logic_vector(LPM_WIDTHU-1 downto 0)
    );
  end component DCFIFO;

  signal MEM_INIT_OKs  : std_logic;  
  signal MEM_INIT_OKss : std_logic;  
  
  signal SRC_V_rise   : std_logic;
  signal SRC_V_rise_r : std_logic;

  constant FIFO_DEPTH : positive := 8;  -- 2**FIFO_DEPTH words in the FIFO
--  constant FIFO_DEPTH : positive := 7;  -- 2**FIFO_DEPTH words in the FIFO
  constant FIFO_WIDTH : positive := DATA_BITS;
  signal FIFO_WR      : std_logic;
  signal FIFO_IN      : std_logic_vector(FIFO_WIDTH-1 downto 0);
  signal FIFO_FUL     : std_logic;
  signal FIFO_NB      : std_logic_vector(FIFO_DEPTH-1 downto 0);
  signal FIFO_EMP     : std_logic;
  signal FIFO_RD      : std_logic;
  signal FIFO_OUT     : std_logic_vector(FIFO_WIDTH-1 downto 0);
  signal FIFO_WRON    : std_logic;
    
--  signal DMA_ADDR_PIX : unsigned(SRC_XSIZE'length-1-2 downto 0);  -- -2 because we store 4pixels in one 64bits word
  signal DMA_ADDR_PIX : unsigned(SRC_XSIZE'length-1 downto 0);  
  signal DMA_ADDR_LIN : unsigned(SRC_YSIZE'length-1-2 downto 0); -- -2 because we have to store maximum 6 lines! FPGA_MODE_l = RGB_6R.
  signal DMA_ADDR_IMG : unsigned(ADDR_BITS-DMA_ADDR_LIN'length-DMA_ADDR_PIX'length-1 downto 0);
  signal DMA_WRREQi   : std_logic;
  signal DMA_CNT      : unsigned(DMA_WRSIZE'range);

  type DMA_WRFSM_t is ( s_WRITE1, s_WRITE2, s_WAIT );
  signal DMA_WRFSM : DMA_WRFSM_t;

  signal FPGA_MODEs     : std_logic_vector(FPGA_MODE'range);
  signal FPGA_MODE_l    : std_logic_vector(FPGA_MODE'range);    
  
  signal RAW_DATAs      : std_logic;
  signal RAW_DATAss     : std_logic;  
  
--------
begin
--------

  -- Resync MEM_INIT_OK on SRC_CLK
  MEM_INIT_OKs  <= MEM_INIT_OK  when rising_edge(SRC_CLK);
  MEM_INIT_OKss <= MEM_INIT_OKs when rising_edge(SRC_CLK);

  -- DMA Write Master FIFO
  -- Store 64bits Data in FIFO
  process(SRC_CLK, SRC_RST)
  begin
    if SRC_RST = '1' then
      FIFO_WRON <= '0';
    elsif rising_edge(SRC_CLK) then
      if SRC_V = '1' then
        FIFO_WRON <= MEM_INIT_OKss;  -- Latch MEM_INIT_OK for this frame !
      end if;
    end if;
  end process; 
  
  -- FIFO Write Side
  FIFO_WR <= SRC_DAV and FIFO_WRON;
  FIFO_IN <= SRC_DATA;  
  
  -- Clock Domain Crossing FIFO
  -- Show Ahead Mode, Output Registered
  -- Data Width 32 bits, Fifo Depth = 2**FIFO_DEPTH
  i_WRFIFO : DCFIFO
    generic map (                               
      CLOCKS_ARE_SYNCHRONIZED => "FALSE",       
      INTENDED_DEVICE_FAMILY  => "Cyclone V",   
      LPM_NUMWORDS            => 2**FIFO_DEPTH, 
      LPM_SHOWAHEAD           => "ON",          
      LPM_TYPE                => "dcfifo",      
      LPM_WIDTH               => FIFO_WIDTH,    
      LPM_WIDTHU              => FIFO_DEPTH,    
      OVERFLOW_CHECKING       => "ON",          
      UNDERFLOW_CHECKING      => "ON",          
      USE_EAB                 => "ON",          
      WRSYNC_DELAYPIPE        => 5,             
      RDSYNC_DELAYPIPE        => 5,             
      READ_ACLR_SYNCH         => "ON",         
      WRITE_ACLR_SYNCH        => "ON"          
    )                                           
    port map (                                  
      ACLR    => DMA_RST ,                     
      WRCLK   => SRC_CLK ,                     
      WRREQ   => FIFO_WR ,                     
      DATA    => FIFO_IN ,                     
      WRUSEDW => FIFO_NB ,  -- just for monitoring in simulation                     
      WRFULL  => FIFO_FUL,                     
      RDCLK   => DMA_CLK ,                     
      RDEMPTY => FIFO_EMP,                    
      RDREQ   => FIFO_RD ,                     
      Q       => FIFO_OUT,                      
      RDUSEDW => open     );       
      
  FIFO_RD     <= DMA_WRREADY and not FIFO_EMP when DMA_WRFSM = s_WRITE2 else '0';
  DMA_WRREQi  <= not FIFO_EMP and not SRC_V when DMA_WRFSM = s_WRITE2 else '0';
  DMA_WRREQ   <= DMA_WRREQi;
  DMA_WRBURST <= DMA_WRREQi when DMA_CNT = WR_SIZE else '0';  
  
  -- FIFO modelsim assertions.
  process(SRC_CLK)
  begin
    if rising_edge(SRC_CLK) then
      assert not ( FIFO_WR = '1' and FIFO_FUL = '1' )
      report "[DMA_WRITE] WRITE while FIFO Full !!!" severity failure;
    end if;
  end process;
  process(DMA_CLK)
  begin
    if rising_edge(DMA_CLK) then
      assert not ( FIFO_RD = '1' and FIFO_EMP = '1' )
      report "[DMA_WRITE] READ while FIFO Empty !!!" severity failure;
    end if;
  end process;
  
  -- FIFO Full Error Detection      
  process(SRC_CLK, DMA_RST)
  begin
    if DMA_RST = '1' then
      FIFO_FUL_ERR <= '0';
    elsif rising_edge(SRC_CLK) then
      if FIFO_FUL = '1' and FIFO_WR = '1' then
        FIFO_FUL_ERR <= '1';
      end if;
    end if;
  end process;


  -- ---------------------------------
  --  DMA Master Write Process
  -- ---------------------------------
  
  FPGA_MODEs <= FPGA_MODE when rising_edge(DMA_CLK);
  RAW_DATAs  <= RAW_DATA  when rising_edge(DMA_CLK);
  RAW_DATAss <= RAW_DATAs when rising_edge(DMA_CLK);
  
  process(DMA_CLK, DMA_RST)
  begin
    if DMA_RST = '1' then      
      DMA_CNT       <= to_unsigned(WR_SIZE, DMA_CNT'length); -- Important !!
      DMA_ADDR_LIN  <= (others => '0');
      DMA_ADDR_PIX  <= (others => '0');
		FPGA_MODE_l   <= (others => '0');
      DMA_WRFSM     <= s_WRITE1;
    elsif rising_edge(DMA_CLK) then
     
      case DMA_WRFSM is

        -- Make request when enough word are in FIFO
        when s_WRITE1 =>
            DMA_CNT <= to_unsigned(WR_SIZE, DMA_CNT'length);
            if FIFO_EMP = '0' and SRC_V = '0' then
					FPGA_MODE_l <= FPGA_MODEs;
              DMA_WRFSM   <= s_WRITE2;
            end if;

        when s_WRITE2 =>
            if DMA_CNT = 1 and FIFO_RD = '1' then
              DMA_ADDR_PIX <= DMA_ADDR_PIX + WR_SIZE;
				  if FPGA_MODE_l = RGB_6R then
					  if RAW_DATAss = '1' then 
						  if DMA_ADDR_PIX >= (unsigned(SRC_XSIZE)/4)-3   then  -- 64bits words = 4 pixels
							 DMA_ADDR_LIN <= DMA_ADDR_LIN + 1; 
							 DMA_ADDR_PIX <= (others => '0');
						  end if;					  
					  else 
						  if DMA_ADDR_PIX >= (unsigned(SRC_XSIZE)/2)-3 then  -- 64bits words = 2 pixels!
							 DMA_ADDR_LIN <= DMA_ADDR_LIN + 1; 
							 DMA_ADDR_PIX <= (others => '0');
						  end if;					  
					  end if;
				  end if;
				  --
              if WR_WAIT > 0 then
                DMA_CNT   <= to_unsigned(WR_WAIT, DMA_CNT'length);
                DMA_WRFSM <= s_WAIT;
              else				  
					  if FIFO_EMP = '0' and SRC_V = '0' then
							DMA_CNT   <= to_unsigned(WR_SIZE, DMA_CNT'length);
					  else
							DMA_CNT   <= to_unsigned(4, DMA_CNT'length);
							DMA_WRFSM <= s_WAIT;
					  end if;				  
              end if;
            elsif FIFO_RD = '1' then
              DMA_CNT <= DMA_CNT - 1;
            end if;

        -- Some time between two Write Requests
        when s_WAIT =>
            if DMA_CNT = 0 then
              DMA_CNT   <= to_unsigned(WR_SIZE, DMA_CNT'length);
              DMA_WRFSM <= s_WRITE1;
            else
              DMA_CNT <= DMA_CNT - 1;
            end if;

      end case;

      -- Clear things on New V flag      
      if SRC_V = '1' then -- in case 
        DMA_ADDR_LIN <= (others => '0');
        DMA_ADDR_PIX <= (others => '0');
        DMA_WRFSM    <= s_WRITE1;
      end if;
      
    end if;
  end process;
     
  -- DDR2 Image Buffer Address
  DMA_ADDR_IMG <= (others => not SRC_DARK); -- Dark Frame in Buffer 0, Bright in Buffer 1
  
  -- -----------------------
  --  DMA Write Outputs
  -- -----------------------
  DMA_WRSIZE <= std_logic_vector(to_unsigned(WR_SIZE, DMA_WRSIZE'length));
  DMA_WRADDR <= std_logic_vector(DMA_ADDR_IMG & DMA_ADDR_LIN & DMA_ADDR_PIX);
  DMA_WRDATA <= FIFO_OUT;
  DMA_WRBE   <= (others => '1');

--------------------------
end architecture RTL;

Reading from DDR2
Code:
 -- ---------------------------------
  --  DMA Master Read Process
  -- ---------------------------------
  -- This prepares the Data for DDS Processing
  -- This process is always computing with one line 
  -- in advance compared to the input video
  -- (vertical synchro is used to start preparing the 1st line)
  
  FPGA_MODEs <= FPGA_MODE   when rising_edge(DMA_CLK);
  RAW_DATAs  <=  RAW_DATA   when rising_edge(DMA_CLK);
  RAW_DATAss <=  RAW_DATAs  when rising_edge(DMA_CLK);
  
  process(DMA_CLK, DMA_RST)
  begin
    if DMA_RST = '1' then 
      FIFO_CLR     <= '0';
      DMA_RDREQ    <= '0';
      DMA_ADDR_PIX <= (others => '0');
      DMA_ADDR_LIN <= (others => '0');
		FPGA_MODE_l  <= (others => '0');	
      DMA_RDFSM    <= s_IDLE;
    elsif rising_edge(DMA_CLK) then

      FIFO_CLR     <= '0';
      
      case DMA_RDFSM is

        -- Wait for New Frame Flag to arrive here
        when s_IDLE =>
            DMA_RDREQ    <= '0';
            DMA_ADDR_PIX <= (others => '0');
            DMA_ADDR_LIN <= (others => '0');
            -- New Frame is arriving !
            if VIDEO_I_SOIsr = '1' and MEM_INIT_OK = '1' and ENABLEss = '1' then
              FIFO_CLR   <= '1';  -- to be sure we always restart from an empty fifo
              DMA_RDREQ  <= '1';
			  FPGA_MODE_l <= FPGA_MODEs;
              DMA_RDFSM  <= s_GET_LINE;
            end if;

        -- Common Routine : Make Read requests from Memory for a "Video Line"
        when s_GET_LINE =>
            DMA_RDREQ <= '1';
            if DMA_RDREADY = '1' then -- Read Accepted
              -- End of Reading this line ?				  
				  if FPGA_MODE_l = RGB_6R then
					  if RAW_DATAss = '1' then 
					     --if DMA_ADDR_PIX+RD_SIZE >= VIDEO_O_XSIZi/4 then  -- /4 because 64bits words = 4 pixels
						  if DMA_ADDR_PIX >= VIDEO_O_XSIZi then
							 DMA_RDREQ    <= '0';
							 DMA_ADDR_PIX <= (others => '0');
							 DMA_ADDR_LIN <= DMA_ADDR_LIN + 1;
							 DMA_RDFSM    <= s_NEXT_LINE;
						  else
							 DMA_ADDR_PIX <= DMA_ADDR_PIX + RD_SIZE;
						  end if;				  					  
					  else
						  --if DMA_ADDR_PIX+RD_SIZE >= VIDEO_O_XSIZi/4 then  -- /4 because 64bits words = 4 pixels
						  if DMA_ADDR_PIX >= VIDEO_O_XSIZi then
							 DMA_RDREQ    <= '0';
							 DMA_ADDR_PIX <= (others => '0');
							 DMA_ADDR_LIN <= DMA_ADDR_LIN + 1;
							 DMA_RDFSM    <= s_NEXT_LINE;
						  else
							 DMA_ADDR_PIX <= DMA_ADDR_PIX + RD_SIZE;
						  end if;				  
					  end if;
				  end if;
            end if;

        -- Wait for next line
        when s_NEXT_LINE =>  
            if VIDEO_I_SOLs = '1' then   -- Next line
              if unsigned(VIDEO_I_YCNT) = unsigned(VIDEO_I_YSIZE)-1 then  -- Last line
                DMA_RDFSM <= s_IDLE;  -- no need to do anything : back to Idle
              else
                DMA_RDFSM <= s_WAIT_FIRST_PIX;
              end if;
            end if;

        -- Wait for 1st pixel of line, in order
        -- not to read too soon (FIFO could go FULL !)
        when s_WAIT_FIRST_PIX =>  
            if VIDEO_I_DAVs = '1' then   -- 1 pixel is here !
              DMA_RDREQ <= '1';
              DMA_RDFSM <= s_GET_LINE;
            end if;

      end case;
                  
      -- Clear FSM on End Of Image and Start of Image
      if VIDEO_I_EOIs = '1' or VIDEO_I_SOIs = '1' then 
        DMA_RDFSM <= s_IDLE;
      end if;
      
    end if;
  end process;


  -- -----------------------
  --  DMA Read Outputs
  -- -----------------------
  DMA_ADDR_IMG <= (others => '0'); -- always read in same frame buffer
  DMA_RDADDR   <= std_logic_vector(DMA_ADDR_IMG & DMA_ADDR_LIN & DMA_ADDR_PIX);
  DMA_RDSIZE   <= std_logic_vector(to_unsigned(RD_SIZE, DMA_RDSIZE'length));

                   
  -- -----------------------------------------------------
  --  FIFO to store Data before processing 
  -- -----------------------------------------------------
  FIFO_WR <= DMA_RDDAV ;
  FIFO_IN <= DMA_RDDATA;  
        
  -- FIFO Full Error Detection      
  process(DMA_CLK, DMA_RST)
  begin
    if DMA_RST = '1' then
      FIFO_FUL_ERR <= '0';
    elsif rising_edge(DMA_CLK) then
      if FIFO_FUL = '1' and FIFO_WR = '1' then
        FIFO_FUL_ERR <= '1';
      end if;
    end if;
  end process;
  
  process(DMA_CLK)
  begin
    if rising_edge(DMA_CLK) then
      assert not ( FIFO_WR = '1' and FIFO_FUL = '1' )
      report "[DDS_WRITE] WRITE while FIFO Full !!!" severity failure;
    end if;
  end process;
  
  -- FIFO Asynchronous Clear  
  FIFO_ACLR <= DMA_RST or FIFO_CLR;
      
  -- Clock Domain Crossing FIFO
  -- Show Ahead Mode, Output Registered
  i_RDFIFO : DCFIFO
    generic map (                               
      CLOCKS_ARE_SYNCHRONIZED => "FALSE",       
      INTENDED_DEVICE_FAMILY  => "Cyclone V",   
      LPM_NUMWORDS            => 2**FIFO_DEPTH, 
      LPM_SHOWAHEAD           => "ON",          
      LPM_TYPE                => "dcfifo",      
      LPM_WIDTH               => FIFO_WIDTH,    
      LPM_WIDTHU              => FIFO_DEPTH,    
      OVERFLOW_CHECKING       => "ON",          
      UNDERFLOW_CHECKING      => "ON",          
      USE_EAB                 => "ON",          
      WRSYNC_DELAYPIPE        => 3,             
      RDSYNC_DELAYPIPE        => 3,             
      READ_ACLR_SYNCH         => "ON",         
      WRITE_ACLR_SYNCH        => "ON"          
    )                                           
    port map (                                  
      ACLR    => FIFO_ACLR,                     
      WRCLK   => DMA_CLK  ,                     
      WRREQ   => FIFO_WR  ,                     
      DATA    => FIFO_IN  ,                     
      WRUSEDW => FIFO_WRNB,                     
      WRFULL  => FIFO_FUL ,                     
      RDCLK   => CLK      ,                     
      RDEMPTY => FIFO_EMP ,                    
      RDREQ   => FIFO_RD  ,                     
      Q       => FIFO_OUT ,                      
      RDUSEDW => open
    );
    
  -- Reading the FIFO when needed
  process(VIDEO_I_DAV, FIFO_EMP, VIDEO_O_FSM)
  begin
    FIFO_RD <= '0';
    if VIDEO_I_DAV = '1' and FIFO_EMP = '0' and VIDEO_O_FSM = s_COMPUTE_LINE then 
      FIFO_RD <= '1';
    end if;
  end process;
  
  -- Dark Value computed from Fifo Output
  DARK_DATA <= FIFO_OUT;

DDR2 Accesses W/R controller:
Code:
library IEEE;
  use IEEE.std_logic_1164.all;
  use IEEE.numeric_std.all;
         
library ALTERA_MF;
  
-------------------------------
entity AVALON_ARBITER4 is
-------------------------------
  generic (
     ADDR_BITS : positive := 22;
     DATA_BITS : positive := 32;
     SIZE_BITS : positive :=  5
  );
  port (
    --  General Inputs
    DMA_CLK      : in  std_logic;                                  -- DMA Clock (half rate)
    DMA_RST      : in  std_logic;                                  -- DMA Asynchronous Reset Active High
    -- Avalon-MM Master 0 - Write Only   
    DMA0_READY   : out std_logic;                                  -- DMA0 Ready
    DMA0_WRITE   : in  std_logic;                                  -- DMA0 Write   Request
    DMA0_WRBURST : in  std_logic;                                  -- DMA0 Write   Request Start of Burst
    DMA0_ADDR    : in  std_logic_vector(ADDR_BITS  -1 downto 0);   -- DMA0 Address Request
    DMA0_SIZE    : in  std_logic_vector(SIZE_BITS  -1 downto 0);   -- DMA0 Size    Request
    DMA0_WRDATA  : in  std_logic_vector(DATA_BITS  -1 downto 0);   -- DMA0 Write Data
    DMA0_WRBE    : in  std_logic_vector(DATA_BITS/8-1 downto 0);   -- DMA0 Write Byte Enable
    -- Avalon-MM Master 1 - Write Only  
    DMA1_READY   : out std_logic;                                  -- DMA1 Ready
    DMA1_WRITE   : in  std_logic;                                  -- DMA1 Write   Request
    DMA1_WRBURST : in  std_logic;                                  -- DMA1 Write   Request Start of Burst
    DMA1_ADDR    : in  std_logic_vector(ADDR_BITS  -1 downto 0);   -- DMA1 Address Request
    DMA1_SIZE    : in  std_logic_vector(SIZE_BITS  -1 downto 0);   -- DMA1 Size    Request
    DMA1_WRDATA  : in  std_logic_vector(DATA_BITS  -1 downto 0);   -- DMA1 Write Data
    DMA1_WRBE    : in  std_logic_vector(DATA_BITS/8-1 downto 0);   -- DMA1 Write Byte Enable
    -- Avalon-MM Master 2 - Read Only   
    DMA2_READY   : out std_logic;                                  -- DMA2 Ready
    DMA2_READ    : in  std_logic;                                  -- DMA2 Read    Request
    DMA2_ADDR    : in  std_logic_vector(ADDR_BITS  -1 downto 0);   -- DMA2 Address Request
    DMA2_SIZE    : in  std_logic_vector(SIZE_BITS  -1 downto 0);   -- DMA2 Size    Request
    DMA2_RDDAV   : out std_logic;                                  -- DMA2 Read Data Valid
    DMA2_RDDATA  : out std_logic_vector(DATA_BITS  -1 downto 0);   -- DMA2 Read Data
    -- Avalon-MM Master 3 - Read Only
    DMA3_READY   : out std_logic;                                  -- DMA3 Ready
    DMA3_READ    : in  std_logic;                                  -- DMA3 Read    Request
    DMA3_ADDR    : in  std_logic_vector(ADDR_BITS  -1 downto 0);   -- DMA3 Address Request
    DMA3_SIZE    : in  std_logic_vector(SIZE_BITS  -1 downto 0);   -- DMA3 Size    Request
    DMA3_RDDAV   : out std_logic;                                  -- DMA3 Read Data Valid
    DMA3_RDDATA  : out std_logic_vector(DATA_BITS  -1 downto 0);   -- DMA3 Read Data
    -- Avalon-MM Arbiter Output
    DMA_WRITE    : out std_logic;                                  -- DMA  Write   Request
    DMA_WRBURST  : out std_logic;                                  -- DMA  Write   Request Start of Burst
    DMA_READ     : out std_logic;                                  -- DMA  Read    Request
    DMA_ADDR     : out std_logic_vector(ADDR_BITS  -1 downto 0);   -- DMA  Address Request
    DMA_SIZE     : out std_logic_vector(SIZE_BITS  -1 downto 0);   -- DMA  Size    Request
    DMA_WRDATA   : out std_logic_vector(DATA_BITS  -1 downto 0);   -- DMA  Write Data
    DMA_WRBE     : out std_logic_vector(DATA_BITS/8-1 downto 0);   -- DMA  Write Byte Enable
    DMA_READY    : in  std_logic;                                  -- DMA  Ready
    DMA_RDDAV    : in  std_logic;                                  -- DMA  Read Data Valid
    DMA_RDDATA   : in  std_logic_vector(DATA_BITS  -1 downto 0)    -- DMA  Read Data

  );
-------------------------------
end entity AVALON_ARBITER4;
-------------------------------


-----------------------------------------
architecture RTL of AVALON_ARBITER4 is
-----------------------------------------

  -- --------------------------
  --  Altera Single Clock FIFO
  -- --------------------------
  component SCFIFO is
    generic (
      ADD_RAM_OUTPUT_REGISTER : string;
      INTENDED_DEVICE_FAMILY  : string;
      LPM_NUMWORDS            : natural;
      LPM_SHOWAHEAD           : string;
      LPM_TYPE                : string;
      LPM_WIDTH               : natural;
      LPM_WIDTHU              : natural;
      OVERFLOW_CHECKING       : string;
      UNDERFLOW_CHECKING      : string;
      USE_EAB                 : string
    );
    port (
      ACLR  : in  std_logic ;
      CLOCK : in  std_logic ;
      SCLR  : in  std_logic ;
      WRREQ : in  std_logic ;
      DATA  : in  std_logic_vector(LPM_WIDTH -1 downto 0);
      FULL  : out std_logic ;
      USEDW : out std_logic_vector(LPM_WIDTHU-1 downto 0);
      EMPTY : out std_logic ;
      RDREQ : in  std_logic ;
      Q     : out std_logic_vector(LPM_WIDTH -1 downto 0)
    );
  end component SCFIFO;
  
  
  type   ARBITER_FSM_t is (s_DMA0, s_DMA1, s_DMA2, s_DMA3);
  signal ARBITER_FSM   : ARBITER_FSM_t;
  --
  signal DMA0_READY_i  : std_logic;
  signal DMA1_READY_i  : std_logic;
  signal DMA2_READY_i  : std_logic;
  signal DMA3_READY_i  : std_logic;
  --
  signal DMA0_WRBURST_CNT : unsigned(DMA0_SIZE'range);
  signal DMA1_WRBURST_CNT : unsigned(DMA1_SIZE'range);

  -- FIFO Read Data Signals
  constant RDFIFO_DEPTH : positive := 6;
  constant RDFIFO_WSIZE : positive := SIZE_BITS+1;
  signal RDFIFO_WR      : std_logic;
  signal RDFIFO_WR2     : std_logic;
  signal RDFIFO_IN      : std_logic_vector(RDFIFO_WSIZE-1 downto 0);
  signal RDFIFO_FUL     : std_logic;
  signal RDFIFO_NB      : std_logic_vector(RDFIFO_DEPTH-1 downto 0);
  signal RDFIFO_EMP     : std_logic;
  signal RDFIFO_RD      : std_logic;
  signal RDFIFO_OUT     : std_logic_vector(RDFIFO_WSIZE-1 downto 0);

  signal DMA_READY_RD : std_logic;
  signal DMA2_RDREQ   : std_logic;
  signal DMA3_RDREQ   : std_logic;
  signal DMA2_RDDAVi  : std_logic;
  signal DMA3_RDDAVi  : std_logic;
  signal DMAs_WHO     : std_logic;
  signal DMAs_RDCNT   : unsigned(SIZE_BITS-1 downto 0);
  signal DMA_OUT_BUSY : std_logic;
  
-------
begin
-------


  -- Arbitration Stage between the four DMA Inputs
  -- Priorities are given by the DMA_PRIO bits
  -- if two DMAs have same priority, a round robbin is then made
  ARBITRATION : process(DMA_CLK, DMA_RST)
    variable DMA0_WRBURST_IPv : std_logic;
    variable DMA1_WRBURST_IPv : std_logic;
  begin
    if DMA_RST = '1' then
      DMA0_WRBURST_IPv := '0';
      DMA1_WRBURST_IPv := '0';
      DMA0_WRBURST_CNT <= (others => '0');
      DMA1_WRBURST_CNT <= (others => '0');
      ARBITER_FSM      <= s_DMA0;
    elsif rising_edge(DMA_CLK) then

      -- DMA0 Write Burst Management
      if DMA0_WRITE = '1' and DMA0_WRBURST = '1' then
        DMA0_WRBURST_CNT <= unsigned(DMA0_SIZE) - 1;
        if unsigned(DMA0_SIZE) > 1 then
          DMA0_WRBURST_IPv := '1';
        else
          DMA0_WRBURST_IPv := '0';
        end if;
        -- Assertion Check
        assert unsigned(DMA0_SIZE) >= 1 report "[AVALON_ARBITER4] DMA0_SIZE=" &
        integer'image(to_integer(unsigned(DMA0_SIZE))) & " < 1 !" severity failure;
      elsif DMA0_WRITE = '1' and DMA0_READY_i = '1' then
        if DMA0_WRBURST_CNT > 1 then                       
          DMA0_WRBURST_CNT <= DMA0_WRBURST_CNT - 1;
          DMA0_WRBURST_IPv := '1';			 
        else
          DMA0_WRBURST_IPv := '0';
        end if;
      end if;		

      -- DMA1 Write Burst Management
      if DMA1_WRITE = '1' and DMA1_WRBURST = '1' then
        DMA1_WRBURST_CNT <= unsigned(DMA1_SIZE) - 1;
        if unsigned(DMA1_SIZE) > 1 then
          DMA1_WRBURST_IPv := '1';
        else
          DMA1_WRBURST_IPv := '0';
        end if;
        -- Assertion Check
        assert unsigned(DMA1_SIZE) >= 1 report "[AVALON_ARBITER4] DMA1_SIZE=" &
        integer'image(to_integer(unsigned(DMA1_SIZE))) & " < 1 !" severity failure;
      elsif DMA1_WRITE = '1' and DMA1_READY_i = '1' then
        if DMA1_WRBURST_CNT > 1 then
          DMA1_WRBURST_CNT <= DMA1_WRBURST_CNT - 1;
          DMA1_WRBURST_IPv := '1';
        else
          DMA1_WRBURST_IPv := '0';
        end if;
      end if;

      -- Arbiter FSM
      case ARBITER_FSM is

        when s_DMA0 =>
          if (DMA_READY = '1') and (DMA0_WRBURST_IPv = '0') then  -- Ready and DMA0 has finished its access
            if (DMA1_WRITE = '1') then
              ARBITER_FSM <= s_DMA1;
            elsif (DMA2_READ = '1') then
              ARBITER_FSM <= s_DMA2;
            elsif (DMA3_READ = '1') then
              ARBITER_FSM <= s_DMA3;
            end if;
          end if;

        when s_DMA1 =>
          if (DMA_READY = '1') and (DMA1_WRBURST_IPv = '0') then  -- Ready and DMA1 has finished its access
            if (DMA2_READ = '1') then
              ARBITER_FSM <= s_DMA2;
            elsif (DMA3_READ = '1') then
              ARBITER_FSM <= s_DMA3;
            elsif (DMA0_WRITE = '1') then
              ARBITER_FSM <= s_DMA0;
            end if;
          end if;

        when s_DMA2 =>
          if (DMA_READY_RD = '1') then  -- Ready and DMA2 has finished its access
            if (DMA3_READ = '1') then
              ARBITER_FSM <= s_DMA3;
            elsif (DMA0_WRITE = '1') then
              ARBITER_FSM <= s_DMA0;
            elsif (DMA1_WRITE = '1') then
              ARBITER_FSM <= s_DMA1;
            end if;
          end if;

        when s_DMA3 =>
          if (DMA_READY_RD = '1') then  -- Ready and DMA3 has finished its access
            if (DMA0_WRITE = '1') then
              ARBITER_FSM <= s_DMA0;
            elsif (DMA1_WRITE = '1') then
              ARBITER_FSM <= s_DMA1;
            elsif (DMA2_READ = '1') then
              ARBITER_FSM <= s_DMA2;
            end if;
          end if;

      end case;

    end if;  -- rising edge
  end process ARBITRATION;

  --
  DMA0_READY    <= DMA0_READY_i;
  DMA1_READY    <= DMA1_READY_i;
  DMA2_READY    <= DMA2_READY_i;
  DMA3_READY    <= DMA3_READY_i;
  --
  DMA0_READY_i  <= DMA_READY    when (ARBITER_FSM = s_DMA0) else '0';
  DMA1_READY_i  <= DMA_READY    when (ARBITER_FSM = s_DMA1) else '0';
  DMA2_READY_i  <= DMA_READY_RD when (ARBITER_FSM = s_DMA2) else '0';
  DMA3_READY_i  <= DMA_READY_RD when (ARBITER_FSM = s_DMA3) else '0';

  DMA_READY_RD <= DMA_READY and not RDFIFO_FUL;
  --
  DMA_WRITE     <= DMA0_WRITE   when (ARBITER_FSM = s_DMA0) else
                   DMA1_WRITE   when (ARBITER_FSM = s_DMA1) else '0';
  --
  DMA_READ      <= DMA2_READ    when (ARBITER_FSM = s_DMA2) else
                   DMA3_READ    when (ARBITER_FSM = s_DMA3) else '0';
  --
  DMA_ADDR      <= DMA0_ADDR    when (ARBITER_FSM = s_DMA0) else
                   DMA1_ADDR    when (ARBITER_FSM = s_DMA1) else
                   DMA2_ADDR    when (ARBITER_FSM = s_DMA2) else
                   DMA3_ADDR    when (ARBITER_FSM = s_DMA3) else (others => '-');
  --
  DMA_SIZE      <= DMA0_SIZE    when (ARBITER_FSM = s_DMA0) else
                   DMA1_SIZE    when (ARBITER_FSM = s_DMA1) else
                   DMA2_SIZE    when (ARBITER_FSM = s_DMA2) else
                   DMA3_SIZE    when (ARBITER_FSM = s_DMA3) else (others => '-');
  --
  DMA_WRBURST   <= DMA0_WRBURST when (ARBITER_FSM = s_DMA0) else
                   DMA1_WRBURST when (ARBITER_FSM = s_DMA1) else '0';
  --
  DMA_WRDATA    <= DMA0_WRDATA  when (ARBITER_FSM = s_DMA0) else
                   DMA1_WRDATA  when (ARBITER_FSM = s_DMA1) else (others => '-');
  --
  DMA_WRBE      <= DMA0_WRBE    when (ARBITER_FSM = s_DMA0) else
                   DMA1_WRBE    when (ARBITER_FSM = s_DMA1) else (others => '-');



  -- ----------------------------
  --  DMAs Read Data Management
  -- ----------------------------
  process(DMA_CLK, DMA_RST)
  begin
    if DMA_RST = '1' then
      DMA2_RDREQ <= '0';
      DMA3_RDREQ <= '0';
    elsif rising_edge(DMA_CLK) then
      DMA2_RDREQ <= DMA2_READY_i and DMA2_READ;  -- DMA2 Read Request Accepted !
      DMA3_RDREQ <= DMA3_READY_i and DMA3_READ;  -- DMA3 Read Request Accepted !
      assert not ( DMA2_RDREQ = '1' and DMA3_RDREQ = '1' ) report "DMA2 and DMA3 both reading at the same time !" severity failure; 
--    assert not ( DMA2_RDREQ = '1' and DMA3_RDREQ = '1' ) report "DMA2 and DMA3 both reading at the same time !" severity error; 
    end if;
  end process;

  -- Store the Requests in FIFO 
  RDFIFO_WR <= DMA2_RDREQ or DMA3_RDREQ;
  RDFIFO_IN <= DMA2_SIZE & "0" when DMA2_RDREQ = '1' else
               DMA3_SIZE & "1";  
  
  -- Store in FIFO the Read Requests, to know
  -- to which DMA give the Read Data when they are arriving !
  RDFIFO_WR2 <= RDFIFO_WR and DMA_OUT_BUSY;
  --
  i_ARBITER_RD_FIFO : SCFIFO
    generic map (
      ADD_RAM_OUTPUT_REGISTER => "ON",
      INTENDED_DEVICE_FAMILY  => "Cyclone IV",
      LPM_NUMWORDS            => 2**RDFIFO_DEPTH,
      LPM_SHOWAHEAD           => "ON",
      LPM_TYPE                => "SCFIFO",
      LPM_WIDTH               => RDFIFO_WSIZE,
      LPM_WIDTHU              => RDFIFO_DEPTH,
      OVERFLOW_CHECKING       => "ON",
      UNDERFLOW_CHECKING      => "ON",
      USE_EAB                 => "ON"
    )
    port map (
      ACLR  => DMA_RST   ,
      CLOCK => DMA_CLK   ,
      SCLR  => '0'       ,
      WRREQ => RDFIFO_WR2,
      DATA  => RDFIFO_IN ,
      FULL  => RDFIFO_FUL,
      USEDW => RDFIFO_NB ,
      EMPTY => RDFIFO_EMP,
      RDREQ => RDFIFO_RD ,
      Q     => RDFIFO_OUT
    );
  

  -- FIFO assertions
  process
  begin
    wait until rising_edge(DMA_CLK);
    assert not (RDFIFO_RD = '1' and RDFIFO_EMP = '1')
      report "[AVALON_ARBITER4] Read in ARBITER READ FIFO Empty !" severity failure;
    assert not (RDFIFO_WR = '1' and RDFIFO_FUL = '1')
      report "[AVALON_ARBITER4] Write in ARBITER READ FIFO Full !" severity failure;
  end process;

  DMA_OUT_BUSY <= '1' when DMAs_RDCNT > 0 or RDFIFO_EMP = '0' else '0';
  
  -- Giving the Read Data to the one who requested them !
  process(DMA_CLK, DMA_RST)
  begin
    if DMA_RST = '1' then
      RDFIFO_RD   <= '0';
      DMAs_WHO    <= '0';
      DMA2_RDDAVi <= '0';
      DMA3_RDDAVi <= '0';
      DMA2_RDDATA <= (others => '0');
      DMA3_RDDATA <= (others => '0');
      DMAs_RDCNT  <= (others => '0');
    elsif rising_edge(DMA_CLK) then
      RDFIFO_RD   <= '0';
      DMA2_RDDAVi <= '0';
      DMA3_RDDAVi <= '0';
      DMA2_RDDATA <= DMA_RDDATA;
      DMA3_RDDATA <= DMA_RDDATA;
      if RDFIFO_WR = '1' and RDFIFO_EMP = '1' and DMAs_RDCNT = 0 then  -- New incoming Burst !
        DMAs_WHO   <= RDFIFO_IN(0);  -- Get the Who !
        DMAs_RDCNT <= unsigned(RDFIFO_IN(SIZE_BITS downto 1));  -- Get the Size !
      elsif RDFIFO_EMP = '0' and DMAs_RDCNT = 0 then  -- New incoming Burst !
        RDFIFO_RD  <= '1';
        DMAs_WHO   <= RDFIFO_OUT(0);  -- Get the Who !
        DMAs_RDCNT <= unsigned(RDFIFO_OUT(SIZE_BITS downto 1));  -- Get the Size !
      elsif DMA_RDDAV = '1' and DMAs_RDCNT > 0 then
        DMAs_RDCNT <= DMAs_RDCNT - 1;
        if DMAs_WHO = '0' then
          DMA2_RDDAVi <= '1';
        else
          DMA3_RDDAVi <= '1';
        end if;
        -- Another access already here ?        
        if RDFIFO_EMP = '0' and DMAs_RDCNT = 1 then
          RDFIFO_RD  <= '1';
          DMAs_WHO   <= RDFIFO_OUT(0);  -- Get the Who !
          DMAs_RDCNT <= unsigned(RDFIFO_OUT(SIZE_BITS downto 1));  -- Get the Size !
        end if;
      end if;
    end if;
  end process;
  
  DMA2_RDDAV <= DMA2_RDDAVi;
  DMA3_RDDAV <= DMA3_RDDAVi;


------------------------
end architecture RTL;
------------------------

Thanks anyway!
 

DDR2 uses bursts to improve the performance of memory accesses. The commands are pipelined in the device, but changing banks incurs latency which would otherwise result in dismal performance if you had to perform the precharging on each word accessed. Given that DDR2 memory is primary used to hold data which is inherently sequentially accessed the burst is a benefit as it allows you to get multiple words from the RAM without having to send each address. If you need completely random accesses to the memory then DDR2 and other Dynamic RAMs aren't the solution. That is why devices like Sync SRAM still exist in the marketplace.

This is why the memory architecture of a PC has Diskdrive: Slow (optimal performance with long sequential accesses), DDR# memory: Fast bursts (optimal performance when accessing sequential bursts in the same page), Cache (L1, L2): Very Fast random access (all accesses have maximum performance), but I digress.
 
Thank you very much for your comments.

then if I say in the DDR2 altera controller, WR_BURST=3 , it means that it is going to read from 3 banks at the same time? In the previous VHDL code, focusing in DMA_WRITE, the DDR2 is addressed like a normal RAM. I don#t understand how can affect the command WR_BURST in the data sotored in DDR2. I have doing some tests, and if WR_BURST=3 I can read from DDR2 (RD_WURST=3 also) without any problem the data previously saved. But when WR_BURST = other value, the AVALON_ARBITER4 leaves the flag DMA0_WRBURST_IPv := '1' always to this value and when I am trying to read, the AVALON_ARBITER4 never gives me the access to read...why is in this way?


 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…