Advertisement
Guest User

Untitled

a guest
May 11th, 2025
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VHDL 12.85 KB | None | 0 0
  1. library IEEE;
  2. use IEEE.STD_LOGIC_1164.ALL;
  3. use IEEE.NUMERIC_STD.ALL;
  4.  
  5. entity HDC_Controller is
  6.     generic (
  7.         D : integer := 10000;
  8.         N : integer := 32;
  9.         M : integer := 200;
  10.         A : integer := 5
  11.     );
  12.     Port (
  13.         clk : in STD_LOGIC;
  14.         reset : in STD_LOGIC;
  15.         start : in STD_LOGIC;
  16.         done : out STD_LOGIC;
  17.         feature_value : in STD_LOGIC_VECTOR(15 downto 0);
  18.         feature_valid : in STD_LOGIC;
  19.         similarity_counter_out : out STD_LOGIC_VECTOR(7 downto 0);
  20.  
  21.         mem_sel      : in  STD_LOGIC_VECTOR(1 downto 0); -- 00=IM, 01=CM, 10=AM
  22.         mem_we       : in  STD_LOGIC;
  23.         mem_addr     : in  STD_LOGIC_VECTOR(15 downto 0);
  24.         mem_data_in  : in  STD_LOGIC_VECTOR(31 downto 0);
  25.         mem_data_out : out STD_LOGIC_VECTOR(31 downto 0);
  26.         done_encoding_monitor : out STD_LOGIC
  27.     );
  28. end HDC_Controller;
  29.  
  30. architecture Behavioral of HDC_Controller is
  31.  
  32.     function rotate_right(signal in_vec : STD_LOGIC_VECTOR; shift : integer) return STD_LOGIC_VECTOR is
  33.     variable len    : natural := in_vec'length;
  34.     variable result : STD_LOGIC_VECTOR(in_vec'range);
  35.     variable base   : natural := in_vec'low;
  36.     variable newpos : natural;
  37. begin
  38.     for i in 0 to len-1 loop
  39.         newpos := (i + shift);
  40.         if newpos >= len then
  41.             newpos := newpos - len; -- schneller als mod
  42.         end if;
  43.         result(i + base) := in_vec(newpos + base);
  44.     end loop;
  45.     return result;
  46. end function;
  47.  
  48.     type popcount_array_t is array (0 to 15) of std_logic_vector(3 downto 0);
  49.     constant popcount_lut : popcount_array_t := (
  50.         "0000", -- 0
  51.         "0001", -- 1
  52.         "0010", -- 2
  53.         "0011", -- 3
  54.         "0100", -- 4
  55.         "0101", -- 5
  56.         "0110", -- 6
  57.         "0111", -- 7
  58.         "1000", -- 8
  59.         "1001", -- 9
  60.         "1010", -- 10
  61.         "1011", -- 11
  62.         "1100", -- 12
  63.         "1101", -- 13
  64.         "1110", -- 14
  65.         "1111"  -- 15
  66.     );
  67.     function popcount4(v : std_logic_vector(3 downto 0)) return integer is
  68.     begin
  69.         return to_integer(unsigned(popcount_lut(to_integer(unsigned(v)))));
  70.     end function;
  71.     -- Statt full 256-bit XOR → sequenziell 4-bit Popcount verwenden
  72.         signal xor_chunk : std_logic_vector(3 downto 0);
  73.  
  74.     constant SEG_WIDTH : integer := 256;
  75.     constant WORD_WIDTH : integer := 32;
  76.     constant NUM_SEGMENTS : integer := D / SEG_WIDTH;
  77.     constant CHUNKS_PER_VEC : integer := (D + WORD_WIDTH - 1) / WORD_WIDTH; -- 313
  78.  
  79.     type feature_array_t is array(0 to N-1) of STD_LOGIC_VECTOR(15 downto 0);
  80.     signal feature_buffer : feature_array_t;
  81.     signal feature_load_index : integer range 0 to N := 0;
  82.     signal features_ready : STD_LOGIC := '0';
  83.     signal feature_values_packed : STD_LOGIC_VECTOR(N*16-1 downto 0);
  84.    
  85.     signal bundled_result, bundled_result_accumulator : STD_LOGIC_VECTOR(D-1 downto 0);
  86.     signal chunk_counter : unsigned(2 downto 0) := (others => '0');
  87.     signal similarity_counter : unsigned(7 downto 0) := (others => '0');
  88.     signal global_counter : unsigned(7 downto 0) := (others => '0');
  89.     signal memory_index : unsigned(2 downto 0) := (others => '0');
  90.     signal closest_memory_index : unsigned(2 downto 0) := (others => '0');
  91.     signal final_accumulation : STD_LOGIC_VECTOR(D-1 downto 0) := (others => '0');
  92.     signal bit_index : integer range 0 to SEG_WIDTH-1 := 0;
  93.     signal xor_bit   : std_logic;
  94.     signal popcount_add_en : std_logic := '0';
  95.     signal done_encoding : STD_LOGIC := '0';
  96.  
  97.     signal compare_state : integer range 0 to 6 := 0;
  98.     signal segment_index : integer range 0 to NUM_SEGMENTS-1 := 0;
  99.     signal word_index : integer range 0 to CHUNKS_PER_VEC-1 := 0;
  100.     signal xor_result : STD_LOGIC_VECTOR(SEG_WIDTH-1 downto 0);
  101.     signal partial_hamming : unsigned(15 downto 0) := (others => '0');
  102.     signal min_hamming_distance : unsigned(15 downto 0) := (others => '1');
  103.  
  104.     signal im_we, cm_we, am_we : std_logic;
  105.     signal im_addr, cm_addr, am_addr : std_logic_vector(15 downto 0):= (others => '0');
  106.     signal im_data_in, cm_data_in, am_data_in : std_logic_vector(31 downto 0);
  107.     signal im_data_out, cm_data_out, am_data_out : std_logic_vector(31 downto 0);
  108.     signal am_buffer : STD_LOGIC_VECTOR(D-1 downto 0) := (others => '0');
  109.     signal popcount_step : integer range 0 to SEG_WIDTH/32 - 1 := 0;
  110.     signal pop_accumulator : unsigned(15 downto 0) := (others => '0');
  111.  
  112.     signal am_addr_internal : std_logic_vector(15 downto 0):= (others => '0');
  113.     signal use_internal_am_addr : std_logic := '0';
  114.  
  115.     component Accelerator
  116.         generic (
  117.             D : integer := 10000;
  118.             N : integer := 32;
  119.             M : integer := 200
  120.         );
  121.         Port (
  122.             clk : in STD_LOGIC;
  123.             reset : in STD_LOGIC;
  124.             feature_values : in STD_LOGIC_VECTOR(N*16-1 downto 0);
  125.             start : in STD_LOGIC;
  126.             done : out STD_LOGIC;
  127.             encoded_hv_ready : out STD_LOGIC;
  128.             bundled_result : out STD_LOGIC_VECTOR(D-1 downto 0);
  129.             im_we : in STD_LOGIC;
  130.             im_addr : in STD_LOGIC_VECTOR(15 downto 0);
  131.             im_data_in : in STD_LOGIC_VECTOR(31 downto 0);
  132.             cm_we : in STD_LOGIC;
  133.             cm_addr : in STD_LOGIC_VECTOR(15 downto 0);
  134.             cm_data_in : in STD_LOGIC_VECTOR(31 downto 0);
  135.             im_data_out : out STD_LOGIC_VECTOR(31 downto 0);
  136.             cm_data_out : out STD_LOGIC_VECTOR(31 downto 0)
  137.         );
  138.     end component;
  139.  
  140.     component AssociativeMemory
  141.         Port (
  142.             clk      : in  STD_LOGIC;
  143.             we       : in  STD_LOGIC;
  144.             am_addr     : in  STD_LOGIC_VECTOR(15 downto 0);
  145.             am_data_in  : in  STD_LOGIC_VECTOR(31 downto 0);
  146.             am_data_out : out STD_LOGIC_VECTOR(31 downto 0)
  147.         );
  148.     end component;
  149.  
  150. begin
  151.  
  152.    
  153.     -- Demultiplex Speicherzugriff basierend auf mem_sel
  154.     im_we <= mem_we when mem_sel = "00" else '0';
  155.     cm_we <= mem_we when mem_sel = "01" else '0';
  156.     am_we <= mem_we when mem_sel = "10" else '0';
  157.  
  158.     im_addr <= mem_addr when mem_sel = "00" else (others => '0');
  159.     cm_addr <= mem_addr when mem_sel = "01" else (others => '0');
  160.  
  161.     -- AM-Adressmultiplex
  162.     am_addr <= am_addr_internal when use_internal_am_addr = '1' else
  163.            mem_addr            when mem_sel = "10" else
  164.            (others => '0');
  165.  
  166.     im_data_in <= mem_data_in;
  167.     cm_data_in <= mem_data_in;
  168.     am_data_in <= mem_data_in;
  169.  
  170.     with mem_sel select
  171.         mem_data_out <= im_data_out when "00",
  172.                         cm_data_out when "01",
  173.                         am_data_out when "10",
  174.                         (others => '0') when others;
  175.  
  176.     done_encoding_monitor <= done_encoding;
  177.  
  178.    
  179.  
  180.    accelerator_unit: Accelerator
  181.     generic map ( D => D, N => N, M => M )
  182.     port map (
  183.         clk => clk,
  184.         reset => reset,
  185.         feature_values => feature_values_packed,
  186.         start => start,
  187.         done => done_encoding,
  188.         encoded_hv_ready => open,
  189.         bundled_result => bundled_result,
  190.         im_we => im_we,
  191.         im_addr => im_addr,
  192.         im_data_in => im_data_in,
  193.         cm_we => cm_we,
  194.         cm_addr => cm_addr,
  195.         cm_data_in => cm_data_in,
  196.         im_data_out => im_data_out,
  197.         cm_data_out => cm_data_out
  198.     );
  199.  
  200.     associative_memory_unit: AssociativeMemory
  201.     port map (
  202.         clk => clk,
  203.         we => am_we,
  204.         am_addr => am_addr,
  205.         am_data_in => am_data_in,
  206.         am_data_out => am_data_out
  207.     );
  208.  
  209.     process(clk, reset)
  210.         variable pop : integer := 0;
  211.     begin
  212.         if reset = '1' then
  213.             feature_load_index <= 0;
  214.             features_ready <= '0';
  215.             bundled_result_accumulator <= (others => '0');
  216.             chunk_counter <= (others => '0');
  217.             compare_state <= 0;
  218.             memory_index <= (others => '0');
  219.             similarity_counter <= (others => '0');
  220.             closest_memory_index <= (others => '0');
  221.             segment_index <= 0;
  222.             partial_hamming <= (others => '0');
  223.             min_hamming_distance <= (others => '1');
  224.             done <= '0';
  225.             word_index <= 0;
  226.         elsif rising_edge(clk) then
  227.             if feature_valid = '1' and features_ready = '0' then
  228.                 feature_values_packed((feature_load_index+1)*16-1 downto feature_load_index*16) <= feature_value;
  229.                 if feature_load_index = N-1 then
  230.                     features_ready <= '1';
  231.                     feature_load_index <= 0;
  232.                 else
  233.                     feature_load_index <= feature_load_index + 1;
  234.                 end if;
  235.             else
  236.                 features_ready <= '0';
  237.             end if;
  238.  
  239.  
  240.             case compare_state is
  241.                 when 0 =>
  242.                     if done_encoding = '1' then
  243.  
  244.                         bundled_result_accumulator <= bundled_result_accumulator xor rotate_right(bundled_result, to_integer(chunk_counter));
  245.                         chunk_counter <= chunk_counter + 1;
  246.                         if chunk_counter = to_unsigned(4, chunk_counter'length) then
  247.                             global_counter <= global_counter + 1;
  248.                             compare_state <= 1;
  249.                             memory_index <= (others => '0');
  250.                             chunk_counter <= (others => '0');
  251.                             word_index <= 0;
  252.                             bundled_result_accumulator <= (others => '0');
  253.                             final_accumulation <= bundled_result_accumulator;
  254.                             am_buffer <= (others => '0');
  255.                         end if;
  256.                     end if;
  257.  
  258.                 when 1 =>
  259.                     am_addr_internal <= std_logic_vector(to_unsigned(to_integer(memory_index) * (CHUNKS_PER_VEC) + word_index, 16));
  260.                     use_internal_am_addr <= '1';
  261.                     compare_state <= 2;
  262.                 when 2 =>
  263.                     compare_state <= 3;
  264.                 when 3 =>
  265.                    
  266.                    if word_index = CHUNKS_PER_VEC - 1 then
  267.                         -- Sonderbehandlung für die letzten 16 Bit (die obersten 16 Bits vom letzten 32-Bit-Block)
  268.                         am_buffer(15 downto 0) <= am_data_out(31 downto 16);
  269.                    
  270.                         -- Zustand zurücksetzen
  271.                         word_index <= 0;
  272.                         segment_index <= 0;
  273.                         partial_hamming <= (others => '0');
  274.                         compare_state <= 4;
  275.                     else
  276.                         -- Speicherblock rückwärts schreiben
  277.                         -- z. B. word_index=0 → D-1 downto D-256
  278.                         --       word_index=1 → D-257 downto D-512
  279.                         am_buffer(D-1 - word_index*WORD_WIDTH downto D - (word_index+1)*WORD_WIDTH) <= am_data_out;
  280.                    
  281.                         -- Weiterzählen
  282.                         word_index <= word_index + 1;
  283.                         compare_state <= 1;
  284.                     end if;
  285.  
  286.                 when 4 =>
  287.                      xor_result <= final_accumulation((segment_index+1)*SEG_WIDTH -1 downto segment_index*SEG_WIDTH)
  288.                                   xor am_buffer((segment_index+1)*SEG_WIDTH -1 downto segment_index*SEG_WIDTH);
  289.                     pop := 0;
  290.                     for i in 0 to SEG_WIDTH/4 - 1 loop
  291.                         xor_chunk <= xor_result(i*4+3 downto i*4);
  292.                         pop := pop + popcount4(xor_chunk);
  293.                     end loop;
  294.                     partial_hamming <= partial_hamming + to_unsigned(pop, 16);
  295.                     if segment_index = NUM_SEGMENTS - 1 then
  296.                         compare_state <= 5;
  297.                     else
  298.                         segment_index <= segment_index + 1;
  299.                     end if;
  300.  
  301.                 when 5 =>
  302.                     if partial_hamming < min_hamming_distance then
  303.                         min_hamming_distance <= partial_hamming;
  304.                         closest_memory_index <= memory_index;
  305.                     end if;
  306.  
  307.                     if memory_index = to_unsigned(4, 3) then
  308.                         if closest_memory_index = "010" then
  309.                             similarity_counter <= similarity_counter + 1;
  310.                         end if;
  311.                         compare_state <= 6;
  312.                     else
  313.                         memory_index <= memory_index + 1;
  314.                         word_index <= 0;
  315.                         compare_state <= 1;
  316.                     end if;
  317.  
  318.                 when 6 =>
  319.                     similarity_counter_out <= std_logic_vector(similarity_counter);
  320.                     done <= '1';
  321.                     compare_state <= 0;
  322.                     min_hamming_distance <= (others => '1');
  323.             end case;
  324.         end if;
  325.     end process;
  326.  
  327. end Behavioral;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement