--
|
--
|
-- Wishbone bus toolkit.
|
-- Wishbone bus toolkit.
|
--
|
--
|
-- (c) Copyright Andras Tantos <andras_tantos@yahoo.com> 2001/03/31
|
-- (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.
|
-- This code is distributed under the terms and conditions of the GNU General Public Lince.
|
--
|
--
|
--
|
--
|
-- ELEMENTS:
|
-- ELEMENTS:
|
-- wb_async_slave: Wishbone bus to async (SRAM-like) bus slave bridge.
|
-- wb_async_slave: Wishbone bus to async (SRAM-like) bus slave bridge.
|
|
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
--
|
--
|
-- wb_async_slave
|
-- wb_async_slave
|
--
|
--
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
library IEEE;
|
library IEEE;
|
use IEEE.std_logic_1164.all;
|
use IEEE.std_logic_1164.all;
|
|
|
library wb_tk;
|
library wb_tk;
|
use wb_tk.technology.all;
|
use wb_tk.technology.all;
|
|
|
entity wb_async_slave is
|
entity wb_async_slave is
|
generic (
|
generic (
|
width: positive := 16;
|
width: positive := 16;
|
addr_width: positive := 20
|
addr_width: positive := 20
|
);
|
);
|
port (
|
port (
|
clk_i: in std_logic;
|
clk_i: in std_logic;
|
rst_i: in std_logic := '0';
|
rst_i: in std_logic := '0';
|
|
|
-- interface for wait-state generator state-machine
|
-- interface for wait-state generator state-machine
|
wait_state: in std_logic_vector (3 downto 0);
|
wait_state: in std_logic_vector (3 downto 0);
|
|
|
-- interface to wishbone master device
|
-- interface to wishbone master device
|
adr_i: in std_logic_vector (addr_width-1 downto 0);
|
adr_i: in std_logic_vector (addr_width-1 downto 0);
|
sel_i: in std_logic_vector ((addr_width/8)-1 downto 0);
|
sel_i: in std_logic_vector ((addr_width/8)-1 downto 0);
|
dat_i: in std_logic_vector (width-1 downto 0);
|
dat_i: in std_logic_vector (width-1 downto 0);
|
dat_o: out std_logic_vector (width-1 downto 0);
|
dat_o: out std_logic_vector (width-1 downto 0);
|
dat_oi: in std_logic_vector (width-1 downto 0) := (others => '-');
|
dat_oi: in std_logic_vector (width-1 downto 0) := (others => '-');
|
we_i: in std_logic;
|
we_i: in std_logic;
|
stb_i: in std_logic;
|
stb_i: in std_logic;
|
ack_o: out std_logic := '0';
|
ack_o: out std_logic := '0';
|
ack_oi: in std_logic := '-';
|
ack_oi: in std_logic := '-';
|
|
|
-- interface to async slave
|
-- interface to async slave
|
a_data: inout std_logic_vector (width-1 downto 0) := (others => 'Z');
|
a_data: inout std_logic_vector (width-1 downto 0) := (others => 'Z');
|
a_addr: out std_logic_vector (addr_width-1 downto 0) := (others => 'U');
|
a_addr: out std_logic_vector (addr_width-1 downto 0) := (others => 'U');
|
a_rdn: out std_logic := '1';
|
a_rdn: out std_logic := '1';
|
a_wrn: out std_logic := '1';
|
a_wrn: out std_logic := '1';
|
a_cen: out std_logic := '1';
|
a_cen: out std_logic := '1';
|
-- byte-enable signals
|
-- byte-enable signals
|
a_byen: out std_logic_vector ((width/8)-1 downto 0)
|
a_byen: out std_logic_vector ((width/8)-1 downto 0)
|
);
|
);
|
end wb_async_slave;
|
end wb_async_slave;
|
|
|
architecture wb_async_slave of wb_async_slave is
|
architecture wb_async_slave of wb_async_slave is
|
-- multiplexed access signals to memory
|
-- multiplexed access signals to memory
|
signal i_ack: std_logic;
|
signal i_ack: std_logic;
|
signal sm_ack: std_logic;
|
signal sm_ack: std_logic;
|
|
|
type states is (sm_idle, sm_wait, sm_deact);
|
type states is (sm_idle, sm_wait, sm_deact);
|
signal state: states;
|
signal state: states;
|
signal cnt: std_logic_vector(3 downto 0);
|
signal cnt: std_logic_vector(3 downto 0);
|
begin
|
begin
|
ack_o <= (stb_i and i_ack) or (not stb_i and ack_oi);
|
ack_o <= (stb_i and i_ack) or (not stb_i and ack_oi);
|
dat_o_gen: for i in dat_o'RANGE generate
|
dat_o_gen: for i in dat_o'RANGE generate
|
dat_o(i) <= (stb_i and a_data(i)) or (not stb_i and dat_oi(i));
|
dat_o(i) <= (stb_i and a_data(i)) or (not stb_i and dat_oi(i));
|
end generate;
|
end generate;
|
|
|
-- For 0WS operation i_ack is an async signal otherwise it's a sync one.
|
-- For 0WS operation i_ack is an async signal otherwise it's a sync one.
|
i_ack_gen: process is
|
i_ack_gen: process is
|
begin
|
begin
|
wait on sm_ack, stb_i, wait_state, state;
|
wait on sm_ack, stb_i, wait_state, state;
|
if (wait_state = "0000") then
|
if (wait_state = "0000") then
|
case (state) is
|
case (state) is
|
when sm_deact => i_ack <= '0';
|
when sm_deact => i_ack <= '0';
|
when others => i_ack <= stb_i;
|
when others => i_ack <= stb_i;
|
end case;
|
end case;
|
else
|
else
|
i_ack <= sm_ack;
|
i_ack <= sm_ack;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
-- SRAM signal-handler process
|
-- SRAM signal-handler process
|
sram_signals: process is
|
sram_signals: process is
|
begin
|
begin
|
wait on state,we_i,a_data,adr_i,rst_i, stb_i, sel_i, dat_i;
|
wait on state,we_i,a_data,adr_i,rst_i, stb_i, sel_i, dat_i;
|
if (rst_i = '1') then
|
if (rst_i = '1') then
|
a_wrn <= '1';
|
a_wrn <= '1';
|
a_rdn <= '1';
|
a_rdn <= '1';
|
a_cen <= '1';
|
a_cen <= '1';
|
a_addr <= (others => '-');
|
a_addr <= (others => '-');
|
a_data <= (others => 'Z');
|
a_data <= (others => 'Z');
|
a_byen <= (others => '1');
|
a_byen <= (others => '1');
|
else
|
else
|
case (state) is
|
case (state) is
|
when sm_deact =>
|
when sm_deact =>
|
a_wrn <= '1';
|
a_wrn <= '1';
|
a_rdn <= '1';
|
a_rdn <= '1';
|
a_cen <= '1';
|
a_cen <= '1';
|
a_addr <= (others => '-');
|
a_addr <= (others => '-');
|
a_data <= (others => 'Z');
|
a_data <= (others => 'Z');
|
a_byen <= (others => '1');
|
a_byen <= (others => '1');
|
when others =>
|
when others =>
|
a_addr <= adr_i;
|
a_addr <= adr_i;
|
a_rdn <= not (not we_i and stb_i);
|
a_rdn <= not (not we_i and stb_i);
|
a_wrn <= not (we_i and stb_i);
|
a_wrn <= not (we_i and stb_i);
|
a_cen <= not stb_i;
|
a_cen <= not stb_i;
|
a_byen <= not sel_i;
|
a_byen <= not sel_i;
|
if (we_i = '1') then
|
if (we_i = '1') then
|
a_data <= dat_i;
|
a_data <= dat_i;
|
else
|
else
|
a_data <= (others => 'Z');
|
a_data <= (others => 'Z');
|
end if;
|
end if;
|
end case;
|
end case;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
-- Aysnc access state-machine.
|
-- Aysnc access state-machine.
|
async_sm: process is
|
async_sm: process is
|
-- variable cnt: std_logic_vector(3 downto 0) := "0000";
|
-- variable cnt: std_logic_vector(3 downto 0) := "0000";
|
-- variable state: states := init;
|
-- variable state: states := init;
|
begin
|
begin
|
wait until clk_i'EVENT and clk_i = '1';
|
wait until clk_i'EVENT and clk_i = '1';
|
if (rst_i = '1') then
|
if (rst_i = '1') then
|
state <= sm_idle;
|
state <= sm_idle;
|
cnt <= ((0) => '1', others => '0');
|
cnt <= ((0) => '1', others => '0');
|
sm_ack <= '0';
|
sm_ack <= '0';
|
else
|
else
|
case (state) is
|
case (state) is
|
when sm_idle =>
|
when sm_idle =>
|
-- Check if anyone needs access to the memory.
|
-- Check if anyone needs access to the memory.
|
-- it's rdy signal will already be pulled low, so we only have to start the access
|
-- it's rdy signal will already be pulled low, so we only have to start the access
|
if (stb_i = '1') then
|
if (stb_i = '1') then
|
case wait_state is
|
case wait_state is
|
when "0000" =>
|
when "0000" =>
|
sm_ack <= '1';
|
sm_ack <= '1';
|
state <= sm_deact;
|
state <= sm_deact;
|
when "0001" =>
|
when "0001" =>
|
sm_ack <= '1';
|
sm_ack <= '1';
|
cnt <= "0001";
|
cnt <= "0001";
|
state <= sm_wait;
|
state <= sm_wait;
|
when others =>
|
when others =>
|
sm_ack <= '0';
|
sm_ack <= '0';
|
cnt <= "0001";
|
cnt <= "0001";
|
state <= sm_wait;
|
state <= sm_wait;
|
end case;
|
end case;
|
end if;
|
end if;
|
when sm_wait =>
|
when sm_wait =>
|
if (cnt = wait_state) then
|
if (cnt = wait_state) then
|
-- wait cycle completed.
|
-- wait cycle completed.
|
state <= sm_deact;
|
state <= sm_deact;
|
sm_ack <= '0';
|
sm_ack <= '0';
|
cnt <= "0000";
|
cnt <= "0000";
|
else
|
else
|
if (add_one(cnt) = wait_state) then
|
if (add_one(cnt) = wait_state) then
|
sm_ack <= '1';
|
sm_ack <= '1';
|
else
|
else
|
sm_ack <= '0';
|
sm_ack <= '0';
|
end if;
|
end if;
|
cnt <= add_one(cnt);
|
cnt <= add_one(cnt);
|
end if;
|
end if;
|
when sm_deact =>
|
when sm_deact =>
|
if (stb_i = '1') then
|
if (stb_i = '1') then
|
case wait_state is
|
case wait_state is
|
when "0000" =>
|
when "0000" =>
|
cnt <= "0000";
|
cnt <= "0000";
|
sm_ack <= '0';
|
sm_ack <= '0';
|
state <= sm_wait;
|
state <= sm_wait;
|
when others =>
|
when others =>
|
sm_ack <= '0';
|
sm_ack <= '0';
|
cnt <= "0000";
|
cnt <= "0000";
|
state <= sm_wait;
|
state <= sm_wait;
|
end case;
|
end case;
|
else
|
else
|
sm_ack <= '0';
|
sm_ack <= '0';
|
state <= sm_idle;
|
state <= sm_idle;
|
end if;
|
end if;
|
end case;
|
end case;
|
end if;
|
end if;
|
end process;
|
end process;
|
end wb_async_slave;
|
end wb_async_slave;
|
|
|
|
|