Rus*_*ell 3 verilog fpga system-verilog
在Verilog程序中使用连续赋值是否可能和/或有用?例如,是否有任何理由放置assign一个always块?
例如这段代码:
always @(*)
begin
assign data_in = Data;
end
Run Code Online (Sandbox Code Playgroud)
此外,用这种方法生成顺序逻辑是否可能?
always @(posedge clk)
begin
assign data_in = Data;
end
Run Code Online (Sandbox Code Playgroud)
它被称为程序连续分配.它是利用一个的assign或force(和它们相应的对应物deassign和release程序块内).在程序块中到达行时,将创建新的连续分配过程.assign可以应用到寄存器类型,例如reg,integer,和real.force可以应用于寄存器和网络(即wires).自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;Run Code Online (Sandbox Code Playgroud)程序性连续分配的有效使用应适用于以下内容:
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
Run Code Online (Sandbox Code Playgroud)
它将使用异步设置合成到翻牌,并以优先级重置为重置.然而,在模拟中,如果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
Run Code Online (Sandbox Code Playgroud)
或(目前有效但不鼓励)
// translate_off
always @(rst_n or set_n)
if (rst_n && !set_n) assign q = 1'b1;
else deassign q;
// translate_on
Run Code Online (Sandbox Code Playgroud)
在未来的IEEE 1800版本中,正在考虑以这种方式使用assign/ deassign折旧.IEEE Std1800-2005§25.3,IEEE Std1800-2009§C.4.2和IEEE Std1800-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);
Run Code Online (Sandbox Code Playgroud)
解:
always @* // <- IEEE Std 1364-2001 construct
if (sel) reg1 = func1(x,y,z);
else reg1 = func2(a,b,c);
Run Code Online (Sandbox Code Playgroud)组合逻辑wire:
always @(sel)
if (sel) force wire1 = func1(x,y,z);
else force wire1 = func2(a,b,c);
Run Code Online (Sandbox Code Playgroud)
解:
assign wire1 = sel ? func1(x,y,z) : func2(a,b,c);
Run Code Online (Sandbox Code Playgroud)顺序逻辑:
always @(posedge clk)
if (sel) assign reg2 = func1(x,y,z);
else assign reg2 = func2(a,b,c);
Run Code Online (Sandbox Code Playgroud)
解决方案(假设原始功能有误):
always @(posedge clk)
if (sel) reg2 <= func1(x,y,z); // Non-blocking assignment !!!
else reg2 <= func2(a,b,c);
Run Code Online (Sandbox Code Playgroud)解决方案(假设原始功能正确):
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);
Run Code Online (Sandbox Code Playgroud)