If I want to create a pipelined flip-flop (FF) structure, where data from the input is at the output after 2 clock cycles. This is a top-down blocking assignment code.
module circuit (
input wire clk,
input wire rstn,
input wire [7:0] din,
output reg [7:0] dout
);
reg [7:0] mid;
always @ (posedge clk) begin
if (!rstn) begin
mid = 0;
dout = 0;
end else begin
mid = din;
dout = mid;
end
end
endmodule
Schematic for this code:
If I use blocking assignment in reversed order:
module circuit (
input wire clk,
input wire rstn,
input wire [7:0] din,
output reg [7:0] dout
);
reg [7:0] mid;
always @(posedge clk) begin
if (!rstn) begin
mid = 0;
dout = 0;
end else begin
/*
mid <= din;
dout <= mid;
*/
dout = mid;
mid = din;
end
end
endmodule
Then I get a schematic like this, which is identical to what would I get if I were to use non-blocking assignments.
If I keep the ordering in mind, can I use the blocking assignments to get the behavior from the circuit for which I usually use the NBA? For example, avoiding race conditions, sampling asynchronous input, etc.?
1 Answer 1
The best approach is to follow the advice in the paper:
Guideline: Use nonblocking assignments in always blocks that are written to generate sequential logic
Then you never need to worry about race conditions or other unexpected simulation/synthesis issues. For sequential logic, use this, for example:
always @(posedge clk) begin
if (!rstn) begin
mid <= 0;
dout <= 0;
end else begin
mid <= din;
dout <= mid;
end
end