142 lines
5.1 KiB
VHDL
142 lines
5.1 KiB
VHDL
|
library ieee;
|
||
|
use ieee.std_logic_1164.all;
|
||
|
use ieee.numeric_std.all;
|
||
|
use work.wishbone_package.all;
|
||
|
use work.fifo_package.all;
|
||
|
|
||
|
entity clock_crossing is
|
||
|
generic(
|
||
|
sync_depth : natural := 2;
|
||
|
log2fifo : natural := 4);
|
||
|
port(
|
||
|
-- Common wishbone signals
|
||
|
rst : in std_logic;
|
||
|
-- Slave control port
|
||
|
slave_clk : in std_logic;
|
||
|
slave_i : in wishbone_slave_in;
|
||
|
slave_o : out wishbone_slave_out;
|
||
|
-- Master reader port
|
||
|
master_clk : in std_logic;
|
||
|
master_i : in wishbone_master_in;
|
||
|
master_o : out wishbone_master_out);
|
||
|
end clock_crossing;
|
||
|
|
||
|
architecture rtl of clock_crossing is
|
||
|
constant mWE_start : natural := 0;
|
||
|
constant mWE_end : natural := mWE_start;
|
||
|
constant mADR_start : natural := mWE_end + 1;
|
||
|
constant mADR_end : natural := mADR_start + wishbone_address_width - 1;
|
||
|
constant mDAT_start : natural := mADR_end + 1;
|
||
|
constant mDAT_end : natural := mDAT_start + wishbone_data_width - 1;
|
||
|
constant mSEL_start : natural := mDAT_end + 1;
|
||
|
constant mSEL_end : natural := mSEL_start + (wishbone_data_width/8) - 1;
|
||
|
constant mlen : natural := mSEL_end + 1;
|
||
|
|
||
|
signal msend, mrecv : wishbone_master_out;
|
||
|
signal msend_vect, mrecv_vect : std_logic_vector(mlen-1 downto 0);
|
||
|
signal mw_rdy, mw_en, mr_rdy, mr_en : std_logic;
|
||
|
|
||
|
constant sACK_start : natural := 0;
|
||
|
constant sACK_end : natural := sACK_start;
|
||
|
constant sRTY_start : natural := sACK_end + 1;
|
||
|
constant sRTY_end : natural := sRTY_start;
|
||
|
constant sERR_start : natural := sRTY_end + 1;
|
||
|
constant sERR_end : natural := sERR_start;
|
||
|
constant sDAT_start : natural := sERR_end + 1;
|
||
|
constant sDAT_end : natural := sDAT_start + wishbone_data_width - 1;
|
||
|
constant slen : natural := sDAT_end + 1;
|
||
|
|
||
|
signal ssend, srecv : wishbone_slave_out;
|
||
|
signal ssend_vect, srecv_vect : std_logic_vector(slen-1 downto 0);
|
||
|
signal sw_rdy, sw_en, sr_rdy, sr_en, sa_rdy, sa_en : std_logic;
|
||
|
|
||
|
signal master_o_STB : std_logic;
|
||
|
signal slave_o_PUSH : std_logic;
|
||
|
begin
|
||
|
mfifo : fifo
|
||
|
generic map(addr_width => log2fifo, data_width => mlen, sync_depth => sync_depth, gray_code => true)
|
||
|
port map(w_clk => slave_clk, w_rdy => mw_rdy, w_en => mw_en, w_data => msend_vect,
|
||
|
r_clk => master_clk, r_rdy => mr_rdy, r_en => mr_en, r_data => mrecv_vect,
|
||
|
a_clk => '0', a_rdy => open, a_en => '0', rst => rst);
|
||
|
|
||
|
msend_vect(mWE_start) <= msend.WE;
|
||
|
msend_vect(mADR_end downto mADR_start) <= msend.ADR;
|
||
|
msend_vect(mDAT_end downto mDAT_start) <= msend.DAT;
|
||
|
msend_vect(mSEL_end downto mSEL_start) <= msend.SEL;
|
||
|
|
||
|
mrecv.WE <= mrecv_vect(mWE_start);
|
||
|
mrecv.ADR <= mrecv_vect(mADR_end downto mADR_start);
|
||
|
mrecv.DAT <= mrecv_vect(mDAT_end downto mDAT_start);
|
||
|
mrecv.SEL <= mrecv_vect(mSEL_end downto mSEL_start);
|
||
|
|
||
|
sfifo : fifo
|
||
|
generic map(addr_width => log2fifo, data_width => slen, sync_depth => sync_depth, gray_code => true)
|
||
|
port map(w_clk => master_clk, w_rdy => open, w_en => sw_en, w_data => ssend_vect,
|
||
|
r_clk => slave_clk, r_rdy => sr_rdy, r_en => sr_en, r_data => srecv_vect,
|
||
|
a_clk => slave_clk, a_rdy => sa_rdy, a_en => sa_en, rst => rst);
|
||
|
|
||
|
ssend_vect(sACK_start) <= ssend.ACK;
|
||
|
ssend_vect(sRTY_start) <= ssend.RTY;
|
||
|
ssend_vect(sERR_start) <= ssend.ERR;
|
||
|
ssend_vect(sDAT_end downto sDAT_start) <= ssend.DAT;
|
||
|
|
||
|
srecv.ACK <= srecv_vect(sACK_start);
|
||
|
srecv.RTY <= srecv_vect(sRTY_start);
|
||
|
srecv.ERR <= srecv_vect(sERR_start);
|
||
|
srecv.DAT <= srecv_vect(sDAT_end downto sDAT_start);
|
||
|
|
||
|
-- Slave clock domain: slave -> mFIFO
|
||
|
mw_en <= mw_rdy and sa_rdy and slave_i.CYC and slave_i.STB;
|
||
|
sa_en <= mw_rdy and sa_rdy and slave_i.CYC and slave_i.STB;
|
||
|
slave_o.STALL <= not mw_rdy or not sa_rdy;
|
||
|
msend.ADR <= slave_i.ADR;
|
||
|
msend.WE <= slave_i.WE;
|
||
|
msend.SEL <= slave_i.SEL;
|
||
|
msend.DAT <= slave_i.DAT;
|
||
|
|
||
|
-- Master clock domain: mFIFO -> master
|
||
|
mr_en <= mr_rdy and (not master_o_STB or not master_i.STALL);
|
||
|
master_o.CYC <= '1';
|
||
|
master_o.STB <= master_o_STB;
|
||
|
master_o.ADR <= mrecv.ADR;
|
||
|
master_o.WE <= mrecv.WE;
|
||
|
master_o.SEL <= mrecv.SEL;
|
||
|
master_o.DAT <= mrecv.DAT;
|
||
|
|
||
|
drive_master_port : process(master_clk)
|
||
|
begin
|
||
|
if rising_edge(master_clk) then
|
||
|
if rst = '1' then
|
||
|
master_o_STB <= '0';
|
||
|
else
|
||
|
master_o_STB <= mr_en or (master_o_STB and master_i.STALL);
|
||
|
end if;
|
||
|
end if;
|
||
|
end process;
|
||
|
|
||
|
-- Master clock domain: master -> sFIFO
|
||
|
sw_en <= master_i.ACK or master_i.ERR or master_i.RTY;
|
||
|
ssend.ACK <= master_i.ACK;
|
||
|
ssend.ERR <= master_i.ERR;
|
||
|
ssend.RTY <= master_i.RTY;
|
||
|
ssend.DAT <= master_i.DAT;
|
||
|
|
||
|
-- Slave clock domain: sFIFO -> slave
|
||
|
sr_en <= sr_rdy;
|
||
|
slave_o.DAT <= srecv.DAT;
|
||
|
slave_o.ACK <= srecv.ACK and slave_o_PUSH;
|
||
|
slave_o.RTY <= srecv.RTY and slave_o_PUSH;
|
||
|
slave_o.ERR <= srecv.ERR and slave_o_PUSH;
|
||
|
|
||
|
drive_slave_port : process(slave_clk)
|
||
|
begin
|
||
|
if rising_edge(slave_clk) then
|
||
|
if rst = '1' then
|
||
|
slave_o_PUSH <= '0';
|
||
|
else
|
||
|
slave_o_PUSH <= sr_en;
|
||
|
end if;
|
||
|
end if;
|
||
|
end process;
|
||
|
end rtl;
|