0
0
VhdlHow-ToBeginner · 4 min read

VHDL Code for Universal Shift Register with Example

A universal shift register in VHDL is a register that can shift data left, right, load parallel data, or hold its value based on control signals. You define it using a process with a clock and control inputs to select the operation mode. The code uses a case statement inside a clocked process to implement these modes.
📐

Syntax

The universal shift register uses a clocked process with inputs for data, shift direction, load, and enable signals. Inside the process, a case statement controls the operation mode:

  • clk: Clock signal triggering register updates.
  • reset: Asynchronous reset to clear the register.
  • shift_left: Control to shift bits left.
  • shift_right: Control to shift bits right.
  • load: Control to load parallel data.
  • data_in: Parallel data input.
  • serial_in_left and serial_in_right: Serial inputs for shifting.
  • q: Register output.
vhdl
process(clk, reset)
begin
  if reset = '1' then
    q <= (others => '0');
  elsif rising_edge(clk) then
    case mode is
      when "00" => q <= q; -- Hold
      when "01" => q <= serial_in_right & q(q'left downto 1); -- Shift right
      when "10" => q <= q(q'right-1 downto 0) & serial_in_left; -- Shift left
      when "11" => q <= data_in; -- Load
      when others => q <= q;
    end case;
  end if;
end process;
💻

Example

This example shows a 4-bit universal shift register with synchronous reset and a 2-bit mode input to select the operation: hold, shift right, shift left, or load parallel data.

vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity UniversalShiftRegister is
  Port (
    clk           : in  std_logic;
    reset         : in  std_logic;
    mode          : in  std_logic_vector(1 downto 0); -- 00: Hold, 01: Shift Right, 10: Shift Left, 11: Load
    data_in       : in  std_logic_vector(3 downto 0);
    serial_in_left  : in  std_logic;
    serial_in_right : in  std_logic;
    q             : out std_logic_vector(3 downto 0)
  );
end UniversalShiftRegister;

architecture Behavioral of UniversalShiftRegister is
  signal reg_q : std_logic_vector(3 downto 0) := (others => '0');
begin
  process(clk, reset)
  begin
    if reset = '1' then
      reg_q <= (others => '0');
    elsif rising_edge(clk) then
      case mode is
        when "00" =>
          reg_q <= reg_q; -- Hold
        when "01" =>
          reg_q <= serial_in_right & reg_q(3 downto 1); -- Shift Right
        when "10" =>
          reg_q <= reg_q(2 downto 0) & serial_in_left; -- Shift Left
        when "11" =>
          reg_q <= data_in; -- Load
        when others =>
          reg_q <= reg_q;
      end case;
    end if;
  end process;

  q <= reg_q;
end Behavioral;
⚠️

Common Pitfalls

Common mistakes include:

  • Not using a clock edge for updates, causing asynchronous behavior.
  • Forgetting to reset the register, leading to unknown initial values.
  • Incorrect bit slicing when shifting left or right.
  • Not handling all mode cases, which can cause latches or unintended behavior.

Always use a synchronous process triggered by rising_edge(clk) and cover all cases in the case statement.

vhdl
process(clk)
begin
  if rising_edge(clk) then
    if mode = "01" then
      -- Wrong: shifting bits incorrectly
      q <= q(2 downto 0) & serial_in_right; -- This shifts left instead of right
    end if;
  end if;
end process;

-- Correct shifting right:
process(clk)
begin
  if rising_edge(clk) then
    if mode = "01" then
      q <= serial_in_right & q(3 downto 1); -- Shift right correctly
    end if;
  end if;
end process;
📊

Quick Reference

Mode Control for Universal Shift Register:

ModeOperation
00Hold (no change)
01Shift Right (insert serial_in_right)
10Shift Left (insert serial_in_left)
11Load Parallel Data (data_in)
ModeOperation
00Hold (no change)
01Shift Right (insert serial_in_right)
10Shift Left (insert serial_in_left)
11Load Parallel Data (data_in)

Key Takeaways

Use a clocked process with rising_edge(clk) to update the register synchronously.
Control the operation mode with a 2-bit input to select hold, shift left, shift right, or load.
Always reset the register to a known state to avoid unknown outputs.
Be careful with bit slicing when shifting left or right to avoid data corruption.
Cover all mode cases in the case statement to prevent unintended latches.