-- ------------------------------------------------ -- Model : SRAM loaded with Hex Format -- -- Purpose : This SRAM model was adapted from Andre' -- Klindworth's SRAM model. The load has -- been replaced to use Intel hex format -- files. -- -- Author : Michael Mayer (mrmayer@computer.org), -- Dr. Hardy J. Pottinger -- Department of Electrical Engineering -- University of Missouri - Rolla -- -- Inspired By : -- (C) Andre' Klindworth -- Dept. of Computer Science -- University of Hamburg -- Vogt-Koelln-Str. 30 -- 22527 Hamburg -- klindwor@informatik.uni-hamburg.de -- -- This VHDL code may be freely copied as long as the copyright note isn't -- removed from its header. Full affiliation of anybody modifying this file -- shall be added to the header prior to further distribution. -- The download procedure originates from DLX memory-behaviour.vhdl: -- Copyright (C) 1993, Peter J. Ashenden -- Mail: Dept. Computer Science -- University of Adelaide, SA 5005, Australia -- e-mail: petera@cs.adelaide.edu.au -- -- -- Date : September 15, 1997 -- -- Limitations : -- ------------------------------------------------ LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.std_logic_arith.ALL; USE ieee.std_logic_textio.ALL; USE ieee.std_logic_unsigned.ALL; USE work.pack8051.to_int; USE std.textio.ALL; ENTITY nvsram IS GENERIC ( download_filename : STRING; -- filename for RAM initial contents -- File must be Hex format -- Configuring RAM size size: INTEGER := 65536; -- number of memory words addr_width: INTEGER := 16; -- number of address bits width: INTEGER := 8; -- number of bits per memory word t_rc : TIME := 70 ns; -- read cycle time t_oe : TIME := 35 ns; -- oe to output valid t_ce : TIME := 70 ns; -- ce to output valid t_wc : TIME := 70 ns; -- write cycle time t_ds : TIME := 30 ns; -- data setup time t_dh1 : TIME := 7 ns -- data hold time ); PORT ( addr : IN std_logic_vector(addr_width-1 DOWNTO 0); -- address data : INOUT std_logic_vector(width-1 DOWNTO 0); -- data in/out ce_N : IN std_logic; -- chip enable we_N : IN std_logic; -- write enable oe_N : IN std_logic -- output enable ); END ENTITY nvsram; ARCHITECTURE behav OF nvsram IS SIGNAL do_write, do_read : std_logic; -- flags to command the memory process -- to perform a given action (rising edge sensitive) SIGNAL read_data : std_logic_vector(width-1 DOWNTO 0); -- the data read from memory process BEGIN do_write <= '1' WHEN (ce_N='0' AND we_N='0') ELSE '0'; do_read <= '1' WHEN (ce_N='0' AND oe_N='0') ELSE '0'; data <= read_data WHEN do_read='1' ELSE (OTHERS => 'Z'); memory: PROCESS (do_write, do_read) IS CONSTANT low_address: natural := 0; CONSTANT high_address: natural := size -1; TYPE memory_array IS ARRAY (natural RANGE low_address TO high_address) OF std_logic_vector(width-1 DOWNTO 0); VARIABLE mem: memory_array; VARIABLE address : natural; VARIABLE write_data: std_logic_vector(width-1 DOWNTO 0); VARIABLE initialized : BOOLEAN := FALSE; PROCEDURE load_hex (mem: INOUT memory_array; download_filename: IN string) IS FILE progfile : TEXT OPEN read_mode IS download_filename; VARIABLE L : LINE; VARIABLE ch : CHARACTER; VARIABLE rec_type : CHARACTER; VARIABLE sum : INTEGER; VARIABLE dig : INTEGER; VARIABLE data : INTEGER; VARIABLE numb_of_bytes : INTEGER; VARIABLE address : INTEGER; VARIABLE address_offset : INTEGER; VARIABLE end_of_data : BOOLEAN; VARIABLE checksum : INTEGER; VARIABLE line_num : INTEGER; BEGIN line_num := 0; address_offset := 0; end_of_data := FALSE; WHILE NOT (endfile(progfile) OR end_of_data) LOOP -- Reset the variables for the line sum := 0; address := 0; line_num := line_num + 1; readline(progfile, L); -- Read in the : character read(L, ch); IF ch /= ':' THEN NEXT; -- go to next loop END IF; -- Read in the number of bytes read(L, ch); -- msb dig := to_int(ch); sum := sum + dig; read(L, ch); -- lsb sum := sum + to_int(ch); numb_of_bytes := dig*16 + to_int(ch); -- Read in the address FOR k IN 3 DOWNTO 0 LOOP read(L, ch); dig := to_int(ch); sum := sum + dig; address := address + dig * 16**k; END LOOP; -- Read in the record type read(L,ch); sum := sum + to_int(ch); ASSERT ch = '0' REPORT "Illegal Record Type - Bad Program File" & " on line " & INTEGER'IMAGE(line_num); read(L,rec_type); sum := sum + to_int(rec_type); -- If it is a line of all zeros, then it is the end of data. IF (numb_of_bytes = 0) AND (address = 0)THEN end_of_data := TRUE; -- If it is normal data, then read in all of the bytes to program_mem ELSIF rec_type = '0' THEN -- It has normal data FOR byte_no IN 0 TO numb_of_bytes-1 LOOP read(L,ch); dig := to_int(ch); sum := sum + dig; read(L,ch); sum := sum + to_int(ch); data := dig*16 + to_int(ch); mem(address_offset*16 + address + byte_no) := conv_std_logic_vector(data,width); END LOOP; -- If it is an end of file record, then set end_of_data true ELSIF rec_type = '1' THEN -- it is an end of file record end_of_data := TRUE; ELSIF rec_type = '2' THEN address_offset := 0; FOR k IN 3 DOWNTO 0 LOOP read(L, ch); dig := to_int(ch); sum := sum + dig; address_offset := address_offset + dig*16**k; END LOOP; END IF; -- get the checksum read(L,ch); dig := to_int(ch); read(L,ch); checksum := dig * 16 + to_int(ch); --ASSERT (checksum + sum MOD 256) = 0; -- REPORT "Checksum Error"& " on line " & INTEGER'IMAGE(line_num); END LOOP; END PROCEDURE load_hex; BEGIN -- process memory IF NOT initialized THEN load_hex(mem,download_filename); initialized := TRUE; END IF; IF rising_edge(do_write) THEN mem(CONV_INTEGER(to_X01(addr))) := to_X01(data); ELSIF rising_edge(do_read) THEN read_data <= mem(CONV_INTEGER(to_X01(addr))); END IF; END PROCESS memory; END ARCHITECTURE behav;