UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor chrisab508
Visitor
6,153 Views
Registered: ‎11-11-2015

Modifications to NPI Example Interface

Hello Everyone,

I'm having trouble understanding how I would modify the code from AR#24912 to suit my needs.  I'm writing to DDR (not reading), and I'm doing single writes at a time (no burst).  So the way I see it, I need three signals to modify: data, address, and write_enable.  Looking at the example from AR#24912 we have the following VHDL which will write all zeros to memory address zero:

 

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity my_npi is
  generic(
    C_PI_ADDR_WIDTH       :     integer                                          := 32;
    C_PI_DATA_WIDTH       :     integer                                          := 64;
    C_PI_BE_WIDTH         :     integer                                          := 8;
    C_PI_RDWDADDR_WIDTH   :     integer                                          := 4
    );
  port(
    
    -- User interface signals
    Compare_Error         : out std_logic                                        := '0';
    
    -- MPMC Port Interface - Bus is prefixed with NPI_
    XIL_NPI_Addr              : out std_logic_vector(C_PI_ADDR_WIDTH-1 downto 0)     := (others => '0');
    XIL_NPI_AddrReq           : out std_logic                                        := '0';
    XIL_NPI_AddrAck           : in  std_logic                                        := '0';
    XIL_NPI_RNW               : out std_logic                                        := '0';
    XIL_NPI_Size              : out std_logic_vector(3 downto 0)                     := (others => '0');
    XIL_NPI_WrFIFO_Data       : out std_logic_vector(C_PI_DATA_WIDTH-1 downto 0)     := (others => '0');
    XIL_NPI_WrFIFO_BE         : out std_logic_vector(C_PI_BE_WIDTH-1 downto 0)       := (others => '0');
    XIL_NPI_WrFIFO_Push       : out std_logic                                        := '0';
    XIL_NPI_RdFIFO_Data       : in  std_logic_vector(C_PI_DATA_WIDTH-1 downto 0)     := (others => '0');
    XIL_NPI_RdFIFO_Pop        : out std_logic                                        := '0';
    XIL_NPI_RdFIFO_RdWdAddr   : in  std_logic_vector(C_PI_RDWDADDR_WIDTH-1 downto 0) := (others => '0');
    XIL_NPI_WrFIFO_Empty      : in  std_logic                                        := '0';
    XIL_NPI_WrFIFO_AlmostFull : in  std_logic                                        := '0';
    XIL_NPI_WrFIFO_Flush      : out std_logic                                        := '0';
    XIL_NPI_RdFIFO_Empty      : in  std_logic                                        := '0';
    XIL_NPI_RdFIFO_Flush      : out std_logic                                        := '0';
    XIL_NPI_RdFIFO_Latency    : in  std_logic_vector(1 downto 0)                     := (others => '0');
    XIL_NPI_RdModWr           : out std_logic                                        := '0';
    XIL_NPI_InitDone          : in  std_logic                                        := '0';
    XIL_NPI_Clk               : in  std_logic                                        := '0';
    XIL_NPI_Rst               : in  std_logic                                        := '0'
    );
end entity;

architecture arc_my_npi of my_npi is
  type state_type is (RST, IDLE, TX_DATA, TX_ADDR, RX_ADDR, RX_WAIT_NOT_EMPTY,
                      RX_WAIT_RXFIFO_LAT2, RX_WAIT_RXFIFO_LAT1, RX_POP);
  signal npi_cs, npi_ns    : state_type;
  signal gen_data          : std_logic                                    := '0';
  signal npi_wrfifo_push_i : std_logic                                    := '0';
  signal npi_req_set       : std_logic                                    := '0';
  signal npi_rnw_i         : std_logic                                    := '0';
  signal npi_wrfifo_be_i   : std_logic_vector(C_PI_BE_WIDTH-1 downto 0)   := (others => '0');
  signal data              : std_logic_vector(C_PI_DATA_WIDTH-1 downto 0) := (others => '0');
  signal npi_size_i        : std_logic_vector(3 downto 0)                 := (others => '0');
  signal npi_addrreq_int   : std_logic                                    := '0';
  signal initdone          : std_logic                                    := '0';
  signal compare_enable    : std_logic                                    := '0';
  signal npi_rdfifo_pop_i  : std_logic                                    := '0';
  signal compare_error_i   : std_logic                                    := '0';
