Avoiding latches when writing processes

C

Carl

Guest
Hello,

In the lecture notes for one of my lectures, I find the following:


//
[...]
This process may generated undesired latches from violation of 2 basic
rules:
1. All input signals must be listed in the sensitivity list
2. All output signals must be driven all time.

[...]

Violation example for rule 2:
In the process below labeled ps_wrong the assignment yout<=b; can be
executed if and only if a='1'. When a='0' then yout must not change. To
guarantee this the synthesizer generates a latch, which is not
combinational. This problem is removed in process ps_right.

a)
ps_wrong:pROCESS(a,b)
BEGIN
IF a='1' THEN
yout<=b;
END IF;
END PROCESS ps_wrong;

b)
ps_right:pROCESS(a,b)
BEGIN
IF a='1' THEN
yout<=b;
ELSE
yout<=yout;
END IF;
END PROCESS ps_right;
//

I agree that a) would create a latch.
Example (suppose yout = 0 first):
a: 00111110000
b: 00001111100
yout: 00001111111

(First a=b=0 and yout=0, later a=b=0 and yout=1 => not combinational.)

But in my opinion, b) does exactly the same.

If, though, I *wanted* to create memory, with the above behaviour, I
would choose b) because it can more easily be seen from the code that
memory is really created.


Who's wrong - me or the lecture notes?

Regards Carl
 
This process may generated >undesired latches from violation of >2 basic
rules:
1. All input signals must be listed in the sensitivity list
....

b)
ps_right:pROCESS(a,b)
BEGIN
IF a='1' THEN
yout<=b;
ELSE
yout<=yout;
END IF;
END PROCESS ps_right;
According to this rule, yout is also an input signal and not listet in
the sensitivity list. So this creates a latch also. The following does
not create a latch, but changes the behaviour:

b)
ps_right2:pROCESS(a,b,yout)
BEGIN
IF a='1' THEN
yout<=b;
ELSE
yout<=yout;
END IF;
END PROCESS ps_right2;

Hubble.
 
Reiner Huober wrote:
This process may generated >undesired latches from violation of >2 basic
rules:
1. All input signals must be listed in the sensitivity list
....


b)
ps_right:pROCESS(a,b)
BEGIN
IF a='1' THEN
yout<=b;
ELSE
yout<=yout;
END IF;
END PROCESS ps_right;

According to this rule, yout is also an input signal and not listet in
the sensitivity list. So this creates a latch also. The following does
not create a latch, but changes the behaviour:

b)
ps_right2:pROCESS(a,b,yout)
BEGIN
IF a='1' THEN
yout<=b;
ELSE
yout<=yout;
END IF;
END PROCESS ps_right2;

Hubble.
That's right, it won't create a latch, but it will create a feedback
loop (in my opinion), which means that the realisation won't be
combinational. And coding feedback loops yourself without latches should
always be avoided, according to what I've learned.

So; the question remains, am I or the lecture notes wrong (see original
post), anyone?
 
Good catch... it looks like you're right- a) and b) are the same.

If it was like this:

IF a = '1' THEN
yout <= b;
ELSE
yout <= (others => '0'); -- or some other constant or input
END IF;

then the latch would be removed.

"Rule" #1:
1. All input signals must be listed in the sensitivity list
That's wrong. A synchronous process might have many inputs, though
only the clock and asynchronous reset would typically be in the
sensitivity list. A better way to put it would probably be like this:

1. All input signals which could directly cause an output to change
must be listed in the sensitivity list

"Rule" #2:
2. All output signals must be driven all time.
Also wrong, I wouldn't consider a tri-stated signal "driven", though
it's a completely valid value for a signal. Maybe a better way to
write that one:

2. All output signals must be assigned all the time.

You might want to question the validity of anything you read in those
lecture notes.

If, though, I *wanted* to create memory, with the above behaviour, I
would choose b) because it can more easily be seen from the code that
memory is really created.
This all depends on what you're doing, what kind of control signals you
have, and what your target device is, but in general, memory is created
using flip-flops instead of latches, whether it's using a part's logic
resources or memory resources. A synchronous process will create
flip-flops (or built-in memory if properly inferred by the design
tools). In general, it's a good idea to avoid latches.
 
Carl wrote:

So; the question remains, am I or the lecture notes wrong (see original
post), anyone?
The answer makes no difference for synchronous designs.
All I need in a sensitivity list is reset and clock.
I only need signals to wire up instances.

-- Mike Treseler
 
You are correct it will create a combinatorial feedback loop which is
bad.

To avoid a latch in this situation you'd have to use a flip-flop.


ps_right3:pROCESS(a,b,yout_q)
BEGIN
IF a='1' THEN
yout<=b;
ELSE
yout<=yout_q;
END IF;
END PROCESS ps_right3;

