Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Reading text, and writing it to a memory block

Status
Not open for further replies.

153rd

Member level 1
Joined
Mar 4, 2011
Messages
34
Helped
5
Reputation
10
Reaction score
5
Trophy points
1,288
Activity points
1,545
Reading text, and writing it to a memory block in VHDL

Hi,

I'm trying to do the following: Reading text(file: GPUdata.txt), writing it to memory, wich will be used to create a 800 x 640 image on a monitor.
I'm having difficulties reading the txtfile/ writing it to a memory block.

For reading text, I wrote the function below:

------------------------------------------------------
-- Read text from GPUdata.txt --
impure function ReadText(Filename : in string) return RAMTYPE is

variable MEM_DATA : RAMTYPE;--std_logic_vector(95 downto 0);
Variable L : line;
Variable i : integer := 0;
File Datafile : text open read_mode is Filename;
begin

if write_en = '1' then
while not((endfile(Datafile))) loop
Readline(Datafile, L);
Read(L, MEM_DATA(i));
i := i +1;
return mem_data;
end loop;
end if;
return mem_data;
File_close(Datafile);
end function;
------------------------------------------------------

When I write this to memory, I see that ONLY the first line in my textfile has beeen written to my memory block.
I've been looking up some examples on the internet, but I can't see where my mistake is. Below you can see my RAM description:

type RAMTYPE is array(15 downto 0) of std_logic_vector(95 downto 0);
signal RAM:RAMTYPE;
signal RD_ADDR_REG: std_logic_vector(3 downto 0);
begin
process(CLK)
begin
if rising_edge(clk) then
if write_en = '1' then
RAM(to_integer(unsigned(Write_addr))) <= ReadText("GPUdata.txt")(to_integer(unsigned(Write_addr)));--RAM(to_integer(unsigned(Write_addr)))
--else data_out <= RAM(to_integer(unsigned(read_addr)));
end if;
RD_ADDR_REG <= Read_ADDR;
end if;
end process;
--data_out <= RAM (to_integer(unsigned(Read_addr)));
-- The noob way:
process(CLK, write_addr)--, write_data_buffer)
begin
if rising_edge(CLK) then
case read_addr is
when "0000" => data_out <= RAM(0);
when "0001" => data_out <= RAM(1);-- Only this spot is written, the rest stays undefined
when "0010" => data_out <= RAM(2);
when "0011" => data_out <= RAM(3);
when "0100" => data_out <= RAM(4);
when "0101" => data_out <= RAM(5);
when "0110" => data_out <= RAM(6);
when "0111" => data_out <= RAM(7);
when "1000" => data_out <= RAM(8);
when "1001" => data_out <= RAM(9);
when "1010" => data_out <= RAM(10);
when "1011" => data_out <= RAM(11);
when "1100" => data_out <= RAM(12);
when "1101" => data_out <= RAM(13);
when "1110" => data_out <= RAM(14);
when others => data_out <= RAM(15);
end case;
end if;
end process;

Does anyone see where my mistake is?
 
Last edited:

Firstly, I assuming you're using Xilinx, because Altera wont let you read a text file to initialise a ROM (very annoying).

You cannot run the ReadText function in a process. You cannot read a file more than once (it doesnt exist inside the FPGA). You have to do it when initialising a constant:

constant RAM: RAMTYPE := ReadText; --you will have you modify the function to return the entire memory array.

And did you mean the RAM to only have 16 elements? For larger RAMs, you wont want to use a case statement (it will get huge!)
 

Hi, yes, i'm using Xilinx. The function is outside the process, (between begin and architecture).
The returntype of the arry already is a memory array(RAMTYPE).
I am also aware that the case statement is far from ideal, but you can see i commented this:
--data_out <= RAM (to_integer(unsigned(Read_addr)));

I just wanted to b sure that my output was exactly what was in the ROM.
 

you need to declare the ram like this:

signal RAM : RAMTYPE := ReadText("file.txt");

then access it like this:

data_out <= RAM(addr)

do not assign the RAM signal inside the process (unless you're assigning a single address from the write data input).
If you want a rom, make RAM a constant rather than signal.
 
  • Like
Reactions: 153rd

    153rd

    Points: 2
    Helpful Answer Positive Rating
Hey, just tried it: Before begin of architecture: signal write_data_buffer:= ReadText("GPUdata.txt"); And then RAM <= write_data_buffer; or RAM(to_integer(unsigned(Write_addr))) <= write_data_buffer(to_integer(unsigned(Write_addr)));
In the testbench my output is completely undefined

When I try:
RAM(to_integer(unsigned(Write_addr))) <= ReadText("GPUdata.txt")(to_integer(unsigned(Write_addr)));

Then only addres 0001 has a value, the first line of GPUdata.txt. All the other addresses are Undefined
 

I'm not using Xilinx and don't know if it's supporting the way you are reading the text file into a temporary array. In any case it's an unnecessary long winded method. Most people would simply read the text in the test bench top level.

Code:
open text file
for each line
  read text
  write array data
close text file
 
  • Like
Reactions: 153rd

    153rd

    Points: 2
    Helpful Answer Positive Rating
I'm not using Xilinx and don't know if it's supporting the way you are reading the text file into a temporary array.

Xilinx support using textio to create a rom in synthesis
Altera dont (please raise a support request, because maybe they will one day!)
 

FvM, thx for help. I put the text reading in the testbench now:
---------------------------------------------------------
File Datafile : text open read_mode is "GPUdata.txt";
variable mem_data : std_logic_vector(95 downto 0);
Variable L : line;
Variable i : integer := 0;
----------------------------------------------------------
BEGIN

The BEGIN is from architecture. Further down I have This process:

------------------------------------------------------
-- Read text from GPUdata.txt --
RDTXT: process
begin
wait for 100 NS;

if write_en <= '1' then
while not((endfile(Datafile))) loop
Readline(Datafile, L);
Read(L, mem_data);
i := i +1;
write_data <= mem_data;
wait for 20 NS;
end loop;
end if;
end process;
--------------------------------------------------------

The Error it gives now is: Variable outside of subprogram or process must be 'shared'. What exactly does this imply?

---------- Post added at 12:37 ---------- Previous post was at 12:31 ----------

Ok, I've looked up what a shared variable is, usually variables are declared inside functions or processes, shared ones can be used by multiple processes or functions. I've put shared in front of all the used variables, and now it works perfectly.
Thx for help FvM and dicky!!
 

I guess, you want to access mem_data outside the read process. Making a global signal would be the obvious method. Shared variable is also possible, but of no particular use in this case, I think. You'll also need a type definition like in your original post to make it a two dimesional array. Now it's an array of bits.

The auxilary variables need to be defined inside the read process.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top