From 86c7da50752bcae73c23411cbf2251c6a7d37534 Mon Sep 17 00:00:00 2001 From: matt Date: Fri, 28 Feb 2020 15:33:10 +0700 Subject: [PATCH] Working muxing with stationary MUX register --- i2c_slave.vhd | 301 +++++++++++++++++++++++ sim_switcher_pkg.vhd | 24 ++ sim_switcher_top.vhd | 574 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 875 insertions(+), 24 deletions(-) create mode 100644 i2c_slave.vhd create mode 100644 sim_switcher_pkg.vhd diff --git a/i2c_slave.vhd b/i2c_slave.vhd new file mode 100644 index 0000000..18d9bb2 --- /dev/null +++ b/i2c_slave.vhd @@ -0,0 +1,301 @@ +------------------------------------------------------------ +-- File : I2C_slave.vhd +------------------------------------------------------------ +-- Author : Peter Samarin +------------------------------------------------------------ +-- Copyright (c) 2016 Peter Samarin +------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +------------------------------------------------------------ +entity i2c_slave is + generic ( + SLAVE_ADDR : std_logic_vector(6 downto 0)); + port ( + scl : inout std_logic; + sda : inout std_logic; + clk : in std_logic; + rst : in std_logic; + -- User interface + read_req : out std_logic; + data_to_master : in std_logic_vector(7 downto 0); + data_valid : out std_logic; + data_from_master : out std_logic_vector(7 downto 0)); +end entity i2c_slave; +------------------------------------------------------------ +architecture arch of i2c_slave is + -- this assumes that system's clock is much faster than SCL + constant DEBOUNCING_WAIT_CYCLES : integer := 4; + + type state_t is (idle, get_address_and_cmd, + answer_ack_start, write, + read, read_ack_start, + read_ack_got_rising, read_stop); + -- I2C state management + signal state_reg : state_t := idle; + signal cmd_reg : std_logic := '0'; + signal bits_processed_reg : integer range 0 to 8 := 0; + signal continue_reg : std_logic := '0'; + + signal scl_reg : std_logic := '1'; + signal sda_reg : std_logic := '1'; + signal scl_debounced : std_logic := '1'; + signal sda_debounced : std_logic := '1'; + + + -- Helpers to figure out next state + signal start_reg : std_logic := '0'; + signal stop_reg : std_logic := '0'; + signal scl_rising_reg : std_logic := '0'; + signal scl_falling_reg : std_logic := '0'; + + -- Address and data received from master + signal addr_reg : std_logic_vector(6 downto 0) := (others => '0'); + signal data_reg : std_logic_vector(6 downto 0) := (others => '0'); + signal data_from_master_reg : std_logic_vector(7 downto 0) := (others => '0'); + + signal scl_prev_reg : std_logic := '1'; + -- Slave writes on scl + signal scl_wen_reg : std_logic := '0'; + signal scl_o_reg : std_logic := '0'; + signal sda_prev_reg : std_logic := '1'; + -- Slave writes on sda + signal sda_wen_reg : std_logic := '0'; + signal sda_o_reg : std_logic := '0'; + + -- User interface + signal data_valid_reg : std_logic := '0'; + signal read_req_reg : std_logic := '0'; + signal data_to_master_reg : std_logic_vector(7 downto 0) := (others => '0'); +begin + + -- debounce SCL and SDA + SCL_debounce : entity work.debounce + generic map ( + WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES) + port map ( + clk => clk, + signal_in => scl_reg, + signal_out => scl_debounced); + + -- it might not make sense to debounce SDA, since master + -- and slave can both write to it... + SDA_debounce : entity work.debounce + generic map ( + WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES) + port map ( + clk => clk, + signal_in => sda_reg, + signal_out => sda_debounced); + + process (clk) is + begin + if rising_edge(clk) then + -- save SCL in registers that are used for debouncing + scl_reg <= scl; + sda_reg <= sda; + + -- Delay debounced SCL and SDA by 1 clock cycle + scl_prev_reg <= scl_debounced; + sda_prev_reg <= sda_debounced; + -- Detect rising and falling SCL + scl_rising_reg <= '0'; + if scl_prev_reg = '0' and scl_debounced = '1' then + scl_rising_reg <= '1'; + end if; + scl_falling_reg <= '0'; + if scl_prev_reg = '1' and scl_debounced = '0' then + scl_falling_reg <= '1'; + end if; + + -- Detect I2C START condition + start_reg <= '0'; + stop_reg <= '0'; + if scl_debounced = '1' and scl_prev_reg = '1' and + sda_prev_reg = '1' and sda_debounced = '0' then + start_reg <= '1'; + stop_reg <= '0'; + end if; + + -- Detect I2C STOP condition + if scl_prev_reg = '1' and scl_debounced = '1' and + sda_prev_reg = '0' and sda_debounced = '1' then + start_reg <= '0'; + stop_reg <= '1'; + end if; + + end if; + end process; + + ---------------------------------------------------------- + -- I2C state machine + ---------------------------------------------------------- + process (clk) is + begin + if rising_edge(clk) then + -- Default assignments + sda_o_reg <= '0'; + sda_wen_reg <= '0'; + -- User interface + data_valid_reg <= '0'; + read_req_reg <= '0'; + + case state_reg is + + when idle => + if start_reg = '1' then + state_reg <= get_address_and_cmd; + bits_processed_reg <= 0; + end if; + + when get_address_and_cmd => + if scl_rising_reg = '1' then + if bits_processed_reg < 7 then + bits_processed_reg <= bits_processed_reg + 1; + addr_reg(6-bits_processed_reg) <= sda_debounced; + elsif bits_processed_reg = 7 then + bits_processed_reg <= bits_processed_reg + 1; + cmd_reg <= sda_debounced; + end if; + end if; + + if bits_processed_reg = 8 and scl_falling_reg = '1' then + bits_processed_reg <= 0; + if addr_reg = SLAVE_ADDR then -- check req address + state_reg <= answer_ack_start; + if cmd_reg = '1' then -- issue read request + read_req_reg <= '1'; + data_to_master_reg <= data_to_master; + end if; + else + assert false + report ("I2C: target/slave address mismatch (data is being sent to another slave).") + severity note; + state_reg <= idle; + end if; + end if; + + ---------------------------------------------------- + -- I2C acknowledge to master + ---------------------------------------------------- + when answer_ack_start => + sda_wen_reg <= '1'; + sda_o_reg <= '0'; + if scl_falling_reg = '1' then + if cmd_reg = '0' then + state_reg <= write; + else + state_reg <= read; + end if; + end if; + + ---------------------------------------------------- + -- WRITE + ---------------------------------------------------- + when write => + if scl_rising_reg = '1' then + bits_processed_reg <= bits_processed_reg + 1; + if bits_processed_reg < 7 then + data_reg(6-bits_processed_reg) <= sda_debounced; + else + data_from_master_reg <= data_reg & sda_debounced; + data_valid_reg <= '1'; + end if; + end if; + + if scl_falling_reg = '1' and bits_processed_reg = 8 then + state_reg <= answer_ack_start; + bits_processed_reg <= 0; + end if; + + ---------------------------------------------------- + -- READ: send data to master + ---------------------------------------------------- + when read => + sda_wen_reg <= '1'; + sda_o_reg <= data_to_master_reg(7-bits_processed_reg); + if scl_falling_reg = '1' then + if bits_processed_reg < 7 then + bits_processed_reg <= bits_processed_reg + 1; + elsif bits_processed_reg = 7 then + state_reg <= read_ack_start; + bits_processed_reg <= 0; + end if; + end if; + + ---------------------------------------------------- + -- I2C read master acknowledge + ---------------------------------------------------- + when read_ack_start => + if scl_rising_reg = '1' then + state_reg <= read_ack_got_rising; + if sda_debounced = '1' then -- nack = stop read + continue_reg <= '0'; + else -- ack = continue read + continue_reg <= '1'; + read_req_reg <= '1'; -- request reg byte + data_to_master_reg <= data_to_master; + end if; + end if; + + when read_ack_got_rising => + if scl_falling_reg = '1' then + if continue_reg = '1' then + if cmd_reg = '0' then + state_reg <= write; + else + state_reg <= read; + end if; + else + state_reg <= read_stop; + end if; + end if; + + -- Wait for START or STOP to get out of this state + when read_stop => + null; + + -- Wait for START or STOP to get out of this state + when others => + assert false + report ("I2C: error: ended in an impossible state.") + severity error; + state_reg <= idle; + end case; + + -------------------------------------------------------- + -- Reset counter and state on start/stop + -------------------------------------------------------- + if start_reg = '1' then + state_reg <= get_address_and_cmd; + bits_processed_reg <= 0; + end if; + + if stop_reg = '1' then + state_reg <= idle; + bits_processed_reg <= 0; + end if; + + if rst = '1' then + state_reg <= idle; + end if; + end if; + end process; + + ---------------------------------------------------------- + -- I2C interface + ---------------------------------------------------------- + sda <= sda_o_reg when sda_wen_reg = '1' else + 'Z'; + scl <= scl_o_reg when scl_wen_reg = '1' else + 'Z'; + ---------------------------------------------------------- + -- User interface + ---------------------------------------------------------- + -- Master writes + data_valid <= data_valid_reg; + data_from_master <= data_from_master_reg; + -- Master reads + read_req <= read_req_reg; +end architecture arch; diff --git a/sim_switcher_pkg.vhd b/sim_switcher_pkg.vhd new file mode 100644 index 0000000..adc06b0 --- /dev/null +++ b/sim_switcher_pkg.vhd @@ -0,0 +1,24 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package sim_switcher_pkg is + + component i2c_slave is + generic ( + SLAVE_ADDR : std_logic_vector(6 downto 0) + ); + port ( + scl : inout std_logic; + sda : inout std_logic; + clk : in std_logic; + rst : in std_logic; + -- User interface + read_req : out std_logic; + data_to_master : in std_logic_vector(7 downto 0); + data_valid : out std_logic; + data_from_master : out std_logic_vector(7 downto 0) + ); + end component i2c_slave; + +end package sim_switcher_pkg; \ No newline at end of file diff --git a/sim_switcher_top.vhd b/sim_switcher_top.vhd index 4bb07c7..27d0705 100644 --- a/sim_switcher_top.vhd +++ b/sim_switcher_top.vhd @@ -1,7 +1,7 @@ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; ---use work.sim_switcher_pkg.all; +use work.sim_switcher_pkg.all; entity sim_switcher_top is generic ( @@ -63,7 +63,7 @@ architecture rtl of sim_switcher_top is ); end component; - constant FLASHES : natural := 1; -- Number of LED flashes on boot + constant FLASHES : natural := 5; -- Number of LED flashes on boot constant CPU_RST_DURATION : natural := 100_000_000; -- 25_000_000 = 1sec constant PON_RST_DURATION : natural := 10; -- 25_000_000 = 1sec constant PON_CPU_DELAY_DURATION : natural := 75_000_000; -- 25_000_000 = 1sec @@ -85,16 +85,55 @@ architecture rtl of sim_switcher_top is signal s_led_o : std_logic := '1'; + -- I2C slave parallel interface + signal i2c_read_req : std_logic := '0'; + signal i2c_data_to_master : std_logic_vector(7 downto 0) := (others => '0'); + signal i2c_data_valid : std_logic := '0'; + signal i2c_data_from_master : std_logic_vector(7 downto 0) := (others => '0'); + + -- I2C slave state machine + type i2c_fsm_t is (ready, receive_byte, wait_while_sent); + signal i2c_slv_state : i2c_fsm_t := ready; + + -- signal reg_sim_sel : sim_mux_addr_t(3 downto 0); + -- signal reg_sim_pwr : std_logic_vector(15 downto 0); + -- signal reg_sim_det : std_logic_vector(15 downto 0); + -- signal s_reg_to_write : std_logic_vector(7 downto 0); + -- SIM data signals - signal s_sim_data_i, sdb_sim_data_i, sdb_sim_data_prev, s_sim_data_o: std_logic_vector(7 downto 0); + signal s_sim_data_i, sdb_sim_data_i, sdb_sim_data_prev, s_sim_data_o: std_logic_vector(15 downto 0); -- Modem data signals - signal s_mod_data_i, sdb_mod_data_i, sdb_mod_data_prev, s_mod_data_o: std_logic_vector(7 downto 0); + signal s_mod_data_i, sdb_mod_data_i, sw_mod_data_i, sw_mod_data_prev, s_mod_data_o, sw_mod_data_o: std_logic_vector(7 downto 0); + -- SIM switch IRQs for repeater state machine reset upon SIM change + signal reg_sim_change_irq: std_logic_vector(15 downto 0) := (others => '0'); + + -- State machine signals and types type state_t is (idle, mod_to_sim, sim_to_mod); - type arr_state_t is array (integer range <>) of state_t; - signal state: arr_state_t(0 to 7); + type arr_state_t is array (natural range <>) of state_t; + signal state: arr_state_t(0 to 7); + + -- SIM-MODEM switching register + type arr_modnum_t is array (natural range <>) of natural range 0 to 15; + signal reg_sim_modemnum: arr_modnum_t(0 to 7); + begin + s_sim_data_i(15 downto 8) <= (others => '1'); + sdb_sim_data_i(15 downto 8) <= (others => '1'); + + reg_sim_modemnum <= ( + 0 => 7, + 1 => 6, + 2 => 5, + 3 => 4, + 4 => 3, + 5 => 2, + 6 => 1, + 7 => 0 + ); + + reg_sim_change_irq <= (others => '0'); ---------------------------------- -- Power-On FPGA IP-cores reset -- @@ -191,10 +230,355 @@ begin end if; end process; + -------------------------------- + -- I2C slave interface to CPU -- + -------------------------------- +-- inst_i2c_slave: i2c_slave +-- generic map ( +-- SLAVE_ADDR => I2C_SLAVE_ADDR +-- ) +-- port map( +-- scl => i2c_scl_io, +-- sda => i2c_sda_io, +-- clk => clk25_i, +-- rst => s_rst_i, +-- read_req => i2c_read_req, +-- data_to_master => i2c_data_to_master, +-- data_valid => i2c_data_valid, +-- data_from_master => i2c_data_from_master +-- ); + +-- i2c_slv_process : process (clk25_i, s_rstn_i) +-- variable wait_cnt : natural := 0; +-- begin +-- if (s_rstn_i = '0') then +-- i2c_data_to_master <= (others => '0'); +-- wait_cnt := 0; + +-- -- SIM select reset: default is SIM#1 +-- reg_sim_sel <= (others => (others => '0')); + +-- -- Turn on all SIM cards +-- reg_sim_pwr <= (others => '1'); + +-- -- Only first SIMs are powered on upon reset +-- -- reg_sim_pwr(0) <= '1'; +-- -- reg_sim_pwr(3 downto 1) <= (others => '0'); +-- -- +-- -- reg_sim_pwr(4) <= '1'; +-- -- reg_sim_pwr(7 downto 5) <= (others => '0'); +-- -- +-- -- reg_sim_pwr(8) <= '1'; +-- -- reg_sim_pwr(11 downto 9) <= (others => '0'); +-- -- +-- -- reg_sim_pwr(12) <= '1'; +-- -- reg_sim_pwr(15 downto 13) <= (others => '0'); +-- +-- reg_sim_change_irq <= (others => '0'); +-- +-- elsif (rising_edge(clk25_i)) then +-- case i2c_slv_state is +-- when ready => +-- wait_cnt := 0; +-- i2c_data_to_master <= (others => '0'); +-- if (i2c_data_valid = '1') then -- master sent a register addr byte +-- -- Save register address for later use in write procedure +-- s_reg_to_write <= i2c_data_from_master; + +-- case i2c_data_from_master is +-- when x"10" => -- Read ID byte +-- i2c_data_to_master <= x"18"; +-- i2c_slv_state <= wait_while_sent; + +-- when x"11" => -- Read SW Version byte (v1.0=0x18, v1.1=0x19) +-- i2c_data_to_master <= x"19"; +-- i2c_slv_state <= wait_while_sent; + +-- when x"0A" => -- Read SIMs detect register (LSB) +-- i2c_data_to_master <= reg_sim_det(7 downto 0); +-- i2c_slv_state <= wait_while_sent; +-- when x"0B" => -- Read SIMs detect register (MSB) +-- i2c_data_to_master <= reg_sim_det(15 downto 8); +-- i2c_slv_state <= wait_while_sent; +-- when x"0C" => -- Read SIMs power register (LSB) +-- i2c_data_to_master <= reg_sim_pwr(7 downto 0); +-- i2c_slv_state <= wait_while_sent; +-- when x"0D" => -- Read SIMs power register (MSB) +-- i2c_data_to_master <= reg_sim_pwr(15 downto 8); +-- i2c_slv_state <= wait_while_sent; + +-- when x"1A" => -- Read M1 SIM select register +-- i2c_data_to_master <= "000000" & reg_sim_sel(0); +-- i2c_slv_state <= wait_while_sent; +-- when x"1B" => -- Read M2 SIM select register +-- i2c_data_to_master <= "000000" & reg_sim_sel(1); +-- i2c_slv_state <= wait_while_sent; +-- when x"1C" => -- Read M3 SIM select register +-- i2c_data_to_master <= "000000" & reg_sim_sel(2); +-- i2c_slv_state <= wait_while_sent; +-- when x"1D" => -- Read M4 SIM select register +-- i2c_data_to_master <= "000000" & reg_sim_sel(3); +-- i2c_slv_state <= wait_while_sent; + +-- when x"8C" => -- Write SIMs power register (LSB) +-- i2c_slv_state <= receive_byte; +-- when x"8D" => -- Write SIMs power register (MSB) +-- i2c_slv_state <= receive_byte; + +-- when x"9A" => -- Write M1 select register +-- i2c_slv_state <= receive_byte; +-- when x"9B" => -- Write M2 select register +-- i2c_slv_state <= receive_byte; +-- when x"9C" => -- Write M3 select register +-- i2c_slv_state <= receive_byte; +-- when x"9D" => -- Write M4 select register +-- i2c_slv_state <= receive_byte; + +-- when others => +-- i2c_slv_state <= ready; +-- end case; +-- end if; + +-- when receive_byte => +-- if (i2c_data_valid = '1') then +-- case s_reg_to_write is +-- when x"8C" => -- Write SIMs power register (LSB) +-- reg_sim_pwr(7 downto 0) <= i2c_data_from_master(7 downto 0); +-- when x"8D" => -- Write SIMs power register (MSB) +-- reg_sim_pwr(15 downto 8) <= i2c_data_from_master(7 downto 0); + +-- when x"9A" => -- Write M1 select register +-- reg_sim_sel(0) <= i2c_data_from_master(1 downto 0); +-- when x"9B" => -- Write M2 select register +-- reg_sim_sel(1) <= i2c_data_from_master(1 downto 0); +-- when x"9C" => -- Write M3 select register +-- reg_sim_sel(2) <= i2c_data_from_master(1 downto 0); +-- when x"9D" => -- Write M4 select register +-- reg_sim_sel(3) <= i2c_data_from_master(1 downto 0); +-- when others => +-- null; +-- end case; +-- i2c_slv_state <= ready; +-- else +-- -- Wait timer to prevent freeze in waiting state +-- if (wait_cnt > I2C_MAX_WAIT) then +-- i2c_slv_state <= ready; +-- else +-- wait_cnt := wait_cnt + 1; +-- end if; +-- end if; + +-- when wait_while_sent => +-- if (i2c_read_req = '1') then +-- i2c_slv_state <= ready; +-- else +-- -- Wait timer to prevent freeze in waiting state +-- if (wait_cnt > I2C_MAX_WAIT) then +-- i2c_slv_state <= ready; +-- else +-- wait_cnt := wait_cnt + 1; +-- end if; +-- end if; + +-- when others => +-- i2c_slv_state <= ready; + +-- end case; +-- end if; +-- end process i2c_slv_process; ------------------------------- --- SIM card emulation test --- ------------------------------- + -- Switch RST line of SIM according to connected MODEM + sim_rst_o(0) <= mod_rst_i(0) when reg_sim_modemnum(0) = 0 + else mod_rst_i(1) when reg_sim_modemnum(0) = 1 + else mod_rst_i(2) when reg_sim_modemnum(0) = 2 + else mod_rst_i(3) when reg_sim_modemnum(0) = 3 + else mod_rst_i(4) when reg_sim_modemnum(0) = 4 + else mod_rst_i(5) when reg_sim_modemnum(0) = 5 + else mod_rst_i(6) when reg_sim_modemnum(0) = 6 + else mod_rst_i(7) when reg_sim_modemnum(0) = 7 + else 'Z'; + sim_rst_o(1) <= mod_rst_i(0) when reg_sim_modemnum(1) = 0 + else mod_rst_i(1) when reg_sim_modemnum(1) = 1 + else mod_rst_i(2) when reg_sim_modemnum(1) = 2 + else mod_rst_i(3) when reg_sim_modemnum(1) = 3 + else mod_rst_i(4) when reg_sim_modemnum(1) = 4 + else mod_rst_i(5) when reg_sim_modemnum(1) = 5 + else mod_rst_i(6) when reg_sim_modemnum(1) = 6 + else mod_rst_i(7) when reg_sim_modemnum(1) = 7 + else 'Z'; + sim_rst_o(2) <= mod_rst_i(0) when reg_sim_modemnum(2) = 0 + else mod_rst_i(1) when reg_sim_modemnum(2) = 1 + else mod_rst_i(2) when reg_sim_modemnum(2) = 2 + else mod_rst_i(3) when reg_sim_modemnum(2) = 3 + else mod_rst_i(4) when reg_sim_modemnum(2) = 4 + else mod_rst_i(5) when reg_sim_modemnum(2) = 5 + else mod_rst_i(6) when reg_sim_modemnum(2) = 6 + else mod_rst_i(7) when reg_sim_modemnum(2) = 7 + else 'Z'; + sim_rst_o(3) <= mod_rst_i(0) when reg_sim_modemnum(3) = 0 + else mod_rst_i(1) when reg_sim_modemnum(3) = 1 + else mod_rst_i(2) when reg_sim_modemnum(3) = 2 + else mod_rst_i(3) when reg_sim_modemnum(3) = 3 + else mod_rst_i(4) when reg_sim_modemnum(3) = 4 + else mod_rst_i(5) when reg_sim_modemnum(3) = 5 + else mod_rst_i(6) when reg_sim_modemnum(3) = 6 + else mod_rst_i(7) when reg_sim_modemnum(3) = 7 + else 'Z'; + sim_rst_o(4) <= mod_rst_i(0) when reg_sim_modemnum(4) = 0 + else mod_rst_i(1) when reg_sim_modemnum(4) = 1 + else mod_rst_i(2) when reg_sim_modemnum(4) = 2 + else mod_rst_i(3) when reg_sim_modemnum(4) = 3 + else mod_rst_i(4) when reg_sim_modemnum(4) = 4 + else mod_rst_i(5) when reg_sim_modemnum(4) = 5 + else mod_rst_i(6) when reg_sim_modemnum(4) = 6 + else mod_rst_i(7) when reg_sim_modemnum(4) = 7 + else 'Z'; + sim_rst_o(5) <= mod_rst_i(0) when reg_sim_modemnum(5) = 0 + else mod_rst_i(1) when reg_sim_modemnum(5) = 1 + else mod_rst_i(2) when reg_sim_modemnum(5) = 2 + else mod_rst_i(3) when reg_sim_modemnum(5) = 3 + else mod_rst_i(4) when reg_sim_modemnum(5) = 4 + else mod_rst_i(5) when reg_sim_modemnum(5) = 5 + else mod_rst_i(6) when reg_sim_modemnum(5) = 6 + else mod_rst_i(7) when reg_sim_modemnum(5) = 7 + else 'Z'; + sim_rst_o(6) <= mod_rst_i(0) when reg_sim_modemnum(6) = 0 + else mod_rst_i(1) when reg_sim_modemnum(6) = 1 + else mod_rst_i(2) when reg_sim_modemnum(6) = 2 + else mod_rst_i(3) when reg_sim_modemnum(6) = 3 + else mod_rst_i(4) when reg_sim_modemnum(6) = 4 + else mod_rst_i(5) when reg_sim_modemnum(6) = 5 + else mod_rst_i(6) when reg_sim_modemnum(6) = 6 + else mod_rst_i(7) when reg_sim_modemnum(6) = 7 + else 'Z'; + sim_rst_o(7) <= mod_rst_i(0) when reg_sim_modemnum(7) = 0 + else mod_rst_i(1) when reg_sim_modemnum(7) = 1 + else mod_rst_i(2) when reg_sim_modemnum(7) = 2 + else mod_rst_i(3) when reg_sim_modemnum(7) = 3 + else mod_rst_i(4) when reg_sim_modemnum(7) = 4 + else mod_rst_i(5) when reg_sim_modemnum(7) = 5 + else mod_rst_i(6) when reg_sim_modemnum(7) = 6 + else mod_rst_i(7) when reg_sim_modemnum(7) = 7 + else 'Z'; + + -- Switch CLK line of SIM according to connected MODEM + sim_clk_o(0) <= mod_clk_i(0) when reg_sim_modemnum(0) = 0 + else mod_clk_i(1) when reg_sim_modemnum(0) = 1 + else mod_clk_i(2) when reg_sim_modemnum(0) = 2 + else mod_clk_i(3) when reg_sim_modemnum(0) = 3 + else mod_clk_i(4) when reg_sim_modemnum(0) = 4 + else mod_clk_i(5) when reg_sim_modemnum(0) = 5 + else mod_clk_i(6) when reg_sim_modemnum(0) = 6 + else mod_clk_i(7) when reg_sim_modemnum(0) = 7 + else 'Z'; + sim_clk_o(1) <= mod_clk_i(0) when reg_sim_modemnum(1) = 0 + else mod_clk_i(1) when reg_sim_modemnum(1) = 1 + else mod_clk_i(2) when reg_sim_modemnum(1) = 2 + else mod_clk_i(3) when reg_sim_modemnum(1) = 3 + else mod_clk_i(4) when reg_sim_modemnum(1) = 4 + else mod_clk_i(5) when reg_sim_modemnum(1) = 5 + else mod_clk_i(6) when reg_sim_modemnum(1) = 6 + else mod_clk_i(7) when reg_sim_modemnum(1) = 7 + else 'Z'; + sim_clk_o(2) <= mod_clk_i(0) when reg_sim_modemnum(2) = 0 + else mod_clk_i(1) when reg_sim_modemnum(2) = 1 + else mod_clk_i(2) when reg_sim_modemnum(2) = 2 + else mod_clk_i(3) when reg_sim_modemnum(2) = 3 + else mod_clk_i(4) when reg_sim_modemnum(2) = 4 + else mod_clk_i(5) when reg_sim_modemnum(2) = 5 + else mod_clk_i(6) when reg_sim_modemnum(2) = 6 + else mod_clk_i(7) when reg_sim_modemnum(2) = 7 + else 'Z'; + sim_clk_o(3) <= mod_clk_i(0) when reg_sim_modemnum(3) = 0 + else mod_clk_i(1) when reg_sim_modemnum(3) = 1 + else mod_clk_i(2) when reg_sim_modemnum(3) = 2 + else mod_clk_i(3) when reg_sim_modemnum(3) = 3 + else mod_clk_i(4) when reg_sim_modemnum(3) = 4 + else mod_clk_i(5) when reg_sim_modemnum(3) = 5 + else mod_clk_i(6) when reg_sim_modemnum(3) = 6 + else mod_clk_i(7) when reg_sim_modemnum(3) = 7 + else 'Z'; + sim_clk_o(4) <= mod_clk_i(0) when reg_sim_modemnum(4) = 0 + else mod_clk_i(1) when reg_sim_modemnum(4) = 1 + else mod_clk_i(2) when reg_sim_modemnum(4) = 2 + else mod_clk_i(3) when reg_sim_modemnum(4) = 3 + else mod_clk_i(4) when reg_sim_modemnum(4) = 4 + else mod_clk_i(5) when reg_sim_modemnum(4) = 5 + else mod_clk_i(6) when reg_sim_modemnum(4) = 6 + else mod_clk_i(7) when reg_sim_modemnum(4) = 7 + else 'Z'; + sim_clk_o(5) <= mod_clk_i(0) when reg_sim_modemnum(5) = 0 + else mod_clk_i(1) when reg_sim_modemnum(5) = 1 + else mod_clk_i(2) when reg_sim_modemnum(5) = 2 + else mod_clk_i(3) when reg_sim_modemnum(5) = 3 + else mod_clk_i(4) when reg_sim_modemnum(5) = 4 + else mod_clk_i(5) when reg_sim_modemnum(5) = 5 + else mod_clk_i(6) when reg_sim_modemnum(5) = 6 + else mod_clk_i(7) when reg_sim_modemnum(5) = 7 + else 'Z'; + sim_clk_o(6) <= mod_clk_i(0) when reg_sim_modemnum(6) = 0 + else mod_clk_i(1) when reg_sim_modemnum(6) = 1 + else mod_clk_i(2) when reg_sim_modemnum(6) = 2 + else mod_clk_i(3) when reg_sim_modemnum(6) = 3 + else mod_clk_i(4) when reg_sim_modemnum(6) = 4 + else mod_clk_i(5) when reg_sim_modemnum(6) = 5 + else mod_clk_i(6) when reg_sim_modemnum(6) = 6 + else mod_clk_i(7) when reg_sim_modemnum(6) = 7 + else 'Z'; + sim_clk_o(7) <= mod_clk_i(0) when reg_sim_modemnum(7) = 0 + else mod_clk_i(1) when reg_sim_modemnum(7) = 1 + else mod_clk_i(2) when reg_sim_modemnum(7) = 2 + else mod_clk_i(3) when reg_sim_modemnum(7) = 3 + else mod_clk_i(4) when reg_sim_modemnum(7) = 4 + else mod_clk_i(5) when reg_sim_modemnum(7) = 5 + else mod_clk_i(6) when reg_sim_modemnum(7) = 6 + else mod_clk_i(7) when reg_sim_modemnum(7) = 7 + else 'Z'; + + -- Switch SIM DETECT line of SIM according to connected MODEM, + mod_detect_o(0) <= sim_detect_i(0) when reg_sim_modemnum(0) = 0 + else sim_detect_i(1) when reg_sim_modemnum(1) = 0 + else sim_detect_i(2) when reg_sim_modemnum(2) = 0 + else sim_detect_i(3) when reg_sim_modemnum(3) = 0 + else sim_detect_i(4) when reg_sim_modemnum(4) = 0 + else sim_detect_i(5) when reg_sim_modemnum(5) = 0 + else sim_detect_i(6) when reg_sim_modemnum(6) = 0 + else sim_detect_i(7) when reg_sim_modemnum(7) = 0 + else 'Z'; + mod_detect_o(1) <= sim_detect_i(0) when reg_sim_modemnum(0) = 1 + else sim_detect_i(1) when reg_sim_modemnum(1) = 1 + else sim_detect_i(2) when reg_sim_modemnum(2) = 1 + else sim_detect_i(3) when reg_sim_modemnum(3) = 1 + else sim_detect_i(4) when reg_sim_modemnum(4) = 1 + else sim_detect_i(5) when reg_sim_modemnum(5) = 1 + else sim_detect_i(6) when reg_sim_modemnum(6) = 1 + else sim_detect_i(7) when reg_sim_modemnum(7) = 1 + else 'Z'; + mod_detect_o(2) <= sim_detect_i(0) when reg_sim_modemnum(0) = 2 + else sim_detect_i(1) when reg_sim_modemnum(1) = 2 + else sim_detect_i(2) when reg_sim_modemnum(2) = 2 + else sim_detect_i(3) when reg_sim_modemnum(3) = 2 + else sim_detect_i(4) when reg_sim_modemnum(4) = 2 + else sim_detect_i(5) when reg_sim_modemnum(5) = 2 + else sim_detect_i(6) when reg_sim_modemnum(6) = 2 + else sim_detect_i(7) when reg_sim_modemnum(7) = 2 + else 'Z'; + mod_detect_o(3) <= sim_detect_i(0) when reg_sim_modemnum(0) = 3 + else sim_detect_i(1) when reg_sim_modemnum(1) = 3 + else sim_detect_i(2) when reg_sim_modemnum(2) = 3 + else sim_detect_i(3) when reg_sim_modemnum(3) = 3 + else sim_detect_i(4) when reg_sim_modemnum(4) = 3 + else sim_detect_i(5) when reg_sim_modemnum(5) = 3 + else sim_detect_i(6) when reg_sim_modemnum(6) = 3 + else sim_detect_i(7) when reg_sim_modemnum(7) = 3 + else 'Z'; + + -- Route one-way signals from mod to SIM + sim_pwron_o <= (others => '1');--mod_pwron_i; + --mod_detect_o(3 downto 0) <= sim_detect_i(3 downto 0); --!! Switching -- Bidir sinals routing gen_datalines: for i in 0 to 7 generate @@ -204,8 +588,8 @@ begin s_mod_data_i(i) <= mod_data_io(i); mod_data_io(i) <= '0' when s_mod_data_o(i) = '0' else 'Z'; - sim_rst_o(i) <= mod_rst_i(i); - sim_clk_o(i) <= mod_clk_i(i); + --sim_rst_o(i) <= mod_rst_i(i); --!! Switching + --sim_clk_o(i) <= mod_clk_i(i); --!! Switching -- Debounce data lines mod_dat_i_debounce : debounce @@ -228,48 +612,190 @@ begin signal_out => sdb_sim_data_i(i) ); end generate gen_datalines; - - -- Route one-way signals from mod to SIM - sim_pwron_o <= (others => '1');--mod_pwron_i; - mod_detect_o(3 downto 0) <= sim_detect_i(3 downto 0); + + sw_mod_data_i(0) <= sdb_mod_data_i(0) when reg_sim_modemnum(0) = 0 + else sdb_mod_data_i(1) when reg_sim_modemnum(0) = 1 + else sdb_mod_data_i(2) when reg_sim_modemnum(0) = 2 + else sdb_mod_data_i(3) when reg_sim_modemnum(0) = 3 + else sdb_mod_data_i(4) when reg_sim_modemnum(0) = 4 + else sdb_mod_data_i(5) when reg_sim_modemnum(0) = 5 + else sdb_mod_data_i(6) when reg_sim_modemnum(0) = 6 + else sdb_mod_data_i(7) when reg_sim_modemnum(0) = 7 + else 'Z'; + sw_mod_data_i(1) <= sdb_mod_data_i(0) when reg_sim_modemnum(1) = 0 + else sdb_mod_data_i(1) when reg_sim_modemnum(1) = 1 + else sdb_mod_data_i(2) when reg_sim_modemnum(1) = 2 + else sdb_mod_data_i(3) when reg_sim_modemnum(1) = 3 + else sdb_mod_data_i(4) when reg_sim_modemnum(1) = 4 + else sdb_mod_data_i(5) when reg_sim_modemnum(1) = 5 + else sdb_mod_data_i(6) when reg_sim_modemnum(1) = 6 + else sdb_mod_data_i(7) when reg_sim_modemnum(1) = 7 + else 'Z'; + sw_mod_data_i(2) <= sdb_mod_data_i(0) when reg_sim_modemnum(2) = 0 + else sdb_mod_data_i(1) when reg_sim_modemnum(2) = 1 + else sdb_mod_data_i(2) when reg_sim_modemnum(2) = 2 + else sdb_mod_data_i(3) when reg_sim_modemnum(2) = 3 + else sdb_mod_data_i(4) when reg_sim_modemnum(2) = 4 + else sdb_mod_data_i(5) when reg_sim_modemnum(2) = 5 + else sdb_mod_data_i(6) when reg_sim_modemnum(2) = 6 + else sdb_mod_data_i(7) when reg_sim_modemnum(2) = 7 + else 'Z'; + sw_mod_data_i(3) <= sdb_mod_data_i(0) when reg_sim_modemnum(3) = 0 + else sdb_mod_data_i(1) when reg_sim_modemnum(3) = 1 + else sdb_mod_data_i(2) when reg_sim_modemnum(3) = 2 + else sdb_mod_data_i(3) when reg_sim_modemnum(3) = 3 + else sdb_mod_data_i(4) when reg_sim_modemnum(3) = 4 + else sdb_mod_data_i(5) when reg_sim_modemnum(3) = 5 + else sdb_mod_data_i(6) when reg_sim_modemnum(3) = 6 + else sdb_mod_data_i(7) when reg_sim_modemnum(3) = 7 + else 'Z'; + sw_mod_data_i(4) <= sdb_mod_data_i(0) when reg_sim_modemnum(4) = 0 + else sdb_mod_data_i(1) when reg_sim_modemnum(4) = 1 + else sdb_mod_data_i(2) when reg_sim_modemnum(4) = 2 + else sdb_mod_data_i(3) when reg_sim_modemnum(4) = 3 + else sdb_mod_data_i(4) when reg_sim_modemnum(4) = 4 + else sdb_mod_data_i(5) when reg_sim_modemnum(4) = 5 + else sdb_mod_data_i(6) when reg_sim_modemnum(4) = 6 + else sdb_mod_data_i(7) when reg_sim_modemnum(4) = 7 + else 'Z'; + sw_mod_data_i(5) <= sdb_mod_data_i(0) when reg_sim_modemnum(5) = 0 + else sdb_mod_data_i(1) when reg_sim_modemnum(5) = 1 + else sdb_mod_data_i(2) when reg_sim_modemnum(5) = 2 + else sdb_mod_data_i(3) when reg_sim_modemnum(5) = 3 + else sdb_mod_data_i(4) when reg_sim_modemnum(5) = 4 + else sdb_mod_data_i(5) when reg_sim_modemnum(5) = 5 + else sdb_mod_data_i(6) when reg_sim_modemnum(5) = 6 + else sdb_mod_data_i(7) when reg_sim_modemnum(5) = 7 + else 'Z'; + sw_mod_data_i(6) <= sdb_mod_data_i(0) when reg_sim_modemnum(6) = 0 + else sdb_mod_data_i(1) when reg_sim_modemnum(6) = 1 + else sdb_mod_data_i(2) when reg_sim_modemnum(6) = 2 + else sdb_mod_data_i(3) when reg_sim_modemnum(6) = 3 + else sdb_mod_data_i(4) when reg_sim_modemnum(6) = 4 + else sdb_mod_data_i(5) when reg_sim_modemnum(6) = 5 + else sdb_mod_data_i(6) when reg_sim_modemnum(6) = 6 + else sdb_mod_data_i(7) when reg_sim_modemnum(6) = 7 + else 'Z'; + sw_mod_data_i(7) <= sdb_mod_data_i(0) when reg_sim_modemnum(7) = 0 + else sdb_mod_data_i(1) when reg_sim_modemnum(7) = 1 + else sdb_mod_data_i(2) when reg_sim_modemnum(7) = 2 + else sdb_mod_data_i(3) when reg_sim_modemnum(7) = 3 + else sdb_mod_data_i(4) when reg_sim_modemnum(7) = 4 + else sdb_mod_data_i(5) when reg_sim_modemnum(7) = 5 + else sdb_mod_data_i(6) when reg_sim_modemnum(7) = 6 + else sdb_mod_data_i(7) when reg_sim_modemnum(7) = 7 + else 'Z'; + + s_mod_data_o(0) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 0 + else sw_mod_data_o(1) when reg_sim_modemnum(1) = 0 + else sw_mod_data_o(2) when reg_sim_modemnum(2) = 0 + else sw_mod_data_o(3) when reg_sim_modemnum(3) = 0 + else sw_mod_data_o(4) when reg_sim_modemnum(4) = 0 + else sw_mod_data_o(5) when reg_sim_modemnum(5) = 0 + else sw_mod_data_o(6) when reg_sim_modemnum(6) = 0 + else sw_mod_data_o(7) when reg_sim_modemnum(7) = 0 + else 'Z'; + s_mod_data_o(1) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 1 + else sw_mod_data_o(1) when reg_sim_modemnum(1) = 1 + else sw_mod_data_o(2) when reg_sim_modemnum(2) = 1 + else sw_mod_data_o(3) when reg_sim_modemnum(3) = 1 + else sw_mod_data_o(4) when reg_sim_modemnum(4) = 1 + else sw_mod_data_o(5) when reg_sim_modemnum(5) = 1 + else sw_mod_data_o(6) when reg_sim_modemnum(6) = 1 + else sw_mod_data_o(7) when reg_sim_modemnum(7) = 1 + else 'Z'; + s_mod_data_o(2) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 2 + else sw_mod_data_o(1) when reg_sim_modemnum(1) = 2 + else sw_mod_data_o(2) when reg_sim_modemnum(2) = 2 + else sw_mod_data_o(3) when reg_sim_modemnum(3) = 2 + else sw_mod_data_o(4) when reg_sim_modemnum(4) = 2 + else sw_mod_data_o(5) when reg_sim_modemnum(5) = 2 + else sw_mod_data_o(6) when reg_sim_modemnum(6) = 2 + else sw_mod_data_o(7) when reg_sim_modemnum(7) = 2 + else 'Z'; + s_mod_data_o(3) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 3 + else sw_mod_data_o(1) when reg_sim_modemnum(1) = 3 + else sw_mod_data_o(2) when reg_sim_modemnum(2) = 3 + else sw_mod_data_o(3) when reg_sim_modemnum(3) = 3 + else sw_mod_data_o(4) when reg_sim_modemnum(4) = 3 + else sw_mod_data_o(5) when reg_sim_modemnum(5) = 3 + else sw_mod_data_o(6) when reg_sim_modemnum(6) = 3 + else sw_mod_data_o(7) when reg_sim_modemnum(7) = 3 + else 'Z'; + s_mod_data_o(4) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 4 + else sw_mod_data_o(1) when reg_sim_modemnum(1) = 4 + else sw_mod_data_o(2) when reg_sim_modemnum(2) = 4 + else sw_mod_data_o(3) when reg_sim_modemnum(3) = 4 + else sw_mod_data_o(4) when reg_sim_modemnum(4) = 4 + else sw_mod_data_o(5) when reg_sim_modemnum(5) = 4 + else sw_mod_data_o(6) when reg_sim_modemnum(6) = 4 + else sw_mod_data_o(7) when reg_sim_modemnum(7) = 4 + else 'Z'; + s_mod_data_o(5) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 5 + else sw_mod_data_o(1) when reg_sim_modemnum(1) = 5 + else sw_mod_data_o(2) when reg_sim_modemnum(2) = 5 + else sw_mod_data_o(3) when reg_sim_modemnum(3) = 5 + else sw_mod_data_o(4) when reg_sim_modemnum(4) = 5 + else sw_mod_data_o(5) when reg_sim_modemnum(5) = 5 + else sw_mod_data_o(6) when reg_sim_modemnum(6) = 5 + else sw_mod_data_o(7) when reg_sim_modemnum(7) = 5 + else 'Z'; + s_mod_data_o(6) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 6 + else sw_mod_data_o(1) when reg_sim_modemnum(1) = 6 + else sw_mod_data_o(2) when reg_sim_modemnum(2) = 6 + else sw_mod_data_o(3) when reg_sim_modemnum(3) = 6 + else sw_mod_data_o(4) when reg_sim_modemnum(4) = 6 + else sw_mod_data_o(5) when reg_sim_modemnum(5) = 6 + else sw_mod_data_o(6) when reg_sim_modemnum(6) = 6 + else sw_mod_data_o(7) when reg_sim_modemnum(7) = 6 + else 'Z'; + s_mod_data_o(7) <= sw_mod_data_o(0) when reg_sim_modemnum(0) = 7 + else sw_mod_data_o(1) when reg_sim_modemnum(1) = 7 + else sw_mod_data_o(2) when reg_sim_modemnum(2) = 7 + else sw_mod_data_o(3) when reg_sim_modemnum(3) = 7 + else sw_mod_data_o(4) when reg_sim_modemnum(4) = 7 + else sw_mod_data_o(5) when reg_sim_modemnum(5) = 7 + else sw_mod_data_o(6) when reg_sim_modemnum(6) = 7 + else sw_mod_data_o(7) when reg_sim_modemnum(7) = 7 + else 'Z'; ------------------ -- SIM repeater -- ------------------ - sim_rptr_proc: process(clk25_i, s_rstn_i, sdb_sim_data_i, sdb_sim_data_prev, sdb_mod_data_i, sdb_mod_data_prev) is + sim_rptr_proc: process(clk25_i, s_rstn_i, sdb_sim_data_i, sdb_sim_data_prev, sw_mod_data_i, sw_mod_data_prev, reg_sim_change_irq) is begin if s_rstn_i = '0' then - s_sim_data_o <= (others => '1'); - s_mod_data_o <= (others => '1'); + s_sim_data_o <= (others => '1'); + sw_mod_data_o <= (others => '1'); sdb_sim_data_prev <= sdb_sim_data_i; - sdb_mod_data_prev <= sdb_mod_data_i; + sw_mod_data_prev <= sw_mod_data_i; state <= (others => idle); elsif (rising_edge(clk25_i)) then sdb_sim_data_prev <= sdb_sim_data_i; - sdb_mod_data_prev <= sdb_mod_data_i; + sw_mod_data_prev <= sw_mod_data_i; for i in 0 to 7 loop case state(i) is when idle => - if (sdb_mod_data_prev(i) = '1' and sdb_mod_data_i(i) = '0') then + if (sw_mod_data_prev(i) = '1' and sw_mod_data_i(i) = '0') then s_sim_data_o(i) <= '0'; state(i) <= mod_to_sim; elsif (sdb_sim_data_prev(i) = '1' and sdb_sim_data_i(i) = '0') then - s_mod_data_o(i) <= '0'; - state(i) <= sim_to_mod; + sw_mod_data_o(i) <= '0'; + state(i) <= sim_to_mod; end if; when mod_to_sim => - if (sdb_mod_data_prev(i) = '0' and sdb_mod_data_i(i) = '1') then + if ((sw_mod_data_prev(i) = '0' and sw_mod_data_i(i) = '1') or reg_sim_change_irq(i) = '1') then s_sim_data_o(i) <= '1'; state(i) <= idle; end if; when sim_to_mod => - if (sdb_sim_data_prev(i) = '0' and sdb_sim_data_i(i) = '1') then - s_mod_data_o(i) <= '1'; - state(i) <= idle; + if ((sdb_sim_data_prev(i) = '0' and sdb_sim_data_i(i) = '1') or reg_sim_change_irq(i) = '1') then + sw_mod_data_o(i) <= '1'; + state(i) <= idle; end if; end case; end loop;