]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/blobdiff - hw/lx_rocon_top.vhd
Remove next_ prefix from chip selects/clock enables to reflect real phase.
[fpga/lx-cpu1/lx-rocon.git] / hw / lx_rocon_top.vhd
index 7a70ec6e7e07d3c37aa70ac5a40e3c28026b99c1..4b30d14e9326cd5d4c1280e0f1420f07ac2c41a3 100644 (file)
@@ -85,7 +85,9 @@ entity lx_rocon_top is
                --
                s1_clk_out  : out std_logic;
                s1_mosi     : out std_logic;
-               s1_sync_out : out std_logic
+               s1_sync_out : out std_logic;
+               -- signal connected to external JK FF
+               event_jk_j  : out std_logic
        );
 end lx_rocon_top;
 
@@ -98,28 +100,40 @@ architecture Behavioral of lx_rocon_top is
        -- Master to Tumbl DMEM / IMEM (Master)
        signal tumbl_out_s              : std_logic_vector(31 downto 0);
        signal tumbl_ce_s               : std_logic;
+       signal tumbl_ce_r               : std_logic;
        -- Measurement (Master)
        signal meas_out_s               : std_logic_vector(31 downto 0);
        signal meas_ce_s                : std_logic;
+       signal meas_ce_r                : 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_ce_r   : 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;
+       signal irc_proc_out_s           : std_logic_vector(31 downto 0);
+       signal irc_proc_ce_s            : std_logic;
+       signal irc_proc_ce_r            : 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;
+       signal lxmaster_ce_r            : std_logic;
+       -- LX function approximation
+       signal lxfncapprox_out_s        : std_logic_vector(31 downto 0);
+       signal lxfncapprox_ce_s         : std_logic;
+       signal lxfncapprox_ce_r         : 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 last_bls_s               : std_logic_vector(3 downto 0);
+       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)
@@ -128,22 +142,26 @@ architecture Behavioral of lx_rocon_top is
        --
        -- 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 rd_d_s              : std_logic; -- D over RD
        signal i_rd_s              : std_logic; -- Internal bus RD (active 1)
+       signal next_last_i_rd_s    : std_logic;
        signal last_i_rd_s         : std_logic; -- Delayed RD bus, used for latching
        --
        signal address_f_s         : std_logic_vector(15 downto 0); -- Filtered address
-       signal address_d_s         : std_logic_vector(15 downto 0); -- D over 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
-       signal bls_d_s             : std_logic_vector(3 downto 0); -- D over BLS
+       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);
@@ -153,6 +171,26 @@ architecture Behavioral of lx_rocon_top is
        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
 
@@ -194,7 +232,7 @@ memory_bus_irc: bus_irc
                --
                clk_i          => clk_50m,
                address_i      => tumbl_address_s(4 downto 0),
-               next_ce_i      => irc_proc_next_ce_s,
+               ce_i           => irc_proc_ce_s,
                data_i         => tumbl_data_i_s,
                data_o         => irc_proc_out_s,
                bls_i          => tumbl_bls_s,
@@ -248,11 +286,13 @@ memory_bus_lxmaster: bus_lxmaster
                --
                clk_i          => clk_50m,
                address_i      => tumbl_address_s(10 downto 0),
-               next_ce_i      => lxmaster_next_ce_s,
+               ce_i           => lxmaster_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,
@@ -260,6 +300,32 @@ memory_bus_lxmaster: bus_lxmaster
                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
+       );
+
+       -- s1_clk_out      <= s0;
+       -- s1_mosi         <= s1;
+       -- s1_sync_out     <= s2;
+
+
+function_approx: component lx_fncapprox
+       port map
+       (
+               reset_i      => reset_s,
+               clk_i        => clk_50m,
+               -- Data bus
+               address_i      => tumbl_address_s(4 downto 0),
+               ce_i           => lxfncapprox_ce_s,
+               data_i         => tumbl_data_i_s,
+               data_o         => lxfncapprox_out_s,
+               bls_i          => tumbl_bls_s
        );
 
 -- Reset
@@ -267,7 +333,6 @@ dff_reset: dff2
        port map
        (
                clk_i   => clk_50m,
-               reset_i => '0',
                d_i     => init_s,
                q_o     => reset_s
        );
@@ -275,13 +340,8 @@ dff_reset: dff2
        -- Reset
        init_s          <= not init;
 
-       -- Filters
-       bls_f_s         <= bls when bls = bls_d_s else "1111";
-       rd_f_s          <= rd when rd = rd_d_s else '1';
-       address_f_s     <= address when address = address_d_s else last_address_s; -- Use last address on mismatch!
-
        -- Signalling
-       data_i_s        <= data_write_s when i_bls_s /= "0000" else (others => '0');
+       data_i_s        <= data_write_s;
 
        -- Tumbl
        tumbl_bls_s     <= i_bls_s when (master_tumbl_xmem_lock_s = '1')
@@ -296,94 +356,150 @@ dff_reset: dff2
        --
        tumbl_xmemb_i_s.int <= '0'; -- No interrupt
        -- Enable clken only when available for Tumbl
-       tumbl_xmemb_i_s.clken <= not master_tumbl_xmem_lock_s;
+       tumbl_xmemb_i_s.bus_taken <= master_tumbl_xmem_lock_s;
+       tumbl_xmemb_i_s.bus_wait <= '0';
 
--- Bus update
-memory_bus_update:
-       process
-       begin
 
-               wait until clk_50m = '1' and clk_50m'event;
 
+-- Bus update
+memory_bus_logic:
+       process(cs0_xc_f_s, rd_f_s, last_rd_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
-               i_bls_s <= "0000";
-               i_rd_s  <= '0';
+               next_address_hold_s <= '0';
 
                -- Check if we have chip select
-               if cs0_xc = '0' then
+               if cs0_xc_f_s = '1' then
 
                        -- Reading
-                       if rd_f_s = '0' then
-
+                       if rd_f_s = '1' then
                                -- Internal read
-                               if (last_rd_s = '1' or last_address_s /= address_f_s) then
+                               if last_rd_s = '0' or (last_address_s /= address_f_s) then
                                        i_rd_s <= '1';
+                                       next_last_i_rd_s  <= '1';
+                               else
+                                       i_rd_s            <= '0';
+                                       next_last_i_rd_s  <= '0';
                                end if;
 
-                               if i_rd_s = '0' and last_i_rd_s = '1' then
+                               if last_i_rd_s = '1' then
                                        -- Latch data we just read - they are valid in this cycle
-                                       data_read_s  <= data_o_s;
+                                       next_data_read_s <= data_o_s;
+                               else
+                                       next_data_read_s <= data_read_s;
                                end if;
-
-                               last_address_s <= address_f_s;
                        else
-                               -- Not reading, anything goes
-                               data_read_s    <= (others => 'X');
+                       --      -- 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;
 
-                       last_rd_s        <= rd_f_s;
+                       next_last_rd_s            <= rd_f_s;
 
-                       -- Writing
-                       if bls_f_s /= "1111" then
+                       -- 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;
 
-                               -- Internal write
-                               if (last_bls_s /= bls_f_s or last_address_s /= address_f_s) then
-                                       i_bls_s      <= not bls_f_s;
-                               end if;
+                       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;
 
-                               last_address_s <= address_f_s;
+               -- 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;
 
-                       last_bls_s       <= bls_f_s;
+       end process;
 
-               else
+-- Bus update
+memory_bus_update:
+       process
+       begin
 
-                       -- Set last read / bls to '1' if CS0 is not asserted
-                       last_rd_s        <= '1';
-                       last_bls_s       <= (others => '1');
-                       last_address_s   <= address_d_s;
+               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;
 
-               -- Filters
-               bls_d_s     <= bls;
-               rd_d_s      <= rd;
-               address_d_s <= address;
+               -- 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;
+               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;
+
+               -- Internal bus chipselects
+               tumbl_ce_r <= tumbl_ce_s;
+               meas_ce_r <= meas_ce_s;
+               master_tumbl_xmem_ce_r <= master_tumbl_xmem_ce_s;
                --
-               last_i_rd_s <= i_rd_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;
+               irc_proc_ce_r <= irc_proc_ce_s;
+               lxmaster_ce_r <= lxmaster_ce_s;
+               lxfncapprox_ce_r <= lxfncapprox_ce_s;
 
        end process;
 
 -- Do the actual wiring here
 memory_bus_wiring:
-       process(cs0_xc, address_f_s, tumbl_out_s, meas_out_s, master_tumbl_xmem_out_s)
+       process(i_rd_s, i_bls_s, address_f_s, tumbl_out_s, meas_out_s, master_tumbl_xmem_out_s,
+               tumbl_ce_r, meas_ce_r, master_tumbl_xmem_ce_r, last_i_rd_s)
        begin
 
                -- Inactive by default
                tumbl_ce_s             <= '0';
                meas_ce_s              <= '0';
                master_tumbl_xmem_ce_s <= '0';
-               data_o_s               <= (others => '0');
+               data_o_s               <= (others => 'X');
 
-               if cs0_xc = '0' then
+               if i_rd_s = '1' or i_bls_s /= "0000" then
 
                        -- Memory Map (16-bit address @ 32-bit each)
 
@@ -394,23 +510,28 @@ memory_bus_wiring:
 
                        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;
 
+               if tumbl_ce_r = '1' then                                  -- Tumbl
+                       data_o_s <= tumbl_out_s;
+               elsif meas_ce_r = '1' then                                -- Measurement
+                       data_o_s <= meas_out_s;
+               elsif master_tumbl_xmem_ce_r = '1' then                   -- Tumbl External BUS
+                       data_o_s <= master_tumbl_xmem_out_s;
+               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_s)
+       process(cs0_xc, rd, data_read_s)
        begin
 
                -- CS0 / RD / BLS are active LOW
