diff --git a/hdl/rtl/hydra_core.vhd b/hdl/rtl/hydra_core.vhd index 259163b5b18cdc449990e39fdc660ffad48cc5d4..427caab5907217f70f71713866c57bd330fd3092 100644 --- a/hdl/rtl/hydra_core.vhd +++ b/hdl/rtl/hydra_core.vhd @@ -31,6 +31,7 @@ use work.genram_pkg.all; --use work.memory_loader_pkg.all; use work.wishbone_pkg.all; use work.urv_pkg.all; +use work.secded_32b_pkg.all; entity hydra_core is generic( @@ -155,30 +156,58 @@ begin p_rom: process (clk_sys_i) is constant IRAM_WSIZE : natural := 2 ** (g_IRAM_LOG_SIZE - 2); - variable iram : t_ram32_type(0 to IRAM_WSIZE - 1); + type t_ram39_type is array(natural range <>) of std_logic_vector(38 downto 0); + variable iram : t_ram39_type(0 to IRAM_WSIZE - 1); -- := f_load_mem32_from_file ("../../../sw/fip_urv/fip_dbg.ram", IRAM_WSIZE, True); - variable addr : std_logic_vector (g_IRAM_LOG_SIZE - 1 downto 2); + variable addr : std_logic_vector (g_IRAM_LOG_SIZE + 1 downto 2); + variable data, wdata : std_logic_vector(38 downto 0); + variable syndrome : std_logic_vector(6 downto 0); + type state_t is (S_READ, S_REWRITE, S_WRITE); + variable state : state_t; begin if rising_edge(clk_sys_i) then if cpu_rst = '1' then if iram_we = '1' then - iram (to_integer(unsigned(iram_addr))) := iram_data; + iram (to_integer(unsigned(iram_addr))) := f_calc_ecc (iram_data) & iram_data; end if; im_valid <= '0'; cpu_rst_d <= '1'; + state := S_WRITE; else cpu_rst_d <= cpu_rst; - if reg_dm_load = '1' and reg_dm_is_wishbone = '0' and reg_dm_addr (16) = '0' then - -- Data read from iram - addr := reg_dm_addr(g_IRAM_LOG_SIZE - 1 downto 2); - im_valid <= '0'; - else - -- Data read from dram. - addr := im_addr(g_IRAM_LOG_SIZE - 1 downto 2); - im_valid <= (not cpu_rst_d); - end if; - im_data <= iram (to_integer(unsigned(addr))); end if; + + case state is + when S_READ => + if reg_dm_load = '1' and reg_dm_is_wishbone = '0' and reg_dm_addr (16) = '0' then + -- Data read from iram + addr := reg_dm_addr(g_IRAM_LOG_SIZE + 1 downto 2); + im_valid <= '0'; + else + -- Data read from dram. + addr := im_addr(g_IRAM_LOG_SIZE + 1 downto 2); + im_valid <= (not cpu_rst_d); + end if; + data := iram (to_integer(unsigned(addr))); + syndrome := data(38 downto 32) xor f_calc_ecc(data(31 downto 0)); + im_data <= data(31 downto 0); + if f_ecc_errors(syndrome) = '1' then + im_valid <= '0'; + -- id_valid <= '0'; + state := S_REWRITE; + end if; + when S_WRITE | S_REWRITE => + if cpu_rst = '1' and iram_we = '1' then + addr := iram_addr; + wdata := f_calc_ecc (iram_data) & iram_data; + else + wdata := f_fix_error (syndrome, data(38 downto 32), data(31 downto 0)); + end if; + iram (to_integer(unsigned(iram_addr))) := wdata; + if cpu_rst = '0' then + state := S_READ; + end if; + end case; end if; end process;