library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; use work.lx_rocon_pkg.all; -- LX Master bus interconnect entity bus_lxmaster is port ( clk_i : in std_logic; reset_i : in std_logic; -- Data bus address_i : in std_logic_vector(10 downto 0); ce_i : in std_logic; data_i : in std_logic_vector(15 downto 0); data_o : out std_logic_vector(15 downto 0); -- bls_i : in std_logic_vector(1 downto 0); -- rx_done_o : out std_logic; -- Signals for LX Master clock_i : in std_logic; miso_i : in std_logic; sync_i : in std_logic; -- clock_o : out std_logic; mosi_o : out std_logic; sync_o : out std_logic ); end bus_lxmaster; architecture Behavioral of bus_lxmaster is constant cycle_cnt_width_c : natural := 12; -- number of bits constant rx_done_div_width_c : natural := 5; -- number of bits constant rx_done_cnt_width_c : natural := 5; -- number of bits signal mem_trans_en_s : std_logic; signal mem_trans_bls_s : std_logic_vector(1 downto 0); signal mem_trans_addr_s : std_logic_vector(8 downto 0); signal mem_trans_data_s : std_logic_vector(15 downto 0); signal mem_trans_out_s : std_logic; signal mem_trans_out_r : std_logic; -- signal mem_recv_en_s : std_logic; signal mem_recv_bls_s : std_logic_vector(1 downto 0); signal mem_recv_addr_s : std_logic_vector(8 downto 0); signal mem_recv_data_s : std_logic_vector(15 downto 0); signal mem_recv_out_s : std_logic; signal mem_recv_out_r : std_logic; -- signal state_o_s : std_logic_vector(15 downto 0); signal state_o_r : std_logic_vector(15 downto 0); -- signal reset_reg_s : std_logic; signal reset_reg_r : std_logic; signal reset_reg_wr_s : std_logic; -- signal reset_s : std_logic; signal ce_r : std_logic; -- signal register_trans_in_s : std_logic; signal register_trans_out_s : std_logic_vector(1 downto 0); signal register_trans_wr_s : std_logic; signal register_cycle_in_s : std_logic_vector(cycle_cnt_width_c-1 downto 0); signal register_cycle_out_s : std_logic_vector(cycle_cnt_width_c-1 downto 0); signal register_cycle_wr_s : std_logic; signal wdog_trans_in_s : std_logic; signal wdog_trans_wr_s : std_logic; -- signal register_recv_in_s : std_logic; signal register_recv_out_s : std_logic_vector(1 downto 0); signal register_recv_wr_s : std_logic; signal rx_done_s : std_logic; signal rx_done_ratio_s : std_logic_vector(rx_done_div_width_c-1 downto 0); signal rx_done_ratio_r : std_logic_vector(rx_done_div_width_c-1 downto 0); signal rx_done_ratio_wr_s : std_logic; signal rx_done_cnt_r : natural range 0 to (2**rx_done_cnt_width_c - 1); -- signal rx_crc_error_s : std_logic; signal rx_crc_error_r : std_logic; begin master_transmitter: lxmaster_transmitter generic map ( cycle_cnt_width_g => cycle_cnt_width_c ) port map ( clk_i => clk_i, reset_i => reset_s, -- Transmission clock_o => clock_o, mosi_o => mosi_o, sync_o => sync_o, -- Register register_i => register_trans_in_s, register_o => register_trans_out_s, register_we_i => register_trans_wr_s, -- Cycle period cycle_reg_i => register_cycle_in_s, cycle_reg_o => register_cycle_out_s, cycle_reg_we_i => register_cycle_wr_s, -- Watchdog wdog_i => wdog_trans_in_s, wdog_we_i => wdog_trans_wr_s, -- BRAM mem_clk_i => clk_i, mem_en_i => mem_trans_en_s, mem_we_i => mem_trans_bls_s, mem_addr_i => mem_trans_addr_s, mem_data_i => data_i, mem_data_o => mem_trans_data_s ); master_receiver: lxmaster_receiver port map ( clk_i => clk_i, reset_i => reset_s, -- Receiver serial data clock_i => clock_i, miso_i => miso_i, sync_i => sync_i, -- Receive done pulse rx_done_o => rx_done_s, rx_crc_error_o => rx_crc_error_s, -- Register register_i => register_recv_in_s, register_o => register_recv_out_s, register_we_i => register_recv_wr_s, -- BRAM mem_clk_i => clk_i, mem_en_i => mem_recv_en_s, mem_we_i => mem_recv_bls_s, mem_addr_i => mem_recv_addr_s, mem_data_i => data_i, mem_data_o => mem_recv_data_s ); rx_done_divider : cnt_div generic map ( cnt_width_g => rx_done_div_width_c ) port map ( clk_i => clk_i, en_i => rx_done_s, reset_i => reset_s, ratio_i => rx_done_ratio_r, q_out_o => rx_done_o ); reset_s <= reset_reg_r or reset_i; wire_in: process(ce_i, ce_r, reset_reg_r, bls_i, address_i, mem_trans_data_s, mem_recv_data_s, data_i, register_trans_out_s, register_recv_out_s, register_cycle_out_s, rx_done_ratio_r, rx_done_cnt_r, rx_crc_error_r) begin mem_trans_en_s <= '0'; mem_trans_out_s <= '0'; mem_trans_bls_s <= (others => '0'); mem_trans_addr_s <= (others => '0'); mem_recv_en_s <= '0'; mem_recv_out_s <= '0'; mem_recv_bls_s <= (others => '0'); mem_recv_addr_s <= (others => '0'); state_o_s <= (others => '0'); reset_reg_s <= '0'; reset_reg_wr_s <= '0'; register_trans_in_s <= '0'; register_trans_wr_s <= '0'; register_cycle_in_s <= (others => '0'); register_cycle_wr_s <= '0'; register_recv_in_s <= '0'; register_recv_wr_s <= '0'; wdog_trans_in_s <= '0'; wdog_trans_wr_s <= '0'; rx_done_ratio_wr_s <= '0'; rx_done_ratio_s <= rx_done_ratio_r; -- Incoming bus request if ce_i = '1' then -- Mapping: -- 00 & xxxxxxxx - LX Master transmitter BRAM -- 01 & xxxxxxxx - LX Master receiver BRAM -- 10 & 00000000 - LX Master reset -- 10 & 00000001 - LX Master transmitter register -- 10 & 00000010 - LX Master watchdog -- 10 & 00000011 - LX Master cycle period register -- 10 & 00000100 - LX Master receiver control register if address_i(10 downto 9) = "00" then mem_trans_addr_s <= address_i(8 downto 0); mem_trans_en_s <= '1'; mem_trans_bls_s <= bls_i; mem_trans_out_s <= '1'; elsif address_i(10 downto 9) = "01" then mem_recv_addr_s <= address_i(8 downto 0); mem_recv_en_s <= '1'; mem_recv_bls_s <= bls_i; mem_recv_out_s <= '1'; else if address_i(8 downto 3) = "000000" then if address_i(2 downto 0) = "000" then -- LX Master reset if bls_i(0) = '1' then reset_reg_s <= data_i(0); reset_reg_wr_s <= '1'; else -- Ugh, hack :-) state_o_s(0) <= reset_reg_r; state_o_s(1) <= '0'; state_o_s(15 downto 2) <= (others => '0'); end if; elsif address_i(2 downto 0) = "001" then -- LX Master register if bls_i(0) = '1' then register_trans_in_s <= data_i(0); register_trans_wr_s <= '1'; else state_o_s(1 downto 0) <= register_trans_out_s; state_o_s(15 downto 2) <= (others => '0'); end if; elsif address_i(2 downto 0) = "010" then if bls_i(0) = '1' then wdog_trans_in_s <= data_i(0); wdog_trans_wr_s <= '1'; end if; elsif address_i(2 downto 0) = "011" then -- LX Master period register if bls_i(0) = '1' then register_cycle_in_s <= data_i(cycle_cnt_width_c-1 downto 0); register_cycle_wr_s <= '1'; else state_o_s <= (15 downto cycle_cnt_width_c => '0') & register_cycle_out_s; end if; elsif address_i(2 downto 0) = "100" then if bls_i(0) = '1' then register_recv_in_s <= data_i(0); register_recv_wr_s <= '1'; else state_o_s(1 downto 0) <= register_recv_out_s; state_o_s(15 downto 2) <= (others => '0'); end if; elsif address_i(2 downto 0) = "101" then -- LX Master receiver done divisor if bls_i(0) = '1' then rx_done_ratio_s <= data_i(rx_done_div_width_c + 8 - 1 downto 8); rx_done_ratio_wr_s <= '1'; else state_o_s(rx_done_cnt_width_c - 1 downto 0) <= std_logic_vector(to_unsigned(rx_done_cnt_r, rx_done_cnt_width_c)); state_o_s(7 downto rx_done_cnt_width_c) <= (others => '0'); state_o_s(rx_done_div_width_c + 8 - 1 downto 8) <= rx_done_ratio_r; state_o_s(14 downto rx_done_div_width_c + 8) <= (others => '0'); state_o_s(15) <= rx_crc_error_r; end if; end if; end if; end if; end if; end process; wire_out: process(ce_r, mem_trans_data_s, mem_trans_out_r, mem_recv_data_s, mem_recv_out_r, state_o_r) begin data_o <= (others => '0'); if ce_r = '1' then if mem_trans_out_r = '1' then data_o <= mem_trans_data_s; elsif mem_recv_out_r = '1' then data_o <= mem_recv_data_s; else data_o <= state_o_r; end if; end if; end process; update: process begin wait until clk_i'event and clk_i= '1'; ce_r <= ce_i; mem_trans_out_r <= mem_trans_out_s; mem_recv_out_r <= mem_recv_out_s; state_o_r <= state_o_s; if reset_i = '1' then reset_reg_r <= '1'; elsif reset_reg_wr_s = '1' then reset_reg_r <= reset_reg_s; end if; if reset_i = '1' then rx_done_ratio_r <= ( 0 => '1', others => '0'); elsif rx_done_ratio_wr_s = '1' then rx_done_ratio_r <= rx_done_ratio_s; end if; if reset_i = '1' then rx_done_cnt_r <= 0; rx_crc_error_r <= '0'; elsif rx_done_s = '1' then rx_done_cnt_r <= rx_done_cnt_r + 1; rx_crc_error_r <= rx_crc_error_s; end if; end process; end Behavioral;