Reformat rotator

Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
remove-potato-uart
Anton Blanchard 3 years ago committed by Anton Blanchard
parent 601f3211be
commit c76e638a77

@ -7,17 +7,17 @@ use work.common.all;


entity rotator is entity rotator is
port (rs: in std_ulogic_vector(63 downto 0); port (rs: in std_ulogic_vector(63 downto 0);
ra: in std_ulogic_vector(63 downto 0); ra: in std_ulogic_vector(63 downto 0);
shift: in std_ulogic_vector(6 downto 0); shift: in std_ulogic_vector(6 downto 0);
insn: in std_ulogic_vector(31 downto 0); insn: in std_ulogic_vector(31 downto 0);
is_32bit: in std_ulogic; is_32bit: in std_ulogic;
right_shift: in std_ulogic; right_shift: in std_ulogic;
arith: in std_ulogic; arith: in std_ulogic;
clear_left: in std_ulogic; clear_left: in std_ulogic;
clear_right: in std_ulogic; clear_right: in std_ulogic;
sign_ext_rs: in std_ulogic; sign_ext_rs: in std_ulogic;
result: out std_ulogic_vector(63 downto 0); result: out std_ulogic_vector(63 downto 0);
carry_out: out std_ulogic carry_out: out std_ulogic
); );
end entity rotator; end entity rotator;


@ -31,159 +31,159 @@ architecture behaviour of rotator is


