Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

Test bench principle

When I write test bench for design simulation, I confronted some weird problems in GTL simulation. The results are similar, but I want to post here to discuss. For example, I have RAM, in testbench I input address to write or read like;

// example 1

always @(posedge clock) // posedge is active edge of the clock

begin

wren<=1;

address<=address+1;

data<=data+1;

end

// example 2

always @(posedge clock) // posedge is active edge of the clock

begin

rden<=1;

address<=address+1;

end

Sometimes, the Modelsim will give warning in each clock posedge to warn the setup and hold timing violation. And GTL simulation results are weird like the output data does not follow the sequence of address.

The Altera staff mentioned "Changing the data in a test bench at the exact same time as the active edge of the clock can produce unreliable and inconsistent results" , and he suggests don't use active edge of clock to change data or add delay like:

always @(negedge clock) // posedge is active edge of the clock

begin

wren<=1;

address<=address+1;

data<=data+1;

end

or

always @(posedge clock) // posedge is active edge of the clock

begin

wren<=1;

# 5 address<=address+1;

# 5 data<=data+1;

end

So I just have questions, when I writed testbench, I always change data using style:

always @(posedge)

begin

data<=f(data); // f(data) means a function of data

end

should I put timing delay in all these commands? And in testbench, blocking assignment and non-blocking assignment, which I should use? I think both of them work the difference are concurrent and one cycle delay.

Hope anyone can give me some advices. Thanks very much.

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You should use

    always @(posedge clock) // posedge is active edge of the clock

    begin

    wren <=# (delay) 1;

    address <=# (delay) address+1;

    data<=# (delay) f(data);

    end

    where delay is what is needed to prevent timing violations. You want to put the delay to the right of the <= the delay is non-blocking; it only effects the delay of the assignment and not when the next statement executes.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    You should use

    always @(posedge clock) // posedge is active edge of the clock

    begin

    wren <=# (delay) 1;

    address <=# (delay) address+1;

    data<=# (delay) f(data);

    end

    where delay is what is needed to prevent timing violations. You want to put the delay to the right of the <= the delay is non-blocking; it only effects the delay of the assignment and not when the next statement executes.

    --- Quote End ---

    Thanks very much for your help. So the# (delay) should be used for all assignments to prevent assignment happen exactly in active edge of clock, right?

    Could you explain a little more why put# (delay) in left not in right? Thanks very much.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    #delay statement;

    The blocks any statement, which includes an assignment statement. The process is blocked until the time the delay specifies.

    That statement can be a non-blocking assignment, which can have a delay that postpone the update to the RHS, but does not block the process. The next statement is executed immediately.

    # delay1 LHS <=# delay2 RHS;

    delay1 blocks the entire statement, delay2 only blocks the update to the RHS.

    See

    http://www.sutherland-hdl.com/papers/1996-cug-presentation_nonblocking_assigns.pdf