Skip to content

Commit

Permalink
I2C: fix SCL rate, data endianness, and repeated start (#268)
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron-Hartwig authored Jan 28, 2025
1 parent 8e3d3c0 commit 76ca485
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 31 deletions.
8 changes: 4 additions & 4 deletions hdl/ip/vhd/i2c/common/sims/i2c_target_vc.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.
--
-- Copyright 2024 Oxide Computer Company
-- Copyright 2025 Oxide Computer Company

library ieee;
use ieee.std_logic_1164.all;
Expand Down Expand Up @@ -182,7 +182,7 @@ begin
rx_ackd <= TRUE when sda_if.i = '0' else FALSE;
rx_bit_count <= to_unsigned(1, rx_bit_count'length);
elsif state = GET_START_BYTE or state = GET_BYTE then
rx_data <= sda_if.i & rx_data(7 downto 1);
rx_data <= rx_data(rx_data'high-1 downto rx_data'low) & sda_if.i;
rx_bit_count <= rx_bit_count + 1;
end if;

Expand Down Expand Up @@ -214,9 +214,9 @@ begin
if tx_bit_count = 0 then
txd := read_word(i2c_target_vc.p_buffer.p_memory_ref, natural(to_integer(reg_addr)), 1);
else
txd := '1' & tx_data(7 downto 1);
txd := tx_data(tx_data'high-1 downto tx_data'low) & '1';
end if;
sda_oe <= not txd(0);
sda_oe <= not txd(7);
tx_bit_count <= tx_bit_count + 1;
else
-- release the bus
Expand Down
46 changes: 23 additions & 23 deletions hdl/ip/vhd/i2c/controller/link_layer/i2c_ctrl_link_layer.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.
--
-- Copyright 2024 Oxide Computer Company
-- Copyright 2025 Oxide Computer Company

library ieee;
use ieee.std_logic_1164.all;
Expand Down Expand Up @@ -51,7 +51,7 @@ architecture rtl of i2c_ctrl_link_layer is
-- fetch the settings for the desired I2C mode
constant SETTINGS : settings_t := get_i2c_settings(MODE);
constant SCL_HALF_PER_TICKS : positive :=
to_integer(calc_ns(SETTINGS.fscl_period_ns, CLK_PER_NS, 10));
to_integer(calc_ns(SETTINGS.fscl_period_ns / 2, CLK_PER_NS, 10));

-- The state machine's counter to enforce timing around various events
constant SM_COUNTER_SIZE_BITS : positive := 8;
Expand Down Expand Up @@ -90,17 +90,17 @@ architecture rtl of i2c_ctrl_link_layer is
bits_shifted : natural range 0 to 8;

-- control
ready : std_logic;
scl_start : std_logic;
scl_active : std_logic;
sda_hold : std_logic;
counter : std_logic_vector(SM_COUNTER_SIZE_BITS - 1 downto 0);
count_load : std_logic;
count_decr : std_logic;
count_clr : std_logic;
transition_sda_cntr_en : std_logic;
ack_sending : std_logic;
scl_fedge_seen : std_logic;
ready : std_logic;
scl_start : std_logic;
scl_active : std_logic;
sda_hold : std_logic;
counter : std_logic_vector(SM_COUNTER_SIZE_BITS - 1 downto 0);
count_load : std_logic;
count_decr : std_logic;
count_clr : std_logic;
transition_sda_cntr_en : std_logic;
ack_sending : std_logic;
sr_scl_fedge_seen : std_logic;

-- interfaces
rx_data : std_logic_vector(7 downto 0);
Expand All @@ -124,7 +124,7 @@ architecture rtl of i2c_ctrl_link_layer is
'0', -- count_clr
'0', -- transition_sda_cntr_en
'0', -- ack_sending
'0', -- scl_fedge_seen
'0', -- sr_scl_fedge_seen
(others => '0'),-- rx_data
'0', -- rx_data_valid
(others => '0'),-- tx_data
Expand Down Expand Up @@ -280,11 +280,12 @@ begin
end if;

when WAIT_REPEAT_START =>
if not sm_reg.scl_fedge_seen then
v.scl_fedge_seen := scl_fedge;
if not sm_reg.sr_scl_fedge_seen then
v.sr_scl_fedge_seen := scl_fedge;
elsif scl_redge then
v.state := START_SETUP;
v.scl_active := '0';
v.state := START_SETUP;
v.scl_active := '0';
v.sr_scl_fedge_seen := '0';
end if;

-- In the event of a repeated START account for setup requirements
Expand Down Expand Up @@ -335,8 +336,8 @@ begin
v.state := ACK_RX;
v.bits_shifted := 0;
else
v.sda_oe := not sm_reg.tx_data(0);
v.tx_data := '1' & sm_reg.tx_data(7 downto 1);
v.sda_oe := not sm_reg.tx_data(7);
v.tx_data := sm_reg.tx_data(sm_reg.tx_data'high-1 downto sm_reg.tx_data'low) & '1';
v.bits_shifted := sm_reg.bits_shifted + 1;
end if;
end if;
Expand All @@ -360,7 +361,7 @@ begin
v.rx_data_valid := '1';
v.bits_shifted := 0;
elsif scl_redge then
v.rx_data := sda_in_syncd & sm_reg.rx_data(7 downto 1);
v.rx_data := sm_reg.rx_data(sm_reg.rx_data'high-1 downto sm_reg.rx_data'low) & sda_in_syncd;
v.bits_shifted := sm_reg.bits_shifted + 1;
end if;

Expand Down Expand Up @@ -404,8 +405,7 @@ begin
end case;

-- next state logic
v.ready := '1' when v.state = IDLE or v.state = HANDLE_NEXT or v.state = HANDLE_NEXT
else '0';
v.ready := '1' when v.state = IDLE or v.state = HANDLE_NEXT else '0';

sm_reg_next <= v;
end process;
Expand Down
3 changes: 1 addition & 2 deletions hdl/ip/vhd/i2c/controller/txn_layer/i2c_ctrl_txn_layer.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.
--
-- Copyright 2024 Oxide Computer Company
-- Copyright 2025 Oxide Computer Company

library ieee;
use ieee.std_logic_1164.all;
Expand All @@ -11,7 +11,6 @@ use ieee.numeric_std_unsigned.all;
use work.stream8_pkg;
use work.tristate_if_pkg.all;

use work.i2c_common_pkg.all;
use work.i2c_common_pkg.all;

entity i2c_txn_layer is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- License, v. 2.0. If a copy of the MPL was not distributed with this
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.
--
-- Copyright 2024 Oxide Computer Company
-- Copyright 2025 Oxide Computer Company

library ieee;
use ieee.std_logic_1164.all;
Expand Down Expand Up @@ -64,7 +64,7 @@ begin
dut: entity work.i2c_txn_layer
generic map (
CLK_PER_NS => 8,
MODE => STANDARD
MODE => FAST_PLUS
)
port map (
clk => clk,
Expand Down

0 comments on commit 76ca485

Please sign in to comment.