VHDL ile Sabit Noktalı Sayılarda Çarpma İşleminin Gerçeklenmesi

Çarpma işleminde yöntem, onluk tabanda yapılan çarpma işlemi gibi fakat ikilik sistemde yapılmaktadır.Aşağıdaki örnekte işlem kolaylığı olması açısından tam kısım 2 bit noktalı kısım ise 3 bit olarak alındı.

Sayı_1 = 1.125           →        01.001

Sayı_2 = 0.875           →        00.111

Sayı_1 * Sayı_2 = 0.984375

Adsız

Bizim sabit noktalı sayı formatı ile elde ettiğimiz sayıyı hesapalarsak:

Sayı = 1 * 2^ -1 + 1 * 2^ -2 + 1 * 2^ -3 + 1 * 2^ -4 + 1 * 2^ -5 + 1 * 2^ -6

Sayı = 0.5 + 0.25 + 0.125 + 0.0625 + 0.03125 + 0.15625= 0.984375

Aşağıda tam ve ondalık uzunlukları tanımlanan sabit noktalı sayı formatlarının istenen tam ve ondalık sayılara dönüştüren VHDL kodu verilmiştir.

  1. function fix_mul(data_1 : std_logic_vector; e_1, f_1 : integer;
  2. data_2 : std_logic_vector; e_2, f_2 : integer;
  3. e_result, f_result : integer) return std_logic_vector is
  4.  
  5. variable data_1_abs : std_logic_vector(e_1 + f_1 - 1 downto 0);
  6. variable data_2_abs : std_logic_vector(e_2 + f_2 - 1 downto 0);
  7. variable v_mul : std_logic_vector(e_1 + e_2 + f_1 + f_2 - 1 downto 0);
  8. variable v_mul_result : std_logic_vector(e_result + f_result - 1 downto 0);
  9. begin
  10.  
  11. v_mul := data_1 * data_2;
  12.  
  13. v_mul_result := v_mul(f_1 + f_2 + e_result - 1 downto f_1 + f_2) &
  14. v_mul(f_1 + f_2 - 1 downto f_1 + f_2 - f_result);
  15.  
  16. return v_mul_result;
  17. end fix_mul;

 

Kod içerisinde tanımlanan fonksiyonlar ise fix_point_packet dosyasında tanımlanmıştır.

  1. library IEEE;
  2. use IEEE.STD_LOGIC_1164.ALL;
  3. use IEEE.STD_LOGIC_SIGNED.ALL;
  4. use IEEE.STD_LOGIC_ARITH.ALL;
  5. use IEEE.MATH_REAL.all;
  6.  
  7. package fix_point_packet is
  8. function int_to_bin(int, e : integer) return std_logic_vector;
  9. function frac_to_bin(frac : real; f : integer) return std_logic_vector;
  10. function real_to_fix(data : real; e, f : integer) return std_logic_vector;
  11.  
  12. end fix_point_packet;
  13.  
  14. package body fix_point_packet is
  15.  
  16. function int_to_bin(int, e : integer) return std_logic_vector is
  17. variable v_exp : std_logic_vector(e - 1 downto 0);
  18. variable v_int : integer;
  19. begin
  20. v_int := int;
  21. for n_i in 0 to e - 1 loop
  22. if v_int /= 0 then
  23. if (v_int / 2) = ((v_int - 1) / 2) then
  24. v_exp(n_i) := '1';
  25. else
  26. v_exp(n_i) := '0';
  27. end if;
  28. else
  29. v_exp(n_i) := '0';
  30.  
  31. end if;
  32. v_int := v_int / 2;
  33. end loop;
  34. return v_exp;
  35. end int_to_bin;
  36.  
  37. function frac_to_bin(frac : real; f : integer) return std_logic_vector is
  38. variable v_frac : real;
  39. variable v_frac_fix : std_logic_vector(f -1 downto 0);
  40. begin
  41. v_frac := frac;
  42. for n_i in f - 1 downto 0 loop
  43. v_frac := v_frac * 2.0;
  44. if v_frac >= 1.0 then
  45. v_frac_fix(n_i) := '1';
  46. v_frac := v_frac - 1.0;
  47. else
  48. v_frac_fix(n_i) := '0';
  49. end if;
  50. end loop;
  51. return v_frac_fix;
  52. end frac_to_bin;
  53.  
  54. function real_to_fix(data : real; e, f : integer) return std_logic_vector is
  55. variable v_data_abs : real;
  56. variable v_data_frac : real;
  57. variable v_fix_data : std_logic_vector(e + f - 1 downto 0) := (others => '0');
  58. begin
  59. v_data_abs := abs(data);
  60. v_data_frac := v_data_abs - floor(v_data_abs);
  61. v_fix_data(e + f - 1 downto f) := int_to_bin(integer(floor(v_data_abs)), e);
  62. v_fix_data(f - 1 downto 0) := frac_to_bin(v_data_frac, f);
  63.  
  64. if data < 0.0 then
  65. v_fix_data := not(v_fix_data) + 1;
  66. end if;
  67.  
  68. return v_fix_data;
  69. end real_to_fix;
  70. end package body;

 

Aşağıda pozitif ve negatif olarak tanımlanan sayıların farklı ondalık ve tam sayı uzunluklarında hesaplanmasını sağlayan VHDL kodu ve benzetimi verilmiştir.

  1. process
  2. variable seed1, seed2 : positive;
  3. variable rand : real;
  4. begin
  5. data_1 <= real_to_fix(1.125, e_1, f_1);
  6. data_2 <= real_to_fix(0.875, e_2, f_2);
  7. wait for 1us;
  8.  
  9. data_result <= fix_mul(data_1, e_1, f_1, data_2, e_2, f_2, e_result, f_result);
  10. wait for 2us;
  11.  
  12. data_1 <= real_to_fix(1.125, e_1 + 1, f_1 - 1);
  13. data_2 <= real_to_fix(0.875, e_2 - 1, f_2 + 1);
  14. wait for 1us;
  15.  
  16. data_result <= fix_mul(data_1, e_1 + 1, f_1 - 1, data_2, e_2 - 1, f_2 + 1, e_result, f_result);
  17. wait for 2us;
  18.  
  19. data_1 <= real_to_fix(-1.125, e_1, f_1 );
  20. data_2 <= real_to_fix(0.875, e_2 - 1, f_2 + 1);
  21. wait for 1us;
  22.  
  23. data_result <= fix_mul(data_1, e_1, f_1, data_2, e_2 - 1, f_2 + 1, e_result, f_result);
  24. wait for 2us;
  25.  
  26. data_1 <= real_to_fix(-1.125, e_1, f_1 );
  27. data_2 <= real_to_fix(-0.875, e_2 - 1, f_2 + 1);
  28. wait for 1us;
  29.  
  30. data_result <= fix_mul(data_1, e_1, f_1, data_2, e_2 - 1, f_2 + 1, e_result, f_result);
  31. wait;
  32.  
  33. end process;

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir