Skip to content

Commit 2f520cc

Browse files
committed
I2C Controller: add proper glitch filtering on SDA
1 parent 46e66c7 commit 2f520cc

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
@@ -77,6 +77,8 @@ architecture rtl of i2c_ctrl_link_layer is
7777
constant SDA_TRANSITION_TICKS : positive :=
7878
to_integer(calc_ns(300, CLK_PER_NS, 5));
7979

80+
constant TSP_TICKS : positive := to_integer(calc_ns(SETTINGS.tsp_ns, CLK_PER_NS, 8));
81+
8082
type state_t is (
8183
IDLE,
8284
WAIT_TBUF,
@@ -198,15 +200,22 @@ begin
198200
-- SDA Control
199201
--
200202

201-
-- TODO: this should be a glitch filter that means `tsp` per the spec
202-
sda_in_sync: entity work.meta_sync
203-
generic map (
204-
STAGES => 2
203+
-- Right now the controller doesn't need much of what this block offers aside from SDA filtering
204+
i2c_glitch_filter_inst: entity work.i2c_glitch_filter
205+
generic map(
206+
filter_cycles => TSP_TICKS
205207
)
206208
port map(
207-
async_input => sda_if.i,
208-
clk => clk,
209-
sycnd_output => sda_in_syncd
209+
clk => clk,
210+
reset => reset,
211+
raw_scl => '1',
212+
raw_sda => sda_if.i,
213+
filtered_scl => open,
214+
scl_fedge => open,
215+
scl_redge => open,
216+
filtered_sda => sda_in_syncd,
217+
sda_fedge => open,
218+
sda_redge => open
210219
);
211220

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

0 commit comments

Comments
 (0)