我有一个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())。
答案 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,就好像你在某人阅读或写作时改变它的大小一样,可能会发生不好的事情!