From 37acb35773e10f96907f6feda6a7c1922a5baf08 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 19 Oct 2019 10:30:39 +1100 Subject: [PATCH] simple_ram: Add pipelining support The generic PIPELINE_DEPTH can be set to 0 to keep it operating as a non-pipelined slave, or a larger value indicating the amount of extra cycles between requests and acks. It will always generate a valid stall signal, so it can be used in either mode with a pipelined master (but only in non-pipelined mode with a non-pipelined master). Signed-off-by: Benjamin Herrenschmidt --- simple_ram_behavioural.vhdl | 84 ++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/simple_ram_behavioural.vhdl b/simple_ram_behavioural.vhdl index 0f6a90a..64135b8 100644 --- a/simple_ram_behavioural.vhdl +++ b/simple_ram_behavioural.vhdl @@ -9,8 +9,9 @@ use work.simple_ram_behavioural_helpers.all; entity mw_soc_memory is generic ( - RAM_INIT_FILE : string; - MEMORY_SIZE : integer + RAM_INIT_FILE : string; + MEMORY_SIZE : integer; + PIPELINE_DEPTH : integer := 0 ); port ( @@ -29,48 +30,101 @@ architecture behave of mw_soc_memory is signal ret_ack : std_ulogic := '0'; signal identifier : integer := behavioural_initialize(filename => RAM_INIT_FILE, size => MEMORY_SIZE); signal reload : integer := 0; + signal ret_dat : wishbone_data_type; + + subtype pipe_idx_t is integer range 0 to PIPELINE_DEPTH-1; + type pipe_ack_t is array(pipe_idx_t) of std_ulogic; + type pipe_dat_t is array(pipe_idx_t) of wishbone_data_type; begin - wishbone_process: process(clk) - variable ret_dat: std_ulogic_vector(63 downto 0) := (others => '0'); - variable adr: std_ulogic_vector(63 downto 0); + + pipe_big: if PIPELINE_DEPTH > 1 generate + signal pipe_ack : pipe_ack_t; + signal pipe_dat : pipe_dat_t; + begin + wishbone_out.stall <= '0'; + wishbone_out.ack <= pipe_ack(0); + wishbone_out.dat <= pipe_dat(0); + + pipe_big_sync: process(clk) + begin + if rising_edge(clk) then + pipe_stages: for i in 0 to PIPELINE_DEPTH-2 loop + pipe_ack(i) <= pipe_ack(i+1); + pipe_dat(i) <= pipe_dat(i+1); + end loop; + pipe_ack(PIPELINE_DEPTH-1) <= ret_ack; + pipe_dat(PIPELINE_DEPTH-1) <= ret_dat; + end if; + end process; + end generate; + + pipe_one: if PIPELINE_DEPTH = 1 generate + signal pipe_ack : std_ulogic; + signal pipe_dat : wishbone_data_type; begin - wishbone_out.ack <= ret_ack and wishbone_in.cyc and wishbone_in.stb; - wishbone_out.dat <= ret_dat; + wishbone_out.stall <= '0'; + wishbone_out.ack <= pipe_ack; + wishbone_out.dat <= pipe_dat; + + pipe_one_sync: process(clk) + begin + if rising_edge(clk) then + pipe_ack <= ret_ack; + pipe_dat <= ret_dat; + end if; + end process; + end generate; + pipe_none: if PIPELINE_DEPTH = 0 generate + begin + wishbone_out.ack <= ret_ack; + wishbone_out.dat <= ret_dat; + wishbone_out.stall <= wishbone_in.cyc and not ret_ack; + end generate; + + wishbone_process: process(clk) + variable ret_dat_v : wishbone_data_type; + variable adr : std_ulogic_vector(63 downto 0); + begin if rising_edge(clk) then if rst = '1' then state <= IDLE; ret_ack <= '0'; else - ret_dat := x"FFFFFFFFFFFFFFFF"; + ret_dat <= x"FFFFFFFFFFFFFFFF"; + ret_ack <= '0'; -- Active if wishbone_in.cyc = '1' then case state is when IDLE => if wishbone_in.stb = '1' then + adr := (wishbone_in.adr'left downto 0 => wishbone_in.adr, + others => '0'); -- write - adr := (wishbone_in.adr'left downto 0 => wishbone_in.adr, others => '0'); if wishbone_in.we = '1' then assert not(is_x(wishbone_in.dat)) and not(is_x(wishbone_in.adr)) severity failure; report "RAM writing " & to_hstring(wishbone_in.dat) & " to " & to_hstring(wishbone_in.adr); behavioural_write(wishbone_in.dat, adr, to_integer(unsigned(wishbone_in.sel)), identifier); reload <= reload + 1; ret_ack <= '1'; - state <= ACK; + if PIPELINE_DEPTH = 0 then + state <= ACK; + end if; else - behavioural_read(ret_dat, adr, to_integer(unsigned(wishbone_in.sel)), identifier, reload); - report "RAM reading from " & to_hstring(wishbone_in.adr) & " returns " & to_hstring(ret_dat); + behavioural_read(ret_dat_v, adr, to_integer(unsigned(wishbone_in.sel)), identifier, reload); + report "RAM reading from " & to_hstring(wishbone_in.adr) & " returns " & to_hstring(ret_dat_v); + ret_dat <= ret_dat_v; ret_ack <= '1'; - state <= ACK; + if PIPELINE_DEPTH = 0 then + state <= ACK; + end if; end if; end if; when ACK => - ret_ack <= '0'; state <= IDLE; end case; else - ret_ack <= '0'; state <= IDLE; end if; end if;