From 913574ba16bb93fc91bc789495694f6d1567b5b0 Mon Sep 17 00:00:00 2001 From: Thomas Fehmel Date: Tue, 23 Jan 2018 14:24:16 +0100 Subject: [PATCH] Experimental Instruction memory adjustment --- soc/mem/mem2wb.vhd | 2 +- soc/mem/memdiv.vhd | 232 +++++++++++++++++++++++++-------------------- 2 files changed, 132 insertions(+), 102 deletions(-) diff --git a/soc/mem/mem2wb.vhd b/soc/mem/mem2wb.vhd index 83ea1ac..df8b51f 100644 --- a/soc/mem/mem2wb.vhd +++ b/soc/mem/mem2wb.vhd @@ -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'; diff --git a/soc/mem/memdiv.vhd b/soc/mem/memdiv.vhd index e4aac17..20605df 100644 --- a/soc/mem/memdiv.vhd +++ b/soc/mem/memdiv.vhd @@ -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