for-generate内部进程vhdl

时间:2014-11-12 05:59:18

标签: vhdl

我知道在进程内部写入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;

3 个答案:

答案 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语句与合成(展开)循环中的另一个语句之间没有依赖关系。他们将iin_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。