在Verilog程序中使用连续赋值是否可行和/或有用?例如,是否有任何理由将assign
置于always
块内?
例如这段代码:
always @(*)
begin
assign data_in = Data;
end
此外,是否可以使用这种方法生成顺序逻辑?
always @(posedge clk)
begin
assign data_in = Data;
end
答案 0 :(得分:6)
它被称为程序连续分配。在程序块中使用assign
或force
(及其对应的对应deassign
和release
)。在程序块中到达行时,将创建新的连续分配过程。 assign
可以应用于注册类型,例如reg
,integer
和real
。 force
可以应用于寄存器和网络(即wire
s)。自1364-1995以来,它一直是LRM的一部分。
大多数工具都可以合成程序性连续分配。然而,建议将其用于限制模拟块,测试台文件或修复RTL - 门功能不匹配的行为建模。
always @* assign data_in = Data;
always @* data_in = Data;
always @(posedge clk) assign data_in = Data;
always @(posedge clk)
enable = 1;
always @*
if (enable==1) data_in = Data;
程序连续分配的有效使用应适用于以下内容:
always @(posedge clk or negedge rst_n, negedge set_n) begin
if (!rst_n) q <= 1'b0;
else if (!set_n) q <= 1'b1;
else q <= d;
end
它将使用异步设置合成到翻牌并重置优先级以重置。然而,在模拟中,如果rst_n
和set_n
都低,则rst_n
变高,模型就不准确。 q
应该转到1,异步集仍然启用,但灵敏度列表中没有触发任何内容。这是Verilog记录完备的问题。当与合成器的translate off关键字一起使用时,在RTL中允许一个程序连续分配。 release
/ deassign
允许以通常的方式分配寄存器/电线。
// translate_off
always @(rst_n or set_n)
if (rst_n && !set_n) force q = 1'b1;
else release q;
// translate_on
OR(目前有效但不鼓励)
// translate_off
always @(rst_n or set_n)
if (rst_n && !set_n) assign q = 1'b1;
else deassign q;
// translate_on
以这种方式使用assign
/ deassign
正在考虑在将来的IEEE 1800版本中进行折旧。 IEEE Std1800-2005§25.3,IEEE Std1800-2009§C.4.2和IEEE Std 1800-2012§C.4.2承认assign
使用这种方式会引起混淆并且是错误的根源。如果需要进行程序性连续分配,请使用force
/ release
。
使用程序连续分配生成(使用force
/ release
)只应在绝对必要时使用。替代方法更可靠。
reg
上的组合逻辑:
always @(sel)
if (sel) assign reg1 = func1(x,y,z);
else assign reg1 = func2(a,b,c);
解决方案:
always @* // <- IEEE Std 1364-2001 construct
if (sel) reg1 = func1(x,y,z);
else reg1 = func2(a,b,c);
wire
上的组合逻辑:
always @(sel)
if (sel) force wire1 = func1(x,y,z);
else force wire1 = func2(a,b,c);
解决方案:
assign wire1 = sel ? func1(x,y,z) : func2(a,b,c);
顺序逻辑:
always @(posedge clk)
if (sel) assign reg2 = func1(x,y,z);
else assign reg2 = func2(a,b,c);
解决方案(假设原始功能错误):
always @(posedge clk)
if (sel) reg2 <= func1(x,y,z); // Non-blocking assignment !!!
else reg2 <= func2(a,b,c);
解决方案(假设原始功能正确):
reg flop_sel;
always @(posedge clk)
flop_sel <= sel; // Non-blocking assignment !!!
always @*
if (flop_sel) reg2 = func1(x,y,z); // Blocking assignment !!!
else reg2 = func2(a,b,c);