Skip to content

Commit 7a0c85e

Browse files
committed
I2C Controller: add proper glitch filtering on SDA
1 parent f87b7d2 commit 7a0c85e

File tree

5 files changed

+30
-15
lines changed

5 files changed

+30
-15
lines changed

hdl/ip/vhd/i2c/common/BUCK

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ vhdl_unit(
1616
name = "i2c_glitch_filter",
1717
srcs = ["i2c_glitch_filter.vhd"],
1818
deps = [
19-
"//hdl/ip/vhd/synchronizers:meta_sync",
19+
"//hdl/ip/vhd/common:transforms_pkg",
20+
"//hdl/ip/vhd/synchronizers:meta_sync",
2021
],
2122
visibility = ['PUBLIC']
2223
)

hdl/ip/vhd/i2c/common/i2c_common_pkg.vhd

+7-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ package i2c_common_pkg is
2727
sta_su_hd_ns : positive; -- START set-up/hold time
2828
sto_su_ns : positive; -- STOP set-up time
2929
sto_sta_buf_ns : positive; -- bus free time between STOP and START
30+
tsp_ns : positive; -- pulse width of spikes to be suppressed by the input filter
3031
end record;
3132

3233
function get_i2c_settings (constant mode : mode_t) return settings_t;
@@ -65,23 +66,26 @@ package body i2c_common_pkg is
6566
250,
6667
4700,
6768
4000,
68-
4700
69+
4700,
70+
50 -- this is technically undefined in the spec
6971
);
7072
when FAST =>
7173
r := (
7274
2500, -- 10^9 / 400_000Hz
7375
100,
7476
600,
7577
600,
76-
1300
78+
1300,
79+
50
7780
);
7881
when FAST_PLUS =>
7982
r := (
8083
1000, -- 10^9 / 1_000_000Hz
8184
50,
8285
260,
8386
260,
84-
500
87+
500,
88+
50
8589
);
8690
end case;
8791

hdl/ip/vhd/i2c/common/i2c_glitch_filter.vhd

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use ieee.std_logic_1164.all;
1818
use ieee.numeric_std.all;
1919
use ieee.numeric_std_unsigned.all;
2020

21+
use work.transforms_pkg.shift_in_at_0;
22+
2123
entity i2c_glitch_filter is
2224
generic(
2325
-- number of register stages the n filter pipeline
@@ -86,11 +88,9 @@ begin
8688
last_sda <= filtered_sda;
8789
-- Using variables here to make the filtered outputs
8890
-- simultaneous more easily
89-
nxt_scl_pipe := shift_left(scl_pipe, 1);
90-
nxt_scl_pipe(0) := scl_syncd;
91+
nxt_scl_pipe := shift_in_at_0(scl_pipe, scl_syncd);
9192
scl_pipe <= nxt_scl_pipe; -- do the register assignment
92-
nxt_sda_pipe := shift_left(sda_pipe, 1);
93-
nxt_sda_pipe(0) := sda_syncd;
93+
nxt_sda_pipe := shift_in_at_0(sda_pipe, sda_syncd);
9494
sda_pipe <= nxt_sda_pipe; -- do the register assignment
9595

9696
-- we use the variables set above here to make the filtered outputs

hdl/ip/vhd/i2c/controller/BUCK

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ vhdl_unit(
1515
"txn_layer/*.vhd",]),
1616
deps = [
1717
"//hdl/ip/vhd/i2c/common:i2c_common_pkg",
18+
"//hdl/ip/vhd/i2c/common:i2c_glitch_filter",
1819
"//hdl/ip/vhd/common:countdown",
1920
"//hdl/ip/vhd/common:strobe",
2021
"//hdl/ip/vhd/common:streaming_if_pkg",

hdl/ip/vhd/i2c/controller/link_layer/i2c_ctrl_link_layer.vhd

+16-7
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ architecture rtl of i2c_ctrl_link_layer is
6868
constant SDA_TRANSITION_TICKS : positive :=
6969
to_integer(calc_ns(300, CLK_PER_NS, 5));
7070

71+
constant TSP_TICKS : positive := to_integer(calc_ns(SETTINGS.tsp_ns, CLK_PER_NS, 8));
72+
7173
type state_t is (
7274
IDLE,
7375
WAIT_TBUF,
@@ -187,15 +189,22 @@ begin
187189
-- SDA Control
188190
--
189191

190-
-- TODO: this should be a glitch filter that means `tsp` per the spec
191-
sda_in_sync: entity work.meta_sync
192-
generic map (
193-
STAGES => 2
192+
-- Right now the controller doesn't need much of what this block offers aside from SDA filtering
193+
i2c_glitch_filter_inst: entity work.i2c_glitch_filter
194+
generic map(
195+
filter_cycles => TSP_TICKS
194196
)
195197
port map(
196-
async_input => sda_if.i,
197-
clk => clk,
198-
sycnd_output => sda_in_syncd
198+
clk => clk,
199+
reset => reset,
200+
raw_scl => '1',
201+
raw_sda => sda_if.i,
202+
filtered_scl => open,
203+
scl_fedge => open,
204+
scl_redge => open,
205+
filtered_sda => sda_in_syncd,
206+
sda_fedge => open,
207+
sda_redge => open
199208
);
200209

201210
-- This counter enforces `tvd` per the spec, ensuring we transition SDA only after an

0 commit comments

Comments
 (0)