Commit f6835b54 authored by Tristan Gingold's avatar Tristan Gingold

l2p_dma_master.vhd: do not cross 4KB page boundary

parent e6162cf4
......@@ -104,9 +104,9 @@ architecture arch of l2p_dma_master is
type wb_dma_state_type is (WB_IDLE, WB_SETUP, WB_DATA, WB_WAIT_ACK);
signal wb_dma_current_state : wb_dma_state_type := WB_IDLE;
signal dma_target_addr : unsigned(29 downto 0) := (others => '0');
signal dma_total_len : unsigned(29 downto 0) := (others => '0');
signal dma_packet_len : unsigned(5 downto 0) := (others => '0');
signal dma_target_addr : unsigned(31 downto 2) := (others => '0');
signal dma_total_len : unsigned(31 downto 2) := (others => '0');
signal dma_packet_len : unsigned(5 downto 0) := (others => '0'); -- In word
signal dma_host_addr : unsigned(63 downto 0) := (others => '0');
signal dma_byte_swap : std_logic_vector(1 downto 0) := (others => '0');
......@@ -114,6 +114,7 @@ architecture arch of l2p_dma_master is
alias dma_host_addr_l : unsigned(31 downto 0) is dma_host_addr(31 downto 0);
signal l2p_64b_address : std_logic := '0';
signal dma_size_page : unsigned(12 downto 2);
signal l2p_fsm_valid : std_logic := '0';
signal l2p_fsm_dframe : std_logic := '0';
......@@ -127,8 +128,6 @@ architecture arch of l2p_dma_master is
signal l2p_timeout_cnt : unsigned(12 downto 0) := (others => '0');
signal dma_last_packet : std_logic := '0';
signal wb_dma_cyc : std_logic := '0';
signal wb_dma_stb : std_logic := '0';
signal wb_dma_fsm_en : std_logic := '0';
......@@ -198,7 +197,6 @@ begin
when L2P_IDLE =>
wb_dma_fsm_en <= '0';
fsm_fifo_rst_n <= '0';
dma_last_packet <= '0';
if dma_ctrl_start_l2p_i = '1' then
dma_target_addr <= unsigned(dma_ctrl_target_addr_i(31 downto 2));
dma_host_addr_h <= unsigned(dma_ctrl_host_addr_h_i);
......@@ -222,16 +220,19 @@ begin
-- constant declaration).
if dma_total_len > c_L2P_MAX_PAYLOAD then
dma_packet_len <= to_unsigned(c_L2P_MAX_PAYLOAD, dma_packet_len'length);
dma_total_len <= dma_total_len - c_L2P_MAX_PAYLOAD;
dma_last_packet <= '0';
else
dma_packet_len <= dma_total_len(5 downto 0);
dma_total_len <= (others => '0');
dma_last_packet <= '1';
dma_packet_len <= dma_total_len(7 downto 2);
end if;
-- Compute the number of word remaining in the current host page.
dma_size_page <= ('0' & not dma_host_addr(11 downto 2)) + 1;
l2p_dma_current_state <= L2P_WAIT;
when L2P_WAIT =>
-- A PCI transfer cannot cross a 4-KB boundary
-- (See PCI Express Base Specification Revision 5.0 version 1.0 p 128)
if dma_packet_len > dma_size_page then
dma_packet_len <= dma_size_page(7 downto 2);
end if;
-- Send request to DMA arbiter
ldm_arb_req_o <= not ldm_arb_gnt_i;
-- Move to next state when:
......@@ -264,7 +265,7 @@ begin
l2p_fsm_data(19 downto 16) <= "1111";
-- Length field (in 32 bit words). When zero it means 1024 words.
l2p_fsm_data(9 downto 0) <= "0000" & std_logic_vector(dma_packet_len);
if (l2p_64b_address = '1') then
if l2p_64b_address = '1' then
l2p_dma_current_state <= L2P_ADDR_H;
else
l2p_dma_current_state <= L2P_ADDR_L;
......@@ -284,7 +285,8 @@ begin
-- Start readout here to get first data out on the next cycle.
data_fifo_rd <= '1';
-- Update host address (for the next transfer)
dma_host_addr <= dma_host_addr + 4*c_L2P_MAX_PAYLOAD;
dma_host_addr <= dma_host_addr + 4*dma_packet_len;
dma_total_len <= dma_total_len - dma_packet_len;
l2p_dma_current_state <= L2P_DATA;
when L2P_DATA =>
......@@ -302,7 +304,7 @@ begin
if dma_packet_len = 1 then
l2p_fsm_dframe <= '0';
data_fifo_rd <= '0';
if dma_last_packet = '0' then
if dma_total_len /= 0 then
l2p_dma_current_state <= L2P_SETUP;
else
l2p_dma_current_state <= L2P_IDLE;
......
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