begin
  
  -- Internally used outputs
  XIL_NPI_RdFIFO_Pop <= npi_rdfifo_pop_i;

  -- Basic pipeline for write path signals
  PIPE         : process (XIL_NPI_Clk)
  begin
    if rising_edge(XIL_NPI_Clk) then
      initdone        <= XIL_NPI_InitDone;
      XIL_NPI_WrFIFO_Push <= npi_wrfifo_push_i;
      XIL_NPI_WrFIFO_BE   <= npi_wrfifo_be_i;
      XIL_NPI_WrFIFO_Data <= data;
    end if;
  end process;

  -- Upon address ack, clear address qualifiers 
  ADDRACK_PIPE : process (XIL_NPI_Clk, XIL_NPI_AddrAck)
  begin
    if rising_edge(XIL_NPI_Clk) then
      if XIL_NPI_AddrAck = '1' then
        XIL_NPI_RNW       <= '0';
        XIL_NPI_Size      <= "0000";
      else
        XIL_NPI_RNW       <= npi_rnw_i;
        XIL_NPI_Size      <= npi_size_i;
      end if;
    end if;
  end process;

  -- Address ack pipeline
  -- Deassert address request 
  NPI_REQ_PIPE : process (XIL_NPI_Clk, XIL_NPI_AddrAck, npi_req_set)
  begin
    if rising_edge(XIL_NPI_Clk) then
      if XIL_NPI_AddrAck = '1' then
        npi_addrreq_int <= '0';
      elsif npi_req_set = '1' then
        npi_addrreq_int <= '1';
      else
        npi_addrreq_int <= npi_addrreq_int;
      end if;
    end if;
  end process;
  XIL_NPI_AddrReq           <= npi_addrreq_int;

  -- Data testbench generator
  -- a simple counter for each NPI beat
  -- activated for both writes and reads (to verify returned data)
  DATA_GEN : process (XIL_NPI_Clk, XIL_NPI_Rst, gen_data)
  begin  -- process
    if rising_edge(XIL_NPI_Clk) then
      if XIL_NPI_Rst = '1' then
        data <= (others => '0');
      elsif (gen_data = '1' or compare_enable = '1') then
        data <= data + 1;
      else
        data <= (others => '0');
      end if;
    end if;
  end process;

  -- Testbench compare logic
  COMPARE : process (XIL_NPI_Clk, XIL_NPI_Rst, compare_enable, XIL_NPI_RdFIFO_Data, data)
  begin  -- process
    if rising_edge(XIL_NPI_Clk) then
      if XIL_NPI_Rst = '1' then
        compare_error_i <= '0';
      elsif (compare_enable = '1') and (XIL_NPI_RdFIFO_Data /= data) then
        -- If data does not match during a valid read, set error flag
        compare_error_i <= '1';
      else
        compare_error_i <= compare_error_i;
      end if;
    end if;
  end process;

  Compare_Error <= compare_error_i;

  -- State machine to sequence through NPI transactions
  -- It will perform a cacheline write to address 0 and then perform a
  -- cacheline read to the same address
  -- Typically, this would be broken into separate read and write processes
  -- with some local arbitration for the NPI address request, and each read
  -- and write FIFOs operating independently of each other
  NPI_STATE_NS : process (npi_cs, data, XIL_NPI_AddrAck, XIL_NPI_RdFIFO_Latency, XIL_NPI_RdFIFO_Empty)
  begin
    --default signal values if not overriden by current state
    npi_ns                  <= npi_cs;
    gen_data                <= '0';
    npi_wrfifo_push_i       <= '0';
    npi_req_set             <= '0';
    npi_rnw_i               <= '0';
    npi_size_i              <= "0000";
    npi_wrfifo_be_i         <= "00000000";
    case (npi_cs) is
      when RST     =>
        npi_ns              <= IDLE;
      when IDLE    =>
        -- Start pushing data into write FIFO
        npi_ns              <= TX_DATA;
        gen_data            <= '1';
        npi_wrfifo_push_i   <= '1';
        npi_wrfifo_be_i     <= "11111111";
      when TX_DATA =>
        -- Continue to fill write FIFO until entire burst is in FIFO
        -- This is conservative, a more agressive approach is to rate-
        -- match with memory single data rate relative to NPI rate enough
        -- to prevent underflow of write FIFO
        if (data = "0100") then
          npi_wrfifo_push_i <= '0';
          npi_wrfifo_be_i   <= "00000000";
          gen_data          <= '0';
          -- Start address phase
          npi_ns      <= TX_ADDR;
          npi_req_set <= '1';
          npi_rnw_i   <= '0';
          npi_size_i  <= "0010";
        else
          -- Continue to push data into WrFIFO
          npi_ns             <= TX_DATA;
          npi_wrfifo_push_i  <= '1';
          npi_wrfifo_be_i    <= "11111111";
          gen_data           <= '1';
        end if;
      when TX_ADDR             =>
        -- Hold qualifiers active  until transaction accepted
        -- into MPMC control path
        if XIL_NPI_AddrAck = '1' then
          -- Start read, which starts with the address phase first
          npi_ns             <= RX_ADDR;
          npi_req_set        <= '1';
          npi_rnw_i          <= '1';
          npi_size_i         <= "0010";
        else
          npi_ns             <= TX_ADDR;
          npi_req_set        <= '1';
          npi_rnw_i          <= '0';
          npi_size_i         <= "0010";
        end if;
      when RX_ADDR             =>
        if XIL_NPI_AddrAck = '1' then
          -- Assuming at least one cycle DDR turnaround latency
          -- to simplify logic
          -- Then wait until FIFO reports that it is non-empty
          npi_ns             <= RX_WAIT_NOT_EMPTY;
          npi_req_set        <= '0';
          npi_rnw_i          <= '0';
          npi_size_i         <= "0000";
        else
          npi_ns             <= RX_ADDR;
          npi_req_set        <= '1';
          npi_rnw_i          <= '1';
          npi_size_i         <= "0010";
        end if;
      when RX_WAIT_NOT_EMPTY   =>
        -- Depending on Rd_FIFO_Latency, wait before popping read FIFO
        if XIL_NPI_RdFIFO_Empty = '0' then
          if XIL_NPI_RdFIFO_Latency = "10" then
            npi_ns           <= RX_WAIT_RXFIFO_LAT2;
            npi_rdfifo_pop_i   <= '1';
          elsif XIL_NPI_RdFIFO_Latency = "01" then
            npi_ns           <= RX_WAIT_RXFIFO_LAT1;
            npi_rdfifo_pop_i   <= '1';
          else
            -- Data can be popped now, start compare logic
            npi_ns           <= RX_POP;
            compare_enable   <= '1';
            npi_rdfifo_pop_i <= '1';
          end if;
        else
          npi_ns             <= RX_WAIT_NOT_EMPTY;
        end if;
      when RX_WAIT_RXFIFO_LAT2 =>
        -- First wait state for Latency = 2 
        if XIL_NPI_RdFIFO_Empty = '1' then
          npi_ns             <= RX_WAIT_RXFIFO_LAT2;
        else
          npi_ns             <= RX_WAIT_RXFIFO_LAT1;
        end if;
      when RX_WAIT_RXFIFO_LAT1 =>
        -- Second wait state for Latency = 2
        -- First wait state for Latency = 1
        if XIL_NPI_RdFIFO_Empty = '1' then
          npi_ns             <= RX_WAIT_RXFIFO_LAT1;
        else
           -- Data can be popped now, start compare logic
          npi_ns             <= RX_POP;
          compare_enable     <= '1';
          npi_rdfifo_pop_i   <= '1';
        end if;
      when RX_POP              =>
        -- Continue to pop data until read FIFO empty
        if XIL_NPI_RdFIFO_Empty = '0' then
          npi_ns             <= RX_POP;
          compare_enable     <= '1';
          npi_rdfifo_pop_i   <= '1';
        else
          -- Start over with another write/read
          npi_ns             <= IDLE;
          npi_rdfifo_pop_i   <= '0';
          compare_enable     <= '0';
        end if;
    end case;
  end process;

  -- State machine synchronous logic
  NPI_STATE_SYNC : process (XIL_NPI_Clk, XIL_NPI_Rst, initdone)
  begin
    if rising_edge(XIL_NPI_Clk) then
      if ((XIL_NPI_Rst = '1') or (initdone = '0')) then
        npi_cs <= RST;
      else
        npi_cs <= npi_ns;
      end if;
    end if;
  end process;

end arc_my_npi;

 

What would I need to modify here to write specific data to a specific address? It looks like I would need to place my data on the "XIL_NPI_WrFIFO_Data" vector (looks like signal data also), and my address onto the XIL_NPI_Addr vector, but where should the write_enable signal go?

 

I would appreciate any help people could offer.

 

Thank you,

 

Chris

0 Kudos