总是阻塞verilog中的阻塞赋值?
Blocking assignments in always block verilog?
现在我知道在 Verilog 中,要制作顺序逻辑,您几乎总是会在 always 块中使用非阻塞赋值 (<=)。但是这条规则也适用于内部变量吗?如果将阻塞赋值用于 always 块中的内部变量,它会使其成为梳状逻辑还是顺序逻辑?
因此,例如,我正在尝试编写顺序预分频器模块的代码。它的输出只会是一个时钟周期持续时间的正脉冲。它将有一个参数值,它将是预分频器(将 clk 分频多少个时钟周期)和一个计数器变量来跟踪它。
我将 count 的赋值设置为阻塞赋值,但输出 q 是非阻塞的。出于模拟目的,代码有效; q 的输出正是我想要的方式。如果我将分配更改为非阻塞,则 q 的输出仅在参数长度的第一个周期内正常工作,然后由于某种原因永远保持为 0(这可能是因为它的编码方式,但我可以'似乎没有想到另一种编码方式)。那么代码现在的行为方式是组合逻辑还是顺序逻辑?而且,这在行业中是否可以接受?这是可合成的吗?
```
module scan_rate2(q, clk, reset_bar);
//I/O's
input clk;
input reset_bar;
output reg q;
//internal constants/variables
parameter prescaler = 8;
integer count = prescaler;
always @(posedge clk) begin
if(reset_bar == 0)
q <= 1'b0;
else begin
if (count == 0) begin
q <= 1'b1;
count = prescaler;
end
else
q <= 1'b0;
end
count = count - 1;
end
endmodule
```
您应该遵循告诉您对时序逻辑的所有输出使用非阻塞分配的行业惯例。唯一的例外是 temporary 变量,它们用于帮助评估顺序逻辑中的复杂表达式,前提是它们 only 在单个块中使用.
在您的情况下,对 'counter' 使用 'blocking' 会导致合成行为不匹配。综合将为 q
和 count
创建触发器。但是,在您使用阻塞分配的情况下,count
将在分配 prescaled 值后立即递减,无论是在合成之后,它只会在下一个周期发生。
所以,你需要一个非阻塞的。顺便说一句,在声明中初始化 'count' 可能适用于 fpga 综合,但不适用于原理图综合,因此最好以不同的方式初始化它。除非我误解了您的意图,否则它应该如下所示。
integer count;
always @(posedge clk) begin
if(reset_bar == 0) begin
q <= 1'b0;
counter <= prescaler - 1;
end
else begin
if (count == 0) begin
q <= 1'b1;
count <= prescaler -1;
end
else begin
q <= 1'b0;
count <= count - 1;
end
end
end
那里不需要临时变量,但为了便于说明,可以按以下方式完成:
...
integer tmp;
always ...
else begin
q <= 1'b0;
tmp = count - 1; // you should use blocking here
count <= tmp; // but here you should still use NBA
end
现在我知道在 Verilog 中,要制作顺序逻辑,您几乎总是会在 always 块中使用非阻塞赋值 (<=)。但是这条规则也适用于内部变量吗?如果将阻塞赋值用于 always 块中的内部变量,它会使其成为梳状逻辑还是顺序逻辑?
因此,例如,我正在尝试编写顺序预分频器模块的代码。它的输出只会是一个时钟周期持续时间的正脉冲。它将有一个参数值,它将是预分频器(将 clk 分频多少个时钟周期)和一个计数器变量来跟踪它。
我将 count 的赋值设置为阻塞赋值,但输出 q 是非阻塞的。出于模拟目的,代码有效; q 的输出正是我想要的方式。如果我将分配更改为非阻塞,则 q 的输出仅在参数长度的第一个周期内正常工作,然后由于某种原因永远保持为 0(这可能是因为它的编码方式,但我可以'似乎没有想到另一种编码方式)。那么代码现在的行为方式是组合逻辑还是顺序逻辑?而且,这在行业中是否可以接受?这是可合成的吗?
```
module scan_rate2(q, clk, reset_bar);
//I/O's
input clk;
input reset_bar;
output reg q;
//internal constants/variables
parameter prescaler = 8;
integer count = prescaler;
always @(posedge clk) begin
if(reset_bar == 0)
q <= 1'b0;
else begin
if (count == 0) begin
q <= 1'b1;
count = prescaler;
end
else
q <= 1'b0;
end
count = count - 1;
end
endmodule
```
您应该遵循告诉您对时序逻辑的所有输出使用非阻塞分配的行业惯例。唯一的例外是 temporary 变量,它们用于帮助评估顺序逻辑中的复杂表达式,前提是它们 only 在单个块中使用.
在您的情况下,对 'counter' 使用 'blocking' 会导致合成行为不匹配。综合将为 q
和 count
创建触发器。但是,在您使用阻塞分配的情况下,count
将在分配 prescaled 值后立即递减,无论是在合成之后,它只会在下一个周期发生。
所以,你需要一个非阻塞的。顺便说一句,在声明中初始化 'count' 可能适用于 fpga 综合,但不适用于原理图综合,因此最好以不同的方式初始化它。除非我误解了您的意图,否则它应该如下所示。
integer count;
always @(posedge clk) begin
if(reset_bar == 0) begin
q <= 1'b0;
counter <= prescaler - 1;
end
else begin
if (count == 0) begin
q <= 1'b1;
count <= prescaler -1;
end
else begin
q <= 1'b0;
count <= count - 1;
end
end
end
那里不需要临时变量,但为了便于说明,可以按以下方式完成:
...
integer tmp;
always ...
else begin
q <= 1'b0;
tmp = count - 1; // you should use blocking here
count <= tmp; // but here you should still use NBA
end