-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
-- =============================================================================
-- Authors: Martin Zabel
-- Patrick Lehmann
--
-- Package: VHDL package for component declarations, types and functions
-- of the PoC.mem namespace
--
-- Description:
--
-- This package holds all component declarations, types and functions of the
-- :ref:`PoC.mem <NS:mem>` namespace.
--
-- It provides the following enumerations:
--
-- * ``T_MEM_FILEFORMAT`` specifies whether a file is in Intel Hex, Lattice
-- Mem, or Xilinx Mem format.
--
-- * ``T_MEM_CONTENT`` specifies whether data in text file is in binary, decimal
-- or hexadecimal format.
--
-- It provides the following functions:
--
-- * ``mem_FileExtension`` returns the file extension of a given filename.
-- * ``mem_ReadMemoryFile`` reads initial memory content from a given file.
--
-- License:
-- =============================================================================
-- Copyright 2008-2015 Technische Universitaet Dresden - Germany
-- Chair of VLSI-Design, Diagnostics and Architecture
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- =============================================================================
library STD;
use STD.TextIO.all;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library PoC;
use PoC.config.all;
use PoC.utils.all;
use PoC.strings.all;
use PoC.vectors.all;
package [docs]mem is
type T_MEM_FILEFORMAT is (
MEM_FILEFORMAT_INTEL_HEX,
MEM_FILEFORMAT_LATTICE_MEM,
MEM_FILEFORMAT_XILINX_MEM
);
type T_MEM_CONTENT is (
MEM_CONTENT_BINARY,
MEM_CONTENT_DECIMAL,
MEM_CONTENT_HEX
);
function [docs]mem_FileExtension(Filename : string) return string;
impure function [docs]mem_ReadMemoryFile(
FileName : string;
MemoryLines : positive;
BitsPerMemoryLine : positive;
FORMAT : T_MEM_FILEFORMAT;
CONTENT : T_MEM_CONTENT := MEM_CONTENT_HEX
) return T_SLM;
end package;
package body mem is
function mem_FileExtension(FileName : string) return string is
begin
for i in FileName'high downto FileName'low loop
if (FileName(i) = '.') then
return str_toLower(FileName(i + 1 to FileName'high));
end if;
end loop;
return "";
end function;
procedure ReadHex(L : inout LINE; Value : out std_logic_vector; Good : out boolean) is
variable ok : boolean;
variable Char : character;
variable Digit : T_DIGIT_HEX;
constant DigitCount : positive := div_ceil(Value'length, 4);
variable slv : std_logic_vector((DigitCount * 4) - 1 downto 0);
variable Swapped : std_logic_vector((DigitCount * 4) - 1 downto 0);
begin
Good := TRUE;
for i in 0 to DigitCount - 1 loop
read(L, Char, ok);
if not ok then
Swapped := swap(slv, 4);
Value := Swapped(Value'length - 1 downto 0);
return;
end if;
Digit := to_digit_hex(Char);
if Digit = -1 then
Good := FALSE;
return;
end if;
slv(i * 4 + 3 downto i * 4) := to_slv(Digit, 4);
end loop;
Swapped := swap(slv, 4);
Value := Swapped(Value'length - 1 downto 0);
end procedure;
-- Reads a memory file and returns a 2D std_logic matrix
impure function mem_ReadMemoryFile(
FileName : string;
MemoryLines : positive;
BitsPerMemoryLine : positive;
FORMAT : T_MEM_FILEFORMAT;
CONTENT : T_MEM_CONTENT := MEM_CONTENT_HEX
) return T_SLM is
file FileHandle : TEXT open READ_MODE is FileName;
variable CurrentLine : LINE;
variable Good : boolean;
variable TempWord : std_logic_vector((div_ceil(BitsPerMemoryLine, 4) * 4) - 1 downto 0);
variable Result : T_SLM(MemoryLines - 1 downto 0, BitsPerMemoryLine - 1 downto 0);
begin
Result := (others => (others => ite(SIMULATION, 'U', '0')));
if FORMAT = MEM_FILEFORMAT_XILINX_MEM then
-- discard the first line of a mem file
readline(FileHandle, CurrentLine);
end if;
for i in 0 to MemoryLines - 1 loop
exit when endfile(FileHandle);
readline(FileHandle, CurrentLine);
-- report CurrentLine.all severity NOTE;
ReadHex(CurrentLine, TempWord, Good);
if not Good then
report "Error while reading memory file '" & FileName & "'." severity FAILURE;
return Result;
end if;
for j in 0 to BitsPerMemoryLine - 1 loop
Result(i, j) := TempWord(j);
end loop;
end loop;
return Result;
end function;
end package body;