]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blobdiff - hw/lx_rocon_top.vhd
Prevent register duplications of FPGA chipselect - cs0_xc_f_s - signal.
[fpga/lx-cpu1/lx-rocon.git] / hw / lx_rocon_top.vhd
index a98a0b80242dd330f9400f303fc3ba2ca3ad5321..439d275615b2b3ec87824eed9304e4dee27df607 100644 (file)
@@ -4,396 +4,628 @@ use ieee.std_logic_arith.all;
 use ieee.std_logic_unsigned.all;
 use ieee.numeric_std.all;
 
--- lx_rocon_top - wires the modules with outside world
+library unisim;
+use unisim.vcomponents.all;
+
+use work.mbl_pkg.all;
+use work.lx_rocon_pkg.all;
+
+-- lx_rocon_top - wires the modules with the outside world
 
 -- ======================================================
---  INTERNAL MEMORY BUS
+--  MASTER CPU EXTERNAL MEMORY BUS
 -- ======================================================
 --
--- Internal memory bus has the following wires:
+-- Master cpu memory bus has the following wires:
 --
--- - address[15..0]          The address
+-- - address[15..0]          The address, used to mark chip enable
 -- - data_in[31..0]          The data coming to bus
 -- - data_out[31..0]         The data coming from bus, multiplexed
--- - rd                      Read enable, active LOW
--- - bls[3..0]               Write enable for respective bytes, active LOW
---                           In some cases, only WR is used
--- - ta                      Transaction acknowledge (latches data out), active LOW, multiplexed
+-- - bls[3..0]               Write enable for respective bytes
 
 entity lx_rocon_top is
        port
        (
                -- External
-               clk_cpu   : in std_logic;
-
-               cs0_xc   : in std_logic;
-
-               rd       : in std_logic;
-               bls      : in std_logic_vector(3 downto 0);
-               address  : in std_logic_vector(15 downto 0);
-               data     : inout std_logic_vector(31 downto 0);
-
-               irc1_a     : in std_logic;
-               irc1_b     : in std_logic;
-               irc1_index : in std_logic;
-               irc1_mark  : in std_logic;
-
-               irc2_a     : in std_logic;
-               irc2_b     : in std_logic;
-               irc2_index : in std_logic;
-               irc2_mark  : in std_logic;
-
-               irc3_a     : in std_logic;
-               irc3_b     : in std_logic;
-               irc3_index : in std_logic;
-               irc3_mark  : in std_logic;
-
-               irc4_a     : in std_logic;
-               irc4_b     : in std_logic;
-               irc4_index : in std_logic;
-               irc4_mark  : in std_logic;
-
-               init       : in std_logic
-       );
-end lx_rocon_top;
-
-architecture Behavioral of lx_rocon_top is
-
-       -- Reset signal
-       signal reset : std_logic;
-
-       -- Peripherals on the memory bus
-       signal bram_out : std_logic_vector(31 downto 0);
-       signal bram_ta : std_logic;
-       signal bram_ce : std_logic;
-
-       signal irc_reg_out : std_logic_vector(31 downto 0);
-       signal irc_reg_ta : std_logic;
-       signal irc_reg_ce : std_logic;
-
-       signal bcd_out : std_logic_vector(31 downto 0);
-       signal bcd_ta : std_logic;
-       signal bcd_ce : std_logic;
-
-       signal calib_out : std_logic_vector(31 downto 0);
-       signal calib_ta : std_logic;
-       signal calib_ce : std_logic;
-
-       -- Signals for external bus transmission
-       signal data_in_bus : std_logic_vector(31 downto 0);
-       signal data_out_bus : std_logic_vector(31 downto 0);
-
-       -- Signals for internal transaction
-       signal last_address : std_logic_vector(15 downto 0);
-       signal last_rd : std_logic;
-       signal last_bls : std_logic_vector(3 downto 0);
-
-       -- Reading logic:
-       -- Broadcast rd only till ta (transaction acknowledge)
-       -- is received, then latch the data till the state of
-       -- rd or address changes
-       --
-       -- Data latching is synchronous - it's purpose is to
-       -- provide stable data for CPU on the bus on high rise
-       -- of trans. ack signal
-       signal i_ta : std_logic;
-       signal i_rd : std_logic;
-       signal data_read : std_logic_vector(31 downto 0);
-       signal acked : std_logic;
-
-       -- Writing logic:
-       signal i_bls : std_logic_vector(3 downto 0);
-       signal data_write : std_logic_vector(31 downto 0);
-
-       component bus_irc
-       port
-       (
-               clk         : in std_logic;
-               reset       : in std_logic;
-
-               address     : in std_logic_vector(3 downto 0);
-               ce          : in std_logic;
-
-               data_in     : in std_logic;
-               data_out    : out std_logic_vector(31 downto 0);
-
+               --clk_cpu     : in std_logic;
+               clk_50m     : in std_logic;
+               --
+               cs0_xc      : in std_logic;
+               --
                rd          : in std_logic;
-               wr          : in std_logic;
-               ta          : out std_logic;
-
+               bls         : in std_logic_vector(3 downto 0);
+               address     : in std_logic_vector(15 downto 0);
+               data        : inout std_logic_vector(31 downto 0);
+               --
+               irc0_a      : in std_logic;
+               irc0_b      : in std_logic;
+               irc0_index  : in std_logic;
+               irc0_mark   : in std_logic;
+               --
                irc1_a      : in std_logic;
                irc1_b      : in std_logic;
                irc1_index  : in std_logic;
                irc1_mark   : in std_logic;
-
+               --
                irc2_a      : in std_logic;
                irc2_b      : in std_logic;
                irc2_index  : in std_logic;
                irc2_mark   : in std_logic;
-
+               --
                irc3_a      : in std_logic;
                irc3_b      : in std_logic;
                irc3_index  : in std_logic;
                irc3_mark   : in std_logic;
-
+               --
                irc4_a      : in std_logic;
                irc4_b      : in std_logic;
                irc4_index  : in std_logic;
-               irc4_mark   : in std_logic
+               irc4_mark   : in std_logic;
+               --
+               irc5_a      : in std_logic;
+               irc5_b      : in std_logic;
+               irc5_index  : in std_logic;
+               irc5_mark   : in std_logic;
+               --
+               irc6_a      : in std_logic;
+               irc6_b      : in std_logic;
+               irc6_index  : in std_logic;
+               irc6_mark   : in std_logic;
+               --
+               irc7_a      : in std_logic;
+               irc7_b      : in std_logic;
+               irc7_index  : in std_logic;
+               irc7_mark   : in std_logic;
+               --
+               init        : in std_logic;
+               --
+               s1_clk_in   : in std_logic;
+               s1_miso     : in std_logic;
+               s1_sync_in  : in std_logic;
+               --
+               s1_clk_out  : out std_logic;
+               s1_mosi     : out std_logic;
+               s1_sync_out : out std_logic;
+               -- signal connected to external JK FF
+               event_jk_j  : out std_logic
        );
-       end component;
+end lx_rocon_top;
 
-       component bus_control_bram
-       port
-       (
-               clk : in std_logic;
-
-    ena : in std_logic;
-    wea : in std_logic_vector(3 downto 0);
-    addra : in std_logic_vector(8 downto 0);
-    dina : in std_logic_vector(31 downto 0);
-    douta : out std_logic_vector(31 downto 0);
-               taa : out std_logic;
-
-    enb : in std_logic;
-    web : in std_logic_vector(3 downto 0);
-    addrb : in std_logic_vector(8 downto 0);
-    dinb : in std_logic_vector(31 downto 0);
-    doutb : out std_logic_vector(31 downto 0)
-  );
-       end component;
-
-       component bus_bcd
-       port
+architecture Behavioral of lx_rocon_top is
+
+       -- Reset signal
+       signal reset_s                  : std_logic;
+       signal init_s                   : std_logic;
+       -- Peripherals on the memory buses
+       -- Master to Tumbl DMEM / IMEM (Master)
+       signal tumbl_out_s              : std_logic_vector(31 downto 0);
+       signal tumbl_ce_s               : std_logic;
+       -- Measurement (Master)
+       signal meas_out_s               : std_logic_vector(31 downto 0);
+       signal meas_ce_s                : std_logic;
+       -- Master to Tumbl XMEM
+       signal master_tumbl_xmem_out_s  : std_logic_vector(31 downto 0);
+       signal master_tumbl_xmem_ce_s   : std_logic;
+       signal master_tumbl_xmem_lock_s : std_logic;
+       -- IRC (Tumbl)
+       signal irc_proc_out_s            : std_logic_vector(31 downto 0);
+       signal irc_proc_ce_s             : std_logic;
+       signal irc_proc_next_ce_s        : std_logic;
+       -- LX Master (Tumbl)
+       signal lxmaster_out_s           : std_logic_vector(15 downto 0);
+       signal lxmaster_ce_s            : std_logic;
+       signal lxmaster_next_ce_s       : std_logic;
+       -- LX function approximation
+       signal lxfncapprox_out_s        : std_logic_vector(31 downto 0);
+       signal lxfncapprox_ce_s         : std_logic;
+       signal lxfncapprox_next_ce_s    : std_logic;
+       -- Signals for external bus transmission
+       signal data_i_s                 : std_logic_vector(31 downto 0);
+       signal data_o_s                 : std_logic_vector(31 downto 0);
+       -- Signals for internal transaction
+       signal last_address_s           : std_logic_vector(15 downto 0);
+       signal next_last_address_s      : std_logic_vector(15 downto 0);
+       signal next_address_hold_s      : std_logic;
+       signal address_hold_s           : std_logic;
+       signal last_rd_s                : std_logic;
+       signal next_last_rd_s           : std_logic;
+       signal last_bls_s               : std_logic_vector(3 downto 0); -- prev bls_f_s (active 1)
+       signal next_last_bls_s          : std_logic_vector(3 downto 0);
+
+       -- Reading logic for Master CPU:
+       -- Broadcast rd only till ta (transaction acknowledge)
+       -- is received, then latch the data till the state of
+       -- rd or address changes
+       --
+       -- Data latching is synchronous - it's purpose is to
+       -- provide stable data for CPU on the bus
+       signal cs0_xc_f_s          : std_logic;
+       signal rd_f_s              : std_logic; -- Filtered RD
+       signal i_rd_s              : std_logic; -- Internal bus RD (active 1)
+       -- signal next_i_rd_s         : std_logic;
+       signal last_i_rd_s         : std_logic; -- Delayed RD bus, used for latching
+       signal next_last_i_rd_s    : std_logic;
+       signal i_rd_cycle2_s       : std_logic; -- Some internal subsystems provide
+       signal next_i_rd_cycle2_s  : std_logic; -- data only after 2 cycles
+       --
+       signal address_f_s         : std_logic_vector(15 downto 0); -- Filtered address
+       --
+       signal data_f_s            : std_logic_vector(31 downto 0); -- Filterred input data
+       --
+       signal data_read_s         : std_logic_vector(31 downto 0); -- Latched read data
+       signal next_data_read_s    : std_logic_vector(31 downto 0);
+
+       -- Writing logic:
+       signal bls_f_s             : std_logic_vector(3 downto 0); -- Filtered BLS (active 1)
+       signal i_bls_s             : std_logic_vector(3 downto 0); -- Internal BLS (active 1)
+       signal next_i_bls_s        : std_logic_vector(3 downto 0);
+       --
+       signal data_write_s        : std_logic_vector(31 downto 0); -- Data broadcasted to write
+       signal next_data_write_s   : std_logic_vector(31 downto 0);
+
+       -- Tumbl:
+       signal tumbl_bls_s         : std_logic_vector(3 downto 0);
+       signal tumbl_address_s     : std_logic_vector(14 downto 0);
+       signal tumbl_data_i_s      : std_logic_vector(31 downto 0);
+       --
+       signal tumbl_xmemb_o_s     : CORE2DMEMB_Type;
+       signal tumbl_xmemb_i_s     : DMEMB2CORE_Type;
+       signal tumbl_xmemb_sel_s   : std_logic;
+       -- Interrupt event sources and processing
+       signal lxmaster_rx_done_s  : std_logic;
+       signal lxmaster_rx_done_r  : std_logic;
+       signal lxmaster_rx_done_last_s : std_logic;
+       signal lxmaster_rx_done_last_r : std_logic;
+
+       -- signal s0   : std_logic;
+       -- signal s1   : std_logic;
+       -- signal s2   : std_logic;
+
+       -- XST attributes
+       attribute REGISTER_DUPLICATION : string;
+       attribute REGISTER_DUPLICATION of rd : signal is "NO";
+       attribute REGISTER_DUPLICATION of rd_f_s : signal is "NO";
+       attribute REGISTER_DUPLICATION of bls : signal is "NO";
+       attribute REGISTER_DUPLICATION of bls_f_s : signal is "NO";
+       attribute REGISTER_DUPLICATION of address : signal is "NO";
+       attribute REGISTER_DUPLICATION of address_f_s : signal is "NO";
+       attribute REGISTER_DUPLICATION of cs0_xc : signal is "NO";
+       attribute REGISTER_DUPLICATION of cs0_xc_f_s : signal is "NO";
+
+begin
+
+-- Tumbl coprocessor
+memory_bus_tumbl: bus_tumbl
+       port map
        (
-               reset      : in std_logic;
-               en         : in std_logic;
-               clk        : in std_logic;
-               ce         : in std_logic;
-               data_out   : out std_logic_vector(31 downto 0);
-               rd         : in std_logic;
-               ta         : out std_logic
+               clk_i          => clk_50m,
+               reset_i        => reset_s,
+               ce_i           => tumbl_ce_s,
+               bls_i          => i_bls_s,
+               address_i      => address_f_s(11 downto 0),
+               data_i         => data_i_s,
+               data_o         => tumbl_out_s,
+               --
+               xmemb_o        => tumbl_xmemb_o_s,
+               xmemb_i        => tumbl_xmemb_i_s,
+               xmemb_sel_o    => tumbl_xmemb_sel_s
        );
