在VHDL'93中声明具有可变位宽的可变数量的信号

时间:2018-04-23 12:49:32

标签: vhdl

我正在尝试实现类似于here的通用加法器树。为了存储中间结果,我需要声明具有可变位宽的可变数量的信号。例如:

bitwidth = 8的4个输入值:

    第一阶段后的
  1. :bitwidth = 9
  2. 的2个值
  3. 在第二阶段之后:1位值,位宽= 10
  4. bitwidth = 8的9个输入值:

      第一阶段后的
    1. :bitwidth = 9
    2. 的5个值
    3. 在第二阶段之后:3个值,位宽= 10
    4. 在第三阶段之后:2个值,其中bitwidth = 11
    5. 在第四阶段之后:1位值,位宽= 12
    6. 我刚刚找到一个解决方案来实例化length = # input valuesbitwidth = bitwidth of the last signal的数组。但我希望得到以下内容。包含连接到std_logic_vector的每个阶段的值的记录,但显然不起作用:

      lb(INPUT_VALUES) == number of stages

      nr_val(i) == number of values at stage -> calculated in a separate function

      type adder_stages is record
        for i in 1 to lb(INPUT_VALUES) generate
          stage(i-1) : std_logic_vector(nr_val(i)*(BITWIDTH+i)-1 downto 0);
        end generate;
      end record adder_stages;
      

      是否可以通过增加位宽来声明可变数量的信号,并且取决于VHDL '93中输入值的数量?

2 个答案:

答案 0 :(得分:2)

与NiM的断言相反,在VHDL的任何版本(修订版)中都不可能declare a variable amount of signals with increasing bitwidth and dependent on the number of input values,这可能是在2008年。

秘诀是使用组件实例化递归和输入端口,该输入端口的类型是无界数组,并且在对象声明中提供了元素子类型指示。在连续的递归级别中,可以改变输入的数量及其长度(输入的数量,元素子类型的长度)。输出端口具有恒定宽度,由最低级别的加法器输出驱动。

在-1993中不支持使用延迟元素子类型指示定义无界数组定义。

除了保证级别的长度和数量正常工作之外,此代码尚未经过验证。它使用无符号算术,因为OP没有另外指定。调整大小用于增加加法器结果长度。

报告语句用于调试,可以删除(令人惊讶的是,你可以在一些只有轻微错综复杂的事情中做出多少简单的错误。)

library ieee;
use ieee.std_logic_1164.all;

package adder_tree_pkg is  
    function clog2 (n: positive) return natural;
    type input_array is array (natural range <>) of
               std_logic_vector; --  -2008 unbounded array definition
    function isodd (n: positive) return natural;
end package;

package body adder_tree_pkg is
    function clog2 (n: positive) return natural is
        variable r: natural := 0;
        variable m: natural := n - 1;
    begin
        while m /= 0 loop
            r := r + 1; 
            m := m / 2;
        end loop;
        return r;
    end function clog2;

    function isodd (n: positive) return natural is
    begin
        if (n/2 * 2 < n) then
            return 1;
        else 
            return 0;
        end if;
    end function;
end package body;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;

use work.adder_tree_pkg.all;

entity adder_tree_level is
    generic (
        constant INPUTS:  positive := 9;
        constant BITS:    positive := 8;
        constant LEVEL:   positive  := clog2(INPUTS);
        constant Y_OUT_LEN: positive := LEVEL + BITS
    );
    port (
        clk:    in  std_logic;
        rst_n:  in  std_logic;
        x_in:   in  input_array (INPUTS - 1 downto 0) (BITS - 1 downto 0);
        y_out:  out std_logic_vector (Y_OUT_LEN - 1 downto 0)
    );
end entity;

architecture foo of adder_tree_level is
    constant ODD_NUM_IN:    natural := isodd(INPUTS);
    constant NXT_INPS:  natural := INPUTS/2 + ODD_NUM_IN;

    signal x:           input_array (INPUTS - 1 downto 0) (BITS - 1 downto 0);
    signal nxt_x:       input_array (NXT_INPS - 1 downto 0)
                                    (BITS downto 0);
    constant NPAIRS:    natural  := (INPUTS)/2;
begin
INPUT_REGISTER:
    process (clk, rst_n)

    begin
        if rst_n = '0' then
            x <= (others =>(others => '0')); 
        elsif rising_edge (clk) then
            x <= x_in;
        end if;
    end process;

ADDERS: 
    process (x)
    begin
        report "LEVEL = " & integer'image(LEVEL);
        report "y_out'length = " & integer'image(y_out'length);
        report "nxt_x(0)'length = " & integer'image(nxt_x(0)'length);
        for i in 0 to NPAIRS - 1 loop  -- odd out is x'high ('left)
            nxt_x(i) <= resize(x(i * 2), BITS + 1) + x(i * 2 + 1);
            report "i * 2 = " & integer'image (i * 2);
            report "i * 2 + 1 = " & integer'image (i * 2 + 1);
        end loop;
        if ODD_NUM_IN = 1 then
            report "x'left = " & integer'image(x'left);
            nxt_x(nxt_x'HIGH) <= resize(x(x'LEFT), BITS + 1);
        end if;
    end process;
RECURSE:
    if LEVEL > 1 generate 
NEXT_LEVEL:
        entity work.adder_tree_level
        generic map (
            INPUTS => NXT_INPS,
            BITS => BITS + 1,
            LEVEL => LEVEL - 1,
            Y_OUT_LEN => Y_OUT_LEN
        )
        port map (
            clk => clk,
            rst_n => rst_n,
            x_in => nxt_x,
            y_out => y_out
        );
    end generate;
OUTPUT: 
   if LEVEL = 1 generate
FINAL_OUTPUT:
        y_out <= nxt_x(0);
    end generate;
end architecture;

这个例子不符合回答OP的问题(是yes/no question)的标准,只是驳斥了NiM的断言,你不能在VHDL的任何版本(修订版)中做到这一点。 / p>

它的端口受到Pipelined Adder Tree OP链接的image VHDL代码的启发。

答案 1 :(得分:0)

在任何版本的VHDL,v93或其他版本中都无法满足您的要求。您可以在generate语句中定义类型,但不能在类型定义中使用generate。

您的初始解决方案就是我个人的方式 - 如果使用现代工具瞄准FPGA,每个阶段未使用的MSB将在合成期间被优化掉,因此产生的电路就像您所描述的那样没有额外的开销(即工具很聪明,知道添加两个8位数字永远不会占用超过9位)。