Commit 4221b112 authored by Tristan Gingold's avatar Tristan Gingold

p2l_dma_master: allow transfer longer than 4096 bytes.

parent f6d26f73
......@@ -145,9 +145,8 @@ architecture arch of p2l_dma_master is
signal l2p_address_h : std_logic_vector(31 downto 0) := (others => '0');
signal l2p_address_l : std_logic_vector(31 downto 0) := (others => '0');
signal l2p_len_cnt : unsigned(29 downto 0) := (others => '0');
signal l2p_len_header : unsigned(9 downto 0) := (others => '0');
signal l2p_len_header : unsigned(10 downto 0);
signal l2p_64b_address : std_logic;
signal l2p_last_packet : std_logic;
signal pdm_arb_data : std_logic_vector(31 downto 0) := (others => '0');
......@@ -174,7 +173,7 @@ architecture arch of p2l_dma_master is
signal wb_dma_tfr : boolean;
-- P2L DMA read request FSM
type p2l_dma_state_type is (P2L_IDLE, P2L_HEADER, P2L_ADDR_H, P2L_ADDR_L, P2L_WAIT_READ_COMPLETION);
type p2l_dma_state_type is (P2L_IDLE, P2L_SETUP, P2L_HEADER, P2L_ADDR_H, P2L_ADDR_L, P2L_WAIT_READ_COMPLETION);
signal p2l_dma_current_state : p2l_dma_state_type;
signal p2l_data_cnt : unsigned(10 downto 0) := (others => '0');
......@@ -212,7 +211,6 @@ begin
rx_error_t <= '0';
l2p_64b_address <= '0';
is_next_item <= '0';
l2p_last_packet <= '0';
else
case p2l_dma_current_state is
......@@ -229,36 +227,31 @@ begin
l2p_address_h <= dma_ctrl_host_addr_h_i;
l2p_address_l <= dma_ctrl_host_addr_l_i;
l2p_len_cnt <= unsigned(dma_ctrl_len_i(31 downto 2)); -- dma_ctrl_len_i is in byte
if dma_ctrl_start_next_i = '1' then
-- Catching next DMA item
is_next_item <= '1'; -- flag for data retrieve block
else
-- P2L DMA transfer
is_next_item <= '0';
end if;
-- Catching whether this is a P2L DMA transfer or just a fetch of the next DMA item
is_next_item <= dma_ctrl_start_next_i;
if dma_ctrl_host_addr_h_i = X"00000000" then
l2p_64b_address <= '0';
else
l2p_64b_address <= '1';
end if;
-- request access to PCIe bus
pdm_arb_req_o <= '1';
-- prepare a packet, first the header
p2l_dma_current_state <= P2L_HEADER;
p2l_dma_current_state <= P2L_SETUP;
end if;
when P2L_HEADER =>
when P2L_SETUP =>
-- if DMA length is bigger than the max PCIe payload size,
-- we have to generate several read request
if l2p_len_cnt > c_MAX_READ_REQ_SIZE then
-- when max payload length is 1024, the header length field = 0
l2p_len_header <= c_MAX_READ_REQ_SIZE(9 downto 0);
l2p_last_packet <= '0';
l2p_len_header <= c_MAX_READ_REQ_SIZE;
else
l2p_len_header <= l2p_len_cnt(9 downto 0);
l2p_last_packet <= '1';
l2p_len_header <= l2p_len_cnt(10 downto 0);
end if;
-- request access to PCIe bus
pdm_arb_req_o <= '1';
p2l_dma_current_state <= P2L_HEADER;
when P2L_HEADER =>
if arb_pdm_gnt_i = '1' then
-- clear access request to the arbiter
-- access is granted until dframe is cleared
......@@ -277,7 +270,7 @@ begin
pdm_arb_data(15 downto 13) <= "111"; --> Reserved
pdm_arb_data(12) <= '0'; --> VC (Virtual Channel)
pdm_arb_data(11 downto 10) <= "01"; --> CID
pdm_arb_data(9 downto 0) <= std_logic_vector(l2p_len_header); --> Length (in 32-bit words)
pdm_arb_data(9 downto 0) <= std_logic_vector(l2p_len_header (9 downto 0)); --> Length (in words)
pdm_arb_valid_o <= '1';
pdm_arb_dframe_o <= '1';
if l2p_64b_address = '1' then
......@@ -296,35 +289,35 @@ begin
p2l_dma_current_state <= P2L_ADDR_L;
when P2L_ADDR_L =>
-- Subtract the number of word requested to generate a new read request if needed
if l2p_last_packet = '0' then
l2p_len_cnt <= l2p_len_cnt - c_MAX_READ_REQ_SIZE;
else
l2p_len_cnt <= (others => '0');
end if;
-- send host address 32 lowest bits
pdm_arb_data <= l2p_address_l;
-- clear dframe signal to indicate the end of packet
pdm_arb_dframe_o <= '0';
-- Subtract the number of word requested to generate a new read request if needed
l2p_len_cnt <= l2p_len_cnt - l2p_len_header;
l2p_address_l <= std_logic_vector(unsigned(l2p_address_l) + 4*l2p_len_header);
p2l_dma_current_state <= P2L_WAIT_READ_COMPLETION;
when P2L_WAIT_READ_COMPLETION =>
-- End of the read request packet
pdm_arb_valid_o <= '0';
if pd_pdm_data_valid_i = '1' and pd_pdm_master_cpld_i = '1' then
-- Received a word.
l2p_len_header <= l2p_len_header - 1;
end if;
if dma_ctrl_abort_i = '1' then
rx_error_t <= '1';
p2l_dma_current_state <= P2L_IDLE;
elsif (pd_pdm_master_cpld_i = '1' and pd_pdm_data_last_i = '1'
and p2l_data_cnt <= 1)
elsif pd_pdm_master_cpld_i = '1' and pd_pdm_data_last_i = '1'
and l2p_len_header = 1
then
-- Note: a read request may result in multiple read completion.
-- last word of read completion has been received
if l2p_last_packet = '0' then
if l2p_len_cnt /= 0 then
-- A new read request is needed, DMA size > max payload
p2l_dma_current_state <= P2L_HEADER;
-- As the end of packet is used to delimit arbitration phases
-- we have to ask again for permission
pdm_arb_req_o <= '1';
p2l_dma_current_state <= P2L_SETUP;
else
-- indicate end of DMA transfer
if is_next_item = '1' then
......@@ -378,14 +371,11 @@ begin
if rising_edge(clk_i) then
if p2l_dma_current_state = P2L_ADDR_L then
-- Store number of 32-bit data words to be received for the current read request
if l2p_len_header = 0 then
p2l_data_cnt <= to_unsigned(1024, p2l_data_cnt'length);
else
p2l_data_cnt <= '0' & l2p_len_header;
end if;
elsif (p2l_dma_current_state = P2L_WAIT_READ_COMPLETION
and pd_pdm_data_valid_i = '1'
and pd_pdm_master_cpld_i = '1') then
p2l_data_cnt <= l2p_len_header;
elsif p2l_dma_current_state = P2L_WAIT_READ_COMPLETION
and pd_pdm_data_valid_i = '1'
and pd_pdm_master_cpld_i = '1'
then
-- decrement number of data to be received
p2l_data_cnt <= p2l_data_cnt - 1;
end if;
......@@ -398,8 +388,8 @@ begin
p_next_item : process (clk_i)
begin
if rising_edge(clk_i) then
if (p2l_dma_current_state = P2L_WAIT_READ_COMPLETION
and is_next_item = '1' and pd_pdm_data_valid_i = '1')
if p2l_dma_current_state = P2L_WAIT_READ_COMPLETION
and is_next_item = '1' and pd_pdm_data_valid_i = '1'
then
-- next item data are supposed to be received in the right order !!
case p2l_data_cnt(2 downto 0) is
......@@ -438,7 +428,7 @@ begin
p_addr_cnt : process (clk_i)
begin
if rising_edge(clk_i) then
if (rst_n_i = '0') then
if rst_n_i = '0' then
dma_busy_error <= '0';
to_wb_fifo_wr <= '0';
to_wb_fifo_wr_d <= '0';
......@@ -446,8 +436,8 @@ begin
to_wb_fifo_din_d <= to_wb_fifo_din;
to_wb_fifo_wr_d <= to_wb_fifo_wr;
if (dma_ctrl_start_p2l_i = '1') then
if (p2l_dma_current_state = P2L_IDLE) then
if dma_ctrl_start_p2l_i = '1' then
if p2l_dma_current_state = P2L_IDLE then
-- dma_ctrl_target_addr_i is a byte address and target_addr_cnt is a
-- 32-bit word address
target_addr_cnt <= unsigned(dma_ctrl_carrier_addr_i(31 downto 2));
......@@ -456,15 +446,15 @@ begin
else
dma_busy_error <= '1';
end if;
elsif (p2l_dma_current_state = P2L_WAIT_READ_COMPLETION
and is_next_item = '0' and pd_pdm_data_valid_i = '1')
elsif p2l_dma_current_state = P2L_WAIT_READ_COMPLETION
and is_next_item = '0' and pd_pdm_data_valid_i = '1'
then
-- increment target address counter
target_addr_cnt <= target_addr_cnt + 1;
-- write target address and data to the sync fifo
to_wb_fifo_wr <= '1';
to_wb_fifo_din(31 downto 0) <= f_byte_swap(g_BYTE_SWAP, pd_pdm_data_i, to_wb_fifo_byte_swap);
to_wb_fifo_din(61 downto 32) <= std_logic_vector(target_addr_cnt);
-- increment target address counter
target_addr_cnt <= target_addr_cnt + 1;
else
dma_busy_error <= '0';
to_wb_fifo_wr <= '0';
......
......@@ -566,7 +566,7 @@ begin
);
-----------------------------------------------------------------------------
-- L2P DMA master
-- L2P DMA master (for board to host transfers)
-----------------------------------------------------------------------------
cmp_l2p_dma_master : entity work.l2p_dma_master
generic map (
......@@ -608,7 +608,7 @@ begin
l2p_dma_in.rty <= dma_rty_i;
-----------------------------------------------------------------------------
-- P2L DMA master
-- P2L DMA master (for host to board transfers)
-----------------------------------------------------------------------------
cmp_p2l_dma_master : entity work.p2l_dma_master
generic map (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment