Use of concatenation to make shift reg - VHDL

Thread Starter

BrianH

Joined Mar 21, 2007
43
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:

Rich (BB code):
elsif (Man_Clock'event and Man_Clock = '1') then -- rising edge triggered
          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,

Brian
 

guitarguy12387

Joined Apr 10, 2008
359
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.
 

Thread Starter

BrianH

Joined Mar 21, 2007
43
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:

Rich (BB code):
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!

BrianH.
 

Thread Starter

BrianH

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

Rich (BB code):
library IEEE;
use IEEE.std_logic_1164.all;

entity Register_E is 
        port 	(
		Set_Alarm_Level 	: in std_logic; -- this is the serial_in pin
		Reset_E 		: in std_logic;
		Man_Clock	        : in std_logic; -- this is the clock pin
		Stored_Alarm_Level      : out std_logic_vector (3 downto 0) := "0000" -- this is the parallel_out pin
		);
end Register_E;

architecture Register_E_RTL of Register_E is
    signal Temp_Alarm_Level    : std_logic_vector (3 downto 0); -- this temp signal is required otherwise compiler complains
begin

process(Man_Clock, Reset_E)
        begin
        if (Reset_E = '1') then
			Stored_Alarm_Level <= "0000";
        elsif (Man_Clock'event and Man_Clock = '1') then -- rising edge triggered
			Temp_Alarm_Level <= Set_Alarm_Level & Temp_Alarm_Level (3 downto 1);
        end if;
end process;

Stored_Alarm_Level <= Temp_Alarm_Level ; -- update the parallel_out pin.

end Register_E_RTL;
 
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
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!

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!
When using an HDL, you cannot read from an output type vairable. The standard solution is to use a temp variable like you have.
 
Top