Writing a binary file in Verilog

5067 views
Skip to first unread message

Charles Bailey

unread,
Oct 5, 2004, 12:49:23 AM10/5/04
to
I have a testbench in which I would like to monitor the sequence of
bytes on a data bus and write the bytes to a file in binary.

I open the output file with
integer wrdata, b1;

wrdata = $fopen("testdata.out", "wb");

and, on every clock cycle,
b1 = out_data[7:0];
$fwrite(wrdata,"%c", b1);

The problem is that, if out_data[7:0] == 8'h00, then
"$fwrite(wrdata,"%c", b1);" writes nothing. It seems that $fwrite sees
the all zeros byte as a string terminator (a la C null character) and
writes a zero-length string, that is, nothing.

I've also tried "$fwrite(wrdata,"%u", b1);", but that insists on writing
4 bytes to the file, regardless of how b1 is declared.

What I want to do is just write a straight binary file, without any
interpretation of the bytes and of any arbitrary length. I looked to
see if Verilog has something like $fputc, but apparently it doesn't. Is
there any way to do what I'm describing in Verilog?

Thanks,
Charles Bailey


annoyed

unread,
Oct 5, 2004, 2:24:36 AM10/5/04
to

A while ago,
I tried to use the "$fwrite( ... "%c" ... )" mechanism to output a
binary file. I found that my success (not good) depended on
the host simulator. Modelsim invariably failed even without
0x00 (NULL) in the output stream. NC-Verilog worked "better", but
I didn't check it exhaustively ...

(I don't have access to Synopsys VCS.)

Petter Gustad

unread,
Oct 5, 2004, 4:59:33 AM10/5/04
to
"Charles Bailey" <ceb_...@ultrasw.com> writes:

> I have a testbench in which I would like to monitor the sequence of
> bytes on a data bus and write the bytes to a file in binary.
>
> I open the output file with
> integer wrdata, b1;
>
> wrdata = $fopen("testdata.out", "wb");
>
> and, on every clock cycle,
> b1 = out_data[7:0];
> $fwrite(wrdata,"%c", b1);
>
> The problem is that, if out_data[7:0] == 8'h00, then
> "$fwrite(wrdata,"%c", b1);" writes nothing. It seems that $fwrite sees

You are telling it to use formatted output of characters. If you want
pure binary data I think you might want do to something like:

integer fd;

initial begin
fd = $fopen("data.out","wb");
$fwrite(fd,"%u",32'h61_62_00_63);
$fclose(fd);
end

If you want to preserve X and Z you will ahve to use %z format.

Petter

--
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Stephen Williams

unread,
Oct 5, 2004, 11:39:40 AM10/5/04
to
Charles Bailey wrote:
> I have a testbench in which I would like to monitor the sequence of
> bytes on a data bus and write the bytes to a file in binary.
>
> I open the output file with
> integer wrdata, b1;
>
> wrdata = $fopen("testdata.out", "wb");
>
> and, on every clock cycle,
> b1 = out_data[7:0];
> $fwrite(wrdata,"%c", b1);

I use $fputc in Icarus Verilog, i.e:

always @(posedge VID_CLK)
if (VID_FVV & VID_LVV * VID_DVAL) begin
$fputc(video_output_fd, VID_DATA[7:0]);
$fputc(video_output_fd, VID_DATA[15:8]);
$fputc(video_output_fd, VID_DATA[23:16]);
end

I do binary compares on the output files and get the expected
results, to I believe it works:-)

--
Steve Williams "The woods are lovely, dark and deep.
steve at icarus.com But I have promises to keep,
http://www.icarus.com and lines to code before I sleep,
http://www.picturel.com And lines to code before I sleep."

Petter Gustad

unread,
Oct 5, 2004, 12:58:48 PM10/5/04
to
Stephen Williams <spam...@icarus.com> writes:

> Charles Bailey wrote:
> > I have a testbench in which I would like to monitor the sequence of
> > bytes on a data bus and write the bytes to a file in binary.
> >
> > I open the output file with
> > integer wrdata, b1;
> >
> > wrdata = $fopen("testdata.out", "wb");
> >
> > and, on every clock cycle,
> > b1 = out_data[7:0];
> > $fwrite(wrdata,"%c", b1);
>
> I use $fputc in Icarus Verilog, i.e:
>
> always @(posedge VID_CLK)
> if (VID_FVV & VID_LVV * VID_DVAL) begin
> $fputc(video_output_fd, VID_DATA[7:0]);
> $fputc(video_output_fd, VID_DATA[15:8]);
> $fputc(video_output_fd, VID_DATA[23:16]);
> end

I don't have my IEEE spec at hand, but I can't remember $fputc as
being a part of the standard. Have I missed it, or have you
implemented something which is a natural extension of the standard?

Steven Sharp

unread,
Oct 5, 2004, 4:01:23 PM10/5/04
to
"Charles Bailey" <ceb_...@ultrasw.com> wrote in message news:<10m4a15...@corp.supernews.com>...

>
> The problem is that, if out_data[7:0] == 8'h00, then
> "$fwrite(wrdata,"%c", b1);" writes nothing. It seems that $fwrite sees
> the all zeros byte as a string terminator (a la C null character) and
> writes a zero-length string, that is, nothing.

The $fwrite implementation was probably written in C, and probably
formats the output into a C string and then writes out that string.
A NUL character in that string would be treated as a string terminator,
as you have described.

NC-Verilog used to have this behavior, but has since been fixed so that
you can output a NUL character with %c, to allow what you are trying to do.
I can't comment on other simulators, but would expect that they generally
don't do what you want. That takes special attention to this issue when
implementing %c.

> I've also tried "$fwrite(wrdata,"%u", b1);", but that insists on writing
> 4 bytes to the file, regardless of how b1 is declared.

Yes, the LRM specifies that it shall be written in units of 32 bits.

> What I want to do is just write a straight binary file, without any
> interpretation of the bytes and of any arbitrary length. I looked to
> see if Verilog has something like $fputc, but apparently it doesn't. Is
> there any way to do what I'm describing in Verilog?

Probably not in most simulators. The LRM doesn't address this issue, so
you could consider it an issue with Verilog, or just a widespread bug in
simulator implementations.

Charles Bailey

unread,
Oct 5, 2004, 4:07:54 PM10/5/04
to
Petter Gustad <newsma...@gustad.com> wrote in message news:<m3d5zxi...@scimul.dolphinics.no>...
> $fwrite(fd,"%u",32'h61_62_00_63);
%u seems to work if I want to write 4 bytes. What if the binary file
I want to write is not a multiple of 4 bytes? How can I write a
single byte, any byte 00-FF?

Charles Bailey

Stephen Williams

unread,
Oct 5, 2004, 5:57:36 PM10/5/04
to
Petter Gustad wrote:

> Stephen Williams <spam...@icarus.com> writes:
>>I use $fputc in Icarus Verilog, i.e:
>>
>> always @(posedge VID_CLK)
>> if (VID_FVV & VID_LVV * VID_DVAL) begin
>> $fputc(video_output_fd, VID_DATA[7:0]);
>> $fputc(video_output_fd, VID_DATA[15:8]);
>> $fputc(video_output_fd, VID_DATA[23:16]);
>> end
>
>
> I don't have my IEEE spec at hand, but I can't remember $fputc as
> being a part of the standard. Have I missed it, or have you
> implemented something which is a natural extension of the standard?

Well, I *thought* $fputc was standard, but I looked it up, and
sure enough there is nothing like it in the actual standard.
So I guess this is an extension so natural that I forgot it
was and extension.

Petter Gustad

unread,
Oct 6, 2004, 4:11:32 AM10/6/04
to
ceb...@ultrasw.com (Charles Bailey) writes:

I don't think you can. You'll have to either use an ASCII file, use
Icarus, or make a $fputc yourself. Can't you use a four byte buffer?

Charles Bailey

unread,
Oct 7, 2004, 8:57:17 AM10/7/04
to
I tried using Icarus, but my Verilog code contains a number of
statements like this:
cw[ 0:22] = lz1data[bitpos+:23];
outdata[outpos+:8] = outbyte;
which Icarus can't handle.
(It gives error messages like
eldc_enc.v:310: syntax error
eldc_enc.v:310: error: malformed statement
)

Charles Bailey

"Stephen Williams" <spam...@icarus.com> wrote in message
news:6111d$4162c03c$40695902$23...@msgid.meganewsservers.com...

Reply all
Reply to author
Forward
0 new messages