Using Xilinx Parameterizable FIFO Macros

XPM or Xilinx Parameterized Macros are simple modules provided by Xilinx that solve common use cases in an HDL flow, such as RAM or ROM, cross domain crossings and FIFOs.

Overview

XPMs are SystemVerilog modules included in Vivado Design Suite, and come in these types:

  • XPM_MEMORY with RAM and ROM memory structures
  • XPM_CDC with various safe cross domain crossing logic implementations
  • XPM_FIFO for synchronous and asynchronous First-In-First-out structures

Using

The simplest way to use these macros is to copy their contents from the language templates window and paste them into your HDL code.

As an example, below is the asynchronous FIFO template version:

xpm_fifo_async_inst : xpm_fifo_async
generic map (
   CDC_SYNC_STAGES => 2,       -- DECIMAL
   DOUT_RESET_VALUE => "0",    -- String
   ECC_MODE => "no_ecc",       -- String
   FIFO_MEMORY_TYPE => "auto", -- String
   FIFO_READ_LATENCY => 1,     -- DECIMAL
   FIFO_WRITE_DEPTH => 2048,   -- DECIMAL
   FULL_RESET_VALUE => 0,      -- DECIMAL
   PROG_EMPTY_THRESH => 10,    -- DECIMAL
   PROG_FULL_THRESH => 10,     -- DECIMAL
   RD_DATA_COUNT_WIDTH => 1,   -- DECIMAL
   READ_DATA_WIDTH => 32,      -- DECIMAL
   READ_MODE => "std",         -- String
   RELATED_CLOCKS => 0,        -- DECIMAL
   SIM_ASSERT_CHK => 0,        -- DECIMAL; 0=disable simulation messages, 1=enable simulation messages
   USE_ADV_FEATURES => "0707", -- String
   WAKEUP_TIME => 0,           -- DECIMAL
   WRITE_DATA_WIDTH => 32,     -- DECIMAL
   WR_DATA_COUNT_WIDTH => 1    -- DECIMAL
)
port map (
   almost_empty => almost_empty,   -- 1-bit output: Almost Empty : When asserted, this signal indicates that
                                   -- only one more read can be performed before the FIFO goes to empty.
   almost_full => almost_full,     -- 1-bit output: Almost Full: When asserted, this signal indicates that
                                   -- only one more write can be performed before the FIFO is full.
   data_valid => data_valid,       -- 1-bit output: Read Data Valid: When asserted, this signal indicates
                                   -- that valid data is available on the output bus (dout).
   dbiterr => dbiterr,             -- 1-bit output: Double Bit Error: Indicates that the ECC decoder
                                   -- detected a double-bit error and data in the FIFO core is corrupted.
   dout => dout,                   -- READ_DATA_WIDTH-bit output: Read Data: The output data bus is driven
                                   -- when reading the FIFO.
   empty => empty,                 -- 1-bit output: Empty Flag: When asserted, this signal indicates that
                                   -- the FIFO is empty. Read requests are ignored when the FIFO is empty,
                                   -- initiating a read while empty is not destructive to the FIFO.
   full => full,                   -- 1-bit output: Full Flag: When asserted, this signal indicates that the
                                   -- FIFO is full. Write requests are ignored when the FIFO is full,
                                   -- initiating a write when the FIFO is full is not destructive to the
                                   -- contents of the FIFO.
   overflow => overflow,           -- 1-bit output: Overflow: This signal indicates that a write request
                                   -- (wren) during the prior clock cycle was rejected, because the FIFO is
                                   -- full. Overflowing the FIFO is not destructive to the contents of the
                                   -- FIFO.
   prog_empty => prog_empty,       -- 1-bit output: Programmable Empty: This signal is asserted when the
                                   -- number of words in the FIFO is less than or equal to the programmable
                                   -- empty threshold value. It is de-asserted when the number of words in
                                   -- the FIFO exceeds the programmable empty threshold value.
   prog_full => prog_full,         -- 1-bit output: Programmable Full: This signal is asserted when the
                                   -- number of words in the FIFO is greater than or equal to the
                                   -- programmable full threshold value. It is de-asserted when the number
                                   -- of words in the FIFO is less than the programmable full threshold
                                   -- value.
   rd_data_count => rd_data_count, -- RD_DATA_COUNT_WIDTH-bit output: Read Data Count: This bus indicates
                                   -- the number of words read from the FIFO.
   rd_rst_busy => rd_rst_busy,     -- 1-bit output: Read Reset Busy: Active-High indicator that the FIFO
                                   -- read domain is currently in a reset state.
   sbiterr => sbiterr,             -- 1-bit output: Single Bit Error: Indicates that the ECC decoder
                                   -- detected and fixed a single-bit error.
   underflow => underflow,         -- 1-bit output: Underflow: Indicates that the read request (rd_en)
                                   -- during the previous clock cycle was rejected because the FIFO is
                                   -- empty. Under flowing the FIFO is not destructive to the FIFO.
   wr_ack => wr_ack,               -- 1-bit output: Write Acknowledge: This signal indicates that a write
                                   -- request (wr_en) during the prior clock cycle is succeeded.
   wr_data_count => wr_data_count, -- WR_DATA_COUNT_WIDTH-bit output: Write Data Count: This bus indicates
                                   -- the number of words written into the FIFO.
   wr_rst_busy => wr_rst_busy,     -- 1-bit output: Write Reset Busy: Active-High indicator that the FIFO
                                   -- write domain is currently in a reset state.
   din => din,                     -- WRITE_DATA_WIDTH-bit input: Write Data: The input data bus used when
                                   -- writing the FIFO.
   injectdbiterr => injectdbiterr, -- 1-bit input: Double Bit Error Injection: Injects a double bit error if
                                   -- the ECC feature is used on block RAMs or UltraRAM macros.
   injectsbiterr => injectsbiterr, -- 1-bit input: Single Bit Error Injection: Injects a single bit error if
                                   -- the ECC feature is used on block RAMs or UltraRAM macros.
   rd_clk => rd_clk,               -- 1-bit input: Read clock: Used for read operation. rd_clk must be a
                                   -- free running clock.
   rd_en => rd_en,                 -- 1-bit input: Read Enable: If the FIFO is not empty, asserting this
                                   -- signal causes data (on dout) to be read from the FIFO. Must be held
                                   -- active-low when rd_rst_busy is active high.
   rst => rst,                     -- 1-bit input: Reset: Must be synchronous to wr_clk. The clock(s) can be
                                   -- unstable at the time of applying reset, but reset must be released
                                   -- only after the clock(s) is/are stable.
   sleep => sleep,                 -- 1-bit input: Dynamic power saving: If sleep is High, the memory/fifo
                                   -- block is in power saving mode.
   wr_clk => wr_clk,               -- 1-bit input: Write clock: Used for write operation. wr_clk must be a
                                   -- free running clock.
   wr_en => wr_en                  -- 1-bit input: Write Enable: If the FIFO is not full, asserting this
                                   -- signal causes data (on din) to be written to the FIFO. Must be held
                                   -- active-low when rst or wr_rst_busy is active high.
);

