Procedures
always blocks (combinational)
procedural blocks 的作用和 assign 语句差别不大,但是相比于assign语句提供了更多的语法(比如if-else,case等等)。比如下面这种写法就是等价的:
assign out1 = a & b | c ^ d;
always @(*) out2 = a & b | c ^ d;
即可以使用always @(*)
隐式的触发always,也可以使用always @(a,b...)
显式的触发always。但是显式触发存在一个问题:当你在代码中显式指定触发变量时,模拟的结果会严格按照触发表生产,即不在触发表内的变量不会导致always block内的输出变化;但是在实际的硬件中,always @(a,b...)
会以always @(*)
的方式运行,因而导致本不应该变化的变量发生变化,极难查错。cite
always blocks (clocked)
遇到时钟触发的always block,就要涉及到verilog中的赋值方式了,主要有以下三种赋值方式:
- Continuous assignment
assign a = b;
- Procedural blocking assignment
x = y;
- Procedural non-blocking assignment
x <= y;
以下内容刻在DNA里:
在 combinational always blocks 里用 blocking assignment,在 clocked always blocks 里用 non-blocking assignment。
if
只能在 always 里用,跟任何一门编程语言中的 if-else 语句类似,但是创造了一种新的犯错方式 —— 不要忘了用 if-else-else… 去遍历所有情况,不然的话你的变量将不会被赋值(就像没有 default 的 case)。
case
- key 可以重复
- 每次只会运行一个 case 项,因此不像 C 需要 break
- 要写 endcase