file array read for ROM

J

jack kilby

I have a array (ROM with 32 bits columns and 128 rows)in my VHDL code
and need to give the values to it through test bench.(from a Textio
file)
Does anybody know how to do it for a ROM block.Thanks in advance
 
D

David R Brooks

(e-mail address removed) (jack kilby) wrote:

:I have a array (ROM with 32 bits columns and 128 rows)in my VHDL code
:and need to give the values to it through test bench.(from a Textio
:file)
: Does anybody know how to do it for a ROM block.Thanks in advance

Here's a package to read Motorola S-records into a memory (assumed to
be a shared variable). Usual disclaimers apply:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library std;
use std.textio.all;

package memory is

-- Memory array which can be loaded/dumped to files
type T_MEMARRAY is array(natural range <>, natural range <>) of
std_logic;

procedure load_memory ( -- Load from Motorola
S-records
constant FNAME : in string; -- File name
variable MEMORY : inout T_MEMARRAY); -- Memory array

procedure clear_memory (
variable MEMORY : out T_MEMARRAY); -- Memory array

end memory;

-------------------------------------------------------------------

package body memory is

subtype T_8B is unsigned(7 downto 0);

constant f_void : natural := 16#101#; -- Null input line
constant f_error : natural := 16#102#; -- Input-error flag
constant f_eof : natural := 16#103#; -- Input EOF flag
constant maxlen : natural := 32; -- Max. data bytes in
S-record

type hexdata is array(0 to maxlen-1) of T_8B;

type hex_rec is record
locn : natural; -- Memory start address
size : natural; -- Byte count
data : hexdata; -- Byte data
end record;

procedure getbyte( -- Get next byte from line
data : inout line; -- Line to read from
csum : inout natural; -- Checksum
ans : out natural -- Byte value
);

procedure gethexline( -- Read a Motorola S-record
file infile : text; -- File to read
ans : out hex_rec; -- Decoded record
LINUM : inout natural -- Line counter
);

-- purpose: Load memory array from Motorola S-records
procedure load_memory (
constant FNAME : in string; -- File name
variable MEMORY : inout T_MEMARRAY) is
file ROMDAT : text open read_mode is FNAME;
variable XREC : hex_rec; -- Decoded line from file
variable LINUM : natural; -- Line count
variable ONEB : T_8B; -- Byte from file
variable WIDTH, HEIGHT, NBYTES : natural;
variable CLIN, BITO : natural;
begin -- load_memory
WIDTH := MEMORY'length(2); -- Get array dimensions
HEIGHT := MEMORY'length(1);
NBYTES := (WIDTH/8)*HEIGHT;
LINUM := 0;
while not endfile(ROMDAT) loop
gethexline(ROMDAT, XREC, LINUM); -- Process one line
case XREC.size is
when f_void => -- Skip this line
next;
when f_eof =>
exit; -- Done with it
when f_error =>
assert false
report "Error in " & FNAME & ": line " &
natural'image(LINUM)
severity error;
when others => -- Process the data
assert (XREC.locn + XREC.size <= NBYTES)
report "Address over-range in " & FNAME & ": line " &
natural'image(LINUM)
severity warning;
for i in XREC.size-1 downto 0 loop -- Copy in data
ONEB := XREC.data(i);
CLIN := (XREC.locn+i)/(WIDTH/8); -- Cache line / memory
locn.
BITO := 8*((XREC.locn+i) mod (WIDTH/8)); -- Bit offset
for j in ONEB'range loop
MEMORY(CLIN, BITO+j) := ONEB(j);
end loop; -- j
end loop; -- i
end case;
end loop;
end load_memory;

-----------------------------------------------------------------------

-- purpose: Clear memory contents to zero
procedure clear_memory (
variable MEMORY : out T_MEMARRAY) is -- Memory array
begin -- clear_memory
for i in MEMORY'range(1) loop
for j in MEMORY'range(2) loop
MEMORY(i,j) := '0'; -- Clear out
end loop; -- j
end loop; -- i
end clear_memory;

-----------------------------------------------------------------------


--------------------------------------------------------------------------
-- Function: gethex
-- Purpose: Convert ASCII to hexadecimal
-- Input: character
-- Output: natural

--------------------------------------------------------------------------
function gethex( -- Convert ASCII to
hexadecimal
ch : character -- Character to convert
) return natural is -- Decoded value, or f_error

begin
if ('0' <= ch) and (ch <= '9') then
return character'pos(ch) - character'pos('0');
elsif ('A' <= ch) and (ch <= 'F') then
return character'pos(ch) - character'pos('A') + 10;
elsif ('a' <= ch) and (CH <= 'f') then
return character'pos(ch) - character'pos('a') + 10;
else
return f_error;
end if;
end gethex;


