Question on clk signal in sensitivity list

G

googler

Guest
I have a doubt that I need to get clear. Firstly, I don't have a lot of
experience in RTL design. I wrote a piece of Verilog code, from which I
am going to show just one line.

always @(clk or posedge rst)

This is followed by some other code which is not really related to the
question. Here are the questions:

1. My assumption is that the always block will be entered whenever
there is an event on clk (be it a positive edge or a negative edge) or
on a positive edge of rst. So according to my understanding, the above
line is equivalent to
always @(posedge clk or negedge clk or posedge rst)
Is that correct? Somebody (who is actually an RTL design engineer) told
me that the first 'always' statement [that is always @(clk or posedge
rst)] is entered when clk has value 1 or on positive edge of reset. Who
is correct here?

2. Is it possible to synthesize a design that has an always statement
like "always @(posedge clk or negedge clk or posedge rst)"? Basically
in such a design I want to update the flip flops on both edges of clk.
Again, I think this is synthesizable and the other person thinks it's
not. Please advise.
 
sharp@cadence.com wrote:
googler wrote:

1. My assumption is that the always block will be entered whenever
there is an event on clk (be it a positive edge or a negative edge) or
on a positive edge of rst. So according to my understanding, the above
line is equivalent to
always @(posedge clk or negedge clk or posedge rst)
Is that correct?

Yes.

2. Is it possible to synthesize a design that has an always statement
like "always @(posedge clk or negedge clk or posedge rst)"? Basically
in such a design I want to update the flip flops on both edges of clk.
Again, I think this is synthesizable and the other person thinks it's
not. Please advise.

Synthesis tools do not generally accept such things. Most technology
libraries do not include dual-edge-triggered flip-flops.

You can build such things yourself out of existing components. For
example, you can use one posedge triggered flop and one negedge
triggered flop wired to the same data and clock, with their outputs
muxed together and selected by the clock level (so that when the clock
is high, it selects the output it just clocked into the posedge flop,
and when it is low it selects the output it just clocked into the
negedge flop). If there were dual-edge flops in a technology library,
they would probably have to be implemented something like this
underneath, though some simplifications might be possible.

This seems to come up pretty regularly, generally from new designers
who think it is a neat idea. It is generally discouraged by the more
experienced ones. I would suggest searching the archives for earlier
responses to this same issue.
While inference of dual-edge flip-flops is generally not supported by
synthesis
tools, implementations of "DDR" flip-flops are common in FPGA's, and
presumably other silicon libraries for instantiation into a design. In
the
case of FPGA's the dual-clocked flip-flops are generally only available
in
the I/O cells, so instantiation is not generally a big problem. There
is a thread in comp.arch.fpga about implementation of the DDR
flip-flops
which discusses possible methods and has a link to the Xilinx patent
on their FDDRSE implementation.

To make a dual-clocked flip-flop from two D flip-flops, you can use XOR
gates to generate the D inputs and final output. One XOR gate has the
two flip-flop Q outputs as inputs and provides the final output. Each
flip-
flop's D input is provided with the XOR of the (not necessarily common)
D
input and the other flip-flop's Q output. This causes the output to
follow
the value of the D input when either flip-flop is clocked. This not
only
works for using both edges of a common clock, but also any other
combination of clocks whose active edges are separated by sufficient
time to meet setup after the XOR gates.
 
On 2006-11-13, Chris F Clark <cfc@shell01.TheWorld.com> wrote:
You are correct on this one. To get an always block that is only
entered when a signal has a value, you need an "if" in the always,
such as:

always @(clk or posedge rst)
if (clk) then
// this code will be executed if clk is high
I haven't tried it myself but I think that it is also legal to
do the following:

always @((clk == 1) or posedge rst)
// This code will be executed when clk transitions to 1 or
// a positive edge occurs on rst.

/Andreas
 
Andreas Ehliar <ehliar@lysator.liu.se> writes:

On 2006-11-13, Chris F Clark <cfc@shell01.TheWorld.com> wrote:
You are correct on this one. To get an always block that is only
entered when a signal has a value, you need an "if" in the always,
such as:

