类型转换$cast(T, S)或者'()
一、always过程语句块:
1、组合逻辑语句块:always_comb
可以自动嵌入敏感列表;
verilog @* 的敏感列表声明方式不同于always_comb
1)@* 不要求可综合的建模要求,但always_comb则会限制其他过程块对同一变量进行赋值。
2)@*的敏感列表可能不完全,比如如果一个过程块调用一个函数,那么@*则只会将该函数的形式参数自动声明到敏感列表,而不会将该函数展开。
3)always_comb则会将被调用函数中可能参与运算的其他信号也声明到敏感列表中。
参考如下代码:
//它的敏感列表里面只有@ (data)。data是函数decode()的形参
always @* begin
a1 = data << 1;
b1 = decode();
...
end
//它的敏感列表有@(data, sel, c, d, e)
always_comb begin
a2 = data << 1;
b2 = decode();
...
end
function decode; // fuction with no inputs
begin
case (sel)
2'b01: decode = d | e;
2'b10: decode = d & e;
default: decode = c;
endcase
end
endfuction
可以禁止共享变量,即赋值左侧的变量无法被另一个过程块所赋值;
软件工具在检查always_comb过程块,如果它所表示的不是组合逻辑,那么会发出告警。
always @(a, en) if (en) y = a; //Verilog 需要写else才表示组合逻辑,但不会发出告警
always_comb if(en) y = a; //SystemVerilog 需要再添加else才表示组合逻辑,因此会发出告警。
它在仿真0时刻会自动触发一次,无论在0时刻敏感信号列表中的信号是否发生变化。
always @* 与always_comb的区别:
always_comb中被赋值的变量,不能在其他过程块中再次被赋值;
always_comb的敏感列表要比always @*更完全。
2、锁存逻辑语句块:always_latch
自动插入敏感列表;
always_latch
if (enable) q <= d;
EDA工具会检查always_latch过程块是否真正实现了锁存逻辑。
3、时序逻辑语句块:always_ff(ff是flip-flop的首字母缩写)
always_ff @(posedge clock, negedge resetN)
if (!resetN) q <= 0;
else q <= d;
它的敏感列表必须指明posedge或者negedge(综合要求),这样才能使得EDA工具实现同步或者异步的复位逻辑。
EDA工具也会帮忙检查always_ff过程语句块是否实现了时序逻辑。
以上3种细分always语句块以及always语句块本身都可以被SV所编译
4、赋值操作符
Verilog没有简单的方法可以对向量填充1.
parameter N = 64;
reg [N-1:0] data_bus;
data_bus = 64'fFFFFFFFFFFFFFFF; //将data_bus的所有bit位都设置成1
data_bus = {64{1'd1}}; //这种方式也可将其所有bit位设置成1
SV可以通过'0, '1, 'z, 'x分别来填充0, 1, z, x。这种方法,代码会根据向量的宽度自动填充,提高了代码的便捷性和复用性。
5、赋值比较操作
SV在比较数据时,可以通过 ==?来进行通配比较
在比较操作符的右侧操作数,如果在某些位置有X或者Z,那么它表示的是在该位置上会与左侧操作数的相同位置的任何值相匹配。
logic [7:0] opcode;
if (opcode ==? 8'b11011???) //表示低三位可以匹配左侧低三位的任何值
...
a | b | a == b | a === b | a ==? b | a != b | a !== b | a !=? b |
0000 | 000 | true | true | true | false | false | false |
0000 | 0101 | false | false | false | true | true | true |
010Z | 0101 | unknown | false | unknown | unknown | false | unknown |
010Z | 010Z | unknown | true | true | unknown | false | false |
010X | 010Z | unknown | false | true | unknown | true | false |
010X | 010X | unknown | true | true | unknown | false | false |
以下代码分别打印出:v1 == 1;v2 == 0
logic v1 = 'x';
if (v1 != 0) // x与0比较结果是unknown,所以执行else
$display("v1 != 0");
else
$display("v1 == 1");
logic v2 = '0';
if (v2 == 0)
$display("v2 == 0");
else
$display("v2 == 1");
6、inside操作符
用来检查数值是否在一系列值的集合之中。
logic [2:0] a;
if (a inside {3'b001, 3'b010, 3'b100})
...
7、unique case语句
Verilog中,case语句在执行时需要按照优先级,因为存在着几条case语句条件相同的情况,如果不定优先级而并行执行的话,会导致每次执行的结果不一致。
1)每次case选择必须且只能满足一条case选项;
2)不能有多个满足条件的选项,即条件相同的选项;
3)可以并行执行,并且case选项也必须完备。
8、priority case语句
1)必须至少有一个case选项满足要求;
2)如果有多个case选项满足时,第一个满足的分支将会被执行,剩下的将不会被执行;
3)它的逻辑和if...else的逻辑一致
unique和priority的声明也可以结合if...else条件语句使用