I'm creating a VHDL project, and using ISim to simulate beforehand - which is all fine.
However, my results use fixed point - and although Isim can represent its signals as a range of radix's, unsurprisingly, fixed point decimal isn't one of them.
Hence I'd like to get the current value of each signal as text but the "copy" function only copies the entity and signal name, and not the string value.
For example
I want to get the value of "[00010000, 00020000...etc etc] but I actually just get the value of "/fixedpointtb/UUT/s1_fcs[0]" i.e. entity name.
Common sense says there must be a simple way of doing this but I can't see how!
You can use VHDL's file I/O capabilities in your testbench (at top-level) to convert the signals from DUT into a human readable string and write it to STDOUT or into a file.
A coarse overview on file I/O.
VHDL has several packages and procedures/functions for file I/O and string operations.
std.textio
VHDL defines an access type (a pointer) called line
for string
and a basic file type text
for text files.
Usage:
use std.textio.all;
Declarations from std.textio
:
-- types
type line is access string;
type text is file of string;
-- STD files
file input : text open read_mode is "STD_INPUT";
file output : text open write_mode is "STD_OUTPUT";
-- procedures (some with overloads)
read (<lineVar>, <vhdlObji [,<status>]);
readline (<fileObj>, <lineVari);
write (<lineVar>, <vhdlObj> [,right|left, <width>]);
write (<lineVar>, <realObj> [,right|left, <width>, <digits>]);
write (<lineVar>, <timeObj> [,right|left, <width>, <unit>]);
writeline (<fileObj>, <lineVar>);
-- functions
endfile (<fileObj>) : boolean
ieee.std_logic_textio
This package declares more procedures to format std_logic
values.
Usage:
library ieee;
use std.textio.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_textio.all;
Declarations from ieee.std_logic_textio
:
read (<lineVar>, <vhdlObj> [,<status>]); -- binary
hread (<lineVar>, <vhdlObj> [,<status>]); -- hexadecimal
oread (<lineVar>, <vhdlObj> [,<status>]); -- octal
write (<lineVar>, <vhdlObj> [,right|left, <width>]); -- binary
hwrite (<lineVar>, <vhdlObj> [,right|left, <width>]); -- hexadecimal
owrite (<lineVar>, <vhdlObj> [,right|left, <width>]); -- octal
Source: VHDL Kompakt (German VHDL book from Universität Hamburg)
Usage example
The following example writes the value of mySignal
to a logfile and reports the time.
signal mySignal : STD_LOGIC_VECTOR(7 downto 0);
-- ....
process
file LogFile : TEXT open WRITE_MODE is "logfile.log";
variable LineBuffer : LINE;
begin
write(LineBuffer, ( STRING'("========================================")));
write(LineBuffer, (CR & STRING'("TESTBENCH REPORT")));
write(LineBuffer, (CR & STRING'("========================================")));
writeline(LogFile, LineBuffer);
wait until mySignal /= x"00";
wait until rising_edge(Clock);
for i in 0 to 7 loop
wait until rising_edge(Clock);
write(LineBuffer, "Time " & to_string(now, 1) & " Value 0x" & raw_format_slv_hex(mySignal));
writeline(LogFile, LineBuffer);
end loop;
end process;
now
is a built-in function, representing the current simulation time. It is formatted by to_string
, which expects a time and a precision. The signal mySignal
is formatted by raw_format_slv_hex
. This function formats a STD_LOGIC_VECTOR
of arbitrary size to a hexadecimal string.
The file should have such content:
========================================
TESTBENCH REPORT
========================================
Time 50 ns Value 0x08
Time 60 ns Value 0x09
Time 70 ns Value 0x0A
Time 80 ns Value 0x0B
Time 90 ns Value 0x0C
....
One last hint
write
procedures append there data to the LineBuffer
string. When you call writeline, the buffer is written to the file and the LineBuffer
is empty after that operation.
And finally, here is an example snippet on how to read a RAM/ROM initialization file and convert it into a generic memory representation.