我有些新来的Verilog。我知道,在一个时钟进程,我们应该使用非阻塞的任务,并在非时钟过程中,我们使用阻塞赋值。
我曾经碰到这个代码来了,当我读别人的代码。
reg iowrb_int,iowrb_met;
reg iordb_int,iordb_met;
always@(*)
begin
iowrb_int <= iowrb_met;
iordb_int <= iordb_met;
iowrb_met <= iowr_bar;
iordb_met <= iord_bar;
end
我真的不知道上面的代码!我不认为这是做任何登记,是否正确?这一切意味着什么有一个始终@(*)语句非阻塞?
有没有在使用中总是阻止与非阻止任何区别@(*)语句?
主要的区别是:
假设一个= 2和b = 3,那么非阻塞赋值:
a <= 4;
b <= a;
导致= 4且b = 2 - 值的之前分配的
但
a = 4;
b = a;
将导致= 4和b = 4 - 阻塞分配完成后值的。
一种可变得到合成到寄存器(锁存器或触发器)对组合逻辑取决于总是块的灵敏度列表上。它不依赖于使用阻塞或非阻塞分配。
例如:
always @(*) begin
if (enable)
q = d;
end
这将导致d-锁,因为不是时启用== 0,因此需要记住的是最后分配指定分配给q为。
而
always @(*) begin
if (enable)
q = d;
else
q = f;
end
这将导致因为对使能等q不必记得任何事情的两种情况下被指定分配到q多路复用器(组合逻辑)。
阻挡与非阻挡是使你的栅极电平(合成)您的RTL仿真匹配。使用不同的一个改变模拟的行为,据我所知不会影响合成,因此门级的行为。
<=
有效无阻塞采取复制右侧的临时副本,使=
在时间步长结束封锁任务。
a <= b;
b <= a;
相当于:
a_temp = b;
b_temp = a;
//
a = a_temp;
b = b_temp;
该示例使用组合逻辑,即它不包含任何状态,因此,所有输入必须通过所有输出来定义。
always@* begin
iowrb_int <= iowrb_met;
iordb_int <= iordb_met;
iowrb_met <= iowr_bar;
iordb_met <= iord_bar;
end
当右侧更新块应该重新触发。由于iowrb_met是双方我不知道这意味着interms电连接性。
而<=
意味着复制到一个临时位置,组合逻辑不具备这种能力,它总是不断被分配驱动。
我想在模拟您有效地有这样的:
always@* begin
iowrb_int_temp = iowrb_met;
iordb_int_temp = iordb_met;
iowrb_met = iowr_bar;
iordb_met = iord_bar;
iowrb_int = iowrb_int_temp;
iordb_int = iordb_int_temp;
end
在硬件你会:
always@* begin
iowrb_int = iowrb_met; //= iowr_bar;
iordb_int = iordb_met; //= iord_bar;
iowrb_met = iowr_bar;
iordb_met = iord_bar;
end
其中iowrb_int
实际上是相同的iowrb_met
触发器使用always @(posedge clk
隐含
组合逻辑是使用always @*
隐含但当输出没有完全从输入锁存器定义可以暗示。
仅通过改变代码来阻塞赋值可以综合成锁存器和/或创建取决于工具的处理逻辑等效性检查不匹配。
这是它的外观通过调度:
*_int
信号被分配
的*_met
信号被分配
移动到下一个时间步长。
*_int
保持*_met
的未更新的值*_int
信号被分配
的*_met
信号被分配
到*_met
变化来检测导致环回调度器的有源区
重新分配*_int
信号
重新分配*_int
信号
移动到下一个时间步长。
*_int
具有如*_met
相同的值
浪费CPU时间再处理。这不是一个小项目很重要,但可以添加在整个大项目中使用明显的开销。正确的逻辑等价的,CPU友好的方式将扭转分配顺序(分配qazxsw POI之前qazxsw POI):
*_met
*_int
信号被分配always@(*)
begin
iowrb_met = iowr_bar;
iordb_met = iord_bar;
iowrb_int = iowrb_met;
iordb_int = iordb_met;
end
信号被分配*_int
具有如*_met
相同的值或使用*_int
作为所述分配值(即,如果一个== B和B == C,然后一个== b和a == c)中:
*_met
*_bar
和always@(*)
begin
iowrb_int = iowr_bar;
iordb_int = iord_bar;
iowrb_met = iowr_bar;
iordb_met = iord_bar;
end
信号被分配*_int
具有如*_met
相同的值正如其他人所说,转变为阻塞赋值这里实际上将无法正常工作。在组合always块使用阻塞赋值(这是我们推荐的)要求你把任务按正确的顺序。
在组合使用非阻塞赋值总是块可能看起来有吸引力的,因为你就可以在任何顺序分配,就像在VHDL。除了性能,一个好理由,以避免这种情况的是,它不与*_int
工作。此代码不能正常工作:
*_met
原因是,always_comb
不会成为敏感列表的一部分。它将按预期工作,如果你使用always_comb begin
tmp <= in;
out <= tmp;
end
,tmp
或阻塞赋值替换。