Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
280 views
in Technique[技术] by (71.8m points)

fpga - Using a continous assignment in a Verilog procedure?

Is it possible and/or useful to ever use a continuous assignment in a Verilog procedure? For example, would there ever be any reason to put an assign inside of an always block?

For example this code:

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

Furthermore would it be possible to generate sequential logic with this approach?

always @(posedge clk) 
begin 
  assign data_in = Data;
end
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is called procedural continuous assignment. It is the use of an assign or force (and their corresponding counterparts deassign and release) within procedural block. A new continuous assignment process is created when the line is reached in the procedural block. assign can be applied to register types such as reg, integer, and real. force can be applied to registers and nets (i.e. wires). It has been part of the LRM since 1364-1995.

  • IEEE Std 1364-1995 § 9.3
  • IEEE Std 1364-2001 § 9.3
  • IEEE Std 1364-2005 § 9.3
  • IEEE Std 1800-2005 § 25.3
  • IEEE Std 1800-2009 § 10.6
  • IEEE Std 1800-2012 § 10.6

Procedural continuous assignments are synthesizable, by most tools. However it is recommend to limit the use to behavior modeling of an analog block, test bench files, or fixing RTL<->gate functional mismatches.

  • always @* assign data_in = Data;
    is functional the same as
    always @* data_in = Data;

  • always @(posedge clk) assign data_in = Data;
    is functional the same as:
    always @(posedge clk)
      enable = 1;
    always @*
      if (enable==1) data_in = Data;

A valid use of procedural continuous assignment would be should be applited to the following:

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

It will synthesize to a flop with an asynchronous set and reset with priority to reset. In simulation however the model is inaccurate if rst_n and set_n are both low then rst_n goes high. q should go to 1 the the asynchronous set is still enabled, but nothing to trigger in in the sensitivity list. This is a well documented issue with Verilog. It is the one case procedural continuous assignment are allowed in RTL when used with the translate off keyword your synthesizer. The release/deassign allows the the register/wire to be assigned in the usual manner.

// translate_off
always @(rst_n or set_n)
  if (rst_n && !set_n) force q = 1'b1;
  else                 release q;
// translate_on

OR (currently valid but discouraged)

// translate_off
always @(rst_n or set_n)
  if (rst_n && !set_n) assign q = 1'b1;
  else                 deassign q;
// translate_on

Using assign/deassign in this manner is being considered to be depreciated in future IEEE 1800 release. IEEE Std 1800-2005 § 25.3, IEEE Std 1800-2009 § C.4.2 and IEEE Std 1800-2012 § C.4.2 recognizes assign used this way causes confusion and is the source of errors. Use force/release if procedural continuous assignment as needed.

In generate using procedural continuous assignment (with force/release) should only be used if absolutely necessary. Alternative approaches are more reliable.

Misuse of procedural continuous assignment and solutions:

  • Combinational logic on reg:

    always @(sel)
      if (sel) assign reg1 = func1(x,y,z);
      else     assign reg1 = func2(a,b,c);
    
    • Solution:

      always @* // <- IEEE Std 1364-2001 construct
        if (sel) reg1 = func1(x,y,z);
        else     reg1 = func2(a,b,c);
      
  • Combinational logic on wire:

    always @(sel)
      if (sel) force wire1 = func1(x,y,z);
      else     force wire1 = func2(a,b,c);
    
    • Solution:

      assign wire1 = sel ? func1(x,y,z) : func2(a,b,c);
      
  • Sequential logic:

    always @(posedge clk)
      if (sel) assign reg2 = func1(x,y,z);
      else     assign reg2 = func2(a,b,c);
    
    • Solution (assuming original functionality is wrong):

      always @(posedge clk)
        if (sel) reg2 <= func1(x,y,z); // Non-blocking assignment !!!
        else     reg2 <= func2(a,b,c);
      
    • Solution (assuming original functionality is correct):

      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);
      

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...