image file reading in system verilog - system-verilog

I have written system verilog code for reading data from an image file (800*600 -
*.raw).
The file actually contains 800 * 600 * 3 bytes. But my code can only read upto almost
half the data.
After that the read data seems to be "00".
Valuable suggestions for resolving this is appreciated..
My code is as follows.
//`define EOF 32'hFFFF_FFFF
//`define EOF \n
reg [7:0]data_byte;
class input_video_IF;
int count;
integer input_file, fread_return,output_file;
function new ();
input_file = $fopen("test_800.raw","r");
if(input_file)
begin
$display("File OPENED");
end
else
begin
$display("File error");
end
output_file = $fopen("output_800.raw", "w");
endfunction:new
task image_file_read();
count = 0;
//while (!$feof(input_file))
while(count != 1440000)
begin
fread_return = $fread(data_byte,input_file);
count++;
$display("%d %h",count,data_byte);
//$fwrite(output_file,data_byte);
end
$finish;
$fclose(input_file);
endtask : image_file_read
endclass
program Image_read_test;
int input_file;
input_video_IF In_IF = new();
initial
In_IF.image_file_read();
endprogram

Related

Writing value 0 to a binary file

I am generating a binary file from a SystemVerilog simulation environment. Currently, I'm doing the following:
module main;
byte arr[] = {0,32, 65, 66, 67};
initial begin
int fh=$fopen("/home/hagain/tmp/h.bin","w");
for (int idx=0; idx<arr.size; idx++) begin //{
$fwrite(fh, "%0s", arr[idx]);
end //}
$fclose(fh);
$system("xxd /home/hagain/tmp/h.bin | tee /home/hagain/tmp/h.txt");
end
endmodule : main
The problem is, that when b has the value of 0, nothing is written to the file. xxd output is:
0000000: 2041 4243 ABC
Same result when casting to string as follows:
$fwrite(fh, string'(arr[idx]));
I tried to change the write command to:
$fwrite(fh, $sformatf("%0c", arr[idx]));
And then I got the same value for the first two bytes ('d0 and 'd32):
0000000: 2020 4142 43 ABC
Any idea on how to generate this binary file?
You cannot have a null(0) character in the middle of a string, it is used to terminate the string.
You should use the %u format specifier for unformated data.
module main;
byte arr[] = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9};
int fh, c, tmp;
initial begin
fh = $fopen("h.bin","wb");
for (int idx=0; idx<arr.size; idx+=4) begin
tmp = {<<8{arr[idx+:4]}};
$fwrite(fh, "%u", tmp);
end
$fclose(fh);
fh = $fopen("h.bin","r");
while ((c = $fgetc(fh)) != -1)
$write("%d ",c[7:0]);
$display;
end
endmodule : main
Note that %u writes a 32-bit value in least-significant bytes first order, so I reversed the bytes being written with the streaming operator {<<8{arr[idx+:4]}}. If the number of bytes is not divisible by 4, it will just pad the file with null bytes.
If you need the exact number of bytes, the you will have to use some DPI C code
#include <stdio.h>
#include "svdpi.h"
void DPI_fwrite(const char* filename,
const svOpenArrayHandle buffer){
int size = svSize(buffer,1);
char *buf = (char *)svGetArrayPtr(buffer);
FILE *fp = fopen(filename,"wb");
fwrite(buf,1,size,fp);
}
And then import it with
import "DPI-C" function void DPI_fwrite(input string filename, byte buffer[]);
...
DPI_fwrite("filename", arr);

How to store return value from $system("...") call in SystemVerilog?

If I simulate the following module:
module test;
longint seconds;
initial begin
seconds = $system("date +%s");
$display("Seconds: %0d", seconds);
$finish;
end
endmodule
The output from both ncsim and vsim is:
1571172006
Seconds: 0
So I can see that the $system call is printing the time in seconds 1571172006, however the variable seconds has a value of 0 so I'm not saving that value.
Is there a way for me to save that value? (Preferably not using DPI)
Thanks in advance.
edaplayground link
I don't know why you wouldn't want to use the DPI. Much simpler than Matthew's approach. 😊
module test;
import "DPI-C" function longint date();
longint seconds;
initial begin
seconds = date();
$display("Seconds: %0d", seconds);
$finish;
end
endmodule
#include <time.h>
long int date() {
return time(NULL);
}
https://www.edaplayground.com/x/5NTw
It's horrible, but you can pipe the output of your linux command into a file and then read the file:
$system("date +%s | tee date.txt");
fd = $fopen("date.txt","r");
count=($fgets(s, fd) == 0); assert(count == 0);
count=($sscanf(s,"%d", seconds)); assert(count == 1);
$display("Seconds: %0d", seconds);
module test;
longint seconds;
initial begin
int fd;
int count;
string s;
$system("date +%s | tee date.txt");
fd = $fopen("date.txt","r");
count=($fgets(s, fd) == 0); assert(count == 0);
count=($sscanf(s,"%d", seconds)); assert(count == 1);
$display("Seconds: %0d", seconds);
$finish;
end
endmodule
https://www.edaplayground.com/x/4R5e

How to use get function in mailbox systemverilog

I am a beginner in systemverilog and I tried to make a complex code used to compare between two mailboxes
and it gives me these errors in simulation
enter image description here
//the package code
package types;
typedef struct{
int pid;
}packet;
endpackage
//the main code
module mbox;
import types::*;
//Declare two mailboxes here
mailbox exp_mb = new(256);
mailbox act_mb = new(256);
// This task supplies stimulus to the two mailboxes
task stimulus();
packet stim_pkt;
for (int i = 0; i < 256; i++) begin
stim_pkt.pid = i;
//*** Write stim_pkt to both mailboxes here
exp_mb.put(stim_pkt);
act_mb.put(stim_pkt);
$display("Sending pkt: ",i);
end
endtask
// Add task checker here
task check(input mailbox exp_mb ,act_mb);
bit com;
packet x;
packet y;
for (int i = 0; i < 256; i++) begin
x.pid = exp_mb.get(i) ;
y.pid = act_mb.get(i);
com = compare(x,y);
if (com == 1)
$display ("No Error");
else
$display ("Error in %d", i);
end
endtask
// Add function compare here
function bit unsigned compare (packet a ,b);
if (a.pid == b.pid)
return 1;
else
return 0;
endfunction// Add an initial block to run stimulus & checker tasks simultaneously
initial
begin
fork
stimulus();
check(exp_mb ,act_mb);
join_none
end
endmodule
The error message tells you exactly what the problem is. The mailbox get() method does not return a value, it places a value in its argument.
I believe you want
exp_mb.get(x) ;
act_mb.get(y);
Also, A good idea is add types to your mailboxes. Will become very helpful in getting compile errors instead of runtime errors as your code grows and the number of different packet types grow.
mailbox #(packet) exp_mb = new(256);
mailbox #(packet) act_mb = new(256);
...
task check(mailbox #(packet) exp_mb ,act_mb);

Invalid index in cross-module reference

below is the code snippet of my top_file
`define NUM_SENSORS 2;
module test_top();
svt_configuration multiple_top_cfg[`NUM_SENSORS]; // configuration class instance
svt_xmtr_if xmtr_if[`NUM_OF_SENSORS](); // interface instance
svt_rcvr_if rcvr_if[`NUM_OF_SENSORS]();
always begin
fork
change_clock_speed();
join_none
end
task automatic change_clock_speed();
for(i=0; i<`NUM_OF_SENSORS; i++) begin
wait(multiple_top_cfg[i] != null);
#(multiple_new_dphy_ui[i]) begin
if(multiple_top_cfg[i].xmtr_cfg.lane_cfg.clock_type == svt_mipi_lane_configuration::NON_CONTINUOUS) begin
wait({xmtr_if[i].serial_if.serial_tx_clk_if.dp,xmtr_if[i].serial_if.serial_tx_clk_if.dn} === 2'b11);
end
else begin
if(multiple_top_cfg[i].xmtr_cfg.lane_cfg.clock_type == svt_mipi_lane_configuration::CONTINUOUS) begin
wait({xmtr_if[i].serial_if.serial_if[0].dp,xmtr_if[i].serial_if.serial_if[0].dn} === 2'b11);
end
end
multiple_change_dphy_ui[i] = 1; // this is a local reg
multiple_tx_clock_period[i] = multiple_new_dphy_ui[i]; // this is a local reg
multiple_quadrature[i] = multiple_new_dphy_ui[i]; // this is a local reg
end
end
endtask
// ... other lines
endmodule
When i am running my test, i am getting this error :
Error-[IIXMR] Invalid index in cross-module reference
top.serial.sv, 311
Invalid index in cross-module reference due to index is not constant.
Argument: xmtr_if[i].serial_if.serial_tx_clk_if.dp
Source info: : wait (({xmtr_if[i].serial_if.serial_tx_clk_if.dp,
xmtr_if[i].serial_if.serial_tx_clk_if.dn} === 2'b11))
I understand why this error is coming, but i don't have any solution to it... can any one help...
I tried to put the always block inside generate block. But another error is coming.
Any solution to this error please...
Thanks,
Biren
I have found a solution it. What i did is :
genvar i;
generate
for(i=0; i<`NUM_SENSORS; i++) begin
always begin
change_clock_speed();
end
end
endgenerate
Now it's working. :)

