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; use work.mbl_pkg.all; use work.lx_rocon_pkg.all; -- Connects tumbl to the Master CPU entity bus_tumbl is port ( -- Clock clk_i : in std_logic; -- Chip enable ce_i : in std_logic; -- Global Reset reset_i : in std_logic; -- Master CPU bus for the memory bls_i : in std_logic_vector(3 downto 0); address_i : in std_logic_vector(11 downto 0); data_i : in std_logic_vector(31 downto 0); data_o : out std_logic_vector(31 downto 0); -- Tumbl extrenal memory bus xmemb_sel_o : out std_logic; xmemb_i : in DMEMB2CORE_Type; xmemb_o : out CORE2DMEMB_Type ); end bus_tumbl; architecture Behavioral of bus_tumbl is -- Types type TUMBL_Input_Type is record halt : std_logic; int : std_logic; trace : std_logic; trace_kick : std_logic; end record; type TUMBL_State_Type is record pc : std_logic_vector(31 downto 0); halted : std_logic; halt_code : std_logic_vector(4 downto 0); end record; -- Reset signal tumbl_reset_s : std_logic; -- Internals signal tumbl_input_s : TUMBL_Input_Type; signal tumbl_state_s : TUMBL_State_Type; -- 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); 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 -- -- Selection: -- 00 - imem -- 01 - dmem -- 10 - reserved -- 11 - registers -- Registers -- 0x000 -- -- Bit 0: RW - Reset -- Bit 1: RW - Interrupt -- Bit 2: RW - Halt -- Bit 3: RW - Trace -- Bit 4: R - Halted -- 0x001 -- Bit 0: W - Write 1 for trace kick -- 0x002 -- Tumbl program counter (R) -- 0x003 -- Halt code begin -- Wire it to the tumbl I_TUMBL: lx_rocon_tumbl generic map ( IMEM_ABITS_g => 9, DMEM_ABITS_g => 10, -- USE_HW_MUL_g => true, USE_BARREL_g => true, COMPATIBILITY_MODE_g => false ) port map ( clk_i => clk_i, rst_i => tumbl_reset_s, halt_i => tumbl_input_s.halt, int_i => tumbl_input_s.int, trace_i => tumbl_input_s.trace, trace_kick_i => tumbl_input_s.trace_kick, pc_o => tumbl_state_s.pc, halted_o => tumbl_state_s.halted, halt_code_o => tumbl_state_s.halt_code, -- Internal memory (instruction) imem_clk_i => clk_i, imem_en_i => imem_en_s, imem_we_i => imem_we_s, imem_addr_i => address_i(8 downto 0), imem_data_i => data_i, imem_data_o => imem_data_o_s, -- Internal memory (data) dmem_clk_i => clk_i, dmem_en_i => dmem_en_s, dmem_we_i => dmem_we_s, dmem_addr_i => address_i(9 downto 0), dmem_data_i => data_i, dmem_data_o => dmem_data_o_s, -- External memory bus xmemb_sel_o => xmemb_sel_o, xmemb_i => xmemb_i, xmemb_o => xmemb_o ); -- Enabling enabling: process(ce_i, address_i) begin if ce_i = '1' and address_i(11 downto 10) = "00" then imem_en_s <= '1'; else imem_en_s <= '0'; end if; if ce_i = '1' and address_i(11 downto 10) = "01" then dmem_en_s <= '1'; else dmem_en_s <= '0'; end if; end process; -- 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, 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 imem_we_s <= bls_i; else imem_we_s <= "0000"; end if; if dmem_en_s = '1' then dmem_we_s <= bls_i; else dmem_we_s <= "0000"; end if; if imem_en_r = '1' then data_o <= imem_data_o_s; elsif dmem_en_r = '1' then data_o <= dmem_data_o_s; 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; end process; -- Transaction acknowledge and writing to registers update: process begin -- 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 tumbl_reset_s <= '1'; tumbl_input_s.int <= '0'; tumbl_input_s.halt <= '0'; tumbl_input_s.trace <= '0'; else if ce_i = '1' and address_i(11 downto 10) = "11" then if bls_i(0) = '1' then if address_i(9 downto 0) = "0000000000" then tumbl_reset_s <= data_i(0); tumbl_input_s.int <= data_i(1); tumbl_input_s.halt <= data_i(2); tumbl_input_s.trace <= data_i(3); elsif address_i(9 downto 0) = "0000000001" then if data_i(0) = '1' then tumbl_input_s.trace_kick <= '1'; 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; end process; end Behavioral;