What is a Shift Register

Create delays, convert serial to parallel data in FPGAs

Shift registers are a common FPGA building block. They are created by cascading Flip-Flops (Registers) in a chain. All registers must share the same clock, and the output of one register must be connected to the input of the next register in the chain. Shift registers are mainly used to accomplish one of three goals:

  1. Delaying data by some number of clock cycles
  2. Converting serial data to parallel data
  3. Converting parallel data to serial data

Creating a Shift Register for Delay

Creating delay in an FPGA is the most common use of a shift register. The delay is often used to align data in time. The figure below shows this simple type of shift register. The number of Flip-Flops in the delay chain dictates how many clock cycles it will take for the data on the input to propagate to the data on the output. So in the picture below, it will take four clock cycles for an input on D on the first Flip-Flop to be seen on the output Q of the last Flip-Flop. Read about Processes in VHDL or Always Blocks in Verilog for a tutorial on how to create a shift register in your HDL of choice.

Simple Delay Shift Register

Shift Register – From D Flip-Flops
-- VHDL Example of Shift Register for Delay:
signal r_Shift : std_logic_vector(3 downto 0);

process (i_clock)
begin
  if rising_edge(i_clock) then
    r_Shift(3 downto 1) <= r_Shift(2 downto 0); -- Shift Left
    r_Shift(0)          <= i_Data_To_Delay;
    -- Bit 3 of r_Shift has been delayed by 4 clock cycles
  end if;
end process;
// Verilog Example of Shift Register for Delay:
reg [3:0] r_Shift;

always @ (posedge i_clock)
  begin
    r_Shift[3:1] <= r_Shift[2:0];  // Shift Left
    r_Shift[0]   <= i_Data_To_Delay; 
    // Bit 3 of r_Shift has been delayed by 4 clock cycles
  end

The code above demonstrates creating delay by passing i_Data_To_Delay to the least significant bit of r_Shift. Then r_Shift is continuously shifted to the left on each clock cycle. This might be useful for example if you get some data in from one module, but don’t want to act on it right away. In the code above, any bit from r_Shift can be used to precisely control how much delay is applied, bit 0 has 1 bit of delay on it, and bit 3 has 4 bits of delay.

Converting serial data to parallel data

Converting from serial data to parallel data is another common use of shift registers. This occurs when interfacing to off-chip signals that transmit data serially such as a UART Receiver. When data comes in over a UART, it need to be converted from serial data 1-bit wide to a parallel byte that the FPGA can look at.

  signal r_RX_Data   : std_logic := '0';
  signal r_Bit_Index : integer range 0 to 7 := 0;  -- 8 Bits Total
  signal r_RX_Byte   : std_logic_vector(7 downto 0) := (others => '0');

  p_UART_RX : process (i_Clk)
  begin
    if rising_edge(i_Clk) then

      r_Rx_Byte[7]   <= r_Rx_Data;       -- Data is sent least-significant byte first
      r_Rx_Byte[6:0] <= r_Rx_Byte[7:1];  -- shift right

      -- ABOVE DOES SAME THING AS:
      -- r_RX_Byte(r_Bit_Index) <= r_RX_Data;
            
      -- Check if we have sent out all bits
      if r_Bit_Index < 7 then
        r_Bit_Index <= r_Bit_Index + 1;
        r_SM_Main   <= s_RX_Data_Bits;
      else
        r_Bit_Index <= 0;   -- RECEIVE OF A UART BYTE COMPLETE HERE
  reg       r_Rx_Data   = 1'b1;  // Received UART Data
  reg [2:0] r_Bit_Index = 0; //8 bits total
  reg [7:0] r_Rx_Byte   = 0;
  
  always @(posedge i_Clock)
    begin
      // SNIPPET:         

      r_Rx_Byte[7]   <= r_Rx_Data;  // Data is sent least-significant byte first, so shift right
      r_Rx_Byte[6:0] <= r_Rx_Byte[7:1];
     
      // ABOVE DOES SAME THING AS:
      // r_Rx_Byte[r_Bit_Index] <= r_Rx_Data;
          
      // Check if we have received all bits
      if (r_Bit_Index < 7)
         r_Bit_Index <= r_Bit_Index + 1;
      else
         r_Bit_Index <= 0;  // RECEIVE OF A UART BYTE COMPLETE HERE

Converting parallel data to serial data

This is the opposite of the above and is used in UART Transmitter. When you want to transmit a byte over UART, it must first be serialized and sent out over the single UART line. A shift register can be used for this purpose.

  signal r_Bit_Index : integer range 0 to 7 := 0;  -- 8 Bits Total
  signal r_TX_Data   : std_logic_vector(7 downto 0) := (others => '0');
  
begin
  
  p_UART_TX : process (i_Clk)
  begin
    if rising_edge(i_Clk) then
      
      -- SNIPPET: 

      o_TX_Serial <= r_TX_Data(0);  -- Data is shifted out least-significant bit first.
      r_TX_Data(6 downto 0) <= r_TX_Data(7 downto 1);  -- Shift next bit into place.

      -- ABOVE DOES SAME THING AS:
      -- o_TX_Serial <= r_TX_Data(r_Bit_Index);

      -- Check if we have sent out all bits
      if r_Bit_Index < 7 then
        r_Bit_Index <= r_Bit_Index + 1;
      else
        r_Bit_Index <= 0;  // TRANSMIT OF A UART BYTE COMPLETE HERE
      end if;
  reg [2:0] r_Bit_Index = 0;
  reg [7:0] r_Tx_Data   = 0;
    
  always @(posedge i_Clock)
    begin       
     
      // SNIPPET:    

      o_TX_Serial    <= r_TX_Data[0];    // Data is shifted out least-significant bit first.
      r_TX_Data[6:0] <= r_TX_Data[7:1];  // Shift next bit into place.
   
      // ABOVE DOES SAME THING AS:
      // o_Tx_Serial <= r_Tx_Data[r_Bit_Index];
            
      // Check if we have sent out all bits
      if (r_Bit_Index < 7)
        begin
          r_Bit_Index <= r_Bit_Index + 1;
        end
      else
        begin
          r_Bit_Index <= 0;
        end
      end

Hopefully this article has given you a basic understanding of what a shift register is in an FPGA or ASIC. To see how to create your own shift register in either Verilog or VHDL, see the links below.

Create a Shift Register in Verilog

Shift Left, Shift Right in VHDL

FPGA-101