diff --git a/src/axi3-interconnect-ar-router.vhd b/src/axi3-interconnect-ar-router.vhd new file mode 100644 index 0000000..49be048 --- /dev/null +++ b/src/axi3-interconnect-ar-router.vhd @@ -0,0 +1,80 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.axi3intercon_pkg.all; +use work.axi_ar_router_pkg.all; + +entity axi3intercon_ar_router is + port( + aclk : in std_logic; + rst : in std_logic; + masters_out : in axi_ar_masters_out_t(0 to MASTER_COUNT - 1); + masters_in : out axi_ar_masters_in_t(0 to MASTER_COUNT - 1); + slaves_out : in axi_ar_slaves_out_t(0 to SLAVE_COUNT); + slaves_in : out axi_ar_slaves_in_t(0 to SLAVE_COUNT); + address_array : in axi_slave_addresses_t(0 to SLAVE_COUNT - 1); + mask_array : in axi_slave_addresses_t(0 to SLAVE_COUNT - 1) + ); +end entity axi3intercon_ar_router; + +architecture RTL of axi3intercon_ar_router is + alias clk is aclk; + type ar_state_t is (AR_READY, AR_ACTIVE); + type ar_states_t is array (0 to MASTER_COUNT - 1) of ar_state_t; + signal ar_states : ar_states_t; + signal arready_s : std_logic_vector(0 to MASTER_COUNT - 1); + type slave_indexes_t is array (0 to MASTER_COUNT - 1) of integer range 0 to SLAVE_COUNT; +begin + arready_gen : for i in 0 to MASTER_COUNT - 1 generate + masters_in(i).arready <= arready_s(i); + end generate arready_gen; + + ar_router : process(clk, rst) is + variable slave_idx : slave_indexes_t; + variable slave_in_use : std_logic_vector(0 to SLAVE_COUNT); + + begin + if rst = '1' then + for i in 0 to MASTER_COUNT - 1 loop + ar_states(i) <= AR_READY; + + end loop; + slave_in_use := (others => '0'); + arready_s <= (others => '1'); + elsif rising_edge(clk) then + for i in 0 to MASTER_COUNT - 1 loop -- Loop for every master + case ar_states(i) is + when AR_READY => + arready_s(i) <= '1'; + if masters_out(i).arvalid = '1' and arready_s(i) = '1' then + slave_idx(i) := calculate_slave(masters_out(i).araddr, address_array, mask_array); + if slave_in_use(slave_idx(i)) /= '1' then + slave_in_use(slave_idx(i)) := '1'; + masters_in(i).arready <= '0'; + -- Write request to slave + slaves_in(slave_idx(i)).araddr <= masters_out(i).araddr; + slaves_in(slave_idx(i)).arid <= std_logic_vector(to_unsigned(i, WID_SLAVE_BITS - WID_MASTER_BITS - 1)) & masters_out(i).arid; + slaves_in(slave_idx(i)).arburst <= masters_out(i).arburst; + slaves_in(slave_idx(i)).arcache <= masters_out(i).arcache; + slaves_in(slave_idx(i)).arlen <= masters_out(i).arlen; + slaves_in(slave_idx(i)).arlock <= masters_out(i).arlock; + slaves_in(slave_idx(i)).arprot <= masters_out(i).arprot; + slaves_in(slave_idx(i)).arsize <= masters_out(i).arsize; + slaves_in(slave_idx(i)).arvalid <= '1'; + ar_states(i) <= AR_ACTIVE; + end if; + end if; + when AR_ACTIVE => + if slaves_out(slave_idx(i)).arready = '1' then + slaves_in(slave_idx(i)).arvalid <= '0'; + ar_states(i) <= AR_READY; + slave_in_use(slave_idx(i)) := '0'; + end if; + end case; + + end loop; + end if; + end process ar_router; + +end architecture RTL; diff --git a/src/axi3-interconnect-ar-router_pkg.vhd b/src/axi3-interconnect-ar-router_pkg.vhd new file mode 100644 index 0000000..051ccbe --- /dev/null +++ b/src/axi3-interconnect-ar-router_pkg.vhd @@ -0,0 +1,14 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.axi3intercon_pkg.all; + +package axi_ar_router_pkg is + type axi_ar_masters_in_t is array (natural range <>) of master_ar_in_t; + type axi_ar_masters_out_t is array (natural range <>) of master_ar_out_t; + type axi_ar_slaves_out_t is array (natural range <>) of slave_ar_out_t; + type axi_ar_slaves_in_t is array (natural range <>) of slave_ar_in_t; +end package axi_ar_router_pkg; + +-- package body filename is +-- end package body filename; \ No newline at end of file diff --git a/src/axi3-interconnect-aw-router.vhd b/src/axi3-interconnect-aw-router.vhd index a36c592..e42515d 100644 --- a/src/axi3-interconnect-aw-router.vhd +++ b/src/axi3-interconnect-aw-router.vhd @@ -32,46 +32,49 @@ begin aw_router : process(clk, rst) is variable slave_idx : integer range 0 to SLAVE_COUNT := SLAVE_COUNT; -- 1 more slave than connected for handling bad requests. variable slave_in_use : std_logic_vector(0 to SLAVE_COUNT); - procedure calculate_slave(address : in std_logic_vector(ADDRESS_BITS - 1 downto 0)) is - begin - slave_idx := SLAVE_COUNT; - for i in 0 to SLAVE_COUNT - 1 loop - if (address and mask_array(i)) = address_array(i) then - slave_idx := i; - end if; - end loop; - - end procedure calculate_slave; + -- procedure calculate_slave(address : in std_logic_vector(ADDRESS_BITS - 1 downto 0)) is + -- begin + -- slave_idx := SLAVE_COUNT; + -- for i in 0 to SLAVE_COUNT - 1 loop + -- if (address and mask_array(i)) = address_array(i) then + -- slave_idx := i; + -- end if; + -- end loop; + -- + -- end procedure calculate_slave; begin if rst = '1' then for i in 0 to MASTER_COUNT - 1 loop aw_states(i) <= AW_READY; masters_in(i).awready <= '1'; + slave_in_use := (others => '0'); end loop; elsif rising_edge(clk) then for i in 0 to MASTER_COUNT - 1 loop -- Loop for every master case aw_states(i) is when AW_READY => masters_in(i).awready <= '1'; - if masters_out(i).awvalid = '1' and masters_in(i).awready = '1' and slave_in_use(i) = '0' then -- check awready. just to prevent glitches - calculate_slave(masters_out(i).awaddr); - write_locks_s(i).slave_idx <= slave_idx; - write_locks_s(i).locked <= '1'; - slave_in_use(slave_idx) := '1'; - masters_in(i).awready <= '0'; - -- output request to slave - slaves_in(slave_idx).awaddr <= masters_out(i).awaddr; - slaves_in(slave_idx).awid <= std_logic_vector(to_unsigned(i, WID_SLAVE_BITS - WID_MASTER_BITS - 1)) & masters_out(i).awid; - slaves_in(slave_idx).awburst <= masters_out(i).awburst; - slaves_in(slave_idx).awcache <= masters_out(i).awcache; - slaves_in(slave_idx).awlen <= masters_out(i).awlen; - slaves_in(slave_idx).awlock <= masters_out(i).awlock; - slaves_in(slave_idx).awprot <= masters_out(i).awprot; - slaves_in(slave_idx).awsize <= masters_out(i).awsize; - slaves_in(slave_idx).awvalid <= '1'; - -- Active state waits for awready to be asserted - aw_states(i) <= AW_ACTIVE; + if masters_out(i).awvalid = '1' and masters_in(i).awready = '1' then -- check awready. just to prevent glitches + slave_idx := calculate_slave(masters_out(i).awaddr, address_array, mask_array); + if slave_in_use(slave_idx) /= '1' then + write_locks_s(i).slave_idx <= slave_idx; + write_locks_s(i).locked <= '1'; + slave_in_use(slave_idx) := '1'; + masters_in(i).awready <= '0'; + -- output request to slave + slaves_in(slave_idx).awaddr <= masters_out(i).awaddr; + slaves_in(slave_idx).awid <= std_logic_vector(to_unsigned(i, WID_SLAVE_BITS - WID_MASTER_BITS - 1)) & masters_out(i).awid; + slaves_in(slave_idx).awburst <= masters_out(i).awburst; + slaves_in(slave_idx).awcache <= masters_out(i).awcache; + slaves_in(slave_idx).awlen <= masters_out(i).awlen; + slaves_in(slave_idx).awlock <= masters_out(i).awlock; + slaves_in(slave_idx).awprot <= masters_out(i).awprot; + slaves_in(slave_idx).awsize <= masters_out(i).awsize; + slaves_in(slave_idx).awvalid <= '1'; + -- Active state waits for awready to be asserted + aw_states(i) <= AW_ACTIVE; + end if; end if; when AW_ACTIVE => if slaves_out(write_locks_s(i).slave_idx).awready = '1' then @@ -81,8 +84,8 @@ begin when AW_BLOCK => if write_releases(i) = '1' then slave_in_use(write_locks_s(i).slave_idx) := '0'; - write_locks_s(i).locked <= '0'; - aw_states(i) <= AW_READY; + write_locks_s(i).locked <= '0'; + aw_states(i) <= AW_READY; end if; end case; diff --git a/src/axi3-interconnect.vhd b/src/axi3-interconnect.vhd index 136c5ef..b31dea3 100644 --- a/src/axi3-interconnect.vhd +++ b/src/axi3-interconnect.vhd @@ -4,6 +4,7 @@ use ieee.numeric_std.all; -- "work" denotes the curent library. Similar to this in C++, C# etc... use work.axi3intercon_pkg.all; use work.axi_aw_router_pkg.all; +use work.axi_ar_router_pkg.all; entity axi3intercon is port( diff --git a/src/axi3-interconnect_pkg.vhd b/src/axi3-interconnect_pkg.vhd index dbe2fbc..86e3049 100644 --- a/src/axi3-interconnect_pkg.vhd +++ b/src/axi3-interconnect_pkg.vhd @@ -88,7 +88,7 @@ package axi3intercon_pkg is end record master_ar_out_t; type master_ar_in_t is record - awready : std_logic; + arready : std_logic; end record master_ar_in_t; type slave_ar_in_t is record @@ -103,7 +103,7 @@ package axi3intercon_pkg is arvalid : std_logic; -- Data valid end record slave_ar_in_t; - subtype slave_ar_out is master_ar_in_t; + subtype slave_ar_out_t is master_ar_in_t; -- type decalarations for W channel type master_w_out_t is record @@ -128,7 +128,7 @@ package axi3intercon_pkg is wready : std_logic; end record master_w_in_t; - subtype slave_w_out is master_w_in_t; + subtype slave_w_out_t is master_w_in_t; -- Type declarations for R channel type master_r_in_t is record @@ -204,8 +204,8 @@ package axi3intercon_pkg is type axi_slave_out_t is record aw : slave_aw_out_t; - ar : slave_ar_out; - w : slave_w_out; + ar : slave_ar_out_t; + w : slave_w_out_t; r : slave_r_out_t; b : slave_b_out_t; end record axi_slave_out_t; @@ -219,7 +219,23 @@ package axi3intercon_pkg is -- Address translation mapping type axi_slave_addresses_t is array (natural range <>) of std_logic_vector(ADDRESS_BITS - 1 downto 0); + function calculate_slave(address : in std_logic_vector(ADDRESS_BITS - 1 downto 0); + address_array : in axi_slave_addresses_t(0 to SLAVE_COUNT - 1); + mask_array : in axi_slave_addresses_t(0 to SLAVE_COUNT - 1)) return integer; end package axi3intercon_pkg; --- package body axi3intercon_pkg is --- end package body axi3intercon_pkg; +package body axi3intercon_pkg is + function calculate_slave(address : in std_logic_vector(ADDRESS_BITS - 1 downto 0); + address_array : in axi_slave_addresses_t(0 to SLAVE_COUNT - 1); + mask_array : in axi_slave_addresses_t(0 to SLAVE_COUNT - 1)) return integer is + variable slave_idx : integer range 0 to SLAVE_COUNT := SLAVE_COUNT; + begin + slave_idx := SLAVE_COUNT; + for i in 0 to SLAVE_COUNT - 1 loop + if (address and mask_array(i)) = address_array(i) then + slave_idx := i; + end if; + end loop; + return slave_idx; + end function calculate_slave; +end package body axi3intercon_pkg;