在Verilog程序中使用连续赋值是否可能和/或有用?例如,是否有任何理由将assign
置于always
区块内?
例如这段代码:
always @(*)
begin
assign data_in = Data;
end
此外,用这种方法生成顺序逻辑是否可能?
always @(posedge clk)
begin
assign data_in = Data;
end
它被称为程序连续分配。它是在程序块中使用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
或(目前有效但不鼓励)
// 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);