reg:pROCESS(clk)
BEGIN
IF ( clk'event AND clk = '1' ) then
yout_q <= y_out;
END IF;
END PROCESS reg;

or if the design allows assign "yout" to a constant...

ps_right4:pROCESS(a,b)
BEGIN
IF a='1' THEN
yout<=b;
ELSE
yout<='0';
END IF;
END PROCESS ps_right4;
 
Mike Treseler wrote:
The answer makes no difference for synchronous designs.
All I need in a sensitivity list is reset and clock.
I only need signals to wire up instances.

-- Mike Treseler
Spoken like a true software engineer turned hardware engineer. Damn,
how BIG are your designs? The use of variables throughout your design
must be horrendous, perhaps double your register count and halve your
simulator speed when debugging.

Good VHDL RTL designs should have only one ultra simple clocked process
per architecture which contains just all of your registers. ALL other
processes should be combinatorial.
 
No offense intended, just never seen anyone write good VHDL in only
clocked processes.
 
a1_nocrap_exh@hotmail.com wrote:
Mike Treseler wrote:

The answer makes no difference for synchronous designs.
All I need in a sensitivity list is reset and clock.
I only need signals to wire up instances.

-- Mike Treseler


Spoken like a true software engineer turned hardware engineer.
Other way around, actually.

Damn, how BIG are your designs?
Here's a little one:
http://home.comcast.net/~mike_treseler/uart.vhd

The use of variables throughout your design
must be horrendous, perhaps double your register count and halve your
simulator speed when debugging.
Not at all.

Good VHDL RTL designs should have only one ultra simple clocked process
per architecture which contains just all of your registers. ALL other
processes should be combinatorial.
That is the common belief.

-- Mike Treseler
>
 
"Carl" <"c.j[dot]w"@telia.com> wrote in message news:43de3f83$1_1@news.arcor-ip.de...
Reiner Huober wrote:
This process may generated >undesired latches from violation of >2 basic
rules:
1. All input signals must be listed in the sensitivity list
....


b)
ps_right:pROCESS(a,b)
BEGIN
IF a='1' THEN
yout<=b;
ELSE
yout<=yout;
END IF;
END PROCESS ps_right;

According to this rule, yout is also an input signal and not listet in
the sensitivity list. So this creates a latch also. The following does
not create a latch, but changes the behaviour:

b)
ps_right2:pROCESS(a,b,yout)
BEGIN
IF a='1' THEN
yout<=b;
ELSE yout<=yout; END IF; END PROCESS ps_right2; Hubble.

That's right, it won't create a latch, but it will create a feedback loop (in my opinion), which means that the realisation won't
be combinational. And coding feedback loops yourself without latches should always be avoided, according to what I've learned.
A combinational feedback loop with enable signal is really behaviorally the same as a latch.
So both (a) and (b) should create latches, and they do (at least in the synthesis tools I tried).

So; the question remains, am I or the lecture notes wrong (see original post), anyone?
The notes are wrong.
How about this :

A latch is created from a signal assigned in a process if :

(1) the process is combinational (more than one bit on the sense-list and no clock'event tests), and
(2) there is at least one path (setting of control signals) under which the signal holds it value
 
Mike Treseler wrote:
Here's a little one:
http://home.comcast.net/~mike_treseler/uart.vhd
Woa, scary... but cool.

The use of variables throughout your design
must be horrendous, perhaps double your register count and halve your
simulator speed when debugging.

Not at all.
I thought that if you want to view the state of variables in you
simulator, e.g. modelsim then you have to use a compiler option e.g.
"vopt +acc" which drastically reduces the speed of the simulator.

Good VHDL RTL designs should have only one ultra simple clocked process
per architecture which contains just all of your registers. ALL other
processes should be combinatorial.

That is the common belief.
I enjoyed reading the articles by Ian Lang. I already do most of what
he suggests. I dont particularly like the mix and match of vhdl and
verilog in his articles though.

Alex
 
a1_nocrap_exh@hotmail.com wrote:

Woa, scary... but cool.
Scary for the netlist-oriented but
it all works on standard synth and sim tools.
and I find the style very easy to follow.

I thought that if you want to view the state of variables in you
simulator, e.g. modelsim then you have to use a compiler option e.g.
"vopt +acc" which drastically reduces the speed of the simulator.
No. All you have to do is include an
add wave command for the processs in your do file
as shown in the reference testbench here:
http://home.comcast.net/~mike_treseler/

I enjoyed reading the articles by Ian Lang.
Me too. He is a huge inspiration for me.

I already do most of what
he suggests. I dont particularly like the mix and match of vhdl and
verilog in his articles though.
I intend to update all of his examples in
both languages as time allows. All of his
single process style examples translate directly into
a verilog single always block style, which also works fine.
The verilog side will not be happy about hearing this,
so I want to get my ducks lined up first.

-- Mike Treseler
 

Welcome to EDABoard.com

Sponsor

Back
Top