Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Implementing shift register in Vhdl

Status
Not open for further replies.

panos_papajohn

Member level 2
Joined
Mar 18, 2011
Messages
46
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,640
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);
  signal load: std_logic;
  begin 
  
    process (C, ALOAD, D)
      begin
        if (ALOAD='1') then
          tmp <= D;
			  for c in 8 downto 1 loop
					load <= tmp(c-1);
					SO <= load;
			  end loop;
        end if;
				   

    end process;
	

end archi;

89_1305231427_thumb.png
[/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?

Thanks in advance
 

Attachments

  • Capture.PNG
    Capture.PNG
    28.1 KB · Views: 116

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.
 

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?
 

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 .
 

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
    if (ALOAD='1') then
      tmp <= D;
    elsif rising_edge(C) then
      tmp <= tmp(6 downto 0) & '0';
      SO <= tmp(7);  
    end if;
  end;
 
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
 

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 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?
 

yes

Code:
process(clk)
begin
  if rising_edge(clk) then
    if ALOAD = '1' then
      --do stuff
    end if;
  end if;
end process;
 

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
  if (SLOAD='1') then
    tmp <= D;
  else
    tmp <= tmp(6 downto 0) & '0';
  end if;
  SO <= tmp(7);  
end if;
 

FvM and TrickyDicky I tried both your ways but I don;t get the results . This the code :entity SPI is
port(clk, ALOAD : in std_logic;
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;

process (clk, ALOAD, data1,SPI_signal,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
if (ALOAD='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
64_1305757953_thumb.png
[/url][/IMG]
 

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.
 

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:

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.
 
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?
 

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
  );

END AD5061;

ARCHITECTURE rtl OF AD5061 IS
   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:
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.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top