always @(clk or posedge rst)
if (clk) then
// this code will be executed if clk is high

I haven't tried it myself but I think that it is also legal to
do the following:

always @((clk == 1) or posedge rst)
// This code will be executed when clk transitions to 1 or
// a positive edge occurs on rst.

/Andreas
Unfortunately, no, I don't think so.

First, an always @(expression), does not wait for the expression to
become 1, it waits for it to change value. If you want an expression
to have a specific value, you must use an if statement within the
block to check the value. So, in you case, if clk changes from 1 to 0
(oftern written 1->0), the expression clk == 1, will also change 1->0
and thus since the value of the expression changed, the always block
will execute, which is not your intent at all.

Technically, that's true even for expressions inside a posedge or
negedge, since 0->x or 0->z is considered a positive edge and so is
x->1 or z->1, as well as the 0->1 that one expects (and the converse
is true for negedges). However, in most cases with well designed
logic those extra "edge" transitions don't occur, so it isn't an
issue.

Second, a lot of tools have problems with expressions in sensitivity
lists. Thus, if you get used to usign such a facility, you may find
that some downstream tool in your tool change refuses to deal with
your verilog. If addition, certain syntheisizers ignore sensitivity
lists except for some specific forms. Therefore, it is best if one
sticks to very simple sensitivity lists.

// These are the 7 I would use exclusively
always @( posedge(clock) )
always @( negedge(clock) )
always @( posedge(clock) or posedge(reset) ) // note below
always @( posedge(clock) or negedge(reset) ) // on clocks
always @( negedge(clock) or posedge(reset) ) // and resets
always @( negedge(clock) or negedge(reset) )
always @ * // note next

// if you have a pre-2001 tool, replace * with a list of all
// right-hand-side only signals in your always block as in:
always @ ( input1 or input2 or input3 )
begin
temp = input1 + input2;
output1 = temp * input3;
output2 = input1 - output1;
end

Note, we have a tool that does the above change for us automatically,
so that we can use the 7 simple forms and get out 1995 compatible
code. When listing the sensitivities of ones always block explicitly,
one should make sure two things are true.

First, that you don't forget an input. If something appears in an
expression, the variable should either be calculated within the block
or in the sensitivity list. If you omit this, your simulator may not
trigger the always block when tha variable has changed and it will act
like a latch for simulation. However, the simulator may not recognize
the construct as a latch and may not instantiate one in hardware, and
then your pre- and post- synthesis results won't match, and more
importantly, your pre-synthesis results won't match the resulting
hardware.

Second, don't list things which you compute within the block. This
can cause the always block to execute more than once. This can mask
problems with cyclic combinatorial logic or it can cause simulation
loops if the code has glitches in it (signals that transition to more
than one state between clocks).

////////////////////////////////////////////////////////////////////////

Clocks and resets: if you have two edge expressions in a sensitivity
list, one of them should be a clock and the other a reset. The reset
should be used in an if (or case) statement, to signal when the device
gets reset to a known state. The condition of the if statement and
the edge of the in the sensitivity list tell one which branch is the
reset logic and in that logic the outputs should be set to constants.

always @( posedge(clock) or posedge(reset) )
begin
if ( reset ) then
output <= 0; // reset branch
else
output <= input; // non-reset branch
end

////////////////////////////////////////////////////////////////////////

Do not do things like the following:

always @( posedge(clock) or negedge(clock) )
// two edges of same clock

always @( posedge(clock1) or posedge(clock2) )
// two clocks (unless 1 is a reset)

always @( (input1 + input2) or (temp * input3) or (input1 - output1) )
// don't use expressions, use the variables in the expressions instead

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 
On 2006-12-12, Chris F Clark <cfc@shell01.TheWorld.com> wrote:
Andreas Ehliar <ehliar@lysator.liu.se> writes:

I haven't tried it myself but I think that it is also legal to
do the following:

always @((clk == 1) or posedge rst)
// This code will be executed when clk transitions to 1 or
// a positive edge occurs on rst.

