Commit ded9f55e authored by Håkan Johansson's avatar Håkan Johansson
Browse files

VME core access arbiter for two clients.

parent cfddd0ac
Pipeline #13921 failed with stage
in 19 seconds
library ieee;
use ieee.std_logic_1164.all;
use work.vme_pkg.all;
-- Multiplex signals between the VME core and two clients.
--
-- Each client sees signals such as if it was the only
-- client connected to the core. (With the exception that it
-- may take a longer time before a 'go' request starts
-- to be processed).
entity vme_cli_arb is
port (
signal clk : in std_logic;
-- Signals to/from the first client.
-- For documentation on the signal purposes, see vme_bus.vhd.
signal p1_busy : out std_logic := '0';
signal p1_int_data_o : out vme_vec_64_t;
signal p1_int_data_strobe : out std_logic := c_DATA_CLEAR;
signal p1_int_go_consumed_strobe : out std_logic := '0';
signal p1_int_blt_decision_strobe : out std_logic := '0';
signal p1_int_err_code : out ERR_CODE := OK;
signal p1_int_addr : in vme_addr_t;
signal p1_int_data_i : in vme_vec_64_t;
signal p1_int_am_i : in am_vec_t;
signal p1_int_vme_rw : in std_logic;
signal p1_int_vme_go : in std_logic;
signal p1_int_blt_decided : in std_logic;
signal p1_int_blt_continue : in std_logic;
signal p1_int_berr_ok : in std_logic;
-- Signals to/from the second client.
signal p2_busy : out std_logic := '0';
signal p2_int_data_o : out vme_vec_64_t;
signal p2_int_data_strobe : out std_logic := c_DATA_CLEAR;
signal p2_int_go_consumed_strobe : out std_logic := '0';
signal p2_int_blt_decision_strobe : out std_logic := '0';
signal p2_int_err_code : out ERR_CODE := OK;
signal p2_int_addr : in vme_addr_t;
signal p2_int_data_i : in vme_vec_64_t;
signal p2_int_am_i : in am_vec_t;
signal p2_int_vme_rw : in std_logic;
signal p2_int_vme_go : in std_logic;
signal p2_int_blt_decided : in std_logic;
signal p2_int_blt_continue : in std_logic;
signal p2_int_berr_ok : in std_logic;
-- Signals to/from the VME core.
-- Directions inverted relative to the core.
signal vc_busy : in std_logic := '0';
signal vc_int_data_o : in vme_vec_64_t;
signal vc_int_data_strobe : in std_logic := c_DATA_CLEAR;
signal vc_int_go_consumed_strobe : in std_logic := '0';
signal vc_int_blt_decision_strobe : in std_logic := '0';
signal vc_int_err_code : in ERR_CODE := OK;
signal vc_int_addr : out vme_addr_t;
signal vc_int_data_i : out vme_vec_64_t;
signal vc_int_am_i : out am_vec_t;
signal vc_int_vme_rw : out std_logic;
signal vc_int_vme_go : out std_logic;
signal vc_int_blt_decided : out std_logic;
signal vc_int_blt_continue : out std_logic;
signal vc_int_berr_ok : out std_logic;
-- Dropped signals (since they cannot be multiplexed /
-- span multiple access cycles).
signal stop : in std_logic;
signal int_err_clear : in std_logic;
signal int_data_ack : in std_logic;
-- Changed behaviour:
-- Single-cycle strobe:
signal int_data_strobe : out std_logic := c_DATA_CLEAR;
);
end entity;
architecture rtl of vme_cli_arb is
signal state : vme_data_state := STOPPED;
signal addr_mode : addr_type_t;
signal transfer_mode : transfer_type_t;
-- In case we are not busy, which client would we like to
-- make active (if any).
signal want_1 : boolean;
signal want_2 : boolean;
-- Who do we start?
signal start_1 : boolean;
signal start_2 : boolean;
-- Who is live, i.e. is active, or activated this cycle.
signal live_1 : boolean;
signal live_2 : boolean;
-- Who is currently live.
signal active_1 : boolean := false;
signal active_2 : boolean := false;
-- Who will we prefer when we can take the next client, i.e. are
-- no longer busy?
signal prefer_1 : std_logic := '1';
begin
want_1 <= (go_1 and not go_2) or (go_1 and prefer_1);
want_2 <= (go_2 and not go_1) or (go_2 and not prefer_1);
start_1 <= not busy and want_1;
start_2 <= not busy and want_2;
-- We kill the live assignment as soon as busy is removed.
-- (Not really needed.)
live_1 <= (active_1 and busy) or start_1;
live_2 <= (active_2 and busy) or start_2;
process (clk)
begin
if (rising_edge(clk)) then
if (not busy) then
active_1 <= false;
active_2 <= false;
end if;
-- These assignments may overwrite the above, if we take another
-- client directly.
if (start_1) then
active_1 <= true;
prefer_1 <= false;
end if;
if (start_2) then
active_2 <= true;
prefer_1 <= true;
end if;
end if;
end process;
-- Signals to the VME core are taken from the live client:
-- If no client is live, we (arbitrarily) take the signals from
-- client 2. This does not matter, since the VME core will
-- only react to anything if the 'go' signal is given.
vc_int_addr <= p1_int_addr when live_1 else p2_int_addr;
vc_int_data_i <= p1_int_data_i when live_1 else p2_int_data_i;
vc_int_am_i <= p1_int_am_i when live_1 else p2_int_am_i;
vc_int_vme_rw <= p1_int_vme_rw when live_1 else p2_int_vme_rw;
vc_int_vme_go <= p1_int_vme_go when live_1 else p2_int_vme_go;
vc_int_blt_decided <= p1_int_blt_decided when live_1 else p2_int_blt_decided;
vc_int_blt_cont <= p1_int_blt_cont when live_1 else p2_int_blt_cont;
vc_int_berr_ok <= p1_int_berr_ok when live_1 else p2_int_berr_ok;
-- Signals to the clients from the VME core:
-- Data is passed directly through on the cycle they have been latched.
-- Otherwise, take the latched value:
p1_int_data_o <= vc_int_data_o when (live_1 and vc_int_data_strobe) else
p1_int_data_o_latched;
p2_int_data_o <= vc_int_data_o when (live_2 and vc_int_data_strobe) else
p2_int_data_o_latched;
-- The error code follows the data.
p1_int_err_code <= vc_int_err_code when (live_1 and vc_int_data_strobe) else
p1_int_err_code_latched;
p2_int_err_code <= vc_int_err_code when (live_2 and vc_int_data_strobe) else
p2_int_err_code_latched;
-- The strobes always go to the live client.
p1_int_data_strobe <= vc_int_data_strobe when live_1 else '0';
p2_int_data_strobe <= vc_int_data_strobe when live_2 else '0';
p1_int_go_consumed_strobe <= vc_int_go_consumed_strobe when live_1 else '0';
p2_int_go_consumed_strobe <= vc_int_go_consumed_strobe when live_2 else '0';
p1_int_blt_decision_strobe <= vc_int_blt_decision_strobe when live_1 else '0';
p2_int_blt_decision_strobe <= vc_int_blt_decision_strobe when live_2 else '0';
-- The busy of a client is simply while it is live.
-- This actually means that we will report busy some cycles
-- early. (But the clients are not likely to use this signal...)
p1_busy <= live_1;
p2_busy <= live_2;
end architecture;
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment