Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- library IEEE;
- use IEEE.STD_LOGIC_1164.ALL;
- use IEEE.NUMERIC_STD.ALL;
- entity HDC_Controller is
- generic (
- D : integer := 10000;
- N : integer := 32;
- M : integer := 200;
- A : integer := 5
- );
- Port (
- clk : in STD_LOGIC;
- reset : in STD_LOGIC;
- start : in STD_LOGIC;
- done : out STD_LOGIC;
- feature_value : in STD_LOGIC_VECTOR(15 downto 0);
- feature_valid : in STD_LOGIC;
- similarity_counter_out : out STD_LOGIC_VECTOR(7 downto 0);
- mem_sel : in STD_LOGIC_VECTOR(1 downto 0); -- 00=IM, 01=CM, 10=AM
- mem_we : in STD_LOGIC;
- mem_addr : in STD_LOGIC_VECTOR(15 downto 0);
- mem_data_in : in STD_LOGIC_VECTOR(31 downto 0);
- mem_data_out : out STD_LOGIC_VECTOR(31 downto 0);
- done_encoding_monitor : out STD_LOGIC
- );
- end HDC_Controller;
- architecture Behavioral of HDC_Controller is
- function rotate_right(signal in_vec : STD_LOGIC_VECTOR; shift : integer) return STD_LOGIC_VECTOR is
- variable len : natural := in_vec'length;
- variable result : STD_LOGIC_VECTOR(in_vec'range);
- variable base : natural := in_vec'low;
- variable newpos : natural;
- begin
- for i in 0 to len-1 loop
- newpos := (i + shift);
- if newpos >= len then
- newpos := newpos - len; -- schneller als mod
- end if;
- result(i + base) := in_vec(newpos + base);
- end loop;
- return result;
- end function;
- type popcount_array_t is array (0 to 15) of std_logic_vector(3 downto 0);
- constant popcount_lut : popcount_array_t := (
- "0000", -- 0
- "0001", -- 1
- "0010", -- 2
- "0011", -- 3
- "0100", -- 4
- "0101", -- 5
- "0110", -- 6
- "0111", -- 7
- "1000", -- 8
- "1001", -- 9
- "1010", -- 10
- "1011", -- 11
- "1100", -- 12
- "1101", -- 13
- "1110", -- 14
- "1111" -- 15
- );
- function popcount4(v : std_logic_vector(3 downto 0)) return integer is
- begin
- return to_integer(unsigned(popcount_lut(to_integer(unsigned(v)))));
- end function;
- -- Statt full 256-bit XOR → sequenziell 4-bit Popcount verwenden
- signal xor_chunk : std_logic_vector(3 downto 0);
- constant SEG_WIDTH : integer := 256;
- constant WORD_WIDTH : integer := 32;
- constant NUM_SEGMENTS : integer := D / SEG_WIDTH;
- constant CHUNKS_PER_VEC : integer := (D + WORD_WIDTH - 1) / WORD_WIDTH; -- 313
- type feature_array_t is array(0 to N-1) of STD_LOGIC_VECTOR(15 downto 0);
- signal feature_buffer : feature_array_t;
- signal feature_load_index : integer range 0 to N := 0;
- signal features_ready : STD_LOGIC := '0';
- signal feature_values_packed : STD_LOGIC_VECTOR(N*16-1 downto 0);
- signal bundled_result, bundled_result_accumulator : STD_LOGIC_VECTOR(D-1 downto 0);
- signal chunk_counter : unsigned(2 downto 0) := (others => '0');
- signal similarity_counter : unsigned(7 downto 0) := (others => '0');
- signal global_counter : unsigned(7 downto 0) := (others => '0');
- signal memory_index : unsigned(2 downto 0) := (others => '0');
- signal closest_memory_index : unsigned(2 downto 0) := (others => '0');
- signal final_accumulation : STD_LOGIC_VECTOR(D-1 downto 0) := (others => '0');
- signal bit_index : integer range 0 to SEG_WIDTH-1 := 0;
- signal xor_bit : std_logic;
- signal popcount_add_en : std_logic := '0';
- signal done_encoding : STD_LOGIC := '0';
- signal compare_state : integer range 0 to 6 := 0;
- signal segment_index : integer range 0 to NUM_SEGMENTS-1 := 0;
- signal word_index : integer range 0 to CHUNKS_PER_VEC-1 := 0;
- signal xor_result : STD_LOGIC_VECTOR(SEG_WIDTH-1 downto 0);
- signal partial_hamming : unsigned(15 downto 0) := (others => '0');
- signal min_hamming_distance : unsigned(15 downto 0) := (others => '1');
- signal im_we, cm_we, am_we : std_logic;
- signal im_addr, cm_addr, am_addr : std_logic_vector(15 downto 0):= (others => '0');
- signal im_data_in, cm_data_in, am_data_in : std_logic_vector(31 downto 0);
- signal im_data_out, cm_data_out, am_data_out : std_logic_vector(31 downto 0);
- signal am_buffer : STD_LOGIC_VECTOR(D-1 downto 0) := (others => '0');
- signal popcount_step : integer range 0 to SEG_WIDTH/32 - 1 := 0;
- signal pop_accumulator : unsigned(15 downto 0) := (others => '0');
- signal am_addr_internal : std_logic_vector(15 downto 0):= (others => '0');
- signal use_internal_am_addr : std_logic := '0';
- component Accelerator
- generic (
- D : integer := 10000;
- N : integer := 32;
- M : integer := 200
- );
- Port (
- clk : in STD_LOGIC;
- reset : in STD_LOGIC;
- feature_values : in STD_LOGIC_VECTOR(N*16-1 downto 0);
- start : in STD_LOGIC;
- done : out STD_LOGIC;
- encoded_hv_ready : out STD_LOGIC;
- bundled_result : out STD_LOGIC_VECTOR(D-1 downto 0);
- im_we : in STD_LOGIC;
- im_addr : in STD_LOGIC_VECTOR(15 downto 0);
- im_data_in : in STD_LOGIC_VECTOR(31 downto 0);
- cm_we : in STD_LOGIC;
- cm_addr : in STD_LOGIC_VECTOR(15 downto 0);
- cm_data_in : in STD_LOGIC_VECTOR(31 downto 0);
- im_data_out : out STD_LOGIC_VECTOR(31 downto 0);
- cm_data_out : out STD_LOGIC_VECTOR(31 downto 0)
- );
- end component;
- component AssociativeMemory
- Port (
- clk : in STD_LOGIC;
- we : in STD_LOGIC;
- am_addr : in STD_LOGIC_VECTOR(15 downto 0);
- am_data_in : in STD_LOGIC_VECTOR(31 downto 0);
- am_data_out : out STD_LOGIC_VECTOR(31 downto 0)
- );
- end component;
- begin
- -- Demultiplex Speicherzugriff basierend auf mem_sel
- im_we <= mem_we when mem_sel = "00" else '0';
- cm_we <= mem_we when mem_sel = "01" else '0';
- am_we <= mem_we when mem_sel = "10" else '0';
- im_addr <= mem_addr when mem_sel = "00" else (others => '0');
- cm_addr <= mem_addr when mem_sel = "01" else (others => '0');
- -- AM-Adressmultiplex
- am_addr <= am_addr_internal when use_internal_am_addr = '1' else
- mem_addr when mem_sel = "10" else
- (others => '0');
- im_data_in <= mem_data_in;
- cm_data_in <= mem_data_in;
- am_data_in <= mem_data_in;
- with mem_sel select
- mem_data_out <= im_data_out when "00",
- cm_data_out when "01",
- am_data_out when "10",
- (others => '0') when others;
- done_encoding_monitor <= done_encoding;
- accelerator_unit: Accelerator
- generic map ( D => D, N => N, M => M )
- port map (
- clk => clk,
- reset => reset,
- feature_values => feature_values_packed,
- start => start,
- done => done_encoding,
- encoded_hv_ready => open,
- bundled_result => bundled_result,
- im_we => im_we,
- im_addr => im_addr,
- im_data_in => im_data_in,
- cm_we => cm_we,
- cm_addr => cm_addr,
- cm_data_in => cm_data_in,
- im_data_out => im_data_out,
- cm_data_out => cm_data_out
- );
- associative_memory_unit: AssociativeMemory
- port map (
- clk => clk,
- we => am_we,
- am_addr => am_addr,
- am_data_in => am_data_in,
- am_data_out => am_data_out
- );
- process(clk, reset)
- variable pop : integer := 0;
- begin
- if reset = '1' then
- feature_load_index <= 0;
- features_ready <= '0';
- bundled_result_accumulator <= (others => '0');
- chunk_counter <= (others => '0');
- compare_state <= 0;
- memory_index <= (others => '0');
- similarity_counter <= (others => '0');
- closest_memory_index <= (others => '0');
- segment_index <= 0;
- partial_hamming <= (others => '0');
- min_hamming_distance <= (others => '1');
- done <= '0';
- word_index <= 0;
- elsif rising_edge(clk) then
- if feature_valid = '1' and features_ready = '0' then
- feature_values_packed((feature_load_index+1)*16-1 downto feature_load_index*16) <= feature_value;
- if feature_load_index = N-1 then
- features_ready <= '1';
- feature_load_index <= 0;
- else
- feature_load_index <= feature_load_index + 1;
- end if;
- else
- features_ready <= '0';
- end if;
- case compare_state is
- when 0 =>
- if done_encoding = '1' then
- bundled_result_accumulator <= bundled_result_accumulator xor rotate_right(bundled_result, to_integer(chunk_counter));
- chunk_counter <= chunk_counter + 1;
- if chunk_counter = to_unsigned(4, chunk_counter'length) then
- global_counter <= global_counter + 1;
- compare_state <= 1;
- memory_index <= (others => '0');
- chunk_counter <= (others => '0');
- word_index <= 0;
- bundled_result_accumulator <= (others => '0');
- final_accumulation <= bundled_result_accumulator;
- am_buffer <= (others => '0');
- end if;
- end if;
- when 1 =>
- am_addr_internal <= std_logic_vector(to_unsigned(to_integer(memory_index) * (CHUNKS_PER_VEC) + word_index, 16));
- use_internal_am_addr <= '1';
- compare_state <= 2;
- when 2 =>
- compare_state <= 3;
- when 3 =>
- if word_index = CHUNKS_PER_VEC - 1 then
- -- Sonderbehandlung für die letzten 16 Bit (die obersten 16 Bits vom letzten 32-Bit-Block)
- am_buffer(15 downto 0) <= am_data_out(31 downto 16);
- -- Zustand zurücksetzen
- word_index <= 0;
- segment_index <= 0;
- partial_hamming <= (others => '0');
- compare_state <= 4;
- else
- -- Speicherblock rückwärts schreiben
- -- z. B. word_index=0 → D-1 downto D-256
- -- word_index=1 → D-257 downto D-512
- am_buffer(D-1 - word_index*WORD_WIDTH downto D - (word_index+1)*WORD_WIDTH) <= am_data_out;
- -- Weiterzählen
- word_index <= word_index + 1;
- compare_state <= 1;
- end if;
- when 4 =>
- xor_result <= final_accumulation((segment_index+1)*SEG_WIDTH -1 downto segment_index*SEG_WIDTH)
- xor am_buffer((segment_index+1)*SEG_WIDTH -1 downto segment_index*SEG_WIDTH);
- pop := 0;
- for i in 0 to SEG_WIDTH/4 - 1 loop
- xor_chunk <= xor_result(i*4+3 downto i*4);
- pop := pop + popcount4(xor_chunk);
- end loop;
- partial_hamming <= partial_hamming + to_unsigned(pop, 16);
- if segment_index = NUM_SEGMENTS - 1 then
- compare_state <= 5;
- else
- segment_index <= segment_index + 1;
- end if;
- when 5 =>
- if partial_hamming < min_hamming_distance then
- min_hamming_distance <= partial_hamming;
- closest_memory_index <= memory_index;
- end if;
- if memory_index = to_unsigned(4, 3) then
- if closest_memory_index = "010" then
- similarity_counter <= similarity_counter + 1;
- end if;
- compare_state <= 6;
- else
- memory_index <= memory_index + 1;
- word_index <= 0;
- compare_state <= 1;
- end if;
- when 6 =>
- similarity_counter_out <= std_logic_vector(similarity_counter);
- done <= '1';
- compare_state <= 0;
- min_hamming_distance <= (others => '1');
- end case;
- end if;
- end process;
- end Behavioral;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement