在Verilog程序中使用连续赋值?

问题描述 投票:3回答:1

在Verilog程序中使用连续赋值是否可能和/或有用?例如,是否有任何理由将assign置于always区块内?

例如这段代码:

always @(*) 
begin 
  assign data_in = Data;
end

此外,用这种方法生成顺序逻辑是否可能?

always @(posedge clk) 
begin 
  assign data_in = Data;
end
verilog fpga system-verilog
1个回答
6
投票

它被称为程序连续分配。它是在程序块中使用assignforce(及其相应的对应物deassignrelease)。在程序块中到达行时,将创建新的连续分配过程。 assign可以应用于注册类型,如regintegerrealforce可以应用于寄存器和网络(即wires)。自1364-1995以来,它一直是LRM的一部分。

  • IEEE Std1364-1995§9.3
  • IEEE Std1364-2001§9.3
  • IEEE Std1364-2005§9.3
  • IEEE Std1800-2005§25.3
  • IEEE Std1800-2009§10.6
  • IEEE Std 1800-2012第10.6节

程序连续分配可由大多数工具综合使用。但是,建议将用途限制为模拟块,测试台文件或修复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_nset_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);
© www.soinside.com 2019 - 2024. All rights reserved.