Типичные виды сдвигов: Сдвиги
SHL
+----------+ <-- | | <-- 0 SHL Shift Left Logical +----------+ SAL Shift Arithmetic Left
SHR
+----------+ 0 ->| |--> SHR Shift Right Logical +----------+
SAR
+-+--------+ +->|S| |--> SRA Shift Right Arithmetic | +-+--------+ | | +---+ повторяем знаковый бит
Кроме сдвигов есть еще и Rotates - это когда регистр "вращается". (т.е. регистр сдвигается так что младший бит становится старшим и наоборот). Есть вращения обычные и есть вращения через Carry Flag - специальный бит микропроцессора в регистре состояния. Вращения
ROL
+----------+ +-- | | <--+ ROL Rotate Left | +----------+ | +-------------------+
ROR
+----------+ +-> | | --+ ROR Rotate Right | +----------+ | +-------------------+
RCL
+----------+ +--+ +-- | | <- |CF|< --+ RCL Rotate with Carry Left | +----------+ +--+ | +---------------------------+
RCR
+----------+ +--+ +-> | | -> |CF| ---+ RCR Rotate with Carry Right | +----------+ +--+ | +---------------------------+
Пример простого логического сдвигового регистра: Паралельные сдвиговые регистры
-------------------------------- DIR D0 D1 D2 D3 | S0 S1 S2 S3 -----------------+-------------- 0 A B C D | B C D 0 1 A B C D | 0 A B C -------------------------------- Результат моделирования:
Пример реализации сдвигового регистра на VHDL: (Поддерживает Logical Shift и Rotate на 1 бит) library IEEE; use IEEE.std_logic_1164.ALL; entity SHIFT is port( a : in std_logic_vector(15 downto 0); sel : in std_logic_vector(2 downto 0); -- Command to shiter -- 000 SHL -- 001 SHR -- 010 ROL -- 011 ROR -- 1XX pass (no shift) y : out std_logic_vector(15 downto 0) ); end SHIFT; architecture RTL of SHIFT is begin shiftprocess: process(a,sel) begin case sel is WHEN "000" => -- SHL y <= a(14 downto 0) & '0' after 1 ns; WHEN "001" => -- SHR y <= '0' & a(15 downto 1) after 1 ns; WHEN "010" => -- ROL y <= a(14 downto 0) & a(15) after 1 ns; WHEN "011" => -- ROR y <= a(0) & a(15 downto 1) after 1 ns; WHEN OTHERS => -- pass it y <= a; end case; end process; end RTL;
Как сдвигать больше чем на 1 бит? Используется каскад.
Пример: 16 битный сдвиговый регистр, сдвигает влево на любое число бит: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity shl16 is port( DIN: in std_logic_vector(15 downto 0); -- Data input S : in std_logic_vector(3 downto 0); -- Shift ammount DOUT: out std_logic_vector(15 downto 0) -- Data Output ); end shl16; architecture ARCH of shl16 is signal X,Y,Z : std_logic_vector(15 downto 0); -- Temporary begin process(DIN,S) begin if S(0) = '1' then X <= DIN(14 downto 0) & "0"; else X <= DIN; end if; end process; process(S,X) begin if S(1) = '1' then Y <= X(13 downto 0) & "00"; else Y <= X; end if; end process; process(S,Y) begin if S(2) = '1' then Z <= Y(11 downto 0) & "0000"; else Z <= Y; end if; end process; process(S,Z) begin if S(3) = '1' then DOUT <= Z(7 downto 0) & "00000000"; else DOUT <= Z; end if; end process; end ARCH;
Можно также иметь управляющий бит который будет показывать направление cдвига: DIR | DATA | | | V | +-----------------------+ +---> | shift 4 | < --------- S3 | +-----------------------+ +----- S2 | | |+---- S1 | V ||+--- S0 | +-----------------------+ ||| +---> | shift 3 | < ---+|| | +-----------------------+ || | | || | V || | +-----------------------+ || +---> | shift 2 |<------+| | +-----------------------+ | | | | | V | | +-----------------------+ | +---> | shift 1 |<-------+ +-----------------------+ | V RESULT Пример: Вращающий 16бит регистр сдвига в любон направлении на любое число бит: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity rot16 is port( DIN : in std_logic_vector(15 downto 0); -- Data input S : in std_logic_vector(3 downto 0); -- Shift ammount DIR : in std_logic; -- Direction (0 = Left, 1 = Right) DOUT: out std_logic_vector(15 downto 0) -- Data Output ); end rot16; architecture ARCH of rot16 is signal X,Y,Z : std_logic_vector(15 downto 0); -- Temporary buses begin process(DIN,S,DIR) begin if S(0) = '1' then if DIR = '0' then X <= DIN(14 downto 0) & DIN(15); else X <= DIN(0) & DIN(15 downto 1); end if; else X <= DIN; end if; end process; process(S,X,DIR) begin if S(1) = '1' then if DIR = '0' then Y <= X(13 downto 0) & X(15 downto 14); else Y <= X(1 downto 0) & X(15 downto 2); end if; else Y <= X; end if; end process; process(S,Y,DIR) begin if S(2) = '1' then if DIR = '0' then Z <= Y(11 downto 0) & Y(15 downto 12); else Z <= Y(3 downto 0) & Y(15 downto 4); end if; else Z <= Y; end if; end process; process(S,Z,DIR) begin if S(3) = '1' then -- rotate by 8 bit is same values for -- both rotate right or left DOUT <= Z(7 downto 0) & Z(15 downto 8); else DOUT <= Z; end if; end process; end ARCH;
Оптимизированный на транзисторах сдвиговый регистр на любое число бит. Barrel Shifter
Последовательные сдвиговые регистры - совокупность триггеров и связей между ними. Каждый такт данные сдвигаются на один бит. (Раньше экономя транзисторв в микропроцессорах делали последовательные сдвиговые регистры (например в 80286). Последовательные сдвиговые регистры: Последовательные сдвиговые регистры
Сдвиговый регистр на JK-триггерах:
Сдвиговый регистр на D-триггерах