-- ============================================================================================================= -- * -- * Copyright (c) Mike -- * -- * File Name: ram_4Kx16_sim.vhd -- * -- * Version: V1.0 -- * -- * Release Date: -- * -- * Author(s): Mike -- * -- * Description: memory simulation 4K x 16bits -- * -- * Conditions of Use: THIS CODE IS COPYRIGHT AND IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND, INCLUDING, -- * BUT NOT LIMITED TO, ANY IMPLIED WARRANTY OF MERCHANTABILITY AND FITNESS FOR A -- * PARTICULAR PURPOSE. -- * -- * Notes: -- * -- ============================================================================================================= use std.textio.all; Library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; entity ram_4Kx16_sim is generic ( load_file_name : string := "code.dat"; save_file_name : string := "dump.dat"; load_ppm_image : boolean := True; load_ppm_image_addr : natural := 1024; load_ppm_image_name : string := "image.ppm"; save_ppm_image : boolean := True; save_ppm_image_addr : natural := 1600; save_ppm_image_rows : natural := 24; save_ppm_image_cols : natural := 24; save_ppm_image_name : string := "output.ppm"; load_pgm_image : boolean := False; load_pgm_image_addr : natural := 1024; load_pgm_image_name : string := "image.pgm"; save_pgm_image : boolean := False; save_pgm_image_addr : natural := 2176; save_pgm_image_rows : natural := 24; save_pgm_image_cols : natural := 24; save_pgm_image_name : string := "output.pgm"; save_pbm_image : boolean := False; save_pbm_image_addr : natural := 2048; save_pbm_image_rows : natural := 24; save_pbm_image_cols : natural := 24; save_pbm_image_name : string := "output.pbm"; debug_code_messages : boolean := False ); port ( CLK : in std_logic; ADDR_IN : in std_logic_vector( 11 downto 0 ); DATA_IN : in std_logic_vector( 15 downto 0 ); DATA_OUT : out std_logic_vector( 15 downto 0 ); EN : in std_logic; WE : in std_logic; DUMP : in std_logic ); end ram_4Kx16_sim; architecture ram_4Kx16_sim_arch of ram_4Kx16_sim is begin mem: process subtype word is std_logic_vector( 15 downto 0 ); type mem_array is array (natural range 4095 downto 0) of word; variable mem: mem_array; variable address : natural; variable L : line; variable saved : boolean := False; -- -- CONVERT NIBBLE TO CHAR -- function hex_to_char (nibble: std_logic_vector(3 downto 0)) return character is variable hex: character; begin case nibble is when "0000" => hex := '0'; when "0001" => hex := '1'; when "0010" => hex := '2'; when "0011" => hex := '3'; when "0100" => hex := '4'; when "0101" => hex := '5'; when "0110" => hex := '6'; when "0111" => hex := '7'; when "1000" => hex := '8'; when "1001" => hex := '9'; when "1010" => hex := 'A'; when "1011" => hex := 'B'; when "1100" => hex := 'C'; when "1101" => hex := 'D'; when "1110" => hex := 'E'; when "1111" => hex := 'F'; when others => hex := 'X'; end case; return hex; end hex_to_char; -- -- LOAD MEM -- procedure load_mem( mem: inout mem_array) is file load_data_file : text open READ_MODE is load_file_name; variable data_string : line; variable message_string : line; variable addr, data, count : natural; variable data_char : character; variable valid : boolean; variable bin_addr : std_logic_vector(11 downto 0); variable bin_data : std_logic_vector(15 downto 0); begin write( message_string, "ram initialization start" ); writeline( output, message_string ); for addr in 0 to 4095 loop mem( addr ) := "0000000000000000"; end loop; while not endfile( load_data_file ) loop readline( load_data_file, data_string ); read( data_string, addr, valid); -- address if (valid) then read( data_string, data_char ); -- space data := 0; count := 0; while count < 16 loop read( data_string, data_char ); if data_char /= ' ' then count := count + 1; -- count bits processed data := data + data; -- shift string if data_char = '1' then data :=data + 1; -- insert 1 if set end if; end if; end loop; bin_data := conv_std_logic_vector( data, 16); bin_addr := (conv_std_logic_vector( addr, 12)); mem( addr ) := bin_data; if (debug_code_messages) then write( message_string , hex_to_char( bin_addr(11 downto 8) ) ); write( message_string , hex_to_char( bin_addr(7 downto 4) ) ); write( message_string , hex_to_char( bin_addr(3 downto 0) ) ); write( message_string, ' ' ); write( message_string , hex_to_char( bin_data(3 downto 0) ) ); write( message_string , hex_to_char( bin_data(7 downto 4) ) ); write( message_string , hex_to_char( bin_data(11 downto 8) ) ); write( message_string , hex_to_char( bin_data(15 downto 12) ) ); writeline( output, message_string ); end if; end if; end loop; end load_mem; -- -- SAVE MEM -- procedure save_mem( mem: inout mem_array) is file save_data_file : text open WRITE_MODE is save_file_name; variable data_string : line; variable message_string : line; variable addr, data, count : natural; variable data_char : character; variable valid : boolean; variable bin_addr : std_logic_vector(11 downto 0); variable bin_data : std_logic_vector(15 downto 0); variable bin_data_bit : std_logic; begin write( message_string, "saving memory to dump file" ); writeline( output, message_string ); for addr in 0 to 500 loop bin_data := mem( addr ); if addr >= 10000 then write( data_string, addr ); elsif addr >= 1000 then write( data_string, 0 ); write( data_string, addr ); elsif addr >= 100 then write( data_string, string'("00") ); write( data_string, addr ); elsif addr >= 10 then write( data_string, string'("000") ); write( data_string, addr ); else write( data_string, string'("0000") ); write( data_string, addr ); end if; write( data_string, " " ); for count in 0 to 15 loop bin_data_bit := bin_data(15-count); if bin_data_bit = '1' then write( data_string, 1 ); else write( data_string, 0 ); end if; end loop; writeline( save_data_file, data_string ); end loop; end save_mem; -- -- LOAD PPM IMAGE -- procedure load_ppm( mem: inout mem_array) is file image_data_file : text open READ_MODE is load_ppm_image_name; variable data_string : line; variable message_string : line; variable addr, count, size, X, Y, R, G, B, MAX : natural; variable data_char : character; variable valid : boolean; variable bin_R : std_logic_vector(7 downto 0); variable bin_G : std_logic_vector(7 downto 0); variable bin_B : std_logic_vector(7 downto 0); begin write( message_string, "load PPM image data into memory" ); writeline( output, message_string ); addr := load_ppm_image_addr; readline( image_data_file, data_string ); read( data_string, data_char, valid); -- P3 if (valid and data_char = 'P') then readline( image_data_file, data_string ); read( data_string, data_char, valid); if (valid and data_char = '#') -- Comment line then readline( image_data_file, data_string ); -- image size X read( data_string, X, valid); write( message_string, "X = " ); write( message_string, X ); if (valid) then read( data_string, Y, valid); -- image size Y write( message_string, " Y = " ); write( message_string, Y ); writeline( output, message_string ); size := (X * Y); write( message_string , "image size = "); write( message_string , size); writeline( output, message_string ); readline( image_data_file, data_string ); -- max value read( data_string, MAX, valid); if (valid) then write( message_string, "MAX = " ); write( message_string, MAX ); writeline( output, message_string ); count := 0; addr := load_ppm_image_addr; while not endfile( image_data_file ) loop readline( image_data_file, data_string ); read( data_string, R, valid); bin_R := conv_std_logic_vector( R, 8 ); read( data_string, G, valid); if (not valid) then readline( image_data_file, data_string ); read( data_string, G, valid); end if; bin_G := conv_std_logic_vector( G, 8 ); read( data_string, B, valid); if (not valid) then readline( image_data_file, data_string ); read( data_string, B, valid); end if; bin_B := conv_std_logic_vector( B, 8 ); mem( addr ) := bin_R(7 DOWNTO 3) & bin_G(7 DOWNTO 2) & bin_B(7 DOWNTO 3); addr := addr + 1; count := count + 1; end loop; if (count = size) then write( message_string , "Pass : "); else write( message_string , "Fail : "); end if; write( message_string , count); write( message_string , " "); write( message_string , size); writeline( output, message_string ); end if; end if; end if; end if; write( message_string, "load PPM image data into memory finished" ); writeline( output, message_string ); end load_ppm; -- -- SAVE PPM IMAGE -- procedure save_ppm( mem: inout mem_array) is file image_data_file : text open WRITE_MODE is save_ppm_image_name; variable data_string : line; variable message_string : line; variable addr, count : natural; variable data_char : character; variable valid : boolean; variable bin_data : std_logic_vector(15 downto 0); begin write( message_string, "save PPM image data to file" ); writeline( output, message_string ); addr := save_ppm_image_addr; write( data_string, "P3"); writeline( image_data_file, data_string); write( data_string, "# MEM GENERATED PPM IMAGE"); writeline( image_data_file, data_string); write( data_string , save_ppm_image_rows); write( data_string , ' '); write( data_string , save_ppm_image_cols); writeline( image_data_file, data_string ); write( data_string, "255"); writeline( image_data_file, data_string ); for count in 0 to (save_ppm_image_rows * save_ppm_image_cols)-1 loop bin_data := mem( addr ); addr := addr + 1; write( data_string , ' '); write( data_string , conv_integer( bin_data(15 downto 11) & "000" ) ); write( data_string , ' '); write( data_string , conv_integer( bin_data(10 downto 5) & "00" ) ); write( data_string , ' '); write( data_string , conv_integer( bin_data(4 downto 0) & "000" ) ); writeline( image_data_file, data_string ); end loop; write( message_string, "save PPM image data to file finished" ); writeline( output, message_string ); end save_ppm; -- -- LOAD PGM IMAGE -- procedure load_pgm( mem: inout mem_array) is file image_data_file : text open READ_MODE is load_pgm_image_name; variable data_string : line; variable message_string : line; variable addr, count, size, X, Y, G, MAX : natural; variable data_char : character; variable valid, low : boolean; variable lowByte : std_logic_vector(7 downto 0); variable highByte : std_logic_vector(7 downto 0); begin write( message_string, "load PGM image data into memory" ); writeline( output, message_string ); addr := load_pgm_image_addr; readline( image_data_file, data_string ); read( data_string, data_char, valid); -- P2 if (valid and data_char = 'P') then readline( image_data_file, data_string ); read( data_string, data_char, valid); if (valid and data_char = '#') -- Comment line then readline( image_data_file, data_string ); -- image size X read( data_string, X, valid); write( message_string, "X = " ); write( message_string, X ); if (valid) then read( data_string, Y, valid); -- image size Y write( message_string, " Y = " ); write( message_string, Y ); writeline( output, message_string ); size := (X * Y); write( message_string , "image size = "); write( message_string , size); writeline( output, message_string ); readline( image_data_file, data_string ); -- max value read( data_string, MAX, valid); if (valid) then write( message_string, "MAX = " ); write( message_string, MAX ); writeline( output, message_string ); count := 0; low := True; addr := load_pgm_image_addr; while not endfile( image_data_file ) loop readline( image_data_file, data_string ); read( data_string, G, valid); if low then lowByte := conv_std_logic_vector( G, 8 ); low := False; else highByte := conv_std_logic_vector( G, 8 ); mem( addr ) := highByte & lowByte; addr := addr + 1; low := True; end if; count := count + 1; end loop; if (count = size) then write( message_string , "Pass : "); else write( message_string , "Fail : "); end if; write( message_string , count); write( message_string , " "); write( message_string , size); writeline( output, message_string ); end if; end if; end if; end if; write( message_string, "load PPM image data into memory finished" ); writeline( output, message_string ); end load_pgm; -- -- SAVE PGM IMAGE -- procedure save_pgm( mem: inout mem_array) is file image_data_file : text open WRITE_MODE is save_pgm_image_name; variable data_string : line; variable message_string : line; variable addr, count, size, total, pixel : natural; variable data_char : character; variable valid : boolean; variable bin_data : std_logic_vector(15 downto 0); variable bin_addr : std_logic_vector(11 downto 0); begin write( message_string, "save PGM image data to file" ); writeline( output, message_string ); addr := save_pgm_image_addr; write( data_string, "P2"); writeline( image_data_file, data_string); write( data_string, "# MEM GENERATED PBM IMAGE"); writeline( image_data_file, data_string); write( data_string , save_pgm_image_rows); write( data_string , ' '); write( data_string , save_pgm_image_cols); writeline( image_data_file, data_string ); write( data_string, "255"); writeline( image_data_file, data_string ); size := (save_pgm_image_rows * save_pgm_image_cols); total := 0; for count in 0 to ((save_pgm_image_rows * save_pgm_image_cols)-1)/2 loop bin_addr := (conv_std_logic_vector( addr, 12)); bin_data := mem( addr ); write( message_string , hex_to_char( bin_addr(11 downto 8) ) ); write( message_string , hex_to_char( bin_addr(7 downto 4) ) ); write( message_string , hex_to_char( bin_addr(3 downto 0) ) ); write( message_string, ' ' ); write( message_string , hex_to_char( bin_data(15 downto 12) ) ); write( message_string , hex_to_char( bin_data(11 downto 8) ) ); write( message_string , hex_to_char( bin_data(7 downto 4) ) ); write( message_string , hex_to_char( bin_data(3 downto 0) ) ); writeline( output, message_string ); write( data_string , conv_integer( bin_data(7 DOWNTO 0) ) ); write( data_string , ' '); total := total +1; if total <= size then write( data_string , conv_integer( bin_data(15 DOWNTO 8) ) ); end if; writeline( image_data_file, data_string ); addr := addr + 1; total := total +1; end loop; write( message_string, "save PGM image data to file finished" ); writeline( output, message_string ); end save_pgm; -- -- SAVE PBM IMAGE -- procedure save_pbm( mem: inout mem_array) is file image_data_file : text open WRITE_MODE is save_pbm_image_name; variable data_string : line; variable message_string : line; variable addr, count, size, total, pixel : natural; variable data_char : character; variable valid : boolean; variable bin_data : std_logic_vector(15 downto 0); begin write( message_string, "save PBM image data to file" ); writeline( output, message_string ); addr := save_pbm_image_addr; write( data_string, "P1"); writeline( image_data_file, data_string); write( data_string, "# MEM GENERATED PBM IMAGE"); writeline( image_data_file, data_string); write( data_string , save_pbm_image_rows); write( data_string , ' '); write( data_string , save_pbm_image_cols); writeline( image_data_file, data_string ); size := (save_pbm_image_rows * save_pbm_image_cols); total := 0; for count in 0 to ((save_pbm_image_rows * save_pbm_image_cols)-1)/16 loop bin_data := mem( addr ); for pixel in 0 to 15 loop if total /= size then write( data_string , conv_integer( bin_data(pixel) ) ); end if; total := total +1; end loop; writeline( image_data_file, data_string ); addr := addr + 1; end loop; write( message_string, "save PBM image data to file finished" ); writeline( output, message_string ); end save_pbm; -- -- MAIN -- begin load_mem( mem ); if load_ppm_image then load_ppm( mem ); end if; if load_pgm_image then load_pgm( mem ); end if; loop if (EN = '1') then address := conv_integer( ADDR_IN ); if (WE = '1') then mem( address ) := DATA_IN; end if; DATA_OUT <= mem( address ); end if; if (DUMP = '1' and not saved) then save_mem( mem ); saved := True; if save_ppm_image then save_ppm( mem ); end if; if save_pgm_image then save_pgm( mem ); end if; if save_pbm_image then save_pbm( mem ); end if; end if; wait on clk; end loop; end process; end ram_4Kx16_sim_arch;