There is a property that needs to be added to the project to avoid build issues, such as:

[Project 1-486] Could not resolve non-primitive black box cell 'design_1_ctrl_0_0_xpm_fifo_sync' instantiated as 'design_1_i/xpm_fifo_sync_inst' ["/home/.../sources_1/bd/design_1/ipshared/5da6/src/rx_chan/rx_fifo.vhd":260]

For some reason, the error is not seen in all cases. The project property is XPM_LIBRARIES and should be set as:

set_property XPM_LIBRARIES {XPM_FIFO} [current_project]

Caveat

The FIFO behavior is similar to the Xilinx IP Catalog versions though a user guide review of the differences would be wise before using them.

Reset behavior

I learned the hard way that the reset sequence is particularly sensitive to active control signals, such as rd_en and wr_en. If these control signals were active during reset, the FIFO would misbehave sporadically, for example, not going empty on reset and the rst_busy signals never asserting after a while.

The screenshot below was taken from a failure on the field: the rd_busy and empty signals are seen asserting for three reset cycles, and then the FIFO starts misbehaving and they stop asserting on the last two resets. This condition was very hard to spot and diagnose as it happened sporadically once in about 30 reset cycles.

Conclusion

The XPM macros are welcome additions to the IP infrastructure from Xilinx, and the FIFOs are no exception. However, there are a few changes in behavior that are important and need to be taken care of while using these macros to avoid misbehavior as seen above.

Installing Lattice Diamond on Fedora 29

Lattice Diamond is an IDE to design, compile and simulate several families of Lattice FPGA’s. While they support .rpm based...

Previous
Petalinux notes

Petalinux tools provide a reference Linux distribution tailored for Xilinx embedded processors, such as Microblaze™ and Zynq™ devices. It's a...

Next