Author Topic: Elastic buffers, join and fork structures  (Read 2845 times)

0 Members and 1 Guest are viewing this topic.

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Elastic buffers, join and fork structures
« on: August 01, 2020, 03:04:55 am »
Could anyone comment on the working mechanism for elastic buffers (Figure 10), join and fork structures (Figure 11) ?


Note: Screenshots are taken from SELF: Specification and design of synchronous elastic circuits





 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #1 on: August 01, 2020, 03:40:37 am »
Trick to understand, the colored vertical rectangle blocks inside the lower 3 yellow blocks are all clocked shift latches running on the same trigger signals as the top two vertical rectangles on the right.  IE, the use the same shift as the signal generated by the 2 input and gates feeding the rectangle's bottom.

You can replicate most of this using 2 or more of my 'Home made SystemVerilog 3 word, Zero latency FIFO, documented for beginners', though, the stop would be the fifo_full from each one which would be OR'ed together to stop the sender, unless your sender is directing the output to 1 or more multiple receivers where you can more efficiently use the each FIFO's memory.  The only advantage to my fifo would be the fall-through 0 latency feature, though using multiple units of mine may utilize additional registers.  Yet, my code is so simple, you could engineer multiple outputs utilizing the same register memory words it has recovering the excess bytes used with multiple separate units for multiple receivers just by adding additional 'read' pointers and additional data outputs tied to the single FIFO's memory registers.

https://www.eevblog.com/forum/fpga/home-made-systemverilog-3-word-zero-latency-fifo-documented-for-beginners/msg3123336/#msg3123336
« Last Edit: August 01, 2020, 03:43:54 am by BrianHG »
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #2 on: August 02, 2020, 01:26:54 pm »
For Figure 10,

1) Why 'stop' signal from receiver is fed back to 'valid' signal for sender using OR gate ?

2) Why 'valid' signal from sender is fed back to 'stop' signal for receiver using AND gate ?

3) Why the AND gates on top of VS and VS' cells depend on 'valid' signal from sender while the AND gate on top of the first version does not ?
« Last Edit: August 02, 2020, 01:31:09 pm by promach »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #3 on: August 02, 2020, 08:26:26 pm »
For Figure 10,

1) Why 'stop' signal from receiver is fed back to 'valid' signal for sender using OR gate ?

2) Why 'valid' signal from sender is fed back to 'stop' signal for receiver using AND gate ?

3) Why the AND gates on top of VS and VS' cells depend on 'valid' signal from sender while the AND gate on top of the first version does not ?

You must remember, each red and grey box is a clocked register which delays the signal by a clock before is passes through.  Those registers are clocked by the individual signals being sent by the vertical wire leaving each yellow 'VS' box directly into the huge red and grey boxes.  Yes, those tiny colored red and grey boxes are part of their master huge red and grey box at the top right in figure 10.

1) Where do you see that?  The valid signal in unidirectional from the sender.  Now, the valid is ored with the stop after it has traversed a red and grey register, meaning, if those 2 buffer registers are full and the sender should not be sending any more data until the stop it's anded with from the receiver has been releases meaning the receiver is reading the buffers.  Though the poor design of this is the lag involved with restarting that elastic chain once it has stopped.  In my FIFO code, it would be the equivalent to this line #71:
Code: [Select]
fifo_full                       =  fifo_full_r && !(shift_out && zero_latency) ;What's being said here if all the fifo words are full, and there is no 'shift_out' from the receiver, the fifo_full / IE 'stop' sent to sender will be seen by the receiver.  But if the FIFO has all 3 words full and the receiver is simultaneously shifting data out, the sender wont see the fifo_full / IE 'stop' condition, without any delay.  (Remember, with my FIFO, the receiver's 'stop' output is inverted feeding the FIFO' 'shift_out' control.  IE, stop=1, no shifting out, stop=0, shift out).

2) read my point #1.

3) remember, those are going through a red and grey register before the result is passed on to the other side.  Those registers are clocked by the individual signal being sent by the vertical wire leaving each yellow 'VS' box directly into the huge red and grey boxes.

This is something like the shift I used in V2.0 of my FIFO to keep track of how much of the buffers were full with how much data.  IE:
Code: [Select]
if (reset) begin
.......
fifo_position     <= 8'b11100001;      // The fifo empty location
end else begin

            if (  shift_in_protect && ~shift_out_protect ) fifo_position[7:0] <= {fifo_position[6:0],fifo_position[7]}; // Rotate the FIFO position left
       else if ( ~shift_in_protect &&  shift_out_protect ) fifo_position[7:0] <= {fifo_position[0],fifo_position[7:1]}; // Rotate the FIFO position right

     This shifts left and right a bit pattern where I would tap the appropriate  fifo_position[ # ] to generate the full/empty flags.  IE stop to sender.  My original Version 1.0 and final version 3.1 said it much better with a counter which just kept track of the number of registers difference between the in and out:

Code: [Select]
            if (  shift_in && ~shift_out ) fifo_size <= fifo_size + 1'b1; // Calculate the number of words stored in the FIFO
       else if ( ~shift_in &&  shift_out ) fifo_size <= fifo_size - 1'b1;

     In this case, the receiver's 'stop' output would be inverted and tied to the FIFO's shift_out.  The fifo's fifo_full output would be generated based on the quantity of the fifo_size and the total numbers of memory words the FIFO has.
« Last Edit: August 02, 2020, 09:24:58 pm by BrianHG »
 
The following users thanked this post: promach

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #4 on: August 02, 2020, 08:53:37 pm »
My short analysis was for 1 sender and 1 receiver shown in figure 10.  Figure 11 shows what logic to add if you have 2 senders and 1 receiver, or, 1 sender and 2 receivers.

To best accommodate 2 senders and 1 receiver, you would need 2 of my zero latency fifos wired together unless you want a ZIPPER together the 2 source streams (IE output will always read S1,S2,S1,S2,...), then 1 fifo with 2 input ports will do.  For 1 sender and 2 receivers, you would need 1 of my zero latency fifos with an added output read port and a second read pointer and fifo_size calculation in the main block.  The rest of the coding is trivial stuff and it can still retain zero latency functionality if needed.
« Last Edit: August 02, 2020, 08:56:55 pm by BrianHG »
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #5 on: August 03, 2020, 12:12:07 pm »
Quote
The valid signal in unidirectional from the sender.  Now, the valid is ored with the stop after it has traversed a red and grey register, meaning, if those 2 buffer registers are full and the sender should not be sending any more data until the stop it's anded with from the receiver has been releases meaning the receiver is reading the buffers.

The explanation above might not reflect actual situation especially the AND gate.

What if the receiver is (not ready) to receive the "valid" signal and its corresponding data ?

Note: "not ready" is equivalent to "STOP = 1"
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #6 on: August 03, 2020, 03:50:56 pm »
See the cyan structures above the first yellow box, there are 2 clocked registers +1 mux where the second output register either receives 1 word immediately from the sender bus, or, it get 1 extra latched clock delay meaning even if the receiver is sending a stop, but hasn't yet reached the sender, the gate structure inserts an additional 1 register delay extending the width of the elastic by 1 for that 1 cyan block.  I'm assuming the red and grey boxes are basic interpretations of the illustrated cyan structure at the top left.

Once the elastic of all those structures at a width or 2 and full, by that time the stop has finally propagated to the sender.

I guess the idea of this elastic system is to have a 1 or 2 width at each stage with a simple glue logic rule between them.  No central overarching flow control system.  The flow control status is being shifted through the latch blocks.

Even I'm having difficulty wrapping my head around the design decision and functionality.  The illustration for what they are trying to achieve is poor and doesn't illustrate the proper intentional mechanics of their desired function.

I'd say, google search for additional third party designs as there may be errors in their illustration.
« Last Edit: August 03, 2020, 03:58:23 pm by BrianHG »
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #7 on: August 05, 2020, 05:52:30 am »
Quote
Because the state machines in Fig. 8 are slightly different, so the controllers in Fig. 9 are slightly different (and so are their copies in Fig. 10). Note that the bottom of Fig. 10 is essentially Fig. 9 with the left and right flipped (and one of them also split).

Someone told me the above.

What do you think about the quoted statement above ?


« Last Edit: August 05, 2020, 05:59:24 am by promach »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #8 on: August 05, 2020, 09:06:09 am »
Are you asking me to comment on the author's different approaches design philosophy and implementation strategy?

Remember, I designed my own which goes down to transparency 0 clock pass through when empty and can stretch to 1 extra word above it's set size 3/7 without corruption, so I am biased and I would say ignore a design where as you add stages, your elastic goes from 1 or 2  with a single stage, then 2 to 4 with 2 sequential stages, then 3 to 6 with 3 sequential stages, then 4 to 8 with 4 sequential stages instead of mine which can go from 0 through 8.

However, they are talking about creating that join/fork function.  In my case, it is similar to adding a second read/empty/full pointer generator and 'OR'ing the that second port's full flag with the first full flag to stop the sender while that second port's empty flag and read data will be used for receiver #2's port.  Deciphering those state machines and verifying those gates driving the latch and AB mux control to add or eliminate a single elastic step, daisy changed among many if you want an elastic with some give and stretch above +/-1 will make my head go numb.
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #9 on: August 12, 2020, 09:45:00 am »
Have a look at Implementing Latency-Insensitive Dataflow Blocks

1. How is "Hold" action different from "Buffer" action ?

2. Why is the '1' pin of the second multiplexer inside the input buffer block fed a symbol of ⊥ ?

 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #10 on: August 13, 2020, 06:26:14 am »
1 )
Buffer takes in and latches a word into the storage register.
Hold freezes everything in place, do nothing at all.  The storage register retains it's previous value.