how to write function about return data

all,i need help.i encounter question about array data transaction.Please help me!
code is following.
packet is data class,and there is three queue,R,G,B,and in module "test",arith function 's return_data is no data. why?
question:though "into-arith" function,output tr_out is no data.
class packet # (int bit_depth =16);//packet class
bit [bit_depth-1:0] R[$];
bit [bit_depth-1:0] G[$];
bit [bit_depth-1:0] B[$];
endclass
//packet is data class
module test #(active_num=1920); //
packet in_tr [4];
initial begin
foreach(in_tr[i]) begin
in_tr[i] = new();
end
foreach(in_tr[j]) begin
for(int i=0;i<1920;i++) begin
in_tr[j].R.push_back(i);
end
end
process_in_tr;
end
task process_in_tr();
packet tr_out[4];
foreach(tr_out[i])begin
tr_out[i] = new();
end
tr_out[4] = into_arith(in_tr);
foreach(tr_out[j]) begin
foreach(tr_out[j].R[i]) begin
$display("%h",tr_out[j].R[i]);
end
end
endtask
function packet[4] into_arith(ref packet in_tr[4]);
packet tr_tmp[4];
foreach(tr_tmp[i]) begin
tr_tmp[i] = new();
end
for(int m=0;m<4;m++) begin
foreach(in_tr[m].R[i]) begin
tr_tmp[m].R.push_back(in_tr[m].R[i]);
tr_tmp[m].G.push_back(in_tr[m].G[i]);
tr_tmp[m].B.push_back(in_tr[m].B[i]);
end
end
return tr_tmp[4];
endfunction
endmodule
I couldn't event get this to compile in Questa, there are many syntax errors.
The three main problems are
The declaration of the function is an error. You must use a typedef when returning an aggregate type (in your case an unpacked array of packet#())
the assignment tr_out[4] = into_arith(in_tr); is illegal. You are trying to assign a unpacked array of 4 elements to the 5th element of an array, which doesn't even exist.
The return tr_tmp[4]; is also illegal. You are trying to return the non-existent 5th element of an array as the return value for a function that requires a 4-element array.
See all my corrections below:
class packet # (int bit_depth =16);//packet class
bit [bit_depth-1:0] R[$];
bit [bit_depth-1:0] G[$];
bit [bit_depth-1:0] B[$];
endclass
//packet is data class
module test #(active_num=1920); //
typedef packet#() packet4_t[4];
packet4_t in_tr;
initial begin
foreach(in_tr[j]) begin
in_tr[j] = new();
for(int i=0;i<1920;i++)
in_tr[j].R.push_back(i);
end
process_in_tr;
end
task process_in_tr();
packet4_t tr_out;
tr_out = into_arith(in_tr);
foreach(tr_out[j]) begin
foreach(tr_out[j].R[i]) begin
$display("%h",tr_out[j].R[i]);
end
end
endtask
function automatic packet4_t into_arith(ref packet4_t in_tr);
packet4_t tr_tmp;
foreach(tr_tmp[i]) begin
tr_tmp[i] = new();
tr_tmp[m].R = in_tr[m].R;
tr_tmp[m].G = in_tr[m].G;
tr_tmp[m].B = in_tr[m].B;
/* assigments above are the same as the foreach loop below
foreach(in_tr[m].R[i]) begin
tr_tmp[m].R.push_back(in_tr[m].R[i]);
tr_tmp[m].G.push_back(in_tr[m].G[i]);
tr_tmp[m].B.push_back(in_tr[m].B[i]);
end */
end
return tr_tmp;
endfunction
endmodule