Commit ff660239 authored by Theodor-Adrian Stana's avatar Theodor-Adrian Stana Committed by Tomasz Wlostowski

Made I2C slave and bridge work properly

- I2C slave component now samples SDA line one rising SCL and changes
states and shifts out bits on its falling edge
- I2C slave component has clearer status outputs
- bridge component changed to reflect changes in I2C slave interface
- bridge component also returns to IDLE state on I2C stop condition, as
reflected by the I2C slave
Signed-off-by: Theodor-Adrian Stana's avatarTheodor Stana <t.stana@cern.ch>
Signed-off-by: Tomasz Wlostowski's avatarTomasz Włostowski <tomasz.wlostowski@cern.ch>
parent cef1c699
...@@ -66,29 +66,10 @@ end entity gc_glitch_filt; ...@@ -66,29 +66,10 @@ end entity gc_glitch_filt;
architecture behav of gc_glitch_filt is architecture behav of gc_glitch_filt is
--============================================================================
-- Component declarations
--============================================================================
component gc_sync_ffs is
generic(
g_sync_edge : string := "positive"
);
port(
clk_i : in std_logic; -- clock from the destination clock domain
rst_n_i : in std_logic; -- reset
data_i : in std_logic; -- async input
synced_o : out std_logic; -- synchronized output
npulse_o : out std_logic; -- negative edge detect output (single-clock
-- pulse)
ppulse_o : out std_logic -- positive edge detect output (single-clock
-- pulse)
);
end component gc_sync_ffs;
--============================================================================ --============================================================================
-- Signal declarations -- Signal declarations
--============================================================================ --============================================================================
signal gc_glitch_filt : std_logic_vector(g_len downto 0); signal glitch_filt : std_logic_vector(g_len downto 0);
signal dat_synced : std_logic; signal dat_synced : std_logic;
--============================================================================== --==============================================================================
...@@ -112,7 +93,7 @@ begin ...@@ -112,7 +93,7 @@ begin
); );
-- Then, assign the current sample of the glitch filter -- Then, assign the current sample of the glitch filter
gc_glitch_filt(0) <= dat_synced; glitch_filt(0) <= dat_synced;
-- Generate glitch filter FFs when the filter length is > 0 -- Generate glitch filter FFs when the filter length is > 0
gen_glitch_filt: if (g_len > 0) generate gen_glitch_filt: if (g_len > 0) generate
...@@ -120,9 +101,9 @@ begin ...@@ -120,9 +101,9 @@ begin
begin begin
if rising_edge(clk_i) then if rising_edge(clk_i) then
if (rst_n_i = '0') then if (rst_n_i = '0') then
gc_glitch_filt(g_len downto 1) <= (others => '0'); glitch_filt(g_len downto 1) <= (others => '0');
else else
gc_glitch_filt(g_len downto 1) <= gc_glitch_filt(g_len-1 downto 0); glitch_filt(g_len downto 1) <= glitch_filt(g_len-1 downto 0);
end if; end if;
end if; end if;
end process p_glitch_filt; end process p_glitch_filt;
...@@ -134,9 +115,9 @@ begin ...@@ -134,9 +115,9 @@ begin
if rising_edge(clk_i) then if rising_edge(clk_i) then
if (rst_n_i = '0') then if (rst_n_i = '0') then
dat_o <= '0'; dat_o <= '0';
elsif (gc_glitch_filt = (gc_glitch_filt'range => '1')) then elsif (glitch_filt = (glitch_filt'range => '1')) then
dat_o <= '1'; dat_o <= '1';
elsif (gc_glitch_filt = (gc_glitch_filt'range => '0')) then elsif (glitch_filt = (glitch_filt'range => '0')) then
dat_o <= '0'; dat_o <= '0';
end if; end if;
end if; end if;
......
This diff is collapsed.
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- File : gencores_pkg.vhd -- File : gencores_pkg.vhd
-- Author : Tomasz Wlostowski -- Author : Tomasz Wlostowski
-- Theodor-Adrian Stana
-- Company : CERN -- Company : CERN
-- Created : 2009-09-01 -- Created : 2009-09-01
-- Last update: 2013-07-02 -- Last update: 2013-11-20
-- Platform : FPGA-generic -- Platform : FPGA-generic
-- Standard : VHDL '93 -- Standard : VHDL '93
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
...@@ -38,6 +39,7 @@ ...@@ -38,6 +39,7 @@
-- Date Version Author Description -- Date Version Author Description
-- 2009-09-01 0.9 twlostow Created -- 2009-09-01 0.9 twlostow Created
-- 2011-04-18 1.0 twlostow Added comments & header -- 2011-04-18 1.0 twlostow Added comments & header
-- 2013-11-20 1.1 tstana Added glitch filter and I2C slave
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
library ieee; library ieee;
...@@ -48,7 +50,9 @@ use work.genram_pkg.all; ...@@ -48,7 +50,9 @@ use work.genram_pkg.all;
package gencores_pkg is package gencores_pkg is
--============================================================================
-- Component instantiations
--============================================================================
component gc_extend_pulse component gc_extend_pulse
generic ( generic (
g_width : natural); g_width : natural);
...@@ -201,7 +205,7 @@ package gencores_pkg is ...@@ -201,7 +205,7 @@ package gencores_pkg is
q_valid_o : out std_logic; q_valid_o : out std_logic;
q_input_id_o : out std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0)); q_input_id_o : out std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0));
end component; end component;
-- Power-On reset generation -- Power-On reset generation
component gc_reset is component gc_reset is
generic( generic(
...@@ -240,7 +244,7 @@ package gencores_pkg is ...@@ -240,7 +244,7 @@ package gencores_pkg is
q_o : out std_logic_vector(g_output_width-1 downto 0); q_o : out std_logic_vector(g_output_width-1 downto 0);
q_valid_o : out std_logic; q_valid_o : out std_logic;
q_req_i : in std_logic); q_req_i : in std_logic);
end component; end component;
component gc_big_adder is component gc_big_adder is
generic( generic(
...@@ -256,8 +260,7 @@ package gencores_pkg is ...@@ -256,8 +260,7 @@ package gencores_pkg is
x2_o : out std_logic_vector(g_data_bits-1 downto 0); x2_o : out std_logic_vector(g_data_bits-1 downto 0);
c2_o : out std_logic); c2_o : out std_logic);
end component; end component;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- I2C slave -- I2C slave
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
constant c_i2cs_idle : std_logic_vector(1 downto 0) := "00"; constant c_i2cs_idle : std_logic_vector(1 downto 0) := "00";
...@@ -266,53 +269,57 @@ package gencores_pkg is ...@@ -266,53 +269,57 @@ package gencores_pkg is
constant c_i2cs_wr_done : std_logic_vector(1 downto 0) := "11"; constant c_i2cs_wr_done : std_logic_vector(1 downto 0) := "11";
component gc_i2c_slave is component gc_i2c_slave is
generic
(
-- Length of glitch filter
-- 0 - SCL and SDA lines are passed only through synchronizer
-- 1 - one clk_i glitches filtered
-- 2 - two clk_i glitches filtered
g_gf_len : natural := 0
);
port port
( (
-- Clock, reset ports -- Clock, reset ports
clk_i : in std_logic; clk_i : in std_logic;
rst_n_i : in std_logic; rst_n_i : in std_logic;
-- I2C lines -- I2C lines
scl_i : in std_logic; scl_i : in std_logic;
scl_o : out std_logic; scl_o : out std_logic;
scl_en_o : out std_logic; scl_en_o : out std_logic;
sda_i : in std_logic; sda_i : in std_logic;
sda_o : out std_logic; sda_o : out std_logic;
sda_en_o : out std_logic; sda_en_o : out std_logic;
-- Slave address -- Slave address
i2c_addr_i : in std_logic_vector(6 downto 0); addr_i : in std_logic_vector(6 downto 0);
-- ACK input, should be set after done_p_o = '1' -- ACK input, should be set after done_p_o = '1'
-- (note that the bit is reversed wrt I2C ACK bit) -- (note that the bit is reversed wrt I2C ACK bit)
-- '1' - ACK -- '1' - ACK
-- '0' - NACK -- '0' - NACK
i2c_ack_i : in std_logic; ack_i : in std_logic;
-- I2C bus operation, set after address detection
-- '0' - write
-- '1' - read
op_o : out std_logic;
-- Byte to send, should be loaded while done_p_o = '1' -- Byte to send, should be loaded while done_p_o = '1'
tx_byte_i : in std_logic_vector(7 downto 0); tx_byte_i : in std_logic_vector(7 downto 0);
-- Received byte, valid after done_p_o = '1' -- Received byte, valid after done_p_o = '1'
rx_byte_o : out std_logic_vector(7 downto 0); rx_byte_o : out std_logic_vector(7 downto 0);
-- Done pulse signal, valid when -- Pulse outputs signaling various I2C actions
-- * received address matches i2c_addr_i, signaling valid op_o; -- Start and stop conditions
-- * a byte was received, signaling valid rx_byte_o and an ACK/NACK should be sta_p_o : out std_logic;
-- sent to master; sto_p_o : out std_logic;
-- * sent a byte, should set tx_byte_i. -- Received address corresponds addr_i
done_p_o : out std_logic; addr_good_p_o : out std_logic;
-- Read and write done
-- I2C transfer state r_done_p_o : out std_logic;
-- "00" - Idle w_done_p_o : out std_logic;
-- "01" - Got address, matches i2c_addr_i
-- "10" - Read done, waiting ACK/NACK -- I2C bus operation, set after address detection
-- "11" - Write done, waiting next byte -- '0' - write
stat_o : out std_logic_vector(1 downto 0) -- '1' - read
op_o : out std_logic
); );
end component gc_i2c_slave; end component gc_i2c_slave;
...@@ -342,10 +349,32 @@ package gencores_pkg is ...@@ -342,10 +349,32 @@ package gencores_pkg is
); );
end component gc_glitch_filt; end component gc_glitch_filt;
------------------------------------------------------------------------------
-- FSM Watchdog Timer
------------------------------------------------------------------------------
component gc_fsm_watchdog is
generic
(
-- Maximum value of watchdog timer in clk_i cycles
g_wdt_max : positive := 65535
);
port
(
-- Clock and active-low reset line
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Active-high watchdog timer reset line, synchronous to clk_i
wdt_rst_i : in std_logic;
-- Active-high reset output, synchronous to clk_i
fsm_rst_o : out std_logic
);
end component gc_fsm_watchdog;
--============================================================================ --============================================================================
-- Procedures -- Procedures and functions
--============================================================================ procedure f_rr_arbitrate ( --============================================================================
procedure f_rr_arbitrate ( procedure f_rr_arbitrate (
signal req : in std_logic_vector; signal req : in std_logic_vector;
signal pre_grant : in std_logic_vector; signal pre_grant : in std_logic_vector;
...@@ -359,7 +388,7 @@ package body gencores_pkg is ...@@ -359,7 +388,7 @@ package body gencores_pkg is
-- req = requests (1 = pending request), -- req = requests (1 = pending request),
-- pre_grant = previous grant vector (1 cycle delay) -- pre_grant = previous grant vector (1 cycle delay)
-- grant = new grant vector -- grant = new grant vector
procedure f_rr_arbitrate ( procedure f_rr_arbitrate (
signal req : in std_logic_vector; signal req : in std_logic_vector;
signal pre_grant : in std_logic_vector; signal pre_grant : in std_logic_vector;
...@@ -370,7 +399,7 @@ package body gencores_pkg is ...@@ -370,7 +399,7 @@ package body gencores_pkg is
variable gnt : std_logic_vector(req'length - 1 downto 0); variable gnt : std_logic_vector(req'length - 1 downto 0);
variable gntM : std_logic_vector(req'length - 1 downto 0); variable gntM : std_logic_vector(req'length - 1 downto 0);
variable zeros : std_logic_vector(req'length - 1 downto 0); variable zeros : std_logic_vector(req'length - 1 downto 0);
begin begin
zeros := (others => '0'); zeros := (others => '0');
...@@ -390,7 +419,7 @@ package body gencores_pkg is ...@@ -390,7 +419,7 @@ package body gencores_pkg is
else else
grant <= pre_grant; grant <= pre_grant;
end if; end if;
end f_rr_arbitrate; end f_rr_arbitrate;
function f_big_ripple(a, b : std_logic_vector; c : std_logic) return std_logic_vector is function f_big_ripple(a, b : std_logic_vector; c : std_logic) return std_logic_vector is
......
...@@ -910,24 +910,30 @@ package wishbone_pkg is ...@@ -910,24 +910,30 @@ package wishbone_pkg is
rst_n_i : in std_logic; rst_n_i : in std_logic;
-- I2C lines -- I2C lines
sda_en_o : out std_logic;
sda_i : in std_logic;
sda_o : out std_logic;
scl_en_o : out std_logic;
scl_i : in std_logic; scl_i : in std_logic;
scl_o : out std_logic; scl_o : out std_logic;
scl_en_o : out std_logic;
sda_i : in std_logic;
sda_o : out std_logic;
sda_en_o : out std_logic;
-- I2C address -- I2C address
i2c_addr_i : in std_logic_vector(6 downto 0); i2c_addr_i : in std_logic_vector(6 downto 0);
-- Transfer In Progress (TIP) and Error outputs -- Status outputs
-- TIP : '1' when the I2C slave detects a matching I2C address, thus a -- TIP : Transfer In Progress
-- transfer is in progress -- '1' when the I2C slave detects a matching I2C address, thus a
-- '0' when idle -- transfer is in progress
-- ERR : '1' when the SysMon attempts to access an invalid WB slave -- '0' when idle
-- ERR : Error
-- '1' when the SysMon attempts to access an invalid WB slave
-- '0' when idle -- '0' when idle
tip_o : out std_logic; -- WDTO : Watchdog timeout (single clock cycle pulse)
err_o : out std_logic; -- '1' -- timeout of watchdog occured
-- '0' -- when idle
tip_o : out std_logic;
err_p_o : out std_logic;
wdto_p_o : out std_logic;
-- Wishbone master signals -- Wishbone master signals
wbm_stb_o : out std_logic; wbm_stb_o : out std_logic;
......
--==============================================================================
-- CERN (BE-CO-HT)
-- I2C bus model
--==============================================================================
--
-- author: Theodor Stana (t.stana@cern.ch)
--
-- date of creation: 2013-11-27
--
-- version: 1.0
--
-- description:
-- A very simple I2C bus model for use in simulation, implementing the
-- wired-AND on the I2C protocol.
--
-- Masters and slaves should implement the buffers internally and connect the
-- SCL and SDA lines to the input ports of this model, as below:
-- - masters should connect to mscl_i and msda_i
-- - slaves should connect to sscl_i and ssda_i
--
-- dependencies:
--
-- references:
--
--==============================================================================
-- GNU LESSER GENERAL PUBLIC LICENSE
--==============================================================================
-- This source file is free software; you can redistribute it and/or modify it
-- under the terms of the GNU Lesser General Public License as published by the
-- Free Software Foundation; either version 2.1 of the License, or (at your
-- option) any later version. This source is distributed in the hope that it
-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Lesser General Public License for more details. You should have
-- received a copy of the GNU Lesser General Public License along with this
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
--==============================================================================
-- last changes:
-- 2013-11-27 Theodor Stana File created
--==============================================================================
-- TODO: -
--==============================================================================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity i2c_bus_model is
generic
(
g_nr_masters : positive := 1;
g_nr_slaves : positive := 1
);
port
(
-- Input ports from master lines
mscl_i : in std_logic_vector(g_nr_masters-1 downto 0);
msda_i : in std_logic_vector(g_nr_masters-1 downto 0);
-- Input ports from slave lines
sscl_i : in std_logic_vector(g_nr_slaves-1 downto 0);
ssda_i : in std_logic_vector(g_nr_slaves-1 downto 0);
-- SCL and SDA line outputs
scl_o : out std_logic;
sda_o : out std_logic
);
end entity i2c_bus_model;
architecture behav of i2c_bus_model is
--==============================================================================
-- architecture begin
--==============================================================================
begin
scl_o <= '1' when (mscl_i = (mscl_i'range => '1')) and
(sscl_i = (sscl_i'range => '1')) else
'0';
sda_o <= '1' when (msda_i = (msda_i'range => '1')) and
(ssda_i = (ssda_i'range => '1')) else
'0';
end architecture behav;
--==============================================================================
-- architecture end
--==============================================================================
This diff is collapsed.
This diff is collapsed.
vlib work
vcom -explicit -93 "../../modules/genrams/genram_pkg.vhd"
vcom -explicit -93 "../../modules/common/gencores_pkg.vhd"
vcom -explicit -93 "../../modules/wishbone/wishbone_pkg.vhd"
vcom -explicit -93 "../../modules/common/gc_sync_ffs.vhd"
vcom -explicit -93 "../../modules/common/gc_glitch_filt.vhd"
vcom -explicit -93 "../../modules/common/gc_fsm_watchdog.vhd"
vcom -explicit -93 "../../modules/common/gc_i2c_slave.vhd"
vcom -explicit -93 "../../modules/wishbone/wb_i2c_bridge/wb_i2c_bridge.vhd"
vcom -explicit -93 "i2c_master_bit_ctrl.vhd"
vcom -explicit -93 "i2c_master_byte_ctrl.vhd"
vcom -explicit -93 "i2c_bus_model.vhd"
vcom -explicit -93 "tb_wb_i2c_bridge.vhd"
#vcom -explicit -93 "tb_gc_i2c_slave.vhd"
vsim -t 1ps -voptargs="+acc" -lib work work.tb_wb_i2c_bridge
radix -hexadecimal
#add wave *
do wave.do
#do busmdl.do
#do wave-i2cs.do
run 20 ms
wave zoomfull
This diff is collapsed.
This diff is collapsed.
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /tb_gc_i2c_slave/clk
add wave -noupdate /tb_gc_i2c_slave/state_mst
add wave -noupdate /tb_gc_i2c_slave/state_slv
add wave -noupdate /tb_gc_i2c_slave/scl_to_slv
add wave -noupdate /tb_gc_i2c_slave/sda_to_slv
add wave -noupdate /tb_gc_i2c_slave/sda_fr_slv
add wave -noupdate /tb_gc_i2c_slave/scl_fr_mst
add wave -noupdate /tb_gc_i2c_slave/sda_to_mst
add wave -noupdate /tb_gc_i2c_slave/sda_fr_mst
add wave -noupdate -divider BUS
add wave -noupdate /tb_gc_i2c_slave/scl_to_slv
add wave -noupdate /tb_gc_i2c_slave/scl_fr_slv
add wave -noupdate /tb_gc_i2c_slave/sda_to_slv
add wave -noupdate /tb_gc_i2c_slave/sda_fr_slv
add wave -noupdate /tb_gc_i2c_slave/scl_to_mst
add wave -noupdate /tb_gc_i2c_slave/scl_fr_mst
add wave -noupdate /tb_gc_i2c_slave/sda_to_mst
add wave -noupdate /tb_gc_i2c_slave/sda_fr_mst
add wave -noupdate -divider loopback
add wave -noupdate /tb_gc_i2c_slave/txb
add wave -noupdate /tb_gc_i2c_slave/rxb
add wave -noupdate /tb_gc_i2c_slave/rcvd
add wave -noupdate /tb_gc_i2c_slave/tmp
add wave -noupdate -divider slave
add wave -noupdate /tb_gc_i2c_slave/DUT/scl_i
add wave -noupdate /tb_gc_i2c_slave/DUT/sda_i
add wave -noupdate /tb_gc_i2c_slave/DUT/tick_p
add wave -noupdate /tb_gc_i2c_slave/DUT/tick_en
add wave -noupdate /tb_gc_i2c_slave/DUT/tick_cnt
add wave -noupdate /tb_gc_i2c_slave/DUT/ack_i
add wave -noupdate /tb_gc_i2c_slave/DUT/sda_en_o
add wave -noupdate /tb_gc_i2c_slave/DUT/tx_byte_i
add wave -noupdate /tb_gc_i2c_slave/DUT/rx_byte_o
add wave -noupdate /tb_gc_i2c_slave/DUT/state
add wave -noupdate /tb_gc_i2c_slave/DUT/txsr
add wave -noupdate /tb_gc_i2c_slave/DUT/rxsr
add wave -noupdate /tb_gc_i2c_slave/DUT/bit_cnt
add wave -noupdate /tb_gc_i2c_slave/cnt
add wave -noupdate /tb_gc_i2c_slave/DUT/op_o
add wave -noupdate /tb_gc_i2c_slave/DUT/sta_p_o
add wave -noupdate /tb_gc_i2c_slave/DUT/sto_p_o
add wave -noupdate /tb_gc_i2c_slave/DUT/addr_good_p_o
add wave -noupdate /tb_gc_i2c_slave/DUT/r_done_p_o
add wave -noupdate /tb_gc_i2c_slave/DUT/w_done_p_o
add wave -noupdate /tb_gc_i2c_slave/DUT/op_o
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {2555133080 ps} 0}
configure wave -namecolwidth 400
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 0
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {0 ps} {4200 us}
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate /tb_wb_i2c_bridge/clk
add wave -noupdate /tb_wb_i2c_bridge/scl
add wave -noupdate /tb_wb_i2c_bridge/sscl
add wave -noupdate /tb_wb_i2c_bridge/sda
add wave -noupdate -expand /tb_wb_i2c_bridge/ssda
add wave -noupdate /tb_wb_i2c_bridge/state
add wave -noupdate /tb_wb_i2c_bridge/stim_cnt
add wave -noupdate /tb_wb_i2c_bridge/send
add wave -noupdate -expand /tb_wb_i2c_bridge/reg
add wave -noupdate -expand /tb_wb_i2c_bridge/reg_1
add wave -noupdate /tb_wb_i2c_bridge/rcvd
add wave -noupdate /tb_wb_i2c_bridge/DUT/cmp_i2c_slave/state
add wave -noupdate /tb_wb_i2c_bridge/DUT_1/cmp_i2c_slave/state
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 2} {728700000 ps} 0}
configure wave -namecolwidth 400
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 0
configure wave -snapdistance 10
configure wave -datasetprefix 0
configure wave -rowmargin 4
configure wave -childrowmargin 2
configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {0 ps} {1640625 ns}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment