dcache: Rework RAM wrapper to synthetize better on Xilinx

The global wr_en signal is causing Vivado to generate two TDP (True Dual Port)
block RAMs instead of one SDP (Simple Dual Port) for each cache way. Remove
it and instead apply a AND to the individual byte write enables.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
jtag-port
Benjamin Herrenschmidt 5 years ago
parent a9178ed0c1
commit ecaa5e2fb2

@ -16,7 +16,6 @@ entity cache_ram is
rd_en : in std_logic; rd_en : in std_logic;
rd_addr : in std_logic_vector(ROW_BITS - 1 downto 0); rd_addr : in std_logic_vector(ROW_BITS - 1 downto 0);
rd_data : out std_logic_vector(WIDTH - 1 downto 0); rd_data : out std_logic_vector(WIDTH - 1 downto 0);
wr_en : in std_logic;
wr_sel : in std_logic_vector(WIDTH/8 - 1 downto 0); wr_sel : in std_logic_vector(WIDTH/8 - 1 downto 0);
wr_addr : in std_logic_vector(ROW_BITS - 1 downto 0); wr_addr : in std_logic_vector(ROW_BITS - 1 downto 0);
wr_data : in std_logic_vector(WIDTH - 1 downto 0) wr_data : in std_logic_vector(WIDTH - 1 downto 0)
@ -31,8 +30,6 @@ architecture rtl of cache_ram is
signal ram : ram_type; signal ram : ram_type;
attribute ram_style : string; attribute ram_style : string;
attribute ram_style of ram : signal is "block"; attribute ram_style of ram : signal is "block";
attribute ram_decomp : string;
attribute ram_decomp of ram : signal is "power";


signal rd_data0 : std_logic_vector(WIDTH - 1 downto 0); signal rd_data0 : std_logic_vector(WIDTH - 1 downto 0);


@ -41,23 +38,25 @@ begin
variable lbit : integer range 0 to WIDTH - 1; variable lbit : integer range 0 to WIDTH - 1;
variable mbit : integer range 0 to WIDTH - 1; variable mbit : integer range 0 to WIDTH - 1;
variable widx : integer range 0 to SIZE - 1; variable widx : integer range 0 to SIZE - 1;
constant sel0 : std_logic_vector(WIDTH/8 - 1 downto 0)
:= (others => '0');
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if wr_en = '1' then if TRACE then
if TRACE then if wr_sel /= sel0 then
report "write a:" & to_hstring(wr_addr) & report "write a:" & to_hstring(wr_addr) &
" sel:" & to_hstring(wr_sel) & " sel:" & to_hstring(wr_sel) &
" dat:" & to_hstring(wr_data); " dat:" & to_hstring(wr_data);
end if; end if;
for i in 0 to WIDTH/8-1 loop end if;
lbit := i * 8; for i in 0 to WIDTH/8-1 loop
mbit := lbit + 7; lbit := i * 8;
widx := to_integer(unsigned(wr_addr)); mbit := lbit + 7;
if wr_sel(i) = '1' then widx := to_integer(unsigned(wr_addr));
ram(widx)(mbit downto lbit) <= wr_data(mbit downto lbit); if wr_sel(i) = '1' then
end if; ram(widx)(mbit downto lbit) <= wr_data(mbit downto lbit);
end loop; end if;
end if; end loop;
if rd_en = '1' then if rd_en = '1' then
rd_data0 <= ram(to_integer(unsigned(rd_addr))); rd_data0 <= ram(to_integer(unsigned(rd_addr)));
if TRACE then if TRACE then

@ -923,6 +923,7 @@ begin
signal wr_addr : std_ulogic_vector(ROW_BITS-1 downto 0); signal wr_addr : std_ulogic_vector(ROW_BITS-1 downto 0);
signal wr_data : std_ulogic_vector(wishbone_data_bits-1 downto 0); signal wr_data : std_ulogic_vector(wishbone_data_bits-1 downto 0);
signal wr_sel : std_ulogic_vector(ROW_SIZE-1 downto 0); signal wr_sel : std_ulogic_vector(ROW_SIZE-1 downto 0);
signal wr_sel_m : std_ulogic_vector(ROW_SIZE-1 downto 0);
signal dout : cache_row_t; signal dout : cache_row_t;
begin begin
way: entity work.cache_ram way: entity work.cache_ram
@ -936,8 +937,7 @@ begin
rd_en => do_read, rd_en => do_read,
rd_addr => rd_addr, rd_addr => rd_addr,
rd_data => dout, rd_data => dout,
wr_en => do_write, wr_sel => wr_sel_m,
wr_sel => wr_sel,
wr_addr => wr_addr, wr_addr => wr_addr,
wr_data => wr_data wr_data => wr_data
); );
@ -986,7 +986,14 @@ begin
severity FAILURE; severity FAILURE;
do_write <= '1'; do_write <= '1';
end if; end if;
end process;
-- Mask write selects with do_write since BRAM doesn't
-- have a global write-enable
for i in 0 to ROW_SIZE-1 loop
wr_sel_m(i) <= wr_sel(i) and do_write;
end loop;

end process;
end generate; end generate;


-- --

@ -340,6 +340,7 @@ begin
signal rd_addr : std_ulogic_vector(ROW_BITS-1 downto 0); signal rd_addr : std_ulogic_vector(ROW_BITS-1 downto 0);
signal wr_addr : std_ulogic_vector(ROW_BITS-1 downto 0); signal wr_addr : std_ulogic_vector(ROW_BITS-1 downto 0);
signal dout : cache_row_t; signal dout : cache_row_t;
signal wr_sel : std_ulogic_vector(ROW_SIZE-1 downto 0);
begin begin
way: entity work.cache_ram way: entity work.cache_ram
generic map ( generic map (
@ -351,8 +352,7 @@ begin
rd_en => do_read, rd_en => do_read,
rd_addr => rd_addr, rd_addr => rd_addr,
rd_data => dout, rd_data => dout,
wr_en => do_write, wr_sel => wr_sel,
wr_sel => (others => '1'),
wr_addr => wr_addr, wr_addr => wr_addr,
wr_data => wishbone_in.dat wr_data => wishbone_in.dat
); );
@ -366,6 +366,9 @@ begin
cache_out(i) <= dout; cache_out(i) <= dout;
rd_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS)); rd_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS));
wr_addr <= std_ulogic_vector(to_unsigned(r.store_row, ROW_BITS)); wr_addr <= std_ulogic_vector(to_unsigned(r.store_row, ROW_BITS));
for i in 0 to ROW_SIZE-1 loop
wr_sel(i) <= do_write;
end loop;
end process; end process;
end generate; end generate;

Loading…
Cancel
Save