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. var quads_screen_width = document.body.clientWidth;
  2. if ( quads_screen_width >= 1140 ) {
  3. /* desktop monitors */
  4. document.write('');
  5. (adsbygoogle = window.adsbygoogle || []).push({});
  6. }if ( quads_screen_width >= 1024 && quads_screen_width < 1140 ) {
  7. /* tablet landscape */
  8. document.write('');
  9. (adsbygoogle = window.adsbygoogle || []).push({});
  10. }if ( quads_screen_width >= 768 && quads_screen_width < 1024 ) {
  11. /* tablet portrait */
  12. document.write('');
  13. (adsbygoogle = window.adsbygoogle || []).push({});
  14. }if ( quads_screen_width < 768 ) {
  15. /* phone */
  16. document.write('');
  17. (adsbygoogle = window.adsbygoogle || []).push({});
  18. }
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25. library IEEE;
  26. use IEEE.STD_LOGIC_1164.ALL;
  27. use IEEE.STD_LOGIC_SIGNED.ALL;
  28. use IEEE.STD_LOGIC_ARITH.ALL;
  29. use IEEE.MATH_REAL.all;
  30.  
  31. package fix_point_packet is
  32. function int_to_bin(int, e : integer) return std_logic_vector;
  33. function frac_to_bin(frac : real; f : integer) return std_logic_vector;
  34. function real_to_fix(data : real; e, f : integer) return std_logic_vector;
  35.  
  36. end fix_point_packet;
  37.  
  38. package body fix_point_packet is
  39.  
  40. function int_to_bin(int, e : integer) return std_logic_vector is
  41. variable v_exp : std_logic_vector(e - 1 downto 0);
  42. variable v_int : integer;
  43. begin
  44. v_int := int;
  45. for n_i in 0 to e - 1 loop
  46. if v_int /= 0 then
  47. if (v_int / 2) = ((v_int - 1) / 2) then
  48. v_exp(n_i) := '1';
  49. else
  50. v_exp(n_i) := '0';
  51. end if;
  52. else
  53. v_exp(n_i) := '0';
  54.  
  55. end if;
  56. v_int := v_int / 2;
  57. end loop;
  58. return v_exp;
  59. end int_to_bin;
  60.  
  61. function frac_to_bin(frac : real; f : integer) return std_logic_vector is
  62. variable v_frac : real;
  63. variable v_frac_fix : std_logic_vector(f -1 downto 0);
  64. begin
  65. v_frac := frac;
  66. for n_i in f - 1 downto 0 loop
  67. v_frac := v_frac * 2.0;
  68. if v_frac >= 1.0 then
  69. v_frac_fix(n_i) := '1';
  70. v_frac := v_frac - 1.0;
  71. else
  72. v_frac_fix(n_i) := '0';
  73. end if;
  74. end loop;
  75. return v_frac_fix;
  76. end frac_to_bin;
  77.  
  78. function real_to_fix(data : real; e, f : integer) return std_logic_vector is
  79. variable v_data_abs : real;
  80. variable v_data_frac : real;
  81. variable v_fix_data : std_logic_vector(e + f - 1 downto 0) := (others => '0');
  82. begin
  83. v_data_abs := abs(data);
  84. v_data_frac := v_data_abs - floor(v_data_abs);
  85. v_fix_data(e + f - 1 downto f) := int_to_bin(integer(floor(v_data_abs)), e);
  86. v_fix_data(f - 1 downto 0) := frac_to_bin(v_data_frac, f);
  87.  
  88. if data < 0.0 then
  89. v_fix_data := not(v_fix_data) + 1;
  90. end if;
  91.  
  92. return v_fix_data;
  93. end real_to_fix;
  94. 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