How to implement a shift register in VHDL

I wrote many posts on different VHDL
topics. Many of them deal with quite complex concepts.

Some days ago, I realized that I didn’t
write anything β€œsimple” dealing with basic hardware building blocks.

I realized that since I received many emails
and Telegram messages asking me to explain some lines of VHDL code. These
lines are relative to a simple shift register implementation.

Sometimes what is simple for you, is not for other people!

In this post, I would like to propose four different ways of implementing a shift register in VHDL.

First of all, let’s review what a shift
register is. It could be represented with a series of flip-flops connected in
series, where the output of one flip-flop is the input of the other.

In Figure 1 you can see a visual representation.

Figure 1 β€” shift register architecture example

As stated before, there are at least four different ways to describe such hardware structure in VHDL. The four descriptions are totally equivalent.

Try it yourself: click the bits to set i_data, then press Clock ↑ to see data shift through the registers.

Shift Register Interactive Demo
4 stages, 2-bit data, left-to-right visual flow
i_data
00
β†’
00
r0
β†’
00
r1
β†’
00
r2
β†’
00
r3
β†’
o_data
00
Ready

Shift register VHDL plain description

Plain description using signals

A plain description of the shift registers in Figure 1 is reported in the VHDL code below.

library ieee;
use ieee.std_logic_1164.all;

entity shift_register is
port (
    i_clk          : in  std_logic;
    i_rstb         : in  std_logic;
    i_data         : in  std_logic_vector(1 downto 0);
    o_data         : out std_logic_vector(1 downto 0));
end shift_register;

architecture rtl of shift_register is
signal r0_data         : std_logic_vector(1 downto 0);
signal r1_data         : std_logic_vector(1 downto 0);
signal r2_data         : std_logic_vector(1 downto 0);
signal r3_data         : std_logic_vector(1 downto 0);

begin

o_data  <= r3_data;

p_sreg : process(i_clk,i_rstb)
begin
    if(i_rstb='0') then
        r0_data    <= (others=>'0');
        r1_data    <= (others=>'0');
        r2_data    <= (others=>'0');
        r3_data    <= (others=>'0');
    elsif(rising_edge(i_clk)) then
        r0_data    <= i_data;
        r1_data    <= r0_data ;
        r2_data    <= r1_data ;
        r3_data    <= r2_data ;
    end if;
end process p_sreg;
end rtl;

Shift register VHDL description #1

In this case, each register is declared in
the architecture declarative part. For sure, this is a straightforward VHDL
description for a shift register.

As you should know, since flip-flops are declared as signals, you can modify the assignment order without changing the final result.

Plain description using variables

library ieee;
use ieee.std_logic_1164.all;

entity shift_register is
port (
    i_clk          : in  std_logic;
    i_rstb         : in  std_logic;
    i_data         : in  std_logic_vector(1 downto 0);
    o_data         : out std_logic_vector(1 downto 0));
end shift_register;

architecture rtl of shift_register is

begin


p_sreg : process(i_clk,i_rstb)
variable v0_data         : std_logic_vector(1 downto 0);
variable v1_data         : std_logic_vector(1 downto 0);
variable v2_data         : std_logic_vector(1 downto 0);
begin
    if(i_rstb='0') then
        v0_data    := (others=>'0');
        v1_data    := (others=>'0');
        v2_data    := (others=>'0');
        o_data     <= (others=>'0');
    elsif(rising_edge(i_clk)) then
        o_data     <= v2_data ;
        v2_data    := v1_data ;
        v1_data    := v0_data ;
        v0_data    := i_data;
    end if;
end process p_sreg;
end rtl;

Shift register VHDL description #2

Figure 2 and Figure 3 show the RTL view of shift register VHDL description #1 and description #2 respectively.

The RTL view is totally equivalent, i.e. the two VHDL codes implement the same hardware.

  • description #1 VHDL code for shift register implemented using signal
  • description #2 VHDL code for shift register implemented using variable

Figure 2 β€” shift register description #1 using signal RTL view

Figure 3 β€” shift register description #2 using variable RTL view

This approach is useful when you need different shift registers without declaring a lot of signals.

As you know, the variables are local to the process where you declare them. So, you can always use the same process implementing a different set of shift-registers. It is a way to encapsulate the code, something like a component instantiation.

