+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+use work.lx_dad_pkg.all;
+
+-- lx_dad_top - wires the modules with the outside world
+
+-- ======================================================
+-- MASTER CPU EXTERNAL MEMORY BUS
+-- ======================================================
+--
+-- Master cpu memory bus has the following wires:
+--
+-- - 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
+-- - bls[3..0] Write enable for respective bytes
+
+entity lx_dad_top is
+ port
+ (
+ -- External
+ --clk_cpu : in std_logic;
+ clk_50m : 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);
+ --
+ init : in std_logic;
+ -- signal connected to external JK FF
+ event_jk_j : out std_logic
+ );
+end lx_dad_top;
+
+architecture Behavioral of lx_dad_top is
+
+ -- Reset signal
+ signal reset_s : std_logic;
+ signal init_s : std_logic;
+ -- Peripherals on the memory buses
+ -- Example memory
+ signal example_out_s : std_logic_vector(31 downto 0);
+ signal example_ce_s : std_logic;
+ -- Measurement (Master)
+ signal meas_out_s : std_logic_vector(31 downto 0);
+ signal meas_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);
+
+ -- 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
+
+-- Example connection
+memory_bus_example: bus_example
+ port map
+ (
+ clk_i => clk_50m,
+ reset_i => reset_s,
+ ce_i => example_ce_s,
+ bls_i => i_bls_s,
+ address_i => address_f_s(11 downto 0),
+ data_i => data_i_s,
+ data_o => example_out_s
+ --
+ --
+ -- additional externally connected signals goes there
+ );
+
+-- Measurement
+memory_bus_measurement: bus_measurement
+ port map
+ (
+ 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
+ );
+
+-- 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;
+
+
+ event_jk_j <= '0';
+
+-- 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
+ i_rd_s <= '0';
+ next_last_i_rd_s <= '0';
+ end if;
+
+ 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;
+
+ next_last_rd_s <= rd_f_s;
+
+ -- 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;
+
+ 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;
+
+ 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;
+
+ end process;
+
+-- Do the actual wiring here
+memory_bus_wiring:
+ process(cs0_xc_f_s, i_bls_s, address_f_s, example_out_s, meas_out_s)
+ begin
+
+ -- Inactive by default
+ example_ce_s <= '0';
+ meas_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: Example memory
+ -- 0x1FFC - 0x1FFF: Measurement
+ -- 0x2000 - 0x8FFF: Free space
+
+ if address_f_s < "0001000000000000" then -- Tumbl
+ example_ce_s <= '1';
+ data_o_s <= example_out_s;
+ elsif address_f_s(15 downto 2) = "00011111111111" then -- Measurement
+ meas_ce_s <= '1';
+ data_o_s <= meas_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_read_s)
+ begin
+
+ -- CS0 / RD / BLS are active LOW
+ if cs0_xc = '0' and rd = '0' then
+ -- 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;
+
+ end process;
+
+end Behavioral;
+