-- -------------------------------------------------------------------------- -- -- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs -- -- -------------------------------------------------------------------------- -- -- Servant-compatible RAM, rewritten in VHDL -- -------------------------------------------------------------------------- -- -- Author : Markus Koch -- Contributors : None -- License : Mozilla Public License (MPL) Version 2 -- -------------------------------------------------------------------------- -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use std.textio.all; library generics; use generics.wishbone_pkg.all; entity ram_vhdl is generic( memfile : string := "data/empty.hex"; read_only : boolean := false; adr_width : integer := 16 ); port( clk : in std_logic; -- CPU and bus clock clr : in std_logic; -- Synchronous reset wb_o : out wishbone_slave_out; -- Wishbone bus (out) wb_i : in wishbone_slave_in -- Wishbone bus (in) ); end entity ram_vhdl; architecture rtl of ram_vhdl is type mem_t is array (0 to 2 ** adr_width - 1) of std_logic_vector(wb_i.dat'range); impure function init_ram_hex return mem_t is file text_file : text open read_mode is memfile; variable text_line : line; variable ram_content : mem_t := (others => (others => '0')); begin for i in 0 to 2 ** adr_width - 1 loop exit when endfile(text_file); readline(text_file, text_line); hread(text_line, ram_content(i)); end loop; return ram_content; end function; signal mem : mem_t := init_ram_hex; signal mem_address : integer range mem'range; begin wb_o.rty <= '0'; wb_o.err <= '0'; wb_o.stall <= '0'; mem_address <= to_integer(unsigned(wb_i.adr(adr_width - 1 + 2 downto 2))); rowarn : process(clk) is begin if rising_edge(clk) then if wb_i.cyc and wb_i.stb then if (unsigned(wb_i.adr) > 2 ** adr_width - 1) then report "ERROR: Out of bounds for " & ram_vhdl'path_name & " @0x" & to_hstring(wb_i.adr) severity error; end if; if (wb_i.we = '1' and read_only) then report "ERROR: Write access to ROM @0x" & to_hstring(wb_i.adr) severity warning; end if; end if; end if; end process rowarn; mem_p : process(clk) is begin if rising_edge(clk) then wb_o.dat <= mem(mem_address); wb_o.ack <= wb_i.stb; if (wb_i.we) then wb_o.dat <= (others => '-'); for i in wb_i.sel'range loop if wb_i.sel(i) then mem(mem_address)((i + 1) * 8 - 1 downto (i * 8)) <= wb_i.dat((i + 1) * 8 - 1 downto (i * 8)); end if; end loop; end if; if clr then wb_o.dat <= (others => '-'); wb_o.ack <= '0'; end if; end if; end process mem_p; end architecture rtl;