From 3349bdc79891364f702b8ce977d14abfda46ae01 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 22 Oct 2019 16:05:18 +1100 Subject: [PATCH] ram: Add block RAM pipelining This adds an output buffer to help with timing and allows the BRAMs to actually pipeline. Signed-off-by: Benjamin Herrenschmidt --- fpga/mw_soc_memory.vhdl | 89 ++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 42 deletions(-) diff --git a/fpga/mw_soc_memory.vhdl b/fpga/mw_soc_memory.vhdl index af31c89..7e998b2 100644 --- a/fpga/mw_soc_memory.vhdl +++ b/fpga/mw_soc_memory.vhdl @@ -4,6 +4,7 @@ library ieee; use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; use std.textio.all; @@ -29,9 +30,10 @@ entity mw_soc_memory is end entity mw_soc_memory; architecture behaviour of mw_soc_memory is - signal wb_adr_in : std_logic_vector(log2(MEMORY_SIZE) - 1 downto 0); + -- RAM type definition type ram_t is array(0 to (MEMORY_SIZE / 8) - 1) of std_logic_vector(63 downto 0); + -- RAM loading impure function init_ram(name : STRING) return ram_t is file ram_file : text open read_mode is name; variable ram_line : line; @@ -48,58 +50,61 @@ architecture behaviour of mw_soc_memory is return temp_ram; end function; + -- RAM instance signal memory : ram_t := init_ram(RAM_INIT_FILE); - attribute ram_style : string; attribute ram_style of memory : signal is "block"; - attribute ram_decomp : string; - attribute ram_decomp of memory : signal is "power"; - - type state_type is (IDLE, ACK); - signal state : state_type; - - signal read_ack : std_logic; - + attribute ram_decomp of memory : signal is "power"; + + -- RAM interface + constant ram_addr_bits : integer := log2(MEMORY_SIZE) - 3; + signal ram_addr : std_logic_vector(ram_addr_bits - 1 downto 0); + signal ram_di : std_logic_vector(63 downto 0); + signal ram_do : std_logic_vector(63 downto 0); + signal ram_sel : std_logic_vector(7 downto 0); + signal ram_we : std_ulogic; + + -- Others + signal ram_obuf : std_logic_vector(63 downto 0); + signal ack, ack_obuf : std_ulogic; begin - wb_adr_in <= wishbone_in.adr(log2(MEMORY_SIZE) - 1 downto 0); + -- Actual RAM template + memory_0: process(clk) + begin + if rising_edge(clk) then + if ram_we = '1' then + for i in 0 to 7 loop + if ram_sel(i) = '1' then + memory(conv_integer(ram_addr))((i + 1) * 8 - 1 downto i * 8) <= + ram_di((i + 1) * 8 - 1 downto i * 8); + end if; + end loop; + end if; + ram_do <= memory(conv_integer(ram_addr)); + ram_obuf <= ram_do; + end if; + end process; - wishbone_out.ack <= read_ack and wishbone_in.cyc and wishbone_in.stb; - wishbone_out.stall <= '0' when wishbone_in.cyc = '0' else not wishbone_out.ack; + -- Wishbone interface + ram_addr <= wishbone_in.adr(ram_addr_bits + 2 downto 3); + ram_di <= wishbone_in.dat; + ram_sel <= wishbone_in.sel; + ram_we <= wishbone_in.we and wishbone_in.stb and wishbone_in.cyc; + wishbone_out.stall <= '0'; + wishbone_out.ack <= ack_obuf; + wishbone_out.dat <= ram_obuf; - memory_0: process(clk) + wb_0: process(clk) begin if rising_edge(clk) then - if rst = '1' then - read_ack <= '0'; - state <= IDLE; + if rst = '1' or wishbone_in.cyc = '0' then + ack_obuf <= '0'; + ack <= '0'; else - if wishbone_in.cyc = '1' then - case state is - when IDLE => - if wishbone_in.stb = '1' and wishbone_in.we = '1' then - for i in 0 to 7 loop - if wishbone_in.sel(i) = '1' then - memory(to_integer(unsigned(wb_adr_in(wb_adr_in'left downto 3))))(((i + 1) * 8) - 1 downto i * 8) - <= wishbone_in.dat(((i + 1) * 8) - 1 downto i * 8); - end if; - end loop; - read_ack <= '1'; - state <= ACK; - elsif wishbone_in.stb = '1' then - wishbone_out.dat <= memory(to_integer(unsigned(wb_adr_in(wb_adr_in'left downto 3)))); - read_ack <= '1'; - state <= ACK; - end if; - when ACK => - read_ack <= '0'; - state <= IDLE; - end case; - else - state <= IDLE; - read_ack <= '0'; - end if; + ack <= wishbone_in.stb; + ack_obuf <= ack; end if; end if; end process; -- 2.30.2