Commit c1e58f09 authored by Carlos Gil Soriano's avatar Carlos Gil Soriano

I2C revamped. Reads work.

parent 31f7081f
This diff is collapsed.
onerror {resume}
quietly WaveActivateNextPane {} 0
add wave -noupdate -expand -group {I2C interface} /i2c_slave_top_tb/uut/scl_i
add wave -noupdate -expand -group {I2C interface} /i2c_slave_top_tb/uut/scl_o
add wave -noupdate -expand -group {I2C interface} /i2c_slave_top_tb/uut/scl_oen
add wave -noupdate -expand -group {I2C interface} /i2c_slave_top_tb/uut/sda_i
add wave -noupdate -expand -group {I2C interface} /i2c_slave_top_tb/uut/sda_o
add wave -noupdate -expand -group {I2C interface} /i2c_slave_top_tb/uut/sda_oen
add wave -noupdate -expand -group {I2C interface} -radix unsigned /i2c_slave_top_tb/uut/i2c_addr_i
add wave -noupdate /i2c_slave_top_tb/uut/wb_clk
add wave -noupdate /i2c_slave_top_tb/uut/wb_rst_i
add wave -noupdate -group {Wishbone Slave} /i2c_slave_top_tb/uut/wb_slave_stb_i
add wave -noupdate -group {Wishbone Slave} /i2c_slave_top_tb/uut/wb_slave_cyc_i
add wave -noupdate -group {Wishbone Slave} /i2c_slave_top_tb/uut/wb_slave_we_i
add wave -noupdate -group {Wishbone Slave} -radix hexadecimal /i2c_slave_top_tb/uut/wb_slave_sel_i
add wave -noupdate -group {Wishbone Slave} -radix unsigned /i2c_slave_top_tb/uut/wb_slave_addr_i
add wave -noupdate -group {Wishbone Slave} -radix hexadecimal /i2c_slave_top_tb/uut/wb_slave_data_o
add wave -noupdate -group {Wishbone Slave} -radix hexadecimal /i2c_slave_top_tb/uut/wb_slave_data_i
add wave -noupdate -group {Wishbone Slave} /i2c_slave_top_tb/uut/wb_slave_ack_o
add wave -noupdate -group {Wishbone Slave} /i2c_slave_top_tb/uut/wb_slave_err_o
add wave -noupdate -group {Wishbone Slave} /i2c_slave_top_tb/uut/wb_slave_rty_o
add wave -noupdate -group {Wishbone Master} /i2c_slave_top_tb/uut/wb_master_stb_o
add wave -noupdate -group {Wishbone Master} /i2c_slave_top_tb/uut/wb_master_cyc_o
add wave -noupdate -group {Wishbone Master} /i2c_slave_top_tb/uut/wb_master_we_o
add wave -noupdate -group {Wishbone Master} -radix hexadecimal /i2c_slave_top_tb/uut/wb_master_sel_o
add wave -noupdate -group {Wishbone Master} -radix unsigned /i2c_slave_top_tb/uut/wb_master_addr_o
add wave -noupdate -group {Wishbone Master} -radix hexadecimal /i2c_slave_top_tb/uut/wb_master_data_i
add wave -noupdate -group {Wishbone Master} -radix hexadecimal /i2c_slave_top_tb/uut/wb_master_data_o
add wave -noupdate -group {Wishbone Master} /i2c_slave_top_tb/uut/wb_master_ack_i
add wave -noupdate -group {Wishbone Master} /i2c_slave_top_tb/uut/wb_master_err_i
add wave -noupdate -group {Wishbone Master} /i2c_slave_top_tb/uut/wb_master_rty_i
add wave -noupdate -divider Registers
add wave -noupdate /i2c_slave_top_tb/uut/inst_i2c_slave_core/i2c_SLA_fsm
add wave -noupdate -radix hexadecimal /i2c_slave_top_tb/uut/s_CTR0
add wave -noupdate -radix hexadecimal /i2c_slave_top_tb/uut/s_DRXA
add wave -noupdate -radix hexadecimal /i2c_slave_top_tb/uut/s_DRXB
add wave -noupdate -radix hexadecimal /i2c_slave_top_tb/uut/s_DTX
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/i2c_master_WB_BASIC_fsm
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/CTR0_o
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/DTX_o
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/load_TX
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/DRXA_i
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/DRXB_i
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/wb_clk
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/wb_rst_i
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_addr_o
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_cyc_o
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_data_o
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_sel_o
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_stb_o
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_we_o
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_ack_i
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_data_i
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_err_i
add wave -noupdate -group i2c_regs -group {WB master} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_master_rty_i
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_addr_i
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_cyc_i
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_data_i
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_sel_i
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_stb_i
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_we_i
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_ack_o
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_data_o
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_err_o
add wave -noupdate -group i2c_regs -group {WB slave} /i2c_slave_top_tb/uut/inst_i2c_regs/wb_slave_rty_o
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/i2c_addr_i
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/pf_wb_addr_i
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/rd_done_i
add wave -noupdate -group i2c_regs /i2c_slave_top_tb/uut/inst_i2c_regs/wr_done_i
add wave -noupdate -expand -group bit_counter /i2c_slave_top_tb/i2c_driver/s_scl_clk
add wave -noupdate -expand -group bit_counter /i2c_slave_top_tb/uut/inst_i2c_slave_core/s_bit_cnt
add wave -noupdate -expand -group bit_counter /i2c_slave_top_tb/uut/inst_i2c_slave_core/bit_counter_8/clk_i
add wave -noupdate -expand -group bit_counter -radix unsigned /i2c_slave_top_tb/uut/inst_i2c_slave_core/bit_counter_8/cnt_o
add wave -noupdate -expand -group bit_counter /i2c_slave_top_tb/uut/inst_i2c_slave_core/bit_counter_8/en_i
add wave -noupdate -expand -group bit_counter /i2c_slave_top_tb/uut/inst_i2c_slave_core/bit_counter_8/rst_i
add wave -noupdate -expand -group byte_counter /i2c_slave_top_tb/uut/inst_i2c_slave_core/byte_counter_8/clk_i
add wave -noupdate -expand -group byte_counter /i2c_slave_top_tb/uut/inst_i2c_slave_core/byte_counter_8/rst_i
add wave -noupdate -expand -group byte_counter /i2c_slave_top_tb/uut/inst_i2c_slave_core/byte_counter_8/en_i
add wave -noupdate -expand -group byte_counter -radix unsigned /i2c_slave_top_tb/uut/inst_i2c_slave_core/byte_counter_8/cnt_o
add wave -noupdate -divider {MCU signals}
add wave -noupdate /i2c_slave_top_tb/uut/pf_wb_addr_o
add wave -noupdate /i2c_slave_top_tb/uut/wr_done_o
add wave -noupdate /i2c_slave_top_tb/uut/rd_done_o
add wave -noupdate -divider {I2C driver}
add wave -noupdate -group i2c_driver /i2c_slave_top_tb/i2c_driver/tb_clk
add wave -noupdate -group i2c_driver /i2c_slave_top_tb/i2c_driver/scl_master_o
add wave -noupdate -group i2c_driver /i2c_slave_top_tb/i2c_driver/sda_master_i
add wave -noupdate -group i2c_driver /i2c_slave_top_tb/i2c_driver/sda_master_o
add wave -noupdate -group i2c_driver -radix hexadecimal /i2c_slave_top_tb/i2c_driver/wishbone_addr_i
add wave -noupdate -group i2c_driver -radix hexadecimal /i2c_slave_top_tb/i2c_driver/wr_data_i
add wave -noupdate -group i2c_driver /i2c_slave_top_tb/i2c_driver/start_i
add wave -noupdate -group i2c_driver /i2c_slave_top_tb/i2c_driver/write_i
add wave -noupdate -group i2c_driver /i2c_slave_top_tb/i2c_driver/start_done_o
add wave -noupdate -group i2c_driver /i2c_slave_top_tb/i2c_driver/write_done_o
add wave -noupdate -radix hexadecimal /i2c_slave_top_tb/uut/inst_i2c_regs/s_CTR0
TreeUpdate [SetDefaultTree]
WaveRestoreCursors {{Cursor 1} {147050000 ps} 0}
configure wave -namecolwidth 193
configure wave -valuecolwidth 100
configure wave -justifyvalue left
configure wave -signalnamewidth 1
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 ps
update
WaveRestoreZoom {1870304 ps} {194025244 ps}
----------------------------------------------------------------------------------
-- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 18:28:55 11/08/2011
-- Design Name: FIFO dispatcher with parallel load
-- Module Name: FIFO_dispatcher - Behavioral
-- Project Name: CTDAH
-- Target Devices: Spartan 6
-- Tool versions:
-- Description: This is a FIFO dispathcher with parallel load and flush.
--
-- | |
-- |----------|
-- reg_i LSB ---> | REG 0 |
-- |----------|
-- ---> | REG 1 |
-- |----------|
-- ---> | REG 2 |
-- |----------|
-- reg_i MSB ---> | REG 3 | ---> reg_o
-- |__________|
--
-- Dependencies: none
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity FIFO_dispatcher is
generic(
g_data_width : NATURAL := 8;
g_dispatcher_depth : NATURAL := 4
);
port (
reg_i : in STD_LOGIC_VECTOR (g_dispatcher_depth*g_data_width-1 downto 0);
clk : in STD_LOGIC;
load : in STD_LOGIC;
flush : in STD_LOGIC;
oen_i : in STD_LOGIC;
reg_o : out STD_LOGIC_VECTOR (g_data_width - 1 downto 0)
);
end FIFO_dispatcher;
architecture Behavioral of FIFO_dispatcher is
type DISPATCHER_REG is array(0 to g_dispatcher_depth-1) of STD_LOGIC_VECTOR(g_data_width - 1 downto 0);
signal reg_int : DISPATCHER_REG;
begin
process(clk, flush)
begin
if flush = '1' then
flushLoop: for i in 0 to g_dispatcher_depth-1 loop
reg_int(i) <= (others => '0');
end loop;
elsif rising_edge(clk) then
if load = '1' then
loadLoop: for i in 0 to g_dispatcher_depth - 1 loop
reg_int(i) <= reg_i((i+1)*g_data_width - 1 downto i*g_data_width) ;
end loop;
else
end if;
if oen_i = '1' then
reg_o <= reg_int(g_dispatcher_depth -1);
for i in 0 to g_dispatcher_depth - 2 loop
reg_int(i+1) <= reg_int(i);
end loop;
reg_int(0) <= (others => '0');
else
end if;
else
end if;
end process;
end Behavioral;
----------------------------------------------------------------------------------
-- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 10:33:33 11/08/2011
-- Design Name: FIFO variable stack length
-- Module Name: FIFO_stack - Behavioral
-- Project Name: CTDAH
-- Target Devices: Spartan 6
-- Tool versions:
-- Description: This module implements a generic FIFO stack of variable
-- data input length and stack depth. The ASCII art represents
-- the behaviour of the module, which works as a g_stack_depth
-- delay with parallel output
--
-- input--->
-- | |
-- |----------|
-- | REG 0 | ---> reg_o LSB
-- |----------|
-- | REG 1 | --->
-- |----------|
-- | REG 2 | --->
-- |----------|
-- | REG 3 | ---> reg_o MSB
-- |__________|
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity FIFO_stack is
generic(
g_data_width : NATURAL := 8;
g_stack_depth : NATURAL := 8
);
port (
reg_i : in STD_LOGIC_VECTOR (g_data_width-1 downto 0);
clk : in STD_LOGIC;
push : in STD_LOGIC;
flush : in STD_LOGIC;
reg_o : out STD_LOGIC_VECTOR (g_stack_depth*g_data_width - 1 downto 0)
);
end FIFO_stack;
architecture Behavioral of FIFO_stack is
type FIFO_REG is array(0 to g_stack_depth-1) of std_logic_vector(g_data_width - 1 downto 0);
signal reg_int : FIFO_REG;
begin
reg_o((g_stack_depth)*g_data_width-1 downto (g_stack_depth-1)*g_data_width ) <= reg_int(g_stack_depth-1);
gen_out: for i in 0 to g_stack_depth-2 generate
reg_o((i+1)*g_data_width-1 downto i*g_data_width ) <= reg_int(i);
end generate gen_out;
reg_proc: process(clk)
begin
if rising_edge(clk) then
if flush = '1' then
for i in 0 to g_stack_depth-1 loop
reg_int(i) <= (others => '0');
end loop;
elsif push = '1' then
reg_int(0) <= reg_i;
for i in 0 to g_stack_depth-2 loop
reg_int(i+1) <= reg_int(i);
end loop;
else
end if;
end if;
end process;
end Behavioral;
-------------------------------------------------------------------------------
-- Title : Counter with asynchronous reset
-- Project : CTDAH
-------------------------------------------------------------------------------
-- File : gc_counter.vhd
-- Author : Carlos Gil Soriano
-- Company : CERN BE-CO-HT
-- Created : 2011-07-11
-- Last update: 2011-07-11
-- Platform : FPGA-generic
-- Standard : VHDL '87
------------------------------------------------------------------------------
-- Description: Counter with asynchronous reset
-------------------------------------------------------------------------------
--
-- Copyright (c) 2009 - 2010 CERN
--
-- 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
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-07-11 1.0 gilsoriano Created
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity gc_counter is
generic(
g_data_width: NATURAL
);
port (
clk_i : in STD_LOGIC;
rst_i : in STD_LOGIC;
en_i : in STD_LOGIC;
cnt_o : out STD_LOGIC_VECTOR (g_data_width-1 downto 0)
);
end gc_counter;
architecture Behavioral of gc_counter is
begin
main_proc: process(clk_i, rst_i)
variable cnt_s : UNSIGNED(g_data_width-1 downto 0);
begin
if rst_i = '1' then
cnt_s := (others => '0');
elsif rising_edge(clk_i) then
if en_i = '1' then
-- Increment the counter if counting is enabled
cnt_s := cnt_s + 1;
else
end if;
else
end if;
cnt_o <= std_logic_vector(cnt_s);
end process;
end Behavioral;
----------------------------------------------------------------------------------
-- Company: CERN
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 17:26:32 15/03/2012
-- Design Name: 16 bit counter
-- Module Name: gc_counter16 - Behavioral
-- Project Name: CTDAH
-- Target Devices: Spartan 6
-- Tool versions:
-- Description: a basic 16 bit counter pin-to-pin compatible with Xilinx
-- IP core
--
-- Dependencies: none
--
-- Revision:
-- Revision 0. 1 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity gc_counter16 is
port(
clk : in STD_LOGIC;
ce : in STD_LOGIC;
sclr : in STD_LOGIC;
sset : in STD_LOGIC;
q : out STD_LOGIC_VECTOR(15 downto 0)
);
end gc_counter16;
architecture Behavioral of gc_counter16 is
signal counter : UNSIGNED(15 downto 0);
signal q_s : STD_LOGIC_VECTOR(15 downto 0);
begin
reg_proc: process(clk)
begin
if rising_edge(clk) and ce = '1' then
q <= STD_LOGIC_VECTOR(counter);
q_s <= STD_LOGIC_VECTOR(counter);
if sclr = '1' then
counter <= (others => '0');
elsif sset = '1' then
counter <= (others => '1');
else
if q_s = X"FFFF" then
counter <= (others => '0');
else
counter <= counter + 1;
end if;
end if;
else
end if;
end process;
end Behavioral;
----------------------------------------------------------------------------------
-- Company: CERN
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 16:26:32 10/07/2011
-- Design Name: Basic debouncer
-- Module Name: debouncer - Behavioral
-- Project Name: CTDAH
-- Target Devices: Spartan 6
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity gc_ff is
port(
Q : out STD_LOGIC;
C : in STD_LOGIC;
CLR : in STD_LOGIC;
D : in STD_LOGIC
);
end gc_ff;
architecture Behavioral of gc_ff is
begin
reg_proc: process(C)
begin
if rising_edge(C) then
if CLR = '1' then
Q <= '0';
else
Q <= D;
end if;
else
end if;
end process;
end Behavioral;
This diff is collapsed.
......@@ -26,97 +26,65 @@ library IEEE;
library work;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.i2c_slave_pkg.ALL;
use work.ctdah_pkg.ALL;
entity i2c_debouncer is
generic (
g_LENGTH : UNSIGNED(3 downto 0) := "0110";
g_outputONrise : BOOLEAN := TRUE
);
port (
rst : IN std_logic;
clk : IN std_logic;
input : IN std_logic;
output : OUT std_logic;
glitch_mask : IN std_logic_vector(to_integer(g_LENGTH)-1 downto 0)
);
generic (g_LENGTH : NATURAL := c_DEBOUNCE_LENGTH);
port (rst : in STD_LOGIC;
clk : in STD_LOGIC;
input : in STD_LOGIC;
output : out STD_LOGIC;
glitch_mask : in STD_LOGIC_VECTOR(g_LENGTH - 1 downto 0));
end i2c_debouncer;
architecture Behavioral of i2c_debouncer is
-- Signals
signal meta_ff1 : std_logic;
signal delay_s : std_logic_vector(to_integer(g_LENGTH)-1 downto 0);
signal output_s : std_logic;
signal s_input_d0 : STD_LOGIC;
--! The first of this signal is already stable (ff'ed two times at [0])
signal s_delay : STD_LOGIC_VECTOR(g_LENGTH - 1 downto 0);
begin
ff1: gc_ff
port map(
Q => meta_ff1,
C => clk,
CLR => rst,
D => input
);
port map(
Q => s_input_d0,
C => clk,
CLR => rst,
D => input);
ff2: gc_ff
port map(
Q => delay_s(0),
C => clk,
CLR => rst,
D => meta_ff1
);
port map(
Q => s_delay(0),
C => clk,
CLR => rst,
D => s_input_d0);
-- Metastability solved here
delay_line: for i in 1 to to_integer(g_LENGTH)-1 generate
sync_delay_line: for i in 1 to g_LENGTH - 1 generate
D_Flip_Flop : gc_ff
port map (
Q => delay_s(i),
Q => s_delay(i),
C => clk,
CLR => rst,
D => delay_s(i-1));
end generate delay_line;
-- This is not VHDL 2008 to support backwards compatibility
outputFalling: if not(g_outputONrise) generate
process (clk)
begin
if rising_edge(clk) then
if rst = '1' then
output_s <= '1';
elsif ( (delay_s and glitch_mask) = glitch_mask or (not(delay_s)and glitch_mask) = glitch_mask) then
output_s <= delay_s(0);
else
output_s <= '1';
end if;
else
output <= output_s;
end if;
end process;
end generate outputFalling;
D => s_delay(i-1));
end generate sync_delay_line;
outputRising: if g_outputONrise generate
p_output : process (clk)
begin
if rising_edge(clk) then
if rst = '1' then
output <= '1';
else
--! We can deglitch either zeros or ones
if ( (s_delay and glitch_mask) = glitch_mask
or (not(s_delay)and glitch_mask) = glitch_mask) then
output <= s_delay(0);
else
--! Internall pull-up of the pin
output <= '1';
end if;
end if;
end if;
end process p_output;
process (clk)
begin
if rising_edge(clk) then
if rst = '1' then
output <= '1';
elsif ( (delay_s and glitch_mask) = glitch_mask or (not(delay_s)and glitch_mask) = glitch_mask) then
output <= delay_s(0);
else
-- Internall pull-up of the pin
output <= '1';
end if;
else
end if;
end process;
end generate outputRising;
end Behavioral;
This diff is collapsed.
----------------------------------------------------------------------------------
--
-- Company: CERN, BE-CO-HT
-- Engineer: Carlos Gil Soriano
--
-- Create Date: 11:03:11 06/19/2012
-- Design Name:
-- Module Name: i2c_slave_pkg - Behavioral
-- Project Name: CTDAH/SVEC
-- Target Devices: Spartan 6
-- Tool versions: Xilinx ISE 13.4
-- Description: Package for the i2c_slave
--
-- Dependencies:
--
-- Revision: 0.1
-- 0.01 + File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.ALL;
package i2c_slave_pkg is
--! Default clock divider
constant c_CLK_DIV : UNSIGNED (31 downto 28) := to_unsigned( 2, 4);
constant c_DEBOUNCE_LENGTH : NATURAL := 6;
--! Broadcast address as specified in I2C standard
constant c_I2C_GENERAL_ADDR : UNSIGNED(6 downto 0) := to_unsigned(0,7);
constant c_RETRY_LENGTH : NATURAL := 10; --! 10 clks max. retries
constant c_SDA_reverse_bytes : BOOLEAN := false;
constant c_SDA_MSb : BOOLEAN := false;
-------------------------------------------------------------------------------
-- This is the declaration area of the constants used in other components:
-- c_COUNTER_WIDTH bit length of the gc_counter
-- c_DATA_WIDTH width of the data to be stored in FIFO_stack
-- and FIFO_dispatchers.
-- c_RX_STACK_DEPTH depth of FIFO_stack
-- c_TX_STACK_DEPTH depth of FIFO_dispatch
-------------------------------------------------------------------------------
constant c_COUNTER_WIDTH : NATURAL := 8;
constant c_DATA_WIDTH : NATURAL := 8;
constant c_RX_STACK_DEPTH : NATURAL := 6;
constant c_TX_STACK_DEPTH : NATURAL := 4;
attribute a_length : NATURAL;
-------------------------------------
-- CTR0 register
-------------------------------------
-- 16 bits
-- Wishbone access: Write-read
------------------------------------
-- BIT NAME Description
-- 0 I2C_OP I2C OPeration
-- 7-1 I2C_ADDR I2C address
-- 11-8 BIA Bytes of Indirect Addressing
-- 19-12 BRD Bytes to be ReaD from FPGA
-- 27-20 BWR Bytes to be WRitten to FPGA
-- 31-28 CLK_DIV Clock Divider for prescaling
-------------------------------------
-- I2C_OP Operations
-- 0 Read from I2C
-- 1 Write into I2C
-------------------------------------
type r_CTR0 is
record
I2C_OP : STD_LOGIC;
I2C_ADDR : UNSIGNED( 7 downto 1);
BIA : UNSIGNED(11 downto 8);
BRD : UNSIGNED(19 downto 12);
BWR : UNSIGNED(27 downto 20);
CLK_DIV : UNSIGNED(31 downto 28);
end record;
attribute a_length of r_CTR0 : type is 32;
-------------------------------------
-- DRX register
-------------------------------------
-- 32 bits
-- Wishbone access: Read-only
------------------------------------
-- BIT NAME Description
-- 31-0 DRX Data RX register
-------------------------------------
type r_DRX is
record
data : STD_LOGIC_VECTOR(31 downto 0);
end record;
attribute a_length of r_DRX : type is 32;
-------------------------------------
-- DTX register
-------------------------------------
-- 32 bits
-- Wishbone access: Read-only
------------------------------------
-- BIT NAME Description
-- 31-0 DTX Data TX register
-------------------------------------
type r_DTX is
record
data : STD_LOGIC_VECTOR(31 downto 0);
end record;
attribute a_length of r_DTX : type is 32;
constant c_CTR0_addr : UNSIGNED(3 downto 0) := X"0";
constant c_DTX_addr : UNSIGNED(3 downto 0) := X"1";
constant c_DRXA_addr : UNSIGNED(3 downto 0) := X"2";
constant c_DRXB_addr : UNSIGNED(3 downto 0) := X"3";
constant c_CTR0_default : r_CTR0 := (I2C_OP => '0',
I2C_ADDR => c_I2C_GENERAL_ADDR,
BIA => to_unsigned(2, 4),
BRD => to_unsigned(4, 8),
BWR => to_unsigned(4, 8),
CLK_DIV => c_CLK_DIV);
component i2c_slave_core
port (
clk : in STD_LOGIC;
rst_i : in STD_LOGIC;
sda_oen : out STD_LOGIC;
sda_i : in STD_LOGIC;
sda_o : out STD_LOGIC;
scl_oen : out STD_LOGIC;
scl_i : in STD_LOGIC;
scl_o : out STD_LOGIC;
CTR0_i : in STD_LOGIC_VECTOR (r_CTR0'a_length - 1 downto 0);
DRXA_o : out STD_LOGIC_VECTOR (r_DRX'a_length - 1 downto 0);
DRXB_o : out STD_LOGIC_VECTOR (r_DRX'a_length - 1 downto 0);
DTX_i : in STD_LOGIC_VECTOR (r_DTX'a_length - 1 downto 0);
load_TX : in STD_LOGIC;
pf_wb_addr_o : out STD_LOGIC;
rd_done_o : out STD_LOGIC;
wr_done_o : out STD_LOGIC);
end component;
component i2c_regs
port (wb_clk : in STD_LOGIC;
wb_rst_i : in STD_LOGIC;
wb_master_we_o : out STD_LOGIC;
wb_master_stb_o : out STD_LOGIC;
wb_master_cyc_o : out STD_LOGIC;
wb_master_sel_o : out STD_LOGIC_VECTOR (3 downto 0);
wb_master_data_i : in STD_LOGIC_VECTOR (31 downto 0);
wb_master_data_o : out STD_LOGIC_VECTOR (31 downto 0);
wb_master_addr_o : out STD_LOGIC_VECTOR (15 downto 0);
wb_master_ack_i : in STD_LOGIC;
wb_master_rty_i : in STD_LOGIC;
wb_master_err_i : in STD_LOGIC;
wb_slave_we_i : in STD_LOGIC;
wb_slave_stb_i : in STD_LOGIC;
wb_slave_cyc_i : in STD_LOGIC;
wb_slave_sel_i : in STD_LOGIC_VECTOR(3 downto 0);
wb_slave_data_i : in STD_LOGIC_VECTOR(31 downto 0);
wb_slave_data_o : out STD_LOGIC_VECTOR(31 downto 0);
wb_slave_addr_i : in STD_LOGIC_VECTOR(3 downto 0);
wb_slave_ack_o : out STD_LOGIC;
wb_slave_rty_o : out STD_LOGIC;
wb_slave_err_o : out STD_LOGIC;
CTR0_o : out STD_LOGIC_VECTOR (r_CTR0'a_length - 1 downto 0);
DRXA_i : in STD_LOGIC_VECTOR (r_DRX'a_length - 1 downto 0);
DRXB_i : in STD_LOGIC_VECTOR (r_DRX'a_length - 1 downto 0);
DTX_o : out STD_LOGIC_VECTOR (r_DTX'a_length - 1 downto 0);
load_TX : out STD_LOGIC;
pf_wb_addr_i : in STD_LOGIC;
rd_done_i : in STD_LOGIC;
wr_done_i : in STD_LOGIC;
i2c_addr_i : in STD_LOGIC_VECTOR(6 downto 0));
end component;
component i2c_debouncer is
generic (g_LENGTH : NATURAL := c_DEBOUNCE_LENGTH);
port (rst : in STD_LOGIC;
clk : in STD_LOGIC;
input : in STD_LOGIC;
output : out STD_LOGIC;
glitch_mask : in STD_LOGIC_VECTOR(g_LENGTH - 1 downto 0));
end component;
component i2c_bit
port (rst_i : in STD_LOGIC;
wb_clk_i : in STD_LOGIC;
sda_i : in STD_LOGIC;
scl_i : in STD_LOGIC;
start_o : out STD_LOGIC;
pause_o : out STD_LOGIC;
rcved_o : out STD_LOGIC;
done_o : out STD_LOGIC);
end component;
function f_CTR0 (signal r_register : in STD_LOGIC_VECTOR(31 downto 0))
return r_CTR0;
function f_STD_LOGIC_VECTOR(r_register : in r_CTR0) return STD_LOGIC_VECTOR;
end i2c_slave_pkg;
package body i2c_slave_pkg is
function f_CTR0 (signal r_register : in STD_LOGIC_VECTOR(31 downto 0))
return r_CTR0 is
variable v_return : r_CTR0;
begin
v_return.I2C_OP := r_register(0);
v_return.I2C_ADDR := UNSIGNED(r_register( 7 downto 1));
v_return.BIA := UNSIGNED(r_register(11 downto 8));
v_return.BRD := UNSIGNED(r_register(19 downto 12));
v_return.BWR := UNSIGNED(r_register(27 downto 20));
v_return.CLK_DIV := UNSIGNED(r_register(31 downto 28));
return v_return;
end function;
function f_STD_LOGIC_VECTOR(r_register : in r_CTR0)
return STD_LOGIC_VECTOR is
variable v_return : STD_LOGIC_VECTOR(31 downto 0);
begin
v_return(0) := r_register.I2C_OP;
v_return( 7 downto 1) := STD_LOGIC_VECTOR(r_register.I2C_ADDR);
v_return(11 downto 8) := STD_LOGIC_VECTOR(r_register.BIA);
v_return(19 downto 12) := STD_LOGIC_VECTOR(r_register.BRD);
v_return(27 downto 20) := STD_LOGIC_VECTOR(r_register.BWR);
v_return(31 downto 28) := STD_LOGIC_VECTOR(r_register.CLK_DIV);
return v_return;
end function;
end i2c_slave_pkg;
......@@ -26,7 +26,10 @@
-- simulation model.
--------------------------------------------------------------------------------
LIBRARY ieee;
library work;
USE ieee.std_logic_1164.ALL;
USE work.i2c_slave_pkg.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
......@@ -43,11 +46,11 @@ ARCHITECTURE behavior OF i2c_bit_tb IS
port(
rst_i : IN std_logic;
wb_clk_i : IN std_logic;
presc_e : IN std_logic;
presc : IN std_logic_vector(15 downto 0);
done : OUT std_logic;
sda_i : IN std_logic;
scl_i : IN std_logic;
done_o : OUT std_logic;
start_o : OUT std_logic;
pause_o : OUT std_logic;
rcved_o : OUT std_logic
......@@ -57,49 +60,33 @@ ARCHITECTURE behavior OF i2c_bit_tb IS
--Inputs
signal rst_i : std_logic := '0';
signal wb_clk_i : std_logic := '0';
signal presc_e : std_logic := '0';
signal presc : std_logic_vector(15 downto 0) := (others => '0');
signal sda_i : std_logic := '0';
signal scl_i : std_logic := '0';
--Outputs
signal done : std_logic;
signal start_o : std_logic;
signal pause_o : std_logic;
signal rcved_o : std_logic;
signal done_o : std_logic;
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name
constant wb_clk_i_period : time := 50 ns; -- @ 20 MHz
constant scl_i_period : time := 2500 ns; -- @ 400 KHz
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: i2c_bit
PORT MAP (
rst_i => rst_i,
wb_clk_i => wb_clk_i,
presc_e => presc_e,
presc => presc,
done => done,
sda_i => sda_i,
scl_i => scl_i,
start_o => start_o,
pause_o => pause_o,
rcved_o => rcved_o
);
-- procedure stop is
-- begin
-- end procedure;
--
-- procedure one is
-- begin
-- end procedure;
--
-- procedure zero is
-- begin
-- end procedure;
PORT MAP (rst_i => rst_i,
wb_clk_i => wb_clk_i,
sda_i => sda_i,
scl_i => scl_i,
start_o => start_o,
pause_o => pause_o,
rcved_o => rcved_o,
done_o => done_o);
-- Clock process definitions
wb_clk_i_process :process
......@@ -170,7 +157,6 @@ BEGIN
start;
addr_send("0101100");
pause;
-- insert stimulus here
wait;
end process;
......
library IEEE;
library work;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use STD.TEXTIO.ALL;
use work.i2c_slave_pkg.ALL;
use work.i2c_tb_pkg.ALL;
use std.textio.ALL;
--! Code intended for simulation only.
entity i2c_master_driver is
generic(g_WR_DATA_LENGTH : NATURAL := 32;
g_RD_DATA_LENGTH : NATURAL := 32;
g_WB_ADDR_LENGTH : NATURAL := 16;
g_SCL_PERIOD : TIME := 250 us);
port(tb_clk : in STD_LOGIC;
sda_master_i : in STD_LOGIC;
sda_master_o : out STD_LOGIC;
scl_master_o : out STD_LOGIC;
i2c_addr_op_i : in STD_LOGIC_VECTOR(7 downto 0);
wishbone_addr_i : in STD_LOGIC_VECTOR(g_WB_ADDR_LENGTH - 1 downto 0);
wr_data_i : in STD_LOGIC_VECTOR(g_WR_DATA_LENGTH - 1 downto 0);
rd_data_o : out STD_LOGIC_VECTOR(g_RD_DATA_LENGTH - 1 downto 0);
start_i : in STD_LOGIC;
start_done_o : out STD_LOGIC;
pause_i : in STD_LOGIC;
pause_done_o : out STD_LOGIC;
write_i : in STD_LOGIC;
write_done_o : out STD_LOGIC;
read_i : in STD_LOGIC;
read_done_o : out STD_LOGIC);
end i2c_master_driver;
architecture Behavioral of i2c_master_driver is
type i2c_byte_field is (ADDRESS_0,
ADDRESS_1,
WISHBONE_HIGH,
WISHBONE_LOW,
DATA0,
DATA1,
DATA2,
DATA3);
file s_file_handler : TEXT;
constant c_LOG_PATH : STRING := "../test/log/i2c_master_driver.txt";
constant sep : CHARACTER := ht;
signal s_scl_clk : STD_LOGIC := '1';
signal s_sda_master_o : STD_LOGIC := '1';
signal s_test_id : NATURAL := 0;
signal s_start_done : STD_LOGIC := '0';
signal s_pause_done : STD_LOGIC := '0';
signal s_write_done : STD_LOGIC := '0';
signal s_read_done : STD_LOGIC := '0';
signal s_active_link : STD_LOGIC := '0';
begin
file_open(s_file_handler, c_LOG_PATH, WRITE_MODE);
sda_master_o <= s_sda_master_o;
scl_master_o <= s_scl_clk when s_active_link = '1'
else '1';
start_done_o <= s_start_done;
pause_done_o <= s_pause_done;
write_done_o <= s_write_done;
read_done_o <= s_read_done;
scl_clk_process: process
begin
s_scl_clk <= not(s_scl_clk);
wait for g_SCL_PERIOD/2;
end process;
p_sda: process
variable v_bit_number : NATURAL := 0;
variable v_write_data : STD_LOGIC_VECTOR(g_RD_DATA_LENGTH - 1 downto 0);
--! @brief Function that returns strings for the acked field to be
--! logged.
--! @param byte_type i2c_byte_field type to be translated into a string
function get_field(byte_type : i2c_byte_field) return STRING is
variable v_return : STRING (16 downto 1) := (others => ' ');
begin
case byte_type is
when ADDRESS_0 =>
v_return := " [ADDRESS|0]";
when ADDRESS_1 =>
v_return := " [ADDRESS|1]";
when WISHBONE_HIGH =>
v_return := " WISHBONE HIGH";
when WISHBONE_LOW =>
v_return := " WISHBONE LOW";
when DATA0 =>
v_return := " READ DATA 0";
when DATA1 =>
v_return := " READ DATA 1";
when DATA2 =>
v_return := " READ DATA 2";
when DATA3 =>
v_return := " READ DATA 3";
when others =>
null;
end case;
return v_return;
end function;
--! @brief Function to reorder data before being sent by driver
--! through SDA
--! @param data Data to be reordered before being sent
function order_write_data(
data : STD_LOGIC_VECTOR(g_WR_DATA_LENGTH - 1 downto 0))
return STD_LOGIC_VECTOR is
variable v_ordered_tmp : STD_LOGIC_VECTOR(g_WR_DATA_LENGTH - 1 downto 0);
variable v_ordered : STD_LOGIC_VECTOR(g_WR_DATA_LENGTH - 1 downto 0);
begin
if c_SDA_reverse_bytes = true then
for i in 0 to g_RD_DATA_LENGTH/8 - 1 loop
for j in 0 to 7 loop
v_ordered_tmp(i*8+j) := data(((g_WR_DATA_LENGTH/8 - 1)-i)*8+j);
end loop;
end loop;
else
v_ordered := data;
end if;
if c_SDA_MSb = true then
for i in 0 to g_RD_DATA_LENGTH/8 - 1 loop
for j in 0 to 7 loop
v_ordered(i*8+j) := v_ordered_tmp(i*8+(8-j));
end loop;
end loop;
else
v_ordered := v_ordered_tmp;
end if;
return v_ordered;
end function;
--! @brief Procedure to send bytes through SDA
--! @param byte Byte to be sent
procedure send_byte(byte : STD_LOGIC_VECTOR(7 downto 0)) is
begin
--! This comes from a falling edge
for i in 0 to 7 loop
wait for g_SCL_PERIOD/4;
s_sda_master_o <= byte(i);
wait until falling_edge(s_scl_clk);
end loop;
end procedure;
--! @brief Procedure to check acks
--! @param test_id Test ID
--! @param operation Operation to be performed, either READ or WRITE
procedure check_ack(test_id : NATURAL;
operation : STRING (5 downto 1);
byte_type : i2c_byte_field) is
variable v_line_buffer : LINE;
variable v_check : STRING ( 4 downto 1) := (others => ' ');
variable v_operation : STRING ( 5 downto 1) := (others => ' ');
variable v_ack : STRING (16 downto 1) := (others => ' ');
begin
wait until rising_edge(s_scl_clk);
v_operation := operation;
v_ack := get_field(byte_type);
if sda_master_i = '1' then
v_check (4 downto 1) := "Fail";
write(v_line_buffer,string'(integer'image(test_id)&sep& v_check&sep&v_operation&sep&v_ack));
else
v_check (2 downto 1) := "OK";
write(v_line_buffer,string'(integer'image(test_id)&sep
& v_check &sep
& v_operation &sep
& v_ack));
end if;
writeline(s_file_handler, v_line_buffer);
wait until falling_edge(s_scl_clk);
end procedure;
procedure pause_I2C is
begin
wait for g_SCL_PERIOD/4;
s_sda_master_o <= '0';
wait until rising_edge(s_scl_clk);
wait for g_SCL_PERIOD/4;
s_sda_master_o <= '1';
s_active_link <= '1';
wait until falling_edge(s_scl_clk);
s_pause_done <= '1';
wait until rising_edge(tb_clk);
s_pause_done <= '0';
s_active_link <= '0';
end procedure;
begin
if start_i = '1' then
wait until rising_edge(s_scl_clk);
wait for g_SCL_PERIOD/4;
s_sda_master_o <= '0';
s_active_link <= '1';
wait until falling_edge(s_scl_clk);
wait until rising_edge(tb_clk);
s_start_done <= '1';
wait until rising_edge(tb_clk);
s_start_done <= '0';
elsif pause_i = '1' then
pause_I2C;
elsif write_i = '1' then
s_test_id <= s_test_id + 1;
v_write_data := order_write_data(wr_data_i);
--! 1.- Send [ADDRESS|0]
send_byte(i2c_addr_op_i);
check_ack(s_test_id, "WRITE", ADDRESS_0);
--! 2.- Send wishbone address high
send_byte(wishbone_addr_i(15 downto 8));
check_ack(s_test_id, "WRITE", WISHBONE_HIGH);
--! 3.- Send wishbone address low
send_byte(wishbone_addr_i(7 downto 0));
check_ack(s_test_id, "WRITE", WISHBONE_LOW);
--! 4.- Send DATA0
send_byte(wr_data_i(7 downto 0));
check_ack(s_test_id, "WRITE", DATA0);
--! 5.- Send DATA1
send_byte(wr_data_i(15 downto 8));
check_ack(s_test_id, "WRITE", DATA1);
--! 6.- Send DATA2
send_byte(wr_data_i(23 downto 16));
check_ack(s_test_id, "WRITE", DATA2);
--! 7.- Send DATA3
send_byte(wr_data_i(31 downto 24));
check_ack(s_test_id, "WRITE", DATA3);
pause_I2C;
elsif read_i = '1' then
end if;
wait until rising_edge(tb_clk);
end process;
end;
This diff is collapsed.
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