我知道在进程内部写入for-generate是不可能的,但我想实现代码所呈现的功能。它基本上是一个地址解码器。任何帮助表示赞赏。
以下代码给出了语法错误:“生成附近的语法错误”
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity address_decoder is
generic (CAM_DEPTH: integer := 8);
port (in_address: in std_logic_vector(CAM_DEPTH-1 downto 0);
out_address: out std_logic_vector(2**CAM_DEPTH-1 downto 0);
clk : in std_logic;
rst: in std_logic
);
end address_decoder;
architecture Behavioral of address_decoder is
begin
decode_process:
process(clk,rst) begin
if(clk'event and clk='1') then
if (rst = '1') then
out_address <= (others => '0');
else
NAME: for i in 0 to 10 generate
if (i = to_integer(unsigned(in_address))) then
out_address(i) <= '1';
else
out_address(i) <= '0';
end if;
end generate NAME;
end if;
end if;
end process;
end Behavioral;
答案 0 :(得分:9)
使用循环语句:
decode_process:
process(clk) -- synchronous reset, no rst in sensitivity list
begin
if clk'event and clk = '1' then
if rst = '1' then
out_address <= (others => '0');
else
for i in 0 to 10 loop
if i = to_integer(unsigned(in_address)) then
out_address(i) <= '1';
else
out_address(i) <= '0' ;
end if;
end loop;
-- name: for i in 0 to 10 generate
-- if (i = to_integer(unsigned(in_address))) then
-- out_address(i) <= '1';
-- else
-- out_address(i) <= '0';
-- end if;
-- end generate name;
end if;
end if;
end process;
另请注意rst
已从敏感列表中删除,它被写为同步重置。
可以合成一个循环语句,现在请参阅已废除的IEEE Std 1076.6-2004 8.8.9,语法,顺序语句,循环语句或您的特定综合供应商的工具文档。循环中的顺序语句将针对循环参数的每个值进行复制,该参数被视为常量。
那么生成迭代和循环迭代之间的区别是什么?
模拟周期甚至在顺序语句中(例如在过程中)模拟信号分配的并发性。一个if语句与合成(展开)循环中的另一个语句之间没有依赖关系。他们将i
个in_address
个识别器与i
和in_address进行比较,每个地址提供一位out_address
。第一个分配a(0)
,第二个分配a(1)
...在这种情况下,循环语句将产生与生成语句相同的逻辑(使用条件信号赋值,尽管顺序逻辑(时钟)语义会让它看起来很尴尬)。
让我们将它与在适当位置的并发语句中使用generate语句进行比较:
architecture foo of address_decoder is
function to_std_ulogic (inp: boolean) return std_ulogic is
begin
if inp = TRUE then
return '1';
else
return '0';
end if;
end;
begin
decoder:
for i in 0 to 10 generate
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end generate;
end architecture;
为了简洁起见,在to_std_ulogic
的条件信号赋值语句中添加了一个带有布尔参数的函数out_address(i)
。
这看起来很好而且紧凑,可能会合成,具体取决于使用将布尔值转换为std_ulogic的函数的能力。
然而,它扩展了详细说明:
architecture fum of address_decoder is
function to_std_ulogic (inp: boolean) return std_ulogic is
begin
if inp = TRUE then
return '1';
else
return '0';
end if;
end;
begin
decoder0:
block
constant i: integer := 0;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder1:
block
constant i: integer := 1;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder2:
block
constant i: integer := 2;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder3:
block
constant i: integer := 3;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder4:
block
constant i: integer := 4;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder5:
block
constant i: integer := 5;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder6:
block
constant i: integer := 6;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder7:
block
constant i: integer := 7;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder8:
block
constant i: integer := 8;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder9:
block
constant i: integer := 9;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
decoder10:
block
constant i: integer := 10;
begin
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)))
when clk'event and clk = '1';
end block;
end architecture;
更糟糕的是,每个块语句并发条件信号赋值语句都成为以下形式的进程语句:
decoder10:
block
constant i: integer := 10;
begin
process
begin
if clk'event and clk = '1' then
out_address(i) <= to_std_ulogic(i = to_integer(unsigned(in_address)));
end if;
wait on clk, in_address;
end process;
所以现在突然而不是模拟一个进程,你有11个进程,每个进程对clk和in_address都很敏感,这意味着进程变得比两个时钟边缘更活跃。
因此,在精化和合成之后,循环语句和等效的generate语句不仅会产生相同的硬件,因此保证循环语句在模拟中更快,这是它的预期目的。
VHDL设计规范中的所有内容都转换为块语句,流程语句和子程序(函数,过程)。并发程序也已下放,而函数则是表达式。
它保证了合成首先阐述了设计。在这种情况下,generate语句和包含循环的单个进程之间的合成差异是分组。除非合成工具接受允许展平的属性(例如,DISSOLVE_HIERARCHY作为生成语句的属性),否则将单独翻译流程语句。
在单个流程案例的循环语句中,您可以默认在10个信号分配之间共享地址识别器逻辑,从而可能产生更少的逻辑。
因此,在合成方面可能没什么区别,但在模拟方面存在显着差异,其中实际影响取决于设计的大小。
答案 1 :(得分:0)
您的解码器只是具有下游寄存器的二进制到单热编码器。 因此,您可以提取编码器并将其放入函数
function bin2onehot(value : std_logic_vector) return std_logic_vector is
variable result : std_logic_vector(2**value'length - 1 downto 0) := (others => '0');
begin
result(2 ** to_integer(unsigned(value))) := '1';
return result;
end function;
这是你的注册:
process(clk)
begin
if rising_edge(clk) then
if (rst = '1') then
out_address <= (others => '0');
else
out_address <= bin2onehot(in_address);
end if;
end if;
end process;
您可以从敏感度列表中保留rst
,因为它是同步重置。
答案 2 :(得分:0)
就像添加到以前的答案一样,
GENERATE语句是并发语句,它只能在体系结构级别使用。
PROCESS块可以是顺序/并发的,所以我想因为这个原因,在PROCESS块中不允许GENERATE。