@@ -427,8 +548,6 @@ memory_bus_out:
                        data <= (others => 'Z');
                end if;
 
-               data_write_s <= data;
-
        end process;
 
 -- Outputs from Tumbl (enabling and address muxing) and Master CPU
@@ -439,8 +558,9 @@ tumbl_bus_o:
        begin
 
                -- Defaults
-               irc_proc_next_ce_s        <= '0';
-               lxmaster_next_ce_s        <= '0';
+               irc_proc_ce_s             <= '0';
+               lxmaster_ce_s             <= '0';
+               lxfncapprox_ce_s          <= '0';
                master_tumbl_xmem_lock_s  <= '0';
                --
                addr_v                    := (others => '0');
@@ -459,11 +579,14 @@ tumbl_bus_o:
 
                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';
+                               irc_proc_ce_s     <= '1';
+                       elsif addr_v(14 downto 5) = "0001100000" then
+                               lxfncapprox_ce_s  <= '1';
                        elsif addr_v(14 downto 11) = "0010" then
-                               lxmaster_next_ce_s     <= '1';
+                               lxmaster_ce_s     <= '1';
                        end if;
                end if;
 
@@ -471,7 +594,8 @@ tumbl_bus_o:
 
 -- 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, tumbl_xmemb_i_s)
+       process(irc_proc_ce_r, irc_proc_out_s, lxmaster_ce_r, lxmaster_out_s,
+               lxfncapprox_ce_r, lxfncapprox_out_s, tumbl_xmemb_i_s)
        begin
 
                tumbl_xmemb_i_s.data  <= (others => 'X');
@@ -479,16 +603,34 @@ tumbl_bus_i:
                -- 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
+               if irc_proc_ce_r = '1' then
                        tumbl_xmemb_i_s.data <= irc_proc_out_s;
-               elsif lxmaster_ce_s = '1' then
+               elsif lxmaster_ce_r = '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_r = '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;
+
+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;