Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
158 lines (137 sloc) 7.96 KB
-- #################################################################################################
-- # << NEO430 - Instruction memory ("IMEM") >> #
-- # ********************************************************************************************* #
-- # This memory includes the in-place executable image of the application. See the #
-- # processor's documentary to get more information. #
-- # Note: IMEM is split up into two 8-bit memories - some EDA tools have problems to synthesize #
-- # a pre-initialized 16-bit memory with byte-enable signals. #
-- # ********************************************************************************************* #
-- # This file is part of the NEO430 Processor project: https://github.com/stnolting/neo430 #
-- # Copyright by Stephan Nolting: stnolting@gmail.com #
-- # #
-- # This source file may be used and distributed without restriction provided that this copyright #
-- # statement is not removed from the file and that any derivative work contains the original #
-- # copyright notice and the associated disclaimer. #
-- # #
-- # This source file is free software; you can redistribute it and/or modify it under the terms #
-- # of the GNU Lesser General Public License as published by the Free Software Foundation, #
-- # either version 3 of the License, or (at your option) any later version. #
-- # #
-- # This source is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; #
-- # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. #
-- # See the GNU Lesser General Public License for more details. #
-- # #
-- # You should have received a copy of the GNU Lesser General Public License along with this #
-- # source; if not, download it from https://www.gnu.org/licenses/lgpl-3.0.en.html #
-- # ********************************************************************************************* #
-- # Stephan Nolting, Hannover, Germany 29.04.2019 #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library neo430;
use neo430.neo430_package.all;
use neo430.neo430_application_image.all; -- this file is generated by the image generator
entity neo430_imem is
generic (
IMEM_SIZE : natural := 4*1024; -- internal IMEM size in bytes
IMEM_AS_ROM : boolean := false; -- implement IMEM as read-only memory?
BOOTLD_USE : boolean := true -- implement and use bootloader?
);
port (
clk_i : in std_ulogic; -- global clock line
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic_vector(01 downto 0); -- write enable
upen_i : in std_ulogic; -- update enable
addr_i : in std_ulogic_vector(15 downto 0); -- address
data_i : in std_ulogic_vector(15 downto 0); -- data in
data_o : out std_ulogic_vector(15 downto 0) -- data out
);
end neo430_imem;
architecture neo430_imem_rtl of neo430_imem is
-- ROM types --
type imem_file8_t is array (0 to IMEM_SIZE/2-1) of std_ulogic_vector(07 downto 0);
-- init function and split 1x16-bit memory into 2x8-bit memories --
impure function init_imem(hilo : std_ulogic; init : application_init_image_t) return imem_file8_t is
variable mem_v : imem_file8_t;
begin
for i in 0 to IMEM_SIZE/2-1 loop
if (hilo = '0') then -- low byte
mem_v(i) := init(i)(07 downto 00);
else -- high byte
mem_v(i) := init(i)(15 downto 08);
end if;
end loop; -- i
return mem_v;
end function init_imem;
-- local signals --
signal acc_en : std_ulogic;
signal rdata : std_ulogic_vector(15 downto 0);
signal rden : std_ulogic;
signal addr : integer;
-- internal "RAM" type - implemented if bootloader is used and IMEM is RAM and initialized with app code --
signal imem_file_init_ram_l : imem_file8_t := init_imem('0', application_init_image);
signal imem_file_init_ram_h : imem_file8_t := init_imem('1', application_init_image);
-- internal "ROM" type - implemented if bootloader is NOT used; always initialize with app code --
constant imem_file_rom_l : imem_file8_t := init_imem('0', application_init_image);
constant imem_file_rom_h : imem_file8_t := init_imem('1', application_init_image);
-- internal "RAM" type - implemented if bootloader is used and IMEM is RAM --
signal imem_file_ram_l : imem_file8_t;
signal imem_file_ram_h : imem_file8_t;
-- RAM attribute to inhibit bypass-logic - Intel only! --
attribute ramstyle : string;
attribute ramstyle of imem_file_init_ram_l : signal is "no_rw_check";
attribute ramstyle of imem_file_init_ram_h : signal is "no_rw_check";
attribute ramstyle of imem_file_ram_l : signal is "no_rw_check";
attribute ramstyle of imem_file_ram_h : signal is "no_rw_check";
-- RAM attribute to inhibit bypass-logic - Lattice only! --
attribute syn_ramstyle : string;
attribute syn_ramstyle of imem_file_init_ram_l : signal is "no_rw_check";
attribute syn_ramstyle of imem_file_init_ram_h : signal is "no_rw_check";
attribute syn_ramstyle of imem_file_ram_l : signal is "no_rw_check";
attribute syn_ramstyle of imem_file_ram_h : signal is "no_rw_check";
begin
-- Access Control -----------------------------------------------------------
-- -----------------------------------------------------------------------------
acc_en <= '1' when (addr_i >= imem_base_c) and (addr_i < std_ulogic_vector(unsigned(imem_base_c) + IMEM_SIZE)) else '0';
addr <= to_integer(unsigned(addr_i(index_size_f(IMEM_SIZE/2) downto 1))); -- word aligned
-- Memory Access ------------------------------------------------------------
-- -----------------------------------------------------------------------------
imem_file_access: process(clk_i)
begin
-- check max size --
if (IMEM_SIZE > 48*1024) then
assert false report "I-mem size out of range! Max 48kB!" severity error;
end if;
-- actual memory access --
if rising_edge(clk_i) then
rden <= rden_i and acc_en;
if (acc_en = '1') then -- reduce switching activity when not accessed
if (IMEM_AS_ROM = true) then -- implement IMEM as true ROM
rdata(07 downto 0) <= imem_file_rom_l(addr);
rdata(15 downto 8) <= imem_file_rom_h(addr);
elsif (BOOTLD_USE = true) then -- implement IMEM as non-initialized RAM
if (wren_i(0) = '1') and (upen_i = '1') then
imem_file_ram_l(addr) <= data_i(07 downto 0);
end if;
rdata(07 downto 0) <= imem_file_ram_l(addr);
if (wren_i(1) = '1') and (upen_i = '1') then
imem_file_ram_h(addr) <= data_i(15 downto 8);
end if;
rdata(15 downto 8) <= imem_file_ram_h(addr);
else -- implement IMEM as PRE-INITIALIZED RAM
if (wren_i(0) = '1') and (upen_i = '1') then
imem_file_init_ram_l(addr) <= data_i(07 downto 0);
end if;
rdata(07 downto 0) <= imem_file_init_ram_l(addr);
if (wren_i(1) = '1') and (upen_i = '1') then
imem_file_init_ram_h(addr) <= data_i(15 downto 8);
end if;
rdata(15 downto 8) <= imem_file_init_ram_h(addr);
end if;
end if;
end if;
end process imem_file_access;
-- output gate --
data_o <= rdata when (rden = '1') else (others => '0');
end neo430_imem_rtl;
You can’t perform that action at this time.