From 74bc6aa7aff24ba0ffc9c469f74124927b89848c Mon Sep 17 00:00:00 2001 From: Timon Heim <timon.heim@cern.ch> Date: Fri, 5 Sep 2014 14:55:05 +0200 Subject: [PATCH] Changes l2p mechanic. --- hdl/gn4124core/rtl/l2p_dma_master.vhd | 1414 +++++++++++-------------- hdl/gn4124core/rtl/p2l_dma_master.vhd | 3 +- 2 files changed, 601 insertions(+), 816 deletions(-) diff --git a/hdl/gn4124core/rtl/l2p_dma_master.vhd b/hdl/gn4124core/rtl/l2p_dma_master.vhd index 31cb04a..020a29a 100644 --- a/hdl/gn4124core/rtl/l2p_dma_master.vhd +++ b/hdl/gn4124core/rtl/l2p_dma_master.vhd @@ -1,839 +1,623 @@ --------------------------------------------------------------------------------- --- -- --- CERN BE-CO-HT GN4124 core for PCIe FMC carrier -- --- http://www.ohwr.org/projects/gn4124-core -- --------------------------------------------------------------------------------- --- --- unit name: 32-bit DMA master (l2p_dma_master.vhd) --- --- authors: Simon Deprez (simon.deprez@cern.ch) --- Matthieu Cattin (matthieu.cattin@cern.ch) --- --- date: 31-08-2010 --- --- version: 1.0 --- --- description: Provides a pipelined Wishbone interface to performs DMA --- transfers from local application to PCI express host. --- --- dependencies: general-cores library (genrams package) --- --------------------------------------------------------------------------------- --- GNU LESSER GENERAL PUBLIC LICENSE --------------------------------------------------------------------------------- --- This source file is free software; you can redistribute it and/or modify it --- under the terms of the GNU Lesser General Public License as published by the --- Free Software Foundation; either version 2.1 of the License, or (at your --- option) any later version. This source is distributed in the hope that it --- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty --- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --- See the GNU Lesser General Public License for more details. You should have --- received a copy of the GNU Lesser General Public License along with this --- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html --------------------------------------------------------------------------------- --- last changes: 11-07-2011 (mcattin) Replaced Xilinx Coregen FIFOs with genrams --- library cores from ohwr.org --- 26.02.14 (theim) Fixed a racecondition where the statemachine could end up --- in a deadlock. Added a Setup state after Idle and fixed the --- counting of the l2p_data_cnt. --------------------------------------------------------------------------------- --- TODO: - byte enable support --------------------------------------------------------------------------------- +-- #################################### +-- # Project: Yarr +-- # Author: Timon Heim +-- # E-Mail: timon.heim at cern.ch +-- # Comments: Rewritten on basis from Matthieu Cattin, +-- # taken from the gn4124-core on ohwr.org +-- #################################### + library IEEE; use IEEE.STD_LOGIC_1164.all; +--use IEEE.STD_LOGIC_ARITH.all; use IEEE.NUMERIC_STD.all; + use work.gn4124_core_pkg.all; use work.genram_pkg.all; - entity l2p_dma_master is - generic ( - -- Enable byte swap module (if false, no swap) - g_BYTE_SWAP : boolean := false + generic ( + g_BYTE_SWAP : boolean := false + ); + port ( + -- GN4124 core clk and reset + clk_i : in std_logic; + rst_n_i : in std_logic; + + -- From the DMA controller + dma_ctrl_target_addr_i : in std_logic_vector(31 downto 0); + dma_ctrl_host_addr_h_i : in std_logic_vector(31 downto 0); + dma_ctrl_host_addr_l_i : in std_logic_vector(31 downto 0); + dma_ctrl_len_i : in std_logic_vector(31 downto 0); + dma_ctrl_start_l2p_i : in std_logic; + dma_ctrl_done_o : out std_logic; + dma_ctrl_error_o : out std_logic; + dma_ctrl_byte_swap_i : in std_logic_vector(1 downto 0); + dma_ctrl_abort_i : in std_logic; + + -- To the arbiter (L2P data) + ldm_arb_valid_o : out std_logic; + ldm_arb_dframe_o : out std_logic; + ldm_arb_data_o : out std_logic_vector(31 downto 0); + ldm_arb_req_o : out std_logic; + arb_ldm_gnt_i : in std_logic; + + + -- L2P channel control + l2p_edb_o : out std_logic; -- Asserted when transfer is aborted + l_wr_rdy_i : in std_logic_vector(1 downto 0); -- Asserted when GN4124 is ready to receive master write + l2p_rdy_i : in std_logic; -- De-asserted to pause transdert already in progress + tx_error_i : in std_logic; -- Asserted when unexpected or malformed paket received + + -- DMA Interface (Pipelined Wishbone) + l2p_dma_clk_i : in std_logic; + l2p_dma_adr_o : out std_logic_vector(31 downto 0); + l2p_dma_dat_i : in std_logic_vector(31 downto 0); + l2p_dma_dat_o : out std_logic_vector(31 downto 0); + l2p_dma_sel_o : out std_logic_vector(3 downto 0); + l2p_dma_cyc_o : out std_logic; + l2p_dma_stb_o : out std_logic; + l2p_dma_we_o : out std_logic; + l2p_dma_ack_i : in std_logic; + l2p_dma_stall_i : in std_logic; + p2l_dma_cyc_i : in std_logic -- P2L dma WB cycle for bus arbitration ); - port - ( - --------------------------------------------------------- - -- GN4124 core clock and reset - clk_i : in std_logic; - rst_n_i : in std_logic; - - --------------------------------------------------------- - -- From the DMA controller - dma_ctrl_target_addr_i : in std_logic_vector(31 downto 0); - dma_ctrl_host_addr_h_i : in std_logic_vector(31 downto 0); - dma_ctrl_host_addr_l_i : in std_logic_vector(31 downto 0); - dma_ctrl_len_i : in std_logic_vector(31 downto 0); - dma_ctrl_start_l2p_i : in std_logic; - dma_ctrl_done_o : out std_logic; - dma_ctrl_error_o : out std_logic; - dma_ctrl_byte_swap_i : in std_logic_vector(1 downto 0); - dma_ctrl_abort_i : in std_logic; - - --------------------------------------------------------- - -- To the arbiter (L2P data) - ldm_arb_valid_o : out std_logic; -- Read completion signals - ldm_arb_dframe_o : out std_logic; -- Toward the arbiter - ldm_arb_data_o : out std_logic_vector(31 downto 0); - ldm_arb_req_o : out std_logic; - arb_ldm_gnt_i : in std_logic; - - --------------------------------------------------------- - -- L2P channel control - l2p_edb_o : out std_logic; -- Asserted when transfer is aborted - l_wr_rdy_i : in std_logic_vector(1 downto 0); -- Asserted when GN4124 is ready to receive master write - l2p_rdy_i : in std_logic; -- De-asserted to pause transfer already in progress - tx_error_i : in std_logic; -- Asserted when unexpected or malformed packet recevied - - --------------------------------------------------------- - -- DMA Interface (Pipelined Wishbone) - l2p_dma_clk_i : in std_logic; -- Bus clock - l2p_dma_adr_o : out std_logic_vector(31 downto 0); -- Adress - l2p_dma_dat_i : in std_logic_vector(31 downto 0); -- Data in - l2p_dma_dat_o : out std_logic_vector(31 downto 0); -- Data out - l2p_dma_sel_o : out std_logic_vector(3 downto 0); -- Byte select - l2p_dma_cyc_o : out std_logic; -- Read or write cycle - l2p_dma_stb_o : out std_logic; -- Read or write strobe - l2p_dma_we_o : out std_logic; -- Write - l2p_dma_ack_i : in std_logic; -- Acknowledge - l2p_dma_stall_i : in std_logic; -- for pipelined Wishbone - p2l_dma_cyc_i : in std_logic -- P2L dma wb cycle (for bus arbitration) - ); end l2p_dma_master; - -architecture behaviour of l2p_dma_master is --- component generic_async_fifo is --- generic ( --- g_data_width : natural; --- g_size : natural; --- g_show_ahead : boolean := false; --- --- -- Read-side flag selection --- g_with_rd_empty : boolean := true; -- with empty flag --- g_with_rd_full : boolean := false; -- with full flag --- g_with_rd_almost_empty : boolean := false; --- g_with_rd_almost_full : boolean := false; --- g_with_rd_count : boolean := false; -- with words counter --- --- g_with_wr_empty : boolean := false; --- g_with_wr_full : boolean := true; --- g_with_wr_almost_empty : boolean := false; --- g_with_wr_almost_full : boolean := false; --- g_with_wr_count : boolean := false; --- --- g_almost_empty_threshold : integer; -- threshold for almost empty flag --- g_almost_full_threshold : integer -- threshold for almost full flag --- ); --- --- port ( --- rst_n_i : in std_logic := '1'; --- --- -- write port --- clk_wr_i : in std_logic; --- d_i : in std_logic_vector(g_data_width-1 downto 0); --- we_i : in std_logic; --- --- wr_empty_o : out std_logic; --- wr_full_o : out std_logic; --- wr_almost_empty_o : out std_logic; --- wr_almost_full_o : out std_logic; --- wr_count_o : out std_logic_vector(log2_ceil(g_size)-1 downto 0); --- --- -- read port --- clk_rd_i : in std_logic; --- q_o : out std_logic_vector(g_data_width-1 downto 0); --- rd_i : in std_logic; --- --- rd_empty_o : out std_logic; --- rd_full_o : out std_logic; --- rd_almost_empty_o : out std_logic; --- rd_almost_full_o : out std_logic; --- rd_count_o : out std_logic_vector(log2_ceil(g_size)-1 downto 0) --- ); --- end component generic_async_fifo; - ----------------------------------------------------------------------------- - -- Constants declaration - ----------------------------------------------------------------------------- - - -- c_L2P_MAX_PAYLOAD is the maximum size (in 32-bit words) of the payload of a packet. - -- Allowed c_L2P_MAX_PAYLOAD values are: 32, 64, 128, 256, 512, 1024. - -- This constant must be set according to the GN4124 and motherboard chipset capabilities. - constant c_L2P_MAX_PAYLOAD : unsigned(10 downto 0) := to_unsigned(32, 11); -- in 32-bit words - constant c_ADDR_FIFO_FULL_THRES : integer := 500; - constant c_DATA_FIFO_FULL_THRES : integer := 500; - - ----------------------------------------------------------------------------- - -- Signals declaration - ----------------------------------------------------------------------------- - - -- Target address counter - signal target_addr_cnt : unsigned(29 downto 0); - signal dma_length_cnt : unsigned(29 downto 0); - - -- Sync FIFOs - signal fifo_rst_n : std_logic; - signal addr_fifo_rd : std_logic; - signal addr_fifo_valid : std_logic; - signal addr_fifo_empty : std_logic; - signal addr_fifo_dout : std_logic_vector(31 downto 0); - signal addr_fifo_din : std_logic_vector(31 downto 0); - signal addr_fifo_wr : std_logic; - signal addr_fifo_full : std_logic; - - signal data_fifo_rd : std_logic; - signal data_fifo_valid : std_logic; - signal data_fifo_empty : std_logic; - signal data_fifo_dout : std_logic_vector(31 downto 0); - signal data_fifo_din : std_logic_vector(31 downto 0); - signal data_fifo_wr : std_logic; - signal data_fifo_full : std_logic; - - signal data_fifo_rd_cnt : unsigned(10 downto 0); - - signal data_fifo_valid_d : std_logic; - - -- Wishbone - signal wb_read_cnt : unsigned(31 downto 0); - signal wb_left_cnt : unsigned(31 downto 0); - signal wb_ack_cnt : unsigned(31 downto 0); - signal wb_timeout_cnt : unsigned(31 downto 0); - signal l2p_dma_cyc_t : std_logic; - signal l2p_dma_stb_t : std_logic; - - -- L2P DMA Master FSM - type l2p_dma_state_type is (L2P_IDLE, L2P_SETUP, L2P_WAIT_DATA, L2P_HEADER, L2P_ADDR_H, - L2P_ADDR_L, L2P_DATA, L2P_LAST_DATA, L2P_WAIT_RDY, L2P_ERROR); - signal l2p_dma_current_state : l2p_dma_state_type; - - -- L2P packet generator - signal s_l2p_header : std_logic_vector(31 downto 0); - - signal l2p_len_cnt : unsigned(29 downto 0); - signal l2p_address_h : unsigned(31 downto 0); - signal l2p_address_l : unsigned(31 downto 0); - signal l2p_data_cnt : unsigned(10 downto 0); - signal l2p_timeout_cnt : unsigned(31 downto 0); - signal l2p_64b_address : std_logic; - signal l2p_len_header : unsigned(9 downto 0); - signal l2p_byte_swap : std_logic_vector(1 downto 0); - signal l2p_last_packet : std_logic; - signal l2p_lbe_header : std_logic_vector(3 downto 0); - +architecture behavioral of l2p_dma_master is + --------------------- + -- Components + --------------------- + component l2p_fifo + port ( + rst : in std_logic; + wr_clk : in std_logic; + rd_clk : in std_logic; + din : in std_logic_vector(31 downto 0); + wr_en : in std_logic; + rd_en : in std_logic; + prog_full_thresh_assert : in std_logic_vector(9 downto 0); + prog_full_thresh_negate : in std_logic_vector(9 downto 0); + dout : out std_logic_vector(31 downto 0); + full : out std_logic; + empty : out std_logic; + valid : out std_logic; + prog_full : out std_logic + ); + end component; + + --------------------- + -- Constants + --------------------- + constant c_L2P_MAX_PAYLOAD : integer := 32; + constant c_ADDR_FIFO_FULL_THRES : integer := 800; + constant c_DATA_FIFO_FULL_THRES : integer := 800; + constant c_TIMEOUT : integer := 2000; + + --------------------- + -- Signals + --------------------- + signal fifo_rst : std_logic; + signal fifo_rst_t : std_logic; + + -- Data FIFO + signal data_fifo_rd : std_logic; + signal data_fifo_wr : std_logic; + signal data_fifo_empty : std_logic; + signal data_fifo_full : std_logic; + signal data_fifo_dout : std_logic_vector(31 downto 0); + signal data_fifo_din : std_logic_vector(31 downto 0); + + -- Addr FIFO + signal addr_fifo_rd : std_logic; + signal addr_fifo_wr : std_logic; + signal addr_fifo_empty : std_logic; + signal addr_fifo_full : std_logic; + signal addr_fifo_dout : std_logic_vector(31 downto 0); + signal addr_fifo_din : std_logic_vector(31 downto 0); + + -- L2P FSM + type l2p_dma_state_type is (L2P_IDLE, L2P_SETUP, L2P_HEADER, + L2P_ADDR_H, L2P_ADDR_L, L2P_DATA, + L2P_LAST_DATA, L2P_ERROR); + signal l2p_dma_current_state : l2p_dma_state_type; + + -- L2P packets + signal s_l2p_header : std_logic_vector(31 downto 0); + signal l2p_len_cnt : unsigned(12 downto 0); + signal l2p_address_h : std_logic_vector(31 downto 0); + signal l2p_address_l : std_logic_vector(31 downto 0); + signal l2p_data_cnt : unsigned(12 downto 0); + signal l2p_64b_address : std_logic; + signal l2p_len_header : unsigned(12 downto 0); + signal l2p_byte_swap : std_logic_vector(1 downto 0); + signal l2p_last_packet : std_logic; + signal l2p_lbe_header : std_logic_vector(3 downto 0); + + signal ldm_arb_data_l : std_logic_vector(31 downto 0); + signal ldm_arb_valid : std_logic; + + signal data_fifo_valid : std_logic; + signal addr_fifo_valid : std_logic; + + -- Counter + signal target_addr_cnt : std_logic_vector(31 downto 0); + signal dma_length_cnt : unsigned(12 downto 0); + signal l2p_timeout_cnt : unsigned(12 downto 0); + signal wb_timeout_cnt : unsigned(12 downto 0); + + -- Wishbone + signal l2p_dma_cyc_t : std_logic; + signal l2p_dma_stb_t : std_logic; + signal wb_ack_cnt : unsigned(12 downto 0); + signal wb_read_cnt : unsigned(12 downto 0); begin - - - ------------------------------------------------------------------------------ - -- Active high reset for fifo - ------------------------------------------------------------------------------ - -- Creates an active high reset for fifos regardless of c_RST_ACTIVE value - gen_fifo_rst_n : if c_RST_ACTIVE = '0' generate - fifo_rst_n <= rst_n_i; - end generate; - - gen_fifo_rst : if c_RST_ACTIVE = '1' generate - fifo_rst_n <= not(rst_n_i); - end generate; - - ------------------------------------------------------------------------------ - -- Target address counter - ------------------------------------------------------------------------------ - p_target_cnt : process (clk_i, rst_n_i) - begin - if(rst_n_i = c_RST_ACTIVE) then - target_addr_cnt <= (others => '0'); - dma_length_cnt <= (others => '0'); - dma_ctrl_error_o <= '0'; - addr_fifo_wr <= '0'; - elsif rising_edge(clk_i) then - if (dma_ctrl_start_l2p_i = '1') then - if (l2p_dma_current_state = L2P_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_target_addr_i(31 downto 2)); - -- dma_ctrl_len_i is in byte and dma_length_cnt is in 32-bit word - dma_length_cnt <= unsigned(dma_ctrl_len_i(31 downto 2)); - dma_ctrl_error_o <= '0'; - else - -- trying to start a DMA transfert when another is still in progress - -- will gives an error - target_addr_cnt <= (others => '0'); - dma_length_cnt <= (others => '0'); - dma_ctrl_error_o <= '1'; - end if; - elsif (dma_length_cnt /= 0 and addr_fifo_full = '0') then - -- increment the target address and write it to address fifo - addr_fifo_wr <= '1'; - target_addr_cnt <= target_addr_cnt + 1; - dma_length_cnt <= dma_length_cnt - 1; - -- Adust data width, fifo width is 32 bits - addr_fifo_din <= "00" & std_logic_vector(target_addr_cnt); - else - addr_fifo_wr <= '0'; - end if; - end if; - end process p_target_cnt; - - ------------------------------------------------------------------------------ - -- Packet generator - ------------------------------------------------------------------------------ - -- Sends data to the host. - -- Split in several packets if amount of data exceeds max payload size. - - p_pkt_gen : process (clk_i, rst_n_i) - begin - if (rst_n_i = c_RST_ACTIVE) then - l2p_len_cnt <= (others => '0'); - l2p_data_cnt <= (others => '0'); - l2p_address_h <= (others => '0'); - l2p_address_l <= (others => '0'); - l2p_64b_address <= '0'; - l2p_len_header <= (others => '0'); - l2p_byte_swap <= (others => '0'); - l2p_last_packet <= '0'; - elsif rising_edge(clk_i) then - -- First packet - if (l2p_dma_current_state = L2P_IDLE) then - if (dma_ctrl_start_l2p_i = '1') then - -- store DMA info locally - l2p_len_cnt <= unsigned(dma_ctrl_len_i(31 downto 2)); - l2p_address_h <= unsigned(dma_ctrl_host_addr_h_i); - l2p_address_l <= unsigned(dma_ctrl_host_addr_l_i); - l2p_byte_swap <= dma_ctrl_byte_swap_i; - end if; - elsif (l2p_dma_current_state = L2P_HEADER) then - -- if DMA length is bigger than the max PCIe payload size, - -- the data is split in several packets - if (l2p_len_cnt > c_L2P_MAX_PAYLOAD) then - l2p_data_cnt <= c_L2P_MAX_PAYLOAD; - -- when max payload length is 1024, the header length field = 0 - l2p_len_header <= c_L2P_MAX_PAYLOAD(9 downto 0); - l2p_last_packet <= '0'; - elsif (l2p_len_cnt = c_L2P_MAX_PAYLOAD) then - l2p_data_cnt <= c_L2P_MAX_PAYLOAD; - -- when max payload length is 1024, the header length field = 0 - l2p_len_header <= c_L2P_MAX_PAYLOAD(9 downto 0); - l2p_last_packet <= '1'; - else - l2p_data_cnt <= l2p_len_cnt(10 downto 0); - l2p_len_header <= l2p_len_cnt(9 downto 0); - l2p_last_packet <= '1'; - end if; - -- if host address is 64-bit, generates a 64-bit address memory write - if (l2p_address_h = 0) then - l2p_64b_address <= '0'; - else - l2p_64b_address <= '1'; - end if; - -- Next packet (if any) - elsif (l2p_dma_current_state = L2P_ADDR_L) then - if (l2p_last_packet = '0' and data_fifo_empty = '0') then - l2p_len_cnt <= l2p_len_cnt - c_L2P_MAX_PAYLOAD; - elsif (l2p_last_packet = '1') then - l2p_len_cnt <= (others => '0'); + fifo_rst <= not rst_n_i or fifo_rst_t; + + ldm_arb_valid_o <= ldm_arb_valid; + ldm_arb_data_o <= ldm_arb_data_l; + +-- ldm_arb_data_o <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap) when (l2p_dma_current_state = L2P_DATA) +-- else f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap) when (l2p_dma_current_state = L2P_LAST_DATA) +-- else ldm_arb_data_l when (l2p_dma_current_state = L2P_HEADER) +-- else ldm_arb_data_l when (l2p_dma_current_state = L2P_ADDR_L) +-- else ldm_arb_data_l when (l2p_dma_current_state = L2P_ADDR_H) +-- else x"DEADBEEF"; + --------------------- + -- L2P FSM + --------------------- + p_l2p_fsm : process (clk_i, rst_n_i) + begin + if (rst_n_i = '0') then + l2p_dma_current_state <= L2P_IDLE; + ldm_arb_req_o <= '0'; + ldm_arb_data_l <= (others => '0'); + ldm_arb_valid <= '0'; + ldm_arb_dframe_o <= '0'; + data_fifo_rd <= '0'; + dma_ctrl_done_o <= '0'; + l2p_edb_o <= '0'; + l2p_timeout_cnt <= (others => '0'); + fifo_rst_t <= '0'; + data_fifo_valid <= '0'; + elsif rising_edge(clk_i) then + case l2p_dma_current_state is + + when L2P_IDLE => + l2p_timeout_cnt <= (others => '0'); + l2p_edb_o <= '0'; + fifo_rst_t <= '0'; + ldm_arb_req_o <= '0'; + ldm_arb_data_l <= (others => '0'); + ldm_arb_valid <= '0'; + ldm_arb_dframe_o <= '0'; + data_fifo_rd <= '0'; + dma_ctrl_done_o <= '0'; + data_fifo_valid <= '0'; + if (dma_ctrl_start_l2p_i = '1') then + l2p_dma_current_state <= L2P_SETUP; + end if; + + + when L2P_SETUP => + ldm_arb_valid <= '0'; + ldm_arb_dframe_o <= '0'; + data_fifo_rd <= '0'; + l2p_timeout_cnt <= (others => '0'); + if (l2p_rdy_i = '1') then + l2p_dma_current_state <= L2P_HEADER; + ldm_arb_req_o <= '1'; -- Request bus + end if; + + when L2P_HEADER => + ldm_arb_valid <= '0'; + if (arb_ldm_gnt_i = '1' and l_wr_rdy_i = "11") then + ldm_arb_req_o <= '0'; -- Bus has been granted + -- Send header + ldm_arb_data_l <= s_l2p_header; + ldm_arb_valid <= '1'; + ldm_arb_dframe_o <= '1'; -- Keep asserted to stay bus master + if (l2p_64b_address = '1') then + l2p_dma_current_state <= L2P_ADDR_H; + else + l2p_dma_current_state <= L2P_ADDR_L; + end if; + end if; + + when L2P_ADDR_H => + ldm_arb_data_l <= l2p_address_h; + l2p_dma_current_state <= L2P_ADDR_L; + + when L2P_ADDR_L => + ldm_arb_data_l <= l2p_address_l; + l2p_dma_current_state <= L2P_DATA; + + when L2P_DATA => + ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); + if (data_fifo_empty = '0' and data_fifo_valid = '1' and l2p_data_cnt > 1) then + ldm_arb_valid <= '1'; + ldm_arb_dframe_o <= '1'; + data_fifo_valid <= '0'; + elsif (data_fifo_empty = '1' and data_fifo_valid = '1' and l2p_data_cnt > 1) then + ldm_arb_valid <= '0'; + ldm_arb_dframe_o <= '1'; + data_fifo_valid <= '0'; + elsif (data_fifo_valid = '1' and l2p_data_cnt <= 1) then + ldm_arb_valid <= '1'; + ldm_arb_dframe_o <= '0'; + l2p_dma_current_state <= L2P_LAST_DATA; + data_fifo_valid <= '0'; + else + ldm_arb_valid <= '0'; + ldm_arb_dframe_o <= '1'; + end if; + + if (data_fifo_empty = '0' and l2p_rdy_i = '1' and l2p_data_cnt > 1) then + data_fifo_rd <= '1'; + data_fifo_valid <= '1'; + elsif (data_fifo_empty = '0' and l2p_rdy_i = '1' and l2p_data_cnt = 0) then + data_fifo_rd <= '1'; + data_fifo_valid <= '1'; + else + data_fifo_rd <= '0'; + end if; + + +-- if (data_fifo_empty = '0' and l2p_rdy_i = '1' and l2p_data_cnt > 1) then +-- data_fifo_rd <= '1'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- elsif (data_fifo_empty = '0' and data_fifo_empty_d = '0' and l2p_data_cnt = 1) then +-- data_fifo_rd <= '0'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- elsif (data_fifo_empty = '0' and data_fifo_empty_d = '1' and l2p_data_cnt = 1) then +-- data_fifo_rd <= '1'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- elsif (data_fifo_empty = '1' and l2p_data_cnt = 1) then +-- data_fifo_rd <= '1'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- elsif (data_fifo_empty = '0' and l2p_data_cnt = 0) then +-- data_fifo_rd <= '1'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- else +-- data_fifo_rd <= '0'; +-- end if; +-- +-- if (data_fifo_empty = '0' and data_fifo_rd = '1' and l2p_data_cnt > 1) then +-- ldm_arb_valid <= '1'; +-- ldm_arb_dframe_o <= '1'; +-- elsif (data_fifo_empty = '0' and data_fifo_empty_d = '0' and l2p_data_cnt = 1 and data_fifo_rd = '1') then +-- ldm_arb_valid <= '1'; +-- ldm_arb_dframe_o <= '0'; +-- l2p_dma_current_state <= L2P_LAST_DATA; +-- elsif (data_fifo_empty = '0' and data_fifo_empty_d = '1' and l2p_data_cnt = 1 and data_fifo_rd = '1') then +-- ldm_arb_valid <= '1'; +-- ldm_arb_dframe_o <= '1'; +-- elsif (l2p_data_cnt = 0) then +-- ldm_arb_valid <= '1'; +-- ldm_arb_dframe_o <= '0'; +-- l2p_dma_current_state <= L2P_LAST_DATA; +-- else +-- ldm_arb_valid <= '0'; +-- ldm_arb_dframe_o <= '1'; +-- end if; + +-- if (data_fifo_empty = '0' and l2p_data_cnt > TO_UNSIGNED(1, 13) and l2p_rdy_i = '1' and data_fifo_rd = '1') then +-- ldm_arb_dframe_o <= '1'; +-- ldm_arb_valid <= '1'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- data_fifo_rd <= '1'; +-- elsif (data_fifo_empty = '0' and l2p_data_cnt > TO_UNSIGNED(1, 13) and l2p_rdy_i = '0' and data_fifo_rd = '1') then +-- ldm_arb_dframe_o <= '1'; +-- ldm_arb_valid <= '1'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- data_fifo_rd <= '0'; +-- elsif (data_fifo_empty = '0' and l2p_data_cnt > TO_UNSIGNED(1, 13) and l2p_rdy_i = '1' and data_fifo_rd = '0') then +-- ldm_arb_dframe_o <= '1'; +-- ldm_arb_valid <= '0'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- data_fifo_rd <= '1'; +-- elsif (l2p_data_cnt = TO_UNSIGNED(1, 13) and data_fifo_empty = '0' and data_fifo_rd = '1') then +-- ldm_arb_dframe_o <= '0'; +-- ldm_arb_valid <= '1'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- data_fifo_rd <= '0'; +-- l2p_dma_current_state <= L2P_LAST_DATA; +-- elsif (l2p_data_cnt = TO_UNSIGNED(1, 13) and data_fifo_empty = '0' and data_fifo_rd = '0') then +-- ldm_arb_dframe_o <= '1'; +-- ldm_arb_valid <= '0'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- data_fifo_rd <= '1'; +-- --l2p_dma_current_state <= L2P_LAST_DATA; +-- elsif (l2p_data_cnt = TO_UNSIGNED(0, 13) and data_fifo_empty = '0' and data_fifo_rd = '0') then +-- ldm_arb_dframe_o <= '0'; +-- ldm_arb_valid <= '1'; +-- ldm_arb_data_l <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); +-- data_fifo_rd <= '1'; +-- l2p_dma_current_state <= L2P_LAST_DATA; +-- else +-- ldm_arb_dframe_o <= '1'; +-- ldm_arb_valid <= '0'; +-- data_fifo_rd <= '0'; +-- end if; + + -- Error condition, aboirt transfer + if (tx_error_i = '1' or l2p_timeout_cnt > c_TIMEOUT or dma_ctrl_abort_i = '1') then + l2p_dma_current_state <= L2P_ERROR; + end if; + + -- Timeout counter + if (data_fifo_empty = '1' or l2p_rdy_i = '1') then + l2p_timeout_cnt <= l2p_timeout_cnt + 1; + else + l2p_timeout_cnt <= (others => '0'); + end if; + + when L2P_LAST_DATA => + ldm_arb_dframe_o <= '0'; + ldm_arb_valid <= '0'; + data_fifo_rd <= '0'; + if (dma_ctrl_abort_i = '1' or tx_error_i = '1') then + l2p_dma_current_state <= L2P_IDLE; + dma_ctrl_done_o <= '1'; + elsif (l2p_last_packet = '0') then + l2p_dma_current_state <= L2P_SETUP; + else + l2p_dma_current_state <= L2P_IDLE; + dma_ctrl_done_o <= '1'; + end if; + + when L2P_ERROR => + ldm_arb_dframe_o <= '0'; + ldm_arb_valid <='1'; + l2p_edb_o <= '1'; + fifo_rst_t <= '1'; + l2p_dma_current_state <= L2P_IDLE; + + when others => + l2p_dma_current_state <= L2P_IDLE; + + end case; end if; - elsif ((l2p_dma_current_state = L2P_DATA) and (data_fifo_valid = '1')) then - l2p_data_cnt <= l2p_data_cnt - 1; - elsif (l2p_last_packet = '0' and l2p_dma_current_state = L2P_LAST_DATA) then - -- load the host address of the next packet - l2p_address_l <= l2p_address_l + (c_L2P_MAX_PAYLOAD * 4); - -- load the size of the next packet - if (l2p_len_cnt > c_L2P_MAX_PAYLOAD) then - l2p_data_cnt <= c_L2P_MAX_PAYLOAD; - -- when max payload length is 1024, the header length field = 0 - l2p_len_header <= c_L2P_MAX_PAYLOAD(9 downto 0); - l2p_last_packet <= '0'; - elsif (l2p_len_cnt = c_L2P_MAX_PAYLOAD) then - l2p_data_cnt <= c_L2P_MAX_PAYLOAD; - -- when max payload length is 1024, the header length field = 0 - l2p_len_header <= c_L2P_MAX_PAYLOAD(9 downto 0); - l2p_last_packet <= '1'; - else - l2p_data_cnt <= l2p_len_cnt(10 downto 0); - l2p_len_header <= l2p_len_cnt(9 downto 0); - l2p_last_packet <= '1'; + end process p_l2p_fsm; + + + --------------------- + --- Paket Generator + --------------------- + -- Last Byte Enable must be "0000" when length = 1 + l2p_lbe_header <= "0000" when l2p_len_header = 1 else "1111"; + -- 64bit address flag + l2p_64b_address <= '0' when l2p_address_h = "00000000" else '1'; + + -- Packet header + s_l2p_header(31 downto 29) <= "000"; --> Traffic Class + s_l2p_header(28) <= '0'; --> Snoop + s_l2p_header(27 downto 25) <= "001"; --> Header type, + -- memory write 32-bit or + -- memory write 64-bit + s_l2p_header(24) <= l2p_64b_address; + s_l2p_header(23 downto 20) <= l2p_lbe_header; --> LBE (Last Byte Enable) + s_l2p_header(19 downto 16) <= "1111"; --> FBE (First Byte Enable) + s_l2p_header(15 downto 13) <= "000"; --> Reserved + s_l2p_header(12) <= '0'; --> VC (Virtual Channel) + s_l2p_header(11 downto 10) <= "00"; --> Reserved + s_l2p_header(9 downto 0) <= STD_LOGIC_VECTOR(l2p_len_header(9 downto 0)); --> Length (in 32-bit words) + -- 0x000 => 1024 words (4096 bytes) + p_pkt_gen : process (clk_i, rst_n_i) + begin + if (rst_n_i = '0') then + l2p_len_cnt <= (others => '0'); + l2p_data_cnt <= (others => '0'); + l2p_address_h <= (others => '0'); + l2p_address_l <= (others => '0'); + l2p_len_header <= (others => '0'); + l2p_byte_swap <= (others => '0'); + l2p_last_packet <= '0'; + elsif rising_edge(clk_i) then + if (l2p_dma_current_state = L2P_IDLE) then + l2p_len_cnt <= unsigned(dma_ctrl_len_i(14 downto 2)); + l2p_address_h <= dma_ctrl_host_addr_h_i; + l2p_address_l <= dma_ctrl_host_addr_l_i; + l2p_byte_swap <= dma_ctrl_byte_swap_i; + l2p_last_packet <= '0'; + elsif (l2p_dma_current_state = L2P_SETUP) then + if (l2p_len_cnt > c_L2P_MAX_PAYLOAD) then + l2p_data_cnt <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD, 13); + l2p_len_header <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD, 13); + l2p_last_packet <= '0'; + elsif (l2p_len_cnt = c_L2P_MAX_PAYLOAD) then + l2p_data_cnt <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD, 13); + l2p_len_header <= TO_UNSIGNED(c_L2P_MAX_PAYLOAD, 13); + l2p_last_packet <= '1'; + else + l2p_data_cnt <= l2p_len_cnt; + l2p_len_header <= l2p_len_cnt; + l2p_last_packet <= '1'; + end if; + --elsif (l2p_dma_current_state = L2P_HEADER) then + --elsif (l2p_dma_current_state = L2P_ADDR_H) then + elsif (l2p_dma_current_state = L2P_ADDR_L) then + --l2p_data_cnt <= l2p_data_cnt -1; + elsif (l2p_dma_current_state = L2P_DATA) then + --if (data_fifo_empty = '0' and l2p_data_cnt > 1 and data_fifo_rd = '1') then + if (ldm_arb_valid = '1') then + l2p_data_cnt <= l2p_data_cnt - 1; + end if; + elsif (l2p_dma_current_state = L2P_LAST_DATA) then + if (l2p_last_packet = '0') then + -- Increase Address + -- TODO Not overflow safe ! + l2p_address_l <= STD_LOGIC_VECTOR(unsigned(l2p_address_l) + (c_L2P_MAX_PAYLOAD * 4)); + l2p_len_cnt <= l2p_len_cnt - c_L2P_MAX_PAYLOAD; + else + l2p_len_cnt <= (others => '0'); + end if; + end if; end if; - end if; - end if; - end process p_pkt_gen; - - -- Last Byte Enable must be "0000" when length = 1 - l2p_lbe_header <= "0000" when l2p_len_header = 1 else "1111"; - - -- Packet header - s_l2p_header <= "000" --> Traffic Class - & '0' --> Snoop - & "001" & l2p_64b_address --> Header type, - -- memory write 32-bit or - -- memory write 64-bit - & l2p_lbe_header --> LBE (Last Byte Enable) - & "1111" --> FBE (First Byte Enable) - & "000" --> Reserved - & '0' --> VC (Virtual Channel) - & "00" --> Reserved - & std_logic_vector(l2p_len_header); --> Length (in 32-bit words) - -- 0x000 => 1024 words (4096 bytes) - - ----------------------------------------------------------------------------- - -- L2P packet write FSM - ----------------------------------------------------------------------------- - process(clk_i, rst_n_i) - begin - if (rst_n_i = c_RST_ACTIVE) then - l2p_dma_current_state <= L2P_IDLE; - ldm_arb_req_o <= '0'; - ldm_arb_data_o <= (others => '0'); - ldm_arb_valid_o <= '0'; - ldm_arb_dframe_o <= '0'; - data_fifo_rd <= '0'; - dma_ctrl_done_o <= '0'; - l2p_edb_o <= '0'; - data_fifo_rd_cnt <= (others => '0'); - l2p_timeout_cnt <= (others => '0'); - --data_fifo_valid_ex <= '0'; - elsif rising_edge(clk_i) then - case l2p_dma_current_state is - - when L2P_IDLE => - -- do nothing ! - data_fifo_rd <= '0'; - dma_ctrl_done_o <= '0'; - ldm_arb_data_o <= (others => '0'); - ldm_arb_valid_o <= '0'; - ldm_arb_dframe_o <= '0'; - l2p_edb_o <= '0'; - l2p_timeout_cnt <= (others => '0'); - --data_fifo_valid_ex <= '0'; - - if (dma_ctrl_start_l2p_i = '1') then - l2p_dma_current_state <= L2P_SETUP; - end if; - - when L2P_SETUP => - if (l2p_rdy_i = '1') then - -- We have data to send -> prepare a packet, first the header - l2p_dma_current_state <= L2P_HEADER; - -- request access to PCIe bus - ldm_arb_req_o <= '1'; - end if; - - when L2P_HEADER => - if(arb_ldm_gnt_i = '1' and l_wr_rdy_i = "11") then - -- clear access request to the arbiter - -- access is granted until dframe is cleared - ldm_arb_req_o <= '0'; - -- send header - ldm_arb_data_o <= s_l2p_header; - ldm_arb_valid_o <= '1'; - ldm_arb_dframe_o <= '1'; - data_fifo_rd_cnt <= l2p_data_cnt(10 downto 0); - if(l2p_64b_address = '1') then - -- if host address is 64-bit, we have to send an additionnal - -- 32-word containing highest bits of the host address - l2p_dma_current_state <= L2P_ADDR_H; + end process p_pkt_gen; + + --------------------- + -- Address Counter + --------------------- + p_target_cnt : process (clk_i, rst_n_i) + begin + if (rst_n_i = '0') then + target_addr_cnt <= (others => '0'); + dma_length_cnt <= (others => '0'); + dma_ctrl_error_o <= '0'; + addr_fifo_wr <= '0'; + addr_fifo_din <= (others => '0'); + elsif rising_edge(clk_i) then + -- New Transfer started + if (l2p_dma_current_state = L2P_ERROR) then + target_addr_cnt <= (others => '0'); + dma_ctrl_error_o <= '1'; + addr_fifo_wr <= '0'; + dma_length_cnt <= (others => '0'); + elsif (dma_ctrl_start_l2p_i = '1') then + if (l2p_dma_current_state = L2P_IDLE) then + -- dma target adrr is byte address, need 32bit address + target_addr_cnt(31 downto 30) <= "00"; + target_addr_cnt(29 downto 0) <= dma_ctrl_target_addr_i(31 downto 2); + -- dma target length is in byte, need 32bit + dma_length_cnt <= unsigned(dma_ctrl_len_i(14 downto 2)); + dma_ctrl_error_o <= '0'; + else + target_addr_cnt <= (others => '0'); + dma_length_cnt <= (others => '0'); + dma_ctrl_error_o <= '1'; + end if; + addr_fifo_wr <= '0'; + elsif (dma_length_cnt > 0) and (addr_fifo_full = '0') then + addr_fifo_wr <= '1'; + target_addr_cnt <= STD_LOGIC_VECTOR(unsigned(target_addr_cnt) + 1); + dma_length_cnt <= dma_length_cnt - 1; + addr_fifo_din <= target_addr_cnt; else - -- for 32-bit host address, we only have to send lowest bits - l2p_dma_current_state <= L2P_ADDR_L; - -- Starts reading data in the fifo now, because there is - -- 1 cycle delay until data are available - --data_fifo_rd <= '1'; + addr_fifo_wr <= '0'; + dma_ctrl_error_o <= '0'; end if; - else - -- arbiter or GN4124 not ready to receive a new packet - ldm_arb_valid_o <= '0'; - end if; - - when L2P_ADDR_H => - ldm_arb_dframe_o <= '1'; - ldm_arb_valid_o <= '1'; - -- send host address 32 highest bits - ldm_arb_data_o <= std_logic_vector(l2p_address_h); - -- Now we still have to send lowest bits of the host address - l2p_dma_current_state <= L2P_ADDR_L; - -- Starts reading data in the fifo now, because there is - -- 1 cycle delay until data are available - --data_fifo_rd <= '1'; - - when L2P_ADDR_L => - ldm_arb_dframe_o <= '1'; - -- send host address 32 lowest bits - --data_fifo_rd <= '1'; - ldm_arb_data_o <= std_logic_vector(l2p_address_l); - if (data_fifo_empty = '0') then - l2p_dma_current_state <= L2P_DATA; - data_fifo_rd <= '1'; - ldm_arb_valid_o <= '1'; - else - ldm_arb_valid_o <= '0'; - data_fifo_rd <= '0'; - end if; - - - when L2P_DATA => - ldm_arb_dframe_o <= '1'; - if (data_fifo_rd = '1' and data_fifo_empty ='0') then - data_fifo_rd_cnt <= data_fifo_rd_cnt -1; - end if; - - l2p_edb_o <= '1'; - - -- Pause until gennum ready - if (l2p_rdy_i = '0' or (data_fifo_rd_cnt <= 1 and data_fifo_rd = '1' and data_fifo_empty ='0') or data_fifo_rd_cnt = 0) then - data_fifo_rd <= '0'; - else - data_fifo_rd <= '1'; - end if; - - if (data_fifo_valid = '1') then - l2p_timeout_cnt <= (others => '0'); - -- send data with byte swap if requested - ldm_arb_data_o <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); - ldm_arb_valid_o <= '1'; - -- last data signaled w/o dframe --- if (data_fifo_rd_cnt = 0) then --- ldm_arb_dframe_o <= '0'; --- l2p_dma_current_state <= L2P_LAST_DATA; --- data_fifo_rd <= '0'; --- end if; - else - ldm_arb_valid_o <= '0'; - l2p_timeout_cnt <= l2p_timeout_cnt + 1; - end if; - - if (data_fifo_rd_cnt = 0 or l2p_timeout_cnt > 2000) then - l2p_dma_current_state <= L2P_LAST_DATA; - ldm_arb_dframe_o <= '0'; - ldm_arb_valid_o <= '1'; - data_fifo_rd <= '0'; - end if; - - when L2P_LAST_DATA => - data_fifo_rd <= '0'; - l2p_edb_o <= '0'; - ldm_arb_valid_o <= '0'; - ldm_arb_dframe_o <= '0'; - if (dma_ctrl_abort_i = '1' or tx_error_i = '1') then - -- Abort transmission - l2p_dma_current_state <= L2P_IDLE; - dma_ctrl_done_o <= '1'; - elsif(l2p_len_cnt > 0) then - -- There is still data to be send -> start a new packet - l2p_dma_current_state <= L2P_SETUP; + end if; + end process p_target_cnt; + + --------------------- + -- Wishbone Master + --------------------- + -- Tie offs + l2p_dma_cyc_o <= l2p_dma_cyc_t; + l2p_dma_stb_o <= l2p_dma_stb_t; + l2p_dma_adr_o <= addr_fifo_dout; + l2p_dma_dat_o <= (others => '0'); + l2p_dma_we_o <= '0'; + +-- l2p_dma_adr_o(18 downto 0) <= addr_fifo_dout(18 downto 0); +-- l2p_dma_adr_o(30 downto 19) <= STD_LOGIC_VECTOR(wb_read_cnt(11 downto 0)); +-- l2p_dma_adr_o(31) <= addr_fifo_empty; +-- l2p_dma_adr_o(11 downto 0) <= STD_LOGIC_VECTOR(wb_read_cnt(11 downto 0)); +-- l2p_dma_adr_o(31 downto 12) <= (others => '0'); + + addr_fifo_valid <= not(addr_fifo_empty or l2p_dma_stall_i or data_fifo_full or p2l_dma_cyc_i); + + p_wb_master : process (l2p_dma_clk_i, rst_n_i, wb_read_cnt) + begin + if (rst_n_i = '0') then + l2p_dma_stb_t <= '0'; + l2p_dma_cyc_t <= '0'; + l2p_dma_sel_o <= (others => '0'); + addr_fifo_rd <= '0'; + wb_read_cnt <= (others => '0'); + wb_ack_cnt <= (others => '0'); + --l2p_dma_adr_o <= (others => '0'); + + elsif rising_edge(l2p_dma_clk_i) then + -- Read logic + if (l2p_dma_current_state = L2P_ERROR) then + wb_read_cnt <= (others => '0'); + l2p_dma_stb_t <= '0'; + l2p_dma_sel_o <= (others => '1'); + addr_fifo_rd <= '0'; + elsif (l2p_dma_current_state = L2P_IDLE and dma_ctrl_start_l2p_i = '1') then + wb_read_cnt <= unsigned(dma_ctrl_len_i(14 downto 2)); + l2p_dma_stb_t <= '0'; + l2p_dma_sel_o <= (others => '1'); + addr_fifo_rd <= '0'; + elsif ((addr_fifo_valid = '1') and (wb_read_cnt > 0)) then + wb_read_cnt <= wb_read_cnt - 1; + l2p_dma_stb_t <= '1'; + l2p_dma_sel_o <= (others => '1'); + addr_fifo_rd <= '1'; else - -- Nomore data to send, go back to sleep - l2p_dma_current_state <= L2P_IDLE; - -- Indicate that the DMA transfer is finished - dma_ctrl_done_o <= '1'; + wb_read_cnt <= wb_read_cnt; + l2p_dma_stb_t <= '0'; + l2p_dma_sel_o <= (others => '1'); + addr_fifo_rd <= '0'; end if; + -- Cycle logic + if (wb_read_cnt = 0 and wb_ack_cnt = 0) then + l2p_dma_cyc_t <= '0'; + else + l2p_dma_cyc_t <= '1'; + end if; --- when L2P_DATA => --- data_fifo_valid_ex <= '0'; --- if (data_fifo_valid = '1' or data_fifo_valid_ex = '1') then --- -- send data with byte swap if requested --- --ldm_arb_data_o <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); --- ldm_arb_data_o(10 downto 0) <= std_logic_vector(l2p_data_cnt); --- ldm_arb_data_o(31 downto 11) <= (others => '0'); --- ldm_arb_valid_o <= '1'; --- else --- ldm_arb_valid_o <= '0'; --- end if; --- --- if (dma_ctrl_abort_i = '1' or tx_error_i = '1') then --- l2p_edb_o <= '1'; --- l2p_dma_current_state <= L2P_IDLE; --- elsif (l2p_rdy_i = '0') then --- -- GN4124 not able to receive more data, have to wait --- l2p_dma_current_state <= L2P_WAIT_RDY; --- -- Stop reading from fifo --- data_fifo_rd <= '0'; --- -- Invalidate data --- ldm_arb_valid_o <= '0'; --- elsif(data_fifo_empty = '1') then --- -- data not ready yet, wait for it --- l2p_dma_current_state <= L2P_WAIT_DATA; --- elsif(l2p_data_cnt <= 2) then --- -- Only one 32-bit data word to send --- l2p_dma_current_state <= L2P_LAST_DATA; --- -- Stop reading from fifo --- data_fifo_rd <= '0'; --- end if; --- --- when L2P_WAIT_RDY => --- ldm_arb_valid_o <= '0'; --- if (l2p_rdy_i = '1') then --- -- GN4124 is ready to receive more data --- -- Validate last data read before de-assertion of l2p_rdy --- ldm_arb_valid_o <= '1'; --- if (l2p_data_cnt <= 1) then --- -- Last data word of the packet --- l2p_dma_current_state <= L2P_LAST_DATA; --- else --- -- More data word to be sent --- l2p_dma_current_state <= L2P_DATA; --- -- Re-start fifo reading --- data_fifo_rd <= '1'; --- data_fifo_valid_ex <= '1'; --- end if; --- end if; --- --- when L2P_WAIT_DATA => --- ldm_arb_valid_o <= '0'; --- if(data_fifo_empty = '0') then --- if(l2p_data_cnt <= 1) then --- -- Only one 32-bit data word to send --- l2p_dma_current_state <= L2P_LAST_DATA; --- -- Stop reading from fifo --- data_fifo_rd <= '0'; --- else --- -- data ready to be send again --- l2p_dma_current_state <= L2P_DATA; --- end if; --- end if; --- --- when L2P_LAST_DATA => --- if (l2p_rdy_i = '0') then --- -- GN4124 not able to receive more data, have to wait --- -- Invalidate data --- ldm_arb_valid_o <= '0'; --- else --- -- send last data word with byte swap if requested --- --ldm_arb_data_o <= f_byte_swap(g_BYTE_SWAP, data_fifo_dout, l2p_byte_swap); --- ldm_arb_data_o(10 downto 0) <= std_logic_vector(l2p_data_cnt); --- ldm_arb_data_o(31 downto 11) <= (others => '0'); --- ldm_arb_valid_o <= '1'; --- -- clear dframe signal to indicate the end of packet --- ldm_arb_dframe_o <= '0'; --- if(l2p_len_cnt > 0) then --- -- There is still data to be send -> start a new packet --- l2p_dma_current_state <= L2P_SETUP; --- else --- -- Nomore data to send, go back to sleep --- l2p_dma_current_state <= L2P_IDLE; --- -- Indicate that the DMA transfer is finished --- dma_ctrl_done_o <= '1'; --- end if; --- end if; - - when others => - -- should no arrive here, but just in case... - l2p_dma_current_state <= L2P_IDLE; - ldm_arb_req_o <= '0'; - ldm_arb_data_o <= (others => '0'); - ldm_arb_valid_o <= '0'; - ldm_arb_dframe_o <= '0'; - data_fifo_rd <= '0'; - dma_ctrl_done_o <= '0'; - --data_fifo_valid_ex <= '0'; - - end case; - end if; - end process; - - ------------------------------------------------------------------------------ - -- FIFOs for transition between GN4124 core and wishbone clock domain - ------------------------------------------------------------------------------ - cmp_addr_fifo : generic_async_fifo - generic map ( - g_data_width => 32, - g_size => 512, - g_show_ahead => false, - g_with_rd_empty => true, - g_with_rd_full => false, - g_with_rd_almost_empty => false, - g_with_rd_almost_full => false, - g_with_rd_count => false, - g_with_wr_empty => false, - g_with_wr_full => false, - g_with_wr_almost_empty => false, - g_with_wr_almost_full => true, - g_with_wr_count => false, - g_almost_empty_threshold => 0, - g_almost_full_threshold => c_ADDR_FIFO_FULL_THRES) + -- Acknowledge counter + if (l2p_dma_ack_i = '1' and wb_ack_cnt > 0) then + wb_ack_cnt <= wb_ack_cnt - 1; + elsif (l2p_dma_current_state = L2P_ERROR) then + wb_ack_cnt <= (others => '0'); + elsif (l2p_dma_current_state = L2P_IDLE and dma_ctrl_start_l2p_i = '1') then + wb_ack_cnt <= unsigned(dma_ctrl_len_i(14 downto 2)); + end if; + + -- Timeout counter + if (l2p_dma_ack_i = '0') then + wb_timeout_cnt <= wb_timeout_cnt + 1; + else + wb_timeout_cnt <= (others => '0'); + end if; + end if; + end process p_wb_master; + + -- Receive data + data_fifo_din <= l2p_dma_dat_i; + data_fifo_wr <= l2p_dma_ack_i and l2p_dma_cyc_t; + + --------------------- + -- FIFOs + --------------------- + cmp_addr_fifo : l2p_fifo port map ( - rst_n_i => fifo_rst_n, - clk_wr_i => clk_i, - d_i => addr_fifo_din, - we_i => addr_fifo_wr, - wr_empty_o => open, - wr_full_o => open, - wr_almost_empty_o => open, - wr_almost_full_o => addr_fifo_full, - wr_count_o => open, - clk_rd_i => l2p_dma_clk_i, - q_o => addr_fifo_dout, - rd_i => addr_fifo_rd, - rd_empty_o => addr_fifo_empty, - rd_full_o => open, - rd_almost_empty_o => open, - rd_almost_full_o => open, - rd_count_o => open); - - p_gen_addr_fifo_valid : process(l2p_dma_clk_i) - begin - if rising_edge(l2p_dma_clk_i) then - addr_fifo_valid <= addr_fifo_rd and (not addr_fifo_empty); - end if; - end process; - - cmp_data_fifo : generic_async_fifo - generic map ( - g_data_width => 32, - g_size => 512, - g_show_ahead => false, - g_with_rd_empty => true, - g_with_rd_full => false, - g_with_rd_almost_empty => false, - g_with_rd_almost_full => false, - g_with_rd_count => false, - g_with_wr_empty => false, - g_with_wr_full => false, - g_with_wr_almost_empty => false, - g_with_wr_almost_full => true, - g_with_wr_count => false, - g_almost_empty_threshold => 0, - g_almost_full_threshold => c_DATA_FIFO_FULL_THRES) + rst => fifo_rst, + wr_clk => clk_i, + rd_clk => l2p_dma_clk_i, + din => addr_fifo_din, + wr_en => addr_fifo_wr, + rd_en => addr_fifo_rd, + prog_full_thresh_assert => STD_LOGIC_VECTOR(TO_UNSIGNED(c_ADDR_FIFO_FULL_THRES, 10)), + prog_full_thresh_negate => STD_LOGIC_VECTOR(TO_UNSIGNED(c_ADDR_FIFO_FULL_THRES-50, 10)), + dout => addr_fifo_dout, + full => open, + empty => addr_fifo_empty, + valid => open, + prog_full => addr_fifo_full + ); + + cmp_data_fifo : l2p_fifo port map ( - rst_n_i => fifo_rst_n, - clk_wr_i => l2p_dma_clk_i, - d_i => data_fifo_din, - we_i => data_fifo_wr, - wr_empty_o => open, - wr_full_o => open, - wr_almost_empty_o => open, - wr_almost_full_o => data_fifo_full, - wr_count_o => open, - clk_rd_i => clk_i, - q_o => data_fifo_dout, - rd_i => data_fifo_rd, - rd_empty_o => data_fifo_empty, - rd_full_o => open, - rd_almost_empty_o => open, - rd_almost_full_o => open, - rd_count_o => open); - - p_gen_data_fifo_valid : process(clk_i) - begin - if rising_edge(clk_i) then - data_fifo_valid <= data_fifo_rd and (not data_fifo_empty); - data_fifo_valid_d <= data_fifo_empty; - end if; - end process; - - data_fifo_din <= l2p_dma_dat_i; - -- latch data when receiving ack and the cycle has been initiated by this master - data_fifo_wr <= l2p_dma_ack_i and l2p_dma_cyc_t; - - ------------------------------------------------------------------------------ - -- Pipelined wishbone master - ------------------------------------------------------------------------------ - -- Initatiates read transactions as long there is an address present - -- in the address fifo. Then fills the data fifo with the read data. - - -- Wishbone master only make reads - l2p_dma_we_o <= '0'; - l2p_dma_dat_o <= (others => '0'); - - -- Read address FIFO - addr_fifo_rd <= not(addr_fifo_empty) - and not(l2p_dma_stall_i) - and not(data_fifo_full) - and not(p2l_dma_cyc_i); - - -- Wishbone master process - p_wb_master : process (l2p_dma_clk_i, rst_n_i) - begin - if (rst_n_i = c_RST_ACTIVE) then - l2p_dma_adr_o <= (others => '0'); - l2p_dma_stb_t <= '0'; - l2p_dma_cyc_t <= '0'; - l2p_dma_sel_o <= (others => '0'); - elsif rising_edge(l2p_dma_clk_i) then - -- adr signal management - if (addr_fifo_valid = '1') then - l2p_dma_adr_o <= addr_fifo_dout; - end if; - -- stb and sel signals management - if (addr_fifo_valid = '1') then --or (l2p_dma_stall_i = '1' and l2p_dma_stb_t = '1') then - l2p_dma_stb_t <= '1'; - l2p_dma_sel_o <= (others => '1'); - else - l2p_dma_stb_t <= '0'; - l2p_dma_sel_o <= (others => '0'); - end if; - -- cyc signal management - if (addr_fifo_valid = '1') then - l2p_dma_cyc_t <= '1'; - elsif (wb_left_cnt = 0 and dma_length_cnt = 0 and addr_fifo_empty = '1') then - -- last ack received -> end of the transaction - l2p_dma_cyc_t <= '0'; - elsif (wb_timeout_cnt >= 6000) then - -- timeout, data not coming - --l2p_dma_cyc_t <= '0'; - end if; - end if; - end process p_wb_master; - - -- for read back - l2p_dma_cyc_o <= l2p_dma_cyc_t; - l2p_dma_stb_o <= l2p_dma_stb_t; - - -- Wishbone read cycle counter - p_wb_read_cnt : process (l2p_dma_clk_i, rst_n_i) - begin - if (rst_n_i = c_RST_ACTIVE) then - wb_read_cnt <= (others => '0'); - elsif rising_edge(l2p_dma_clk_i) then - if (addr_fifo_valid = '1') then - wb_read_cnt <= wb_read_cnt + 1; - end if; - end if; - end process p_wb_read_cnt; - - -- Wishbone ack counter - p_wb_ack_cnt : process (l2p_dma_clk_i, rst_n_i) - begin - if (rst_n_i = c_RST_ACTIVE) then - wb_ack_cnt <= (others => '0'); - elsif rising_edge(l2p_dma_clk_i) then - if (l2p_dma_ack_i = '1' and l2p_dma_cyc_t = '1') then - wb_ack_cnt <= wb_ack_cnt + 1; - end if; - end if; - end process p_wb_ack_cnt; - - -- Wishbone timeout counter - p_wb_timeout_cnt : process (l2p_dma_clk_i, rst_n_i) - begin - if (rst_n_i = c_RST_ACTIVE) then - wb_timeout_cnt <= (others => '0'); - elsif rising_edge(l2p_dma_clk_i) then - if (not(wb_ack_cnt = wb_read_cnt)) then - wb_timeout_cnt <= wb_timeout_cnt + 1; - else - wb_timeout_cnt <= (others =>'0'); - end if; - end if; - end process p_wb_timeout_cnt; - - -- Wishbone left counter - p_wb_left_cnt : process (l2p_dma_clk_i, rst_n_i) - begin - if (rst_n_i = c_RST_ACTIVE) then - wb_left_cnt <= (others => '0'); - elsif rising_edge(l2p_dma_clk_i) then - if (l2p_dma_ack_i = '0' and l2p_dma_stb_t = '1') then - wb_left_cnt <= wb_left_cnt + 1; - elsif (l2p_dma_ack_i = '1' and l2p_dma_stb_t = '0') then - wb_left_cnt <= wb_left_cnt - 1; - elsif (l2p_dma_cyc_t = '0') then - wb_left_cnt <= (others => '0'); - end if; - end if; - end process p_wb_left_cnt; - - -end behaviour; + rst => fifo_rst, + wr_clk => l2p_dma_clk_i, + rd_clk => clk_i, + din => data_fifo_din, + wr_en => data_fifo_wr, + rd_en => data_fifo_rd, + prog_full_thresh_assert => STD_LOGIC_VECTOR(TO_UNSIGNED(c_DATA_FIFO_FULL_THRES, 10)), + prog_full_thresh_negate => STD_LOGIC_VECTOR(TO_UNSIGNED(c_DATA_FIFO_FULL_THRES-50, 10)), + dout => data_fifo_dout, + full => open, + empty => data_fifo_empty, + valid => open, + prog_full => data_fifo_full + ); +end behavioral; diff --git a/hdl/gn4124core/rtl/p2l_dma_master.vhd b/hdl/gn4124core/rtl/p2l_dma_master.vhd index 0eda357..81cf824 100644 --- a/hdl/gn4124core/rtl/p2l_dma_master.vhd +++ b/hdl/gn4124core/rtl/p2l_dma_master.vhd @@ -580,7 +580,8 @@ begin elsif rising_edge(p2l_dma_clk_i) then -- data and address if (to_wb_fifo_valid = '1') then - p2l_dma_adr_o <= "00" & to_wb_fifo_dout(61 downto 32); + p2l_dma_adr_o(31 downto 30) <= "00"; + p2l_dma_adr_o(29 downto 0) <= to_wb_fifo_dout(61 downto 32); p2l_dma_dat_o <= to_wb_fifo_dout(31 downto 0); end if; -- stb and sel signals management -- GitLab