I would like to write an integer (variable num) on a file (write.txt). Here my code but obviously it does not work. Any suggestion?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.MATH_REAL.ALL;
library std;
use std.textio.all;
entity file_handle is
end file_handle;
architecture Behavioral of file_handle is
begin
process
variable line_var : line;
file text_var : text;
variable num : integer := 40;
begin
file_open(text_var,"C:\Users\Tommy\Desktop\write.txt", write_mode);
write(line_var, num); -- write num into line_var
writeline(text_var, line_var); -- write line_var into the file
file_close(text_var);
end process;
end Behavioral;
After running the synthesis, If I open write.txt file, I read b00000000000000000000000000101000. It seems an address or something else. I expected to read 40.
Try write(line_var, integer'image(num)); instead. It will convert the variable num to a decimal string.
Related
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 need to set a constant's value using an "if-else" or "case", and select a different constant value based on another constant's value. Is this possible in VHDL? It would be a one time change of constant values at the beginning of simulation... Example:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bridge is
generic (
burst_mode :std_logic := '0'
);
end entity;
architecture rtl of bridge is
constant fifo_aw_wdata :natural := 2 when (burst_mode = '0') else 5;
begin
-- fifo: entity work myfifo
-- generic map(
-- aw => fifo_aw_wdata
-- )
-- port map(
-- ...
-- );
end architecture;
The above VHDL code gives the error message:
Error ';' is expected instead of 'when'
In Verilog, Its very easy to do this type of thing...so I assume VHDL has a away to do this as well? Verilog example:
module #(parameter burst_mode = 1'b0) bridge;
localparam fifo_aw_wdata = (!burst_mode) ? 2 : 5;
// fifo myfifo #(.aw(fifo_aw_wdata)) ( ...);
endmodule;
This solution is a little bit strange, but it works:
architecture rtl of bridge is
function setup1(s:std_logic; i0:integer; i1:integer)
return integer is
begin
if s = '1' then
return i1;
else
return i0;
end if;
end function;
constant fifo_aw_wdata :natural := setup1(burst_mode, 2, 5);
begin
-- fifo: entity work myfifo
-- generic map(
-- aw => fifo_aw_wdata
-- )
-- port map(
-- ...
-- );
end architecture;
Correct answers have been posted, but there are also one-line alternatives.
The simplest solution is to change the datatype of burst_mode to integer with range 0 to 1, and then use some math:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bridge is
generic (
burst_mode :integer range 0 to 1 := 0
);
end entity;
architecture rtl of bridge is
constant fifo_aw_wdata :natural := 2 + burst_mode * 3;
begin
If the datatype of burst_mode cannot be changed, then you can also do it with a type conversion:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bridge is
generic (
burst_mode :std_logic := '0'
);
end entity;
architecture rtl of bridge is
constant fifo_aw_wdata :natural := 2 + to_integer(unsigned('0' & burst_mode)) * 3;
begin
Though pico posted an answer already, it is a very relevant question worthy of elaboration.
The declaration of the function may be similar to "conditional expressions" or "ternary if" in other languages like Python with res_true if cond else res_false or C with cond ? res_true : res_false.
The condition is then a boolean, and the result for true comes before the result for false. The declaration could be like:
function tif(cond : boolean; ref_true, ref_false : integer) return integer is
begin
if cond then
return res_true;
else
return res_false;
end if;
end function;
And having multiple functions with different result types, a version for real could also be defined like:
function tif(cond : boolean; res_true, res_false : real) return real is
begin
if cond then
return res_true;
else
return res_false;
end if;
end function;
I want to create a package that holds types that I can load somewhere else and use there. But I don't get it to work.
In my case I have something like this:
types.vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package types is
constant number : integer := 42;
subtype fancy_vector is std_logic_vector(10 downto 0);
type fancy_vector_array is array (4 downto 0) of fancy_vector;
end types;
tb_types.vhdl
library ieee;
use work.types.all;
entity tb_types is
end tb_types;
-- If I comment this entity out, everything works as expected
entity dummy is
port (
test : in fancy_vector_array
);
end dummy;
architecture implementation of tb_types is
begin
main: process begin
assert (number = 42);
report "Everything went well";
wait;
end process;
end implementation;
I analyze and compile the testbench with ghdl like this:
$ ghdl -i types.vhdl tb_types.vhdl
$ ghdl -m tb_types
tb_types.vhdl:10:26:error: no declaration for "fancy_vector_array"
If I comment the dummy entity out, everything works fine as expected. The assertion doesn't trigger and it reports "Everything went well".
What did I do wrong here?
I also tried without .all and with types.fancy_vector_array and types.number. Then it says: no declaration for "types".
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;