Use of concatenation to make shift reg - VHDL

Discussion in 'Programmer's Corner' started by BrianH, Feb 6, 2011.

  1. BrianH

    Thread Starter Active Member

    Mar 21, 2007
    Hi all,

    I'm trying to get to grips with this VHDL language. As part of that I'm following some exercises, one of which asks me to write some VHDL code to perform a 4-bit shift register operation (serial in, parallel out).

    So, I had a very obvious idea in mind for this that I knew would work, but I decided to do some googling to see if there were any better solutions that I could try. I found reference to the use of the concatenation operator for shift register operation. It goes something like this:

    Code ( (Unknown Language)):
    1. elsif (Man_Clock'event and Man_Clock = '1') then -- rising edge triggered
    2.           Parallel_Out <= Serial_In & Parallel_Out (3 downto 1);
    I tried this technique in my own program (in fact the above is my own use of the technique) and it works. The only question I have now is; why does it work?!

    I understand that concatenation is the act of joining two variables together. I have experience of this with strings in the C language.

    So, I understand how a bit on the Serial_In can be added on to the 4-bit Parallel_Out signal. What I don't understand, is how the shifting works. I can see that it has something to do with operating on the Parallel_Out signal using "3 downto 1" instead of "3 downto 0", so the right-most bit is not part of the concatenation, but I can't quite grasp why this means it would be shifted?

    Can anyone advise?

    Thanks very much,

  2. guitarguy12387

    Active Member

    Apr 10, 2008
    Probably the easiest thing to do would be to write the output for several clock cycles, keeping track of a particular bit. You will see it 'shifting' from MSB to LSB. Think of it as a FIFO if you like.

    More explicitly, the first clock cycle, you're appending Serial_in (call this bit 'A') to the MSB of Parallel_Out and then 'chopping off' the LSB of Parallel_Out. Bit A is now the MSB of Parallel_Out. The next clock tick, a new bit from Serial_In is added and the LSB of Par_Out is again chopped. Bit A (which was previously MSB of Par_Out) is now shifted down one bit. And so on and so on.
    BrianH likes this.
  3. BrianH

    Thread Starter Active Member

    Mar 21, 2007
    Thanks for your response guitarguy.

    Your suggestion to write the output for several clock cycles is actually the same idea I initially had but as I am inexperienced with VHDL stuff I wondered if there was a better way, which is why I played around with the concatenation method I found on a couple of websites.

    Thanks for your explanation. One last thing that had me sratching my head:

    Initially I could not get the program I wrote to work because the compiler complained that it was not able to read "Parallel_Out". It was specifically complaining about the following line:

    Code ( (Unknown Language)):
    1. Parallel_Out <= Serial_In & Parallel_Out (3 downto 1);
    In the end I found that to make it work I had to use a temporary signal within the process in place of "Parallel_Out", and then update Parallel_Out afterwards by making it equal to my temporary signal.

    I don't quite understand why this is the case, but it certainly does work this way!

  4. BrianH

    Thread Starter Active Member

    Mar 21, 2007
    Here's the full code, after I got it working:

    Code ( (Unknown Language)):
    2. library IEEE;
    3. use IEEE.std_logic_1164.all;
    5. entity Register_E is
    6.         port    (
    7.         Set_Alarm_Level     : in std_logic; -- this is the serial_in pin
    8.         Reset_E         : in std_logic;
    9.         Man_Clock           : in std_logic; -- this is the clock pin
    10.         Stored_Alarm_Level      : out std_logic_vector (3 downto 0) := "0000" -- this is the parallel_out pin
    11.         );
    12. end Register_E;
    14. architecture Register_E_RTL of Register_E is
    15.     signal Temp_Alarm_Level    : std_logic_vector (3 downto 0); -- this temp signal is required otherwise compiler complains
    16. begin
    18. process(Man_Clock, Reset_E)
    19.         begin
    20.         if (Reset_E = '1') then
    21.             Stored_Alarm_Level <= "0000";
    22.         elsif (Man_Clock'event and Man_Clock = '1') then -- rising edge triggered
    23.             Temp_Alarm_Level <= Set_Alarm_Level & Temp_Alarm_Level (3 downto 1);
    24.         end if;
    25. end process;
    27. Stored_Alarm_Level <= Temp_Alarm_Level ; -- update the parallel_out pin.
    29. end Register_E_RTL;
  5. guitarguy12387

    Active Member

    Apr 10, 2008
    It's less to do with VHDL and more to do with thinking of the actual circuit. Think about how a shift register works. Think about what concatenation does. On a cycle by cycle basis.

    In any case, glad it works!

    When using an HDL, you cannot read from an output type vairable. The standard solution is to use a temp variable like you have.
  6. cupcake


    Sep 20, 2010
    wrong section