commit b06870f628188f8a92a7435f3d698877fd0d5b2d Author: matt Date: Fri Feb 7 17:18:28 2020 +0700 First commit diff --git a/debounce.vhd b/debounce.vhd new file mode 100644 index 0000000..68efcf7 --- /dev/null +++ b/debounce.vhd @@ -0,0 +1,63 @@ +------------------------------------------------------------ +-- File : debounce.vhd +------------------------------------------------------------ +-- Author : Peter Samarin +------------------------------------------------------------ +-- Copyright (c) 2016 Peter Samarin +------------------------------------------------------------ +-- Description: debouncing circuit that forwards only +-- signals that have been stable for the whole duration of +-- the counter +------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +------------------------------------------------------------ +entity debounce is + generic ( + WAIT_CYCLES : integer := 5); + port ( + signal_in : in std_logic; + signal_out : out std_logic; + clk : in std_logic); +end entity debounce; +------------------------------------------------------------ +architecture arch of debounce is + type state_t is (idle, check_input_stable); + signal state_reg : state_t := idle; + signal out_reg : std_logic := signal_in; + signal signal_in_reg : std_logic; + signal counter : integer range 0 to WAIT_CYCLES-1 := 0; +begin + + process (clk) is + begin + if rising_edge(clk) then + case state_reg is + when idle => + if out_reg /= signal_in then + signal_in_reg <= signal_in; + state_reg <= check_input_stable; + counter <= WAIT_CYCLES-1; + end if; + + when check_input_stable => + if counter = 0 then + if signal_in = signal_in_reg then + out_reg <= signal_in; + end if; + state_reg <= idle; + else + if signal_in /= signal_in_reg then + state_reg <= idle; + end if; + counter <= counter - 1; + end if; + end case; + end if; + end process; + + -- output + signal_out <= to_UX01(out_reg); + +end architecture arch; diff --git a/sim_switcher_top.vhd b/sim_switcher_top.vhd new file mode 100644 index 0000000..a5347fc --- /dev/null +++ b/sim_switcher_top.vhd @@ -0,0 +1,367 @@ +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) := "1010110" -- Address of I2C slave, dafault 0x56 + ); + 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; + + -- 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 signals + vsim_data_io : inout std_logic_vector(3 downto 0); + + -- Modem signals + mod_detect_o : out std_logic_vector(3 downto 0); + mod_wake_host_i : in std_logic_vector(3 downto 0); + mod_pwron_i : in std_logic_vector(7 downto 0); + mod_rst_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) + ); +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 := 4; -- 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 DEBOUNCING_WAIT_CYCLES : natural := 3; -- Number of debouncing wait cycles + + 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'; + + -- 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); + + -- 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); + + 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); +begin + + ---------------------------------- + -- 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 card emulation test --- +------------------------------- + + -- 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; + + -- Route one-way signals from mod to SIM + sim_pwron_o <= (others => '1');--mod_pwron_i; + sim_rst_o <= mod_rst_i; + sim_clk_o <= mod_clk_i; + mod_detect_o(3 downto 0) <= sim_detect_i(3 downto 0); + + ------------------ + -- 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 + begin + if s_rstn_i = '0' then + s_sim_data_o <= (others => '1'); + s_mod_data_o <= (others => '1'); + sdb_sim_data_prev <= sdb_sim_data_i; + sdb_mod_data_prev <= sdb_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; + + 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 + 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; + end if; + + when mod_to_sim => + if (sdb_mod_data_prev(i) = '0' and sdb_mod_data_i(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; + end if; + end case; + end loop; + + end if; + end process; + + +--------------------------------- +----- SIM card emulation test --- +--------------------------------- +-- +-- -- 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; +-- +-- -- Route one-way signals from mod to SIM +-- sim_pwron_o <= (others => '1');--mod_pwron_i; +-- sim_rst_o <= mod_rst_i; +-- sim_clk_o <= mod_clk_i; +-- mod_detect_o(3 downto 0) <= sim_detect_i(3 downto 0); +-- +-- ------------------ +-- -- SIM repeater -- +-- ------------------ +-- sims: for num in 0 to 7 generate +-- sim_rptr_proc: process(clk25_i) is +-- begin +-- if s_rstn_i = '0' then +-- s_sim_data_o(num) <= '1'; +-- s_mod_data_o(num) <= '1'; +-- sdb_sim_data_prev(num) <= sdb_sim_data_i(num); +-- sdb_mod_data_prev(num) <= sdb_mod_data_i(num); +-- state(num) <= idle; +-- +-- elsif (rising_edge(clk25_i)) then +-- sdb_sim_data_prev(num) <= sdb_sim_data_i(num); +-- sdb_mod_data_prev(num) <= sdb_mod_data_i(num); +-- +-- case state(num) is +-- when idle => +-- if (sdb_mod_data_prev(num) = '1' and sdb_mod_data_i(num) = '0') then +-- s_sim_data_o(num) <= '0'; +-- state(num) <= mod_to_sim; +-- elsif (sdb_sim_data_prev(num) = '1' and sdb_sim_data_i(num) = '0') then +-- s_mod_data_o(num) <= '0'; +-- state(num) <= sim_to_mod; +-- end if; +-- +-- when mod_to_sim => +-- if (sdb_mod_data_prev(num) = '0' and sdb_mod_data_i(num) = '1') then +-- s_sim_data_o(num) <= '1'; +-- state(num) <= idle; +-- end if; +-- +-- when sim_to_mod => +-- if (sdb_sim_data_prev(num) = '0' and sdb_sim_data_i(num) = '1') then +-- s_mod_data_o(num) <= '1'; +-- state(num) <= idle; +-- end if; +-- +-- end case; +-- +-- end if; +-- end process; +-- end generate sims; + + +end architecture rtl;