--------------------------------------------------------------------------
-- Procedure: getbyte
-- Purpose: Get next byte from line
-- InOut: line, natural
-- Output: natural

--------------------------------------------------------------------------
-- Since the line must be INOUT, this cannot be a function.
procedure getbyte( -- Get next byte from line
data : inout line; -- Line to read from
csum : inout natural; -- Checksum
ans : out natural -- Byte value
) is
variable ch : character;
variable x : natural;
variable res : natural := 0;
variable rdok : boolean; -- Read-function check
begin
ans := f_error; -- Pre-set to trap errors
for i in 1 to 2 loop -- Process two input
characters
if (data'length = 0) then -- End of line?
return;
end if;
read(data, ch, rdok); -- Next character
if not rdok then
return; -- Read errors
end if;
x := gethex(ch); -- To hexadecimal
if (x = f_error) then
ans := f_error; -- Invalid data
return;
end if;
res := (res * 16) + x; -- Big-endian data
end loop;
ans := res; -- Post the result
csum := csum + res;
end getbyte;


--------------------------------------------------------------------------
-- Procedure: gethexline
-- Purpose: Read a line from file, & decode it as a Motorola
S-record
-- Input: text
-- Output: hex_rec

--------------------------------------------------------------------------
-- Since the file must be INOUT, this cannot be a function.
procedure gethexline( -- Read a Motorola S-record
file infile : text; -- File to read
ans : out hex_rec; -- Decoded record
LINUM : inout natural -- Line number
) is
variable data : line; -- Source-file line
variable outrec : hex_rec; -- Record for output
variable ch : character;
variable csum : natural; -- Checksum
variable adlen : natural; -- No. of address bytes
variable bcount : natural; -- Byte counter
variable x : natural;
variable rdok : boolean; -- Read-function check
begin
ans.locn := 0; -- Pre-set to trap errors
ans.size := f_error;
csum := 0;

if endfile(infile) then -- Trap EOF
ans.size := f_eof;
return;
end if;

LINUM := LINUM + 1;
readline(infile, data); -- Fetch the line
read(data, ch, rdok); -- Record type-mark
if not rdok then -- Catch read errors
return;
end if;

case ch is
when '$' => -- Block header data
while not endfile(infile) loop
LINUM := LINUM + 1;
readline(infile, data); -- Get next line
read(data, ch, rdok); -- Record type-mark
if not rdok then -- Catch read errors
return;
end if;
if ch = '$' then -- Mating block-mark
ans.size := f_void;
return; -- Let the caller skip this
line
end if;
end loop;
ans.size := f_eof; -- Premature EOF
return;

when 'S' => -- S-record data
read(data, ch, rdok); -- Record sub-type
if not rdok then
return;
end if;

case ch is
when '1' => -- 2-byte address
adlen := 2;
when '2' => -- 3-byte address
adlen := 3;
when '3' => -- 4-byte address
adlen := 4;
when others => -- Unrecognised type
return;
end case;

getbyte(data, csum, bcount); -- Get byte counter
if (bcount = f_error) or (bcount > maxlen) then
return;
end if;
outrec.size := bcount;

outrec.locn := 0; -- Get the start address
for i in 1 to adlen loop
getbyte(data, csum, x);
if x = f_error then
return; -- Read error
end if;
outrec.locn := (outrec.locn * 256) + x;
end loop; -- i

for i in 0 to bcount-1 loop
getbyte(data, csum, x); -- Get next data byte
if x = f_error then
return;
end if;
outrec.data(i) := to_unsigned(x, 8);
end loop; -- i

getbyte(data, csum, x); -- Get checksum (& add to
count)

while csum > 255 loop -- Reduce modulo-256
csum := csum - 256; -- "mod" can behave oddly!
end loop;

if csum /= 255 then
return; -- Checksum error
end if;

ans := outrec; -- Return data from file

when others => -- Corrupt line
return;
end case;

end gethexline;

end memory;
 
J

jack kilby

hello,
i think my question was not clear.I want to know if it is possible to
give the values to a look up table from the TESTBENCH through a text
I/O File (I dont want to force the values through source code ).If
yes.Kindly explain how.
Thanks and regards
jack
 
M

Mike Treseler

jack said:
i think my question was not clear.I want to know if it is possible to
give the values to a look up table from the TESTBENCH through a text
I/O File (I dont want to force the values through source code ).If
yes.Kindly explain how.

A VHDL testbench can only drive or check VHDL data types.
If you intend to enter this data by hand anyway,
consider using VHDL constants as in my previous example.

If you already have the data file, and you don't want
to type anything in, then you have to make the
testbench do the conversion as in David's previous
example of Motorola S-records, which is a very
common format for generated binary data.

-- Mike Treseler
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top