fp_product.sv 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. typedef enum logic [1:0]{
  2. flag_none,
  3. flag_nan,
  4. flag_inf,
  5. flag_zero
  6. } product_flags;
  7. module fp_product #(parameter N=16, M=5)(input_a, input_b, output_z, clk, reset);
  8. localparam K=N-M-1; // Size of mantissa
  9. input logic [N-1:0] input_a, input_b;
  10. input logic clk, reset;
  11. output logic [N-1:0] output_z;
  12. reg [K-1:0] a_m0, b_m0, z_m1; // mantissa
  13. reg [K-1:0] a_m1, b_m1, z_m2; // mantissa
  14. reg [K-1:0] a_m2, b_m2, z_m3; // mantissa
  15. reg [K-1:0] z_m4;
  16. reg [M:0] a_e0, b_e0, z_e1; // exponent
  17. reg [M:0] a_e1, b_e1, z_e2; // exponent
  18. reg [M:0] a_e2, b_e2, z_e3; // exponent
  19. reg [M:0] z_e4;
  20. reg a_s0, b_s0, z_s1; // sign
  21. reg a_s1, b_s1, z_s2; // sign
  22. reg a_s2, b_s2, z_s3; // sign
  23. reg z_s4; // sign
  24. product_flags flags1; // 00 for no flag, 01 for NaN, 10 for infinity, 11 for zero
  25. reg [2*K-1:0] z_p3; // For storing the product of the two mantissa
  26. always_comb begin
  27. // Packing the output
  28. output_z = {z_s4, z_e4 + (1<<M), z_m4};
  29. end
  30. always_ff @(posedge clk)
  31. begin
  32. if (~reset)
  33. begin
  34. // Unpacking the inputs
  35. a_s0 <= input_a[N-1];
  36. a_e0 <= input_a[N-2:N-2-M] - (1<<M);
  37. a_m0 <= input_a[N-3-M:0];
  38. b_s0 <= input_b[N-1];
  39. b_e0 <= input_b[N-2:N-2-M] - (1<<M);
  40. b_m0 <= input_b[N-3-M:0];
  41. // Untouched pipelined registers
  42. a_s1 <= a_s0;
  43. a_s2 <= a_s1;
  44. a_e1 <= a_e0;
  45. a_m1 <= a_m0;
  46. b_s1 <= b_s0;
  47. b_s2 <= b_s1;
  48. b_e1 <= b_e0;
  49. b_m1 <= b_m0;
  50. z_s2 <= z_s1;
  51. z_s4 <= z_s3;
  52. z_e4 <= z_e3;
  53. z_m2 <= z_m1;
  54. z_m3 <= z_m2;
  55. z_s3 <= a_s2 ^ b_s2; //signs xor together
  56. z_e3 <= a_e2 + b_e2 - (1<<M); // exponents added together subtracting one offset
  57. z_p3 <= a_m2 * b_m2; // mantissa multiplied together and the most significant bits are stored in the output mantissa
  58. z_m4 <= z_p3[2*K-1:K];
  59. // If input a or input b is NaN then return NaN
  60. if (((a_e0 ==(1<<M)) && (a_m0 != 0)) || ((b_e0 == (1<<M)) && (b_m0 != 0)))
  61. begin
  62. z_s1 <= 1;
  63. z_e1 <= (1 << (M+1)) - 1;
  64. z_m1[K-1] <= 1;
  65. z_m1[K-2:0] <= 0;
  66. flags1 <= flag_nan;
  67. end
  68. // If a is infinity then return infinity
  69. else if (a_e0 == (1<<M))
  70. begin
  71. // Unless b is zero, then you return NaN instead
  72. if (($signed(b_e0) == (-1*((1<<M)-1))) && b_m0 == 0)
  73. begin
  74. z_s1 <= 1;
  75. z_e1 <= (1 << (M+1)) - 1;
  76. z_m1[K-1] <= 1;
  77. z_m1[K-2:0] <= 0;
  78. flags1 <= flag_nan;
  79. end
  80. else
  81. // Returning infinity
  82. begin
  83. z_s1 <= a_s0 ^ b_s0;
  84. z_e1 <= (1 << (M+1)) - 1;
  85. z_m1 <= 0;
  86. flags1 <= flag_inf;
  87. end
  88. end
  89. // If b is infinity then return infinity
  90. else if (b_s0 == (1<<M))
  91. begin
  92. //Unless a is zero, then return NaN instead
  93. if (($signed(a_e0) == (-1*((1<<M)-1))) && a_m0 == 0)
  94. begin
  95. z_s1 <= 1;
  96. z_e1 <= (1 << (M+1)) - 1;
  97. z_m1[K-1] <= 1;
  98. z_m1[K-2:0] <= 0;
  99. flags1 <= flag_nan;
  100. end
  101. else
  102. // Returning infinity
  103. begin
  104. z_s1 <= a_s0 ^ b_s0;
  105. z_e1 <= (1 << (M+1)) - 1;
  106. z_m1 <= 0;
  107. flags1 <= flag_inf;
  108. end
  109. end
  110. // If either input is zero then return zero
  111. else if ((($signed(a_e0) == (-1*((1<<M)-1))) && (a_m0 == 0)) || (($signed(b_e0) == (-1*((1<<M)-1))) && (b_m0 == 0)))
  112. begin
  113. z_s1 <= a_s0 ^ b_s0;
  114. z_e1 <= 0;
  115. z_m1 <= 0;
  116. flags1 <= flag_zero;
  117. end
  118. // If b is zero then return zero
  119. // If none of the return flags have been set
  120. if (flags1 == flag_none)
  121. begin
  122. // If msb of a_m is 0 then shift left and reduce exponent by 1
  123. if (a_m1[K-1] == 0)
  124. begin
  125. a_m2 <= a_m1 << 1;
  126. a_e2 <= a_e1 - 1;
  127. end
  128. //Just for completion of logic
  129. else
  130. begin
  131. a_m2 <= a_m1;
  132. a_e2 <= a_e1;
  133. end
  134. // If msb of b_m is 0 then shift left and reduce exponent by 1
  135. if (b_m1[K-1] == 0)
  136. begin
  137. b_m2 <= b_m1 << 1;
  138. b_e2 <= b_e1 - 1;
  139. end
  140. //Just for completion of logic
  141. else
  142. begin
  143. b_m2 <= b_m1;
  144. b_e2 <= b_e1;
  145. end
  146. end
  147. else
  148. begin
  149. a_m2 <= a_m1;
  150. a_e2 <= a_e1;
  151. b_m2 <= b_m1;
  152. b_e2 <= b_e1;
  153. z_s3 <= z_s2;
  154. z_e2 <= z_e1;
  155. z_e3 <= z_e2;
  156. z_m4 <= z_m3;
  157. z_p3 <= 0;
  158. end
  159. end
  160. else
  161. begin
  162. a_s0 <= 0;
  163. a_e0 <= 0;
  164. a_m0 <= 0;
  165. a_s1 <= 0;
  166. a_e1 <= 0;
  167. a_m1 <= 0;
  168. a_s2 <= 0;
  169. a_e2 <= 0;
  170. a_m2 <= 0;
  171. b_s0 <= 0;
  172. b_e0 <= 0;
  173. b_m0 <= 0;
  174. b_s1 <= 0;
  175. b_e1 <= 0;
  176. b_m1 <= 0;
  177. b_s2 <= 0;
  178. b_e2 <= 0;
  179. b_m2 <= 0;
  180. z_s1 <= 0;
  181. z_e1 <= 0;
  182. z_m1 <= 0;
  183. z_s2 <= 0;
  184. z_e2 <= 0;
  185. z_m2 <= 0;
  186. z_s3 <= 0;
  187. z_e3 <= 0;
  188. z_m3 <= 0;
  189. z_s4 <= 0;
  190. z_e4 <= 0;
  191. z_m4 <= 0;
  192. z_p3 <= 0;
  193. flags1 <= flag_none;
  194. end
  195. end
  196. endmodule : fp_product