begin-end and
fork-join are used to combine a group of statements in a single
block. General syntax with begin-end is as follows:
type_of_block @(sensitivity_list)
begin: group_name
local_variable_declarations;
statements;
end
|
type_of_block may
be initial or always. sensitivity_list is optional and
possible only in always block. You are knowing about initial and
always block in the previous chapter.
Sensitivity list is used to model sequential or combinational
logic. To make it more clear, observe these examples:
module comb(a, b, c);
input c;
input b;
output a;
reg a;
always @( c or b)
begin
a = c & b;
end
endmodule
|
module seq(a, b, c);
output a;
input b;
input c;
reg a;
always @( posedge c)
begin
a <= b;
end
endmodule
|
In the left hand side example, whenever c or b changes, a will
become c & b. So it is combinational logic,
represents and gate. Note that actual hardware register won't be
implemented while synthesizing in the left-hand side example, even
though it is declared as the type reg. Right hand side example will
be synthesized as D-type Flip-flop since b will be assigned to a
when ever c goes high. Difference between "=" and
"<=" is explained in the next chapter. These codes
can be represented in the form of circuits as shown
below.
Output of module comb
|
Output of the module seq
|
Inside an initial or always block, we can group statements using
begin--end or fork--join. begin--endgroups
two or more statements together sequentially, so that statements
are evaluated in the order they are listed. Each timing control is
relative to the previous
statement. fork--join groups
two or more statements together in parallel, so that all statements
are evaluated concurrently. Each timing control is absolute to when
the group started.
These are some examples to understand how begin--end and fork--join
executes.
module forkjoin(clk, a, b);
input clk;
output a;
output b;
reg a, b;
initial
begin
a = 0;
b = 0;
end
always @(posedge clk)
fork
#2 a = 1;
#1 b = 1;
join
endmodule
|
module forkjoin1(clk, a, b);
input clk;
output a;
output b;
reg a, b;
initial
begin
a = 0;
b = 0;
end
always @(posedge clk)
fork
#2 a = 1;
#1 b = a;
join
endmodule
|
Output of forkjoin ^
|
Output of forkjoin1 ^
|
module beginend(clk, a, b);
input clk;
output a;
output b;
reg a, b;
initial
begin
a = 0;
b = 0;
end
always @(posedge clk)
begin
#2 a = 1;
#1 b = a;
end
endmodule |
Output of beginend ^
|
From these examples,
you can understand the execution.
We can nest
begin--end and fork--join. That is, inside a begin--end we can have
fork--join and inside fork--join we can have
begin--end. Consider these codes to find out how
nested begin--end and fork--join works.
module nesting1(clk, a, b, c, d, e, f);
input clk;
output a, b, c, d, e, f;
reg a, b, c, d, e, f;
initial
begin
a = 0;
b = 0;
c = 0;
d = 0;
e = 0;
f = 0;
end
always @(posedge clk)
fork
#2 a = 1;
#2 b = 1;
begin
#2 c = 1;
#2 d = 1;
#2 e = 1;
end
#2 f = 1;
join
endmodule
|
and here is the output: You can notice that a,
b, c and f became high 2 ns after the clock, d 2ns after c and e
2ns after d.
![关于Verilog中begin-end <wbr>& <wbr>fork-join begin-end and fork-join - 温柔的爱你 - 温柔的爱你,耐心的等你](http://image109.360doc.com/DownloadImg/2018/10/1017/146582657_6_20181010053440199.jpg)
|
module nesting2(clk, a, b, c, d, e, f);
input clk;
output a, b, c, d, e, f;
reg a, b, c, d, e, f;
initial
begin
a = 0;
b = 0;
c = 0;
d = 0;
e = 0;
f = 0;
end
always @(posedge clk)
begin
#2 a = 1;
#2 b = 1;
fork
#2 c = 1;
#2 d = 1;
#2 e = 1;
join
#2 f = 1;
end
endmodule |
Output wave of the above code is here. Notice
that a, b and c became 1 with 2ns delay in-between, d and e became
1 together with c, after that f with 2 ns delay.![关于Verilog中begin-end <wbr>& <wbr>fork-join begin-end and fork-join - 温柔的爱你 - 温柔的爱你,耐心的等你](http://image109.360doc.com/DownloadImg/2018/10/1017/146582657_7_20181010053440730.jpg)
|
Program control will
come out of the fork--join block when all the statements finishes
executing. in the case of code bellow, control will come out of
block after 30ns.
fork
#20 c = 1;
#30 d = 1;
#10 e = 1;
join
|