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;