Hello,

I would say that, in your case, it would be best to use the "unsigned" notation for the data.

You could keep the address pointers in integer notation.

Calculating the required number of bits for the accumulator can be straight forward.

constant MY_ACC_WIDTH : integer := INPUT_WIDTH + NUM_OF_ACCS_LOG2;

signal my_unsigned : unsigned(MY_ACC_WIDTH-1 downto 0);

signal my_acc : unsigned(MY_ACC_WIDTH-1 downto 0); -- Single accumulator

-- Accumulator RAM

type type_acc_ram is array(integer range 0 to RAM_SIZE-1) of unsigned(MY_ACC_WIDTH-1 downto 0);

signal my_acc_ram : type_acc_ram := (others => (others => '0'));

In case your input is an integer, you just have to cast it into an equivalent unsigned vector.

Note: In order not to truncate any information and to simplify subsequent operations, you may use the full accumulator width for all your operations.

The synthesis tool (in most cases) should be smart enough to eliminate any bits tied to 'zero' or to 'one'.

If you are using the numeric_std library, you can use the following casts/conversions.

-- integer to unsigned

my_unsigned <= to_unsigned(my_int, my_unsigned'length);

-- unsigned to integer

my_int <= to_integer(my_unsigned);

-- resize (if unsigned: pads with zeros, if signed: performs sign extension)

my_new_unsigned <= resize(my_old_unsigned, my_new_unsigned'length);

Note: If your number of accumulations is a power of 2, (e.g. 2**1

you just have to use NUM_OF_ACCS_LOG2 = 18;

If it's not the case you might need to calculate NUM_OF_ACCS_LOG2; it can be done as such.

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

use ieee.math_real.all; -- Only required if you need to calculated the log2

-- ...

constant NUM_OF_ACCS_LOG2 : integer := integer(ceil(log2(real(NUM_OF_ACCS))));

The "real" data types are not used for synthesis, but just for calculating ranges.

Note: You might be able to calculate the log2 in a different way by defining a looping function (instead of using the "real" type).

I hope this helps,

Cheers !