Search code examples
vhdlsimulationfpgaxilinxxilinx-ise

Copying ISim results as strings/text


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

enter image description here

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!


Solution

  • 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.