Methods for flow control

C

carloshyneman

Hello,

I like sharing some ideas to see the different points of view out there! :D

Assuming that you have a pipelined design that does some calculation that requires 10 (or N) clock cycles of latency.
The module is supposed to be able to perform flow control (pause its input and avoid writing to its output) whenever its output is busy, so the interface would look something similar to the one shown below.

The way I see it, there are two main ways (at least that I know of) to implement correct flow control:
#1- Use a clock enable signal that is controlled by busy_in, connect busy_out to busy_in, and disable your data_out_val whenever busy_out is set.
#2- Don't using a clock enable on your processing, use a FIFO at the end ofyour processing that is deep enough to accommodate the remaining data flushed from the pipe (at least 10 elements), use an almost full flag, connect busy_out to busy_in, and empty the FIFO when the output is not busy.

I usually use method #1 (roughly shown below)
The way I see it, you save some resources (no FIFO) and the registers and multipliers already have a clock enable port, so no extra logic is required.

- Are there any major pros/cons to using a method over another other?
- Would you guys implement that differently?

C.

entity test is
port (
clk : in std_logic;
reset : out std_logic;
-- input port
data_in : in std_logic_vector(7 downto 0);
data_in_val : in std_logic;
busy_out : out std_logic;
-- output port
data_out : out std_logic_vector(7 downto 0);
data_out_val : in std_logic;
busy_in : in std_logic
);
end test;

architecture my_arc of test is
type type_data_array is array (0 to 9) of std_logic_vector(7 downto 0);
signal my_data_array : type_data_array;
signal my_data_val : std_logic_vector(9 downto 0);
signal my_enable : std_logic;

begin

my_enable <= not busy_in;
busy_out <= busy_in;

data_out <= my_data_array(9);
data_out_val <= my_data_val(9) and (not busy_in);

my_processing : process (clk)
begin
if rising_edge(clk) then
if reset = '1' then
my_data_array <= (others => (others => '0'));
my_data_val <= (others => '0');
elsif my_enable = '1' then

-- shift register (emulates some random processing)
my_data_array(0) <= data_in;
my_data_val(0) <= data_in_val;
for i in 1 to 9 loop
my_data_array(i) <= my_data_array(i-1);
my_data_val(i) <= my_data_val(i-1)
end loop;

end if;
end if;
end process my_processing;

end my_arc;
 
G

goouse99

Am Donnerstag, 18. Oktober 2012 16:35:57 UTC+2 schrieb (e-mail address removed):
Hello,



I like sharing some ideas to see the different points of view out there! :D



Assuming that you have a pipelined design that does some calculation thatrequires 10 (or N) clock cycles of latency.

The module is supposed to be able to perform flow control (pause its input and avoid writing to its output) whenever its output is busy, so the interface would look something similar to the one shown below.



The way I see it, there are two main ways (at least that I know of) to implement correct flow control:

#1- Use a clock enable signal that is controlled by busy_in, connect busy_out to busy_in, and disable your data_out_val whenever busy_out is set.

#2- Don't using a clock enable on your processing, use a FIFO at the end of your processing that is deep enough to accommodate the remaining data flushed from the pipe (at least 10 elements), use an almost full flag, connect busy_out to busy_in, and empty the FIFO when the output is not busy.



I usually use method #1 (roughly shown below)

The way I see it, you save some resources (no FIFO) and the registers andmultipliers already have a clock enable port, so no extra logic is required.



- Are there any major pros/cons to using a method over another other?

- Would you guys implement that differently?



C.



entity test is

port (

clk : in std_logic;

reset : out std_logic;

-- input port

data_in : in std_logic_vector(7 downto 0);

data_in_val : in std_logic;

busy_out : out std_logic;

-- output port

data_out : out std_logic_vector(7 downto 0);

data_out_val : in std_logic;

busy_in : in std_logic

);

end test;



architecture my_arc of test is

type type_data_array is array (0 to 9) of std_logic_vector(7 downto 0);

signal my_data_array : type_data_array;

signal my_data_val : std_logic_vector(9 downto 0);

signal my_enable : std_logic;



begin



my_enable <= not busy_in;

busy_out <= busy_in;



data_out <= my_data_array(9);

data_out_val <= my_data_val(9) and (not busy_in);



my_processing : process (clk)

begin

if rising_edge(clk) then

if reset = '1' then

my_data_array <= (others => (others => '0'));

my_data_val <= (others => '0');

elsif my_enable = '1' then



-- shift register (emulates some random processing)

my_data_array(0) <= data_in;

my_data_val(0) <= data_in_val;

for i in 1 to 9 loop

my_data_array(i) <= my_data_array(i-1);

my_data_val(i) <= my_data_val(i-1)

end loop;



end if;

end if;

end process my_processing;



end my_arc;

Hi,
it depends on the structure of your pipelined algorithm.
If it is as simple as mentioned, that you have a number of independent stages, then you don't even need to stop the system. You only need to flag valid data.

The pipeline will continue to process the input, but without the data beingvalid.

However, it depends on the following modules if it is necessary to stop thedata input at some time. But this can be done early (depending on the length of the pipeline) directly from the "slow" module.

If you have some more complicated pipeline with feedbacks things are entirely different. These must be filled and flushed in a controlled way.

So everything can be done in a special way.

But maybe you prefer a design that uses standardized interfaces and handshakes between the modules. In that case you need to think about the type of data you are processing. If the data goes through the pipeline in a word by word way, stoping the pipeline would be OK. But if you are processing blocks of data the fifo solution will be preferable to ensure that always a complete block is available at the input of the next module.

These are just some thoughts on the topic and far from being complete.
There are just too many things having influence to the way you are doing the flow controll in a system.
In any case you have to ensure that no deadlocks or pipeline stalls can happen with the chosen way of flow controll. Also data throughput and ressource usage should be taken into account when designing such a system.

Have a nice synthesis
Eilert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top