I am working with altera QuartusII version 13.I want to write a program that reads data from a text file and outputs this data serially at every positive clk edge.
I have tried writing a code,but it did not work.The simulation result shows a value '1' for y(data read from) all the time even when reset is set '1' initially .Could someone help me in resolving this problem.
--code
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use STD.textio.all;
ENTITY readfile IS
port(rst,clk:in std_logic;
EOR:out std_logic;
y:out std_logic );
END readfile;
ARCHITECTURE behav OF readfile IS
BEGIN
process (rst,clk)
file file_pointer : text;
variable line_content : character;
variable line_num : line;
variable j : integer := 0;
variable char : character:='0';
variable cnt:integer range 0 to 80:=0;
begin
if rst='1'then
EOR<='0';
file_open(file_pointer,"C:\input.txt",READ_MODE);
elsif rising_edge(clk) then
if cnt<80 then
readline (file_pointer,line_num);
READ (line_num,line_content);
EOR<='1';
char := line_content;
if(char = '0') then
y <= '0';
else
y <= '1';
end if;
cnt:=cnt+1;
end if;
end if;
file_close(file_pointer);
end process;
end behav;
--text file(input.txt) 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0 1 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 1 0 0 1 1 0 1 0 0 0 1 0 0 0 1 0 1 0 1 0 1 0 1 1 0 0 1 1 0 0 1 1 1 0 1 1 1 1 0 0 0 1 0 0 0
-
1\$\begingroup\$ Isn't this why people use soft-core CPUs? :) \$\endgroup\$pipe– pipe2016年06月14日 06:29:29 +00:00Commented Jun 14, 2016 at 6:29
-
2\$\begingroup\$ Altera Quartus does not support VHDL's text-I/O. Altera considers text-I/O as not synthesizable. \$\endgroup\$Paebbels– Paebbels2016年06月14日 08:54:23 +00:00Commented Jun 14, 2016 at 8:54
2 Answers 2
Not surprisingly, readline
reads one line of text and stores it into the variable you confusingly named line_num
. Your input file seem to have only one line of text, which starts with 1
.
read
is called with a line_content
output argument which is a single character, so it reads the first character of the line and outputs it in line_content
. That's why you only see a single 1
in the output.
You have to split your input file into multiple lines (each containing a single character). Alternatively, you can make a single call to readline
and then iterate through your line_num
variable by calling read
on it multiple times.
In any case, rename line_num
to line_buf
or something similar. It looks confusing, especially side by side with line_content
, which doesn't hold the line contents as its name advertises.
-
\$\begingroup\$ I've actually written single character in a line. Sorry for not mentioning this in the question. I'll try the alternate method you have suggested. \$\endgroup\$srujana– srujana2016年06月14日 11:35:10 +00:00Commented Jun 14, 2016 at 11:35
You're trying to readline from a file you've closed.
I wrote a little testbench:
library ieee;
use ieee.std_logic_1164.all;
entity readfile_tb is
end entity;
architecture foo of readfile_tb is
signal rst: std_logic := '1';
signal clk: std_logic := '0';
signal eor: std_logic;
signal y: std_logic;
begin
DUT:
entity work.readfile
port map (
rst => rst,
clk => clk,
eor => eor,
y => y
);
CLOCK:
process
begin
wait for 5 ns;
clk <= not clk;
if now > 830 ns then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 10 ns;
rst <= '0';
wait;
end process;
end architecture;
I created input.txt from the 1 and 0 values in your question, one per line.
The first thing my simulator told me was there was a null access (pointer), which would have been the line (line_num). It occurred on the rising edge clock edge after rst is released in the READLINE procedure call.
On closer look, at the end of process you're obliviously doing a FILE_CLOSE, and the next READLINE will fail.
The solution to that is to perform a FILE_OPEN and FILE_CLOSE only once. This also raises the point that we're hanging our hat on rst to hold off readlines, and we could add an enable as an embellishment.
So, modifying the process:
process (rst, clk)
file file_pointer: text;
variable line_content: character;
variable line_num: line;
-- variable j: integer := 0;
variable char: character := '0';
variable cnt: integer range 0 to 80 := 0; -- defaults to 0
begin
if rst = '1' then
eor <= '0';
-- file_open (file_pointer, "c:\input.txt", read_mode);
elsif rising_edge(clk) then
if cnt < 80 then
if cnt = 0 then -- open file once
file_open (file_pointer, "input.txt", READ_MODE);
eor <= '1';
end if;
readline (file_pointer, line_num);
read (line_num, line_content);
-- eor <= '1';
char := line_content;
if char = '0' then
y <= '0';
else
y <= '1';
end if;
cnt := cnt + 1;
end if;
if cnt = 80 then -- variable updated immediately
file_close (file_pointer); -- close only once
eor <= '0'; -- signal end of input
end if;
end if;
end process;
We get only one file_open and one file_close. I modified eor to show when y is valid from the file. That can easily be changed.
And this gives us:
I made a change to the path to input.txt for my environment. I can imagine adding an enable to the elsif rising_edge(clk) portion of the if statement so you don't have to hold readfile in reset.
Another useful modification might be to enclose the readline and read in an if statement with a condition test using function ENDFILE for the case of a short file being read.
-
\$\begingroup\$ PlayDough's suggestions don't provide any insight in this case. The file opened just fine, it was subsequently closed. The error occurs in READLINE following FILE_CLOSE prior to the process suspending from any event. The READ procedure call was unreached. Note calling ENDFILE on an un-opened file is also simulation fatal. See IEEE 1076-2008, 16.4 Package TEXTIO, 5.5.2 File operations. \$\endgroup\$user8352– user83522016年06月16日 00:00:57 +00:00Commented Jun 16, 2016 at 0:00
-
\$\begingroup\$ @user115120 Ok. You win. I've deleted my comments as irrelevant. \$\endgroup\$PlayDough– PlayDough2016年06月16日 19:15:43 +00:00Commented Jun 16, 2016 at 19:15