Verilog Blocking Assignment

后端 未结 4 1285
太阳男子
太阳男子 2021-01-21 10:04

I am somewhat new to Verilog. I know that in a Clock Process we should use non blocking assignments, and in a Non Clock processes, we use blocking assignments.

I have c

相关标签:
4条回答
  • 2021-01-21 10:29

    The blocking vs non-blocking is so that your gate level (synthesis) matches your RTL simulation. Using a different one to alter the behaviour of the simulation as far as I know will not effect synthesis and therefore the behaviour of gate-level.

    <= non-blocking effectively take a temporary copy of the copy right-hand side, and make the = blocking assignment at the end of the timestep.

    a <= b;
    b <= a;
    

    is equivalent to:

    a_temp = b;
    b_temp = a;
    //
    a = a_temp;
    b = b_temp;
    

    The example uses combinatorial logic, that is it contains no state, so all inputs must be defined by all outputs.

    always@* begin
      iowrb_int <= iowrb_met;
      iordb_int <= iordb_met;
      iowrb_met <= iowr_bar;
      iordb_met <= iord_bar;
    end
    

    When the right hand side updates the block should be retriggered. Since iowrb_met is on both sides I am not sure what this implies interms of electrical connectivity.

    while <= implies copying to a temp location, combinatorial logic does not have this capability, it is always and continuously driven by the assignment.

    I think in simulation you effectively have this:

    always@* begin
      iowrb_int_temp = iowrb_met;
      iordb_int_temp = iordb_met;
      iowrb_met      = iowr_bar;
      iordb_met      = iord_bar;
      iowrb_int      = iowrb_int_temp;
      iordb_int      = iordb_int_temp;
    end
    

    In hardware you would have:

    always@* begin
      iowrb_int = iowrb_met;  //= iowr_bar;
      iordb_int = iordb_met;  //= iord_bar;
      iowrb_met = iowr_bar;
      iordb_met = iord_bar;
    end
    

    Where iowrb_int is effectively the same as iowrb_met

    Flip-flops are implied using always @(posedge clk
    Combinatorial logic is implied using always @* but latches can be implied when the output is not fully defined from inputs.

    0 讨论(0)
  • 2021-01-21 10:34

    By only changing to code to blocking assignments it may synthesize to latches and/or create logical equivalency check mismatches depending on the tools handle.

    This is how it looks through the scheduler:

    • With blocking:

      1. The *_int signals are assigned
      2. The *_met signals are assigned
      3. Move on to the next time step.
        • *_int keeps the non-updated values of *_met
    • With non-blocking:

      1. The *_int signals are assigned
      2. The *_met signals are assigned
      3. A change to *_met is detected causes a loop back the the Active region of the scheduler
      4. Re-assign the *_int signals
      5. Re-assign the *_int signals
      6. Move on to the next time step.
        • *_int has the same values as *_met
        • Waste CPU time to reprocessing. This is not important on a small project, but can add noticeable overhead used throughout a large project.

    The correct, logical equivalent, and CPU friendly way would be to revers the assignment order (assign *_met before *_int):

    always@(*)
    begin
      iowrb_met = iowr_bar;
      iordb_met = iord_bar;
    
      iowrb_int = iowrb_met;
      iordb_int = iordb_met;
    end
    
    1. The *_int signals are assigned
    2. The *_met signals are assigned
    3. Move on to the next time step.
      • *_int has the same values as *_met

    OR use *_bar as the assigning value (i.e. if a==b and b==c, then a==b and a==c):

    always@(*)
    begin
      iowrb_int = iowr_bar;
      iordb_int = iord_bar;
    
      iowrb_met = iowr_bar;
      iordb_met = iord_bar;
    end
    
    1. The *_int and *_met signals are assigned
    2. Move on to the next time step.
      • *_int has the same values as *_met
    0 讨论(0)
  • 2021-01-21 10:43

    As others have said, changing to blocking assignments here will actually not work. Using blocking assignments in combinational always blocks (which is the recommendation) require you to put assignments in the right order.

    Using non-blocking assignments in combinational always blocks may seem attractive, because you can then have assignments in any order, like in VHDL. Besides performance, one good reason to avoid this is that it doesn't work with always_comb. This code does not work:

    always_comb begin
      tmp <= in;
      out <= tmp;
    end
    

    The reason is that tmp will not be part of the sensitivity list. It will work as expected if you use always @(*), always @(tmp, in) or replace with blocking assignments.

    0 讨论(0)
  • The main difference is:

    • a blocking assignment is executed before the next assignment i.e. it blocks the execution of the next statement.
    • non-blocking assignments execute in parallel i.e. they don't block the execution of the statement following them.

    Suppose a = 2 and b = 3 then non-blocking assignments:

    a <= 4;
    b <= a; 
    

    results in a = 4 and b = 2 - value of a before assignment

    But

    a = 4;
    b = a;
    

    Will result in a=4 and b=4 - value of a after the blocking assignment completes.

    A variable getting synthesized to a register (latch or flip-flop) vs. combinatorial logic depends on the sensitivity list of the always block. It does not depend on use of blocking or non-blocking assignment.

    For example:

    always @(*) begin
      if (enable)
         q = d;
    end
    

    This will result in a D-latch since assignment to q is not specified for when enable==0 so it needs to remember is last assignment.

    While

    always @(*) begin
      if (enable)
        q = d;
      else
        q = f;
    end
    

    This will result in a mux (combinatorial logic) since assignment to q is specified for both cases of enable and so q need not remember anything.

    0 讨论(0)
提交回复
热议问题