Declare a variable number of signals with variable bitwidth in VHDL'93

守給你的承諾、 提交于 2020-01-25 09:30:07

问题


I'm trying to implement an generic adder tree similar to here. For storing the intermediate results, I need to declare a variable number of signals with variable bitwidth. For example:

4 input values with bitwidth = 8:

  1. after first stage: 2 values with bitwidth = 9
  2. after second stage: 1 value with bitwidth = 10

9 input values with bitwidth = 8:

  1. after first stage: 5 values with bitwidth = 9
  2. after second stage: 3 values with bitwidth = 10
  3. after third stage: 2 values with bitwidth = 11
  4. after forth stage: 1 value with bitwidth = 12

I just found one solution to instantiate an array with length = # input values and bitwidth = bitwidth of the last signal. But I want to have something like the following. A record including the values of each stage concatenated to an std_logic_vector, but it's obviously not working:

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;

Is it possible to declare a variable amount of signals with increasing bitwidth and dependent on the number of input values in VHDL '93?


回答1:


Contrary to NiM's assertion that it's impossible to declare a variable amount of signals with increasing bitwidth and dependent on the number of input values in any version (revision) of VHDL, it is possible in -2008.

The secret is to use component instantiation recursion with an input port whose type is an unbounded array with an element subtype indication provided in the object declaration. The number of inputs and their length can be changed (number of inputs down, element subtype length up) in successive recursion levels. The output port is of a constant width and is driven by the lowest level adder output.

Defining an unbounded array definition with a deferred element subtype indication is not supported in -1993.

This code hasn't been verified other than guaranteeing the lengths and numbers of levels work correctly. It uses unsigned arithmetic because the OP didn't specify otherwise. Resize is used to increase the adder result length.

The report statements were used for debugging and can be removed (amazing how many simple errors you can make in something only mildly convoluted).

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;

This example doesn't meet the criteria for answering Yes to the OP's question (which is a yes/no question) and simply refutes NiM's assertion that you can't do it in any version (revision) of VHDL.

It's ports are inspired by the Pipelined Adder Tree VHDL code found by the image the OP linked.




回答2:


What you are asking for is not possible in any version of VHDL, v93 or otherwise. You can define a type inside a generate statement, but not use a generate within a type definition.

Your initial solution is the way that I would do it personally - if targeting an FPGA using modern tools the unused MSBs at each stage will be optimised away during synthesis, so the resulting circuit is as you've described with no additional overhead (i.e. the tools are clever enough to know that adding two 8-bit numbers can never occupy more than 9 bits).



来源:https://stackoverflow.com/questions/49981526/declare-a-variable-number-of-signals-with-variable-bitwidth-in-vhdl93

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!