在std_logic_vector字节上合成动态多路复用器

时间:2013-10-02 12:16:58

标签: vhdl synthesis

我有一个FIFO,其大小是根据包中的参数确定的:

signal fifo : std_logic_vector(FIFO_SIZE*8 -1 downto 0);

我还有一个4位向量(numOfBytes),表示在任何给定时间(最多8个)FIFO中有多少字节。
我希望根据numOfBytes信号确定FIFO中的数据(单个字节):
Do <= fifo(to_integer(unsigned(numOfBytes)*8 -1 downto to_integer(unsigned(numOfBytes)*8 -8) when numOfBytes /= x"0" else (others => '0');
在模拟时,这很有效,但是当我尝试合成它时(使用Synopsys DC),我在链接设计时说“需要恒定值(ELAB-922)”时会出现详细错误。

ELAB代码表示“出现此错误消息是因为RTL描述的指示行中的表达式未按语言要求计算为常量值。”

如何才能使输出多路复用器进行合成? 如果没有参数,我会将Do行更改为常规多路复用,但它不能用于参数。 (当fifo是4字节时,我无法调用fifo(63 downto 54)...)

P.S。 我尝试在开始时使用conv_integer,但由于在网络上找到了答案,因此更改为to_integer(unsigned())。

3 个答案:

答案 0 :(得分:2)

用于构造范围的信号索引必须是编译时常量才能合成以接受它们。

有两种方法可以解决这个问题:

1)更改FIFO以使用阵列。这是声明任何形式存储器的标准方式,例如FIFO。

type fifo_type is array(0 to FIFO_SIZE-1) of std_logic_vector(8-1 downto 0);
signal fifo : fifo_type;
...
Do <= fifo(to_integer(unsigned(numOfBytes))-1) when(numOfBytes/=0) else (others=>'0');

2)使用循环将变量转换为常量。这是编写通用多路复用器的常用方法。

Do <= (others=>'0');
for i in 0 to FIFO_SIZE-1 loop
    if(numOfBytes=i+1) then
        Do <= fifo((i+1)*8-1 downto i*8);
    end if;
end loop;

我建议第一种方法用于较大的基于存储器的FIFO,第二种用于较小的基于寄存器的方法。

答案 1 :(得分:1)

如果使用多个字节创建FIFO,而不是将其组合到相同的std_logic_vector,那么Synopsys DC可能能够处理它。代码可能如下所示:

library ieee;
use ieee.numeric_std.all;

architecture syn of mdl is

  ... Declaration of FIFO_SIZE natural constant

  type fifo_t is array(natural range <>) of std_logic_vector(7 downto 0);
  signal fifo : fifo_t(FIFO_SIZE - 1 downto 0);

begin

  ... Handling FIFO insert and remove

  Do <= fifo(to_integer(unsigned(numOfBytes))) when numOfBytes /= x"0" else (others => '0');

end architecture;

答案 2 :(得分:0)

如果您不需要FIFO的运行时动态大小,请在您的实体上使用generic

如果你真的需要一个动态大小的FIFO,你将不得不像其他人所说的那样在进程中使用循环。但要非常小心你如何使用这样的FIFO,就好像你在某人阅读或写作时改变它的大小一样,可能会发生不好的事情!