-       end component;
 
-       component bus_calibration
-       port
+-- Measurement
+memory_bus_measurement: bus_measurement
+       port map
        (
-               clk         : in std_logic;
-               reset       : in std_logic;
-               ce          : in std_logic;
-               address     : in std_logic_vector(1 downto 0);
-               data_in     : in std_logic_vector(31 downto 0);
-               data_out    : out std_logic_vector(31 downto 0);
-               rd          : in std_logic;
-               bls         : in std_logic_vector(3 downto 0);
-               ta          : out std_logic
+               clk_i     => clk_50m,
+               reset_i   => reset_s,
+               ce_i      => meas_ce_s,
+               address_i => address_f_s(1 downto 0),
+               bls_i     => i_bls_s,
+               data_i    => data_i_s,
+               data_o    => meas_out_s
        );
-       end component;
 
-begin
-
-       -- IRC interconnect
-       memory_bus_irc: bus_irc
+-- IRC interconnect
+memory_bus_irc: bus_irc
        port map
        (
-               clk => clk_cpu,
-               reset => reset,
-               address => address(3 downto 0),
-               ce => irc_reg_ce,
-               data_in => data_in_bus(0),
-               data_out => irc_reg_out,
-               rd => i_rd,
-               wr => bls(0),
-               ta => irc_reg_ta,
-
-               irc1_a => irc1_a,
-               irc1_b => irc1_b,
-               irc1_index => irc1_index,
-               irc1_mark => irc1_mark,
-
-               irc2_a => irc2_a,
-               irc2_b => irc2_b,
-               irc2_index => irc2_index,
-               irc2_mark => irc2_mark,
-
-               irc3_a => irc3_a,
-               irc3_b => irc3_b,
-               irc3_index => irc3_index,
-               irc3_mark => irc3_mark,
-
-               irc4_a => irc4_a,
-               irc4_b => irc4_b,
-               irc4_index => irc4_index,
-               irc4_mark => irc4_mark
+               reset_i        => reset_s,
+               --
+               clk_i          => clk_50m,
+               address_i      => tumbl_address_s(4 downto 0),
+               next_ce_i      => irc_proc_next_ce_s,
+               data_i         => tumbl_data_i_s,
+               data_o         => irc_proc_out_s,
+               bls_i          => tumbl_bls_s,
+               --
+               irc_i(0).a     => irc0_a,
+               irc_i(0).b     => irc0_b,
+               irc_i(0).index => irc0_index,
+               irc_i(0).mark  => irc0_mark,
+               --
+               irc_i(1).a     => irc1_a,
+               irc_i(1).b     => irc1_b,
+               irc_i(1).index => irc1_index,
+               irc_i(1).mark  => irc1_mark,
+               --
+               irc_i(2).a     => irc2_a,
+               irc_i(2).b     => irc2_b,
+               irc_i(2).index => irc2_index,
+               irc_i(2).mark  => irc2_mark,
+               --
+               irc_i(3).a     => irc3_a,
+               irc_i(3).b     => irc3_b,
+               irc_i(3).index => irc3_index,
+               irc_i(3).mark  => irc3_mark,
+               --
+               irc_i(4).a     => irc4_a,
+               irc_i(4).b     => irc4_b,
+               irc_i(4).index => irc4_index,
+               irc_i(4).mark  => irc4_mark,
+               --
+               irc_i(5).a     => irc5_a,
+               irc_i(5).b     => irc5_b,
+               irc_i(5).index => irc5_index,
+               irc_i(5).mark  => irc5_mark,
+               --
+               irc_i(6).a     => irc6_a,
+               irc_i(6).b     => irc6_b,
+               irc_i(6).index => irc6_index,
+               irc_i(6).mark  => irc6_mark,
+               --
+               irc_i(7).a     => irc7_a,
+               irc_i(7).b     => irc7_b,
+               irc_i(7).index => irc7_index,
+               irc_i(7).mark  => irc7_mark
        );
 
-       -- Control BRAM interconnect (9 kib)
-       memory_bus_control_bram: bus_control_bram
+-- LX Master
+memory_bus_lxmaster: bus_lxmaster
        port map
        (
-               clk => clk_cpu,
-               ena => bram_ce,
-               taa => bram_ta,
-               wea => i_bls,
-               addra => address(8 downto 0),
-               dina => data_in_bus,
-               douta => bram_out,
-
-               enb => '0',
-               web => (others => '0'),
-               addrb => (others => '0'),
-               dinb => (others => '0'),
-               doutb => open
+               reset_i        => reset_s,
+               --
+               clk_i          => clk_50m,
+               address_i      => tumbl_address_s(10 downto 0),
+               next_ce_i      => lxmaster_next_ce_s,
+               data_i         => tumbl_data_i_s(15 downto 0),
+               data_o         => lxmaster_out_s,
+               bls_i          => tumbl_bls_s(1 downto 0),
+               --
+               rx_done_o      => lxmaster_rx_done_s,
+               --
+               clock_i        => s1_clk_in,
+               miso_i         => s1_miso,
+               sync_i         => s1_sync_in,
+               --
+               clock_o        => s1_clk_out,
+               mosi_o         => s1_mosi,
+               sync_o         => s1_sync_out
+               --
+               -- clock_i        => s0,
+               -- miso_i         => s1,
+               -- sync_i         => not s2,
+               --
+               -- clock_o        => s0,
+               -- mosi_o         => s1,
+               -- sync_o         => s2
        );
 
-       -- BCD
-       memory_bus_bcd: bus_bcd
+       -- s1_clk_out      <= s0;
+       -- s1_mosi         <= s1;
+       -- s1_sync_out     <= s2;
+
+
+function_approx: component lx_fncapprox
        port map
        (
-               clk => clk_cpu,
-               reset => reset,
-               en => '1',
-               ce => bcd_ce,
-               rd => i_rd,
-               ta => bcd_ta,
-               data_out => bcd_out
+               reset_i      => reset_s,
+               clk_i        => clk_50m,
+               -- Data bus
+               address_i      => tumbl_address_s(4 downto 0),
+               next_ce_i      => lxfncapprox_next_ce_s,
+               data_i         => tumbl_data_i_s,
+               data_o         => lxfncapprox_out_s,
+               bls_i          => tumbl_bls_s
        );
 
-       -- Calibration
-       memory_bus_calibration: bus_calibration
+-- Reset
+dff_reset: dff2
        port map
        (
-               clk => clk_cpu,
-               reset => reset,
-               ce => calib_ce,
-               address => address(1 downto 0),
-               rd => i_rd,
-               bls => i_bls,
-               ta => calib_ta,
-               data_in => data_in_bus,
-               data_out => calib_out
+               clk_i   => clk_50m,
+               d_i     => init_s,
+               q_o     => reset_s
        );
 
-       -- Bus update
-       memory_bus_update: process(clk_cpu)
-       begin
+       -- Reset
+       init_s          <= not init;
+
+       -- Signalling
+       data_i_s        <= data_write_s;
+
+       -- Tumbl
+       tumbl_bls_s     <= i_bls_s when (master_tumbl_xmem_lock_s = '1')
+                          else tumbl_xmemb_o_s.bls when (tumbl_xmemb_sel_s = '1')
+                          else "0000";
+       tumbl_address_s <= address_f_s(14 downto 0) when (master_tumbl_xmem_lock_s = '1')
+                          else tumbl_xmemb_o_s.addr when (tumbl_xmemb_sel_s = '1')
+                          else (others => '0');
+       tumbl_data_i_s  <= data_i_s when (master_tumbl_xmem_lock_s = '1')
+                          else tumbl_xmemb_o_s.data when (tumbl_xmemb_sel_s = '1')
+                          else (others => '0');
+       --
+       tumbl_xmemb_i_s.int <= '0'; -- No interrupt
+       -- Enable clken only when available for Tumbl
+       tumbl_xmemb_i_s.bus_taken <= master_tumbl_xmem_lock_s;
+       tumbl_xmemb_i_s.bus_wait <= '0';
 
