---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
-- TITLE: Random Access Memory
|
-- TITLE: Random Access Memory
|
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
|
-- DATE CREATED: 4/21/01
|
-- DATE CREATED: 4/21/01
|
-- FILENAME: ram.vhd
|
-- FILENAME: ram.vhd
|
-- PROJECT: Plasma CPU core
|
-- PROJECT: Plasma CPU core
|
-- COPYRIGHT: Software placed into the public domain by the author.
|
-- COPYRIGHT: Software placed into the public domain by the author.
|
-- Software 'as is' without warranty. Author liable for nothing.
|
-- Software 'as is' without warranty. Author liable for nothing.
|
-- DESCRIPTION:
|
-- DESCRIPTION:
|
-- Implements the RAM, reads the executable from either "code.txt",
|
-- Implements the RAM, reads the executable from either "code.txt",
|
-- or for Altera "code[0-3].hex".
|
-- or for Altera "code[0-3].hex".
|
-- Modified from "The Designer's Guide to VHDL" by Peter J. Ashenden
|
-- Modified from "The Designer's Guide to VHDL" by Peter J. Ashenden
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_misc.all;
|
use ieee.std_logic_misc.all;
|
use ieee.std_logic_arith.all;
|
use ieee.std_logic_arith.all;
|
use ieee.std_logic_textio.all;
|
use ieee.std_logic_textio.all;
|
use std.textio.all;
|
use std.textio.all;
|
|
|
use ieee.std_logic_unsigned.all;
|
use ieee.std_logic_unsigned.all;
|
use work.mlite_pack.all;
|
use work.mlite_pack.all;
|
|
|
entity ram is
|
entity ram is
|
generic(memory_type : string := "GENERIC");
|
generic(memory_type : string := "GENERIC");
|
port(clk : in std_logic;
|
port(clk : in std_logic;
|
mem_byte_sel : in std_logic_vector(3 downto 0);
|
mem_byte_sel : in std_logic_vector(3 downto 0);
|
mem_write : in std_logic;
|
mem_write : in std_logic;
|
mem_address : in std_logic_vector(31 downto 0);
|
mem_address : in std_logic_vector(31 downto 0);
|
mem_data : inout std_logic_vector(31 downto 0));
|
mem_data_w : in std_logic_vector(31 downto 0);
|
|
mem_data_r : out std_logic_vector(31 downto 0));
|
end; --entity ram
|
end; --entity ram
|
|
|
architecture logic of ram is
|
architecture logic of ram is
|
|
constant ADDRESS_WIDTH : natural := 13;
|
|
signal clk_inv : std_logic;
|
signal mem_sel : std_logic;
|
signal mem_sel : std_logic;
|
signal read_enable : std_logic;
|
signal read_enable : std_logic;
|
signal write_byte_enable : std_logic_vector(3 downto 0);
|
signal write_byte_enable : std_logic_vector(3 downto 0);
|
begin
|
begin
|
|
clk_inv <= not clk;
|
mem_sel <= '1' when mem_address(30 downto 16) = ZERO(30 downto 16) else
|
mem_sel <= '1' when mem_address(30 downto 16) = ZERO(30 downto 16) else
|
'0';
|
'0';
|
read_enable <= mem_sel and not mem_write;
|
read_enable <= mem_sel and not mem_write;
|
write_byte_enable <= mem_byte_sel when mem_sel = '1' else
|
write_byte_enable <= mem_byte_sel when mem_sel = '1' else
|
"0000";
|
"0000";
|
|
|
generic_ram:
|
generic_ram:
|
if memory_type = "GENERIC" generate
|
if memory_type = "GENERIC" generate
|
ram_proc: process(clk, mem_byte_sel, mem_write,
|
ram_proc: process(clk, mem_byte_sel, mem_write,
|
mem_address, mem_data, mem_sel)
|
mem_address, mem_data_w, mem_sel)
|
|
variable mem_size : natural := 8192;
|
variable data : std_logic_vector(31 downto 0);
|
variable data : std_logic_vector(31 downto 0);
|
subtype word is std_logic_vector(mem_data'length-1 downto 0);
|
subtype word is std_logic_vector(mem_data_w'length-1 downto 0);
|
type storage_array is
|
type storage_array is
|
array(natural range 0 to 8191) of word;
|
array(natural range 0 to mem_size-1) of word;
|
variable storage : storage_array;
|
variable storage : storage_array;
|
variable index : natural := 0;
|
variable index : natural := 0;
|
file load_file : text is in "code.txt";
|
file load_file : text is in "code.txt";
|
variable hex_file_line : line;
|
variable hex_file_line : line;
|
begin
|
begin
|
--load in the ram executable image
|
--load in the ram executable image
|
if index = 0 then
|
if index = 0 then
|
while not endfile(load_file) loop
|
while not endfile(load_file) loop
|
|
--The following two lines had to be commented out for synthesis
|
readline(load_file, hex_file_line);
|
readline(load_file, hex_file_line);
|
hread(hex_file_line, data);
|
hread(hex_file_line, data);
|
storage(index) := data;
|
storage(index) := data;
|
index := index + 1;
|
index := index + 1;
|
end loop;
|
end loop;
|
--assert false report "done reading code" severity note;
|
--assert false report "done reading code" severity note;
|
end if;
|
end if;
|
|
|
index := conv_integer(mem_address(mem_address'length-1 downto 2));
|
index := conv_integer(mem_address(ADDRESS_WIDTH-1 downto 2));
|
data := storage(index);
|
data := storage(index);
|
|
|
if mem_sel = '1' then
|
if mem_sel = '1' then
|
if mem_write = '0' then
|
if mem_write = '0' then
|
mem_data <= data;
|
mem_data_r <= data;
|
end if;
|
end if;
|
if mem_byte_sel(0) = '1' then
|
if mem_byte_sel(0) = '1' then
|
data(7 downto 0) := mem_data(7 downto 0);
|
data(7 downto 0) := mem_data_w(7 downto 0);
|
end if;
|
end if;
|
if mem_byte_sel(1) = '1' then
|
if mem_byte_sel(1) = '1' then
|
data(15 downto 8) := mem_data(15 downto 8);
|
data(15 downto 8) := mem_data_w(15 downto 8);
|
end if;
|
end if;
|
if mem_byte_sel(2) = '1' then
|
if mem_byte_sel(2) = '1' then
|
data(23 downto 16) := mem_data(23 downto 16);
|
data(23 downto 16) := mem_data_w(23 downto 16);
|
end if;
|
end if;
|
if mem_byte_sel(3) = '1' then
|
if mem_byte_sel(3) = '1' then
|
data(31 downto 24) := mem_data(31 downto 24);
|
data(31 downto 24) := mem_data_w(31 downto 24);
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
if rising_edge(clk) then
|
if rising_edge(clk) then
|
if mem_write = '1' then
|
if mem_write = '1' then
|
storage(index) := data;
|
storage(index) := data;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
end generate; --generic_ram
|
end generate; --generic_ram
|
|
|
|
|
altera_ram:
|
altera_ram:
|
if memory_type = "ALTERA" generate
|
if memory_type = "ALTERA" generate
|
lpm_ram_io_component0 : lpm_ram_io
|
--Quartus II does not allow asynchronous RAM to be initialized
|
|
--since the RAM may see glitches on the write enable during powerup.
|
|
--Making lpm_address_control="REGISTERED" makes the RAM synchronous
|
|
--but then the reads are delayed by a clock cycle.
|
|
--Inverting the RAM clock appears to solve the clock cycle delay problem.
|
|
lpm_ram_io_component0 : lpm_ram_dq
|
GENERIC MAP (
|
GENERIC MAP (
|
intended_device_family => "UNUSED",
|
intended_device_family => "UNUSED",
|
lpm_width => 8,
|
lpm_width => 8,
|
lpm_widthad => 11,
|
lpm_widthad => ADDRESS_WIDTH-2,
|
lpm_indata => "REGISTERED",
|
lpm_indata => "REGISTERED",
|
lpm_address_control => "UNREGISTERED",
|
lpm_address_control => "REGISTERED",
|
lpm_outdata => "UNREGISTERED",
|
lpm_outdata => "UNREGISTERED",
|
lpm_file => "code0.hex",
|
lpm_file => "code0.hex",
|
use_eab => "ON",
|
use_eab => "ON",
|
lpm_type => "LPM_RAM_DQ")
|
lpm_type => "LPM_RAM_DQ")
|
PORT MAP (
|
PORT MAP (
|
outenab => read_enable,
|
data => mem_data_w(31 downto 24),
|
address => mem_address(12 downto 2),
|
address => mem_address(ADDRESS_WIDTH-1 downto 2),
|
inclock => clk,
|
inclock => clk_inv,
|
we => write_byte_enable(3),
|
we => write_byte_enable(3),
|
dio => mem_data(31 downto 24));
|
q => mem_data_r(31 downto 24));
|
|
|
lpm_ram_io_component1 : lpm_ram_io
|
lpm_ram_io_component1 : lpm_ram_dq
|
GENERIC MAP (
|
GENERIC MAP (
|
intended_device_family => "UNUSED",
|
intended_device_family => "UNUSED",
|
lpm_width => 8,
|
lpm_width => 8,
|
lpm_widthad => 11,
|
lpm_widthad => ADDRESS_WIDTH-2,
|
lpm_indata => "REGISTERED",
|
lpm_indata => "REGISTERED",
|
lpm_address_control => "UNREGISTERED",
|
lpm_address_control => "REGISTERED",
|
lpm_outdata => "UNREGISTERED",
|
lpm_outdata => "UNREGISTERED",
|
lpm_file => "code1.hex",
|
lpm_file => "code1.hex",
|
use_eab => "ON",
|
use_eab => "ON",
|
lpm_type => "LPM_RAM_DQ")
|
lpm_type => "LPM_RAM_DQ")
|
PORT MAP (
|
PORT MAP (
|
outenab => read_enable,
|
data => mem_data_w(23 downto 16),
|
address => mem_address(12 downto 2),
|
address => mem_address(ADDRESS_WIDTH-1 downto 2),
|
inclock => clk,
|
inclock => clk_inv,
|
we => write_byte_enable(2),
|
we => write_byte_enable(2),
|
dio => mem_data(23 downto 16));
|
q => mem_data_r(23 downto 16));
|
|
|
lpm_ram_io_component2 : lpm_ram_io
|
lpm_ram_io_component2 : lpm_ram_dq
|
GENERIC MAP (
|
GENERIC MAP (
|
intended_device_family => "UNUSED",
|
intended_device_family => "UNUSED",
|
lpm_width => 8,
|
lpm_width => 8,
|
lpm_widthad => 11,
|
lpm_widthad => ADDRESS_WIDTH-2,
|
lpm_indata => "REGISTERED",
|
lpm_indata => "REGISTERED",
|
lpm_address_control => "UNREGISTERED",
|
lpm_address_control => "REGISTERED",
|
lpm_outdata => "UNREGISTERED",
|
lpm_outdata => "UNREGISTERED",
|
lpm_file => "code2.hex",
|
lpm_file => "code2.hex",
|
use_eab => "ON",
|
use_eab => "ON",
|
lpm_type => "LPM_RAM_DQ")
|
lpm_type => "LPM_RAM_DQ")
|
PORT MAP (
|
PORT MAP (
|
outenab => read_enable,
|
data => mem_data_w(15 downto 8),
|
address => mem_address(12 downto 2),
|
address => mem_address(ADDRESS_WIDTH-1 downto 2),
|
inclock => clk,
|
inclock => clk_inv,
|
we => write_byte_enable(1),
|
we => write_byte_enable(1),
|
dio => mem_data(15 downto 8));
|
q => mem_data_r(15 downto 8));
|
|
|
lpm_ram_io_component3 : lpm_ram_io
|
lpm_ram_io_component3 : lpm_ram_dq
|
GENERIC MAP (
|
GENERIC MAP (
|
intended_device_family => "UNUSED",
|
intended_device_family => "UNUSED",
|
lpm_width => 8,
|
lpm_width => 8,
|
lpm_widthad => 11,
|
lpm_widthad => ADDRESS_WIDTH-2,
|
lpm_indata => "REGISTERED",
|
lpm_indata => "REGISTERED",
|
lpm_address_control => "UNREGISTERED",
|
lpm_address_control => "REGISTERED",
|
lpm_outdata => "UNREGISTERED",
|
lpm_outdata => "UNREGISTERED",
|
lpm_file => "code3.hex",
|
lpm_file => "code3.hex",
|
use_eab => "ON",
|
use_eab => "ON",
|
lpm_type => "LPM_RAM_DQ")
|
lpm_type => "LPM_RAM_DQ")
|
PORT MAP (
|
PORT MAP (
|
outenab => read_enable,
|
data => mem_data_w(7 downto 0),
|
address => mem_address(12 downto 2),
|
address => mem_address(ADDRESS_WIDTH-1 downto 2),
|
inclock => clk,
|
inclock => clk_inv,
|
we => write_byte_enable(0),
|
we => write_byte_enable(0),
|
dio => mem_data(7 downto 0));
|
q => mem_data_r(7 downto 0));
|
|
|
end generate; --altera_ram
|
end generate; --altera_ram
|
|
|
end; --architecture logic
|
end; --architecture logic
|
|
|
|
|