Skip to content

Blocking and Non-blocking Assignments

continuous assignment

  • each assign statement models a separate hardware gate, runs concurrently
  • multiple assign statements to the same variable will cause a conflict (multiple drivers)
continuous_assignment.sv
1
2
3
4
5
6
7
8
module continuous_assignment (
    input logic a,
    input logic b,
    output logic y
);
    assign y = a & b; // continuous assignment
    assign y = a | b; // ERROR: multiple drivers to y
endmodule

fuctions

  • used to encapsulate reusable combinational logic
function_example.sv
module function_example (
    input logic [3:0] a,
    input logic [3:0] b,
    output logic [3:0] sum
);
    // function to add two 4-bit numbers
    function logic [3:0] add4bit(input logic [3:0] x, input logic [3:0] y);
        add4bit = x + y;
    endfunction

    assign sum = add4bit(a, b); // use the function
endmodule

blocking and non-blocking assignments

  • blocking assignment (=): statements execute sequentially, next statement waits for current to complete
    • order matters
  • non-blocking assignment (<=): statements execute concurrently, all right-hand sides are evaluated before any left-hand sides are updated
    • order does not matter
    • DO NOT make assignments to the same variable in multiple non-blocking assignments within the same procedural block
blocking_nonblocking.sv
module blocking_nonblocking (
    input logic a,b,c
    output logic sum, prod);

    // note: this two blocks will be executed at the same time (concurrently)
    always @(posedge clk) begin
        a = 5; b = 10; c = 4; sum = 2, prod = 8;
        // blocking assignments
        sum = a + b; // sum = 15
        prod = sum * c; // prod = 60
    end
    always @(posedge clk) begin
        a = 5; b = 10; c = 4; sum = 2, prod = 8;
        // non-blocking assignments
        sum <= a + b; // sum = 15
        prod <= sum * c; // prod = 8 (uses old value of sum)
    end
endmodule

what is the value of p and q after the rising edge of clk?

example1.sv
module example1(input q, p, clk);
    assign p = 5;
    assign q = 8;
    always @(posedge clk) begin
        p = q
    end
    always @(posedge clk) begin
        q = p;
    end
endmodule

answer: p = q = 5, or p = q = 8, depending on which always block executes first

example2.sv
1
2
3
4
5
6
7
8
module example2(input q, p, clk);
    assign p = 5;
    assign q = 8;
    always @(posedge clk) begin
        p = q;
        q = p;
    end
endmodule

answer: p = q = 8

example3.sv
1
2
3
4
5
6
7
8
module example3(input q, p, clk);
    assign p = 5;
    assign q = 8;
    always @(posedge clk) begin
        p <= q;
        q <= p;
    end
endmodule

answer: p = 8, q = 5

example4.sv
1
2
3
4
5
6
7
8
module example4(input q, p, clk);
    assign p = 5;
    assign q = 8;
    always @(posedge clk) begin
       p <= q + 2;
       p <= q + 3;
    end
endmodule

answer: p = 10 or p = 11, depending on which non-blocking assignment is executed last. when synthesizing, the netlist may only keep one of the assignments, leading to unpredictable behavior.

example5.sv
module example5(input q, p, clk);
    assign p = 5;
    assign q = 8;
    always@ (posedge clock) begin
        p = q;
    end
    always@ (posedge clock) begin
        q = p;
    end
endmodule

answer: p = q = 5, or p = q = 8, depending on which always block executes first

example6.sv
1
2
3
4
5
6
7
8
9
logic [3:0] a = 4'd10;
logic [3:0] b = 4'd0;
logic [3:0] c = 4'd0;

always_ff @(posedge clk) begin
    a <= 4'd5;
    b  = a;
    c <= b;
end

what are the values of a, b, and c after the rising edge of clk?


answer: a = 5, b = 10, c = 0

a is scheduled to be updated to 5 at the end of the time step (non-blocking). b is assigned the old value of a (10) immediately (blocking). c is scheduled to be updated to the old value of b (which changed to be 10) at the end of the time step (non-blocking),