-               if clk_cpu = '1' and clk_cpu'event then
-
-                       -- Set every signal to inactive state here
-                       irc_reg_ce <= '1';
-                       bram_ce <= '1';
-                       bcd_ce <= '1';
-                       calib_ce <= '1';
-                       i_rd <= '1';
-                       i_bls <= (others => '1');
-                       data_in_bus <= (others => 'X');
-
-                       -- Check if we have chip select
-                       if cs0_xc = '0' then
-
-                               -- Memory Map (16-bit address @ 32-bit each)
-
-                               -- Each address is seen as 32-bit entry now
-                               -- 0x0000 - 0x011F: Control dual-port BRAM
-                               -- 0x8000 - 0x800F: IRC registers
-                               -- 0xFFFB:          32-bit BCD
-                               -- 0xFFFC - 0xFFFF: Calibration
-
-                               if address < "0000000100100000" then -- Control BRAM
-                                       bram_ce <= '0';
-                                       i_ta <= bram_ta;
-                                       data_out_bus <= bram_out;
-                               elsif address(15 downto 4) = "100000000000" then -- IRC
-                                       irc_reg_ce <= '0';
-                                       i_ta <= irc_reg_ta;
-                                       data_out_bus <= irc_reg_out;
-                               elsif address = "1111111111111011" then -- BCD
-                                       bcd_ce <= '0';
-                                       i_ta <= bcd_ta;
-                                       data_out_bus <= bcd_out;
-                               elsif address(15 downto 2) = "11111111111111" then -- Calibration
-                                       calib_ce <= '0';
-                                       i_ta <= calib_ta;
-                                       data_out_bus <= calib_out;
-                               end if;
 
-                               -- Reading
-                               if rd = '0' then
-                                       if last_rd = '1' or last_address /= address then
-                                               -- Getting something new
-                                               -- Set internal RD to active and reset ack and latched data
-                                               acked <= '0';
-                                               i_rd <= '0';
-                                               -- Data latching - synchronous
-                                               data_read <= (others => 'X');
-                                       elsif i_rd = '0' and acked = '0' and i_ta = '0' then
-                                               -- Got acknowledge, latch data
-                                               acked <= '1';
-                                               data_read <= data_out_bus;
-                                       elsif acked = '0' then
-                                               -- Ongoing read, keep the signal low
-                                               i_rd <= '0';
-                                               data_read <= (others => 'X');
-                                       end if;
-
-                                       last_address <= address;
+
+-- Bus update
+memory_bus_logic:
+       process(cs0_xc_f_s, rd_f_s, last_rd_s, i_rd_cycle2_s, last_i_rd_s,
+               bls_f_s, last_bls_s, data_f_s, data_write_s,
+               data_o_s, data_read_s, last_address_s, address_f_s)
+       begin
+               -- Defaults
+               next_i_rd_cycle2_s <= '0';
+               next_address_hold_s <= '0';
+
+               -- Check if we have chip select
+               if cs0_xc_f_s = '1' then
+
+                       -- Reading
+                       if rd_f_s = '1' then
+                               -- Internal read
+                               if last_rd_s = '0' or (last_address_s /= address_f_s) then
+                                       i_rd_s <= '1';
+                                       next_i_rd_cycle2_s <= '1';
+                                       next_last_i_rd_s  <= '1';
+                               elsif i_rd_cycle2_s = '1' then    -- FIXME it seems that some internal
+                                       i_rd_s <= '1';            -- peripherals demands 2 cycles to read
+                                       next_last_i_rd_s  <= '1';
                                else
-                                       -- Not reading, anything goes
-                                       data_read <= (others => 'X');
+                                       i_rd_s            <= '0';
+                                       next_last_i_rd_s  <= '0';
                                end if;
 
-                               last_rd <= rd;
+                               if last_i_rd_s = '1' then
+                                       -- Latch data we just read - they are valid in this cycle
+                                       next_data_read_s <= data_o_s;
+                               else
+                                       next_data_read_s <= data_read_s;
+                               end if;
+                       else
+                       --      -- Not reading, anything goes
+                       --      data_read_s       <= (others => 'X');
+                               next_data_read_s  <= data_read_s;
+                               i_rd_s            <= '0';
+                               next_last_i_rd_s  <= '0';
+                       end if;
 
-                               -- Writing
-                               if bls /= "1111" then
-                                       if last_bls /= bls or last_address /= address then
-                                               -- Data are valid when BLS is active, broadcast it for one cycle
-                                               i_bls <= bls;
-                                               data_in_bus <= data_write;
-                                       end if;
+                       next_last_rd_s            <= rd_f_s;
 
-                                       last_address <= address;
-                               end if;
+                       -- Data for write are captured only when BLS signals are stable
+                       if bls_f_s /= "0000" then
+                               next_data_write_s <= data_f_s;
+                               next_address_hold_s <= '1';
+                       else
+                               next_data_write_s <= data_write_s;
+                       end if;
 
