Latches and flip flops

C

crazyrdx

Hi ,

I have been told that a design should not have latches, only flip
flops. How do i differentiate between them in my vhdl code? Thanks

RP
 
R

Ralf Hildebrandt

crazyrdx said:
I have been told that a design should not have latches, only flip
flops. How do i differentiate between them in my vhdl code? Thanks

You should get knowledge about what is the "level sensitive latch" and
the "edge-sensitive flipflop". That really basic stuff.

process(reset,enable,data_in)
begin
if (reset='1') then
my_latch<='0';
elsif (enable='1') then
my_latch<=data_in;
end if;
end process;

process(reset,clock)
begin
if (reset='1') then
my_flipflop<='0';
elsif rising_edge(clock) then
my_flipflop<=data_in;
end if;
end process;


Ralf
 
K

KJ

Given
signal A, B, C : std_logic;

An example of a latch

process(A)
begin
if (A = '1') then
C <= B;
end if;
end process;

An example of a flop flop
process(A)
begin
if rising_edge(A) then
C <= B;
end if;
end process;

Latches should not be used unless the underlying hardware directly supports
them with a latch primitive AND you make sure that your code gets
implemented using them. If you break down the 'latch' example into sum of
products form you'll get the following:

C <= (A and B) -- Term 1
or (not(A) and C; -- Term 2

The problem comes about when signal 'A' switches. Assuming that the
underlying hardware is like common PLDs then what will be implemented will
be darn near what I've got here. Ask yourself then what happens if the
propogation delay to compute what I've called 'Term 1' and 'Term 2' are
different. When 'A' switches from '1' to '0' and 'Term 1' gets computed
slightly faster than 'Term 2' than 'C' will shut off instead of holding or
latching. If you draw out the Karnaugh map for this equation and hark back
to long forgotten digital logic classes, you may notice that you can add a
redundant term that may solve your problem.

C <= (A and B) -- Term 1
or (not(A) and C -- Term 2
or (B and C); -- Term 3

Term 3 is the 'redundant' term that's been added. Logically the two
equations implement the exact same logic. When implementing a latch this
second form (with 'Term 3') will work flawlessly and not be sensitive to
propogation delays in computing any of the 'Terms'.

If you write your VHDL for a latch in the form with all 3 terms you're still
not done. Now the problem is that every synthesizer tool in the world will
spot the redundant logic term and reduce it right back out in the interest
of saving resources and getting things down to the minimum amount of logic.
All the synthesizer tools will also likely allow you some tool dependent way
of letting you tell .it not to muck with the equation that you want it to
implement exactly what you've written. That might seem like a 'solution'
but you should really ask yourself how closely you want to tie your code to
a particular tool or a particular device. As a general rule you shouldn't.
Usually, all a 'latch' buys you above a flip flop is you capture the data a
little bit sooner. Most of the time latches are not really needed a flip
flop will do if you put some thought into it.

As a final aside, the two additional ways I wrote the latch as a sum of
products in VHDL obviously are also forms of latches. If you EVER see a
signal on both sides of the assignment (i.e. signal 'C' in both of the sum
of products forms) than that equation is also some form of latch. If you
run your code through some form of implementation into a real part the tool
will detect latches when it reports 'combinatorial loops' when it performs a
timing analysis....just another check.

KJ
 
R

radarman

You also get latches when you don't fully flesh out if/else or case
structures. This is a common problem I see all the time. For example:

process(A,B,C)
begin
if( B = '1')
A <= '1';
elsif( C = '1' )
A <= '0';
end if;
end process;

What happens if both B and C are '0'? A must retain the last state, so
you have essentially created a latch. I find the best way to avoid
creating UNINTENTIONAL latches is to always create a default condition.
Using the above example:

process(A,B,C)
begin
A <= '0'; -- insert a default condition, so that the signal gets
updated everytime the process is called.
if( B = '1')
A <= '1';
elsif( C = '1' )
A <= '0';
end if;
end process;

This is a simple case, but it illustrates the idea of always assigning
a signal a value during every pass to avoid latches. As a general rule,
I write the following instead of using 'else'.

process( <input signals> )
begin
Output <= <default_value>;
if( <condition> )then
Output <= <alternate_value>;
end if;
end process;

For registers (D flip-flops), I always include as the very first line D
<= Q, and use the two-process model. For example:

process( reset_n, clk )
begin
if( reset_n = '0' )then
A_q <= '0'';
elsif( rising_edge(clk) )then
A_q <= A_d;
end if;
end process;

process(A_q,B,C)
begin
A_d <= A_q; -- insert as the default condition d <= q.
if( B = '1')
A_d <= '1';
elsif( C = '1' )
A_d <= '0';
end if;
end process;

This virtually guarantees that you get the D flip-flop and
combinational logic you are expecting. I generally recommend the two
process model for synchronous designs anyway, because it enforces the
idea of the clock explicitly. It also makes the demarcation between
combinational and registered logic clear. Of course, for me it isn't
generally optional. The company I work for requires the "two-process"
model for all code written, and requires an explanation if you don't
use it.

Lastly, almost any circumstance where you might consider a latch, a D
FF can be used instead. For example, I am working with a legacy
application where the clock isn't fast enough to reliably sample
"short" pulses. In this case, we use the input to clock a FF, which
toggles between high and low. (d <= not q) The output is fed into an
XOR type edge detector, which fires a single clock pulse every time the
input flop changes state. This allows us to reliably detect short
pulses that we might miss with a traditional sampling scheme - but
still avoids the pitfalls of a traditional SR latch.
 
M

Mike Treseler

crazyrdx said:
I have been told that a design should not have latches, only flip
flops. How do i differentiate between them in my vhdl code? Thanks

To avoid latches I use design rules
that eliminate the possibility of
latch inference.
One way to do this is to base
designs on this template:
....
begin -- process template
if reset = '1' then
init_regs;
elsif rising_edge(clock) then
update_regs;
end if;
update_ports;
end process one;
end architecture synth;

For details see:
http://home.comcast.net/~mike_treseler/

-- Mike Treseler
 
K

KJ

This virtually guarantees that you get the D flip-flop and
combinational logic you are expecting. I generally recommend the two
process model for synchronous designs anyway, because it enforces the
idea of the clock explicitly.

The single clocked process is pretty clear that there is a clock and doesn't
require any extra gymnastics about remembering to have default assignments
like 'A_d <= A_q'.
It also makes the demarcation between combinational and registered logic
clear.

Not sure why this demarcation is important to you. But when writing code
that is intended to be synthesizable, as a general rule I only have clocked
processes, the combinatorial logic are not in a process at all. When you
can do that it totally avoids the problems of unintended latches due to
missing cases or missing signals in the sensitivity list. For the few cases
where it really is clearer to use statements only available in a process
(i.e. if/case) then I'll use a process knowing that I need to inspect that
code quite closely for just those issues, the FF processes do not need that
inspection.

For FFs you also don't have double the number of signals than you really
need (i.e. A_d and A_q....'almost' every time I'm really only interested in
the output of the FF, not the input). Cutting down on clutter in terms of
how many signals there are in play has real value as well.

But single versus dual process conventions seems to be more of a religion in
itself ;)

KJ
 
M

Mike Treseler

KJ said:
The single clocked process is pretty clear that there is a clock and doesn't
require any extra gymnastics about remembering to have default assignments
like 'A_d <= A_q'.

Yes. One less thing to worry about.
... when writing code
that is intended to be synthesizable, as a general rule I only have clocked
processes, the combinatorial logic are not in a process at all.

Any combinational logic that is needed needed is
inferred from the clocked process. I could even declare a variable
representing an asynchronous node inside the synchronous process if
I had a reason to.
When you
can do that it totally avoids the problems of unintended latches due to
missing cases or missing signals in the sensitivity list.

Yes, this is a significant simplification
of the design and simulation process.
For FFs you also don't have double the number of signals than you really
need (i.e. A_d and A_q....'almost' every time I'm really only interested in
the output of the FF, not the input). Cutting down on clutter in terms of
how many signals there are in play has real value as well.

Indeed, let synthesis work out the wires.
The only signals I _really_ need are to
wire up the top level ports and entity instances.
But single versus dual process conventions seems to be more of a religion in
itself ;)

Yes, I can never predict personal preferences.
Some like writing software in assembly language and
some enjoy do-it-yourself logic synthesis.

-- Mike Treseler
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top