(原)verilog中的reg类型变量,一定会综合出触发器吗?

初学verilog的同学们,可能潜意识就认为一个reg对应一个触发器,其实不然。

我们先看一个例子:

 1 `timescale 1ns/100ps
 2 
 3 module prj_1(
 4 input b1,b2,
 5 output reg a1,a2
 6 );
 7 
 8 always@(*) begin
 9 #5 a1 = b1;
10 end
11 
12 always@(*) begin
13 a2 = #5 b2;
14 end
15 endmodule

由于always模块要求赋值左端都是reg类型,所以定义a1、a2均为reg类型。

注意,第8行,敏感列表是"*",*号代替了本always模块里面所有的触发信号。

查看其RTL电路图,会发现是这样的

可以看到,设计的电路是一个纯粹的组合逻辑电路,不会综合出DFF。为什么会这样呢?

以下是verilog-2001的标准中对wire和reg的定义如下:

wire
A wire net can be used for nets that are driven by a single gate or continuous assignment.
reg
Assignments to a reg are made by procedural assignments (see 6.2 and 9.2). Since the reg holds a value between assignments, it can be used to model hardware registers. Edge-sensitive (i.e., flip-flops) and level sensitive (i.e., RS and transparent latches) storage elements can be modeled. A reg needs not represent a hardware storage element since it can also be used to represent combinatorial logic.

这段话的意思是:在过程赋值语句中,表达式右侧的计算结果在某种条件的触发下放到一个变量当中,而这个变量可以声明成reg类型的。根据触发条件的不同,过程赋值语句可以建模不同的硬件结构:如果这个条件是时钟的上升沿或下降沿,那么这个硬件模型就是一个触发器如果这个条件是某一信号的高电平或低电平,那么这个硬件模型就是一个锁存器;如果这个条件是赋值语句右侧任意操作数的变化,那么这个硬件模型就是一个组合逻辑

也就是说,综合出触发器的条件是,需要有时钟的沿触发。

同样,我们看一段使用function的代码

 1 module prj_1(
 2 input [7:0]a,b,c,d,
 3 input [15:0]e,f,
 4 output [15:0] x,y
 5 );
 6 
 7 
 8 function reg [15:0]  muladd;
 9 input [7:0] a;
10 input [7:0] b;
11 input [15:0] c;
12 begin
13 muladd = a*b + c;
14 end
15 endfunction
16 
17 assign x = muladd(a,b,e);
18 assign y = muladd(c,d,f);
19 
20 
21 endmodule

function默认返还类型为reg,所以第8句,reg类型可以不声明。muladd实现的功能就是一个乘加运算,是一个纯粹的组合电路。这个module的RTL电路图是这样的

因为没有时钟触发,所以仍是一个纯粹的组合逻辑。

总结:

在一些语句中,需要定义变量为reg类型(always、fuction等)。根据触发条件的不同,过程赋值语句可以建模不同的硬件结构。如果有时钟沿触发,则会生成DFF。

======================================================

ps:

其实

always@(*)

是设计组合逻辑最常的使用方式。

原文地址:https://www.cnblogs.com/surpassal/p/2747789.html