Experimental Instruction memory adjustment

This commit is contained in:
Thomas Fehmel
2018-01-23 14:24:16 +01:00
parent 2487bece9e
commit 913574ba16
2 changed files with 132 additions and 102 deletions

View File

@@ -78,7 +78,7 @@ BEGIN
if rst = '1' then
ack <= '0';
else
if wslvi.stb = '1' and wslvi.cyc = '1' and ack = '0' then
if wslvi.stb = '1' and wslvi.cyc = '1' and ack = '0' and out_dmem.ready = '1' then
ack <= '1';
else
ack <= '0';

View File

@@ -55,7 +55,9 @@ architecture RTL of memdiv is
-- type for the memory signal
type memory_type is array (0 to size - 1) of std_logic_vector(width - 1 downto 0);
-- type for dmem_write fsm
type write_states is (read_old, write_new);
-- this function initializes an array of memory_type with the contents of a given file
-- function from http://myfpgablog.blogspot.de/2011/12/memory-initialization-methods.html
-- and from http://www.stefanvhdl.com/vhdl/html/file_read.html
@@ -114,6 +116,11 @@ architecture RTL of memdiv is
signal dmem_write_fault : std_logic;
-- fault signal for imem read faults
signal imem_read_fault : std_logic;
signal old_word : std_logic_vector(width - 1 downto 0);
signal in_dmem_reg : core_dmem;
signal mem_ready : std_logic;
signal write_state : write_states;
begin
-- fault logic
@@ -276,73 +283,86 @@ begin
if rising_edge(clk) then
if rst = '1' then
dmem_write_fault <= '0';
elsif (in_dmem.write_en = '1') then
dmem_write_fault <= '0';
wordaddress := to_integer(unsigned(in_dmem.write_addr(in_dmem.write_addr'high downto 2)));
byteaddress := in_dmem.write_addr(1 downto 0);
if (wordaddress < size) then -- in memory range and no special word
-- read old word
word := memory(wordaddress)(31 downto 0);
-- modify word
case in_dmem.write_size is
when "00" => -- byte access
case byteaddress is
when "00" =>
word(31 downto 24) := in_dmem.write_data(7 downto 0);
when "01" =>
word(23 downto 16) := in_dmem.write_data(7 downto 0);
when "10" =>
word(15 downto 8) := in_dmem.write_data(7 downto 0);
when "11" =>
word(7 downto 0) := in_dmem.write_data(7 downto 0);
when others =>
-- will not happen in synthesis, but might in simulation
word(7 downto 0) := (others => 'X');
end case;
when "01" => -- halfword access
case byteaddress is
when "00" =>
word(31 downto 16) := in_dmem.write_data(15 downto 0);
when "01" =>
word(23 downto 8) := in_dmem.write_data(15 downto 0);
when "10" =>
word(15 downto 0) := in_dmem.write_data(15 downto 0);
when others =>
write_state <= read_old;
old_word <= (others => '0');
mem_ready <= '1';
else
case write_state is
when read_old =>
wordaddress := to_integer(unsigned(in_dmem.write_addr(in_dmem.write_addr'high downto 2)));
if (wordaddress < size) then -- in memory range and no special word
in_dmem_reg <= in_dmem;
mem_ready <= '1';
if (in_dmem.write_en = '1') then
write_state <= write_new;
mem_ready <= '0';
-- read old word
old_word <= memory(wordaddress)(31 downto 0);
end if;
else
dmem_write_fault <= '1';
-- synthesis translate_off
assert false report "memory access out of bounds (dmem write at " & integer'image(to_integer(unsigned(in_dmem.write_addr))) & ")" severity error;
-- synthesis translate_on
end if;
when write_new =>
wordaddress := to_integer(unsigned(in_dmem_reg.write_addr(in_dmem.write_addr'high downto 2)));
byteaddress := in_dmem_reg.write_addr(1 downto 0);
word := old_word;
write_state <= read_old;
mem_ready <= '1';
case in_dmem_reg.write_size is
when "00" => -- byte access
case byteaddress is
when "00" =>
word(31 downto 24) := in_dmem_reg.write_data(7 downto 0);
when "01" =>
word(23 downto 16) := in_dmem_reg.write_data(7 downto 0);
when "10" =>
word(15 downto 8) := in_dmem_reg.write_data(7 downto 0);
when "11" =>
word(7 downto 0) := in_dmem_reg.write_data(7 downto 0);
when others =>
-- will not happen in synthesis, but might in simulation
word(7 downto 0) := (others => 'X');
end case;
when "01" => -- halfword access
case byteaddress is
when "00" =>
word(31 downto 16) := in_dmem_reg.write_data(15 downto 0);
when "01" =>
word(23 downto 8) := in_dmem_reg.write_data(15 downto 0);
when "10" =>
word(15 downto 0) := in_dmem_reg.write_data(15 downto 0);
when others =>
-- memory access exceeds word boundaries
dmem_write_fault <= '1';
-- synthesis translate_off
assert false report "memory access exceeds word boundaries (16bit dmem write at " & integer'image(to_integer(unsigned(in_dmem.write_addr))) & ")" severity error;
-- synthesis translate_on
end case;
when "10" =>
if (byteaddress = "00") then
word := in_dmem_reg.write_data;
else
-- memory access exceeds word boundaries
dmem_write_fault <= '1';
-- synthesis translate_off
assert false report "memory access exceeds word boundaries (16bit dmem write at " & integer'image(to_integer(unsigned(in_dmem.write_addr))) & ")" severity error;
assert false report "memory access exceeds word boundaries (32bit dmem write at " & integer'image(to_integer(unsigned(in_dmem.write_addr))) & ")" severity error;
-- synthesis translate_on
end case;
when "10" =>
if (byteaddress = "00") then
word := in_dmem.write_data;
else
-- memory access exceeds word boundaries
end if;
when others =>
-- memory size not implemented
dmem_write_fault <= '1';
-- synthesis translate_off
assert false report "memory access exceeds word boundaries (32bit dmem write at " & integer'image(to_integer(unsigned(in_dmem.write_addr))) & ")" severity error;
assert false report "memory size not implemented" severity error;
-- synthesis translate_on
end if;
when others =>
-- memory size not implemented
dmem_write_fault <= '1';
-- synthesis translate_off
assert false report "memory size not implemented" severity error;
-- synthesis translate_on
end case;
memory(wordaddress) <= word;
else
dmem_write_fault <= '1';
-- synthesis translate_off
assert false report "memory access out of bounds (dmem write at " & integer'image(to_integer(unsigned(in_dmem.write_addr))) & ")" severity error;
-- synthesis translate_on
end if;
end case;
memory(wordaddress) <= word;
end case;
end if;
end if;
end process dmem_write;
@@ -350,9 +370,11 @@ begin
-- in synthesis, data is always valid in next clock cycle
synthesis_only : if (in_synthesis) generate
out_imem.read_data <= imem_data;
out_imem.ready <= '1';
out_dmem.read_data <= dmem_data;
out_dmem.ready <= '1';
-- out_imem.ready <= '1';
out_imem.ready <= mem_ready;
out_dmem.read_data <= dmem_data;
-- out_dmem.ready <= '1';
out_dmem.ready <= mem_ready;
end generate synthesis_only;
-- add latency in simulation only
@@ -360,44 +382,52 @@ begin
-- synthesis translate_off
simulation_only : if (in_simulation) generate
-- instruction memory latency
imem_delay : process is
begin
wait until imem_data'event;
-- wait artificial delay
if (imem_latency > 0 ns) then
-- show not ready-yet data as XX
out_imem.ready <= '0';
out_imem.read_data <= (others => 'X');
wait for imem_latency;
end if;
-- output data
out_imem.read_data <= imem_data;
-- now we're ready
out_imem.ready <= '1';
end process imem_delay;
-- data memory latency
dmem_delay : process is
begin
wait until dmem_data'event;
-- wait artificial delay
if (dmem_latency > 0 ns) then
-- show not ready-yet data as XX
out_dmem.ready <= '0';
out_dmem.read_data <= (others => 'X');
wait for dmem_latency;
end if;
-- output data
out_dmem.read_data <= dmem_data;
-- now we're ready
out_dmem.ready <= '1';
end process dmem_delay;
out_imem.read_data <= imem_data;
out_imem.ready <= mem_ready;
out_dmem.read_data <= dmem_data;
out_dmem.ready <= mem_ready;
-- imem_delay : process is
-- begin
-- wait until imem_data'event;
--
-- -- wait artificial delay
-- if (imem_latency > 0 ns) then
-- -- show not ready-yet data as XX
-- out_imem.ready <= '0';
-- out_imem.read_data <= (others => 'X');
-- wait for imem_latency;
-- end if;
--
-- -- output data
-- out_imem.read_data <= imem_data;
--
-- -- now we're ready
-- -- out_imem.ready <= '1';
-- out_dmem.ready <= mem_ready;
-- end process imem_delay;
--
-- -- data memory latency
-- dmem_delay : process is
-- begin
-- wait until dmem_data'event;
--
-- -- wait artificial delay
-- if (dmem_latency > 0 ns) then
-- -- show not ready-yet data as XX
-- out_dmem.ready <= '0';
-- out_dmem.read_data <= (others => 'X');
-- wait for dmem_latency;
-- end if;
--
-- -- output data
-- out_dmem.read_data <= dmem_data;
--
-- -- now we're ready
-- -- out_dmem.ready <= '1';
-- out_dmem.ready <= mem_ready;
-- end process dmem_delay;
end generate simulation_only;
-- synthesis translate_on