— =============================================================================================================
— *
— * Copyright (c) Mike
— *
— * File Name: ram_4Kx16_sim.vhd
— *
— * Version: V1.0
— *
— * Release Date:
— *
— * Author(s): M.Freeman
— *
— * 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 := “bug24x24.ppm”;
save_ppm_image : boolean := True;
save_ppm_image_addr : natural := 1024;
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 := True;
save_pgm_image_addr : natural := 1600;
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 := 1600;
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); — 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;
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 );
else
highByte := conv_std_logic_vector( G, 8 );
mem( addr ) := highByte & lowByte;
addr := addr + 1;
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;