/Andreas

Unfortunately, no, I don't think so.

First, an always @(expression), does not wait for the expression to
become 1, it waits for it to change value. If you want an expression
to have a specific value, you must use an if statement within the
block to check the value. So, in you case, if clk changes from 1 to 0
(oftern written 1->0), the expression clk == 1, will also change 1->0
and thus since the value of the expression changed, the always block
will execute, which is not your intent at all.
Ah, that does make more sense than what I thought was true. If my idea
was true there would be no real need for a posedge directive, I guess I
should have read what I wrote in the comment a bit more thoroughly and
thought about it a bit more.

Something else I didn't think about which your post made me think about
is that a transition from 0 to 1 via x will actually give 2 posedges.
I guess this might be troublesome if you happen to use a simulation
library for pads which gives you an x between transitions. (I recently
heard about someone struggling with this.)


/Andreas
 
"googler" <pinaki_m77@yahoo.com> writes:

I have a doubt that I need to get clear. Firstly, I don't have a lot of
experience in RTL design. I wrote a piece of Verilog code, from which I
am going to show just one line.

always @(clk or posedge rst)

This is followed by some other code which is not really related to the
question. Here are the questions:

1. My assumption is that the always block will be entered whenever
there is an event on clk (be it a positive edge or a negative edge) or
on a positive edge of rst. So according to my understanding, the above
line is equivalent to
always @(posedge clk or negedge clk or posedge rst)
Is that correct? Somebody (who is actually an RTL design engineer) told
me that the first 'always' statement [that is always @(clk or posedge
rst)] is entered when clk has value 1 or on positive edge of reset. Who
is correct here?
You are correct on this one. To get an always block that is only
entered when a signal has a value, you need an "if" in the always,
such as:

always @(clk or posedge rst)
if (clk) then
// this code will be executed if clk is high

2. Is it possible to synthesize a design that has an always
statement like "always @(posedge clk or negedge clk or posedge
rst)"? Basically in such a design I want to update the flip flops on
both edges of clk. Again, I think this is synthesizable and the
other person thinks it's not. Please advise.
This is not synthesizable. To verify this, design a flip-flop that is
sensitive to both edges of a clock and yet retains state. When does it
retain state? If the clock is transitioning in either direction, the
device is changing value.

However, there is logic that can change with every transition of the
clock, it is combinational logic, and-gates, or-gates, muxes. It will
faithfully change value whenever the inputs change. Unfortunately,
what you can't do with combinational logic is refer to its previous
value, for that you need something that retains state.

So, the question you must ask your self is, "what do you want your
device to do?" Do you want it to change value on every edge of the
clock or do you want it to retain value across a clock edge?

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 
googler wrote:
1. My assumption is that the always block will be entered whenever
there is an event on clk (be it a positive edge or a negative edge) or
on a positive edge of rst. So according to my understanding, the above
line is equivalent to
always @(posedge clk or negedge clk or posedge rst)
Is that correct?
Yes.

2. Is it possible to synthesize a design that has an always statement
like "always @(posedge clk or negedge clk or posedge rst)"? Basically
in such a design I want to update the flip flops on both edges of clk.
Again, I think this is synthesizable and the other person thinks it's
not. Please advise.
Synthesis tools do not generally accept such things. Most technology
libraries do not include dual-edge-triggered flip-flops.

You can build such things yourself out of existing components. For
example, you can use one posedge triggered flop and one negedge
triggered flop wired to the same data and clock, with their outputs
muxed together and selected by the clock level (so that when the clock
is high, it selects the output it just clocked into the posedge flop,
and when it is low it selects the output it just clocked into the
negedge flop). If there were dual-edge flops in a technology library,
they would probably have to be implemented something like this
underneath, though some simplifications might be possible.

This seems to come up pretty regularly, generally from new designers
who think it is a neat idea. It is generally discouraged by the more
experienced ones. I would suggest searching the archives for earlier
responses to this same issue.
 

Welcome to EDABoard.com

Sponsor

Back
Top