Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17255 Discussions

shift register mystery

Altera_Forum
Honored Contributor II
3,782 Views

Hi guys, I would like to implement a serial in serial out, parallel in parallel out combo shift register. Is it even possible, is it fantasy or is it just nonsense (please don't laugh if in fact it is) ? It's basically for a SPI , nothing inter-galactic. I also made a simple drawing to express better my idea. This is how I plan for it to work: 

 

rx_buffer saves data of received packet (step 5 on picture). on the next clock pulse after saving rx data, tx_buffer loads data in the registers (step 1). one bit by one bit is clocked-out of the mosi. in the same time, new data is clocked-in replacing tx_buffer data. process continues packet after packet.  

 

So I would like to know if this in fact can be done with vhdl. I am trying to code it but I'm having my doubts if it can happen. Thanks for all thoughts and replies.
0 Kudos
11 Replies
Altera_Forum
Honored Contributor II
2,157 Views

In times like this, what I do is ask, is there a 7400 or 4000 series logic IC that does the job. In this case there is, the 74xx166 

The great thing about those is that a lot of manufacturers give you a logic diagram of how they work, e.g. here: 

http://www.ti.com/lit/ds/symlink/sn74als166.pdf 

 

You can see from that datasheet what the logic for a parallel load shift register is. (parallel out is dead easy to add). 

Some simplifications to that diagram can be made. e.g. they show a J-K flip flop, hence the two data inputs connected by a not gate. The FPGA has d-type flip flops, which are interchangeable in this case. 

 

The one sticking point about SPI is that the incoming data is read on the opposite edge of the outgoing data. So the way I got around that in one design is to add a register on the input of the shift register which clocks on the opposite edge, that way it re-times the incoming data ready to be clocked in to the shift register.
0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

It should be rather straight forward. You cannot do exactly what you have drawn because you then have multiple drivers on each register D input. 

All you need is a mux on each flip flop, and another signal to select the parallel load or MISO input
0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

Hello, I just started learning VHDL after working a few years with assembly and C and I'm having some difficulties understanding the semantics of this phrase. 

 

temp <= temp(6 DOWNTO 0) & d; 

 

from this sequence 

 

library ieee ; use ieee.std_logic_1164.all; use work.all; entity gpr is port (d, ck : in std_logic; q: out std_logic_vector (7 downto 0)); end gpr; architecture reg of gpr is signal temp: std_logic_vector (7 downto 0); begin process (ck) begin if (ck = '1' and ck'event) then temp <= temp(6 DOWNTO 0) & d; end if; end process; q <= temp; end reg;  

 

Would anyone care to give some detail of how that particular phrase represents the structure of a shift register and how the information is passed to each flip flop sequentially and not all together? 

 

Thank you.
0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

If you rewrite: 

 

temp <= temp(6 downto 0) & d; 

 

as 

 

temp(7 downto 0) <= temp(6 downto 0) & d; 

 

then you can see that d is assigned to temp(0), temp(0) assigned to temp(1),temp(1) assigned to temp(2) etc. 

i.e. keep shifting at each clock edge. 

 

This is smart way instead of having individually named registers
0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

I guess it is a smart way to get rid of the (time consuming) details, I was not sure how the assignment was done. Thanks

0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

Hi , I made you this diagram, hope it helps:

0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

Thank you for your answers, on the same subject if I would want a bidirectional register how would the previous line would look like, tried: 

 

temp <= temp (0 to 6) & d; 

 

but got an error, it seems that it is not so simple just to reverse order.
0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

if you signal is declared as (n downto m), you cannot slice it as (x to y). 

 

By Bidrectional register, do you mean one that can shift in either direction? in this case, you need a control signal to control the direction and have two explicit cases. 

 

if shift_left = '1' then temp <= temp(6 downto 0) & ip; else temp <= ip & temp(7 downto 1); end if;
0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

I see, indeed I need a GPR that can be used to shift data in both directions, from your example it seems that the identifier (or instruction) for shift right is 6 downto 0 and the identifier for shift left is 7 downto 1 am I correct to assume this, i'm asking because I may need to load data in parallel not just serially and just sift data left or right according to one's needs. 

 

Sorry to be a hassle for you , thanks for your help so far :D as you can see i want to understand not just throw code around.
0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

Hi iulianvalentin, try this code: 

 

package instructions is 

type instructions is(load, s_right, s_left); 

end instructions; 

 

library ieee; 

use ieee.std_logic_1164.all; 

use work.instructions.all; 

 

entity shifty is port( 

clock : in std_logic; 

--shsel : in std_logic_vector(1 downto 0); 

shsel : in instructions; 

serial_in : in std_logic; 

d : in std_logic_vector(7 downto 0); 

serial_out : out std_logic; 

q : out std_logic_vector(7 downto 0)); 

end entity; 

 

architecture arch of shifty is 

signal content: std_logic_vector(7 downto 0); 

begin 

process(clock) 

begin 

if(rising_edge(clock))then 

case shsel is 

when load => content <= d; --load 

when s_right => content <= serial_in & content(7 downto 1); --shift right, pad with bit from serial_in 

when s_left => content <= content(6 downto 0) & serial_in; --shift left, pad with bit from serial_in 

when others => null; 

end case; 

end if; 

end process; 

 

q <= content; 

serial_out <= content(0) when shsel = s_right else 

content(7) when shsel = s_left else 'Z'; 

 

end arch;
0 Kudos
Altera_Forum
Honored Contributor II
2,157 Views

Thank you for the example.

0 Kudos
Reply