]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/commitdiff
Correct FPGA bus design for external CPU read cycle.
authorPavel Pisa <ppisa@pikron.com>
Sun, 15 Feb 2015 18:08:40 +0000 (19:08 +0100)
committerPavel Pisa <ppisa@pikron.com>
Sun, 15 Feb 2015 18:08:40 +0000 (19:08 +0100)
The original design required to keep peripheral
chip/clock enable signal for two clock cycles
during read to ensure correct output data routing.

Signed-off-by: Pavel Pisa <ppisa@pikron.com>
hw/bus_tumbl.vhd
hw/lx_rocon_top.vhd

index 2496570c1edda5b1c6ccdc0c42199d504401c9a8..9e09ef9681d5977a8b92be0d6e4d2fe502e26777 100644 (file)
@@ -53,7 +53,9 @@ architecture Behavioral of bus_tumbl is
 
        -- Internal memory signals
        signal imem_en_s     : std_logic;
+       signal imem_en_r     : std_logic;
        signal dmem_en_s     : std_logic;
+       signal dmem_en_r     : std_logic;
 
        signal imem_we_s     : std_logic_vector(3 downto 0);
        signal dmem_we_s     : std_logic_vector(3 downto 0);
@@ -61,6 +63,11 @@ architecture Behavioral of bus_tumbl is
        signal imem_data_o_s : std_logic_vector(31 downto 0);
        signal dmem_data_o_s : std_logic_vector(31 downto 0);
 
+       -- Control registers read access
+       signal tumbl_reg_en_control_r   : std_logic;
+       signal tumbl_reg_en_pc_r        : std_logic;
+       signal tumbl_reg_en_halt_code_r : std_logic;
+
        -- Internal bus structure
        -- 12 address bits: 2 bits for selection, 10 bits for address
        --
@@ -157,7 +164,9 @@ enabling: process(ce_i, address_i)
 -- Wiring
 wiring:
        process(ce_i, bls_i, address_i, imem_en_s, imem_data_o_s, dmem_en_s,
-                                                               dmem_data_o_s, tumbl_reset_s, tumbl_input_s, tumbl_state_s)
+               dmem_data_o_s, tumbl_reset_s, tumbl_input_s, tumbl_state_s,
+               imem_en_r, dmem_en_r, tumbl_reg_en_control_r, tumbl_reg_en_pc_r,
+               tumbl_reg_en_halt_code_r)
        begin
 
                if imem_en_s = '1' then
@@ -172,26 +181,22 @@ wiring:
                        dmem_we_s <= "0000";
                end if;
 
-               if imem_en_s = '1' then
+               if imem_en_r = '1' then
                        data_o <= imem_data_o_s;
-               elsif dmem_en_s = '1' then
+               elsif dmem_en_r = '1' then
                        data_o <= dmem_data_o_s;
-               elsif ce_i = '1' and address_i(11 downto 10) = "11" then
-                       if address_i(9 downto 0) = "0000000000" then
-                               data_o(0) <= tumbl_reset_s;
-                               data_o(1) <= tumbl_input_s.int;
-                               data_o(2) <= tumbl_input_s.halt;
-                               data_o(3) <= tumbl_input_s.trace;
-                               data_o(4) <= tumbl_state_s.halted;
-                               data_o(31 downto 5) <= (others => '0');
-                       elsif address_i(9 downto 0) = "0000000010" then
-                               data_o <= tumbl_state_s.pc;
-                       elsif address_i(9 downto 0) = "0000000011" then
-                               data_o(4 downto 0)  <= tumbl_state_s.halt_code;
-                               data_o(31 downto 5) <= (others => '0');
-                       else
-                               data_o <= (others => 'X');
-                       end if;
+               elsif tumbl_reg_en_control_r = '1' then
+                       data_o(0) <= tumbl_reset_s;
+                       data_o(1) <= tumbl_input_s.int;
+                       data_o(2) <= tumbl_input_s.halt;
+                       data_o(3) <= tumbl_input_s.trace;
+                       data_o(4) <= tumbl_state_s.halted;
+                       data_o(31 downto 5) <= (others => '0');
+               elsif tumbl_reg_en_pc_r = '1' then
+                       data_o <= tumbl_state_s.pc;
+               elsif tumbl_reg_en_halt_code_r = '1' then
+                       data_o(4 downto 0)  <= tumbl_state_s.halt_code;
+                       data_o(31 downto 5) <= (others => '0');
                else
                        data_o <= (others => 'X');
                end if;
