mmv5_FirmwareMS/sim_switcher_top.vhd

769 lines
27 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.sim_switcher_pkg.all;
entity sim_switcher_top is
generic (
-- General parameters
SYSFREQ : integer := 25_000_000; -- System clock frequency
INSIM : std_logic := '0'; -- In Simulation flag: 0 - real work (default), 1 - simulation
-- I2C parameters
I2C_SLAVE_ADDR : std_logic_vector(6 downto 0) := "1010111" -- Address of I2C slave, dafault 0x57
);
port (
-- Clock and reset
clk25_i : in std_logic;
clk125_i : in std_logic;
rstn_i : in std_logic;
-- User LED
led_o : out std_logic;
-- Power Good signals
pg_10v_i : in std_logic;
pg_25v_i : in std_logic;
pg_33v_i : in std_logic;
-- CPU reset signals
cpu_rst_reqn_i : in std_logic;
cpu_trstn_o : out std_logic;
cpu_jtag_rstn_o : out std_logic;
-- FPGA interrupt to CPU
fpga_int_o : out std_logic; -- FPGA_INTn_V18, PIN_F12, active high
-- I2C slave interface
i2c_scl_io : inout std_logic;
i2c_sda_io : inout std_logic;
-- SIM board CONF bits
sb_conf_i : in std_logic_vector(2 downto 0);
-- SIM signals
sim_detect_i : in std_logic_vector(7 downto 0);
sim_pwron_o : out std_logic_vector(7 downto 0);
sim_rst_o : out std_logic_vector(7 downto 0);
sim_clk_o : out std_logic_vector(7 downto 0);
sim_data_io : inout std_logic_vector(7 downto 0);
-- Virtual SIM data IO signals
vsim_data_io : inout std_logic_vector(3 downto 0);
-- Modem signals for SIM cards
mod_detect_o : out std_logic_vector(3 downto 0);
mod_wake_host_i : in std_logic_vector(3 downto 0);
mod_simpwr_i : in std_logic_vector(7 downto 0);
mod_simrst_i : in std_logic_vector(7 downto 0);
mod_clk_i : in std_logic_vector(7 downto 0);
mod_data_io : inout std_logic_vector(7 downto 0);
-- Modem LEDs
mod_led_o : out std_logic_vector(7 downto 0);
-- Modem manage signals
mod_pwr_o : out std_logic_vector(7 downto 0); -- Modem power on signals
mod_rstn_o : out std_logic_vector(7 downto 5); -- PCIe reset signal
mod_pciehstwake_i : in std_logic_vector(7 downto 5); -- PCIe wake host signal
-- Expansion card GPIO signals
exp_card_io : inout std_logic_vector(5 downto 0);
-- FAN power on signals
fan_o : out std_logic_vector(1 downto 0);
-- I2C slave interface FPGA-MCU (BitBang by MCU)
i2c_mcuscl_io : inout std_logic;
i2c_mcusda_io : inout std_logic;
-- POE IN add-in card
poe_in_vpres : in std_logic; -- Voltage present at card power output
poe_in_enn : out std_logic; -- PD enable signal (active low)
poe_in_t2p : in std_logic_vector(1 downto 0); -- PSE connected signal
-- POE OUT add-in card signals
pse_rst : out std_logic; -- PSE reset
pse_vpwr_enn : out std_logic; -- PSE enable (active low)
pse_i2c_scl_io : inout std_logic; -- PSE I2C SCL signal
pse_i2c_sda_io : inout std_logic; -- PSE I2C SDA signal
pse_intn : in std_logic; -- PSE interrupt (active low)
pse_vpwr_pg : in std_logic -- PSE power good signal
);
end entity sim_switcher_top;
architecture rtl of sim_switcher_top is
component debounce is
generic (
WAIT_CYCLES : integer := 5
);
port (
signal_in : in std_logic;
signal_out : out std_logic;
clk : in std_logic
);
end component;
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
constant SB_CONF_UPDATE_INTERVAL : natural := 25_000_000; -- 25_000_000 = 1sec
constant DEBOUNCING_WAIT_CYCLES : natural := 3; -- Number of debouncing wait cycles
constant I2C_MAX_WAIT : natural := 2_500_000; -- 25_000_000 = 1sec
signal s_clk_i : std_logic; -- clock buffer
signal s_rstn_i : std_logic; -- reset signal
signal s_rst_i : std_logic; -- reset signal
-- Signals to detect CPU reset request falling edge
signal s_cpu_rst_reqn : std_logic;
signal s_cpu_rst_reqn_prev : std_logic;
signal s_cpu_trst_dir_o : std_logic := '1';
signal s_rst_cntr_start : std_logic;
-- CPU delay signal
signal s_cpu_delay : std_logic := '1';
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_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(15 downto 0);
-- Modem data signals
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 board CONF bits register
signal reg_sim_board_conf : std_logic_vector(2 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');
-- Modem LED register
signal reg_mod_led : std_logic_vector(7 downto 0);
-- Modem power register
signal reg_mod_pwr : std_logic_vector(7 downto 0);
-- PCI-e signals
signal reg_pcie_rstn : std_logic_vector(7 downto 5);
signal reg_pcie_waken : std_logic_vector(7 downto 5);
-- M.2 modem wake host register
signal reg_mod_hstwake : std_logic_vector(3 downto 0);
-- FAN control register
signal reg_fan_ctl : std_logic_vector(1 downto 0);
-- PSE registers
signal reg_pse_status : std_logic_vector(1 downto 0);
signal reg_pse_ctl : std_logic_vector(1 downto 0);
-- POE PD registers
signal reg_poepd_status : std_logic_vector(2 downto 0);
signal reg_poepd_ctl : std_logic;
-- Expansion card IO tri-state control
signal reg_expio_line : std_logic_vector(5 downto 0);
signal reg_expio_output : std_logic_vector(5 downto 0);
signal s_exp_card_i : std_logic_vector(5 downto 0);
signal s_dbexp_card_i : std_logic_vector(5 downto 0);
-- State machine signals and types
type state_t is (idle, mod_to_sim, sim_to_mod);
type arr_state_t is array (natural range <>) of state_t;
signal state: arr_state_t(0 to 7);
-- SIM-MODEM switching register
signal reg_sim_modemnum: arr_modnum_t(0 to 7);
begin
-- Interrupt generation
fpga_int_o <= not pse_intn;
-- Currently unused SIM data lines for VirtualSIM
s_sim_data_i(15 downto 8) <= (others => '1');
sdb_sim_data_i(15 downto 8) <= (others => '1');
-- Fill SIM detect register
reg_sim_det(7 downto 0) <= sim_detect_i;
reg_sim_det(15 downto 8) <= (others => '0');
-- Drive modem LEDs and Power
mod_led_o <= reg_mod_led;
mod_pwr_o <= reg_mod_pwr;
-- Drive PCI-e RSTn and WAKEn signals
mod_rstn_o <= reg_pcie_rstn;
reg_pcie_waken <= mod_pciehstwake_i;
-- Drive M.2 wake host signals
reg_mod_hstwake <= mod_wake_host_i;
-- Drive FAN control signals
fan_o <= reg_fan_ctl;
-- PSE init
pse_rst <= reg_pse_ctl(0);
pse_vpwr_enn <= reg_pse_ctl(1);
reg_pse_status <= pse_intn&pse_vpwr_pg;
-- Connect PSE I2C bus to main I2C bus
pse_scl_rptr: odio_repeater
generic map (
WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES
)
port map (
clk => clk25_i,
rstn => s_rstn_i,
signal_n1 => i2c_scl_io,
signal_n2 => pse_i2c_scl_io
);
pse_sda_rptr: odio_repeater
generic map (
WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES
)
port map (
clk => clk25_i,
rstn => s_rstn_i,
signal_n1 => i2c_sda_io,
signal_n2 => pse_i2c_sda_io
);
-- POE PD init
reg_poepd_status <= poe_in_vpres&poe_in_t2p;
poe_in_enn <= reg_poepd_ctl;
-- Expansion card IO control
gen_expio_dbnc: for i in 0 to 5 generate
s_exp_card_i(i) <= exp_card_io(i);
exp_card_io(i) <= '0' when reg_expio_output(i) = '0' else 'Z';
reg_expio_line(i) <= s_dbexp_card_i(i);
expio_debounce : debounce
generic map (
WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES
)
port map (
clk => clk25_i,
signal_in => s_exp_card_i(i),
signal_out => s_dbexp_card_i(i)
);
end generate gen_expio_dbnc;
---------------------------------------------------------
----------------------------------
-- Power-On FPGA IP-cores reset --
----------------------------------
pon_rst_proc: process(clk25_i) is
variable wait_cnt : natural := 0;
begin
if (rising_edge(clk25_i)) then
if (wait_cnt > PON_RST_DURATION) then
s_rstn_i <= '1';
else
wait_cnt := wait_cnt + 1;
s_rstn_i <= '0';
end if;
end if;
end process;
s_rst_i <= not s_rstn_i;
-----------------------
-- Startup LED blink --
-----------------------
led_o <= s_led_o;
led_blink_proc: process(clk25_i) is
variable wait_cnt : natural := 0;
variable flash_cnt : natural := 0;
begin
if (rising_edge(clk25_i)) then
if (wait_cnt > SYSFREQ/4) then
if (flash_cnt <= (FLASHES-1)*2) then
wait_cnt := 0;
s_led_o <= not s_led_o;
flash_cnt := flash_cnt + 1;
end if;
end if;
if (flash_cnt <= FLASHES*2) then
wait_cnt := wait_cnt + 1;
end if;
end if;
end process;
------------------------------
-- Power-On CPU start delay --
------------------------------
pon_cpu_start_proc: process(clk25_i) is
variable wait_cnt : natural := 0;
begin
if (rising_edge(clk25_i)) then
if (wait_cnt > PON_CPU_DELAY_DURATION) then
s_cpu_delay <= '1';
else
wait_cnt := wait_cnt + 1;
s_cpu_delay <= '0';
end if;
end if;
end process;
-------------------------------------
-- Reset generator per CPU request --
-------------------------------------
s_cpu_rst_reqn <= cpu_rst_reqn_i;
cpu_trstn_o <= '0' when s_cpu_trst_dir_o = '0' or s_cpu_delay = '0'
else 'Z'; --pg_10v_i and pg_25v_i and pg_33v_i;
--cpu_trstn_o <= pg_10v_i and pg_25v_i and pg_33v_i;
cpu_jtag_rstn_o <= '0' when s_cpu_trst_dir_o = '0' or s_cpu_delay = '0'
else 'Z';
cpu_rst_gen_proc: process(clk25_i, s_rstn_i, cpu_rst_reqn_i) is
variable wait_cnt : natural := CPU_RST_DURATION;
begin
if s_rstn_i = '0' then
wait_cnt := 0;
s_rst_cntr_start <= '0';
s_cpu_rst_reqn_prev <= cpu_rst_reqn_i;
elsif rising_edge(clk25_i) then
s_cpu_rst_reqn_prev <= s_cpu_rst_reqn; -- Capture value of RESET_REQn for further edge detection
-- Check for start
if s_rst_cntr_start = '1' then
if (wait_cnt >= CPU_RST_DURATION) then
s_cpu_trst_dir_o <= '1';
s_rst_cntr_start <= '0';
else
wait_cnt := wait_cnt + 1;
s_cpu_trst_dir_o <= '0';
end if;
else
if (s_cpu_rst_reqn_prev = '1' and s_cpu_rst_reqn = '0') then
wait_cnt := 0;
s_rst_cntr_start <= '1';
end if;
end if;
end if;
end process;
---------------------------
-- SIM board CONF update --
---------------------------
sb_conf_upd_proc: process(clk25_i, s_rstn_i, sb_conf_i) is
variable wait_cnt : natural := 0;
begin
if s_rstn_i = '0' then
wait_cnt := 0;
reg_sim_board_conf <= sb_conf_i;
elsif (rising_edge(clk25_i)) then
if (wait_cnt > SB_CONF_UPDATE_INTERVAL) then
wait_cnt := 0;
reg_sim_board_conf <= sb_conf_i;
else
wait_cnt := wait_cnt + 1;
end if;
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 attach reset assigment: default is 1-to-1 SIM to MODEM connection
reg_sim_modemnum <= (
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7
);
-- SIM change IRQ register reset
reg_sim_change_irq <= (others => '0');
-- Turn on all SIM cards
reg_sim_pwr(7 downto 0) <= (others => '1'); -- Real SIMs power is on
reg_sim_pwr(15 downto 8) <= (others => '0'); -- Virtual SIMs power is "off"
reg_mod_led <= (others => '0'); -- Modem LEDs are not lit
reg_mod_pwr <= (others => '0'); -- Modem power is off
reg_pcie_rstn <= (others => '1'); -- PCIe RSTn is not active
reg_fan_ctl <= (others => '0'); -- FANs are off
reg_pse_ctl <= (others => '0'); -- POE out is on
reg_poepd_ctl <= '0'; -- POE PD enabled
reg_expio_output <= (others => '1'); -- All Expansion card IOs in HighZ at start
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 MBCr1, v1.1=0x19 MBSr1, v2.0=0x28 MBSr2)
i2c_data_to_master <= x"28";
i2c_slv_state <= wait_while_sent;
when x"12" => -- Read SIM board model regiser
i2c_data_to_master <= "00000" & reg_sim_board_conf;
i2c_slv_state <= wait_while_sent;
when x"13" => -- Read FAN control regiser
i2c_data_to_master <= "000000" & reg_fan_ctl;
i2c_slv_state <= wait_while_sent;
when x"14" => -- Read POE OUT status register
i2c_data_to_master <= "000000" & reg_pse_status;
i2c_slv_state <= wait_while_sent;
when x"15" => -- Read POE OUT control register
i2c_data_to_master <= "000000" & reg_pse_ctl;
i2c_slv_state <= wait_while_sent;
when x"16" => -- Read POE IN status register
i2c_data_to_master <= "00000" & reg_poepd_status;
i2c_slv_state <= wait_while_sent;
when x"17" => -- Read POE IN control register
i2c_data_to_master <= "0000000" & reg_poepd_ctl;
i2c_slv_state <= wait_while_sent;
when x"18" => -- Read Expansion card IO lines
i2c_data_to_master <= "00" & reg_expio_line;
i2c_slv_state <= wait_while_sent;
when x"19" => -- Read Expansion card output register
i2c_data_to_master <= "00" & reg_expio_output;
i2c_slv_state <= wait_while_sent;
when x"05" => -- Read M.2 modem wake host register
i2c_data_to_master <= "0000"&reg_mod_hstwake(3 downto 0);
i2c_slv_state <= wait_while_sent;
when x"06" => -- Read modem LED register
i2c_data_to_master <= reg_mod_led(7 downto 0);
i2c_slv_state <= wait_while_sent;
when x"07" => -- Read modem power register
i2c_data_to_master <= reg_mod_pwr(7 downto 0);
i2c_slv_state <= wait_while_sent;
when x"08" => -- Read PCIe RSTn register
i2c_data_to_master <= reg_pcie_rstn(7 downto 5)&"00000";
i2c_slv_state <= wait_while_sent;
when x"09" => -- Read PCIe WAKEn register
i2c_data_to_master <= reg_pcie_waken(7 downto 5)&"00000";
i2c_slv_state <= wait_while_sent;
when x"0A" => -- Read SIM detect register (LSB)
i2c_data_to_master <= reg_sim_det(7 downto 0);
i2c_slv_state <= wait_while_sent;
-- when x"0B" => -- Read SIM detect register (MSB)
-- i2c_data_to_master <= reg_sim_det(15 downto 8);
-- i2c_slv_state <= wait_while_sent;
when x"0C" => -- Read SIM power register (LSB)
i2c_data_to_master <= reg_sim_pwr(7 downto 0);
i2c_slv_state <= wait_while_sent;
-- when x"0D" => -- Read SIM power register (MSB)
-- i2c_data_to_master <= reg_sim_pwr(15 downto 8);
-- i2c_slv_state <= wait_while_sent;
when x"20" => -- Read SIM1 modem register
i2c_data_to_master <= "0000" & std_logic_vector(to_unsigned(reg_sim_modemnum(0),4));
i2c_slv_state <= wait_while_sent;
when x"21" => -- Read SIM2 modem register
i2c_data_to_master <= "0000" & std_logic_vector(to_unsigned(reg_sim_modemnum(1),4));
i2c_slv_state <= wait_while_sent;
when x"22" => -- Read SIM3 modem register
i2c_data_to_master <= "0000" & std_logic_vector(to_unsigned(reg_sim_modemnum(2),4));
i2c_slv_state <= wait_while_sent;
when x"23" => -- Read SIM4 modem register
i2c_data_to_master <= "0000" & std_logic_vector(to_unsigned(reg_sim_modemnum(3),4));
i2c_slv_state <= wait_while_sent;
when x"24" => -- Read SIM5 modem register
i2c_data_to_master <= "0000" & std_logic_vector(to_unsigned(reg_sim_modemnum(4),4));
i2c_slv_state <= wait_while_sent;
when x"25" => -- Read SIM6 modem register
i2c_data_to_master <= "0000" & std_logic_vector(to_unsigned(reg_sim_modemnum(5),4));
i2c_slv_state <= wait_while_sent;
when x"26" => -- Read SIM7 modem register
i2c_data_to_master <= "0000" & std_logic_vector(to_unsigned(reg_sim_modemnum(6),4));
i2c_slv_state <= wait_while_sent;
when x"27" => -- Read SIM8 modem register
i2c_data_to_master <= "0000" & std_logic_vector(to_unsigned(reg_sim_modemnum(7),4));
i2c_slv_state <= wait_while_sent;
when x"86" => -- Write modem LED register
i2c_slv_state <= receive_byte;
when x"87" => -- Write modem power register
i2c_slv_state <= receive_byte;
when x"88" => -- Write PCIe RSTn register
i2c_slv_state <= receive_byte;
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"93" => -- Write FAN control regiser
i2c_slv_state <= receive_byte;
when x"95" => -- Write POE OUT control register
i2c_slv_state <= receive_byte;
when x"97" => -- Write POE IN control register
i2c_slv_state <= receive_byte;
when x"99" => -- Write Expansion card output register
i2c_slv_state <= receive_byte;
when x"A0" => -- Write SIM1 modem register
i2c_slv_state <= receive_byte;
when x"A1" => -- Write SIM2 modem register
i2c_slv_state <= receive_byte;
when x"A2" => -- Write SIM3 modem register
i2c_slv_state <= receive_byte;
when x"A3" => -- Write SIM4 modem register
i2c_slv_state <= receive_byte;
when x"A4" => -- Write SIM5 modem register
i2c_slv_state <= receive_byte;
when x"A5" => -- Write SIM6 modem register
i2c_slv_state <= receive_byte;
when x"A6" => -- Write SIM7 modem register
i2c_slv_state <= receive_byte;
when x"A7" => -- Write SIM8 modem 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"86" => -- Write modem LED register
reg_mod_led(7 downto 0) <= i2c_data_from_master(7 downto 0);
when x"87" => -- Write modem power register
reg_mod_pwr(7 downto 0) <= i2c_data_from_master(7 downto 0);
when x"88" => -- Write PCIe RSTn register
reg_pcie_rstn(7 downto 5) <= i2c_data_from_master(7 downto 5);
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"93" => -- Write FAN control regiser
reg_fan_ctl(1 downto 0) <= i2c_data_from_master(1 downto 0);
when x"95" => -- Write POE OUT control register
reg_pse_ctl(1 downto 0) <= i2c_data_from_master(1 downto 0);
when x"97" => -- Write POE IN control register
reg_poepd_ctl <= i2c_data_from_master(0);
when x"99" => -- Write Expansion card output register
reg_expio_output <= i2c_data_from_master(5 downto 0);
when x"A0" => -- Write SIM1 modem register
reg_sim_modemnum(0) <= to_integer(unsigned(i2c_data_from_master(3 downto 0)));
when x"A1" => -- Write SIM2 modem register
reg_sim_modemnum(1) <= to_integer(unsigned(i2c_data_from_master(3 downto 0)));
when x"A2" => -- Write SIM3 modem register
reg_sim_modemnum(2) <= to_integer(unsigned(i2c_data_from_master(3 downto 0)));
when x"A3" => -- Write SIM4 modem register
reg_sim_modemnum(3) <= to_integer(unsigned(i2c_data_from_master(3 downto 0)));
when x"A4" => -- Write SIM5 modem register
reg_sim_modemnum(4) <= to_integer(unsigned(i2c_data_from_master(3 downto 0)));
when x"A5" => -- Write SIM6 modem register
reg_sim_modemnum(5) <= to_integer(unsigned(i2c_data_from_master(3 downto 0)));
when x"A6" => -- Write SIM7 modem register
reg_sim_modemnum(6) <= to_integer(unsigned(i2c_data_from_master(3 downto 0)));
when x"A7" => -- Write SIM8 modem register
reg_sim_modemnum(7) <= to_integer(unsigned(i2c_data_from_master(3 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 switching ---
--------------------------
-- Power on SIM card according to the reg_sim_pwr register
sim_pwron_o <= reg_sim_pwr(7 downto 0);
-- Bidir sinals routing
gen_datalines: for i in 0 to 7 generate
s_sim_data_i(i) <= sim_data_io(i);
sim_data_io(i) <= '0' when s_sim_data_o(i) = '0' else 'Z';
s_mod_data_i(i) <= mod_data_io(i);
mod_data_io(i) <= '0' when s_mod_data_o(i) = '0' else 'Z';
-- Debounce data lines
mod_dat_i_debounce : debounce
generic map (
WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES
)
port map (
clk => clk25_i,
signal_in => s_mod_data_i(i),
signal_out => sdb_mod_data_i(i)
);
sim_dat_i_debounce : debounce
generic map (
WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES
)
port map (
clk => clk25_i,
signal_in => s_sim_data_i(i),
signal_out => sdb_sim_data_i(i)
);
end generate gen_datalines;
-- Actual SIM/MODEM signal muxing
sim_muxing : sim_mux
port map (
reg_sim_modemnum => reg_sim_modemnum,
sim_rst_o => sim_rst_o,
mod_simrst_i => mod_simrst_i,
sim_clk_o => sim_clk_o,
mod_clk_i => mod_clk_i,
mod_detect_o => mod_detect_o,
sim_detect_i => sim_detect_i,
sw_mod_data_i => sw_mod_data_i, -- For switched tri-state buffer there are input and output part of
mod_data_i => sdb_mod_data_i, -- the lines which are switched transparently, thus ports
mod_data_o => s_mod_data_o, -- sw_mod_data_i is actual output and sw_mod_data_o is
sw_mod_data_o => sw_mod_data_o -- actual input. Please, don't be confused by conflicting name.
);
------------------
-- SIM repeater --
------------------
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');
sw_mod_data_o <= (others => '1');
sdb_sim_data_prev <= sdb_sim_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;
sw_mod_data_prev <= sw_mod_data_i;
for i in 0 to 7 loop
case state(i) is
when idle =>
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
sw_mod_data_o(i) <= '0';
state(i) <= sim_to_mod;
end if;
when mod_to_sim =>
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') or reg_sim_change_irq(i) = '1') then
sw_mod_data_o(i) <= '1';
state(i) <= idle;
end if;
end case;
end loop;
end if;
end process;
end architecture rtl;