task problems

P

Paul

Guest
Hi,

what's wrong with these task?:

task hit;
input s;
begin
@(posedge clock); s <= 1'b1;
@(posedge clock); s <= 1'b0;
end
endtask

.....

reg trigger;
....
hit(trigger);

nothings happens on signal trigger, why? Who to fix?

Thanks!
 
Paul wrote:
Hi,

what's wrong with these task?:

task hit;
input s;
begin
@(posedge clock); s <= 1'b1;
@(posedge clock); s <= 1'b0;
end
endtask

....

reg trigger;
...
hit(trigger);

nothings happens on signal trigger, why? Who to fix?

Thanks!
I see two problems.

1) s should be an output or inout.
2) A task will only make assignments to its outputs or inouts
when the task completes. This means that although internally
the signal s will toggle high and then low, the output port,
in your case trigger, will only be assigned when the task
completes. Since the last assignment is non-blocking I would
expect trigger to go high when hit is called and stay high
because the last assignment to 1'b0 is scheduled to occur
after the task completion. This may be simulator dependent.

If you don't need to apply this task to too many different
variables, then I would suggest making a task for each
variable that directly makes the assignments to that
variable rather than making it a port of the task.

If you need to do this for a lot of variables, then you
could make two tasks that are always called in succession
like go_hi and go_lo, the first waiting for one clock edge
and then assigning the ouput high, the second waiting for
one clock edge and assigning the output low.

-- Gabor
 
On Thu, 12 Apr 2012 15:28:08 +0200, Paul <Paul@noreply.com> wrote:

Hi,

what's wrong with these task?:

task hit;
input s;
begin
@(posedge clock); s <= 1'b1;
@(posedge clock); s <= 1'b0;
end
endtask

Fully agree with Gabor's comments, but there are some
other options too.

1)
If your simulator supports SystemVerilog, consider
passing "s" as a ref argument. This will have the
effect you (probably) expect, but note that you
must supply a variable (reg) as the argument when
you call such a task; wires cannot be passed as
ref arguments.

2)
Consider writing a module to provide the stimulus.

module pulsegen(input clk, output reg signal);
task hit;
begin
@(posedge clk) signal <= 1;
@(posedge clk) signal <= 0;
end
endtask
endmodule

Now you can connect an instance of that module to any
net that you need to drive, and call the "hit" task
in that module instance to generate the pulse:

module top;
wire A, B;
reg clk;
// provide some clock generator here...
pulsegen pg_A(clk, A);
pulsegen pg_B(clk, B);
initial begin
#100 pg_A.hit();
#200 pg_B.hit();
end
endmodule

In this way the effort of creating the generator can be
re-used across various signals.
--
Jonathan Bromley
 
thanks Gabor and Jonathan!

what's wrong with these task?:

task hit;
input s;
begin
@(posedge clock); s <= 1'b1;
@(posedge clock); s <= 1'b0;
end
endtask

....

reg trigger;
...
hit(trigger);

1) s should be an output or inout.
yes, after reading it it's so clear ...

2) A task will only make assignments to its outputs or inouts
when the task completes. This means that although internally
the signal s will toggle high and then low, the output port,
in your case trigger, will only be assigned when the task
completes. Since the last assignment is non-blocking I would
expect trigger to go high when hit is called and stay high
because the last assignment to 1'b0 is scheduled to occur
after the task completion. This may be simulator dependent.
Modelsim shows the behavior as you described - but I don't understand
your last statement. The last assignment is: s <= 1'b0; isn't it? The
assignment will be assigned when the task completes - I would expect
1'b0 since the task completes with this last statement. Obviously I do
have a wrong understanding of Verilog's task and simulator behavior and
implementation.

If you don't need to apply this task to too many different
variables, then I would suggest making a task for each
variable that directly makes the assignments to that
variable rather than making it a port of the task.

If you need to do this for a lot of variables, then you
could make two tasks that are always called in succession
like go_hi and go_lo, the first waiting for one clock edge
and then assigning the ouput high, the second waiting for
one clock edge and assigning the output low.
these is the intention - the use for a testbench. Unfortunately, while
your first suggestion works the second doesn't - no changes. Hopefully
correctly shortened:

module DpTimer16_TB;

reg clock;
reg enable;

parameter ClockPeriod = 10;
always #(ClockPeriod/2) clock = ~clock;

// initialize
initial begin
clock = 0;
enable = 0;
end

// TB tasks
task hit_enable;
begin
@(posedge clock); enable <= 1'b1;
@(posedge clock); enable <= 1'b0;
end
endtask

task hit_high;
inout s;
begin
@(posedge clock) s <= 1'b1;
end
endtask // hit_high

task hit_low;
inout s;
begin
@(posedge clock) s <= 1'b0;
end
endtask // hit_high

task hit;
inout s;
begin
hit_high(s);
hit_low(s);
end
endtask // hit

// TB control
initial
begin: TEST_CASE

repeat(4)@(posedge clock);
hit(enable);

end

endmodule

The approach from Jonathan works, but how can I initialize the signal
correctly?

Thanks
 
Paul wrote:
thanks Gabor and Jonathan!

what's wrong with these task?:

task hit;
input s;
begin
@(posedge clock); s <= 1'b1;
@(posedge clock); s <= 1'b0;
end
endtask

....

reg trigger;
...
hit(trigger);

1) s should be an output or inout.

yes, after reading it it's so clear ...

2) A task will only make assignments to its outputs or inouts
when the task completes. This means that although internally
the signal s will toggle high and then low, the output port,
in your case trigger, will only be assigned when the task
completes. Since the last assignment is non-blocking I would
expect trigger to go high when hit is called and stay high
because the last assignment to 1'b0 is scheduled to occur
after the task completion. This may be simulator dependent.

Modelsim shows the behavior as you described - but I don't understand
your last statement. The last assignment is: s <= 1'b0; isn't it? The
assignment will be assigned when the task completes - I would expect
1'b0 since the task completes with this last statement. Obviously I do
have a wrong understanding of Verilog's task and simulator behavior and
implementation.
A non-blocking assignment is _scheduled_ to occur when an
block completes or waits on another event. In the case
of a task, even thought there is no delay in your assignment,
it has _not_ _ocurred_ when you reach the end of the block
and therefore the output of the task is not assigned the
new value on exit. If you push into the task in the
hirarchy view in ModelSim, and look at variable s,
you should see it change state at the end of hit_high
even though the variable at the top level does not.

If you don't need to apply this task to too many different
variables, then I would suggest making a task for each
variable that directly makes the assignments to that
variable rather than making it a port of the task.

If you need to do this for a lot of variables, then you
could make two tasks that are always called in succession
like go_hi and go_lo, the first waiting for one clock edge
and then assigning the ouput high, the second waiting for
one clock edge and assigning the output low.

these is the intention - the use for a testbench. Unfortunately, while
your first suggestion works the second doesn't - no changes. Hopefully
correctly shortened:

module DpTimer16_TB;

reg clock;
reg enable;

parameter ClockPeriod = 10;
always #(ClockPeriod/2) clock = ~clock;

// initialize
initial begin
clock = 0;
enable = 0;
end

// TB tasks
task hit_enable;
begin
@(posedge clock); enable <= 1'b1;
@(posedge clock); enable <= 1'b0;
end
endtask

task hit_high;
inout s;
begin
@(posedge clock) s <= 1'b1;
end
endtask // hit_high
Try changing the <= (non-blocking assignment) to = (blocking assignment)
for hit_high and hit_low.

task hit_low;
inout s;
begin
@(posedge clock) s <= 1'b0;
end
endtask // hit_high

task hit;
inout s;
begin
hit_high(s);
hit_low(s);
end
endtask // hit

// TB control
initial
begin: TEST_CASE

repeat(4)@(posedge clock);
hit(enable);

end

endmodule

The approach from Jonathan works, but how can I initialize the signal
correctly?

Thanks
 

Welcome to EDABoard.com

Sponsor

Back
Top