From 1a63c3970495c6fbe350c22d4dea0cdac6dc691e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 25 Sep 2019 16:54:25 +1000 Subject: [PATCH] Make it possible to change wishbone address size All that needs to be changed now is the size in wishbone_types.vhdl and the address decoder in soc.vhdl Signed-off-by: Benjamin Herrenschmidt --- dcache.vhdl | 16 ++++++++------- icache.vhdl | 13 +++++++----- simple_ram_behavioural.vhdl | 6 ++++-- simple_ram_behavioural_tb.vhdl | 37 +++++++++++++++++++--------------- wishbone_debug_master.vhdl | 2 +- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/dcache.vhdl b/dcache.vhdl index 087e71d..7657dbd 100644 --- a/dcache.vhdl +++ b/dcache.vhdl @@ -244,16 +244,16 @@ architecture rtl of dcache is end; -- Returns whether this is the last row of a line - function is_last_row(addr: std_ulogic_vector(63 downto 0)) return boolean is + function is_last_row(addr: wishbone_addr_type) return boolean is constant ones : std_ulogic_vector(ROW_LINEBITS-1 downto 0) := (others => '1'); begin return addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS) = ones; end; -- Return the address of the next row in the current cache line - function next_row_addr(addr: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is + function next_row_addr(addr: wishbone_addr_type) return std_ulogic_vector is variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0); - variable result : std_ulogic_vector(63 downto 0); + variable result : wishbone_addr_type; begin -- Is there no simpler way in VHDL to generate that 3 bits adder ? row_idx := addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS); @@ -573,6 +573,7 @@ begin wr_data => wr_data ); process(all) + variable tmp_adr : std_ulogic_vector(63 downto 0); begin -- Cache hit reads do_read <= '1'; @@ -595,7 +596,8 @@ begin -- Otherwise, we might be doing a reload wr_data <= wishbone_in.dat; wr_sel <= (others => '1'); - wr_addr <= std_ulogic_vector(to_unsigned(get_row(r1.wb.adr), ROW_BITS)); + tmp_adr := (r1.wb.adr'left downto 0 => r1.wb.adr, others => '0'); + wr_addr <= std_ulogic_vector(to_unsigned(get_row(tmp_adr), ROW_BITS)); end if; -- The two actual write cases here @@ -733,7 +735,7 @@ begin -- Prep for first wishbone read. We calculate the address of -- the start of the cache line -- - r1.wb.adr <= d_in.addr(63 downto LINE_OFF_BITS) & + r1.wb.adr <= d_in.addr(r1.wb.adr'left downto LINE_OFF_BITS) & (LINE_OFF_BITS-1 downto 0 => '0'); r1.wb.sel <= (others => '1'); r1.wb.we <= '0'; @@ -743,7 +745,7 @@ begin when OP_LOAD_NC => r1.wb.sel <= bus_sel; - r1.wb.adr <= d_in.addr(63 downto 3) & "000"; + r1.wb.adr <= d_in.addr(r1.wb.adr'left downto 3) & "000"; r1.wb.cyc <= '1'; r1.wb.stb <= '1'; r1.wb.we <= '0'; @@ -755,7 +757,7 @@ begin r1.update_valid <= '1'; end if; r1.wb.sel <= bus_sel; - r1.wb.adr <= d_in.addr(63 downto 3) & "000"; + r1.wb.adr <= d_in.addr(r1.wb.adr'left downto 3) & "000"; r1.wb.dat <= store_data; r1.wb.cyc <= '1'; r1.wb.stb <= '1'; diff --git a/icache.vhdl b/icache.vhdl index 95e37af..fccff9a 100644 --- a/icache.vhdl +++ b/icache.vhdl @@ -193,16 +193,17 @@ architecture rtl of icache is end; -- Returns whether this is the last row of a line - function is_last_row(addr: std_ulogic_vector(63 downto 0)) return boolean is + function is_last_row(addr: wishbone_addr_type) return boolean is constant ones : std_ulogic_vector(ROW_LINEBITS-1 downto 0) := (others => '1'); begin return addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS) = ones; end; -- Return the address of the next row in the current cache line - function next_row_addr(addr: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is + function next_row_addr(addr: wishbone_addr_type) + return std_ulogic_vector is variable row_idx : std_ulogic_vector(ROW_LINEBITS-1 downto 0); - variable result : std_ulogic_vector(63 downto 0); + variable result : wishbone_addr_type; begin -- Is there no simpler way in VHDL to generate that 3 bits adder ? row_idx := addr(LINE_OFF_BITS-1 downto ROW_OFF_BITS); @@ -297,6 +298,7 @@ begin wr_data => wishbone_in.dat ); process(all) + variable tmp_adr : std_ulogic_vector(63 downto 0); begin do_read <= '1'; do_write <= '0'; @@ -305,7 +307,8 @@ begin end if; cache_out(i) <= dout; rd_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS)); - wr_addr <= std_ulogic_vector(to_unsigned(get_row(r.wb.adr), ROW_BITS)); + tmp_adr := (r.wb.adr'left downto 0 => r.wb.adr, others => '0'); + wr_addr <= std_ulogic_vector(to_unsigned(get_row(tmp_adr), ROW_BITS)); end process; end generate; @@ -474,7 +477,7 @@ begin -- Prep for first wishbone read. We calculate the address of -- the start of the cache line -- - r.wb.adr <= i_in.nia(63 downto LINE_OFF_BITS) & + r.wb.adr <= i_in.nia(r.wb.adr'left downto LINE_OFF_BITS) & (LINE_OFF_BITS-1 downto 0 => '0'); r.wb.cyc <= '1'; r.wb.stb <= '1'; diff --git a/simple_ram_behavioural.vhdl b/simple_ram_behavioural.vhdl index afc3d51..0f6a90a 100644 --- a/simple_ram_behavioural.vhdl +++ b/simple_ram_behavioural.vhdl @@ -32,6 +32,7 @@ architecture behave of mw_soc_memory is begin wishbone_process: process(clk) variable ret_dat: std_ulogic_vector(63 downto 0) := (others => '0'); + variable adr: std_ulogic_vector(63 downto 0); begin wishbone_out.ack <= ret_ack and wishbone_in.cyc and wishbone_in.stb; wishbone_out.dat <= ret_dat; @@ -49,15 +50,16 @@ begin when IDLE => if wishbone_in.stb = '1' then -- 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, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier); + behavioural_write(wishbone_in.dat, adr, to_integer(unsigned(wishbone_in.sel)), identifier); reload <= reload + 1; ret_ack <= '1'; state <= ACK; else - behavioural_read(ret_dat, wishbone_in.adr, to_integer(unsigned(wishbone_in.sel)), identifier, reload); + 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); ret_ack <= '1'; state <= ACK; diff --git a/simple_ram_behavioural_tb.vhdl b/simple_ram_behavioural_tb.vhdl index 1527801..bee7d2e 100644 --- a/simple_ram_behavioural_tb.vhdl +++ b/simple_ram_behavioural_tb.vhdl @@ -16,6 +16,11 @@ architecture behave of simple_ram_behavioural_tb is signal w_in : wishbone_slave_out; signal w_out : wishbone_master_out; + + impure function to_adr(a: integer) return std_ulogic_vector is + begin + return std_ulogic_vector(to_unsigned(a, w_out.adr'length)); + end; begin simple_ram_0: entity work.mw_soc_memory generic map ( @@ -56,7 +61,7 @@ begin -- test various read lengths and alignments w_out.stb <= '1'; w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000000"; + w_out.adr <= to_adr(0); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -67,7 +72,7 @@ begin w_out.stb <= '1'; w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000001"; + w_out.adr <= to_adr(1); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -78,7 +83,7 @@ begin w_out.stb <= '1'; w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000007"; + w_out.adr <= to_adr(7); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -89,7 +94,7 @@ begin w_out.stb <= '1'; w_out.sel <= "00000011"; - w_out.adr <= x"0000000000000000"; + w_out.adr <= to_adr(0); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -100,7 +105,7 @@ begin w_out.stb <= '1'; w_out.sel <= "00000011"; - w_out.adr <= x"0000000000000001"; + w_out.adr <= to_adr(1); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -111,7 +116,7 @@ begin w_out.stb <= '1'; w_out.sel <= "00000011"; - w_out.adr <= x"0000000000000007"; + w_out.adr <= to_adr(7); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -122,7 +127,7 @@ begin w_out.stb <= '1'; w_out.sel <= "00001111"; - w_out.adr <= x"0000000000000000"; + w_out.adr <= to_adr(0); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -133,7 +138,7 @@ begin w_out.stb <= '1'; w_out.sel <= "00001111"; - w_out.adr <= x"0000000000000001"; + w_out.adr <= to_adr(1); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -144,7 +149,7 @@ begin w_out.stb <= '1'; w_out.sel <= "00001111"; - w_out.adr <= x"0000000000000007"; + w_out.adr <= to_adr(7); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -155,7 +160,7 @@ begin w_out.stb <= '1'; w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000000"; + w_out.adr <= to_adr(0); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -166,7 +171,7 @@ begin w_out.stb <= '1'; w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000001"; + w_out.adr <= to_adr(1); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -177,7 +182,7 @@ begin w_out.stb <= '1'; w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000007"; + w_out.adr <= to_adr(7); assert w_in.ack = '0'; wait for clk_period; assert w_in.ack = '1'; @@ -189,7 +194,7 @@ begin -- test various write lengths and alignments w_out.stb <= '1'; w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000000"; + w_out.adr <= to_adr(0); w_out.we <= '1'; w_out.dat(7 downto 0) <= x"0F"; assert w_in.ack = '0'; @@ -201,7 +206,7 @@ begin w_out.stb <= '1'; w_out.sel <= "00000001"; - w_out.adr <= x"0000000000000000"; + w_out.adr <= to_adr(0); w_out.we <= '0'; assert w_in.ack = '0'; wait for clk_period; @@ -213,7 +218,7 @@ begin w_out.stb <= '1'; w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000007"; + w_out.adr <= to_adr(7); w_out.we <= '1'; w_out.dat <= x"BADC0FFEBADC0FFE"; assert w_in.ack = '0'; @@ -225,7 +230,7 @@ begin w_out.stb <= '1'; w_out.sel <= "11111111"; - w_out.adr <= x"0000000000000007"; + w_out.adr <= to_adr(7); w_out.we <= '0'; assert w_in.ack = '0'; wait for clk_period; diff --git a/wishbone_debug_master.vhdl b/wishbone_debug_master.vhdl index b8d936b..3ba6b21 100644 --- a/wishbone_debug_master.vhdl +++ b/wishbone_debug_master.vhdl @@ -117,7 +117,7 @@ begin dmi_ack <= dmi_req when (dmi_addr /= DBG_WB_DATA or state = DMI_WAIT) else '0'; -- Some WB signals are direct wires from registers or DMI - wb_out.adr <= reg_addr; + wb_out.adr <= reg_addr(wb_out.adr'left downto 0); wb_out.dat <= dmi_din; wb_out.sel <= reg_ctrl(7 downto 0); wb_out.we <= dmi_wr; -- 2.30.2