-- note BE bit numbering -- note BE bit numbering
function right_mask(mask_begin: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is function right_mask(mask_begin: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector(63 downto 0); variable ret: std_ulogic_vector(63 downto 0);
begin begin
ret := (others => '0'); ret := (others => '0');
for i in 0 to 63 loop for i in 0 to 63 loop
if i >= to_integer(unsigned(mask_begin)) then if i >= to_integer(unsigned(mask_begin)) then
ret(63 - i) := '1'; ret(63 - i) := '1';
end if; end if;
end loop; end loop;
return ret; return ret;
end; end;


function left_mask(mask_end: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is function left_mask(mask_end: std_ulogic_vector(6 downto 0)) return std_ulogic_vector is
variable ret: std_ulogic_vector(63 downto 0); variable ret: std_ulogic_vector(63 downto 0);
begin begin
ret := (others => '0'); ret := (others => '0');
if mask_end(6) = '0' then if mask_end(6) = '0' then
for i in 0 to 63 loop for i in 0 to 63 loop
if i <= to_integer(unsigned(mask_end)) then if i <= to_integer(unsigned(mask_end)) then
ret(63 - i) := '1'; ret(63 - i) := '1';
end if; end if;
end loop; end loop;
end if; end if;
return ret; return ret;
end; end;


begin begin
rotator_0: process(all) rotator_0: process(all)
variable hi32: std_ulogic_vector(31 downto 0); variable hi32: std_ulogic_vector(31 downto 0);
begin begin
-- First replicate bottom 32 bits to both halves if 32-bit -- First replicate bottom 32 bits to both halves if 32-bit
if is_32bit = '1' then if is_32bit = '1' then
hi32 := rs(31 downto 0); hi32 := rs(31 downto 0);
elsif sign_ext_rs = '1' then elsif sign_ext_rs = '1' then
-- sign extend bottom 32 bits -- sign extend bottom 32 bits
hi32 := (others => rs(31)); hi32 := (others => rs(31));
else else
hi32 := rs(63 downto 32); hi32 := rs(63 downto 32);
end if; end if;
repl32 <= hi32 & rs(31 downto 0); repl32 <= hi32 & rs(31 downto 0);


-- Negate shift count for right shifts -- Negate shift count for right shifts
if right_shift = '1' then if right_shift = '1' then
rot_count <= std_ulogic_vector(- signed(shift(5 downto 0))); rot_count <= std_ulogic_vector(- signed(shift(5 downto 0)));
else else
rot_count <= shift(5 downto 0); rot_count <= shift(5 downto 0);
end if; end if;


-- Rotator works in 3 stages using 2 bits of the rotate count each -- Rotator works in 3 stages using 2 bits of the rotate count each
-- time. This gives 4:1 multiplexors which is ideal for the 6-input -- time. This gives 4:1 multiplexors which is ideal for the 6-input
-- LUTs in the Xilinx Artix 7. -- LUTs in the Xilinx Artix 7.
-- We look at the low bits of the rotate count first because they will -- We look at the low bits of the rotate count first because they will
-- have less delay through the negation above. -- have less delay through the negation above.
-- First rotate by 0, 1, 2, or 3 -- First rotate by 0, 1, 2, or 3
case rot_count(1 downto 0) is case rot_count(1 downto 0) is
when "00" => when "00" =>
rot1 <= repl32; rot1 <= repl32;
when "01" => when "01" =>
rot1 <= repl32(62 downto 0) & repl32(63); rot1 <= repl32(62 downto 0) & repl32(63);
when "10" => when "10" =>
rot1 <= repl32(61 downto 0) & repl32(63 downto 62); rot1 <= repl32(61 downto 0) & repl32(63 downto 62);
when others => when others =>
rot1 <= repl32(60 downto 0) & repl32(63 downto 61); rot1 <= repl32(60 downto 0) & repl32(63 downto 61);
end case; end case;
-- Next rotate by 0, 4, 8 or 12 -- Next rotate by 0, 4, 8 or 12
case rot_count(3 downto 2) is case rot_count(3 downto 2) is
when "00" => when "00" =>
rot2 <= rot1; rot2 <= rot1;
when "01" => when "01" =>
rot2 <= rot1(59 downto 0) & rot1(63 downto 60); rot2 <= rot1(59 downto 0) & rot1(63 downto 60);
when "10" => when "10" =>
rot2 <= rot1(55 downto 0) & rot1(63 downto 56); rot2 <= rot1(55 downto 0) & rot1(63 downto 56);
when others => when others =>
rot2 <= rot1(51 downto 0) & rot1(63 downto 52); rot2 <= rot1(51 downto 0) & rot1(63 downto 52);
end case; end case;
-- Lastly rotate by 0, 16, 32 or 48 -- Lastly rotate by 0, 16, 32 or 48
case rot_count(5 downto 4) is case rot_count(5 downto 4) is
when "00" => when "00" =>
rot <= rot2; rot <= rot2;
when "01" => when "01" =>
rot <= rot2(47 downto 0) & rot2(63 downto 48); rot <= rot2(47 downto 0) & rot2(63 downto 48);
when "10" => when "10" =>
rot <= rot2(31 downto 0) & rot2(63 downto 32); rot <= rot2(31 downto 0) & rot2(63 downto 32);
when others => when others =>
rot <= rot2(15 downto 0) & rot2(63 downto 16); rot <= rot2(15 downto 0) & rot2(63 downto 16);
end case; end case;


-- Trim shift count to 6 bits for 32-bit shifts -- Trim shift count to 6 bits for 32-bit shifts
sh <= (shift(6) and not is_32bit) & shift(5 downto 0); sh <= (shift(6) and not is_32bit) & shift(5 downto 0);


-- Work out mask begin/end indexes (caution, big-endian bit numbering) -- Work out mask begin/end indexes (caution, big-endian bit numbering)
if clear_left = '1' then if clear_left = '1' then
if is_32bit = '1' then if is_32bit = '1' then
mb <= "01" & insn(10 downto 6); mb <= "01" & insn(10 downto 6);
else else
mb <= "0" & insn(5) & insn(10 downto 6); mb <= "0" & insn(5) & insn(10 downto 6);
end if; end if;
elsif right_shift = '1' then elsif right_shift = '1' then
-- this is basically mb <= sh + (is_32bit? 32: 0); -- this is basically mb <= sh + (is_32bit? 32: 0);
if is_32bit = '1' then if is_32bit = '1' then
mb <= sh(5) & not sh(5) & sh(4 downto 0); mb <= sh(5) & not sh(5) & sh(4 downto 0);
else else
mb <= sh; mb <= sh;
end if; end if;
else else
mb <= ('0' & is_32bit & "00000"); mb <= ('0' & is_32bit & "00000");
end if; end if;
if clear_right = '1' and is_32bit = '1' then if clear_right = '1' and is_32bit = '1' then
me <= "01" & insn(5 downto 1); me <= "01" & insn(5 downto 1);
elsif clear_right = '1' and clear_left = '0' then elsif clear_right = '1' and clear_left = '0' then
me <= "0" & insn(5) & insn(10 downto 6); me <= "0" & insn(5) & insn(10 downto 6);
else else
-- effectively, 63 - sh -- effectively, 63 - sh
me <= sh(6) & not sh(5 downto 0); me <= sh(6) & not sh(5 downto 0);
end if; end if;


-- Calculate left and right masks -- Calculate left and right masks
mr <= right_mask(mb); mr <= right_mask(mb);
ml <= left_mask(me); ml <= left_mask(me);


-- Work out output mode -- Work out output mode
-- 00 for sl[wd] -- 00 for sl[wd]
-- 0w for rlw*, rldic, rldicr, rldimi, where w = 1 iff mb > me -- 0w for rlw*, rldic, rldicr, rldimi, where w = 1 iff mb > me
-- 10 for rldicl, sr[wd] -- 10 for rldicl, sr[wd]
-- 1z for sra[wd][i], z = 1 if rs is negative -- 1z for sra[wd][i], z = 1 if rs is negative
if (clear_left = '1' and clear_right = '0') or right_shift = '1' then if (clear_left = '1' and clear_right = '0') or right_shift = '1' then
output_mode(1) <= '1'; output_mode(1) <= '1';
output_mode(0) <= arith and repl32(63); output_mode(0) <= arith and repl32(63);
else else
output_mode(1) <= '0'; output_mode(1) <= '0';
if clear_right = '1' and unsigned(mb(5 downto 0)) > unsigned(me(5 downto 0)) then if clear_right = '1' and unsigned(mb(5 downto 0)) > unsigned(me(5 downto 0)) then
output_mode(0) <= '1'; output_mode(0) <= '1';
else else
output_mode(0) <= '0'; output_mode(0) <= '0';
end if; end if;
end if; end if;


-- Generate output from rotated input and masks -- Generate output from rotated input and masks
case output_mode is case output_mode is
when "00" => when "00" =>
result <= (rot and (mr and ml)) or (ra and not (mr and ml)); result <= (rot and (mr and ml)) or (ra and not (mr and ml));
when "01" => when "01" =>
result <= (rot and (mr or ml)) or (ra and not (mr or ml)); result <= (rot and (mr or ml)) or (ra and not (mr or ml));
when "10" => when "10" =>
result <= rot and mr; result <= rot and mr;
when others => when others =>
result <= rot or not mr; result <= rot or not mr;
end case; end case;


-- Generate carry output for arithmetic shift right of negative value -- Generate carry output for arithmetic shift right of negative value
if output_mode = "11" then if output_mode = "11" then
carry_out <= or (rs and not ml); carry_out <= or (rs and not ml);
else else
carry_out <= '0'; carry_out <= '0';
end if; end if;
end process; end process;
end behaviour; end behaviour;

Loading…
Cancel
Save