2 ) This clears the buffer and also assigns 1'bxxxxxx to the latch (IE: set reg as dont care bits).  This is useful when simulating where in your resulting waveform, the simulator will report an XX/or/ZZ value instead of an old value or a 0 which may be mistaken for a buffer which was just written a 0 value to it.  This really helps when debugging code, however, it wont effect the functionality as you can see the case of this example the buffer being emptied instead of being cleared to 0.

Note that the illustrations are feeding the register word are correct functionally, but should have been presented with as a clock enable/load enable for the register as the way the code is written.

This 'Latency-Insensitive Dataflow Blocks' is better presented & explained than you first elastic buffer.  It is also basically an almost identical implemented 1.5 word version of my 3 word 0 latency fifo, except, the full & empty tracking is stuffed in the highest bit of the ireg reg and odata reg where I made a parallel shifting register called 'fifo_position' which almost does the same thing.
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #11 on: August 13, 2020, 09:32:28 am »
2) Will assigning value of unknown 'x' not affecting verilog code synthesis ? 
    Besides, using 'x' still does not explain why is the '1' pin of the second multiplexer inside the input buffer block fed a symbol of ⊥ ?

Note: symbol ⊥ literally means absence of token pair (data, valid)  which means that 'valid' is low, while 'data' is don't care.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #12 on: August 13, 2020, 02:29:38 pm »
That symbol 'Note: symbol ⊥ ' is the selection line:

ireg <= {1'b0, W{1'bx}}};

Which was chosen to make ireg = that mux selection by the previous line's 'IF' command.

It would have been just as valid to say:
ireg[W] <= 1'b0; // don't bother with the ireg[W-1:0], just clear ireg's MSB status flag.

While the rest of ireg[W-1:0] would never change it's value.  However, when debugging during simulation, you could not tell the difference between a 'Core stop, empty?' and a 'Will core consume?' as they would both appear to have the same end result in the ireg buffer and ireg[W] would have a 0 already in both cases.

When running the IC/FPGA, the 2 'ireg <=' I listed are function identically in the silicon.  But when simulating, in the first case, the simulated viewed vector waveform will report that the lower bits of ireg[W-1:0] have reported a value of XX instead of still holding it's previous data.

Read up on Verilog 'don't care bits', both Z and X.  How to use them in if A==B and what how simulation results change when assigning a register to them compared to actual function.
« Last Edit: August 13, 2020, 02:43:54 pm by BrianHG »
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #13 on: August 14, 2020, 03:41:02 am »
WHY the variable  ireg  does not have the  else   part   ??


Code: [Select]
always @(posedge clk)
    if(!cstop && ireg [W]) // Will core consume?
        ireg < = { 1'b0, { W { 1'bx }}} ; // Yes: empty buffer

    else if ( cstop && !ireg[W]) // Core stop, empty?
        ireg < = idata; // Yes: load buffer


Quote
you could not tell the difference between a 'Core stop, empty?' and a 'Will core consume?' as they would both appear to have the same end result in the ireg buffer and ireg[W] would have a 0 already in both cases.

Wait, I am confused with your quoted sentence above.
« Last Edit: August 14, 2020, 03:56:45 am by promach »
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #14 on: August 14, 2020, 07:04:36 pm »
WHY the variable  ireg  does not have the  else   part   ??


Code: [Select]
always @(posedge clk)
    if(!cstop && ireg [W]) // Will core consume?
        ireg < = { 1'b0, { W { 1'bx }}} ; // Yes: empty buffer

    else if ( cstop && !ireg[W]) // Core stop, empty?
        ireg < = idata; // Yes: load buffer


Quote
you could not tell the difference between a 'Core stop, empty?' and a 'Will core consume?' as they would both appear to have the same end result in the ireg buffer and ireg[W] would have a 0 already in both cases.

Wait, I am confused with your quoted sentence above.
During the second 'else if':
ireg < = idata; // Yes: load buffer

