flote21
Advanced Member level 1
- Joined
- Jan 22, 2014
- Messages
- 411
- Helped
- 1
- Reputation
- 2
- Reaction score
- 3
- Trophy points
- 1,298
- 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:
Reading from DDR2
DDR2 Accesses W/R controller:
Thanks anyway!
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!