# Implementing shift register in Vhdl

Status
Not open for further replies.

#### panos_papajohn

##### Member level 2
Hi everyone ,

Im trying to implement a parallel in/serial out shift register in VHDL. I have written this code but when I run the simulation the results are the expected ones. Can anyone help me understand how the shifting is created? This is my code and below is the result from the simulation.

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity shift is
port(C, SI, ALOAD : in std_logic;
D   : in std_logic_vector(7 downto 0);
SO  : out std_logic);
end shift;
architecture archi of shift is
signal tmp: std_logic_vector(7 downto 0);
begin

begin
tmp <= D;
for c in 8 downto 1 loop
end loop;
end if;

end process;

end archi;
[/url][/IMG]

This code it was supposed to shift all the loaded data to the SO but instead I can get only the MSB. Any ideas?

#### Attachments

• 28.1 KB Views: 2

#### Alexium

##### Full Member level 2
For loop is not doing what you think it is, I guess. It performs all iterations at once, in parallel, in the single clock cycle.

---------- Post added at 23:38 ---------- Previous post was at 23:35 ----------

Try using a counter or a "&" operator.

#### TrickyDicky

In VHDL, signal assignments only take the last thing assigned to them, and they are not updated immediatly like variables.

SO in this case, when ALOAD goes to a '1', tmp dates the previous value of D, load takes the old value of (not current D, but old D) and S0 only takes the last thing assigned to it, which is old D(1).

Also, without a clock, how do you expect to shift it out bit by bit?

#### panos_papajohn

##### Member level 2
Actually I want to implement a SPI protocol that's why I used the shift reg. I used variable before using a signal but the results were the same. How am I going to use the concatenate operator since the output is LOGIC and the signal id LOGIC_VECTOR? I had a clock but I had commented it .

#### FvM

##### Super Moderator
Staff member
As TrickyDicky said, a shift register won't work without a clock. A basic SR looks like below. Of course, there are various possible variations. In most cases, you would rather want a synchronous (SLOAD) than an asynchronous (ALOAD) action. In the example, SO is delayed by a clock cycle, because it's assigned "under" rising_edge(C). You can get it undelayed by moving the assignment out of the process.

Code:
process (C, ALOAD,D)
begin
tmp <= D;
elsif rising_edge(C) then
tmp <= tmp(6 downto 0) & '0';
SO <= tmp(7);
end if;
end;

points: 2

### RAVINDRA SINGH

points: 2

#### panos_papajohn

##### Member level 2
FvM thank you very much for the reply the code works fine (as you would already know ). Can I ask sth else? When I make changes to my VHDL script how can I update my testbench file too? I m using ISE13.1

#### panos_papajohn

##### Member level 2
Does anyone know how to shift my data without having to make a transition to ALOAD? I want when the ALOAD has the value '1' to continuously shift data on the output. When I change the code to accept ALOAD with '1' my output has a constant value without any shift. I dont know if this is possible but I want to change it cause I interconnect this block with a DDS and when data are available to the output of DDS the ready signal is constantly at '1'.
Thanks

#### TrickyDicky

without a clock, your idea is impossible

#### panos_papajohn

##### Member level 2
TrickyDicky I know that I have to use a clock. I use this ALOAD as a ready signal to know that I have data for my input. But when I run the simulations I must have a transition from '0' to '1' on the ALOAD in order for the ddata to shift. I want when ALOAD is '1' the data to be shifted and when its '0' nothing to happen. Is this possible?

#### TrickyDicky

yes

Code:
process(clk)
begin
if rising_edge(clk) then
--do stuff
end if;
end if;
end process;

#### FvM

##### Super Moderator
Staff member
The name ALOAD usually means asynchronous load. What you're apparently asking for is a synchronous load, in fact better suited in most cases.

Code:
if rising_edge(C) then
tmp <= D;
else
tmp <= tmp(6 downto 0) & '0';
end if;
SO <= tmp(7);
end if;

#### panos_papajohn

##### Member level 2
FvM and TrickyDicky I tried both your ways but I don;t get the results . This the code :entity SPI is
D : in std_logic_vector(11 downto 0);
SO : out std_logic;
clock_out : OUT STD_LOGIC;
chip_select : OUT STD_LOGIC);
end SPI;
architecture archi of SPI is

signal SPI_signal: std_logic_vector(31 downto 0) := (others => '0');
signal data1 : std_logic_vector (11 downto 0):= (others => '0');
signal clock : std_logic ;

begin
data1 <=D;

variable chip : std_logic;
begin

-- Shift registers implements the SPI communication

--Disable DAC

chip :='0';
chip_select <= chip;

--Create the data stream for the ADC on the SPARTAN3E board.

