Using posedge and negedge causing me grief

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
First off, let me point out that I'm a newbie trying to teach
myself verilog. :)

I get warnings (shown below) whenever I try to assign values to a register
in a "always @ (posedge clk)" block, and change the values in a "always @
(negedge clk)" block.

My thinking is that I want to update an internal register on the negedge,
and then present it to the output on the posedge. I'm pretty sure that my
thinking is wrong because if I "`ifdef" out the negedge block the
warning goes away. [The logic also stops working, but that's not the point.]

As a final note, this logic simulates just fine.

Thanks for looking at this for me. I appreciate the help.

-MO

module top(clk, reset, enable, cnt);

   input clk,reset,enable;
   output cnt;

   wire clk,reset,enable;
   reg [3:0] cnt, curval, ov1;
   reg [1:0] acnt;

   always @ (posedge clk) begin
          if (reset) begin
                 curval <= 5;
          end
          else begin
                 case (acnt)
                   0: cnt <= curval;
                   1: cnt <= ov1;
                   2: cnt <= 2;
                   3: cnt <= 3;
                 endcase

                 if (!enable)
                   acnt <= acnt + 1;
          end
   end
 
   // Update the values
   always @ (negedge clk) begin
          if (enable) begin
                 ov1 <= curval;
                 curval <= curval + 1;
          end
   end

endmodule


Here are warnings I get when trying to synthesize the above code:

INFO:Xst:1304 - Contents of register <curval> in unit
<top> never changes during circuit operation. The register is replaced by
logic.

WARNING:Xst:1426 - The value init of the FF/Latch curval_2 hinder the
constant cleaning in the block top.
   You should achieve better results by setting this init to 1.
WARNING:Xst:1426 - The value init of the FF/Latch curval_1 hinder the
constant cleaning in the block top.
   You should achieve better results by setting this init to 1.
WARNING:Xst:1710 - FF/Latch  <curval_3> (without init value) has a
constant value of 0 in block <top>. WARNING:Xst:1895 - Due to other
FF/Latch trimming, FF/Latch  <curval_0> (without init value) has a
constant value of 0 in block <top>. Register <ov1_3> equivalent to <ov1_0>
has been removed Register <curval_2> equivalent to <curval_1> has been
removed Register <ov1_2> equivalent to <ov1_1> has been removed

ERROR:Xst:528 - Multi-source in Unit <top> on signal <N0>
Sources are:
   Signal <curval<3>> in Unit <top> is assigned to GND
   Signal <N0> in Unit <top> is assigned to GND
   Signal <curval<0>> in Unit <top> is assigned to VCC

ERROR:Xst:528 - Multi-source in Unit <top> on signal <curval<1>>
Sources are:
   Output signal of FDE_1 instance <curval_1>
   Signal <curval<1>> in Unit <top> is assigned to GND
   Signal <curval<2>> in Unit <top> is assigned to VCC
CPU : 6.59 / 15.27 s | Elapsed : 8.00 / 9.00 s
 
-->
Total memory usage is 66588 kilobytes

Number of errors   :    0 (   0 filtered)
Number of warnings :    4 (   0 filtered)
Number of infos    :    1 (   0 filtered)

ERROR: XST failed
Process "Synthesize" did not complete.



Re: Using posedge and negedge causing me grief

Quoted text here. Click to load it

-snip-

I would guess that you're working with a chip that only supports
clocking on one edge of any given clock line.  If you want to implement
a two-phase clock you'll probably have to do it explicitly.

On recent Xilinx parts it looks like you can do this more or less
directly with a DCM or a DLL -- figuring out how is up to you.

--

Tim Wescott
Wescott Design Services
We've slightly trimmed the long signature. Click to see the full one.
Re: Using posedge and negedge causing me grief

Quoted text here. Click to load it

Thanks for the speedy reply.

I'm working with the XS3S200 Spartan 3 device, on a Spartan-3 starter
board. I'll have to do some digging in the docs to see if what you've
suggested is true for my device. Thanks again.



Re: Using posedge and negedge causing me grief
On Tue, 03 Jan 2006 22:34:02 -0800, Mike Oxlarge

Quoted text here. Click to load it

To be frank I don't think your issue is whether your chip supports
mixed edge clocks etc but basic logic design background. To do regular
digital logic you don't need mixed edges as you describe above. The
flops already do that for you internally. You need to partition your
design into combinational blocks and storage and you use the flop as a
storage element which samples its input every clock edge and presents
it to the output. Your combinational blocks also depend on the current
value of the storage but as you need an edge for it to be sampled the
loop is cut at the input of the flop so to speak. You don't need a two
phase implementation which necessiates mixed clock edges. You can do
everything you need with a single edge. Imagine a cloud of logic which
takes your enable and the cnt value and calculates the next value of
cnt to be presented. When the clock edge happens this value gets to
the flop output and the cycle starts again. No need for an internal
phase.
HTH.


Re: Using posedge and negedge causing me grief
There's Verilog and there's synthesizeable Verilog.

Not everything you can write in Verilog turns into sensible hardware.

The basic rules for syntheizeable code are that only a single block
can drive a register unless tristates/multiplexors are used. You
update curval on both edges.

Perhaps the curval reset logic should be done on the negedge ?

Jon

Re: Using posedge and negedge causing me grief
crurval is reset in the posedge block, and assigned in the negedge
block. Move the reset to the negedge block, and it should work.

Andy


Re: Using posedge and negedge causing me grief
Quoted text here. Click to load it

^^^^^^^^^^^^^^^^^^^^^^ curval is synchronously set here.

Quoted text here. Click to load it

^^^^^^^^^^^^^^^^  curval is clocked here.

The simple rule to remember is that you can't assign to a signal in
more than one always block.  Put the synchronous reset curval <= 5; in
the negedge-clocked block.

-a


Re: Using posedge and negedge causing me grief

Quoted text here. Click to load it

I get what you're saying, and have tried your (and the other's) suggestion
of putting the reset in the negedge-clocked block, and it synthesizes just
fine. However, I'm now trying to implement what mk suggested:

