Verilog HDL Abstraction Levels //Verilog HDL 的抽象层次 | ||
| ||
Procedural Blocks//过程模块 | ||
Verilog behavioral code is inside procedure blocks, but there is an exception: some behavioral code also exist outside procedure blocks. We can see this in detail as we make progress. Verilog HDL 行为级的编码是内部过程块,但是也有一个例外:一些行为编码也存在过程块的外部。我们将在下面的讲解的过程中,看到具体的细节。 | ||
There are two types of procedural blocks in Verilog: //在Verilog HDL中有两种类型的过程块。 | ||
| ||
Example - initial // initial 举例 | ||
1 module initial_example(); 2 reg clk,reset,enable,data; 3 4 initial begin 5 clk = 0; 6 reset = 0; 7 enable = 0; 8 data = 0; 9 end 10 11 endmoduleYou could download file initial_example.v here | ||
Example - always //always举例 | ||
1 module always_example(); 2 reg clk,reset,enable,q_in,data; 3 4 always @ (posedge clk) 5 if (reset) begin 6 data <= 0; 7 end else if (enable) begin 8 data <= q_in; 9 end 10 11 endmoduleYou could download file always_example.v here | ||
In the above example, the initial block execution and always block execution starts at time 0. Always block waits for the event, here positive edge of clock, whereas initial block just executed all the statements within begin and end statement, without waiting. 在上面的例子中,initial block 和always block都是从time 0 开始执行。 always block 要等待事件的发生,这里是时钟正沿,然而initial block 只执行在begin-end之间的语句,而不等待(只执行一次)。 |
In an always block, when the trigger event occurs, the code inside begin and end is executed; then once again the always block waits for next event triggering. This process of waiting and executing on event is repeated till simulation stops.
在一个always block 中,当触发事件发生时,在begin-end之间的代码被执行,接着always block等待下一个事件的触发。
这个基于事件触发的等待和执行不停的重复执行,直至仿真结束。
Procedural Assignment Statements //过程赋值语句- Procedural assignment statements assign values to reg, integer, real, or time variables and can not assign values to nets (wire data types)
- 过程赋值语句,可以为reg、integer、real、time变量赋值,但是不能给net类型变量赋值(如 wire)。
- You can assign to a register (reg data type) the value of a net (wire), constant, another register, or a specific value.
- 你可以为register(reg类型)变量赋值为net类型的值(wire),constant、另一个reg类型的值,或者一个具体的值。
1 module initial_bad(); 2 reg clk,reset; 3 wire enable,data; //无法为net类型的变量赋值 4 5 initial begin 6 clk = 0; 7 reset = 0; 8 enable = 0; 9 data = 0; 10 end 11 12 endmoduleYou could download file initial_bad.v here Example - Good procedural assignment //正确的过程赋值
1 module initial_good(); 2 reg clk,reset,enable,data; 3 4 initial begin 5 clk = 0; 6 reset = 0; 7 enable = 0; 8 data = 0; 9 end 10 11 endmoduleYou could download file initial_good.v here Procedural Assignment Groups //过程赋值组
If a procedure block contains more than one statement, those statements must be enclosed within
如果一个过程块包含多天语句的话,应该将这些语句包含在begin-end中(顺序的)或者 fork-join(并行的)。
- Sequential begin - end block //顺序的begin-end块
- Parallel fork - join block //并发的fork-join块
When using begin-end, we can give name to that group. This is called named blocks.
当使用begin-end块时,我们可以为这个组命名。这就是命名块。
Example - "begin-end" // begin-end举例1 module initial_begin_end(); 2 reg clk,reset,enable,data; 3 4 initial begin 5 $monitor( 6 "%g clk=%b reset=%b enable=%b data=%b", 7 $time, clk, reset, enable, data); 8 #1 clk = 0; 9 #10 reset = 0; 10 #5 enable = 0; 11 #3 data = 0; 12 #1 $finish; 13 end 14 15 endmoduleYou could download file initial_begin_end.v here
Begin : clk gets 0 after 1 time unit, reset gets 0 after 11 time units, enable after 16 time units, data after 19 units. All the statements are executed sequentially.
begin-end 中的所有语句都是顺序执行的。
Simulator Output //仿真输出
0 clk=x reset=x enable=x data=x
1 clk=0 reset=x enable=x data=x
11 clk=0 reset=0 enable=x data=x
16 clk=0 reset=0 enable=0 data=x
19 clk=0 reset=0 enable=0 data=0
Example - "fork-join" // fork-join 举例
1 module initial_fork_join(); 2 reg clk,reset,enable,data; 3 4 initial begin 5 $monitor("%g clk=%b reset=%b enable=%b data=%b", 6 $time, clk, reset, enable, data); 7 fork 8 #1 clk = 0; 9 #10 reset = 0; 10 #5 enable = 0; 11 #3 data = 0; 12 join 13 #1 $display ("%g Terminating simulation", $time); 14 $finish; 15 end 16 17 endmoduleYou could download file initial_fork_join.v here
Fork : clk gets its value after 1 time unit, reset after 10 time units, enable after 5 time units, data after 3 time units. All the statements are executed in parallel.
fork-join中所有语句是同时并发执行的的。
Simulator Output //仿真输出
0 clk=x reset=x enable=x data=x
1 clk=0 reset=x enable=x data=x
3 clk=0 reset=x enable=x data=0
5 clk=0 reset=x enable=0 data=0
10 clk=0 reset=0 enable=0 data=0
11 Terminating simulation
Sequential Statement Groups // 顺序语句组
The begin - end keywords: // begin-end 关键字
- Group several statements together. //将几个语句一起作为一个组
- Cause the statements to be evaluated sequentially (one at a time) // 造成所有的语句按顺序执行时被计算,(一次执行一个)。
- Any timing within the sequential groups is relative to the previous statement. //在一时序组中的所有时间都是相对前一个状态的时间来说的
- Delays in the sequence accumulate (each delay is added to the previous delay) //顺序语句中的时延是累加的
- Block finishes after the last statement in the block. //顺序块结束在,块中最后一个语句执行完成之后。
1 module sequential(); 2 3 reg a; 4 5 initial begin 6 $monitor ("%g a = %b", $time, a); 7 #10 a = 0; 8 #11 a = 1; 9 #12 a = 0; 10 #13 a = 1; 11 #14 $finish; 12 end 13 14 endmoduleYou could download file sequential.v here
Simulator Output
0 a = x
10 a = 0
21 a = 1
33 a = 0
46 a = 1
Parallel Statement Groups //并行语句块组
The fork - join keywords: //fork-join关键字之间的语句
- Group several statements together. //将几个语句归并为一个组。
- Cause the statements to be evaluated in parallel (all at the same time). //使其中的语句的计算是并行。(所有的语句,并行执行)。
- Timing within parallel group is absolute to the beginning of the group. //并行组中所有时间都是相对并行组的开始的时间。
- Block finishes after the last statement completes (Statement with highest delay, it can be the first statement in the block).
- 整个块的完成在最后完成的一条语句完成之后,(即有最大时延的语句,又可能是块中的第一条语句)。
1 module parallel(); 2 3 reg a; 4 5 initial 6 fork 7 $monitor ("%g a = %b", $time, a); 8 #10 a = 0; 9 #11 a = 1; 10 #12 a = 0; 11 #13 a = 1; 12 #14 $finish; 13 join 14 15 endmoduleYou could download file parallel.v here
Simulator Output //仿真输出
0 a = x
10 a = 0
11 a = 1
12 a = 0
13 a = 1
Example - Mixing "begin-end" and "fork - join" //begin-end和fork-join的混合举例
1 module fork_join(); 2 3 reg clk,reset,enable,data; 4 5 initial begin 6 $display ("Starting simulation"); 7 $monitor("%g clk=%b reset=%b enable=%b data=%b", 8 $time, clk, reset, enable, data); 9 fork : FORK_VAL 10 #1 clk = 0; 11 #5 reset = 0; 12 #5 enable = 0; 13 #2 data = 0; 14 join 15 #10 $display ("%g Terminating simulation", $time); 16 $finish; 17 end 18 19 endmoduleYou could download file fork_join.v here
Simulator Output
0 clk=x reset=x enable=x data=x
1 clk=0 reset=x enable=x data=x
2 clk=0 reset=x enable=x data=0
5 clk=0 reset=0 enable=0 data=0
15 Terminating simulation
Blocking and Nonblocking assignment //阻塞的赋值语句和非阻塞的赋值语句
Blocking assignments are executed in the order they are coded, hence they are sequential. Since they block the execution of next statment, till the current statement is executed, they are called blocking assignments. Assignment are made with "=" symbol. Example a = b;
阻塞赋值语句的执行顺序是其编码的先后顺序,因此,是顺序执行的。因为,其阻塞下一个语句的执行,直到当前语句执行完。这就是阻塞的赋值语句。使用符号=, 如a= b;
Nonblocking assignments are executed in parallel. Since the execution of next statement is not blocked due to execution of current statement, they are called nonblocking statement. Assignments are made with "<=" symbol. Example a <= b;
非阻塞的语句时并行执行的,下一个语句的执行,不依赖与当前语句的执行。称之为,非阻塞的赋值语句。 非阻塞的赋值,使用符号<=, 如a<=b;
Note : Correct way to spell 'nonblocking' is 'nonblocking' and not 'non-blocking'.
注意:争取的的拼写nonblocking 是nonblocking 而不是non-blocking。
Example - blocking and nonblocking //blocking赋值语句与nonblocking赋值语句的举例1 module blocking_nonblocking(); 2 3 reg a,b,c,d; 4 // Blocking Assignment 5 initial begin 6 #10 a = 0; 7 #11 a = 1; 8 #12 a = 0; 9 #13 a = 1; 10 end 11 12 initial begin 13 #10 b <= 0; 14 #11 b <= 1; 15 #12 b <= 0; 16 #13 b <= 1; 17 end 18 19 initial begin 20 c = #10 0; 21 c = #11 1; 22 c = #12 0; 23 c = #13 1; 24 end 25 26 initial begin 27 d <= #10 0; 28 d <= #11 1; 29 d <= #12 0; 30 d <= #13 1; 31 end 32 33 initial begin 34 $monitor("TIME = %g A = %b B = %b C = %b D = %b",$time, a, b, c, d); 35 #50 $finish; 36 end 37 38 endmoduleYou could download file blocking_nonblocking.v here
Simulator Output
TIME = 0 A = x B = x C = x D = x
TIME = 10 A = 0 B = 0 C = 0 D = 0
TIME = 11 A = 0 B = 0 C = 0 D = 1
TIME = 12 A = 0 B = 0 C = 0 D = 0
TIME = 13 A = 0 B = 0 C = 0 D = 1
TIME = 21 A = 1 B = 1 C = 1 D = 1
TIME = 33 A = 0 B = 0 C = 0 D = 1
TIME = 46 A = 1 B = 1 C = 1 D = 1
Waveform
assign and deassign // 赋值和取消赋值
The assign and deassign procedural assignment statements allow continuous assignments to be placed onto registers for controlled periods of time.
赋值和取消赋值过程语句允许连续的赋值语句在不同的控制时间段被设置。
The assign procedural statement overrides procedural assignments to a register. The deassign procedural statement ends a continuous assignment to a register.
这个赋值过程语句能够覆盖一个寄存器的过程赋值。 取消赋值过程语句可以结束对一个寄存器的连续赋值。
Example - assign and deassign//赋值和取消赋值1 module assign_deassign (); 2 3 reg clk,rst,d,preset; 4 wire q; 5 6 initial begin 7 $monitor("@%g clk %b rst %b preset %b d %b q %b", 8 $time, clk, rst, preset, d, q); 9 clk = 0; 10 rst = 0; 11 d = 0; 12 preset = 0; 13 #10 rst = 1; 14 #10 rst = 0; 15 repeat (10) begin 16 @ (posedge clk); 17 d <= $random; 18 @ (negedge clk) ; 19 preset <= ~preset; 20 end 21 #1 $finish; 22 end 23 // Clock generator 24 always #1 clk = ~clk; 25 26 // assign and deassign q of flip flop module 27 always @(preset) 28 if (preset) begin 29 assign U.q = 1; // assign procedural statement 30 end else begin 31 deassign U.q; // deassign procedural statement 32 end 33 34 d_ff U (clk,rst,d,q); 35 36 endmodule 37 38 // D Flip-Flop model 39 module d_ff (clk,rst,d,q); 40 input clk,rst,d; 41 output q; 42 reg q; 43 44 always @ (posedge clk) 45 if (rst) begin 46 q <= 0; 47 end else begin 48 q <= d; 49 end 50 51 endmoduleYou could download file assign_deassign.v here
Simulator Output
@0 clk 0 rst 0 preset 0 d 0 q x
@1 clk 1 rst 0 preset 0 d 0 q 0
@2 clk 0 rst 0 preset 0 d 0 q 0
@3 clk 1 rst 0 preset 0 d 0 q 0
@4 clk 0 rst 0 preset 0 d 0 q 0
@5 clk 1 rst 0 preset 0 d 0 q 0
@6 clk 0 rst 0 preset 0 d 0 q 0
@7 clk 1 rst 0 preset 0 d 0 q 0
@8 clk 0 rst 0 preset 0 d 0 q 0
@9 clk 1 rst 0 preset 0 d 0 q 0
@10 clk 0 rst 1 preset 0 d 0 q 0
@11 clk 1 rst 1 preset 0 d 0 q 0
@12 clk 0 rst 1 preset 0 d 0 q 0
@13 clk 1 rst 1 preset 0 d 0 q 0
@14 clk 0 rst 1 preset 0 d 0 q 0
@15 clk 1 rst 1 preset 0 d 0 q 0
@16 clk 0 rst 1 preset 0 d 0 q 0
@17 clk 1 rst 1 preset 0 d 0 q 0
@18 clk 0 rst 1 preset 0 d 0 q 0
@19 clk 1 rst 1 preset 0 d 0 q 0
@20 clk 0 rst 0 preset 0 d 0 q 0
@21 clk 1 rst 0 preset 0 d 0 q 0
@22 clk 0 rst 0 preset 1 d 0 q 1
@23 clk 1 rst 0 preset 1 d 1 q 1
@24 clk 0 rst 0 preset 0 d 1 q 1
@25 clk 1 rst 0 preset 0 d 1 q 1
@26 clk 0 rst 0 preset 1 d 1 q 1
@27 clk 1 rst 0 preset 1 d 1 q 1
@28 clk 0 rst 0 preset 0 d 1 q 1
@29 clk 1 rst 0 preset 0 d 1 q 1
@30 clk 0 rst 0 preset 1 d 1 q 1
@31 clk 1 rst 0 preset 1 d 1 q 1
@32 clk 0 rst 0 preset 0 d 1 q 1
@33 clk 1 rst 0 preset 0 d 1 q 1
@34 clk 0 rst 0 preset 1 d 1 q 1
@35 clk 1 rst 0 preset 1 d 0 q 1
@36 clk 0 rst 0 preset 0 d 0 q 1
@37 clk 1 rst 0 preset 0 d 1 q 0
@38 clk 0 rst 0 preset 1 d 1 q 1
@39 clk 1 rst 0 preset 1 d 1 q 1
@40 clk 0 rst 0 preset 0 d 1 q 1
force and release
Another form of procedural continuous assignment is provided by the force and release procedural statements. These statements have a similar effect on the assign-deassign pair, but a force can be applied to nets as well as to registers.
过程化的连续赋值的另一种形式是通过force-release过程语句提供的。这些语句和assign-deassign语句块有这相似的作用。但是force可以应用到net类型变量和reg变量。
One can use force and release while doing gate level simulation to work around reset connectivity problems. Also can be used insert single and double bit errors on data read from memory.
当进行gate level的仿真时,可以使用force 和relase 来解决复位连接的问题。同样也可以用来向从memory中读取的数据中插入一位或者2位错误。
Example - force and release // force-release举例1 module force_release (); 2 3 reg clk,rst,d,preset; 4 wire q; 5 6 initial begin 7 $monitor("@%g clk %b rst %b preset %b d %b q %b", 8 $time, clk, rst, preset, d, q); 9 clk = 0; 10 rst = 0; 11 d = 0; 12 preset = 0; 13 #10 rst = 1; 14 #10 rst = 0; 15 repeat (10) begin 16 @ (posedge clk); 17 d <= $random; 18 @ (negedge clk) ; 19 preset <= ~preset; 20 end 21 #1 $finish; 22 end 23 // Clock generator 24 always #1 clk = ~clk; 25 26 // force and release of flip flop module 27 always @(preset) 28 if (preset) begin 29 force U.q = preset; // force procedural statement 30 end else begin 31 release U.q; // release procedural statement 32 end 33 34 d_ff U (clk,rst,d,q); 35 36 endmodule 37 38 // D Flip-Flop model 39 module d_ff (clk,rst,d,q); 40 input clk,rst,d; 41 output q; 42 wire q; 43 reg q_reg; 44 45 assign q = q_reg; 46 47 always @ (posedge clk) 48 if (rst) begin 49 q_reg <= 0; 50 end else begin 51 q_reg <= d; 52 end 53 54 endmoduleYou could download file force_release.v here
Simulator Output
@0 clk 0 rst 0 preset 0 d 0 q x
@1 clk 1 rst 0 preset 0 d 0 q 0
@2 clk 0 rst 0 preset 0 d 0 q 0
@3 clk 1 rst 0 preset 0 d 0 q 0
@4 clk 0 rst 0 preset 0 d 0 q 0
@5 clk 1 rst 0 preset 0 d 0 q 0
@6 clk 0 rst 0 preset 0 d 0 q 0
@7 clk 1 rst 0 preset 0 d 0 q 0
@8 clk 0 rst 0 preset 0 d 0 q 0
@9 clk 1 rst 0 preset 0 d 0 q 0
@10 clk 0 rst 1 preset 0 d 0 q 0
@11 clk 1 rst 1 preset 0 d 0 q 0
@12 clk 0 rst 1 preset 0 d 0 q 0
@13 clk 1 rst 1 preset 0 d 0 q 0
@14 clk 0 rst 1 preset 0 d 0 q 0
@15 clk 1 rst 1 preset 0 d 0 q 0
@16 clk 0 rst 1 preset 0 d 0 q 0
@17 clk 1 rst 1 preset 0 d 0 q 0
@18 clk 0 rst 1 preset 0 d 0 q 0
@19 clk 1 rst 1 preset 0 d 0 q 0
@20 clk 0 rst 0 preset 0 d 0 q 0
@21 clk 1 rst 0 preset 0 d 0 q 0
@22 clk 0 rst 0 preset 1 d 0 q 1
@23 clk 1 rst 0 preset 1 d 1 q 1
@24 clk 0 rst 0 preset 0 d 1 q 0
@25 clk 1 rst 0 preset 0 d 1 q 1
@26 clk 0 rst 0 preset 1 d 1 q 1
@27 clk 1 rst 0 preset 1 d 1 q 1
@28 clk 0 rst 0 preset 0 d 1 q 1
@29 clk 1 rst 0 preset 0 d 1 q 1
@30 clk 0 rst 0 preset 1 d 1 q 1
@31 clk 1 rst 0 preset 1 d 1 q 1
@32 clk 0 rst 0 preset 0 d 1 q 1
@33 clk 1 rst 0 preset 0 d 1 q 1
@34 clk 0 rst 0 preset 1 d 1 q 1
@35 clk 1 rst 0 preset 1 d 0 q 1
@36 clk 0 rst 0 preset 0 d 0 q 1
@37 clk 1 rst 0 preset 0 d 1 q 0
@38 clk 0 rst 0 preset 1 d 1 q 1
@39 clk 1 rst 0 preset 1 d 1 q 1
@40 clk 0 rst 0 preset 0 d 1 q 1
the above original link:http://www.asic-world.com/verilog/vbehave1.html