Skip to content
Snippets Groups Projects
Commit b7b8eb3a authored by Tristan Gingold's avatar Tristan Gingold
Browse files

hydra_ram: handle corrections

parent 17aef615
Branches
No related merge requests found
...@@ -85,6 +85,7 @@ architecture arch of hydra_core is ...@@ -85,6 +85,7 @@ architecture arch of hydra_core is
signal im_data, im1_data : std_logic_vector(31 downto 0); signal im_data, im1_data : std_logic_vector(31 downto 0);
signal im_rd, im_valid : std_logic; signal im_rd, im_valid : std_logic;
signal im1_done, im1_dm_en, im1_err : std_logic; signal im1_done, im1_dm_en, im1_err : std_logic;
signal im2_err, im2_valid : std_logic;
signal dm_addr, dm_data_s, dm_data_l : std_logic_vector(31 downto 0); signal dm_addr, dm_data_s, dm_data_l : std_logic_vector(31 downto 0);
signal dm_data_select : std_logic_vector(3 downto 0); signal dm_data_select : std_logic_vector(3 downto 0);
...@@ -94,7 +95,7 @@ architecture arch of hydra_core is ...@@ -94,7 +95,7 @@ architecture arch of hydra_core is
signal reg_dm_data_select : std_logic_vector(3 downto 0); signal reg_dm_data_select : std_logic_vector(3 downto 0);
signal reg_dm_load, reg_dm_store : std_logic; signal reg_dm_load, reg_dm_store : std_logic;
signal dm_cycle_in_progress, reg_dm_is_wishbone : std_logic; signal dm_cycle_in_progress, reg_dm_is_wishbone, reg_dm_is_iram : std_logic;
signal dm_mem_rdata, dm_wb_rdata : std_logic_vector(31 downto 0); signal dm_mem_rdata, dm_wb_rdata : std_logic_vector(31 downto 0);
signal dm_wb_write, dm_select_wb : std_logic; signal dm_wb_write, dm_select_wb : std_logic;
...@@ -137,6 +138,7 @@ begin ...@@ -137,6 +138,7 @@ begin
dbg_mbx_write_i => '0', dbg_mbx_write_i => '0',
dbg_mbx_data_o => open); dbg_mbx_data_o => open);
-- Add registers on uRV data bus
process (clk_sys_i) process (clk_sys_i)
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
...@@ -165,17 +167,21 @@ begin ...@@ -165,17 +167,21 @@ begin
clk_i => clk_sys_i, clk_i => clk_sys_i,
rst_n_i => rst_n_i, rst_n_i => rst_n_i,
-- uRV data read from iRAM
r1_addr_i => reg_dm_addr(g_IRAM_LOG_SIZE - 1 downto 2), r1_addr_i => reg_dm_addr(g_IRAM_LOG_SIZE - 1 downto 2),
r1_en_i => im1_dm_en, r1_en_i => im1_dm_en,
r1_data_o => im1_data, r1_data_o => im1_data,
r1_done_o => im1_done, r1_done_o => im1_done,
r1_err_o => im1_err, r1_err_o => im1_err,
-- uRV instructions
r2_addr_i => im_addr(g_IRAM_LOG_SIZE - 1 downto 2), r2_addr_i => im_addr(g_IRAM_LOG_SIZE - 1 downto 2),
r2_en_i => im_rd, --rst_n_i, r2_en_i => im_rd,
r2_data_o => im_data, r2_data_o => im_data,
r2_done_o => im_valid, r2_done_o => im2_valid,
r2_err_o => im2_err,
-- iRAM initialization
waddr_i => iram_addr, waddr_i => iram_addr,
we_i => iram_we, we_i => iram_we,
wdata_i => iram_data, wdata_i => iram_data,
...@@ -184,12 +190,14 @@ begin ...@@ -184,12 +190,14 @@ begin
scrubber_period_i => x"0010" scrubber_period_i => x"0010"
); );
im_valid <= im2_valid and not im2_err;
-- 1st MByte of the mem is the RAM -- 1st MByte of the mem is the RAM
-- 1st 64KB is the IRAM. -- 1st 64KB is the IRAM.
-- 2nd 64KB is the DRAM -- 2nd 64KB is the DRAM
reg_dm_is_wishbone <= '1' when reg_dm_addr(31 downto 20) /= x"000" else '0'; reg_dm_is_wishbone <= '1' when reg_dm_addr(31 downto 20) /= x"000" else '0';
dm_data_l <= dm_wb_rdata when dm_select_wb = '1' else reg_dm_is_iram <= '1' when reg_dm_addr(16) = '0' and reg_dm_is_wishbone = '0' else '0';
im_data when reg_dm_addr(16) = '0' else dm_data_l <= dm_wb_rdata when (dm_select_wb = '1' or reg_dm_is_iram = '1') else
dm_mem_rdata; dm_mem_rdata;
p_ram: process (clk_sys_i) p_ram: process (clk_sys_i)
...@@ -198,8 +206,12 @@ begin ...@@ -198,8 +206,12 @@ begin
variable addr : natural range dram'range; variable addr : natural range dram'range;
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
addr := to_integer(unsigned(reg_dm_addr(g_DRAM_LOG_SIZE - 1 downto 2))); if reg_dm_load = '1' then
dm_mem_rdata <= dram(addr); addr := to_integer(unsigned(reg_dm_addr(g_DRAM_LOG_SIZE - 1 downto 2)));
dm_mem_rdata <= dram(addr);
else
dm_mem_rdata <= (others => 'X');
end if;
if reg_dm_store = '1' and reg_dm_addr(16) = '1' and reg_dm_is_wishbone = '0' then if reg_dm_store = '1' and reg_dm_addr(16) = '1' and reg_dm_is_wishbone = '0' then
for i in 0 to 3 loop for i in 0 to 3 loop
if reg_dm_data_select (i) = '1' then if reg_dm_data_select (i) = '1' then
...@@ -210,10 +222,14 @@ begin ...@@ -210,10 +222,14 @@ begin
end if; end if;
end process; end process;
-- Data bus
-- Wishbone bus arbitration / internal RAM access -- Wishbone bus arbitration / internal RAM access
p_wishbone_master : process(clk_sys_i) p_wishbone_master : process(clk_sys_i)
begin begin
if rising_edge(clk_sys_i) then if rising_edge(clk_sys_i) then
dm_store_done <= '0';
dm_load_done <= '0';
if rst_n_i = '0' then if rst_n_i = '0' then
dwb_out.cyc <= '0'; dwb_out.cyc <= '0';
dwb_out.stb <= '0'; dwb_out.stb <= '0';
...@@ -222,62 +238,64 @@ begin ...@@ -222,62 +238,64 @@ begin
dwb_out.we <= '0'; dwb_out.we <= '0';
dwb_out.dat <= (others => '0'); dwb_out.dat <= (others => '0');
dm_cycle_in_progress <= '0'; dm_cycle_in_progress <= '0';
dm_load_done <= '0';
dm_store_done <= '0';
dm_select_wb <= '0'; dm_select_wb <= '0';
else else
if dm_cycle_in_progress = '0' then if dm_cycle_in_progress = '0' then
-- Data bus was idle.
dm_wb_write <= reg_dm_store;
if reg_dm_is_wishbone = '0' then if reg_dm_is_wishbone = '0' then
-- Internal access -- Internal access
dm_select_wb <= '0'; dm_select_wb <= '0';
if reg_dm_store = '1' then if reg_dm_store = '1' then
dm_load_done <= '0';
dm_store_done <= '1'; dm_store_done <= '1';
elsif reg_dm_load = '1' then elsif reg_dm_load = '1' then
dm_load_done <= '1'; if reg_dm_is_iram = '1' then
dm_store_done <= '0'; -- Need to wait for the done (may need extra cycles due to ECC)
else dm_cycle_in_progress <= '1';
dm_store_done <= '0'; else
dm_load_done <= '0'; -- Immediate answer
dm_load_done <= '1';
end if;
end if; end if;
else else
-- Wishbone access -- Wishbone access
dm_select_wb <= '1';
if reg_dm_load = '1' or reg_dm_store = '1' then if reg_dm_load = '1' or reg_dm_store = '1' then
dwb_out.cyc <= '1'; dwb_out.cyc <= '1';
dwb_out.stb <= '1'; dwb_out.stb <= '1';
dwb_out.we <= reg_dm_store; dwb_out.we <= reg_dm_store;
dm_wb_write <= reg_dm_store;
dwb_out.adr <= reg_dm_addr; dwb_out.adr <= reg_dm_addr;
dwb_out.dat <= reg_dm_data_s; dwb_out.dat <= reg_dm_data_s;
dwb_out.sel <= reg_dm_data_select; dwb_out.sel <= reg_dm_data_select;
dm_load_done <= '0';
dm_store_done <= '0';
dm_cycle_in_progress <= '1'; dm_cycle_in_progress <= '1';
else
dm_store_done <= '0';
dm_load_done <= '0';
dm_cycle_in_progress <= '0';
end if; end if;
end if; end if;
else else
-- Wishbone transfer in progress. -- Transfer in progress
if dwb_i.stall = '0' then if dm_select_wb = '1' then
dwb_out.stb <= '0'; -- Wishbone transfer in progress.
end if; if dwb_i.stall = '0' then
dwb_out.stb <= '0';
end if;
if dwb_i.ack = '1' then if dwb_i.ack = '1' then
if dm_wb_write = '0' then if dm_wb_write = '0' then
dm_wb_rdata <= f_x_to_zero(dwb_i.dat); dm_wb_rdata <= f_x_to_zero(dwb_i.dat);
dm_select_wb <= '1'; dm_load_done <= '1';
else
dm_store_done <= '1';
end if;
dm_cycle_in_progress <= '0';
dwb_out.cyc <= '0';
end if;
else
-- IRAM/DRAM transfer in progress
if im1_done = '1' and im1_err = '0' then
dm_wb_rdata <= im1_data;
dm_load_done <= '1'; dm_load_done <= '1';
else dm_cycle_in_progress <= '0';
dm_store_done <= '1';
dm_select_wb <= '0';
end if; end if;
dm_cycle_in_progress <= '0';
dwb_out.cyc <= '0';
end if; end if;
end if; end if;
end if; end if;
......
...@@ -80,15 +80,15 @@ architecture arch of hydra_ram is ...@@ -80,15 +80,15 @@ architecture arch of hydra_ram is
signal recc, rsyndrome : std_logic_vector(6 downto 0); signal recc, rsyndrome : std_logic_vector(6 downto 0);
signal rerr, rerr_one : std_logic; signal rerr, rerr_one : std_logic;
signal r1_done, n_r1_done : std_logic; signal r1_done, n_r1_done, r1_done_d : std_logic;
signal r2_done, n_r2_done : std_logic; signal r2_done, n_r2_done, r2_done_d : std_logic;
signal wdone, n_wdone : std_logic; signal wdone, n_wdone : std_logic;
signal n_ecc_one, n_ecc_fatal : std_logic; signal n_ecc_one, n_ecc_fatal : std_logic;
signal last_raddr, n_last_raddr, scrub_addr : std_logic_vector(g_RAM_LOG_SIZE - 1 downto 2); signal last_raddr, n_last_raddr, scrub_addr : std_logic_vector(g_RAM_LOG_SIZE - 1 downto 2);
signal scrub_counter : unsigned(15 downto 0); signal scrub_counter : unsigned(15 downto 0);
signal scrub_rd, scrub_done, n_scrub_done : std_logic; signal scrub_rd, scrub_done, scrub_done_d, n_scrub_done : std_logic;
type state_t is (S_READ, S_REWRITE); type state_t is (S_READ, S_REWRITE);
signal state, n_state : state_t; signal state, n_state : state_t;
...@@ -97,13 +97,27 @@ begin ...@@ -97,13 +97,27 @@ begin
p_ram: process (clk_i) p_ram: process (clk_i)
is is
variable iram : t_ram39_type(0 to RAM_WSIZE - 1); variable iram : t_ram39_type(0 to RAM_WSIZE - 1);
variable d : std_logic_vector(38 downto 0);
variable err : std_logic_vector(38 downto 0) := (0 => '1', others => '0');
variable sim_cnt : natural;
begin begin
if rising_edge(clk_i) then if rising_edge(clk_i) then
if wen = '1' then if wen = '1' then
iram (to_integer(unsigned(waddr))) := wdata_ecc; iram (to_integer(unsigned(waddr))) := wdata_ecc;
end if; end if;
if ren = '1' then if ren = '1' then
rdata_ecc <= iram (to_integer(unsigned(raddr))); d := iram (to_integer(unsigned(raddr)));
-- Simulate errors.
if sim_cnt < 7 then
sim_cnt := sim_cnt + 1;
else
sim_cnt := 0;
d := d xor err;
err := err(err'left - 1 downto 0) & err(err'left);
end if;
rdata_ecc <= d;
else else
rdata_ecc <= (others => 'X'); rdata_ecc <= (others => 'X');
end if; end if;
...@@ -133,7 +147,7 @@ begin ...@@ -133,7 +147,7 @@ begin
scrub_addr <= (others => '0'); scrub_addr <= (others => '0');
scrub_rd <= '0'; scrub_rd <= '0';
else else
if scrub_done = '1' then if scrub_done = '1' and rerr = '0' then
scrub_counter <= unsigned(scrubber_period_i); scrub_counter <= unsigned(scrubber_period_i);
scrub_addr <= std_logic_vector(unsigned(scrub_addr) + 1); scrub_addr <= std_logic_vector(unsigned(scrub_addr) + 1);
scrub_rd <= '0'; scrub_rd <= '0';
...@@ -148,9 +162,9 @@ begin ...@@ -148,9 +162,9 @@ begin
end if; end if;
end process; end process;
p_ctrl: process (state, r1_done, r2_done, rerr, rdata_ecc, rsyndrome, last_raddr, p_ctrl: process (state, r1_done, r2_done, rerr, rerr_one, rdata_ecc, rsyndrome, last_raddr, recc,
r1_en_i, r1_addr_i, we_i, waddr_i, wdata_i, wforce_i, r1_en_i, r1_addr_i, we_i, waddr_i, wdata_i, wforce_i, r1_done_d, r2_done_d,
r2_en_i, r2_addr_i, scrub_rd, scrub_addr, scrub_done) r2_en_i, r2_addr_i, scrub_rd, scrub_addr, scrub_done, scrub_done_d, rst_n_i)
begin begin
wen <= '0'; wen <= '0';
waddr <= (others => 'X'); waddr <= (others => 'X');
...@@ -169,7 +183,7 @@ begin ...@@ -169,7 +183,7 @@ begin
case state is case state is
when S_READ => when S_READ =>
if (r2_done = '1' or r1_done = '1') and rerr = '1' then if (r2_done = '1' or r1_done = '1' or scrub_done = '1') and rerr = '1' then
-- There was an error on the last access. -- There was an error on the last access.
-- Write to fix it. -- Write to fix it.
if rerr_one = '1' then if rerr_one = '1' then
...@@ -210,8 +224,8 @@ begin ...@@ -210,8 +224,8 @@ begin
ren <= '1'; ren <= '1';
n_r2_done <= '1'; n_r2_done <= '1';
n_last_raddr <= r2_addr_i; n_last_raddr <= r2_addr_i;
else elsif rst_n_i = '1' then
-- scrub if idle. -- scrub if idle (but not during reset)
raddr <= scrub_addr; raddr <= scrub_addr;
ren <= '1'; ren <= '1';
n_scrub_done <= '1'; n_scrub_done <= '1';
...@@ -221,8 +235,11 @@ begin ...@@ -221,8 +235,11 @@ begin
-- Reread -- Reread
raddr <= last_raddr; raddr <= last_raddr;
ren <= '1'; ren <= '1';
n_r1_done <= '1'; n_r1_done <= r1_done_d;
n_r2_done <= r2_done_d;
n_scrub_done <= scrub_done_d;
n_last_raddr <= last_raddr; n_last_raddr <= last_raddr;
n_state <= S_READ;
end case; end case;
end process; end process;
...@@ -231,18 +248,23 @@ begin ...@@ -231,18 +248,23 @@ begin
if rising_edge(clk_i) then if rising_edge(clk_i) then
if rst_n_i = '0' then if rst_n_i = '0' then
r1_done <= '0'; r1_done <= '0';
r1_done_d <= '0';
r2_done <= '0'; r2_done <= '0';
r2_done_d <= '0';
scrub_done <= '0'; scrub_done <= '0';
scrub_done_d <= '0';
state <= S_READ; state <= S_READ;
last_raddr <= (others => 'X'); last_raddr <= (others => 'X');
ecc_one_o <= '0'; ecc_one_o <= '0';
ecc_fatal_o <= '0'; ecc_fatal_o <= '0';
else else
r1_done_d <= r1_done;
r1_done <= n_r1_done; r1_done <= n_r1_done;
r2_done_d <= r2_done;
r2_done <= n_r2_done; r2_done <= n_r2_done;
scrub_done_d <= scrub_done;
scrub_done <= n_scrub_done; scrub_done <= n_scrub_done;
assert ((r2_done or scrub_done) and rerr) = '0' severity error; -- TODO
state <= n_state; state <= n_state;
last_raddr <= n_last_raddr; last_raddr <= n_last_raddr;
......
...@@ -69,7 +69,7 @@ architecture behav of sf2_test is ...@@ -69,7 +69,7 @@ architecture behav of sf2_test is
signal iram_we : std_logic; signal iram_we : std_logic;
signal iram_data : std_logic_vector(31 downto 0); signal iram_data : std_logic_vector(31 downto 0);
signal cpu_rst_n : std_logic; signal cpu_rst_n : std_logic := '0';
signal dwb_out : t_wishbone_master_out; signal dwb_out : t_wishbone_master_out;
signal dwb_in : t_wishbone_master_in; signal dwb_in : t_wishbone_master_in;
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment