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

Asynchronous load

Altera_Forum
Honored Contributor II
6,079 Views

This is a shift register question that I'm looking to get some light shed on. I have a 4 16bit shift registers that I'm using to detect a pattern. I feed bits into the shift regs until they match a pattern, at which point I replace the entire contents of the 4 shift registers with something else in a parallel load. The problem is that on one cycle, the pattern is detected and on the next clock cycle, the parallel load occurs. But also occurring on this cycle is the normal serial load. So the parallel load and the serial load collide and the parallel load seems to win and the 4 bits that I wanted to be shifted in serially are lost. Is it possible to do the comparison and load on the same cycle so that the first set of 4 bits on the serial input don't get lost? Is there a special shift register setting for this? 

 

There's a setting for asynchronous load in lpm_shiftreg but its greyed out 

 

Thanks
0 Kudos
36 Replies
Altera_Forum
Honored Contributor II
840 Views

readEN is a signal that will be unrelated to clock meaning that I'll be asserting readEN via some switch or something.  

 

How do I correctly register readEN? Also, do I then have to register all input signals (like validin?)
0 Kudos
Altera_Forum
Honored Contributor II
840 Views

 

--- Quote Start ---  

do I then have to register all input signals 

--- Quote End ---  

Yes, if they are actually unrelated to clk. In a synchronous FPGA design, typically a few external signals need synchronization.
0 Kudos
Altera_Forum
Honored Contributor II
840 Views

validin is an external signal generated by another board so I definitely think it would need to be registered too. 

 

What's the appropriate way to register the signals? Do I just say "regReadEN <= readEN" at the top of the process block and then use regReadEN instead of readEN everywhere in my code or is that asking for trouble?
0 Kudos
Altera_Forum
Honored Contributor II
840 Views