if (clk'event and clk='1') then
SPI_signal <= "11111111"& "0011"& "0000"& data1 & "1111";

else
SPI_signal <= SPI_signal(30 downto 0) & '0';
end if;
SO <= SPI_signal(31);

--Enable DAC for the data conversion
end if;
chip :='1';
chip_select <= chip;

end process;

--Clock output for the DAC

clock<=clk;
clock_out <= clock;

end archi;

I both occasions I only see the first bit in the output. Can you please run my code to see yourself. This is the result I get from the second code
[/url][/IMG]

#### FvM

##### Super Moderator
Staff member
I only see the first bit in the output.
Quite exepectable, if the LOAD signal isn't deasserted again.

The chip_select assignments are pretty useless at present, only the last one gets effective, setting chip_select to '1' permanently.

As a general comment, you have been initially asking for a shift register. For a SPI master, additional points have to be taken into consideration. A clear specification should be the starting point, e.g. intended SPI mode, required timing of CS related to SCK. Original SPI uses an active low select, by the way.

#### panos_papajohn

##### Member level 2
FvM I want to connect a DDS core before the SPI interface. The DDS core has a ready signal for output when the data are valid. So I want to check when this signal is ready in order to start the transmission through the SPI. I sent this data to the DAC (http://cds.linear.com/docs/Datasheet/2604fd.pdf). The SPI interface has 5 lines: MOSI , MISO, SCLK, CS, CLR. I read that the MISO bus is used for checking if the data have be sent correctly that's why I didn't use it in my design. The device can receive a max clock of 50Mhz. My board has 50MHz oscillator. Can i use that directly without reducing the frequency with the gbufs of the FPGA? Why do we need a relation between the CS and the SCLK? The CS will be low every time we have data to send. I know I was asking for a shift register, cause I thought that is how I could implement the SPI, I am sorry for the confusion. Oh the mode of the SPI is 0

Last edited:

#### FvM

##### Super Moderator
Staff member
I know I was asking for a shift register, cause I thought that is how I could implement the SPI
Of course SPI is basically a shift register, but some details have to considered. I suggest to study data sheet figure 1 and the related timing specification. Particularly pay attention to t1, t2, t6 and t10. (setup and hold times for DI and nCS). It clarifies, that both signals have to be set on the falling edge of SCK, or SCK has to be inverted on output. The mode operation is usually designated SPI mode 0 (referring to the original Motorola syntax).

Generally, you can use the 50 MHz system clock as SCK output directly. If highest speed isn't required, it may be more easy to generate SCK in the shift register logic. It's also an option to run SCK continuously or only during data transmission.

panos_papajohn

### panos_papajohn

points: 2

#### panos_papajohn

##### Member level 2
FvM excuse my ignorance but I am new to VHDL and when I see timings I always think of delays, and I know that you can't have delays in your code unless its a testbench file. Moreover I have learnt that for all the synchronous functions you need a process and an if statement that checks the rising or the falling edge. So how Im I going to sent the data before checking the clock in order to meet the t1 specifications?

#### FvM

##### Super Moderator
Staff member
I know that you can't have delays in your code unless its a testbench file.
In the first place, these timings are design constraints, that have to be kept. If delays are required, that the logic device can't generate by nature, they have to be implemented in a synchronous way.
So how Im I going to sent the data before checking the clock in order to meet the t1 specifications?
I suggested a method in my post explicitely. It's about using the negative clock edge. This would be my suggestion, if the 50 MHz sysclock is used for SCK. If SCK is generated in your logic, you can e.g. set DO on one clock edge and SCK on the next.

P.S.: Here's an example of the second method, in contrast to your rqeuirements, it's setting outputs on rising edge:
Code:
ENTITY AD5061 IS

PORT
(
-- Globale Signale
CLK         : IN  STD_LOGIC;
RESET        : IN STD_LOGIC;
data        : IN   UNSIGNED(15 downto 0);
dav         : IN STD_LOGIC;
DACCLK      : OUT STD_LOGIC;
nCS_DAC   : OUT STD_LOGIC;
MOSI       : OUT STD_LOGIC
);

SIGNAL sr         : STD_LOGIC_VECTOR(23 downto 0);
SIGNAL bitcnt     : INTEGER RANGE 0 TO 24;
SIGNAL DACCLKi    : STD_LOGIC;
BEGIN
PROCESS (clk)

BEGIN
IF reset = '1' THEN
bitcnt <= 0;
nCS_DAC <= '1';
DACCLKi <= '0';
ELSIF rising_edge(clk) THEN
IF dav = '1' AND bitcnt = 0 THEN
DACCLKi <= '1';
sr <= x"00" & STD_LOGIC_VECTOR(data);
nCS_DAC <= '0';
bitcnt <= 24;
ELSIF bitcnt > 0 THEN
DACCLKi <= NOT DACCLKi;
IF DACCLKi = '0' THEN -- this is a rising edge
bitcnt <= bitcnt - 1;
IF bitcnt > 1 THEN
nCS_DAC <= '0';
sr <= sr(22 downto 0) & "0";
ELSE
nCS_DAC <= '1';
END IF;
END IF;
ELSE
DACCLKi <= '0';
END IF;
END IF;
END PROCESS;
DACCLK <= DACCLKi;
MOSI <= sr(23);
END rtl;

Last edited:
panos_papajohn

### panos_papajohn

points: 2

#### panos_papajohn

##### Member level 2
Ok FvM thank you .I ll try this and I let you know. Sorry if I ve been annoying .

Status
Not open for further replies.