@@ -206,6 +211,13 @@ update:
                -- Update
                wait until clk_i'event and clk_i = '1';
 
+               imem_en_r <= imem_en_s;
+               dmem_en_r <= dmem_en_s;
+
+               tumbl_reg_en_control_r   <= '0';
+               tumbl_reg_en_pc_r        <= '0';
+               tumbl_reg_en_halt_code_r <= '0';
+
                tumbl_input_s.trace_kick <= '0';
 
                if reset_i = '1' then
@@ -229,6 +241,15 @@ update:
                                                end if;
                                        end if;
                                end if;
+
+
+                               if address_i(9 downto 0) = "0000000000" then
+                                       tumbl_reg_en_control_r   <= '1';
+                               elsif address_i(9 downto 0) = "0000000010" then
+                                       tumbl_reg_en_pc_r        <= '1';
+                               elsif address_i(9 downto 0) = "0000000011" then
+                                       tumbl_reg_en_halt_code_r <= '1';
+                               end if;
                        end if;
                end if;
 
index 439d275615b2b3ec87824eed9304e4dee27df607..10ecdca4a6566ab573a0b8117c50ee5dfac2cf06 100644 (file)
@@ -100,25 +100,28 @@ 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_next_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);
@@ -142,11 +145,8 @@ architecture Behavioral of lx_rocon_top is
        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 last_i_rd_s         : std_logic; -- Delayed RD bus, used for latching
        --
        signal address_f_s         : std_logic_vector(15 downto 0); -- Filtered address
        --
@@ -232,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,
+               next_ce_i      => irc_proc_ce_s,
                data_i         => tumbl_data_i_s,
                data_o         => irc_proc_out_s,
                bls_i          => tumbl_bls_s,
@@ -286,7 +286,7 @@ memory_bus_lxmaster: bus_lxmaster
                --
                clk_i          => clk_50m,
                address_i      => tumbl_address_s(10 downto 0),
-               next_ce_i      => lxmaster_next_ce_s,
+               next_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),
@@ -322,7 +322,7 @@ function_approx: component lx_fncapprox
                clk_i        => clk_50m,
                -- Data bus
                address_i      => tumbl_address_s(4 downto 0),
-               next_ce_i      => lxfncapprox_next_ce_s,
+               next_ce_i      => lxfncapprox_ce_s,
                data_i         => tumbl_data_i_s,
                data_o         => lxfncapprox_out_s,
                bls_i          => tumbl_bls_s
@@ -363,12 +363,11 @@ dff_reset: dff2
 
 -- Bus update
 memory_bus_logic:
-       process(cs0_xc_f_s, rd_f_s, last_rd_s, i_rd_cycle2_s, last_i_rd_s,
+       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
-               next_i_rd_cycle2_s <= '0';
                next_address_hold_s <= '0';
 
                -- Check if we have chip select
@@ -379,10 +378,6 @@ memory_bus_logic:
                                -- 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
                                        i_rd_s            <= '0';
@@ -471,36 +466,40 @@ memory_bus_update:
                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;
+
+               -- 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;
                --
                -- ======================================================
                --  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;
+               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_f_s, i_bls_s, 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_f_s = '1' or i_bls_s /= "0000" then
+               if i_rd_s = '1' or i_bls_s /= "0000" then
 
                        -- Memory Map (16-bit address @ 32-bit each)
 
@@ -511,17 +510,22 @@ 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
@@ -554,9 +558,9 @@ tumbl_bus_o:
        begin
 
                -- Defaults
-               irc_proc_next_ce_s        <= '0';
-               lxmaster_next_ce_s        <= '0';
-               lxfncapprox_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');
@@ -578,11 +582,11 @@ tumbl_bus_o:
                        -- 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_next_ce_s  <= '1';
+                               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;
 
@@ -590,8 +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,
-               lxfncapprox_ce_s, lxfncapprox_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');
@@ -599,12 +603,12 @@ 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_s = '1' then
+               elsif lxfncapprox_ce_r = '1' then
                        tumbl_xmemb_i_s.data <= lxfncapprox_out_s;
                end if;