wire类型在每次赋值前要加assign,而reg类型在每次赋值前不需要加任何东西。
在 always 块内被赋值的信号应定义成 reg 型,用 assign 语句赋值的信号应定义成 wire 型。
操作符
~
按位取反、&
按位与、|
按位或。
||
逻辑或
wire:
在Verilog中,线网型信号(wire
)是一种主要的数据类型,用于表示连接信号。它类似于实际电路中的导线,用于传输信号。wire
类型的信号通常用于组合逻辑电路中,表示信号的传递和连接。
wire
类型信号的主要特点是它们不能存储值,只能传递值。因此,它们通常用于组合逻辑电路,而不是时序逻辑电路。wire
类型的信号在assign
语句中被赋值,但不能在always
块中被赋值。
assign:
实现组合逻辑操作的一种主要描述方式。只能给wire赋值
assign out={b,a}
把b,a拼接到out上面去
reg:
除 wire 类型外,另外一种常用的数据类型,一般表示寄存器类型数据,不过并不绝对,记住一条原则:在 always 块内被赋值的信号应定义成 reg 型,用 assign 语句赋值的信号应定义成 wire 型。
always:
除 assign 外,另外一种实现赋值操作的关键字,两者都不可嵌套,区别在于,assign 语句只能实现组合逻辑赋值,且一个 assign 语句后面只能跟一条赋值表达式。而 always 即能实现组合逻辑赋值,又能实现时序逻辑赋值操作,且可以包含多条赋值表达式,多条赋值表达式,则应位于 begin/end 对中间。
USTC VLab Verilog OJ | YAVG Group Presents
所有的数字电路都是由逻辑门和连线构成的,因此理论上来说都可以通过模块的连接和assign语句进行描述,然而在很多情况下这并不是最方便的一种方式,过程块提供了一种更加方便的描述方式,always过程块便是其中最常用的一种。
对于可综合电路(即能转化成实际电路的verilog描述方式,与之相对的是不可综合电路,多用于电路仿真,不能转换成实际电路),有两种always块的语法形式:
-组合逻辑电路:always@()
-时序逻辑电路:always@(posedge clk)
组合逻辑电路的always块与assign语句等效,用户描述组合逻辑电路时,可根据便利性选择其中一种方式使用。两者生成的硬件电路一般是等效的,但在语法规则上稍有不同:
-assign语句只能对一个信号进行赋值,always块内可对多个信号进行赋值
-assign语句中被赋值信号为wire类型,always块内被赋值信号需定义为reg类型
-always块内支持更加丰富的语法,如使用if…else..、case等适合实现交复杂的组合逻辑
例如下述两条语句是等效的(out1需定义为wire类型,out2需定义为reg类型,但这仅仅是语法上的要求,生成的电路并没有区别):
assign out1 = a & b | c ^ d;
always @() out2 = a & b | c ^ d;
其对应的电路图如下所示:
always语句后的括号内放的是敏感变量列表,对于上例来说,可以写成always @(a,b,c,d) out2 = a & b | c ^ d,但为了简单起见,我们一般都用符号*代替。
posedge/negedge:
posedge是Verilog 关键字,表示上升沿的意思。always @(posedge clk)
表示在 clk 信号的上升沿的时刻,执行 always 块内部的语句,与此相对应的,是表示下降沿的关键字 negedge。凡是带有 posedge 或 negedge 的 always 块,都会被综合成时序逻辑电路。
在同一个always进程块中,同一触发信号只能使用一种边沿,即上升沿和下降沿不可同时使用。(例如:always@(posedge clk or negedge clk),这种写法是错误的)
阻塞/非阻塞赋值:
采用 <=
进行赋值的语句,称为“非阻塞赋值”,采用 =
进行赋值的语句,称为“阻塞赋值”。在 always 块中,阻塞式赋值方式语句执行有先后顺序,而非阻塞赋值语句则是同时执行。因此,在时序逻辑电路中,两种赋值方式可能或综合出不同的电路结构。
按位或\与
按位与、归并与操作,如该操作符只有一个操作数时,则将该操作数的所有位进行相与操作
向量拼接
part_selection用于选择向量信号中的一部分,而向量拼接算子{a,b,c}用于将多个信号组合成一个位宽更大的向量信号,如:
{3'b111, 3'b000} 等同于 6'b111000
{1'b1, 1'b0, 3'b101} 等同于5'b10101
{4'ha, 4'd10} 等同于 8'b10101010 // 4'ha and 4'd10 are both 4'b1010 in binary
向量拼接时,每个信号都需要有明确的位宽,这样拼接后的信号才会有明确的位宽。例如,{1,2,3}就是非法的,因为无法确定各信号的位宽,语法检查时会报错。
向量拼接算子既可以用于赋值语句的左侧,也可用于右侧,如下所示:
input [15:0] in;
output [23:0] out;
assign {out[7:0], out[15:8]} = in;
assign out[15:0] = {in[7:0], in[15:8]};
assign out = {in[7:0], in[15:8]};
复制算子
复制算子是拼接算子的一种特殊情况,如a={b,b,b,b,b,b}便可以写成a={6{b}}的形式。复制算子的格式为:{num{vector}},其中num必须为常量。如下所示:
{5{1'b1}} // 5'b11111 (or 5'd31 or 5'h1f)
{2{a,b,c}} // The same as {a,b,c,a,b,c}
{3'd5, {2{3'd6}}} // 9'b101_110_110
parameter
定义常量的关键字。它允许你在模块中定义一些固定的值,这些值可以在模块实例化时进行参数化,从而使模块更加灵活和可重用。
case/casez
casez的用途:它将值为z的位在比较中视为无关紧要。
//四输入优先编码器
always @(*) begin
casez (in[3:0])
4'bzzz1: out = 0; // in[3:1] can be anything
4'bzz1z: out = 1;
4'bz1zz: out = 2;
4'b1zzz: out = 3;
default: out = 0;
endcase
end
标签:语句,always,verilog,信号,out,assign,赋值
From: https://www.cnblogs.com/r0xy/p/18646009