- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I have a problem with using wait segments in my task. I am trying to test a deserializer, that has to work with a specific format. I want to give the full byte to send to the task, then it transforms it to the format the deserializer, and in the end I check whether the input corresponds to the output. My code for the task is:task send_8bit;
input reg Y8bit;
input reg C8bit;
output reg rx_in;
integer counter;
reg PIXEL_IN_Y1;
reg PIXEL_IN_Y2;
reg PIXEL_IN_C1;
reg PIXEL_IN_C2;
begin
// Data protocol:
// Y1: Y6 Y5 Y4 Y3 Y2 Y1 Y0
// Y2: 0 0 0 X X X Y7
// C1: C6 C5 C4 C3 C2 C1 C0
// C2: 0 0 0 0 0 C6 C7
PIXEL_IN_Y1=Y8bit;
PIXEL_IN_Y2=Y8bit;
PIXEL_IN_C1=C8bit;
PIXEL_IN_C2=C8bit;
PIXEL_IN_C2=C8bit;
PIXEL_IN_Y2=6'b000XXX;
PIXEL_IN_C2=5'b00000;
Y8bit_debug=Y8bit;
C8bit_debug=C8bit;
for(counter = 6; counter >=0; counter = counter - 1)
begin
# 1924 //length of 1 data period in ps
rx_in= PIXEL_IN_Y1;
rx_in= PIXEL_IN_Y2;
rx_in= PIXEL_IN_C1;
rx_in= PIXEL_IN_C2;
end
end
endtask
However, the code does not work, it seems it only assigns the values once. I simply want to have the option to write send_8bit(MYBYTE1,MYBYTE2,OUTPUT);
, have rx_in appear on OUTPUT at the right times and be done with it.
Link Copied
3 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In Verilog, input arguments get copied upon entry, and output arguments get copied upon exit of a task or function. If you use Systemverilog, you can change the last argument to a ref, which means rx_in will be a reference to the actual argument instead of a value that gets copied to it.
task automatic send_8bit(
input reg Y8bit,
input reg C8bit,
ref reg rx_in
);
Most tools now support SystemVerilog just by changing the file extension from *.v to *.SystemVerilog . Note that the task needs to have an automatic lifetime to use the ref argument. If you are not able to do this, your only other option is for the task to directly modify OUPUT instead of passing it in as an argument to the task.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you, it works now.
For anyone stumbling upon this question, note that the task must be automatic; so the working code is:task automatic send_8bit;
input reg Y8bit;
input reg C8bit;
ref reg rx_in;
integer counter;
reg PIXEL_IN_Y1;
reg PIXEL_IN_Y2;
reg PIXEL_IN_C1;
reg PIXEL_IN_C2;
begin
// Data protocol for the Tamron camera:
// Y1: Y6 Y5 Y4 Y3 Y2 Y1 Y0
// Y2: 0 0 0 X X X Y7
// C1: C6 C5 C4 C3 C2 C1 C0
// C2: 0 0 0 0 0 C6 C7
PIXEL_IN_Y1=Y8bit;
PIXEL_IN_Y2=Y8bit;
PIXEL_IN_C1=C8bit;
PIXEL_IN_C2=C8bit;
PIXEL_IN_C2=C8bit;
PIXEL_IN_Y2=6'b000XXX;
PIXEL_IN_C2=5'b00000;
Y8bit_debug=Y8bit;
C8bit_debug=C8bit;
for(counter = 6; counter >=0; counter = counter - 1)
begin
# 1924 //length of 1 data period in ps
rx_in= PIXEL_IN_Y1;
rx_in= PIXEL_IN_Y2;
rx_in= PIXEL_IN_C1;
rx_in= PIXEL_IN_C2;
end
end
endtask
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The use of 'automatic' means the verilog compiler/simulator must make the task re-entrant, so it must copy all input/outputs to temp variables during execution. So this probably means you are calling the task multiple times in parallel, while older invocations are still executing, because of your builtin time delays.
As an example, in old style verilog, I have the task just reference the module signals in its called context, and not pass everything as arguments. I also don't call the task again until I know the existing call has finished (which in my case calling it multiple times in parallel does not make any sense). Example:
reg sd_dat_adr = 0;
reg sd_dat_wen = 0;
reg sd_dat_din = 0;
wire sd_dat_dout;
task rd_buf;
input fradr;
input toadr;
integer i;
begin
@(posedge clk)# TPD ;
$write("\n");
for (i = fradr; i <= toadr; i = i+1)
begin
sd_dat_adr = i;
sd_dat_wen = 0;
sd_dat_din = 0;
@(posedge clk)# TPD ;
@(posedge clk)# TPD ;
@(posedge clk)# TPD ;
if (sd_dat_adr % 16 == 0) $write("%h:", sd_dat_adr);
$write(" %h", sd_dat_dout);
if (sd_dat_adr % 16 == 15) $write("\n");
end
@(posedge clk)# TPD ;
$write("\n");
end
endtask // rd_buf
And then in my testbench I just call the task when needed: initial
begin
init_card(10);
rd_buf(0,511);
delay(250);
$finish;
end
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page