0

I wrote an image manipulation piece of VHDL code. For testing, I created a file of pixel values with Matlab and a relatively simple testbench (it just fills the values from file to the input). I wanted to write results to a new file, so that I can process them and see the resulting image.

The code compiles and testbench runs, I see all the reports I put in to check if it stops anywhere, but the file with results remains empty. Neither print nor writeline seem to do anything. The file exists and is added to project in Vivado, so I don't have to write the whole path. There are no warnings or errors in simulator output.

I got the write to file code from here and here and expanded it a bit to make a write to file each clock and add a caption on top.

color_out(0) is a piece of output. color_out_v is output valid.

Any ideas? What am I missing?

Verify_data_process : process
variable my_line : line; 
file l_file      : TEXT;        -- open write_mode is "color_out.txt";   
begin -- process
file_open(l_file, "C:\Users\vevo\branches\Vivado_IP\repo\testing_data\color_out.txt", write_mode);
  wait until clk128_tb = '1';
    print(l_file, "R G B" );

    if(color_out_v = '1') then
    report "Color_out";
        write(my_line, integer'(to_integer(color_out(0).R)));
        write(my_line, integer'(to_integer(color_out(0).G)));
        write(my_line, integer'(to_integer(color_out(0).B)));
        writeline(l_file, my_line);
    report "write line";
    end if;
    file_close(l_file);
end process;
Community
  • 1
  • 1
FlyinGazebo
  • 3
  • 1
  • 7
  • 1
    Welcome to SO. It would help if you had given some code that [minimally reproduced your problem](http://stackoverflow.com/help/mcve); instead I had to add quite a lot of code and take quite a lot out, just to make your code compile and run. Having done [that](http://www.edaplayground.com/x/2fwc), I see no problem - it writes to a file, which has the contents I expected. So why to I get some content in my file? One of the lines I had to comment out was `if(color_out_v = '1') then`; the obvious suggestion is that `color_out_v` is never `1`. If you had provide a MCVE, I could have checked that. – Matthew Taylor May 13 '16 at 08:11
  • BTW: the qualification in this `integer'(to_integer` is redundant: `to_integer` returns an `integer`; the compile knows that, so no qualification is necessary. – Matthew Taylor May 13 '16 at 08:12
  • @Matthew Taylor: I noted the comment for future. I always felt I should put in as little code as possible for readability. color_out_v becomes '1' perfectly fine, I believe the report "write line" would not happen as well if it didn't. If it works for you, I might have a system problem I'm not aware of. – FlyinGazebo May 13 '16 at 08:27
  • Putting in as little code as possible for readability is a very good thing to do, but instead of taking stuff out that enables the code to compile, it would be better to take stuff out that is nothing to do with the problem. That way others can simple run your code and reproduce your problem with little effort. There's another advantage too: the act of paring down your code to this MCVE might enable you to find the problem yourself. Anyway, in this case, I think that would be a good idea: you may be able to solve the problem yourself; if not, how about posting the code you end up with? ... – Matthew Taylor May 13 '16 at 08:43
  • ...so the problem _was_ with a line of code that I commented out to get it to compile. – Matthew Taylor May 13 '16 at 12:22
  • Actually, it turned out my problem was in not terminating simulation properly. Vhdl only writes to file when simulation ends, but I was looking at it with simulation still running. – FlyinGazebo May 18 '16 at 07:55

2 Answers2

1

The question code is opening and closing the file every time clk128_tb has an event and is found to equal '1'.

A Minimal, Complete, and Verifiable example with the question's process at it's core:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;

entity color_out is
end entity;

architecture foo of color_out is

    signal clk128_tb:   std_logic := '0';
    signal color_out_v: std_logic := '0';

    type pixel is record
        R: unsigned (7 downto 0);
        G: unsigned (7 downto 0);
        B: unsigned (7 downto 0);
    end record;
    type scan is array (0 to 3) of pixel;

    signal color_out:   scan :=  ( (X"FF", X"A0", X"FF"), 
                                   (X"7F", X"7F", X"7F"),
                                   (X"00", X"FF", X"00"), 
                                   (X"C0", X"C0", X"C0") );
begin

Verify_data_process : 
    process
        variable my_line:  line; 
        file l_file:       TEXT;   -- open write_mode is "color_out.txt";
        constant header:    string := "  R   G   B";
        variable file_is_open:  boolean;
    begin -- process
        if not file_is_open then
            file_open (l_file, "color_out.txt", write_mode);
            file_is_open := true;
            -- print(l_file, "R G B" );
            write(my_line, header);
            writeline(l_file, my_line);
        end if;
        wait until rising_edge(clk128_tb ); --  wait until clk128_tb = '1';
        -- print(l_file, "R G B" );

        if color_out_v = '1' then
            report "Color_out";
            write(my_line, integer'image(to_integer(color_out(0).R)) & " ");
            write(my_line, integer'image(to_integer(color_out(0).G)) & " ");
            write(my_line, integer'image(to_integer(color_out(0).B)));
            writeline(l_file, my_line);
            report "write line";
        end if;
        -- file_close(l_file);
    end process;

CLOCK:
    process
    begin
        wait for 10 ns;
        clk128_tb <= not clk128_tb;
        if now > 100 ns then
            wait;
        end if;
    end process;
STIMULIS:
    process
    begin
        wait for 20 ns;
        color_out_v <= '1';
        wait;
    end process;
end architecture;

The changes include only opening the file once and not closing it explicitly. The file will be closed implicitly when the simulation ends or the process can be passed a signal to close the file explicitly if provided with a sensitivity list. The signal could be provided with a transaction when now = TIME'HIGH for instance.

Also not having a procedure named print, it's been replaced by a constant header string a write to the line buffer and a write line. Note this only occurs once when the file is opened.

The use of the rising_edge function is force of habit. Without an MCVe the code grew organically.

As A. Kieffer commented as an answer integer'image is used plus some added formatting spaces. A line is a access (pointer) to a string, you write strings to a line.

And when run the above gives console output:

ghdl -r color_out
color_out.vhdl:45:13:@30ns:(report note): Color_out
color_out.vhdl:50:13:@30ns:(report note): write line
color_out.vhdl:45:13:@50ns:(report note): Color_out
color_out.vhdl:50:13:@50ns:(report note): write line
color_out.vhdl:45:13:@70ns:(report note): Color_out
color_out.vhdl:50:13:@70ns:(report note): write line
color_out.vhdl:45:13:@90ns:(report note): Color_out
color_out.vhdl:50:13:@90ns:(report note): write line
color_out.vhdl:45:13:@110ns:(report note): Color_out
color_out.vhdl:50:13:@110ns:(report note): write line

And the file color_out.txt contains:

  R   G   B
255 160 255
255 160 255
255 160 255
255 160 255
255 160 255

A set of pixel values for each rising_edge event when color_out_v = '1'. And with the locally static index 0 they're always the same pixel.

So the problem was opening and closing the file repeatedly every time the process is wakened.

A file_open after a file close has the effect of clearing the file contents and you won't have any results.

See IEEE Std 1076-2008 5.5.2 File operations paragraph 2 (excerpted):

— If the value supplied to the Open_Kind parameter is WRITE_MODE, the access mode of the file object is write-only. In addition, the external file is made initially empty. Values written to the file object are placed in the external file in the order in which they are written.

Community
  • 1
  • 1
0

I cannot comment so I post it as an answer. Like Matthew , I don't see any "coding problem". Though you are writing integers onto your line. Try converting them to string, it might be the problem.

You can use this function for example:

FUNCTION to_string (value : integer) RETURN string IS

BEGIN

RETURN integer'image(value);

END FUNCTION to_string;
A. Kieffer
  • 372
  • 2
  • 13