Fixed PSE I2C for read only, not tested
This commit is contained in:
parent
611076ca6d
commit
b1782ac316
|
|
@ -22,6 +22,27 @@ package sim_switcher_pkg is
|
||||||
);
|
);
|
||||||
end component sim_mux;
|
end component sim_mux;
|
||||||
|
|
||||||
|
component i2c_master IS
|
||||||
|
generic (
|
||||||
|
input_clk : integer := 50_000_000; --input clock speed from user logic in Hz
|
||||||
|
bus_clk : integer := 400_000 --speed the i2c bus (scl) will run at in Hz
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
clk : in std_logic; --system clock
|
||||||
|
reset_n : in std_logic; --active low reset
|
||||||
|
ena : in std_logic; --latch in command
|
||||||
|
addr : in std_logic_vector(6 downto 0); --address of target slave
|
||||||
|
rw : in std_logic; --'0' is write, '1' is read
|
||||||
|
data_wr : in std_logic_vector(7 downto 0); --data to write to slave
|
||||||
|
busy : out std_logic; --indicates transaction in progress
|
||||||
|
data_rd : out std_logic_vector(7 downto 0); --data read from slave
|
||||||
|
ack_error : buffer std_logic; --flag if improper acknowledge from slave
|
||||||
|
sda : inout std_logic; --serial data output of i2c bus
|
||||||
|
scl : inout std_logic; --serial clock output of i2c bus
|
||||||
|
scl_invert: in std_logic --true if need to invert output SCL signal
|
||||||
|
);
|
||||||
|
end component i2c_master;
|
||||||
|
|
||||||
component i2c_slave is
|
component i2c_slave is
|
||||||
generic (
|
generic (
|
||||||
SLAVE_ADDR : std_logic_vector(6 downto 0)
|
SLAVE_ADDR : std_logic_vector(6 downto 0)
|
||||||
|
|
@ -39,6 +60,20 @@ package sim_switcher_pkg is
|
||||||
);
|
);
|
||||||
end component i2c_slave;
|
end component i2c_slave;
|
||||||
|
|
||||||
|
component i2c_repeater is
|
||||||
|
generic (
|
||||||
|
WAIT_CYCLES : integer := 3
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
clk : in std_logic;
|
||||||
|
rstn : in std_logic;
|
||||||
|
pr_scl : inout std_logic;
|
||||||
|
pr_sda : inout std_logic;
|
||||||
|
sec_scl : inout std_logic;
|
||||||
|
sec_sda : inout std_logic
|
||||||
|
);
|
||||||
|
end component i2c_repeater;
|
||||||
|
|
||||||
component odio_repeater is
|
component odio_repeater is
|
||||||
generic (
|
generic (
|
||||||
WAIT_CYCLES : integer := 3
|
WAIT_CYCLES : integer := 3
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,10 @@ architecture rtl of sim_switcher_top is
|
||||||
|
|
||||||
constant I2C_MAX_WAIT : natural := 2_500_000; -- 25_000_000 = 1sec
|
constant I2C_MAX_WAIT : natural := 2_500_000; -- 25_000_000 = 1sec
|
||||||
|
|
||||||
|
constant PSE_I2C_ADDR : std_logic_vector(6 downto 0) := "0100000"; -- 0x20
|
||||||
|
constant PSE_REG_NUM : natural := 8;
|
||||||
|
constant PSE_POLL_INTERVAL : natural := 25_000_000; -- 25_000_000 = 1sec
|
||||||
|
|
||||||
signal s_clk_i : std_logic; -- clock buffer
|
signal s_clk_i : std_logic; -- clock buffer
|
||||||
signal s_rstn_i : std_logic; -- reset signal
|
signal s_rstn_i : std_logic; -- reset signal
|
||||||
signal s_rst_i : std_logic; -- reset signal
|
signal s_rst_i : std_logic; -- reset signal
|
||||||
|
|
@ -217,6 +221,25 @@ architecture rtl of sim_switcher_top is
|
||||||
-- SIM-MODEM switching register
|
-- SIM-MODEM switching register
|
||||||
signal reg_sim_modemnum: arr_modnum_t(0 to 7);
|
signal reg_sim_modemnum: arr_modnum_t(0 to 7);
|
||||||
|
|
||||||
|
-- PSE regs and control signals
|
||||||
|
type arr_regs_t is array (natural range <>) of std_logic_vector(7 downto 0);
|
||||||
|
signal pse_regs_to_read, pse_regs_value: arr_regs_t(0 to PSE_REG_NUM-1);
|
||||||
|
|
||||||
|
type i2c_pse_fsm_t is (ready, i2c_trn_start, i2c_trn_main, i2c_wr_wait, i2c_rd_wait, wait_ack);
|
||||||
|
signal i2c_state : i2c_pse_fsm_t := ready;
|
||||||
|
|
||||||
|
signal s_i2c_data_wr : std_logic_vector(7 downto 0);
|
||||||
|
signal s_i2c_data_rd : std_logic_vector(7 downto 0);
|
||||||
|
signal s_i2c_txn_start : std_logic;
|
||||||
|
signal s_i2c_rw_flag : std_logic;
|
||||||
|
signal s_i2c_busy_flag : std_logic;
|
||||||
|
signal i2c_busy_prev : std_logic;
|
||||||
|
signal i2c_core_start : std_logic;
|
||||||
|
signal i2c_core_busy : std_logic;
|
||||||
|
signal i2c_wr_done : std_logic;
|
||||||
|
signal reg_i2c_trn_dir : std_logic;
|
||||||
|
signal wait_i2c_start : std_logic;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
-- Interrupt output routing
|
-- Interrupt output routing
|
||||||
|
|
@ -251,63 +274,108 @@ begin
|
||||||
reg_pse_status(0) <= pse_vpwr_pg;
|
reg_pse_status(0) <= pse_vpwr_pg;
|
||||||
|
|
||||||
-- Connect PSE I2C bus to main I2C bus
|
-- Connect PSE I2C bus to main I2C bus
|
||||||
-- inst_i2c_master: i2c_master
|
inst_i2c_master: i2c_master
|
||||||
-- generic map (
|
generic map (
|
||||||
-- input_clk => SYSFREQ,
|
input_clk => SYSFREQ,
|
||||||
-- bus_clk => I2C_CLK
|
bus_clk => I2C_CLK
|
||||||
-- )
|
)
|
||||||
-- port map (
|
port map (
|
||||||
-- clk => clk25_i,
|
clk => clk25_i,
|
||||||
-- reset_n => s_rstn_i,
|
reset_n => s_rstn_i,
|
||||||
-- ena => s_i2c_txn_start,
|
ena => s_i2c_txn_start,
|
||||||
-- addr => x"20",
|
addr => PSE_I2C_ADDR,
|
||||||
-- rw => s_i2c_rw_flag,
|
rw => s_i2c_rw_flag,
|
||||||
-- data_wr => s_i2c_data_wr,
|
data_wr => s_i2c_data_wr,
|
||||||
-- busy => s_i2c_busy_flag,
|
busy => s_i2c_busy_flag,
|
||||||
-- data_rd => s_i2c_data_rd,
|
data_rd => s_i2c_data_rd,
|
||||||
-- ack_error => open,
|
ack_error => open,
|
||||||
-- sda => pse_i2c_sda_io,
|
sda => pse_i2c_sda_io,
|
||||||
-- scl => pse_i2c_scl_io,
|
scl => pse_i2c_scl_io,
|
||||||
-- scl_invert => '0'
|
scl_invert => '0'
|
||||||
-- );
|
);
|
||||||
|
|
||||||
-- -- PSE I2C interaction process
|
-- SIM attach reset assigment: default is 1-to-1 SIM to MODEM connection
|
||||||
-- pse_i2c_proc: process (clk_i, rstn_i)
|
pse_regs_to_read <= (
|
||||||
-- variable data_wr_cnt : natural := 0;
|
0 => x"0C", -- RO
|
||||||
-- variable data_rd_cnt : natural := 0;
|
1 => x"0D", -- RO
|
||||||
-- begin
|
2 => x"0E", -- RO
|
||||||
-- if (rstn_i = '0') then
|
3 => x"0F", -- RO
|
||||||
-- i2c_state <= ready;
|
4 => x"10", -- RO
|
||||||
-- i2c_core_busy <= '0';
|
5 => x"12", -- R/W
|
||||||
-- i2c_busy_prev <= (others => '0');
|
6 => x"13", -- R/W
|
||||||
-- i2c_ram_we <= (others => '0');
|
7 => x"14" -- R/W
|
||||||
-- i2c_wr_done <= '0';
|
);
|
||||||
|
|
||||||
-- elsif (rising_edge(clk_i)) then
|
------------------------------
|
||||||
-- case i2c_state is
|
-- PSE read trigger process --
|
||||||
-- when ready =>
|
------------------------------
|
||||||
-- if (i2c_core_start = '1') then
|
pse_readtrig_proc: process(clk25_i, s_rstn_i, wait_i2c_start, i2c_core_busy) is
|
||||||
-- i2c_state <= i2c_trn_start;
|
variable wait_cnt : natural := 0;
|
||||||
-- i2c_core_busy <= '1';
|
begin
|
||||||
-- data_wr_cnt := 0;
|
if (s_rstn_i = '0') then
|
||||||
-- data_rd_cnt := 0;
|
wait_i2c_start <= '0';
|
||||||
-- spi_ram_raddr <= data_wr_cnt; -- Request data from RAM
|
elsif (rising_edge(clk25_i)) then
|
||||||
|
if (wait_i2c_start = '1') then
|
||||||
|
if (i2c_core_busy = '1') then
|
||||||
|
wait_i2c_start <= '0';
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
if (i2c_core_start = '1' and i2c_core_busy = '0') then
|
||||||
|
i2c_core_start <= '0';
|
||||||
|
elsif (wait_cnt > PSE_POLL_INTERVAL) then
|
||||||
|
wait_cnt := 0;
|
||||||
|
wait_i2c_start <= '1';
|
||||||
|
i2c_core_start <= '1';
|
||||||
|
end if;
|
||||||
|
wait_cnt := wait_cnt + 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
-- i2c_busy_prev <= (i2c_busy_prev'range => '0');
|
-- PSE I2C interaction process
|
||||||
-- end if;
|
pse_i2c_proc: process (clk25_i, s_rstn_i)
|
||||||
|
variable reg_num_rd : natural := 0;
|
||||||
|
begin
|
||||||
|
if (s_rstn_i = '0') then
|
||||||
|
pse_regs_value <= (
|
||||||
|
0 => x"00",
|
||||||
|
1 => x"00",
|
||||||
|
2 => x"00",
|
||||||
|
3 => x"00",
|
||||||
|
4 => x"00",
|
||||||
|
5 => x"00",
|
||||||
|
6 => x"00",
|
||||||
|
7 => x"00"
|
||||||
|
);
|
||||||
|
i2c_state <= ready;
|
||||||
|
i2c_core_busy <= '0';
|
||||||
|
i2c_busy_prev <= '0';
|
||||||
|
i2c_wr_done <= '0';
|
||||||
|
reg_num_rd := 0;
|
||||||
|
|
||||||
-- when i2c_trn_start =>
|
elsif (rising_edge(clk25_i)) then
|
||||||
-- i2c_txn_start_o <= reg_i2c_mask; -- Initiate the transaction
|
case i2c_state is
|
||||||
-- i2c_slv_addr_o <= (others => reg_i2c_addr); -- Set the address of the slave
|
when ready =>
|
||||||
-- i2c_rw_flag_o <= (others => '0'); -- First byte is always write
|
if (i2c_core_start = '1') then
|
||||||
-- i2c_data_wr_o <= (others => spi_ram_data_o); -- Data to be written
|
i2c_state <= i2c_trn_start;
|
||||||
-- i2c_state <= i2c_trn_main;
|
i2c_core_busy <= '1';
|
||||||
|
reg_num_rd := 0;
|
||||||
|
i2c_busy_prev <= '0';
|
||||||
|
reg_i2c_trn_dir <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
-- when i2c_trn_main =>
|
when i2c_trn_start =>
|
||||||
-- i2c_data_wr_o <= (others => spi_ram_data_o); -- Data to be written to the I2C buses
|
s_i2c_txn_start <= '1'; -- Initiate the transaction
|
||||||
-- i2c_busy_prev <= i2c_busy_flag_i; -- Capture the value of the previous i2c busy signal
|
s_i2c_rw_flag <= '0'; -- First byte is always write
|
||||||
-- if (i2c_busy_prev = (i2c_busy_prev'range => '0') and i2c_busy_flag_i = reg_i2c_mask) then -- I2C busy just went high
|
s_i2c_data_wr <= pse_regs_to_read(reg_num_rd); -- Place reg number to I2C master core
|
||||||
-- case reg_i2c_trn_dir is -- Switches to the needed transaction direction
|
i2c_busy_prev <= s_i2c_busy_flag;
|
||||||
|
i2c_wr_done <= '0';
|
||||||
|
i2c_state <= i2c_trn_main;
|
||||||
|
|
||||||
|
when i2c_trn_main =>
|
||||||
|
i2c_busy_prev <= s_i2c_busy_flag; -- Capture the value of the previous i2c busy signal
|
||||||
|
if (i2c_busy_prev = '0' and s_i2c_busy_flag = '1') then -- I2C busy just went high
|
||||||
|
case reg_i2c_trn_dir is -- Switches to the needed transaction direction
|
||||||
-- when '0' => -- When write - continue to write
|
-- when '0' => -- When write - continue to write
|
||||||
-- data_wr_cnt := data_wr_cnt + 1;
|
-- data_wr_cnt := data_wr_cnt + 1;
|
||||||
-- if (data_wr_cnt > 0 and data_wr_cnt < spi_command_len) then -- Keep writing if there's still data in the RAM
|
-- if (data_wr_cnt > 0 and data_wr_cnt < spi_command_len) then -- Keep writing if there's still data in the RAM
|
||||||
|
|
@ -315,79 +383,59 @@ begin
|
||||||
-- i2c_state <= wait_ram;
|
-- i2c_state <= wait_ram;
|
||||||
-- else -- Else - finish the transaction
|
-- else -- Else - finish the transaction
|
||||||
-- i2c_state <= i2c_trn_final_word_wait;
|
-- i2c_state <= i2c_trn_final_word_wait;
|
||||||
-- i2c_txn_start_o <= (others => '0');
|
-- s_i2c_txn_start <= (others => '0');
|
||||||
-- end if;
|
-- end if;
|
||||||
-- when '1' => -- When read
|
when '1' => -- When read
|
||||||
-- if (data_rd_cnt = 0 and i2c_wr_done = '0') then -- Change the transaction from Write to Read after writing the first byte
|
if (i2c_wr_done = '0') then -- Change the transaction from Write to Read after writing the first byte
|
||||||
-- i2c_rw_flag_o <= (others => '1');
|
s_i2c_rw_flag <= '1'; -- Switch to read
|
||||||
-- i2c_state <= i2c_wr_wait; -- Switch to read
|
i2c_state <= i2c_wr_wait;
|
||||||
-- else
|
else
|
||||||
-- i2c_state <= i2c_rd_wait;
|
i2c_wr_done <= '0';
|
||||||
-- i2c_wr_done <= '0';
|
s_i2c_txn_start <= '0'; -- Stop core after reading 1 byte
|
||||||
-- end if;
|
i2c_state <= i2c_rd_wait;
|
||||||
-- i2c_ram_we <= (others => '0');
|
end if;
|
||||||
|
|
||||||
-- when others =>
|
when others =>
|
||||||
-- i2c_state <= ready;
|
i2c_state <= ready;
|
||||||
-- end case;
|
end case;
|
||||||
|
|
||||||
-- end if;
|
end if;
|
||||||
|
|
||||||
-- when wait_ram =>
|
|
||||||
-- i2c_state <= i2c_trn_main;
|
|
||||||
|
|
||||||
-- when i2c_trn_final_word_wait =>
|
-- when i2c_trn_final_word_wait =>
|
||||||
-- if (i2c_busy_prev = reg_i2c_mask and i2c_busy_flag_i = (i2c_busy_prev'range => '0')) then -- I2C became free
|
-- if (i2c_busy_prev = '1' and s_i2c_busy_flag = '0') then -- I2C became free
|
||||||
-- i2c_state <= wait_ack;
|
-- i2c_state <= wait_ack;
|
||||||
-- end if;
|
-- end if;
|
||||||
|
|
||||||
-- when i2c_wr_wait =>
|
when i2c_wr_wait =>
|
||||||
-- if (i2c_busy_flag_i = (i2c_busy_flag_i'range => '0')) then -- Indicates data read in last command is ready
|
if (s_i2c_busy_flag = '0') then -- Indicates data read in last command is ready
|
||||||
-- i2c_state <= i2c_trn_main; -- Transaction complete, go to next state in design
|
i2c_state <= i2c_trn_main; -- Transaction complete, go to next state in design
|
||||||
-- i2c_wr_done <= '1';
|
i2c_wr_done <= '1';
|
||||||
-- end if;
|
i2c_busy_prev <= s_i2c_busy_flag;
|
||||||
|
end if;
|
||||||
|
|
||||||
-- when i2c_rd_wait =>
|
when i2c_rd_wait =>
|
||||||
-- if (i2c_busy_flag_i = (i2c_busy_flag_i'range => '0')) then -- Indicates data read in last command is ready
|
if (s_i2c_busy_flag = '0') then -- Indicates data read in last command is ready
|
||||||
-- data_rd_cnt := data_rd_cnt + 1;
|
pse_regs_value(reg_num_rd) <= s_i2c_data_rd; -- Store received byte
|
||||||
-- i2c_ram_waddr <= (others => data_rd_cnt-1);
|
reg_num_rd := reg_num_rd + 1;
|
||||||
-- i2c_ram_we <= reg_i2c_mask;
|
if (reg_num_rd = PSE_REG_NUM) then -- All regs are 1 byte length
|
||||||
-- for i in 0 to I2C_NUM-1 loop
|
i2c_state <= wait_ack; -- Transaction complete, go to next state in design
|
||||||
-- if (reg_i2c_mask(i) = '1') then
|
else
|
||||||
-- i2c_ram_data_i(i) <= i2c_data_rd_i(i); -- Store received byte
|
i2c_state <= i2c_trn_start; -- Transaction complete, go to next state in design
|
||||||
-- end if;
|
end if;
|
||||||
-- end loop;
|
end if;
|
||||||
-- if (data_rd_cnt = reg_i2c_read_len) then
|
|
||||||
-- i2c_state <= wait_ack; -- Transaction complete, go to next state in design
|
|
||||||
-- else
|
|
||||||
-- i2c_state <= i2c_trn_main; -- Transaction complete, go to next state in design
|
|
||||||
-- end if;
|
|
||||||
-- end if;
|
|
||||||
|
|
||||||
-- if (data_rd_cnt+1 = reg_i2c_read_len) then
|
when wait_ack =>
|
||||||
-- i2c_txn_start_o <= (others => '0');
|
i2c_core_busy <= '0';
|
||||||
-- end if;
|
i2c_busy_prev <= '0';
|
||||||
|
if (i2c_core_start = '0') then
|
||||||
-- when wait_ack =>
|
i2c_state <= ready;
|
||||||
-- i2c_core_busy <= '0';
|
end if;
|
||||||
-- i2c_ram_we <= (others => '0');
|
|
||||||
-- i2c_busy_prev <= (others => '0');
|
|
||||||
-- if (i2c_core_start = '0') then
|
|
||||||
-- i2c_state <= ready;
|
|
||||||
-- end if;
|
|
||||||
|
|
||||||
-- when others =>
|
|
||||||
-- i2c_state <= ready;
|
|
||||||
-- end case;
|
|
||||||
-- end if;
|
|
||||||
-- end process pse_i2c_proc;
|
|
||||||
|
|
||||||
-- s_i2c_txn_start
|
|
||||||
-- s_i2c_rw_flag
|
|
||||||
-- s_i2c_data_wr
|
|
||||||
-- s_i2c_busy_flag
|
|
||||||
-- s_i2c_data_rd
|
|
||||||
|
|
||||||
|
when others =>
|
||||||
|
i2c_state <= ready;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process pse_i2c_proc;
|
||||||
|
|
||||||
-- pse_scl_rptr: odio_repeater
|
-- pse_scl_rptr: odio_repeater
|
||||||
-- generic map (
|
-- generic map (
|
||||||
|
|
@ -836,6 +884,38 @@ begin
|
||||||
i2c_data_to_master <= "0000000" & reg_poepd_ctl;
|
i2c_data_to_master <= "0000000" & reg_poepd_ctl;
|
||||||
i2c_slv_state <= wait_while_sent;
|
i2c_slv_state <= wait_while_sent;
|
||||||
|
|
||||||
|
when x"60" => -- Read PSE register "Port 1 Status" 0x0C
|
||||||
|
i2c_data_to_master <= pse_regs_value(0);
|
||||||
|
i2c_slv_state <= wait_while_sent;
|
||||||
|
|
||||||
|
when x"61" => -- Read PSE register "Port 2 Status" 0x0D
|
||||||
|
i2c_data_to_master <= pse_regs_value(1);
|
||||||
|
i2c_slv_state <= wait_while_sent;
|
||||||
|
|
||||||
|
when x"62" => -- Read PSE register "Port 3 Status" 0x0E
|
||||||
|
i2c_data_to_master <= pse_regs_value(2);
|
||||||
|
i2c_slv_state <= wait_while_sent;
|
||||||
|
|
||||||
|
when x"63" => -- Read PSE register "Port 4 Status" 0x0F
|
||||||
|
i2c_data_to_master <= pse_regs_value(3);
|
||||||
|
i2c_slv_state <= wait_while_sent;
|
||||||
|
|
||||||
|
when x"64" => -- Read PSE register "Power Status" 0x10
|
||||||
|
i2c_data_to_master <= pse_regs_value(4);
|
||||||
|
i2c_slv_state <= wait_while_sent;
|
||||||
|
|
||||||
|
when x"65" => -- Read PSE register "Operating Mode" 0x12
|
||||||
|
i2c_data_to_master <= pse_regs_value(5);
|
||||||
|
i2c_slv_state <= wait_while_sent;
|
||||||
|
|
||||||
|
when x"66" => -- Read PSE register "Disconnect Enable" 0x13
|
||||||
|
i2c_data_to_master <= pse_regs_value(6);
|
||||||
|
i2c_slv_state <= wait_while_sent;
|
||||||
|
|
||||||
|
when x"67" => -- Read PSE register "Detect/Class Enable" 0x14
|
||||||
|
i2c_data_to_master <= pse_regs_value(7);
|
||||||
|
i2c_slv_state <= wait_while_sent;
|
||||||
|
|
||||||
when x"A0" => -- Write SIM1 modem register
|
when x"A0" => -- Write SIM1 modem register
|
||||||
i2c_slv_state <= receive_byte;
|
i2c_slv_state <= receive_byte;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue