In a certain simulation testbench using questasim, I am trying to read the files with integers numbers which looks like,
0000
0001
0005
3864
2290
1234
.
.
.
0002
0004
0006
4532
3457
.
.
.
My aim here is to read the text file, store first few numbers in an array of integers and write that array in text output, my attempted code looks like,
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_textio.all;
use std.textio.all;
entity HFA_tb is
end HFA_tb;
architecture behave of HFA_tb is
--clock 100 MHz change to any value suitable
constant c_CLOCK_PERIOD : time:= 100 ns;
signal r_CLOCK : std_logic := '0';
--**signal r_ENABLE : std_logic := '0';
signal r_adcpulse : integer;
signal r_hitstart : integer; ---output of single threshold
signal r_hitend : integer;
signal r_hitpeak : integer;
signal r_peaktime : integer;
signal r_hitsum : integer;
signal r_opready : std_logic := '0';
--more signal
--describe HFA component here (Unit Under Test)
component HFA is
port (
adcpulse_i : in integer;
clk : in std_logic;
hitstart_o : out integer; ---output of single threshold
hitend_o : out integer;
hitpeak_o : out integer;
peaktime_o : out integer;
hitsum_o : out integer;
opready_o : out std_logic
);
end component HFA;
begin
--Instatiate the unit under test
UUT : HFA
port map (
clk => r_CLOCK,
adcpulse_i => r_adcpulse,
hitstart_o => r_hitstart,
hitend_o => r_hitend,
hitpeak_o => r_hitpeak,
peaktime_o => r_peaktime,
hitsum_o => r_hitsum,
opready_o => r_opready
);
p_CLK_GEN : process is
begin
wait for c_CLOCK_PERIOD/2;
r_CLOCK <= not r_CLOCK;
end process p_CLK_GEN;
--main testing logic for reading from text file; feed in the loop and check output
process
file in_buffer : text;
file out_buffer : text;
variable v_ILINE : line;
variable v_OLINE : line;
variable v_adcValue : integer;
variable line_counter : integer :=0;
variable block_length : integer :=0;
variable block_counter : integer :=0;
variable header_length : integer :=0;
type header is array (0 to 2) of integer;
variable H: header;
begin
file_open(in_buffer,"/home/eu18461/Data/DUNE/QuestaSim_Examples/HFA_test4_SliceTest/sample.txt",read_mode);
file_open(out_buffer,"/home/eu18461/Data/DUNE/QuestaSim_Examples/HFA_test4_SliceTest/results.txt",write_mode);
while not endfile(in_buffer) loop
if line_counter=0 then
f1 : for k in 0 to 2 loop
readline(in_buffer, v_ILINE);
read(v_ILINE, v_adcValue);
H(k) := v_adcValue;
line_counter := line_counter+1;
end loop f1;
end if;
if line_counter /= 2 and block_length /= 9 then
f2 : for k in 0 to 2 loop
readline(in_buffer, v_ILINE);
read(v_ILINE, v_adcValue);
r_adcpulse <= v_adcValue;
line_counter := line_counter+1;
block_length := block_length+1;
end loop f2;
end if;
if block_length=9 then
f3 : for k in 0 to 2 loop
readline(in_buffer, v_ILINE);
read(v_ILINE, v_adcValue);
H(k) := v_adcValue;
line_counter := line_counter+1;
header_length := header_length+1;
if header_length=3 then
block_length := 0;
exit;
end if;
end loop f3;
end if;
wait for c_CLOCK_PERIOD;
end loop;
if endfile(in_buffer) then
write(v_OLINE, string'("hit_start_time"));
writeline(out_buffer, v_OLINE);
write(v_OLINE, r_hitstart);
writeline(out_buffer, v_OLINE);
end if;
wait for c_CLOCK_PERIOD;
file_close(in_buffer);
file_close(out_buffer);
wait;
end process;
end behave;
Updated the code, my desired output text should look like,
Int1 int2 int3 Op1 op2 op3 Op3 ...
Int11 int12 int13 op1 op2 op3 ...
.
.
.
Intx inty intZ op1 op2 op3 ...
Here int1, Int2 ...etc represent the integers from the input text file, these no. goes upto a fixed block length. I want to store them, and send the remaining integers to my processing block, after the process I want the output in row format as shown in the text file and again repeat the process. Any hints will be much appreciated. Here the for loop no. indicate the integers storing length and block length after which the process i s repeated.
-
\$\begingroup\$ Do we really need to could lines here ... Where is line 107? \$\endgroup\$Paebbels– Paebbels2018年12月18日 22:21:15 +00:00Commented Dec 18, 2018 at 22:21
-
\$\begingroup\$ I have altered the code now. \$\endgroup\$EngineerPhysicist– EngineerPhysicist2018年12月20日 20:35:10 +00:00Commented Dec 20, 2018 at 20:35
1 Answer 1
Wish I could comment, b/c there are a lot of syntactical issues here.
You defined a type
called H
and then tried to assign something to the type: H(0) := v_adcValue
which is illegal and may explain the first part of the error. You must define the type and then declare a variable or signal of the defined type, which can then receive assignment.
It looks like you may have meant to declare a signal called header
of type H
, based on this line: header(k) <= v_adcValue
, but the declaration of header
is missing. Or perhaps you removed it, as suggested by:
** Error: (vcom-1583) Illegal type converson from 'std.STANDARD.INTEGER' to 'header' (numeric to array).
You're also trying to use to_string()
on the non-existent signal header
. The function is overloaded for many built-in types as of VHDL-2008, but not user-defined types, like an array of integers.
Your MONITOR
process has no wait statement. It will execute immediately at the start of sim and create an infinite loop. It needs something to trigger it periodically, otherwise your simulation will be stuck executing that process continually and never advance past a delta cycle until it hits the iteration limit.
Please address these things first.
EDIT
You could write the first values directly to the output line as they are read in. This will preserve the 4 digit padding format your input file has. Note - I added another line
variable called temp
to the file process:
...
if line_counter=0 then
v_OLINE := new string'(""); --Needs to be initialized
f1 : for k in 0 to 2 loop
readline(in_buffer, v_ILINE);
temp := new string'(v_ILINE.all&" "); --Create new line with added space
v_OLINE := new string'(v_OLINE.all&temp.all); --Concatenate new line to existing
read(v_ILINE, v_adcValue);
H(k) := v_adcValue;
line_counter := line_counter+1;
end loop f1;
...
If you then output the line (after loop f1
):
v_OLINE := new string'(v_OLINE(1 to v_OLINE'length-1)); --Remove ending space
writeline(out_buffer,v_OLINE);
then, for input of:
0000
0001
0005
Your output would be:
0000 0001 0005
Of course, you'll want to wait to write that line to file until you get back the values from your other process. After your wait for c_CLOCK_PERIOD;
, you would simply write another loop for putting your additional data into the output line before writing to file.
You'll need another array in addition to H
for your secondary chunk of integers from the input file, and for the processed data to be written out. Since you're processing that data elsewhere, I recommend making these arrays signals rather than variables.
If you need to output your processed data with 4-wide fields (like '0000', '0002', etc), you can define a string
variable, "zeros
", of length 4 in your file process to help pad your values:
-- "proc_data" is your processed data array
for k in 0 to <needed_length> loop
zeros := (others=>'0');
zeros(zeros'length-integer'image(proc_data(k))'length+1 to zeros'length) := integer'image(proc_data(k));
write(v_OLINE,zeros);
write(v_OLINE,string'(" "));
end loop;
v_OLINE := new string'(v_OLINE(1 to v_OLINE'length-1)); --Remove ending space
writeline(out_buffer,v_OLINE);
Be sure none of your processed integers are longer then 4, or you'll get a length mismatch. Or just adjust zeroes to the max. length needed.
This is about all I can suggest. You'll have to work out the details on how many loop iterations you need for your data, etc, but this should give you enough.
-
\$\begingroup\$ Thanks, I very much appreciate your response. The code is now compiling successfully. Any hints to get my desired output.txt will be really useful. Cheers! \$\endgroup\$EngineerPhysicist– EngineerPhysicist2018年12月20日 20:36:30 +00:00Commented Dec 20, 2018 at 20:36
-
\$\begingroup\$ Updated my answer. \$\endgroup\$user_007– user_0072018年12月21日 22:48:03 +00:00Commented Dec 21, 2018 at 22:48