下面是功能相同但写法不同的两段代码:
第一段A
module assign_test_a (
clk,
lhold,
lholda
);
input clk;
input lhold;
output lholda;
reg lholda;
always @(posedge clk)
if (lhold)
lholda<=lhold;
else
lholda<=0;
endmodule
第二段B
module assign_test_b (
clk,
lhold,
lholda
);
input clk;
input lhold;
output lholda;
reg lholda_r;
always @(posedge clk)
if (lhold)
lholda_r<=lhold;
else
lholda_r<=0;
assign lholda=lholda_r;
endmodule
第一段A分析
第二段B的分析
Quartus RTL图
加入assign风格的综合结果
Xillinx RTL图
分析:
1. 从代码角度来看。 A是直接把内部reg信号做为输出,因此相对外部来说,外部信号引脚lholda没有选择的连接到reg输出信号。 这里其实暗含了用根导线直接把reg的输出与lholda连接起来。因此B代码就是把这个暗含的明显化。因此他们的RTL没有多大区别。
2. 从实用角度来说,这里的意义比较大。当内部有多个信号需要输出,可是输出引脚只有一个,那么这时就可以进行选择。如下:
assign lholda= (条件)? (lholda_ra): lholda_rb; 可以嵌套使用。
或者在这种情况下也非常有用。
Lholda 与 内部的reg输出lholda_ra, lholda_rb,…., 存在逻辑函数关系。
附录:
两相比较,几乎没有差别。可又为什么经常采用(2)的风格来编写类似代码?
一些verilog书上说assign用在连续型赋值的场合,摘自某书籍——
“连续赋值语句用来驱动线型变量,这一线型变量必须已经事先定义过。只要输入端操作数的值发生变化,该语句就重新计算并刷新赋值结果。我们可以使用连续赋值语句来描述组合逻辑而不需要用门电路和互连线。在前面一节中已经对连续赋值做了介绍,关键词assign用来区分连续赋值语句和过程赋值语句,下面一条语句将线型变量int1和int2相与,并用这一结果去驱动out信号:
wire out ;
assign out= int1 & int2 ;”
现在我不解的是,为什么在使用寄存器赋值的场合(过程赋值)也用到了
“assign 端口=寄存器 ;”
module assign_test_c (
clk,
lholda,
lholdb,
select,
lhold
);
input clk;
input lholda;
input lholdb;
input select;
output lhold;
wire lhold_ra;
wire lhold_rb;
assign_test_a uu1 (
.clk(clk),
. lhold(lholda),
.lholda(lhold_ra));
assign_test_a uu2 (
.clk(clk),
. lhold(lholdb),
.lholda(lhold_rb));
assign lhold=(select)?lhold_rb:lhold_ra;
endmodule
用户382800 2011-10-12 16:05
用户1324552 2010-7-17 10:52
jlx_cuc 2010-7-16 21:39