1
\$\begingroup\$

I need to learn Vivado and Verilog for an exam in my university, and I think I'm having a problem in learning non blocking assignments. The code is the following:

`timescale 1ns / 1ps
module button_register(
 input wire clk, // Clock signal
 input wire btn, // Button input (debounced)
 output reg value // Register storing the button state
);
 // On every rising edge of the clock, store the button value in the register
 always @(posedge clk) begin
 value <= btn;
 end
endmodule

and I'm simulating its behavior with the following test bench:

`timescale 1ns / 1ps
module tb_button_register;
 reg clk; // Testbench clock signal
 reg btn; // Simulated debounced button
 wire value; // Output register
 // Instantiate the module under test (MUT)
 button_register uut (
 .clk(clk),
 .btn(btn),
 .value(value)
 );
 // Clock generation: 10 ns period (100 MHz frequency)
 initial begin
 clk = 0;
 forever #10 clk = ~clk; // Toggle clock every 5 ns
 end
 // Stimulus: Simulate the button behavior
 initial begin
 // Initialize button to 0
 btn = 0;
 // Wait a few clock cycles, then toggle the button
 #25 btn = 1; // Button goes high after 20 ns
 #10 btn = 0; // Button goes low after 30 ns
 #100 $finish; // End simulation after 100 ns
 end
 // Monitor signals for debugging
 initial begin
 $monitor("Time: %0dns | clk: %b | btn: %b | value: %b ", $time, clk, btn, value);
 end
endmodule

If I understood correctly (and at this point I'm pretty sure I'm wrong), at the rising edge of the clock, the button is sampled. If it is pressed, since I'm using a non blocking assignment, "value" is scheduled to be 1 at the end of the current clock cycle. Which means that the next clock cycle it will be 1. Here the problem comes: when I simulate it, this is what I see:

Simulation result in vivado

"value" is updated immediately to 1 as soon as the button is detected to be pressed, at the rising edge of the clock. Why? I was expecting value to be one the following clock cycle.

toolic
10.8k11 gold badges31 silver badges35 bronze badges
asked Nov 21, 2024 at 9:12
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

"value" is scheduled to be 1 at the end of the current clock cycle

That is incorrect. You misunderstood the meaning of nonblocking assignments. value is scheduled to be 1 at the end of the current simulation time step, not the current clock cycle which takes 10ns of simulation time. This is a subtlety of the Verilog standard (IEEE Std 1800-2023).

The simulation is behaving as expected. Since you are sampling the btn signal when it is stable (with a value of 1) at time=30ns, value is immediately updated with that value (1).

If you change the testbench to also use nonblocking assignments for the btn input signal, and drive the input the same way as you drive value (@(posedge clk)), which is a good coding practice when simulating synchronous logic, then you will see value change at the end of the clock cycle:

initial begin
 // Initialize button to 0
 btn = 0;
 // Wait a few clock cycles, then toggle the button
 #20;
 @(posedge clk) btn <= 1;
 @(posedge clk) btn <= 0;
 /*
 #25 btn = 1; // Button goes high after 20 ns
 #10 btn = 0; // Button goes low after 30 ns
 */
 #100 $finish; // End simulation after 100 ns
end

waves

answered Nov 21, 2024 at 10:39
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.