DMA_DATA_IN : in std_logic_vector(31 downto 0);
DMA_LENGTH_WR_IN : in std_logic;
+ --23-0: Buffer size in 32 Bit words
DMA_ADDR_WR_IN : in std_logic;
DMA_CONTROL_IN : in std_logic_vector(31 downto 0); --0x702 write
--0: activate
--1: buffer full - waiting for reactivation
--31..8: data length in 32bit words
DMA_CONFIG_IN : in std_logic_vector(31 downto 0); --0x703
- --7..0 max burst size
+ --9..0 max burst size
API_RUNNING_IN : in std_logic;
API_DATA_IN : in std_logic_vector(15 downto 0);
RX_DWEN_IN : in std_logic;
RX_DATA_IN : in std_logic_vector(63 downto 0);
+ DEBUG_FIFO_DATA_OUT : out std_logic_vector(63 downto 0);
+ DEBUG_FIFO_EMPTY_OUT : out std_logic_vector(1 downto 0);
+ DEBUG_FIFO_READ_IN : in std_logic_vector(1 downto 0);
+
STATUS_REG_OUT : out std_logic_vector(159 downto 0);
DEBUG_OUT : out std_logic_vector(31 downto 0)
signal reset_i : std_logic;
- signal credit_available_np : std_logic := '0';
- signal credit_available_p : std_logic := '0';
+-- signal credit_available_np : std_logic := '0';
+-- signal credit_available_p : std_logic := '0';
signal tx_wr_en : std_logic := '0';
signal tx_rd_en : std_logic := '0';
type copy_state_t is (IDLE, RUNNING, LAST_WORD, BUFFER_FULL_WAIT, WAIT_ONE, WAIT_BUFFER);
signal copy_state : copy_state_t;
- signal copy_length : unsigned(11 downto 0) := (others => '0');
+ signal copy_length : unsigned(9 downto 0) := (others => '0');
signal current_address : unsigned(31 downto 0) := (others => '0');
signal buf_API_READ_OUT : std_logic := '0';
signal finished_sys : std_logic := '0';
signal busy : std_logic := '0';
- signal tx_req_i : std_logic;
- signal tx_end_i : std_logic;
- signal tx_st_i : std_logic;
+ signal tx_req_i : std_logic := '0';
+ signal tx_end_i : std_logic := '0';
+ signal tx_st_i : std_logic := '0';
signal send_state_bits : std_logic_vector(3 downto 0);
signal copy_state_bits : std_logic_vector(1 downto 0);
signal total_length : unsigned(23 downto 0) := (others => '0');
- signal current_buffer : unsigned(23 downto 0) := (others => '0');
signal tx_fifo_padding : std_logic_vector(3 downto 0) := (others => '0');
signal api_running_rising : std_logic;
signal api_running_falling : std_logic;
- signal api_starts : std_logic;
signal last_api_running : std_logic;
signal buf_TX_DATA_OUT : std_logic_vector(63 downto 0) := (others => '0');
signal buffer_full_strobe : std_logic;
signal buffer_full : std_logic;
- signal current_burst_length : unsigned(11 downto 0);
+ signal current_burst_length : unsigned(9 downto 0) := (others => '0');
signal buffer_space_available : std_logic;
- signal buffer_space_end : unsigned(31 downto 0);
- signal buffer_space_afull : unsigned(31 downto 0);
-
- signal credits_sys : std_logic_vector(12 downto 0);
-
+ signal buffer_length : unsigned(23 downto 0) := (others => '0');
+ signal credits_sys : std_logic_vector(12 downto 0) := (others => '0');
+
signal rden_dma_fifo : std_logic := '0';
signal reset_dma_fifo : std_logic := '0';
signal empty_addr_fifo : std_logic := '0';
signal empty_length_fifo : std_logic := '0';
- signal next_dma_length_i : std_logic_vector(31 downto 0);
- signal next_dma_start_address_i : std_logic_vector(31 downto 0);
- signal dma_length_i : std_logic_vector(31 downto 0);
- signal dma_start_address_i : std_logic_vector(31 downto 0);
+ signal next_dma_length_i : std_logic_vector(31 downto 0) := (others => '0');
+ signal next_dma_start_address_i : std_logic_vector(31 downto 0) := (others => '0');
+ signal dma_length_i : std_logic_vector(31 downto 0) := (others => '0');
+ signal dma_start_address_i : std_logic_vector(31 downto 0) := (others => '0');
signal new_buffer_available : std_logic := '0';
- signal dma_fifo_state : std_logic_vector(3 downto 0);
+ signal dma_fifo_state : std_logic_vector(3 downto 0) := (others => '0');
type dma_state_t is (INACTIVE, ACTIVE, WAIT_1, WAIT_2, WAIT_3, ENABLE, WORKING, DMA_RESET);
signal current_dma_state : dma_state_t;
-
+
signal dummy : std_logic_vector(2 downto 0);
-
+
+ signal df_write_en : std_logic;
+ signal df_read_en : std_logic_vector(1 downto 0);
+ signal df_full : std_logic;
+ signal df_full_q : std_logic;
+ signal next_df_write_en : std_logic;
+
begin
if rising_edge(CLK_IN) then
rden_dma_fifo <= '0';
reset_dma_fifo <= '0';
- new_buffer_available <= '0';
+ new_buffer_available <= '0';
case current_dma_state is
when INACTIVE =>
DMA_STATUS_OUT(1) <= '0';
DMA_STATUS_OUT(1) <= '1';
current_dma_state <= INACTIVE;
end case;
-
+
if RESET_IN = '1' then
current_dma_state <= INACTIVE;
end if;
end if;
end if;
end process;
-
+
process(CLK_IN)
begin
if rising_edge(CLK_IN) then
dma_length_i <= next_dma_length_i;
dma_start_address_i <= next_dma_start_address_i;
-
+
end if;
end process;
-- Burst Length & Buffer Space calculation
-----------------------------------------------------------------------
PROC_BUFFER_SPACE : process(CLK_IN)
+ variable credit_sys_u : unsigned(23 downto 0);
+ variable max_burst_u : unsigned(23 downto 0);
+ variable current_burst_u : unsigned(23 downto 0);
+ variable space_left_u : unsigned(23 downto 0);
+ begin
+ credit_sys_u := "000000000" & unsigned(credits_sys(12 downto 0)) & "00";
+ max_burst_u := "00000000000000" & unsigned(DMA_CONFIG_IN(9 downto 0));
+ space_left_u := unsigned(dma_length_i(23 downto 0)) - buffer_length;
+ current_burst_u := max_burst_u;
- begin
- buffer_space_end <= unsigned(dma_start_address_i) + unsigned(dma_length_i(28 downto 0)) * to_unsigned(4,3);
- buffer_space_afull <= buffer_space_end - (unsigned(DMA_CONFIG_IN(11 downto 0)) * to_unsigned(4,20));
-
- --Enough space for full burst
- if rising_edge(CLK_IN) then
+ if rising_edge(CLK_IN) then
if (copy_state = IDLE or copy_state = LAST_WORD or copy_state = BUFFER_FULL_WAIT or copy_state = WAIT_BUFFER) then
if busy = '0' then
buffer_space_available <= '1';
- current_burst_length <= unsigned(DMA_CONFIG_IN(11 downto 0));
- elsif current_address < buffer_space_afull then
- if unsigned(DMA_CONFIG_IN(11 downto 0)) < unsigned(credits_sys(11 downto 0)) then
- current_burst_length <= unsigned(DMA_CONFIG_IN(11 downto 0));
- else
- current_burst_length <= unsigned(credits_sys(11 downto 0));
- end if;
- buffer_space_available <= '1';
- elsif current_address < buffer_space_end then
- if buffer_space_end(13 downto 2) - current_address(13 downto 2) < unsigned(credits_sys(11 downto 0)) then
- current_burst_length <= buffer_space_end(13 downto 2) - current_address(13 downto 2);
- else
- current_burst_length <= unsigned(credits_sys(11 downto 0));
+ current_burst_u := max_burst_u;
+ elsif unsigned(dma_length_i(23 downto 0)) > buffer_length then --space available
+ buffer_space_available <= '1';
+ if credit_sys_u < max_burst_u then --less credits than max burst
+ if space_left_u >= credit_sys_u then --more space than credits
+ current_burst_u := credit_sys_u;
+ else --less space than credits
+ current_burst_u := space_left_u;
+ end if;
+ else --more credits than max burst
+ if space_left_u >= max_burst_u then --more space than credits
+ current_burst_u := max_burst_u;
+ else --less space than credits
+ current_burst_u := space_left_u;
+ end if;
end if;
- buffer_space_available <= '1';
- else
- buffer_space_available <= '0';
+ else -- no space
+ buffer_space_available <= '0';
+ current_burst_u := (others => '0');
end if;
+ current_burst_length <= current_burst_u(9 downto 0);
end if;
end if;
end process;
tx_length_wr_en <= '0';
copy_state <= IDLE;
buf_API_READ_OUT <= '0';
- copy_length <= (others => '0'); --length counter while copying
+ copy_length <= (others => '0'); --length counter while copying for current burst
buffer_full_strobe <= '0';
- total_length <= (others => '0');
+ buffer_length <= (others => '0'); --length of data written to current buffer
+ total_length <= (others => '0'); --total length of transfer
else
tx_wr_en <= '0';
tx_length_wr_en <= '0';
copy_state_bits <= "00";
if new_buffer_available = '1' then
current_address <= unsigned(dma_start_address_i);
+ buffer_length <= (others => '0');
end if;
- if busy = '1' and (API_RUNNING_IN = '1' or API_DATAREADY_IN = '1') and tx_almost_full = '0' then --DMA enable and API running
+ if busy = '1' and (API_RUNNING_IN = '1' or API_DATAREADY_IN = '1') and tx_almost_full = '0' and tx_length_almost_full = '0' then
+
if buffer_space_available = '1' then --Enough space in buffer for one burst
--- current_address + unsigned(DMA_CONFIG_IN(7 downto 0)) * to_unsigned(4,32)
--- < unsigned(DMA_START_ADDR_IN) + unsigned(DMA_LENGTH_IN) * to_unsigned(4,32) then
- tx_data_in( 7 downto 0) <= std_logic_vector(current_address(31 downto 24));
- tx_data_in(15 downto 8) <= std_logic_vector(current_address(23 downto 16));
- tx_data_in(23 downto 16) <= std_logic_vector(current_address(15 downto 8));
- tx_data_in(31 downto 24) <= std_logic_vector(current_address( 7 downto 0));
- tx_data_in(35 downto 32) <= x"0";
- buf_API_READ_OUT <= '1';
- copy_length <= (0 => '1', others => '0');
- copy_state <= RUNNING;
- tx_wr_en <= '1';
- tx_fifo_padding <= x"8";
+ if current_burst_length /= 0 then
+ tx_data_in( 7 downto 0) <= std_logic_vector(current_address(31 downto 24));
+ tx_data_in(15 downto 8) <= std_logic_vector(current_address(23 downto 16));
+ tx_data_in(23 downto 16) <= std_logic_vector(current_address(15 downto 8));
+ tx_data_in(31 downto 24) <= std_logic_vector(current_address( 7 downto 0));
+ tx_data_in(35 downto 32) <= x"0";
+ buf_API_READ_OUT <= '1';
+ copy_length <= (0 => '1', others => '0');
+ copy_state <= RUNNING;
+ tx_wr_en <= '1';
+ tx_fifo_padding <= x"8";
+ end if;
else
buffer_full_strobe <= '1';
copy_state <= BUFFER_FULL_WAIT;
when RUNNING =>
copy_state_bits <= "01";
if API_DATAREADY_IN = '1' then
- tx_data_in <= x"0" & "00000001000000"
+ tx_data_in <= x"0" & "000000" & API_RUNNING_IN & "1000000"
& API_PACKET_NUM_IN(2) & API_PACKET_NUM_IN(0) & API_DATA_IN(15 downto 0);
tx_wr_en <= '1';
- copy_length <= copy_length + to_unsigned(1,7);
+ copy_length <= copy_length + to_unsigned(1,10);
total_length <= total_length + to_unsigned(1,1);
+ buffer_length <= buffer_length + to_unsigned(1,1);
current_address <= current_address + to_unsigned(4,32);
-- if copy_length = unsigned(DMA_CONFIG_IN(6 downto 0)) - to_unsigned(1,1) then
-- buf_API_READ_OUT <= '0';
copy_state_bits <= "11";
if new_buffer_available = '1' then
copy_state <= WAIT_BUFFER;
- current_address <= unsigned(dma_start_address_i);
+ buffer_length <= (others => '0');
+ current_address <= unsigned(dma_start_address_i);
end if;
-
+
when WAIT_BUFFER =>
copy_state <= IDLE;
end case;
end if;
end process;
- tx_length_data_in <= last_words & "000" & std_logic_vector(copy_length-to_unsigned(1,12));
+ tx_length_data_in <= last_words & "00000" & std_logic_vector(copy_length(9 downto 0)-to_unsigned(1,10));
when SEND_CREDIT_WAIT =>
send_state_bits <= x"1";
- if tx_length_data_out(11 downto 0) = "0000000" then --no data
+ if tx_length_data_out(9 downto 0) = "0000000000" then --no data
finished <= tx_length_data_out(15);
send_state <= SEND_IDLE;
- elsif (TX_CA_PH_IN(8) = '1' or (unsigned(TX_CA_PH_IN(7 downto 0)) > to_unsigned(1,8)))
- and ((TX_CA_PD_IN(12 downto 8) /= "00000") or (unsigned(TX_CA_PD_IN(11 downto 0)) >= unsigned(tx_length_data_out(11 downto 0))))
+ elsif (TX_CA_PH_IN(8) = '1' or (unsigned(TX_CA_PH_IN(7 downto 0)) >= to_unsigned(1,8)))
+ and ((TX_CA_PD_IN(12 downto 8) /= "00000")
+ or (unsigned(TX_CA_PD_IN(7 downto 0)) > unsigned(tx_length_data_out(9 downto 2)))
+ or (unsigned(TX_CA_PD_IN(7 downto 0)) = unsigned(tx_length_data_out(9 downto 2)) and tx_length_data_out(1 downto 0) = "00"))
then
tx_st_i <= '0';
tx_end_i <= '0';
x"FF"; --Byte Enables
tx_rd_en <= '1'; --
tx_req_i <= '1';
- tx_length <= unsigned(tx_length_data_out(11 downto 0));
+ tx_length <= "00" & unsigned(tx_length_data_out(9 downto 0));
send_state <= SEND_START;
end if;
if TX_RDY_IN = '1' then
if TX_VAL_IN = '1' then
tx_st_i <= '1';
- if tx_length > to_unsigned(1,3) then
+ if tx_length > to_unsigned(1,12) then
tx_rd_en <= '1';
end if;
- tx_length <= tx_length - to_unsigned(1,1);
+ tx_length <= tx_length - to_unsigned(1,12);
send_state <= SEND_DATA; --SEND_FIRST;
tx_req_i <= '0';
end if;
--sync credits to sys clock
THE_Credit_FIFO : fifo_16x512_dualclock
port map (
- Data => "000" & TX_CA_PD_IN(12 downto 0),
+ Data(15 downto 13)=> "000",
+ Data(12 downto 0) => TX_CA_PD_IN(12 downto 0),
WrClock => CLK_125_IN,
RdClock => CLK_IN,
WrEn => '1',
end if;
end process;
+-----------------------------------------------------------------------
+-- RX Path
+-----------------------------------------------------------------------
+THE_DEBUG_FIFO_1 : fifo_dc_32x1024
+ port map(
+ Data => buf_TX_DATA_OUT(31 downto 0),
+ WrClock => CLK_125_IN,
+ RdClock => CLK_IN,
+ WrEn => df_write_en,
+ RdEn => df_read_en(0),
+ Reset => RESET_IN,
+ RPReset => RESET_IN,
+ Q => DEBUG_FIFO_DATA_OUT(31 downto 0),
+ Empty => DEBUG_FIFO_EMPTY_OUT(0),
+ Full => open,
+ AlmostEmpty => open,
+ AlmostFull => df_full
+ );
+THE_DEBUG_FIFO_2 : fifo_dc_32x1024
+ port map(
+ Data => buf_TX_DATA_OUT(63 downto 32),
+ WrClock => CLK_125_IN,
+ RdClock => CLK_IN,
+ WrEn => df_write_en,
+ RdEn => df_read_en(1),
+ Reset => RESET_IN,
+ RPReset => RESET_IN,
+ Q => DEBUG_FIFO_DATA_OUT(63 downto 32),
+ Empty => DEBUG_FIFO_EMPTY_OUT(1),
+ Full => open,
+ AlmostEmpty => open,
+ AlmostFull => open
+ );
+
+process(CLK_125_IN)
+ begin
+ if rising_edge(CLK_125_IN) then
+ if tx_st_i = '1' then
+ next_df_write_en <= '1';
+ elsif tx_end_i = '1' or send_state = SEND_IDLE then
+ next_df_write_en <= '0';
+ end if;
+ end if;
+ end process;
+
+df_write_en <= next_df_write_en or tx_st_i;
+df_read_en(0) <= df_full_q or DEBUG_FIFO_READ_IN(0);
+df_read_en(1) <= df_full_q or DEBUG_FIFO_READ_IN(1);
+
+THE_DF_FIFO_SYNC : signal_sync
+ generic map(
+ WIDTH => 1, --
+ DEPTH => 2
+ )
+ port map(
+ RESET => RESET_IN,
+ CLK0 => CLK_IN,
+ CLK1 => CLK_IN,
+ D_IN(0) => df_full,
+ D_OUT(0) => df_full_q
+ );
+
-----------------------------------------------------------------------
-- RX Path
STATUS_REG_OUT(13) <= tx_length_empty;
STATUS_REG_OUT(14) <= tx_almost_full;
STATUS_REG_OUT(15) <= tx_end_i;
-STATUS_REG_OUT(27 downto 16) <= std_logic_vector(copy_length);
-STATUS_REG_OUT(28) <= buffer_full;
-STATUS_REG_OUT(31 downto 29) <= (others => '0');
+STATUS_REG_OUT(25 downto 16) <= std_logic_vector(copy_length);
+STATUS_REG_OUT(26) <= buffer_full;
+STATUS_REG_OUT(31 downto 27) <= (others => '0');
STATUS_REG_OUT(40 downto 32) <= TX_CA_PH_IN;
STATUS_REG_OUT(53 downto 41) <= credits_sys(12 downto 0); --TX_CA_PD_IN;
STATUS_REG_OUT(62 downto 54) <= TX_CA_NPH_IN;
STATUS_REG_OUT(63) <= '0';
-STATUS_REG_OUT(95 downto 64) <= std_logic_vector(current_burst_length) & x"0" & tx_length_data_out;
+STATUS_REG_OUT(95 downto 64) <= "00" & std_logic_vector(current_burst_length) & x"0" & tx_length_data_out;
STATUS_REG_OUT(127 downto 96)<= std_logic_vector(current_address);
DEBUG_OUT(11 downto 10)<= dma_fifo_state(1 downto 0);
DEBUG_OUT(13 downto 12) <= copy_state_bits;
DEBUG_OUT(15 downto 14) <= send_state_bits(1 downto 0);
- DEBUG_OUT(23 downto 16) <= credits_sys(7 downto 0);
- DEBUG_OUT(31 downto 24) <= tx_length(7 downto 0);
+ DEBUG_OUT(28 downto 16) <= credits_sys(12 downto 0);
+ DEBUG_OUT(31 downto 29) <= "000";
end if;
end process;
-- else
-- tx_end_i <= '0';
-- end if;
+
+
+-- elsif current_address < buffer_space_afull then
+-- if unsigned(DMA_CONFIG_IN(11 downto 0)) < unsigned(credits_sys(11 downto 0)) then
+-- current_burst_length <= unsigned(DMA_CONFIG_IN(11 downto 0));
+-- else
+-- current_burst_length <= unsigned(credits_sys(11 downto 0));
+-- end if;
+-- buffer_space_available <= '1';
+-- elsif current_address < buffer_space_end then
+-- if buffer_space_end(13 downto 2) - current_address(13 downto 2) < unsigned(credits_sys(11 downto 0)) then
+-- current_burst_length <= buffer_space_end(13 downto 2) - current_address(13 downto 2);
+-- else
+-- current_burst_length <= unsigned(credits_sys(11 downto 0));
+-- end if;
+-- buffer_space_available <= '1';
+-- else
+-- buffer_space_available <= '0';
+-- end if;