rotator.vhdl 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. use ieee.numeric_std.all;
  4. library work;
  5. use work.common.all;
  6. entity rotator is
  7. port (rs: in std_ulogic_vector(63 downto 0);
  8. ra: in std_ulogic_vector(63 downto 0);
  9. shift: in std_ulogic_vector(6 downto 0);
  10. insn: in std_ulogic_vector(31 downto 0);
  11. is_32bit: in std_ulogic;
  12. right_shift: in std_ulogic;
  13. arith: in std_ulogic;
  14. clear_left: in std_ulogic;
  15. clear_right: in std_ulogic;
  16. sign_ext_rs: in std_ulogic;
  17. result: out std_ulogic_vector(63 downto 0);
  18. carry_out: out std_ulogic
  19. );
  20. end entity rotator;
  21. architecture behaviour of rotator is
  22. signal repl32: std_ulogic_vector(63 downto 0);
  23. signal rot_count: std_ulogic_vector(5 downto 0);
  24. signal rot1, rot2, rot: std_ulogic_vector(63 downto 0);
  25. signal sh, mb, me: std_ulogic_vector(6 downto 0);
  26. signal mr, ml: std_ulogic_vector(63 downto 0);
  27. signal output_mode: std_ulogic_vector(1 downto 0);
  28. -- note BE bit numbering
  29. function right_mask(mask_begin: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is
  30. variable ret: std_ulogic_vector(63 downto 0);
  31. begin
  32. ret := (others => '0');
  33. for i in 0 to 63 loop
  34. if i >= to_integer(unsigned(mask_begin)) then
  35. ret(63 - i) := '1';
  36. end if;
  37. end loop;
  38. return ret;
  39. end;
  40. function left_mask(mask_end: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is
  41. variable ret: std_ulogic_vector(63 downto 0);
  42. begin
  43. ret := (others => '0');
  44. if mask_end(6) = '0' then
  45. for i in 0 to 63 loop
  46. if i <= to_integer(unsigned(mask_end)) then
  47. ret(63 - i) := '1';
  48. end if;
  49. end loop;
  50. end if;
  51. return ret;
  52. end;
  53. begin
  54. rotator_0: process(all)
  55. variable hi32: std_ulogic_vector(31 downto 0);
  56. begin
  57. -- First replicate bottom 32 bits to both halves if 32-bit
  58. if is_32bit = '1' then
  59. hi32 := rs(31 downto 0);
  60. elsif sign_ext_rs = '1' then
  61. -- sign extend bottom 32 bits
  62. hi32 := (others => rs(31));
  63. else
  64. hi32 := rs(63 downto 32);
  65. end if;
  66. repl32 <= hi32 & rs(31 downto 0);
  67. -- Negate shift count for right shifts
  68. if right_shift = '1' then
  69. rot_count <= std_ulogic_vector(- signed(shift(5 downto 0)));
  70. else
  71. rot_count <= shift(5 downto 0);
  72. end if;
  73. -- Rotator works in 3 stages using 2 bits of the rotate count each
  74. -- time. This gives 4:1 multiplexors which is ideal for the 6-input
  75. -- LUTs in the Xilinx Artix 7.
  76. -- We look at the low bits of the rotate count first because they will
  77. -- have less delay through the negation above.
  78. -- First rotate by 0, 1, 2, or 3
  79. case rot_count(1 downto 0) is
  80. when "00" =>
  81. rot1 <= repl32;
  82. when "01" =>
  83. rot1 <= repl32(62 downto 0) & repl32(63);
  84. when "10" =>
  85. rot1 <= repl32(61 downto 0) & repl32(63 downto 62);
  86. when others =>
  87. rot1 <= repl32(60 downto 0) & repl32(63 downto 61);
  88. end case;
  89. -- Next rotate by 0, 4, 8 or 12
  90. case rot_count(3 downto 2) is
  91. when "00" =>
  92. rot2 <= rot1;
  93. when "01" =>
  94. rot2 <= rot1(59 downto 0) & rot1(63 downto 60);
  95. when "10" =>
  96. rot2 <= rot1(55 downto 0) & rot1(63 downto 56);
  97. when others =>
  98. rot2 <= rot1(51 downto 0) & rot1(63 downto 52);
  99. end case;
  100. -- Lastly rotate by 0, 16, 32 or 48
  101. case rot_count(5 downto 4) is
  102. when "00" =>
  103. rot <= rot2;
  104. when "01" =>
  105. rot <= rot2(47 downto 0) & rot2(63 downto 48);
  106. when "10" =>
  107. rot <= rot2(31 downto 0) & rot2(63 downto 32);
  108. when others =>
  109. rot <= rot2(15 downto 0) & rot2(63 downto 16);
  110. end case;
  111. -- Trim shift count to 6 bits for 32-bit shifts
  112. sh <= (shift(6) and not is_32bit) & shift(5 downto 0);
  113. -- Work out mask begin/end indexes (caution, big-endian bit numbering)
  114. if clear_left = '1' then
  115. if is_32bit = '1' then
  116. mb <= "01" & insn(10 downto 6);
  117. else
  118. mb <= "0" & insn(5) & insn(10 downto 6);
  119. end if;
  120. elsif right_shift = '1' then
  121. -- this is basically mb <= sh + (is_32bit? 32: 0);
  122. if is_32bit = '1' then
  123. mb <= sh(5) & not sh(5) & sh(4 downto 0);
  124. else
  125. mb <= sh;
  126. end if;
  127. else
  128. mb <= ('0' & is_32bit & "00000");
  129. end if;
  130. if clear_right = '1' and is_32bit = '1' then
  131. me <= "01" & insn(5 downto 1);
  132. elsif clear_right = '1' and clear_left = '0' then
  133. me <= "0" & insn(5) & insn(10 downto 6);
  134. else
  135. -- effectively, 63 - sh
  136. me <= sh(6) & not sh(5 downto 0);
  137. end if;
  138. -- Calculate left and right masks
  139. mr <= right_mask(mb);
  140. ml <= left_mask(me);
  141. -- Work out output mode
  142. -- 00 for sl[wd]
  143. -- 0w for rlw*, rldic, rldicr, rldimi, where w = 1 iff mb > me
  144. -- 10 for rldicl, sr[wd]
  145. -- 1z for sra[wd][i], z = 1 if rs is negative
  146. if (clear_left = '1' and clear_right = '0') or right_shift = '1' then
  147. output_mode(1) <= '1';
  148. output_mode(0) <= arith and repl32(63);
  149. else
  150. output_mode(1) <= '0';
  151. if clear_right = '1' and unsigned(mb(5 downto 0)) > unsigned(me(5 downto 0)) then
  152. output_mode(0) <= '1';
  153. else
  154. output_mode(0) <= '0';
  155. end if;
  156. end if;
  157. -- Generate output from rotated input and masks
  158. case output_mode is
  159. when "00" =>
  160. result <= (rot and (mr and ml)) or (ra and not (mr and ml));
  161. when "01" =>
  162. result <= (rot and (mr or ml)) or (ra and not (mr or ml));
  163. when "10" =>
  164. result <= rot and mr;
  165. when others =>
  166. result <= rot or not mr;
  167. end case;
  168. -- Generate carry output for arithmetic shift right of negative value
  169. if output_mode = "11" then
  170. carry_out <= or (rs and not ml);
  171. else
  172. carry_out <= '0';
  173. end if;
  174. end process;
  175. end behaviour;