-                               last_bls <= bls;
+                       if (bls_f_s /= "0000") or (rd_f_s = '1') then
+                               next_last_address_s <= address_f_s;
+                       else
+                               next_last_address_s <= last_address_s;
+                       end if;
+               else
+                       next_last_rd_s <= '0';
+                       i_rd_s <= '0';
+                       next_last_i_rd_s <= '0';
+
+                       next_i_bls_s <= "0000";
+                       next_data_write_s <= data_write_s;
+                       next_data_read_s  <= data_read_s;
+                       next_last_address_s <= last_address_s;
+               end if;
 
+               -- Data for write are captured at/before BLS signals are negated
+               -- and actual write cycle takes place exacly after BLS negation
+               if ((last_bls_s and not bls_f_s) /= "0000") or
+                   ((last_bls_s /= "0000") and (cs0_xc_f_s = '0')) then
+                       next_i_bls_s <= last_bls_s;
+                       next_last_bls_s   <= "0000";
+                       next_address_hold_s <= '1';
+               else
+                       next_i_bls_s <= "0000";
+                       if cs0_xc_f_s = '1' then
+                               next_last_bls_s <= bls_f_s;
                        else
+                               next_last_bls_s <= "0000" ;
+                       end if;
+               end if;
 
-                               -- Set last read / bls to '1' if CS0 is not asserted
-                               last_rd <= '1';
-                               last_bls <= (others => '1');
+       end process;
+
+-- Bus update
+memory_bus_update:
+       process
+       begin
+
+               wait until clk_50m = '1' and clk_50m'event;
+
+               address_hold_s <= next_address_hold_s;
+
+               -- Synchronized external signals with main clock domain
+               cs0_xc_f_s     <= not cs0_xc;
+               bls_f_s        <= not bls;
+               rd_f_s         <= not rd;
+               data_f_s       <= data;
+               if address_hold_s = '0' then
+                       address_f_s <= address;
+               else
+                       address_f_s <= next_last_address_s;
+               end if;
 
+               -- Synchronoust state andvance to next period
+               last_bls_s     <= next_last_bls_s;
+               last_rd_s      <= next_last_rd_s;
+               i_bls_s        <= next_i_bls_s;
+               -- i_rd_s         <= next_i_rd_s;
+               i_rd_cycle2_s  <= next_i_rd_cycle2_s;
+               last_i_rd_s    <= next_last_i_rd_s;
+               data_write_s   <= next_data_write_s;
+               last_address_s <= next_last_address_s;
+               data_read_s    <= next_data_read_s;
+               --
+               -- ======================================================
+               --  TUMBL BUS
+               -- ======================================================
+
+               -- Just copy these to their desired next state
+               irc_proc_ce_s <= irc_proc_next_ce_s;
+               lxmaster_ce_s <= lxmaster_next_ce_s;
+               lxfncapprox_ce_s <= lxfncapprox_next_ce_s;
+
+       end process;
+
+-- Do the actual wiring here
+memory_bus_wiring:
+       process(cs0_xc_f_s, i_bls_s, address_f_s, tumbl_out_s, meas_out_s, master_tumbl_xmem_out_s)
+       begin
+
+               -- Inactive by default
+               tumbl_ce_s             <= '0';
+               meas_ce_s              <= '0';
+               master_tumbl_xmem_ce_s <= '0';
+               data_o_s               <= (others => '0');
+
+               if cs0_xc_f_s = '1' or i_bls_s /= "0000" then
+
+                       -- Memory Map (16-bit address @ 32-bit each)
+
+                       -- Each address is seen as 32-bit entry now
+                       -- 0x0000 - 0x0FFF: Tumbl IMEM / DMEM
+                       -- 0x1FFC - 0x1FFF: Measurement
+                       -- 0x8000 - 0x8FFF: Tumbl BUS
+
+                       if address_f_s < "0001000000000000" then                  -- Tumbl
+                               tumbl_ce_s             <= '1';
+                               data_o_s               <= tumbl_out_s;
+                       elsif address_f_s(15 downto 2) = "00011111111111" then    -- Measurement
+                               meas_ce_s              <= '1';
+                               data_o_s               <= meas_out_s;
+                       elsif address_f_s(15) = '1' then                          -- Tumbl External BUS
+                               master_tumbl_xmem_ce_s <= '1';
+                               data_o_s               <= master_tumbl_xmem_out_s;
                        end if;
 
                end if;
 
        end process;
 
-       -- If RD and BLS is not high, we must keep DATA at high impedance
-       -- or the FPGA collides with SDRAM (damaging each other)
-       memory_bus_out: process(cs0_xc, rd, data, data_read)
+-- If RD and BLS is not high, we must keep DATA at high impedance
+-- or the FPGA collides with SDRAM (damaging each other)
+memory_bus_out:
+       process(cs0_xc, rd, data_read_s)
        begin
 
                -- CS0 / RD / BLS are active LOW
                if cs0_xc = '0' and rd = '0' then
