Instead of just taking input from a file and writing output to a file, is there a way to dynamically creating a file from the VHDL design??
I am trying to create multiple files depending on number of fpgas connected to the system ( which can be varying).
thanks in advance
Not sure I understand your question, but maybe you mean this:
process
file outputf : text;
begin
file_open(outputf, "path/to/file", WRITE_MODE); -- READ_MODE and APPEND_MODE as the other options
-- Do your file operation as usual
file_close(outputf);
end process;
Create a file name based on the instance of some entity:
each file created has the postfix of 'DATA_NAME' (for example)
Is this what you mean?
entity ENTITY_NAME is
generic (
DATA_NAME : Character := '1'
);
port (
...
);
architecture rtl of ENTITY_NAME is
[signals]
file file_out : TEXT open write_mode is "data_out/ENTITY_NAME" & DATA_NAME & ".txt";
begin
Proc_Data_Output : process
variable line_out : LINE;
begin
d_inout <= "ZZZZZZZZZZZZZZZZ";
write (line_out, string'("Data: "));
hwrite (line_out, d_inout);
writeline (file_out, line_out);
end process;
end rtl;
Related
I would like to separate my data with new line character in an output file, but the following codes result in error "can't resolve overload for procedure call":
write(out_line, "\n");
write(out_line, "");
write(out_line, '');
An example code how I want to use it:
ENTITY writer IS
PORT ( clk : IN STD_LOGIC := '0'; start : IN STD_LOGIC := '0');
END ENTITY;
ARCHITECTURE arch OF writer IS
SIGNAL vect : STD_LOGIC_VECTOR (2 downto 0) := "000";
TYPE state_type IS (init, write_file);
SIGNAL state : state_type := init;
BEGIN
PROCESS (clk, start)
FILE out_file : text;
VARIABLE out_line : line;
BEGIN
IF rising_edge(clk) THEN
CASE state IS
WHEN init =>
IF start = '1' THEN
state <= write_file;
ELSE
state <= init;
END IF;
WHEN write_file =>
state => init;
FOR i IN 0 TO 10 LOOP
write(out_line, vect);
writeline(out_file, out_line);
-- write(out_line, "\n"); <--
-- write(out_line, ""); <--
-- write(out_line, ''); <-- None of these work
writeline(out_file, out_line);
END LOOP;
END CASE;
END IF;
END PROCESS;
END ARCHITECTURE;
So I would like to know, is it possible in VHDL? If yes, how?
The following will consistently give you a single blank line:
write(out_line, string'(""));
writeline(out_file, out_line);
I suspect what #Dani posted may be tool dependent. For example while on one popular simulator, the following produces one line feed:
write(out_line, LF);
writeline(out_file, out_line);
However when I add a space after the LF, I get two lines:
write(out_line, LF & ' ');
writeline(out_file, out_line);
Creating a minimal, complete and verifiable example from the question's incomplete sample code:
library ieee; -- ADDED
use ieee.std_logic_1164.all; -- ADDED
use std.textio.all; -- ADDED
-- use ieee.std_logic_textio.all; -- ADDED for revisions earlier than -2008
ENTITY writer IS
-- PORT ( clk : IN STD_LOGIC := '0'; start : IN STD_LOGIC := '0');
END ENTITY;
ARCHITECTURE arch OF writer IS
SIGNAL vect : STD_LOGIC_VECTOR (2 downto 0) := "000";
-- TYPE state_type IS (init, write_file);
-- SIGNAL state : state_type := init;
BEGIN
PROCESS -- (clk, start)
FILE out_file : text;
VARIABLE out_line : line;
BEGIN
file_open(out_file, "some_file", WRITE_MODE); -- ADDED
-- IF rising_edge(clk) THEN
-- CASE state IS
-- WHEN init =>
-- IF start = '1' THEN
-- state <= write_file;
-- ELSE
-- state <= init;
-- END IF;
-- WHEN write_file =>
-- state => init;
FOR i IN 0 TO 10 LOOP
write(out_line, vect);
writeline(out_file, out_line);
-- write(out_line, "\n"); <--
-- write(out_line, ""); <--
-- write(out_line, ''); <-- None of these work
writeline(out_file, out_line);
END LOOP;
-- END CASE;
-- END IF;
wait; -- ADDED
END PROCESS;
END ARCHITECTURE;
demonstrates a way to get a blank line in the output:
some_file contents:
000
000
000
000
000
000
000
000
000
000
000
The second writeline procedure call produces an empty line without an intervening write procedure call.
Why is seen in IEEE Std 1076-2008 16.4 Package TEXTIO:
Procedures READLINE, WRITELINE, and TEE declared in package TEXTIO read and write entire lines of a file of type TEXT. Procedure READLINE causes the next line to be read from the file and returns as the value of parameter L an access value that designates an object representing that line. If parameter L contains a non-null access value at the start of the call, the procedure may deallocate the object designated by that value. The representation of the line does not contain the representation of the end of the line. It is an error if the file specified in a call to READLINE is not open or, if open, the file has an access mode other than read-only (see 5.5.2). Procedures WRITELINE and TEE each cause the current line designated by parameter L to be written to the file and returns with the value of parameter L designating a null string. Procedure TEE additionally causes the current line to be written to the file OUTPUT. If parameter L contains a null access value at the start of the call, then a null string is written to the file or files. If parameter L contains a non-null access value at the start of the call, the procedures may deallocate the object designated by that value. It is an error if the file specified in a call to WRITELINE or TEE is not open or, if open, the file has an access mode other than write-only.
The language does not define the representation of the end of a line. An implementation shall allow all possible values of types CHARACTER and STRING to be written to a file. However, as an implementation is permitted to use certain values of types CHARACTER and STRING as line delimiters, it might not be possible to read these values from a TEXT file.
A line feed (LF) format effector occurring as an element of a string written to a file of type TEXT, either using procedure WRITELINE or TEE, or using the WRITE operation implicitly defined for the type TEXT, is interpreted by the implementation as signifying the end of a line. The implementation shall transform the LF into the implementation-defined representation of the end of a line.
...
For each WRITE, OWRITE, and HWRITE procedure, after data is appended to the string value designated by the parameter L, L designates the entire line. The procedure may modify the value of the object designated by the parameter L at the start of the call or may deallocate the object.
If deallocation occurs out_line will have a value of null after a writeline call and a null string is written in the immediately following writeline call which also provides an end of line.
If the object value accessed by out_line is a null array (having no elements, 5.3.2.2 Index constraints and discrete ranges, a null string) the immediately following writeline call will result in an end of line being written to the file.
In essence your code example already contains one of these methods for writing a blank line, which depends on whether deallocation is used conditionally (may).
Variants of allocate() and free() can be relatively expensive in terms of execution time and when the size of the allocated object and it's element size is known a smaller 'allocated' object can be written to the same object space saving simulation time. The simulation kernel representation of an array object can have bounds separate from the array value, deallocation and re-allocation can be reserved for when the object size is larger than the previously allocated size or an explicit deallocate call occurs.
There's also a requirement that an implementation translate an LF character to an end of line in a write to a file. This is the other mechanism that allows you to write an LF character as the last or only character to a line and get a following blank line.
You could also explicitly write a null string to out_line
write(out_line, string'(""));
prior to the second writeline call. The qualified expression provides the type of the string literal unlike the attempt commented out in the original question where the type of the string literal can't be determined. See 9.3.2 Literals "... The type of a string or bit string literal shall be determinable solely from the context in which the literal appears, excluding the literal itself but using the fact that the type of the literal shall be a one-dimensional array of a character type. ...". The procedure write would be ambiguous in this context, failing overload resolution (12.5 The context of overload resolution).
Finally after a lot of searching and trying I found that the following code works:
write(out_line, lf);
writeline(out_file, out_line);
I found that write(out_line, cr); does the same thing, and write(out_line, nul); adds ' ' character between the outputs.
I have a procedure (testbench only, non-synthesisable) which receives data via an AXIS interface and writes it to a byte array. I also want the option to write the received data to file. To do this i've added a file handle such that any test bench using this procedure can declare a file handle and pass it to the procedure and the received data will be written to the given file via the file handle.
Here's the procedure declaration:
procedure AXI_STREAM_RECEIVER
(
-- AXI-Stream Parameters
variable PAYLOAD : inout p_byte_array;
constant SLAVE_READY_BEHAVE : in t_slave_ready_behave := always_ready;
constant READY_GAP_RANGE : in natural := 20;
constant VERIFY_TKEEP : in boolean := false;
file file_handle : text;
-- Interface Clock
signal CLK : in std_logic;
-- Master/Slave I/O
signal axis_tdata : in std_logic_vector;
signal axis_tkeep : in std_logic_vector;
signal axis_tvalid : in std_logic;
signal axis_tlast : in std_logic;
signal axis_tready : out std_logic;
-- Misc.
constant VERIFY_TLAST : in boolean := true;
constant VERBOSE : in boolean := c_verbosity_default;
constant DEBUG_SEVERITY_LEVEL : in severity_level := c_axil_debug_severity_level;
constant DEBUG_PAYLOAD_CONTENT : in boolean := false
);
As I want the write to file to be optional, I was hoping to be able to provide a 'null' file handle as a default when writing to file is not required. I've tried assigning a default but I get:
FILE interface declaration must not contain a default expression
Then i've tried assigning it to 'null' when instanced:
Illegal use of NULL literal.
But then if I leave it with no default and not assigned I get:
No feasible entries for subprogram "AXI_STREAM_RECEIVER"
Anybody know if it's possible to pass in some sort of null file descriptor?
You can achieve this using a package with generics using VHDL-2008. The file handle and procedure are declared separately within the package header. Here's an example:
library ieee;
use ieee.std_logic_1164.all;
library std;
use std.textio.all;
package gen_pkg is
generic (
PRINT_TO_FILE : boolean;
FILE_NAME : string;
FILE_MODE : file_open_kind := write_mode
);
file outfile : text;
procedure TEST_PROCEDURE;
end gen_pkg;
package body gen_pkg is
procedure TEST_PROCEDURE is
variable outline : line;
begin
write(outline,string'("TEST STRING"));
if PRINT_TO_FILE then
file_open(outfile, FILE_NAME, FILE_MODE);
writeline(outfile, outline);
file_close(outfile);
end if;
end TEST_PROCEDURE;
end gen_pkg;
I've only shown a string being written, but use any of the overloaded variants of write in the textio package depending on your required datatype or you can use the VHDL-2008 function to_string which supports conversions of all types.
Then in your testbench, create a new instantiation of the package and access procedures/functions, etc. using the instantiation name:
library ieee;
use ieee.std_logic_1164.all;
library std;
use std.textio.all;
entity tb is
end tb;
architecture arch of tb is
package gp is new work.gen_pkg
generic map (
PRINT_TO_FILE => TRUE,
FILE_NAME => "./test_file.txt",
FILE_MODE => append_mode
);
begin
process begin
for i in 0 to 4 loop
gp.TEST_PROCEDURE;
end loop;
wait;
end process;
end arch;
Please note, if you write to the file more than once, like shown in this example, file mode must be append_mode. In write_mode, the file will be overwritten everytime file_open is called. If you only write to the file once per simulation, write_mode is fine. You can also have multiple new instantiations of your generic package in multiple locations, all writing to the same file, as along as they all use append_mode for the file mode.
Here's the working example on EDA playground setup to use Aldec Riviera Pro 2017.02. A login is required to run it. You must have pop-up blocker disabled in your browser in order to download the output file to inspect. The string "TEST STRING" should be written to the file 5 times.
In VHDL 2008 and earlier, you must always connect a file object in an interface list to another file object. Accessing the object when it is not open will cause an error, but there is no way to detect if the file is open or not. VHDL2019 does add a FILE_STATE function to do this, but I assume you still need to connect it to an existing file object with no defaults allowed.
Would it be easier to pass in a string of the filepath, which can have a default of ""? If it is a null string then dont open the file.
I try to write VHDL simulation result at txt file.
I can write some data.
But i like to stack these data by row order. That is, there is new line between saved data.
I exptected writeline function to move newline. But it isn`t.
TEXT_OUT : process (I_CLK,I_RST)
file file_RESULTS : text open write_mode is "output_result.txt";
variable v_OLINE : line;
begin
if (I_RST = '1') then
null;
elsif (rising_edge(I_CLK)) then
if (I_BRAM_ENA = '1') then
hwrite(v_OLINE, O_ADDRB, left, 5);
writeline(file_RESULTS, v_OLINE);
report "Save the output address!";
end if;
end if;
end process;
if O_ADDRB have sequentially 0000, 0001, 0002, as time gone.
Then output_result.txt have data like below
0000
0001
0002
If you need to print in new line then probably I can't help you unless you have to do it all in one go, without having to close the file and open again (in which case you can follow as mentioned in comments by user1155120.
But if it is only for debugging purposes, then use this code to print in console:
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
use ieee.std_logic_textio.all;
procedure writeproc(sig: in std_logic_vector; s : string) is
variable li : line;
variable str : string(1 to sig'length);
file f_in : text; -- open read_mode is "output";
file f_out : text; -- open write_mode is "output";
begin
file_open(f_out, "output", write_mode);
write(li, std_logic_vector(sig));
write(li, lf); writeline(f_out, li);
file_close(f_out);
file_open(f_in, "output", read_mode);
readline(f_in, li);
read(li, str);
file_close(f_in);
report "read " & s & str;
end procedure writeproc;
I have a file source.txt, it looks like this:
00660066006700670067006800680069006B006D006E
00660066006700670067006800680069006B006D006E
00660066006700670067006800680069006B006D006E
00660066006700670067006800680069006B006D006E
00660066006700670067006800680069006B006D006E
0065006500660067006700690069006A006B006C006E
00650065006600670067006700680069006A006C006D
00650065006600670067006600660068006A006B006D
006500650066006700670065006600670069006B006D
00650065006600670067006600670068006A006C006D
0065006500660067006700690069006A006B006C006E
*
After each line there is the hidden newline character '\n'.
The asterix '*' is my visible end-of-file character.
How do I write a testbench in VHDL that does the following:
read file
store one line in a vector
write that vector in a new target.txt
Using VHDL-2008, and showing the std_logic_vector underway, the code can be:
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
entity tb is
end entity;
architecture syn of tb is
begin
process is
variable line_v : line;
file read_file : text;
file write_file : text;
variable slv_v : std_logic_vector(44 * 4 - 1 downto 0);
begin
file_open(read_file, "source.txt", read_mode);
file_open(write_file, "target.txt", write_mode);
while not endfile(read_file) loop
readline(read_file, line_v);
hread(line_v, slv_v);
report "slv_v: " & to_hstring(slv_v);
hwrite(line_v, slv_v);
writeline(write_file, line_v);
end loop;
file_close(read_file);
file_close(write_file);
wait;
end process;
end architecture;
is it possible to write a module code for a test bench? I have a test bench code that reads a text file and shows it in the Isim but I want to put this data on a port and process it. how can I get it out of simulation environment? how can I write a module for that in VHDL? thank you
, the code is here:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use STD.textio.all; --Dont forget to include this library for file operations.
ENTITY read_file IS
END read_file;
ARCHITECTURE beha OF read_file IS
signal bin_value : std_logic_vector(2 downto 0):="000";
BEGIN
--Read process
process
file file_pointer : text;
variable line_content : string(1 to 3);
variable line_num : line;
variable j : integer := 0;
variable char : character:='0';
begin
--Open the file read.txt from the specified location for reading(READ_MODE).
file_open(file_pointer,"C:\read.txt",READ_MODE);
while not endfile(file_pointer) loop --till the end of file is reached continue.
readline (file_pointer,line_num); --Read the whole line from the file
--Read the contents of the line from the file into a variable.
READ (line_num,line_content);
--For each character in the line convert it to binary value.
--And then store it in a signal named 'bin_value'.
for j in 1 to 3 loop
char := line_content(j);
if(char = '0') then
bin_value(3-j) <= '0';
else
bin_value(3-j) <= '1';
end if;
end loop;
wait for 10 ns; --after reading each line wait for 10ns.
end loop;
file_close(file_pointer); --after reading all the lines close the file.
wait;
end process;
end beha;