mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-05 04:35:00 +00:00
committed by
Anton Blanchard
parent
601f3211be
commit
c76e638a77
280
rotator.vhdl
280
rotator.vhdl
@@ -7,17 +7,17 @@ use work.common.all;
|
||||
|
||||
entity rotator is
|
||||
port (rs: in std_ulogic_vector(63 downto 0);
|
||||
ra: in std_ulogic_vector(63 downto 0);
|
||||
shift: in std_ulogic_vector(6 downto 0);
|
||||
insn: in std_ulogic_vector(31 downto 0);
|
||||
is_32bit: in std_ulogic;
|
||||
right_shift: in std_ulogic;
|
||||
arith: in std_ulogic;
|
||||
clear_left: in std_ulogic;
|
||||
clear_right: in std_ulogic;
|
||||
ra: in std_ulogic_vector(63 downto 0);
|
||||
shift: in std_ulogic_vector(6 downto 0);
|
||||
insn: in std_ulogic_vector(31 downto 0);
|
||||
is_32bit: in std_ulogic;
|
||||
right_shift: in std_ulogic;
|
||||
arith: in std_ulogic;
|
||||
clear_left: in std_ulogic;
|
||||
clear_right: in std_ulogic;
|
||||
sign_ext_rs: in std_ulogic;
|
||||
result: out std_ulogic_vector(63 downto 0);
|
||||
carry_out: out std_ulogic
|
||||
result: out std_ulogic_vector(63 downto 0);
|
||||
carry_out: out std_ulogic
|
||||
);
|
||||
end entity rotator;
|
||||
|
||||
@@ -31,159 +31,159 @@ architecture behaviour of rotator is
|
||||
|
||||
-- note BE bit numbering
|
||||
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
|
||||
ret := (others => '0');
|
||||
for i in 0 to 63 loop
|
||||
if i >= to_integer(unsigned(mask_begin)) then
|
||||
ret(63 - i) := '1';
|
||||
end if;
|
||||
end loop;
|
||||
return ret;
|
||||
ret := (others => '0');
|
||||
for i in 0 to 63 loop
|
||||
if i >= to_integer(unsigned(mask_begin)) then
|
||||
ret(63 - i) := '1';
|
||||
end if;
|
||||
end loop;
|
||||
return ret;
|
||||
end;
|
||||
|
||||
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
|
||||
ret := (others => '0');
|
||||
if mask_end(6) = '0' then
|
||||
for i in 0 to 63 loop
|
||||
if i <= to_integer(unsigned(mask_end)) then
|
||||
ret(63 - i) := '1';
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
return ret;
|
||||
ret := (others => '0');
|
||||
if mask_end(6) = '0' then
|
||||
for i in 0 to 63 loop
|
||||
if i <= to_integer(unsigned(mask_end)) then
|
||||
ret(63 - i) := '1';
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
return ret;
|
||||
end;
|
||||
|
||||
begin
|
||||
rotator_0: process(all)
|
||||
variable hi32: std_ulogic_vector(31 downto 0);
|
||||
begin
|
||||
-- First replicate bottom 32 bits to both halves if 32-bit
|
||||
if is_32bit = '1' then
|
||||
-- First replicate bottom 32 bits to both halves if 32-bit
|
||||
if is_32bit = '1' then
|
||||
hi32 := rs(31 downto 0);
|
||||
elsif sign_ext_rs = '1' then
|
||||
elsif sign_ext_rs = '1' then
|
||||
-- sign extend bottom 32 bits
|
||||
hi32 := (others => rs(31));
|
||||
else
|
||||
hi32 := rs(63 downto 32);
|
||||
end if;
|
||||
hi32 := rs(63 downto 32);
|
||||
end if;
|
||||
repl32 <= hi32 & rs(31 downto 0);
|
||||
|
||||
-- Negate shift count for right shifts
|
||||
if right_shift = '1' then
|
||||
rot_count <= std_ulogic_vector(- signed(shift(5 downto 0)));
|
||||
else
|
||||
rot_count <= shift(5 downto 0);
|
||||
end if;
|
||||
-- Negate shift count for right shifts
|
||||
if right_shift = '1' then
|
||||
rot_count <= std_ulogic_vector(- signed(shift(5 downto 0)));
|
||||
else
|
||||
rot_count <= shift(5 downto 0);
|
||||
end if;
|
||||
|
||||
-- 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
|
||||
-- LUTs in the Xilinx Artix 7.
|
||||
-- We look at the low bits of the rotate count first because they will
|
||||
-- have less delay through the negation above.
|
||||
-- First rotate by 0, 1, 2, or 3
|
||||
case rot_count(1 downto 0) is
|
||||
when "00" =>
|
||||
rot1 <= repl32;
|
||||
when "01" =>
|
||||
rot1 <= repl32(62 downto 0) & repl32(63);
|
||||
when "10" =>
|
||||
rot1 <= repl32(61 downto 0) & repl32(63 downto 62);
|
||||
when others =>
|
||||
rot1 <= repl32(60 downto 0) & repl32(63 downto 61);
|
||||
end case;
|
||||
-- Next rotate by 0, 4, 8 or 12
|
||||
case rot_count(3 downto 2) is
|
||||
when "00" =>
|
||||
rot2 <= rot1;
|
||||
when "01" =>
|
||||
rot2 <= rot1(59 downto 0) & rot1(63 downto 60);
|
||||
when "10" =>
|
||||
rot2 <= rot1(55 downto 0) & rot1(63 downto 56);
|
||||
when others =>
|
||||
rot2 <= rot1(51 downto 0) & rot1(63 downto 52);
|
||||
end case;
|
||||
-- Lastly rotate by 0, 16, 32 or 48
|
||||
case rot_count(5 downto 4) is
|
||||
when "00" =>
|
||||
rot <= rot2;
|
||||
when "01" =>
|
||||
rot <= rot2(47 downto 0) & rot2(63 downto 48);
|
||||
when "10" =>
|
||||
rot <= rot2(31 downto 0) & rot2(63 downto 32);
|
||||
when others =>
|
||||
rot <= rot2(15 downto 0) & rot2(63 downto 16);
|
||||
end case;
|
||||
-- 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
|
||||
-- LUTs in the Xilinx Artix 7.
|
||||
-- We look at the low bits of the rotate count first because they will
|
||||
-- have less delay through the negation above.
|
||||
-- First rotate by 0, 1, 2, or 3
|
||||
case rot_count(1 downto 0) is
|
||||
when "00" =>
|
||||
rot1 <= repl32;
|
||||
when "01" =>
|
||||
rot1 <= repl32(62 downto 0) & repl32(63);
|
||||
when "10" =>
|
||||
rot1 <= repl32(61 downto 0) & repl32(63 downto 62);
|
||||
when others =>
|
||||
rot1 <= repl32(60 downto 0) & repl32(63 downto 61);
|
||||
end case;
|
||||
-- Next rotate by 0, 4, 8 or 12
|
||||
case rot_count(3 downto 2) is
|
||||
when "00" =>
|
||||
rot2 <= rot1;
|
||||
when "01" =>
|
||||
rot2 <= rot1(59 downto 0) & rot1(63 downto 60);
|
||||
when "10" =>
|
||||
rot2 <= rot1(55 downto 0) & rot1(63 downto 56);
|
||||
when others =>
|
||||
rot2 <= rot1(51 downto 0) & rot1(63 downto 52);
|
||||
end case;
|
||||
-- Lastly rotate by 0, 16, 32 or 48
|
||||
case rot_count(5 downto 4) is
|
||||
when "00" =>
|
||||
rot <= rot2;
|
||||
when "01" =>
|
||||
rot <= rot2(47 downto 0) & rot2(63 downto 48);
|
||||
when "10" =>
|
||||
rot <= rot2(31 downto 0) & rot2(63 downto 32);
|
||||
when others =>
|
||||
rot <= rot2(15 downto 0) & rot2(63 downto 16);
|
||||
end case;
|
||||
|
||||
-- Trim shift count to 6 bits for 32-bit shifts
|
||||
sh <= (shift(6) and not is_32bit) & shift(5 downto 0);
|
||||
-- Trim shift count to 6 bits for 32-bit shifts
|
||||
sh <= (shift(6) and not is_32bit) & shift(5 downto 0);
|
||||
|
||||
-- Work out mask begin/end indexes (caution, big-endian bit numbering)
|
||||
if clear_left = '1' then
|
||||
if is_32bit = '1' then
|
||||
mb <= "01" & insn(10 downto 6);
|
||||
else
|
||||
mb <= "0" & insn(5) & insn(10 downto 6);
|
||||
end if;
|
||||
elsif right_shift = '1' then
|
||||
-- this is basically mb <= sh + (is_32bit? 32: 0);
|
||||
if is_32bit = '1' then
|
||||
mb <= sh(5) & not sh(5) & sh(4 downto 0);
|
||||
else
|
||||
mb <= sh;
|
||||
end if;
|
||||
else
|
||||
mb <= ('0' & is_32bit & "00000");
|
||||
end if;
|
||||
if clear_right = '1' and is_32bit = '1' then
|
||||
me <= "01" & insn(5 downto 1);
|
||||
elsif clear_right = '1' and clear_left = '0' then
|
||||
me <= "0" & insn(5) & insn(10 downto 6);
|
||||
else
|
||||
-- effectively, 63 - sh
|
||||
me <= sh(6) & not sh(5 downto 0);
|
||||
end if;
|
||||
-- Work out mask begin/end indexes (caution, big-endian bit numbering)
|
||||
if clear_left = '1' then
|
||||
if is_32bit = '1' then
|
||||
mb <= "01" & insn(10 downto 6);
|
||||
else
|
||||
mb <= "0" & insn(5) & insn(10 downto 6);
|
||||
end if;
|
||||
elsif right_shift = '1' then
|
||||
-- this is basically mb <= sh + (is_32bit? 32: 0);
|
||||
if is_32bit = '1' then
|
||||
mb <= sh(5) & not sh(5) & sh(4 downto 0);
|
||||
else
|
||||
mb <= sh;
|
||||
end if;
|
||||
else
|
||||
mb <= ('0' & is_32bit & "00000");
|
||||
end if;
|
||||
if clear_right = '1' and is_32bit = '1' then
|
||||
me <= "01" & insn(5 downto 1);
|
||||
elsif clear_right = '1' and clear_left = '0' then
|
||||
me <= "0" & insn(5) & insn(10 downto 6);
|
||||
else
|
||||
-- effectively, 63 - sh
|
||||
me <= sh(6) & not sh(5 downto 0);
|
||||
end if;
|
||||
|
||||
-- Calculate left and right masks
|
||||
mr <= right_mask(mb);
|
||||
ml <= left_mask(me);
|
||||
-- Calculate left and right masks
|
||||
mr <= right_mask(mb);
|
||||
ml <= left_mask(me);
|
||||
|
||||
-- Work out output mode
|
||||
-- 00 for sl[wd]
|
||||
-- 0w for rlw*, rldic, rldicr, rldimi, where w = 1 iff mb > me
|
||||
-- 10 for rldicl, sr[wd]
|
||||
-- 1z for sra[wd][i], z = 1 if rs is negative
|
||||
if (clear_left = '1' and clear_right = '0') or right_shift = '1' then
|
||||
output_mode(1) <= '1';
|
||||
output_mode(0) <= arith and repl32(63);
|
||||
else
|
||||
output_mode(1) <= '0';
|
||||
if clear_right = '1' and unsigned(mb(5 downto 0)) > unsigned(me(5 downto 0)) then
|
||||
output_mode(0) <= '1';
|
||||
else
|
||||
output_mode(0) <= '0';
|
||||
end if;
|
||||
end if;
|
||||
-- Work out output mode
|
||||
-- 00 for sl[wd]
|
||||
-- 0w for rlw*, rldic, rldicr, rldimi, where w = 1 iff mb > me
|
||||
-- 10 for rldicl, sr[wd]
|
||||
-- 1z for sra[wd][i], z = 1 if rs is negative
|
||||
if (clear_left = '1' and clear_right = '0') or right_shift = '1' then
|
||||
output_mode(1) <= '1';
|
||||
output_mode(0) <= arith and repl32(63);
|
||||
else
|
||||
output_mode(1) <= '0';
|
||||
if clear_right = '1' and unsigned(mb(5 downto 0)) > unsigned(me(5 downto 0)) then
|
||||
output_mode(0) <= '1';
|
||||
else
|
||||
output_mode(0) <= '0';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Generate output from rotated input and masks
|
||||
case output_mode is
|
||||
when "00" =>
|
||||
result <= (rot and (mr and ml)) or (ra and not (mr and ml));
|
||||
when "01" =>
|
||||
result <= (rot and (mr or ml)) or (ra and not (mr or ml));
|
||||
when "10" =>
|
||||
result <= rot and mr;
|
||||
when others =>
|
||||
result <= rot or not mr;
|
||||
end case;
|
||||
-- Generate output from rotated input and masks
|
||||
case output_mode is
|
||||
when "00" =>
|
||||
result <= (rot and (mr and ml)) or (ra and not (mr and ml));
|
||||
when "01" =>
|
||||
result <= (rot and (mr or ml)) or (ra and not (mr or ml));
|
||||
when "10" =>
|
||||
result <= rot and mr;
|
||||
when others =>
|
||||
result <= rot or not mr;
|
||||
end case;
|
||||
|
||||
-- Generate carry output for arithmetic shift right of negative value
|
||||
if output_mode = "11" then
|
||||
carry_out <= or (rs and not ml);
|
||||
else
|
||||
carry_out <= '0';
|
||||
end if;
|
||||
-- Generate carry output for arithmetic shift right of negative value
|
||||
if output_mode = "11" then
|
||||
carry_out <= or (rs and not ml);
|
||||
else
|
||||
carry_out <= '0';
|
||||
end if;
|
||||
end process;
|
||||
end behaviour;
|
||||
|
||||
Reference in New Issue
Block a user