In the case of a shift register implemented using variables, you must pay attention to the assignment order. For the variable the value is assigned immediately, it is not scheduled and it is performed immediately.

Synthesis tools handle variables by inferring the same flip-flop structure as signals. Despite the different simulation behavior, the synthesized hardware is identical when the code is written correctly. This is why the RTL view in Figure 3 matches Figure 2.

Shift register VHDL for-loop description

A more efficient VHDL shift register
implementation, in terms of VHDL code description, can be achieved using
a for-loop iterative statement. With respect to the shift register plain
description, the VHDL for-loop implementation can be parametrized.

In the VHDL code, we used a type declaration for the shift register so the number of shift registers to be implemented can be passed as constant or generic in the VHDL entity.

library ieee;
use ieee.std_logic_1164.all;

entity shift_register is
port (
    i_clk          : in  std_logic;
    i_rstb         : in  std_logic;
    i_data         : in  std_logic_vector(1 downto 0);
    o_data         : out std_logic_vector(1 downto 0));
end shift_register;

architecture rtl of shift_register is

type t_sreg is array(0 to 3) of std_logic_vector(1 downto 0);
signal r_data               : t_sreg;

begin

o_data     <= r_data(r_data'length-1) ;

p_sreg : process(i_clk,i_rstb)
begin
    if(i_rstb='0') then
        r_data    <= (others=>(others=>'0'));
    elsif(rising_edge(i_clk)) then
        r_data(0)    <= i_data;
        for idx in 1 to r_data'length-1 loop
            r_data(idx)    <= r_data(idx-1) ;
        end loop;
    end if;
end process p_sreg;
end rtl;

Shift register VHDL description #3

Even in this case, we can use a variable description for the shift register VHDL implementation. In Figure 4 is reported the RTL view for VHDL implementation of a shift register implemented using FOR-LOOP description #3

Figure 4 β€” shift register description #3 using FOR-LOOP RTL view

Shift register single line VHDL description

The last shift-register implementation is my preferred one. It is a very compact VHDL code description. You can implement a shift-register in a parametric way with a single line of VHDL code. Cool!

library ieee;
use ieee.std_logic_1164.all;

entity shift_register is
port (
    i_clk          : in  std_logic;
    i_rstb         : in  std_logic;
    i_data         : in  std_logic_vector(1 downto 0);
    o_data         : out std_logic_vector(1 downto 0));
end shift_register;

architecture rtl of shift_register is

type t_sreg is array(0 to 3) of std_logic_vector(1 downto 0);
signal r_data               : t_sreg;

begin

o_data     <= r_data(r_data'length-1) ;

p_sreg : process(i_clk,i_rstb)
begin
    if(i_rstb='0') then
        r_data    <= (others=>(others=>'0'));
    elsif(rising_edge(i_clk)) then
        r_data    <= i_data&r_data(0 to r_data'length-2);
    end if;
end process p_sreg;
end rtl;

Shift register VHDL description #4

In this description, the shift functionality is implemented using the assignment feature provided by VHDL. VHDL allows assigning objects of the same type in a single line of code.

Figure 5 β€” shift register description #4 using single line VHDL code RTL view

As you can see this shift register description takes full advantage of the power of VHDL description.

If you need to describe a huge shift register you can do it with a single line of VHDL code!

Of course, pay attention, you can fill an
FPGA with a single VHDL line of code!

As is clear from Figure 5 the single line VHDL shift register implementation produces the same output as the other three shift register descriptions.

Conclusion

In this post, we clarified how to implement
a shift register in VHDL using four different approaches. The first approach
(plain description) is very clear and straightforward. As a drawback, it is not parametrizable.

The second approach uses variables inside a
process. It is useful to encapsulate the code without declaring many signals.

The third approach uses the for-loop VHDL
statement. It is simple to read and understand, and it is parametrizable.

The fourth approach takes advantage of the
power of VHDL syntax. In this case, we can describe a shift register with a
single line of VHDL code. It is less intuitive but very elegant and compact.

The VHDL code relative to the shift register implementation above has been laid out using Intel Quartus II v 13 web edition

I hope you find this post useful, and if you have any question or you want to propose another shift register VHDL implementation, just comment below.

References

[1] Altera/Intel website

[2] https://www.mathworks.com/

[3] https://www.scilab.org