Skip to content
Snippets Groups Projects
Commit 28ff4e33 authored by Reinier van der Walle's avatar Reinier van der Walle
Browse files

added axi4_lite_mm_bridge

parent ae0b9b89
No related branches found
No related tags found
2 merge requests!319Resolve HPR-87,!315Resolve HPR-87
Pipeline #46760 passed
......@@ -8,6 +8,7 @@ synth_files =
src/vhdl/axi4_lite_pkg.vhd
src/vhdl/axi4_stream_pkg.vhd
src/vhdl/axi4_stream_dp_bridge.vhd
src/vhdl/axi4_lite_mm_bridge.vhd
src/vhdl/mem_to_axi4_lite.vhd
test_bench_files =
......
-- --------------------------------------------------------------------------
-- Copyright 2023
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- --------------------------------------------------------------------------
-- Author:
-- . Reinier van der Walle
-- Purpose:
-- . Bridge between AXI4 lite and MM interfaces.
-- Description:
-- . This core consists of:
-- . Combinatorial translation of one interface to the other.
-- . Ready latency adapters as AXI4-Lite has RL = 0 and MM has RL = 1.
-- . Details:
-- . g_active_low_rst should be set to TRUE when in_rst is active low. This is useful as an
-- AXI4 interface often comes with an active-low reset while DP comes with an active-high
-- reset.
LIBRARY IEEE, common_lib, dp_lib, technology_lib, mm_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE work.axi4_stream_pkg.ALL;
USE work.axi4_lite_pkg.ALL;
ENTITY axi4_lite_mm_bridge IS
GENERIC (
g_active_low_rst : BOOLEAN := FALSE -- When True, in_rst is interpreted as active-low.
);
PORT (
in_clk : IN STD_LOGIC := '0';
in_rst : IN STD_LOGIC := is_true(g_active_low_rst); -- Default state is "not in reset".
aresetn : OUT STD_LOGIC := '1'; -- AXI4 active-low reset
mm_rst : OUT STD_LOGIC := '0'; -- MM active-high reset
axi4_in_copi : IN t_axi4_lite_copi := c_axi4_lite_copi_rst;
axi4_in_cipo : OUT t_axi4_lite_cipo := c_axi4_lite_cipo_rst;
axi4_out_copi : OUT t_axi4_lite_copi := c_axi4_lite_copi_rst;
axi4_out_cipo : IN t_axi4_lite_cipo := c_axi4_lite_cipo_rst;
mm_in_copi : IN t_mem_copi := c_mem_copi_rst;
mm_in_cipo : OUT t_mem_cipo := c_mem_cipo_rst;
mm_out_copi : OUT t_mem_copi := c_mem_copi_rst;
mm_out_cipo : IN t_mem_cipo := c_mem_cipo_rst
);
END axi4_lite_mm_bridge;
ARCHITECTURE str OF axi4_lite_mm_bridge IS
-- Sum of all t_mem_copi fields widths (synthesis will optimize away unused address and data bits)
CONSTANT c_data_w : NATURAL := c_mem_address_w + c_mem_data_w + 2; -- 32 + 72 + 1 (wr) + 1 (rd) = 106
SIGNAL i_rst : STD_LOGIC := '0'; -- Internal active high reset.
SIGNAL axi4_from_mm_copi : t_mem_copi;
SIGNAL axi4_from_mm_cipo : t_mem_cipo;
SIGNAL mm_from_axi4_copi : t_mem_copi;
SIGNAL mm_from_axi4_cipo : t_mem_cipo;
SIGNAL rl_decr_snk_ready : STD_LOGIC := '0';
SIGNAL rl_decr_snk_dat : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
SIGNAL rl_decr_snk_val : STD_LOGIC := '0';
SIGNAL rl_decr_src_ready : STD_LOGIC := '0';
SIGNAL rl_decr_src_dat : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
SIGNAL rl_incr_snk_ready : STD_LOGIC := '0';
SIGNAL rl_incr_snk_dat : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
SIGNAL rl_incr_snk_val : STD_LOGIC := '0';
SIGNAL rl_incr_src_ready : STD_LOGIC := '0';
SIGNAL rl_incr_src_dat : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
SIGNAL d_bvalid : STD_LOGIC := '0';
SIGNAL q_bvalid : STD_LOGIC := '0';
BEGIN
i_rst <= NOT in_rst WHEN g_active_low_rst ELSE in_rst;
aresetn <= NOT i_rst;
mm_rst <= i_rst;
-----------------------------------------------
-- Translate MM to AXI4 Lite and RL 1 to RL 0
-----------------------------------------------
-- Decrease ready latency
rl_decr_snk_dat <= func_slv_concat(mm_in_copi.address, mm_in_copi.wrdata, slv(mm_in_copi.wr), slv(mm_in_copi.rd));
rl_decr_snk_val <= mm_in_copi.wr OR mm_in_copi.rd;
u_common_rl_decrease : ENTITY common_lib.common_rl_decrease
GENERIC MAP (
g_dat_w => c_axi4_lite_data_w
)
PORT MAP (
rst => i_rst,
clk => in_clk,
-- Sink RL = 1
snk_out_ready => rl_decr_snk_ready,
snk_in_dat => rl_decr_snk_dat,
snk_in_val => rl_decr_snk_val,
-- Source RL = 0
src_in_ready => rl_decr_src_ready,
src_out_dat => rl_decr_src_dat,
src_out_val => OPEN
);
-- Account for opposite meaning of waitrequest and ready
mm_in_cipo.waitrequest <= NOT rl_decr_snk_ready;
rl_decr_src_ready <= NOT axi4_from_mm_cipo.waitrequest;
-- Wire remaining copi/cipo signals
mm_from_axi4_cipo.rddata <= mm_out_cipo.rddata;
mm_from_axi4_cipo.rdval <= mm_out_cipo.rdval;
axi4_from_mm_copi.address <= func_slv_extract(c_mem_address_w, c_mem_data_w, 1, 1, rl_decr_src_dat, 0);
axi4_from_mm_copi.wrdata <= func_slv_extract(c_mem_address_w, c_mem_data_w, 1, 1, rl_decr_src_dat, 1);
axi4_from_mm_copi.wr <= sl(func_slv_extract(c_mem_address_w, c_mem_data_w, 1, 1, rl_decr_src_dat, 2));
axi4_from_mm_copi.rd <= sl(func_slv_extract(c_mem_address_w, c_mem_data_w, 1, 1, rl_decr_src_dat, 3));
-- MM to AXI4 Lite
axi4_out_copi.awaddr <= axi4_from_mm_copi.address;
axi4_out_copi.awprot <= (OTHERS => '0');
axi4_out_copi.awvalid <= axi4_from_mm_copi.wr;
axi4_out_copi.wdata <= axi4_from_mm_copi.wrdata(c_axi4_lite_data_w-1 DOWNTO 0);
axi4_out_copi.wstrb <= (OTHERS => '1'); -- Either ignored or all bytes selected.
axi4_out_copi.wvalid <= axi4_from_mm_copi.wr;
axi4_out_copi.bready <= '1'; -- Unsupported by MM, assuming always ready.
axi4_out_copi.araddr <= axi4_from_mm_copi.address;
axi4_out_copi.arprot <= (OTHERS => '0');
axi4_out_copi.arvalid <= axi4_from_mm_copi.rd;
axi4_out_copi.rready <= '1'; -- Unsupported by MM, assuming always ready.
axi4_from_mm_cipo.rddata(c_axi4_lite_data_w-1 DOWNTO 0) <= axi4_out_cipo.rdata;
axi4_from_mm_cipo.rdval <= axi4_out_cipo.rvalid;
axi4_from_mm_cipo.waitrequest <= NOT (axi4_out_cipo.awready AND axi4_out_cipo.wready AND axi4_out_cipo.arready);
-------------------------------------------
-- Translate AXI4 to MM and RL 0 to RL 1
-------------------------------------------
-- AXI4 Lite to MM
mm_from_axi4_copi.address <= axi4_in_copi.awaddr WHEN axi4_in_copi.awvalid = '1' ELSE axi4_in_copi.araddr;
mm_from_axi4_copi.wrdata(c_axi4_lite_data_w-1 DOWNTO 0) <= axi4_in_copi.wdata;
mm_from_axi4_copi.wr <= axi4_in_copi.awvalid;
mm_from_axi4_copi.rd <= axi4_in_copi.arvalid;
axi4_in_cipo.awready <= NOT mm_from_axi4_cipo.waitrequest;
axi4_in_cipo.wready <= NOT mm_from_axi4_cipo.waitrequest;
axi4_in_cipo.bresp <= c_axi4_lite_resp_okay;
axi4_in_cipo.bvalid <= q_bvalid;
axi4_in_cipo.arready <= NOT mm_from_axi4_cipo.waitrequest;
axi4_in_cipo.rdata <= mm_from_axi4_cipo.rddata(c_axi4_lite_data_w-1 DOWNTO 0);
axi4_in_cipo.rresp <= c_axi4_lite_resp_okay;
axi4_in_cipo.rvalid <= mm_from_axi4_cipo.rdval;
-- Generate bvalid
q_bvalid <= d_bvalid WHEN rising_edge(in_clk);
p_bvalid : PROCESS(i_rst, mm_from_axi4_cipo, mm_from_axi4_copi, axi4_in_copi)
BEGIN
d_bvalid <= q_bvalid;
IF mm_from_axi4_cipo.waitrequest = '0' AND mm_from_axi4_copi.wr = '1' THEN
d_bvalid <= '1';
ELSIF axi4_in_copi.bready = '1' THEN
d_bvalid <= '0';
END IF;
IF i_rst = '1' THEN
d_bvalid <= '0';
END IF;
END PROCESS;
-- Increase ready latency
rl_incr_snk_dat <= func_slv_concat(mm_from_axi4_copi.address, mm_from_axi4_copi.wrdata, slv(mm_from_axi4_copi.wr), slv(mm_from_axi4_copi.rd));
rl_incr_snk_val <= mm_from_axi4_copi.wr OR mm_from_axi4_copi.rd;
u_common_rl_increase : ENTITY common_lib.common_rl_increase
GENERIC MAP (
g_dat_w => c_axi4_lite_data_w
)
PORT MAP (
rst => i_rst,
clk => in_clk,
-- Sink RL = 0
snk_out_ready => rl_incr_snk_ready,
snk_in_dat => rl_incr_snk_dat,
snk_in_val => rl_incr_snk_val,
-- Source RL = 1
src_in_ready => rl_incr_src_ready,
src_out_dat => rl_incr_src_dat,
src_out_val => OPEN
);
-- Account for opposite meaning of waitrequest and ready
mm_from_axi4_cipo.waitrequest <= NOT rl_incr_snk_ready;
rl_incr_src_ready <= NOT mm_out_cipo.waitrequest;
-- Wire remaining copi/cipo signals
mm_from_axi4_cipo.rddata <= mm_out_cipo.rddata;
mm_from_axi4_cipo.rdval <= mm_out_cipo.rdval;
mm_out_copi.address <= func_slv_extract(c_mem_address_w, c_mem_data_w, 1, 1, rl_incr_src_dat, 0);
mm_out_copi.wrdata <= func_slv_extract(c_mem_address_w, c_mem_data_w, 1, 1, rl_incr_src_dat, 1);
mm_out_copi.wr <= sl(func_slv_extract(c_mem_address_w, c_mem_data_w, 1, 1, rl_incr_src_dat, 2));
mm_out_copi.rd <= sl(func_slv_extract(c_mem_address_w, c_mem_data_w, 1, 1, rl_incr_src_dat, 3));
END str;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment