--
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);
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)
--
-- 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);
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
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')
--
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
-- ======================================================
-- 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
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)
-- 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
data <= (others => 'Z');
end if;
- data_write_s <= data;
-
end process;
-- Outputs from Tumbl (enabling and address muxing) and Master CPU
-- 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');
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;
-- 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');
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;