OpenCores
URL https://opencores.org/ocsvn/wb_tk/wb_tk/trunk

Subversion Repositories wb_tk

[/] [wb_tk/] [trunk/] [wb_arbiter.vhd] - Rev 7

Compare with Previous | Blame | View Log

--
--  Wishbone bus toolkit.
--
--  (c) Copyright Andras Tantos <andras_tantos@yahoo.com> 2001/03/31
--  This code is distributed under the terms and conditions of the GNU General Public Lince.
--
--
-- ELEMENTS:
--   wb_arbiter: two-way bus arbiter. Asyncronous logic ensures 0-ws operation on shared bus
 
-------------------------------------------------------------------------------
--
--  wb_arbiter
--
-------------------------------------------------------------------------------
 
library IEEE;
use IEEE.std_logic_1164.all;
 
library wb_tk;
use wb_tk.technology.all;
 
entity wb_arbiter is
	port (
--		clk: in std_logic;
		rst_i: in std_logic := '0';
 
		-- interface to master device a
		a_we_i: in std_logic;
		a_stb_i: in std_logic;
		a_cyc_i: in std_logic;
		a_ack_o: out std_logic;
		a_ack_oi: in std_logic := '-';
		a_err_o: out std_logic;
		a_err_oi: in std_logic := '-';
		a_rty_o: out std_logic;
		a_rty_oi: in std_logic := '-';
 
		-- interface to master device b
		b_we_i: in std_logic;
		b_stb_i: in std_logic;
		b_cyc_i: in std_logic;
		b_ack_o: out std_logic;
		b_ack_oi: in std_logic := '-';
		b_err_o: out std_logic;
		b_err_oi: in std_logic := '-';
		b_rty_o: out std_logic;
		b_rty_oi: in std_logic := '-';
 
		-- interface to shared devices
		s_we_o: out std_logic;
		s_stb_o: out std_logic;
		s_cyc_o: out std_logic;
		s_ack_i: in std_logic;
		s_err_i: in std_logic := '-';
		s_rty_i: in std_logic := '-';
 
		mux_signal: out std_logic; -- 0: select A signals, 1: select B signals
 
		-- misc control lines
		priority: in std_logic -- 0: A have priority over B, 1: B have priority over A
	);
end wb_arbiter;
 
-- This acthitecture is a clean asyncron state-machine. However it cannot be mapped to FPGA architecture
architecture behaviour of wb_arbiter is
	type states is (idle,aa,ba);
	signal i_mux_signal: std_logic;
 
	signal e_state: states;
begin
	mux_signal <= i_mux_signal;
 
	sm: process
		variable state: states;
	begin
		wait on a_cyc_i, b_cyc_i, priority, rst_i;
		if (rst_i = '1') then
			state := idle;
			i_mux_signal <= priority;
		else
			case (state) is
				when idle =>
					if (a_cyc_i = '1' and (priority = '0' or b_cyc_i = '0')) then
						state := aa;
						i_mux_signal <= '0';
					elsif (b_cyc_i = '1' and (priority = '1' or a_cyc_i = '0')) then
						state := ba;
						i_mux_signal <= '1';
					else
						i_mux_signal <= priority;
					end if;
				when aa =>
					if (a_cyc_i = '0') then
						if (b_cyc_i = '1') then
							state := ba;
							i_mux_signal <= '1';
						else
							state := idle;
							i_mux_signal <= priority;
						end if;
					else
						i_mux_signal <= '0';
					end if;
				when ba =>
					if (b_cyc_i = '0') then
						if (a_cyc_i = '1') then
							state := aa;
							i_mux_signal <= '0';
						else
							state := idle;
							i_mux_signal <= priority;
						end if;
					else
						i_mux_signal <= '1';
					end if;
			end case;
		end if;
		e_state <= state;
	end process;
 
	signal_mux: process
	begin
		wait on a_we_i, a_stb_i, a_ack_oi, a_err_oi, a_rty_oi, a_cyc_i,
				b_we_i, b_stb_i, b_ack_oi, b_err_oi, b_rty_oi, b_cyc_i,
				s_ack_i, s_err_i, s_rty_i, i_mux_signal;
		if (i_mux_signal = '0') then
			s_we_o <= a_we_i;
			s_stb_o <= a_stb_i;
			s_cyc_o <= a_cyc_i;
			a_ack_o <= (a_stb_i and s_ack_i) or (not a_stb_i and a_ack_oi);
			a_err_o <= (a_stb_i and s_err_i) or (not a_stb_i and a_err_oi);
			a_rty_o <= (a_stb_i and s_rty_i) or (not a_stb_i and a_rty_oi);
			b_ack_o <= (b_stb_i and '0') or (not b_stb_i and b_ack_oi);
			b_err_o <= (b_stb_i and '0') or (not b_stb_i and b_err_oi);
			b_rty_o <= (b_stb_i and '0') or (not b_stb_i and b_rty_oi);
		else
			s_we_o <= b_we_i;
			s_stb_o <= b_stb_i;
			s_cyc_o <= b_cyc_i;
			b_ack_o <= (b_stb_i and s_ack_i) or (not b_stb_i and b_ack_oi);
			b_err_o <= (b_stb_i and s_err_i) or (not b_stb_i and b_err_oi);
			b_rty_o <= (b_stb_i and s_rty_i) or (not b_stb_i and b_rty_oi);
			a_ack_o <= (a_stb_i and '0') or (not a_stb_i and a_ack_oi);
			a_err_o <= (a_stb_i and '0') or (not a_stb_i and a_err_oi);
			a_rty_o <= (a_stb_i and '0') or (not a_stb_i and a_rty_oi);
		end if;
	end process;