So I went ahead and added these two lines right under the elsif(clk'event and clk='1'): 

validinreg <= validin; readENreg <= readEN;  

 

Then I went ahead and changed all of the references to valdin and readEN to their registered counterparts. This did not work as intended however and there were still problems. Of course, when I went to test what exactly the problem was by introducing some output signals, the problems went away and it worked so I'm at a loss...
0 Kudos
Altera_Forum
Honored Contributor II
840 Views

It's basically correct to register unrelated signals this way. Using a single register stage actually still keeps a finite risk of metastable events, so two cascaded registers are usually suggested. The likelihood of metastability is however low and the effect doesn't show up in simulation, so it's definitely not related to the presently observed problems. 

 

Apart from need for registering, there are possibly other problems in the design.
0 Kudos
Altera_Forum
Honored Contributor II
840 Views

Apart from adding the registers which I've done, how do you go about troubleshooting a design that, as soon as you add output signals so you have a clue of whats going on, starts to work?

0 Kudos
Altera_Forum
Honored Contributor II
840 Views

Two points. 

 

The problem is most likely related to timing issues. Different place and route causes a variation. 

 

You can visualize internal signals in the Quartus simulator without exposing them as output ports, just select internal signals directly in the waveform node finder.
0 Kudos
Altera_Forum
Honored Contributor II
840 Views

Not all of the internal signals are there though. Many of them aren't in fact.

0 Kudos
Altera_Forum
Honored Contributor II
840 Views

I think the best thing to do is start from scratch with a good design plan and do this correctly. You guys have been really helpful so far and I really appreciate it. Perhaps you can let me know if I'm on the right track? 

 

Here's what I'm working on. I need to store ethernet frames in SRAM so that I can retrieve them later. 

 

An ethernet frame contains a preamble, a start frame delimiter, and then a bunch of other stuff. When I receive a frame, it will arrive with a validin signal. The validin signal will be high at some point between the beginning of the preamble and right before the start frame delimiter and stay high as long as the frame is valid. I want to store everything from the start frame delimiter to the end of the frame in memory. I'll also want to add my own delimiter to let me know when I've reached the end of the frame. 

 

At some point I will want to retrieve these frames from memory but before I send them out, I need to attach a preamble to the front of them. I also need to preserve a minimum frame gap between two consecutive frames that I read out of memory so I want to write out 12 bytes of zeros. 

 

Here's a diagram of what it looks like in my head: 

http://img143.imageshack.us/img143/3365/design.png 

 

In the front I have 4 2-bit shift registers to check for the start frame delimiter (1010 1011). I'm doing everything in 4 bits because thats what I get on my input. When I see the frame, I start writing the entire frame to memory until validin goes low, and then I write 24 nibs of 1's to signify the end of the frame. 

 

On the other side of memory I have a 4 1-bit shift registers which hold the data coming out of memory. First I look for the start frame delimiter, if I find it, I load a preamble into the 4-24bit shift registers, and then start sending it out until I count 24 consecutive "1111"s in the 4 1-bit shift registers which signifies the end of frame delimiter. At this point there should be 24 nibs of 1's in the 4-24bit shift registers. I parallel load 24 nibs of 0's to keep a gap between frames. Then I stop reading from memory and allow all of those 0's to shift out of the 24 bit registers. At this point, I'm ready to start again. 

 

It's fairly simple with a few complexities. I think its just important to make sure I get started out on the right foot. 

 

Here's my starting skeleton (I remembered to register all of the inputs): 

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity fixer is port ( clk,reset : in std_logic; input: in std_logic_vector(3 downto 0); -- the input ethernet frame validin: in std_logic; --the valid signal that we get readEN: in std_logic; --high when we want to read from memory validout: out std_logic; --high when we're sending a valid frame out output : out std_logic_vector(3 downto 0) --output has value if we're reading ); end fixer; architecture structure of fixer is --registering inputs signal reg_validin : std_logic; signal reg_input : std_logic_vector(3 downto 0); signal reg_readEN : std_logic; -------------------------------- signal wren : std_logic; -- memory write enable signal load: std_logic; -- load enable for the 24 bit shift registers signal stop: std_logic; -- tells memory not to read and the 1 bit shift registers not to change their value signal sfd: std_logic_vector(7 downto 0); -- parallel output of 4 - 2 bit shift registers signal qin : std_logic_vector (3 downto 0); --input to memory signal send: std_logic_vector(3 downto 0); --output of shift set of shift registers, to memory unless we're loading our end of frame delimiter signal hold1: std_logic_vector (3 downto 0); --output of memory signal hold2: std_logic_vector (3 downto 0); --output of 4 - 2 bit shift registers and input to 4 - 24 bit shift registers signal address: std_logic_vector(14 downto 0);--address to read and write from memory at signal outload0: std_logic_vector(23 downto 0); --vectors to load into the 24 bit shift registers signal outload1: std_logic_vector(23 downto 0); signal outload2: std_logic_vector(23 downto 0); signal outload3: std_logic_vector(23 downto 0); component shiftreg2 is PORT ( clock : IN STD_LOGIC ; sclr : IN STD_LOGIC ; shiftin : IN STD_LOGIC ; q : OUT STD_LOGIC_VECTOR (1 DOWNTO 0); shiftout : OUT STD_LOGIC ); end component; component framestore is port ( clk,reset : in std_logic; input: in std_logic_vector(3 downto 0); -- the input ethernet frame address: in std_logic_vector(14 downto 0); valid: in std_logic; --valid signal that comes with input readEN: in std_logic; --high when we want to read from memory output : out std_logic_vector(3 downto 0) --output, has value if we're reading ); end component; component shiftreg1 IS PORT ( clock : IN STD_LOGIC ; enable : IN STD_LOGIC ; sclr : IN STD_LOGIC ; shiftin : IN STD_LOGIC ; q : OUT STD_LOGIC_VECTOR (0 DOWNTO 0); shiftout : OUT STD_LOGIC ); END component; component shiftreg24 is PORT ( clock : IN STD_LOGIC ; data : IN STD_LOGIC_VECTOR (23 DOWNTO 0); load : IN STD_LOGIC ; sclr : IN STD_LOGIC ; shiftin : IN STD_LOGIC ; shiftout : OUT STD_LOGIC ); end component; begin process(clk,reset) begin if(reset = '1') then wren <= '0'; load <= '0'; stop <= '0'; address <= "000000000000000"; outload0 <= "000000000000000000000000"; outload1 <= "000000000000000000000000"; outload2 <= "000000000000000000000000"; outload3 <= "000000000000000000000000"; elsif(clk'event and clk = '1') then --register inputs reg_input <= input; reg_validin <= validin; reg_readEN <= readEN; --figuring out address --writing to memory --reading from memory end if; end process; --input to memory bit3in: shiftreg port map(clk,reset,input(3),sfd(7 downto 6),send(3)); bit2in: shiftreg port map(clk,reset,input(2),sfd(5 downto 4),send(2)); bit1in: shiftreg port map(clk,reset,input(1),sfd(3 downto 2),send(1)); bit0in: shiftreg port map(clk,reset,input(0),sfd(1 downto 0),send(0)); --memory mem: framestore port map(clk,reset,qin,address,wren,readEN and not stop,hold1); --output of memory bit3hold: shiftreg1 port map(clk,readEN and not stop,reset,hold1(3),hold2(3)); bit2hold: shiftreg1 port map(clk,readEN and not stop,reset,hold1(2),hold2(2)); bit1hold: shiftreg1 port map(clk,readEN and not stop,reset,hold1(1),hold2(1)); bit0hold: shiftreg1 port map(clk,readEN and not stop,reset,hold1(0),hold2(0)); --24 bit shift registers bit3out: shiftreg24 port map(clk,outload3,load,reset,hold2(3),output(3)); bit2out: shiftreg24 port map(clk,outload2,load,reset,hold2(2),output(2)); bit1out: shiftreg24 port map(clk,outload1,load,reset,hold2(1),output(1)); bit0out: shiftreg24 port map(clk,outload0,load,reset,hold2(0),output(0)); end structure;
0 Kudos
Altera_Forum
Honored Contributor II
840 Views

 

--- Quote Start ---  

I think the best thing to do is start from scratch with a good design plan and do this correctly. 

--- Quote End ---  

Absolutely. 

 

There are however some unclear points with the design enviroment. You consider the control signals (readEn, validin) as asynchronous and register them to clk. But why the data stream can be assumed synchronous and consistent as a 4-bit entity?
0 Kudos
Altera_Forum
Honored Contributor II
840 Views

I didn't really think about it. Now that I think about it, the only way I can forsee this possibly working is if the source of the data (an ethernet PHY board) runs at the same clock speed as the FPGA. How else would this be able to work correctly then? I'd still need to register the inputs though right? Just because they're running at the same speed, the clocks could be not completely in sync with each other right?

0 Kudos
Altera_Forum
Honored Contributor II
840 Views

The PHY board transmits at 25 MHz and the FPGA runs at 50 MHz. So does that mean that for the simulation to be accurate, I should run the simulation clock at 50 MHz and provide a new set of 4 bits every 2 FPGA cycles?

0 Kudos
Altera_Forum
Honored Contributor II
840 Views

Or I can just create a clock divider and not worry about that!

0 Kudos
Altera_Forum
Honored Contributor II
840 Views

Wow it works so much better now! I can change to a different device/add or remove output ports and it all still works. The code didn't even really change that much except for the clock divider and registering those inputs. 

 

Something else I thought of, when I actually hook this up to hardware I'm going to have to 25 MHz clocks (one from the phy board, one from the fpga). The code I wrote relies on the fact that they are at the same speed so that the data I'm supplying is in line with the data I'm receiving. Could I use a FIFO as a buffer for the data and just pump it in at one clock speed (the phy board clock speed) and read it at another speed ( the fpga clock speed) and then as long as the fifo is long enough, I shouldn't have to worry about the clocks violating some setup time?
0 Kudos
Altera_Forum
Honored Contributor II
840 Views

Yes a FIFO is one of the usual means to move data between unsynchronized clock domains. The Quartus FIFO MegaFunction has all options to handle this situation. Actually, the FIFO depth requirement isn't high, because Ethernet has a clock accuracy specification of +/- 100 ppm, so the required buffer elasticity isn't more than a few bytes, even with extra large frames.

0 Kudos
Altera_Forum
Honored Contributor II
840 Views

That's good to know. I've been messing around with the fifo buffer and the one thing I'm confused about is how the read and write request signals. I assume that I want to be reading and writing all the time. But if one clock is faster than the other (say my fpga clock is faster) then it will read the same value again if the buffer is empty. I've been messing around with this by using a 30mhz clock and a 25 mhz clock which is a huge stretch and I can see that if I just read and write all the time I'll run into problems.

0 Kudos
Reply