1
\$\begingroup\$

I have the following code:

always @ (posedge clk or posedge reset) begin 
    if (reset) begin 
        count <= 0;
    end else begin 
        if (rd_en) begin 
            count <= count - 1;
        end else begin 
            count <= count;
        end 

        if (wr_en) begin 
            count <= count + 1;
        end else begin 
            count <= count;
        end 
    end 
end 

If rd_en and wr_en occur at the same time, will the count <= count + 1 be nullified by count <= count - 1, or will the addition due to the wr_en take effect as it was the final assignment (or code wise it was the last remaining assignment) to the count register?

Is the below one a better code which specifies the design intent more clearly?

if (rd_en && wr_en) begin
    count <= count; 
end else if (rd_en) begin 
    count <= count - 1;
end else if (wr_en) begin 
    count <= count + 1;
end else begin 
    count <= count;
end 
\$\endgroup\$
0

2 Answers 2

3
\$\begingroup\$

Within a single procedural process, last assignment in the procedural flow of statements wins.

Since you are using nonblocking assignments, count will not have an updated value from previous assignments, so the count <= count - 1 is effectively nullified. If both enables were active, the wr_en has priority so the count gets incremented.

If your intent is to make both enables cancel each other out, it is better to explicitly code for that. A chain of if statements usually works better with else if. I would do something like

if (rd_en && !wr_en)
  count <= count - 1;
else if (wr_en && !rd_en)
  count <= count + 1;
else
   ; // nothing happens

You could also use a case statement

case ({rd_en,wr_en})
  2'b10: count <= count - 1;
  2'b01: count <= count + 1;
endcase
\$\endgroup\$
4
  • \$\begingroup\$ Meaning that the count won't be incremented? \$\endgroup\$
    – lousycoder
    Commented Apr 8 at 9:03
  • \$\begingroup\$ I've edited the question. \$\endgroup\$
    – lousycoder
    Commented Apr 8 at 9:09
  • 1
    \$\begingroup\$ @lousycoder, I've edited my answer. \$\endgroup\$
    – dave_59
    Commented Apr 8 at 16:10
  • \$\begingroup\$ Ok, so according to the case, if both are high, then count doesn't change and it retains the existing value. \$\endgroup\$
    – lousycoder
    Commented Apr 9 at 6:01
1
\$\begingroup\$

When you have a question about how Verilog code behaves, the most direct way to answer the question is to run Verilog simulations. A less direct way is to ask a bunch of strangers on the internet :)

The previous answer correctly tells you what you will observe in simulations because that is how the IEEE Std 1800-2017 defines the behavior.

In general, you should always write code as simply and as clearly as possible. The reason you posted the question in the first place is that you have doubts about the code. The way you wrote the code is not the best way because you have doubts.

It is great that you are trying to improve the situation with your second code sample. However, as you would quickly find out with simulations, that code has syntax errors. You should always run simulations before posting your code.

Let's assume you want to retain the behavior of your 1st code example. Here is an outline of how it behaves:

  • If the asynchronous reset is asserted, then initialize count to 0
  • If reset is not asserted and if write is enabled, then increment count
  • If read is enabled and write is not enabled, then decrement count
  • Otherwise, don't change count

Here is a customary way to describe that behavior which is simpler than your code:

always @(posedge clk or posedge reset) begin 
    if (reset) begin 
        count <= 0;
    end if (wr_en) begin 
        count <= count + 1;
    end if (rd_en) begin 
        count <= count - 1;
    end 
end 

Note that there is no need to make the self-assignment:

        count <= count;

For simplicity, this is usually omitted.

If you really want reads to take priority over writes, you need to change the code.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Note that your code does not have the same behaviour as the ops second example which I assume is the true intended behaviour. In your example if write and read are both high, it will increment the counter as does the ops first code example. Whereas the second one does not increment if both are high. \$\endgroup\$ Commented Apr 8 at 17:43
  • 1
    \$\begingroup\$ @TomCarpenter: Yes, but I clearly stated in the answer that the code I posted behaves the same as the 1st code example in the OP and that the 2nd example was broken code when I 1st posted the answer. The OP can leave a comment here if the OP needs clarification. \$\endgroup\$
    – toolic
    Commented Apr 8 at 20:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.