Here’s a quick course on procedural code in Verilog:
always statement; is an instantiation of a procedural process that begins at time 0, and when that statement completes, it repeats. initial statement; is also an instantiation of a procedural process that begins at time 0, but when that statement completes, the process terminates. All always and initial blocks start concurrently at time 0 in any order that is not deterministic. You cannot nest always or initial blocks inside each other as they are not procedural statements.
@(expression) (also called an event control) is a procedural construct that means “wait for a value change in the expression”. You can put an event control in front of any procedural statement.
You can executed multiple statements where one is required by surrounding it with begin/end. In front of any procedural statement, you can put a @(expr) or Delay control that blocks execution of that statement. This code does not execute the block every clock cycle:
always @(posedge clk)
begin
A< = B;
@(posedge clk);
C <= D;
end
could also be written as
always
begin
@(posedge clk) A< = B;
@(posedge clk) C <= D;
end
And this block of code will take two clock cycles to complete. Each assignment occurs every other clock cycle.
There is also procedural forever looping statement that continuously executes the enclosing statement. So
always statement;
is essentially the same as
initial forever statement;