我正在尝试实现类似于here的通用加法器树。为了存储中间结果,我需要声明具有可变位宽的可变数量的信号。例如:
bitwidth = 8的4个输入值:
bitwidth = 8的9个输入值:
我刚刚找到一个解决方案来实例化length = # input values
和bitwidth = 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中输入值的数量?
答案 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位)。