- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for the example.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page