12. СДВИГОВЫЙ РЕГИСТР



Сдвиги

Типичные виды сдвигов:


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-триггерах


Index Prev Next