1
\$\begingroup\$

At the outset, I would like to say that I am not able to run this snippet at the moment but, even if I were, I hope this question would still stand as I'd like to understand why the Verilog standard implies a given interpretation of this snippet.

The snippet below is adapated from one seen in Chapter 8 of Saurabh's Introduction to VLSI Design Flow. It is written in 2001-Verilog but, I think, it works in modern simulators too.

module top();
  reg a,b, clock;
  initial begin
    a = 1'b1;
    b = 1'b0;
    clock = 1'b0;
  end

  always clock = #10 ~clock; // clock with period 20 time units

  always @(posedge clock) begin
    a<= b; //a changes to 1'b0 at t=10 and 1'b1 at t=30 and so on...
    b<= a; //b changes to 1'b1 at t=10 and 1'b0 at t=30 and so on...
  end
endmodule


What I am confused about is the following: is this code guaranteed to work as intended given the comments below?

(1) In Verilog there is no guarantee that an initial block executes before an always block. This is up to the simulator.

(2) For intra-assignment delay (as in the clock updating always) the RHS is evaluated before the delay.

Given (1) and (2), it's not clear to me that this code is guaranteed to work. For example: if the always block is entered first, before the initial block, then, since clock has as yet not been intitialized I believe we will get clock toggled to x after 10 seconds, meaning that we do not get a positive edge of the clock at 10 seconds. On the other hand, if the initial is entered first then things work out as intended. Is this understanding correct?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Your understanding is correct. Not only are the execution order between all initial and always blocks in a design indeterminate, but the relative ordering of statements between processes is indeterminate as well. That means the first two statements inside the initial could execute and switch to the always block before the clock='b0; statement. This is exactly what might happen if the design was executing on a truly multithreaded system. Section 4.7 Nondeterminism enables this for many other kinds of optimizations.

I would NEVER use a use an assignment with an intra-assignment delay. This is left over from before non-blocking assignments were introduced into Verilog in the 1980s.

This should be written as

always #10 clock = ~clock;

or better

initial begin
   clock = 1'b0
   forever #10 clock = ~clock;
end
\$\endgroup\$
4
  • \$\begingroup\$ What if we initialize the variable at the declaration time? i.e. reg clk = 0;. I assume that this will avoid any such condition in the first place. Isn't it so? \$\endgroup\$ Commented Mar 19, 2024 at 16:53
  • 1
    \$\begingroup\$ Thank you so much for this very helpful answer! I now think I understand your comment that "Not only are the execution order between all initial and always blocks in a design indeterminate, , but the relative ordering of statements between processes is indeterminate as well" after reading Chapter 9 of the text (which discusses the details of simulation) but I was hoping to confirm with you if that's OK: I think my original suspicion that what matters is which procedural block was "entered first" was wrong, and what matters instead are the individual time slots in the event queue... \$\endgroup\$ Commented Mar 19, 2024 at 17:36
  • \$\begingroup\$ ... That is, the simulator goes through all processes concurrently and sets up the event queue. Within a given time slot -- like t=0 as is under discussion here -- and in the active region the simulator may order events in any order desired, modulo that events from a given procedural block must execute in-order. \$\endgroup\$ Commented Mar 19, 2024 at 17:38
  • 1
    \$\begingroup\$ @ImGroot Verilog-2001 added the syntax reg clk = 0; however it described its behavior as the same as reg clk; initial clk = ; SystemVerilog strengthened that behavior to say that initialization happens before any other initial or always blocks start their processes. \$\endgroup\$ Commented Mar 19, 2024 at 17:49
1
\$\begingroup\$

Can you share with us why you are unable to run the code snippet at the moment ?

Verilog uses event-driven simulation, so the order of execution of 'always' blocks, 'initial' blocks or 'assign' statements depends on the flow of those types of events.

Generally, signals updated in one particular block will trigger execution of all other blocks which depend on those signals.

The main difference between always blocks and initial blocks is that the latter are executed unconditionally at time 0 and usually produce some initial events, such as the generation of clocks and/or the scheduling of reset signals.

For this reason initial blocks are generally considered to be executed first and before any other blocks react to these events which are produced by them.

\$\endgroup\$
6
  • \$\begingroup\$ My only tool for running Verilog is the online EDAPlayground and I was having issues opening the waveform viewer to actually see the results of the snippet. At any rate, thanks very much for your answer here. I am not sure though that the resolution is that initial blocks execute first; indeed, my book explicitly says they do not necessarily? \$\endgroup\$ Commented Mar 19, 2024 at 14:38
  • \$\begingroup\$ It all depends how you define "first" and what the book means by "not necessarily" - only sometimes, occasionally or rarely ? You may want to double check the context of that statement in your book (and if you can, also make a link to it here for us...). The initial blocks will definitely execute at time t=0, and from this you can logically follow the signal flow ... \$\endgroup\$ Commented Mar 19, 2024 at 15:28
  • \$\begingroup\$ As an asside, it is generally known this is the case for simulation, however for sythnesis (as you may or may not already know), the initial state of variables that you want to initialise when the machine starts up, is best served with an always @(posedge clock, negedge reset) begin if (~reset) { initialise variables} else {continue with always block logic as if already started} ... hope this might clarify the slight differences ... \$\endgroup\$ Commented Mar 19, 2024 at 15:33
  • \$\begingroup\$ To clarify what I mean: certainly the initial block will execute at t=0 but what the book means I think is that if there is an always block which is also possible to execute at t =0 then it is possible that the always block is entered first. Indeed, that is the case here (again, I think): always clock = #10 ~clock; gets entered at $t = 0$ and the intra-assignment delay (please correct if wrong) schedules a clock inversion for t = 10, but does this with the value of the clock it has at the current instant? \$\endgroup\$ Commented Mar 19, 2024 at 15:41
  • 1
    \$\begingroup\$ Incidentally, totally agreed regarding the synthesizable subset of Verilog and appreciate you mentioning it, but here I am interested in the full Verilog superset. \$\endgroup\$ Commented Mar 19, 2024 at 15:42

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.