]> 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 d644e6f3cad98af5715724ca27b5793103bc8b24..439d275615b2b3ec87824eed9304e4dee27df607 100644 (file)
@@ -79,18 +79,23 @@ entity lx_rocon_top is
                --
                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;
-               s1_mosi     : out std_logic
+               -- signal connected to external JK FF
+               event_jk_j  : out std_logic
        );
 end lx_rocon_top;
 
 architecture Behavioral of lx_rocon_top is
 
        -- Reset signal
-       signal reset_s                 : std_logic;
-       signal init_f_s                : std_logic;
-       signal init_f_r                : std_logic;
+       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);
@@ -110,13 +115,22 @@ architecture Behavioral of lx_rocon_top is
        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 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)
@@ -125,22 +139,29 @@ 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_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 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);
@@ -150,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
 
@@ -244,24 +285,63 @@ memory_bus_lxmaster: bus_lxmaster
                reset_i        => reset_s,
                --
                clk_i          => clk_50m,
-               address_i      => tumbl_address_s(9 downto 0),
+               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),
                --
-               mosi_o         => s1_mosi,
+               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
        );
 
-       -- 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!
+       -- 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),
+               next_ce_i      => lxfncapprox_next_ce_s,
+               data_i         => tumbl_data_i_s,
+               data_o         => lxfncapprox_out_s,
+               bls_i          => tumbl_bls_s
+       );
+
+-- Reset
+dff_reset: dff2
+       port map
+       (
+               clk_i   => clk_50m,
+               d_i     => init_s,
+               q_o     => reset_s
+       );
+
+       -- Reset
+       init_s          <= not init;
 
        -- 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')
@@ -276,72 +356,128 @@ memory_bus_lxmaster: bus_lxmaster
        --
        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, 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
-               i_bls_s <= "0000";
-               i_rd_s  <= '0';
+               next_i_rd_cycle2_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_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
+                                       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;
+               -- 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;
                --
-               last_i_rd_s <= i_rd_s;
-
                -- ======================================================
                --  TUMBL BUS
                -- ======================================================
@@ -349,16 +485,13 @@ memory_bus_update:
                -- Just copy these to their desired next state
                irc_proc_ce_s <= irc_proc_next_ce_s;
                lxmaster_ce_s <= lxmaster_next_ce_s;
-
-               -- Other
-               init_f_s <= init;
-               init_f_r <= init_f_s;
+               lxfncapprox_ce_s <= lxfncapprox_next_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(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
@@ -367,7 +500,7 @@ memory_bus_wiring:
                master_tumbl_xmem_ce_s <= '0';
                data_o_s               <= (others => '0');
 
-               if cs0_xc = '0' then
+               if cs0_xc_f_s = '1' or i_bls_s /= "0000" then
 
                        -- Memory Map (16-bit address @ 32-bit each)
 
@@ -394,7 +527,7 @@ memory_bus_wiring:
 -- 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
@@ -411,8 +544,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
@@ -425,6 +556,7 @@ tumbl_bus_o:
                -- 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');
@@ -443,10 +575,13 @@ tumbl_bus_o:
 
                if sel_v = '1' then
                        -- IRC:       0x0800 - 0x081F (32-bit address)
-                       -- LX MASTER: 0x0C00 - 0x0FFF (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 10) = "00011" then
+                       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;
@@ -455,7 +590,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_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');
@@ -468,19 +604,28 @@ tumbl_bus_i:
                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;
 
--- Reset
-initialization:
-       process(init_f_s, init_f_r)
+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_s <= (not init_f_s) and (not init_f_r);
+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;