end behaviour;
 
-- This acthitecture is a more-or-less structural implementation. Fits for FPGA realization.
architecture FPGA of wb_arbiter is
	component d_ff
		port (  d  :  in STD_LOGIC;
				clk:  in STD_LOGIC;
				ena:  in STD_LOGIC := '1';
				clr:  in STD_LOGIC := '0';
				pre:  in STD_LOGIC := '0';
				q  :  out STD_LOGIC
		);
	end component;
 
	signal i_mux_signal: std_logic;
 
	type states is (idle,aa,ba,XX);
	signal e_state: states;
 
	-- signals for a DFF in FPGA
	signal idle_s, aa_s, ba_s: std_logic;
 
	signal aa_clk, aa_ena, aa_clr, aa_pre: std_logic;
	signal ba_clk, ba_ena, ba_clr, ba_pre: std_logic;
 
	signal one: std_logic := '1';
begin
	one <= '1';
	mux_signal <= i_mux_signal;
 
	idle_s <= not (a_cyc_i or b_cyc_i);
 
	aa_clr <= rst_i or not a_cyc_i;
	aa_clk <= a_cyc_i;
	aa_ena <= not b_cyc_i and priority;
	aa_pre <= (a_cyc_i and not priority and not ba_s) or (a_cyc_i and not b_cyc_i);
	aa_ff: d_ff port map (
		d => one,
		clk => aa_clk,
		ena => aa_ena,
		clr => aa_clr,
		pre => aa_pre,
		q => aa_s
	);
 
	ba_clr <= rst_i or not b_cyc_i;
	ba_clk <= b_cyc_i;
	ba_ena <= not a_cyc_i and not priority;
	ba_pre <= (b_cyc_i and priority and not aa_s) or (b_cyc_i and not a_cyc_i);
	ba_ff: d_ff port map (
		d => one,
		clk => ba_clk,
		ena => ba_ena,
		clr => ba_clr,
		pre => ba_pre,
		q => ba_s
	);
 
	i_mux_signal <= (priority and idle_s) or ba_s;
 
	signal_mux: process
	begin
		wait on a_we_i, a_stb_i, a_ack_oi, a_err_oi, a_rty_oi, a_cyc_i,
				b_we_i, b_stb_i, b_ack_oi, b_err_oi, b_rty_oi, b_cyc_i,
				s_ack_i, s_err_i, s_rty_i, i_mux_signal;
		if (i_mux_signal = '0') then
			s_we_o <= a_we_i;
			s_stb_o <= a_stb_i;
			s_cyc_o <= a_cyc_i;
			a_ack_o <= (a_stb_i and s_ack_i) or (not a_stb_i and a_ack_oi);
			a_err_o <= (a_stb_i and s_err_i) or (not a_stb_i and a_err_oi);
			a_rty_o <= (a_stb_i and s_rty_i) or (not a_stb_i and a_rty_oi);
			b_ack_o <= (b_stb_i and '0') or (not b_stb_i and b_ack_oi);
			b_err_o <= (b_stb_i and '0') or (not b_stb_i and b_err_oi);
			b_rty_o <= (b_stb_i and '0') or (not b_stb_i and b_rty_oi);
		else
			s_we_o <= b_we_i;
			s_stb_o <= b_stb_i;
			s_cyc_o <= b_cyc_i;
			b_ack_o <= (b_stb_i and s_ack_i) or (not b_stb_i and b_ack_oi);
			b_err_o <= (b_stb_i and s_err_i) or (not b_stb_i and b_err_oi);
			b_rty_o <= (b_stb_i and s_rty_i) or (not b_stb_i and b_rty_oi);
			a_ack_o <= (a_stb_i and '0') or (not a_stb_i and a_ack_oi);
			a_err_o <= (a_stb_i and '0') or (not a_stb_i and a_err_oi);
			a_rty_o <= (a_stb_i and '0') or (not a_stb_i and a_rty_oi);
		end if;
	end process;
 
	gen_e_state: process
	begin
		wait on idle_s,aa_s,ba_s;
		   if (idle_s = '1' and ba_s = '0' and aa_s = '0') then e_state <= idle;
		elsif (idle_s = '0' and ba_s = '1' and aa_s = '0') then e_state <= aa;
		elsif (idle_s = '0' and ba_s = '0' and aa_s = '1') then e_state <= ba;
		else                                                    e_state <= XX;
		end if;
	end process;
end FPGA;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.