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;
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 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;
--==============================================================================
......@@ -112,7 +93,7 @@ begin
);
-- 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
gen_glitch_filt: if (g_len > 0) generate
......@@ -120,9 +101,9 @@ begin
begin
if rising_edge(clk_i) 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
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 process p_glitch_filt;
......@@ -134,9 +115,9 @@ begin
if rising_edge(clk_i) then
if (rst_n_i = '0') then
dat_o <= '0';
elsif (gc_glitch_filt = (gc_glitch_filt'range => '1')) then
elsif (glitch_filt = (glitch_filt'range => '1')) then
dat_o <= '1';
elsif (gc_glitch_filt = (gc_glitch_filt'range => '0')) then
elsif (glitch_filt = (glitch_filt'range => '0')) then
dat_o <= '0';
end if;
end if;
......
This diff is collapsed.
......@@ -4,9 +4,10 @@
-------------------------------------------------------------------------------
-- File : gencores_pkg.vhd
-- Author : Tomasz Wlostowski
-- Theodor-Adrian Stana
-- Company : CERN
-- Created : 2009-09-01
-- Last update: 2013-07-02
-- Last update: 2013-11-20
-- Platform : FPGA-generic
-- Standard : VHDL '93
-------------------------------------------------------------------------------
......@@ -38,6 +39,7 @@
-- Date Version Author Description
-- 2009-09-01 0.9 twlostow Created
-- 2011-04-18 1.0 twlostow Added comments & header
-- 2013-11-20 1.1 tstana Added glitch filter and I2C slave
-------------------------------------------------------------------------------
library ieee;
......@@ -48,7 +50,9 @@ use work.genram_pkg.all;
package gencores_pkg is
--============================================================================
-- Component instantiations
--============================================================================
component gc_extend_pulse
generic (
g_width : natural);
......@@ -201,7 +205,7 @@ package gencores_pkg is
q_valid_o : out std_logic;
q_input_id_o : out std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0));
end component;
-- Power-On reset generation
component gc_reset is
generic(
......@@ -240,7 +244,7 @@ package gencores_pkg is
q_o : out std_logic_vector(g_output_width-1 downto 0);
q_valid_o : out std_logic;
q_req_i : in std_logic);
end component;
end component;
component gc_big_adder is
generic(
......@@ -256,8 +260,7 @@ package gencores_pkg is
x2_o : out std_logic_vector(g_data_bits-1 downto 0);
c2_o : out std_logic);
end component;
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- I2C slave
------------------------------------------------------------------------------
constant c_i2cs_idle : std_logic_vector(1 downto 0) := "00";
......@@ -266,53 +269,57 @@ package gencores_pkg is
constant c_i2cs_wr_done : std_logic_vector(1 downto 0) := "11";
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
(
-- Clock, reset ports
clk_i : in std_logic;
rst_n_i : in std_logic;
clk_i : in std_logic;
rst_n_i : in std_logic;
-- I2C lines
scl_i : in 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;
scl_i : in 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;
-- 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'
-- (note that the bit is reversed wrt I2C ACK bit)
-- '1' - ACK
-- '0' - NACK
i2c_ack_i : in std_logic;
-- I2C bus operation, set after address detection
-- '0' - write
-- '1' - read
op_o : out std_logic;
ack_i : in std_logic;
-- 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'
rx_byte_o : out std_logic_vector(7 downto 0);
-- Done pulse signal, valid when
-- * received address matches i2c_addr_i, signaling valid op_o;
-- * a byte was received, signaling valid rx_byte_o and an ACK/NACK should be
-- sent to master;
-- * sent a byte, should set tx_byte_i.
done_p_o : out std_logic;
-- I2C transfer state
-- "00" - Idle
-- "01" - Got address, matches i2c_addr_i
-- "10" - Read done, waiting ACK/NACK
-- "11" - Write done, waiting next byte
stat_o : out std_logic_vector(1 downto 0)
rx_byte_o : out std_logic_vector(7 downto 0);
-- Pulse outputs signaling various I2C actions
-- Start and stop conditions
sta_p_o : out std_logic;
sto_p_o : out std_logic;
-- Received address corresponds addr_i
addr_good_p_o : out std_logic;
-- Read and write done
r_done_p_o : out std_logic;
w_done_p_o : out std_logic;
-- I2C bus operation, set after address detection
-- '0' - write
-- '1' - read
op_o : out std_logic
);
end component gc_i2c_slave;
......@@ -342,10 +349,32 @@ package gencores_pkg is
);
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
--============================================================================ procedure f_rr_arbitrate (
-- Procedures and functions
--============================================================================
procedure f_rr_arbitrate (
signal req : in std_logic_vector;
signal pre_grant : in std_logic_vector;
......@@ -359,7 +388,7 @@ package body gencores_pkg is
-- req = requests (1 = pending request),
-- pre_grant = previous grant vector (1 cycle delay)
-- grant = new grant vector
procedure f_rr_arbitrate (
signal req : in std_logic_vector;
signal pre_grant : in std_logic_vector;
......@@ -370,7 +399,7 @@ package body gencores_pkg is
variable gnt : 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);
begin
zeros := (others => '0');
......@@ -390,7 +419,7 @@ package body gencores_pkg is
else
grant <= pre_grant;
end if;
end f_rr_arbitrate;
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
rst_n_i : in std_logic;
-- 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_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_addr_i : in std_logic_vector(6 downto 0);
-- Transfer In Progress (TIP) and Error outputs
-- TIP : '1' when the I2C slave detects a matching I2C address, thus a
-- transfer is in progress
-- '0' when idle
-- ERR : '1' when the SysMon attempts to access an invalid WB slave
-- Status outputs
-- TIP : Transfer In Progress
-- '1' when the I2C slave detects a matching I2C address, thus a
-- transfer is in progress
-- '0' when idle
-- ERR : Error
-- '1' when the SysMon attempts to access an invalid WB slave
-- '0' when idle
tip_o : out std_logic;
err_o : out std_logic;
-- WDTO : Watchdog timeout (single clock cycle pulse)
-- '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
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