ハミング重み / VHDL

pp.257-258

内部信号を一種の変数として使う。

inp_vector = 0b11110011の場合:
1回目のループ: inp_vector[0]に1が立っているので internal[1]にinternal[0]+1 = 1を入れる。
2回目のループ: inp_vector[1]に1が立っているので internal[2]にinternal[1]+1 = 2を入れる。
3回目のループ: inp_vector[2]に1が立っていないのでinternal[3]にinternal[2] = 2を入れる。
4回目のループ: inp_vector[3]に1が立っていないのでinternal[4]にinternal[3] = 2を入れる。
5回目のループ: inp_vector[4]に1が立っているので internal[5]にinternal[4]+1 = 3を入れる。
6回目のループ: inp_vector[5]に1が立っているので internal[6]にinternal[5]+1 = 4を入れる。
7回目のループ: inp_vector[6]に1が立っているので internal[7]にinternal[6]+1 = 5を入れる。
8回目のループ: inp_vector[7]に1が立っているので internal[8]にinternal[7]+1 = 6を入れる。
......

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity hamming_weight_calculator is
    generic(
        BITS_IN : positive := 16; -- 入力を16ビットとすると、ハミング重みは最大16なので、
        BITS_OUT: positive := 5   -- 出力は最大0b10000、すなわち5ビット = ceil(log2(BITS_IN+1))
    );
    port(
        inp_vector : in  std_logic_vector(BITS_IN -1 downto 0);
        hamm_weight: out std_logic_vector(BITS_OUT-1 downto 0)
    );
end entity;

architecture rtl of hamming_weight_calculator is
   -- {int[0], int[1], ..., int[16]}という1Dx1D排列型integer_arrayを定義して、
   -- その型の信号internalを宣言する。
   -- 要するに途中の計算結果を入れておくための信号(内部変数として使う)を16個用意しておく。
    type integer_array is array(0 to BITS_IN) of integer range 0 to BITS_IN;
    signal internal: integer_array;
begin
    internal(0) <= 0;
    
    gen: for i in 1 to BITS_IN generate
        internal(i) <= internal(i-1) + 1 when inp_vector(i-1) else internal(i-1);
    end generate;
    
   -- internal(16)を5ビット幅のunsingedに変換して、それをさらにベクタに変換する。
    hamm_weight <= std_logic_vector(to_unsigned(internal(BITS_IN), BITS_OUT));
end architecture;