-                       data <= data_read;
+                       -- Don't risk flipping (between data_o_s and latched data_read_s, it's better to wait)
+                       -- Maybe check this later.
+                       -- if last_i_rd_s = '1' then
+                       --   data <= data_o_s;
+                       -- else
+                       data <= data_read_s;
+                       -- end if;
                else
                        -- IMPORTANT!!!
                        data <= (others => 'Z');
                end if;
 
-               data_write <= data;
+       end process;
+
+-- Outputs from Tumbl (enabling and address muxing) and Master CPU
+tumbl_bus_o:
+       process(tumbl_xmemb_sel_s, tumbl_xmemb_o_s, master_tumbl_xmem_ce_s, address_f_s, i_rd_s, i_bls_s)
+               variable addr_v : std_logic_vector(14 downto 0); -- This space is visible by both (32-bit)
+               variable sel_v  : std_logic;
+       begin
+
+               -- Defaults
+               irc_proc_next_ce_s        <= '0';
+               lxmaster_next_ce_s        <= '0';
+               lxfncapprox_next_ce_s     <= '0';
+               master_tumbl_xmem_lock_s  <= '0';
+               --
+               addr_v                    := (others => '0');
+               sel_v                     := '0';
+
+               -- Check who is accessing
+               if master_tumbl_xmem_ce_s = '1' and (i_rd_s = '1' or i_bls_s /= "0000") then
+                       -- Master blocks Tumbl
+                       master_tumbl_xmem_lock_s <= '1';
+                       addr_v                   := address_f_s(14 downto 0);
+                       sel_v                    := '1';
+               else
+                       addr_v                   := tumbl_xmemb_o_s.addr;
+                       sel_v                    := '1';
+               end if;
+
+               if sel_v = '1' then
+                       -- IRC:       0x0800 - 0x081F (32-bit address)
+                       -- LX FNC AP: 0x0C00 - 0x0C1F (32-bit address)
+                       -- LX MASTER: 0x1000 - 0x17FF (32-bit address)
+                       if addr_v(14 downto 5) = "0001000000" then
+                               irc_proc_next_ce_s     <= '1';
+                       elsif addr_v(14 downto 5) = "0001100000" then
+                               lxfncapprox_next_ce_s  <= '1';
+                       elsif addr_v(14 downto 11) = "0010" then
+                               lxmaster_next_ce_s     <= '1';
+                       end if;
+               end if;
 
        end process;
 
-       -- Reset
-       initialization: process(init)
+-- Inputs to Tumbl (enabling and address muxing)
+tumbl_bus_i:
+       process(irc_proc_ce_s, irc_proc_out_s, lxmaster_ce_s, lxmaster_out_s,
+               lxfncapprox_ce_s, lxfncapprox_out_s, tumbl_xmemb_i_s)
+       begin
+
+               tumbl_xmemb_i_s.data  <= (others => 'X');
+
+               -- NOTE: This is input to Tumbl EXEQ - with MUL instruction for input > 18-bit,
+               -- (i.e. more DSPs in a sequence), this already has tough timing constraints
+               -- and SmartXplorer has to be used with XiSE or use Synplify.
+               if irc_proc_ce_s = '1' then
+                       tumbl_xmemb_i_s.data <= irc_proc_out_s;
+               elsif lxmaster_ce_s = '1' then
+                       tumbl_xmemb_i_s.data(15 downto 0)  <= lxmaster_out_s;
+                       tumbl_xmemb_i_s.data(31 downto 16) <= (others => '0');
+               elsif lxfncapprox_ce_s = '1' then
+                       tumbl_xmemb_i_s.data <= lxfncapprox_out_s;
+               end if;
+
+               master_tumbl_xmem_out_s <= tumbl_xmemb_i_s.data;
+
+       end process;
+
+events_logic:
+       process(lxmaster_rx_done_r, lxmaster_rx_done_last_r)
        begin
+               event_jk_j <= lxmaster_rx_done_r or lxmaster_rx_done_last_r;
+               lxmaster_rx_done_last_s <= lxmaster_rx_done_r;
+       end process;
 
-               reset <= not init;
+events_update:
+       process
+       begin
+               wait until clk_50m = '1' and clk_50m'event;
 
+               lxmaster_rx_done_r <= lxmaster_rx_done_s;
+               lxmaster_rx_done_last_r <= lxmaster_rx_done_last_s;
        end process;
 
 end Behavioral;