<quote mk>
...
You don't need a two phase implementation which necessiates mixed clock
edges. You can do everything you need with a single edge. Imagine a cloud
of logic which takes your enable and the cnt value and calculates the next
value of cnt to be presented. When the clock edge happens this value gets
to the flop output and the cycle starts again.
...
</quote mk>

Any ideas on how I can implement what he suggested? I'm working on it, but
not making much progress. I'm sure there's probably a simple and elegant
solution to this that I'm missing.
 

Re: Using posedge and negedge causing me grief
Quoted text here. Click to load it

My suggestion would be eliminate using both the posedge and negedge
conditions in your design and just use posedge for the clock edge.

You have created a half-cycle path in your design when it appears
that you have no need to do so.  This will likely lead to a race
condition (aka hold violation) where some of the data gets through
the other edge when it shouldn't have or a setup violation where
the data doesn't get to the register on the other edge in time.

Unless you really need to use opposite edges for a very specific
timing reason you should avoid doing so it minimize lengthy debug
sessions where the design works when it's cold and then starts to
fail when it warms up or the reverse.

Ed

Re: Using posedge and negedge causing me grief
On Wed, 04 Jan 2006 12:18:48 -0800, Mike Oxlarge

Quoted text here. Click to load it

To be frank I am not sure what your code is trying to do but let me
start it here and you can fix it the way you want:

   always @ (posedge clk) begin
          if (reset) begin
                 curval <= 5;
       acnt <= 2'h0;    // nice clean value
          end
          else begin
                 case (acnt)
                   0: cnt <= curval;
                   1: cnt <= ov1;
                   2: cnt <= 2;
                   3: cnt <= 3;
                 endcase

                 if (!enable)
                   acnt <= acnt + 1;

       if (enable) begin
                         ov1 <= curval;
                     curval <= curval + 1;
                end
          end
   end

As there is no specific reason I can see for you to have the negedge,
put all your code into the posedge. If the behavior is not what you
want, change it till you get it right. One thing you can do is to put
all the code between the first else to the end of code in a
combinational always block so that not all variables are registered or
you don't have to wait for unnecessary cycles to get curval+1 etc.

HTH.

Re: Using posedge and negedge causing me grief

Quoted text here. Click to load it
<snip>
Quoted text here. Click to load it

Thanks for setting me straight with not using a mixed phase approach. I
had only used it because I had seen it used as an example somewhere on the
internet. It was probably either a bad example, or I just didn't get the
point of the code. I do see the need to keep to a single clk edge, and to
use a combinational block (or combinational plus sequential) to calculate
my next value.

Many thanks to you, and everyone else who offered guidance and advice.

-MO



Site Timeline