------------------------------------------------------------------------------ -- Model : 8051 Behavioral Model, -- Supporting Package of Procedures -- -- File : pack8051.vhd -- -- Author : Michael Mayer, -- Department of Electrical Engineering -- University of Missouri - Rolla -- -- Inspired By : Sundar Subbarayan -- UC Riverside CS 122a (lab 3) -- Professor: Dr.Frank Vahid -- 17th January 1996 -- -- Date Started : September 15, 1997 -- -- Limitations : -- -- Revisions : -- -- REV DATE Description -- ----- -------- _____________________________________ -- 2.0 11/04/97 Initial implementation of types for -- memory, functions or, and, xor, not -- and procedure load_program -- -- 2.1 11/12/97 Changed memory to lo and hi mem's -- -- 2.2 11/13/97 Added type for states for machine cycles -- -- ------------------------------------------------------------------------------ LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.std_logic_arith.ALL; USE std.textio.ALL; PACKAGE pack8051 IS SUBTYPE bvec IS UNSIGNED(7 DOWNTO 0); SUBTYPE wvec IS UNSIGNED(15 DOWNTO 0); SUBTYPE smallint IS INTEGER RANGE 0 TO 255; TYPE program_mem_T IS ARRAY(0 TO 65535) OF bvec; TYPE data_lomem_T IS ARRAY(0 TO 127) OF bvec; TYPE data_himem_T IS ARRAY(128 TO 255) OF bvec; -- The following type is used to declare if direct or indirect memory -- access is being used and, hence, which segment of upper memory -- is to be used. TYPE access_type IS (direct, indirect); -- The following type is used to break up the machine cycle -- into 6 states, with 2 pulses for each state TYPE machine_cycle_states IS (init, s1p1, s1p2, s2p1, s2p2, s3p1, s3p2, s4p1, s4p2, s5p1, s5p2, s6p1, s6p2); FUNCTION to_int(ch : CHARACTER) RETURN INTEGER; FUNCTION "or"(l,r : unsigned) RETURN unsigned; FUNCTION "and"(l,r : unsigned) RETURN unsigned; FUNCTION "xor"(l,r : unsigned) RETURN unsigned; FUNCTION "not"(r : unsigned) RETURN unsigned; FUNCTION conv_signed_to_int(arg : bvec) RETURN INTEGER; FUNCTION to_high_imped(arg : bvec) RETURN bvec; FUNCTION inc(state : machine_cycle_states) RETURN machine_cycle_states; PROCEDURE load_program( CONSTANT program_filename : IN string; VARIABLE pmem : OUT program_mem_T -- the program memory ); END pack8051; PACKAGE BODY pack8051 IS ------------------------------------------------------------------------ -- to_int -- -- A function that converts a character to an integer (0-9,A-F) ------------------------------------------------------------------------ FUNCTION to_int( CONSTANT ch : CHARACTER ) RETURN INTEGER IS VARIABLE result : INTEGER := 0; BEGIN CASE ch IS WHEN '0' => result := 16#0#; WHEN '1' => result := 16#1#; WHEN '2' => result := 16#2#; WHEN '3' => result := 16#3#; WHEN '4' => result := 16#4#; WHEN '5' => result := 16#5#; WHEN '6' => result := 16#6#; WHEN '7' => result := 16#7#; WHEN '8' => result := 16#8#; WHEN '9' => result := 16#9#; WHEN 'A' => result := 16#A#; WHEN 'B' => result := 16#B#; WHEN 'C' => result := 16#C#; WHEN 'D' => result := 16#D#; WHEN 'E' => result := 16#E#; WHEN 'F' => result := 16#F#; WHEN OTHERS => result := 16#0#; END CASE; RETURN result; END FUNCTION to_int; ------------------------------------------------------------------------ FUNCTION "or"(l,r : unsigned) RETURN unsigned IS BEGIN RETURN unsigned(std_logic_vector(l) OR std_logic_vector(r)); END FUNCTION "or"; ------------------------------------------------------------------------ FUNCTION "and"(l,r : unsigned) RETURN unsigned IS BEGIN RETURN unsigned(std_logic_vector(l) AND std_logic_vector(r)); END FUNCTION "and"; ------------------------------------------------------------------------ FUNCTION "xor"(l,r : unsigned) RETURN unsigned IS BEGIN RETURN unsigned(std_logic_vector(l) XOR std_logic_vector(r)); END FUNCTION "xor"; ------------------------------------------------------------------------ FUNCTION "not"(r : unsigned) RETURN unsigned IS BEGIN RETURN unsigned(NOT std_logic_vector(r)); END FUNCTION "not"; ------------------------------------------------------------------------ FUNCTION conv_signed_to_int(arg : bvec) RETURN INTEGER IS VARIABLE result : INTEGER; BEGIN IF arg(7) = '1' THEN -- convert to positive result := -1 * conv_integer(NOT(arg) + 1); ELSE result := conv_integer(arg); END IF; RETURN result; END FUNCTION conv_signed_to_int; ------------------------------------------------------------------------ FUNCTION to_high_imped(arg : bvec) RETURN bvec IS VARIABLE result : bvec; BEGIN FOR k in arg'RANGE LOOP CASE arg(k) IS WHEN '0' => result(k) := 'L'; WHEN '1' => result(k) := 'H'; WHEN 'L' => result(k) := 'L'; WHEN 'H' => result(k) := 'H'; WHEN OTHERS => result(k) := 'Z'; END CASE; END LOOP; RETURN(result); END FUNCTION to_high_imped; ------------------------------------------------------------------------ FUNCTION inc(state : machine_cycle_states) RETURN machine_cycle_states IS VARIABLE result : machine_cycle_states; BEGIN CASE state IS WHEN init => result := s1p1; WHEN s1p1 => result := s1p2; WHEN s1p2 => result := s2p1; WHEN s2p1 => result := s2p2; WHEN s2p2 => result := s3p1; WHEN s3p1 => result := s3p2; WHEN s3p2 => result := s4p1; WHEN s4p1 => result := s4p2; WHEN s4p2 => result := s5p1; WHEN s5p1 => result := s5p2; WHEN s5p2 => result := s6p1; WHEN s6p1 => result := s6p2; WHEN s6p2 => result := s1p1; END CASE; RETURN result; END FUNCTION inc; PROCEDURE load_program( CONSTANT program_filename : IN string; VARIABLE pmem : OUT program_mem_T -- the program memory ) IS FILE progfile : TEXT OPEN read_mode IS program_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); pmem(address_offset*16 + address + byte_no) := conv_unsigned(data,8); 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_program; END pack8051;