It is possible to load a '0' or a '1' into the ireg[W] bit as idata input contains a the bulk data [W-1:0] and the [W] bit input as well coming from the source.  This is the source data status bit.

This is why it is useful during a simulation to know the difference between the first 'IF' clearing the ireg[W] to a 0, or, if the second 'IF''s 'ireg < = idata' was the one who set the ireg[W] to 0 with the rest of the bulk data coming in as ireg[W-1:0].

In the drawing illustration, the [W] in the data in, out and through the logic is that really thin black line in parallel, always the same offset from the thick black data bus.
« Last Edit: August 15, 2020, 12:03:23 am by BrianHG »
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #15 on: August 15, 2020, 03:08:37 am »
Code: [Select]
assign istop = ireg [W];   // Stop if buffering
Why does 'istop' need to depend on previous value of 'idata[W]' ?
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #16 on: August 15, 2020, 03:15:32 am »
Because if you fill that buffer's [W] with a 1 and the rest with data, there are no other buffers.  This is a 1 word FIFO.  You'll loose the word inside that buffer waiting to leave if you try to send data again before it is told to empty/feed out.

« Last Edit: August 15, 2020, 03:19:38 am by BrianHG »
 
The following users thanked this post: promach

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #17 on: August 15, 2020, 06:04:07 am »
but according to the hardware diagram, why 'istop' does not depend on 'cstop' ?

 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #18 on: August 15, 2020, 09:40:02 am »
Because it should not.  istop only depends on the 1 storage buffer ireg being full and the output buffer not sending out data at the same time.

This is what is meant by an elastic buffer.

Like my fifo, your transmitter can keep on transmitting even though the output side is stopped, that is until all the storage registers fill up, then I tell my sender to stop, if, storage buffer is full.
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #19 on: August 15, 2020, 09:57:31 am »
Quote
output buffer not sending out data at the same time

cstop is the signal describing the above quoted condition.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #20 on: August 15, 2020, 02:41:14 pm »
Do not confuse the output buffer being halted with the input buffer having 1 spare word of room or not to decide if the stop condition needs to be sent to the sender.

We have thoroughly gone through the pieces of this design.  It is time for you to either manually simulate on paper or in a simulator and work out step by step what is happening & when so you can figure out when and why each stage operates the way it does.

 
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #21 on: August 16, 2020, 05:49:44 pm »
Here, I created a 'FIFO' style System Verilog module of you latest elastic buffer here:

https://www.eevblog.com/forum/fpga/2-word-first-word-fall-through-(fwft)-fifo-fifo-style-elastic-buffer-for-speed/msg3191352/#msg3191352

The rules are different where the internal functioning of the output clocks/advances and will stop automatically once a valid word becomes present until the receiver request a shift_out.
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #22 on: August 17, 2020, 11:36:05 am »
Quote
but according to the hardware diagram, why 'istop' does not depend on 'cstop' ?

That's kind of the whole point of that buffer: to break the combinational path from cstop to istop. They do depend on each other, but only through a register. The idea of that buffer is to make it so things upstream from it can know whether there's buffer space available (istop) without having to know whether there's downstream space available (cstop).
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 7732
  • Country: ca
Re: Elastic buffers, join and fork structures
« Reply #23 on: August 17, 2020, 06:09:10 pm »
Quote
but according to the hardware diagram, why 'istop' does not depend on 'cstop' ?

That's kind of the whole point of that buffer: to break the combinational path from cstop to istop. They do depend on each other, but only through a register. The idea of that buffer is to make it so things upstream from it can know whether there's buffer space available (istop) without having to know whether there's downstream space available (cstop).
Yes, you got it.
Though it seems we are thinking about these things little differently as our case usages are different, that is a very useful function of these elastic buffers.
It is also the reason why I made that 2 word fifo.  My 3/4 word fifo still works great, but, if you have 2 or 3 gigantic set of functions all dependent on a single 'ENABLE', and your FPGA fabric & compiler just cant use a global bus for the enable, (eg: clk line is usually a dedicated global bus with specific buffers throughout the FPGA), sticking 1 or more of these 2 word elastic fifo's in between those modules regenerates a whole new 'enable' & 'stop' condition between them to drive the next bundle of logic.
 

Offline promachTopic starter

  • Frequent Contributor
  • **
  • Posts: 875
  • Country: us
Re: Elastic buffers, join and fork structures
« Reply #24 on: September 21, 2020, 01:39:46 pm »
In Figure 2 of the reply #9, why are there some table entries highlighted in yellow ?

What are those for ?
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf