1

我正在学习 VHDL,并且正在寻求实现自己的 FIFO 缓冲区,但我遇到了一些问题。因为我想在 Xilinx Spartan 6 设备上部署代码,所以我使用 Xilinx WebPack ISE 和相关的 VHDL 编译器,但我收到了非常奇怪的警告:

WARNING:Par:288 - The signal Mram_buf_mem1_RAMD_D1_O has no load. PAR will not attempt to route this signal.

WARNING:Par:283 - There are 1 loadless signals in this design. This design will cause Bitgen to issue DRC warnings.

这是我的代码:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity FIFO_buffer is
    generic ( BUFFER_SIZE : positive := 4; -- # of words
              WORD_WIDTH : positive := 8); -- # of bits per word

    port ( data_in : in  STD_LOGIC_VECTOR (WORD_WIDTH - 1 downto 0);
           full : out  STD_LOGIC := '0';
           write : in  STD_LOGIC;
           data_out : out  STD_LOGIC_VECTOR (WORD_WIDTH - 1 downto 0);
           empty : out  STD_LOGIC := '1';
           read : in  STD_LOGIC);
end FIFO_buffer;

architecture arch of FIFO_buffer is
type ram_t is array (0 to BUFFER_SIZE - 1) of std_logic_vector(WORD_WIDTH - 1 downto 0); 
signal buf_mem : ram_t := (others => (others=>'0'));

signal read_idx : integer range 0 to BUFFER_SIZE  - 1 := 0;
signal write_idx : integer range 0 to BUFFER_SIZE - 1 := 0;
signal buf_full : std_logic := '0';
signal buf_empty : std_logic := '0';

begin
    writing_data: process(write)
    begin
        if(rising_edge(write)) then
            if(buf_full = '0') then
                buf_mem(write_idx) <= data_in;

                write_idx <= write_idx + 1;

                if(write_idx = read_idx) 
                    then buf_full <= '1';
                    else buf_full <= '0'; 
                end if;
            end if;
        end if;
    end process;

    reading_data: process(read)
    begin
        if(rising_edge(read)) then
            if(buf_empty = '0') then
                data_out <= buf_mem(read_idx);

                read_idx <= read_idx + 1;

                if(read_idx = write_idx) 
                    then buf_empty <= '1'; 
                    else buf_empty <= '0'; 
                end if;
            end if; 
        end if;
    end process;

    full <= buf_full;
    empty <= buf_empty;

end arch;

该错误似乎是由data_out <= buf_mem(read_idx);reading_data 过程中的行引起的。谁能向我解释警告的原因?(我知道我的代码有一些功能问题,但这不应该影响警告的原因)

PS 因为我这里有代码,让我再问一个问题。拥有一个与全局时钟不同步的组件(例如 FIFO 缓冲区)有多不明智?

4

1 回答 1

1

我将首先解决您的第二个问题,即“拥有与全局时钟不同步的组件(例如该 FIFO 缓冲区)有多不明智?”

这取决于您的要求。通常,您应该为您的组件提供时钟,这样您就有了同步逻辑,并且不会出现由异步路径引起的奇怪故障。

但是,请考虑您在这里所做的事情。您已经为您的组件计时:rising_edge(read) 和rising_edge(write)。您将在综合报告中找到以下内容:

Primitive and Black Box Usage:
------------------------------
<snip>
# Clock Buffers                    : 2
#      BUFGP                       : 2
<snip>

Clock Information:
------------------
-----------------------------------+------------------------+-------+
Clock Signal                       | Clock buffer(FF name)  | Load  |
-----------------------------------+------------------------+-------+
read                               | BUFGP                  | 11    |
write                              | BUFGP                  | 6     |
-----------------------------------+------------------------+-------+

这是因为您没有使用组合过程。这会导致各种各样的问题。您提到了 Xilinx Spartan-6。假设您没有意外地在最佳 IOB/BUFG 站点对上进行读写操作,您将收到以下消息(通常是错误):

Place:1109 - A clock IOB / BUFGMUX clock component pair have been found
that are not placed at an optimal clock IOB / BUFGMUX site pair. The clock
IOB component <write> is placed at site <A5>. The corresponding BUFG
component <write_BUFGP/BUFG> is placed at site <BUFGMUX_X2Y9>. There is only
a select set of IOBs that can use the fast path to the Clocker buffer, and
they are not being used. You may want to analyze why this problem exists and
correct it.

这条消息非常冗长地解释了以下内容。FPGA 具有专用的时钟路由网络,可确保低偏差。(查看 Xilinx UG382 了解更多信息)。但是,FPGA 上有特定的引脚可以直接访问这个时钟网络。在那里,IOB(I/O 缓冲器)和 BUFG[MUX]([复用] 全局 [时钟] 缓冲器)就在附近,确保来自引脚的信号可以使用专用时钟资源在整个 FPGA 中快速分布。您可以使用 FPGA 编辑器检查布局。例如,我的写管脚必须穿过一半的 FPGA,然后才能使用全局时钟缓冲器进行路由。在我的情况下,这是 3.878ns 的延迟。

当然,这同样适用于阅读。所以你看这是一个坏主意。您应该为时钟使用专用时钟资源,并将输入和输出同步到该时钟。

现在,关于你的主要问题。您必须了解您的 HDL 实际描述的内容。您有两个不同的进程,每个进程都有自己的时钟(读;写)来访问相同的内存。您还有两个不同的地址(write_idx;read_idx)。

因此,XST 合成器(ISE 使用)推断出双端口 RAM。由于深度和元素宽度都很小,因此推断为分布式双端口 RAM。检查你的综合报告,它会说

Found 4x8-bit dual-port RAM <Mram_buf_mem> for signal <buf_mem>.
<snip>
INFO:Xst:3231 - The small RAM <Mram_buf_mem> will be implemented on LUTs in order to maximize performance and save block RAM resources. If you want to force its implementation on block, use option/constraint ram_style.
-----------------------------------------------------------------------
| ram_type           | Distributed                         |          |
-----------------------------------------------------------------------
| Port A                                                              |
|     aspect ratio   | 4-word x 8-bit                      |          |
|     clkA           | connected to signal <write>         | rise     |
|     weA            | connected to signal <full>          | low      |
|     addrA          | connected to signal <write_idx>     |          |
|     diA            | connected to signal <data_in>       |          |
-----------------------------------------------------------------------
| Port B                                                              |
|     aspect ratio   | 4-word x 8-bit                      |          |
|     addrB          | connected to signal <read_idx>      |          |
|     doB            | connected to internal node          |          |
-----------------------------------------------------------------------

当您现在查看技术示意图时,您将看到 XST 推断出三个实例:Mram_buf_mem1、Mram_buf_mem21、Mram_buf_mem22。无论如何,就我而言,您的可能会有所不同。

mram_buf_mem1 是 data_in(5:0) 的输入缓冲区,data_in(6) 和 data_in(7) 实际上分别使用了 Mram_buf_mem21。Mram_buf_mem22。这只是设计没有受到适当约束的产物(读写的时钟周期是多少?等)

所以,基本上你上面的信息

WARNING:Par:288 - The signal Mram_buf_mem1_RAMD_D1_O has no load. PAR will not attempt to route this signal.

表示推断的双端口分布式 RAM 提供的某些输出信号 (D1_O) 未被使用(它不驱动逻辑/触发器)。因此,布局布线 (PAR) 步骤甚至不会尝试布线。有了我们收集的所有这些信息,我们可以放心地假设这无关紧要,并且根本不会影响您的 FIFO。

但是,重要的是以下几点:您没有对两个时钟域(读取域和写入域)之间的路径进行任何限制。这意味着,您可能会遇到 write_idx 在执行读取时发生变化的问题,反之亦然。这可能会让您陷入一种状态,即 full 未被取消断言或 empty 未被断言,因为您缺少需要跨时钟域的信号的同步逻辑。XST 不会为您插入此逻辑。您可以使用异步延迟报告和时钟区域报告检查这些类型的错误。

现在,如果您刚刚开始接触 FPGA 世界,您可能想尝试一下原语推理与原语实例化。查看 Spartan 6 HDL 库指南,了解哪些 VHDL 语言结构会导致 XST 推断出例如 RAM、FIFO、触发器,以及由于一些不切实际的推断时序/区域约束,哪些结构会导致它推断出奇怪和神秘的逻辑结构。

最后,尽量使用同步逻辑并适当约束您的设计。另外,如果你只是在寻找一个简单的两线,那么很抱歉写了这么长的文章……

于 2014-02-15T00:21:42.160 回答