diff --git a/src/axi3-interconnect-aw-router.vhd b/src/axi3-interconnect-aw-router.vhd index 211152f..a36c592 100644 --- a/src/axi3-interconnect-aw-router.vhd +++ b/src/axi3-interconnect-aw-router.vhd @@ -22,14 +22,16 @@ end entity axi3intercon_aw_router; architecture RTL of axi3intercon_aw_router is alias clk is aclk; - type aw_state_t is (READY, ACTIVE, BLK); + type aw_state_t is (AW_READY, AW_ACTIVE, AW_BLOCK); type aw_states_t is array (0 to MASTER_COUNT - 1) of aw_state_t; - signal aw_states : aw_states_t; + signal aw_states : aw_states_t; + signal write_locks_s : write_locks_t(0 to MASTER_COUNT - 1); begin - aw_router : process(clk, rst) is - variable slave_block : std_logic_vector(0 to SLAVE_COUNT - 1) := (others => '0'); - variable slave_idx : integer range 0 to SLAVE_COUNT := SLAVE_COUNT; -- 1 more slave than connected for handling bad requests. + write_locks <= write_locks_s; + 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; @@ -44,19 +46,44 @@ begin begin if rst = '1' then for i in 0 to MASTER_COUNT - 1 loop - aw_states(i) <= READY; + aw_states(i) <= AW_READY; + masters_in(i).awready <= '1'; end loop; - slave_block := (others => '0'); elsif rising_edge(clk) then - for i in MASTER_COUNT - 1 downto 0 loop -- Loop for every master + for i in 0 to MASTER_COUNT - 1 loop -- Loop for every master case aw_states(i) is - when READY => - if masters_out(i).awvalid = '1' then + 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); - -- TODO: Write router itself - -- TODO: lock output + 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; + when AW_ACTIVE => + if slaves_out(write_locks_s(i).slave_idx).awready = '1' then + slaves_in(write_locks_s(i).slave_idx).awvalid <= '0'; + aw_states(i) <= AW_BLOCK; + end if; + 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; end if; - when others => null; end case; end loop;