OpenCores
URL https://opencores.org/ocsvn/i2c/i2c/trunk

Subversion Repositories i2c

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 30 to Rev 31
    Reverse comparison

Rev 30 → Rev 31

/trunk/rtl/vhdl/i2c_master_byte_ctrl.vhd
37,10 → 37,10
 
-- CVS Log
--
-- $Id: i2c_master_byte_ctrl.vhd,v 1.2 2002-11-30 22:24:37 rherveille Exp $
-- $Id: i2c_master_byte_ctrl.vhd,v 1.3 2002-12-26 16:05:47 rherveille Exp $
--
-- $Date: 2002-11-30 22:24:37 $
-- $Revision: 1.2 $
-- $Date: 2002-12-26 16:05:47 $
-- $Revision: 1.3 $
-- $Author: rherveille $
-- $Locker: $
-- $State: Exp $
47,6 → 47,9
--
-- Change History:
-- $Log: not supported by cvs2svn $
-- Revision 1.2 2002/11/30 22:24:37 rherveille
-- Cleaned up code
--
-- Revision 1.1 2001/11/05 12:02:33 rherveille
-- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version.
-- Code updated, is now up-to-date to doc. rev.0.4.
83,9 → 86,10
din : in std_logic_vector(7 downto 0);
 
-- output signals
cmd_ack : out std_logic;
cmd_ack : out std_logic; -- command done
ack_out : out std_logic;
i2c_busy : out std_logic;
i2c_busy : out std_logic; -- arbitration lost
i2c_al : out std_logic; -- i2c bus busy
dout : out std_logic_vector(7 downto 0);
 
-- i2c lines
109,8 → 113,9
clk_cnt : in unsigned(15 downto 0); -- clock prescale value
 
cmd : in std_logic_vector(3 downto 0);
cmd_ack : out std_logic;
busy : out std_logic;
cmd_ack : out std_logic; -- command done
busy : out std_logic; -- i2c bus busy
al : out std_logic; -- arbitration lost
 
din : in std_logic;
dout : out std_logic;
135,6 → 140,7
-- signals for bit_controller
signal core_cmd : std_logic_vector(3 downto 0);
signal core_ack, core_txd, core_rxd : std_logic;
signal al : std_logic;
 
-- signals for shift register
signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
147,7 → 153,7
 
begin
-- hookup bit_controller
u1: i2c_master_bit_ctrl port map(
bit_ctrl: i2c_master_bit_ctrl port map(
clk => clk,
rst => rst,
nReset => nReset,
156,6 → 162,7
cmd => core_cmd,
cmd_ack => core_ack,
busy => i2c_busy,
al => al,
din => core_txd,
dout => core_rxd,
scl_i => scl_i,
165,6 → 172,7
sda_o => sda_o,
sda_oen => sda_oen
);
i2c_al <= al;
 
-- generate host-command-acknowledge
cmd_ack <= host_ack;
230,7 → 238,7
c_state <= st_idle;
ack_out <= '0';
elsif (clk'event and clk = '1') then
if (rst = '1') then
if (rst = '1' or al = '1') then
core_cmd <= I2C_CMD_NOP;
core_txd <= '0';
shift <= '0';
/trunk/rtl/vhdl/i2c_master_bit_ctrl.vhd
37,10 → 37,10
 
-- CVS Log
--
-- $Id: i2c_master_bit_ctrl.vhd,v 1.4 2002-11-30 22:24:37 rherveille Exp $
-- $Id: i2c_master_bit_ctrl.vhd,v 1.5 2002-12-26 16:05:47 rherveille Exp $
--
-- $Date: 2002-11-30 22:24:37 $
-- $Revision: 1.4 $
-- $Date: 2002-12-26 16:05:47 $
-- $Revision: 1.5 $
-- $Author: rherveille $
-- $Locker: $
-- $State: Exp $
47,6 → 47,9
--
-- Change History:
-- $Log: not supported by cvs2svn $
-- Revision 1.4 2002/11/30 22:24:37 rherveille
-- Cleaned up code
--
-- Revision 1.3 2002/10/30 18:09:53 rherveille
-- Fixed some reported minor start/stop generation timing issuess.
--
68,25 → 71,25
-- Translate simple commands into SCL/SDA transitions
-- Each command has 5 states, A/B/C/D/idle
--
-- start: SCL ~~~~~~~~~~\____
-- SDA ~~~~~~~~\______
-- x | A | B | C | D | i
-- start: SCL ~~~~~~~~~~~~~~\____
-- SDA XX/~~~~~~~\______
-- x | A | B | C | D | i
--
-- repstart SCL ____/~~~~\___
-- SDA __/~~~\______
-- x | A | B | C | D | i
-- repstart SCL ______/~~~~~~~\___
-- SDA __/~~~~~~~\______
-- x | A | B | C | D | i
--
-- stop SCL ____/~~~~~~~~
-- SDA ==\____/~~~~~
-- x | A | B | C | D | i
-- stop SCL _______/~~~~~~~~~~~
-- SDA ==\___________/~~~~~
-- x | A | B | C | D | i
--
--- write SCL ____/~~~~\____
-- SDA ==X=========X=
-- x | A | B | C | D | i
--- write SCL ______/~~~~~~~\____
-- SDA XXX===============XX
-- x | A | B | C | D | i
--
--- read SCL ____/~~~~\____
-- SDA XXXX=====XXXX
-- x | A | B | C | D | i
--- read SCL ______/~~~~~~~\____
-- SDA XXXXXXX=XXXXXXXXXXX
-- x | A | B | C | D | i
--
 
-- Timing: Normal mode Fast mode
113,8 → 116,9
clk_cnt : in unsigned(15 downto 0); -- clock prescale value
 
cmd : in std_logic_vector(3 downto 0);
cmd_ack : out std_logic;
busy : out std_logic;
cmd_ack : out std_logic; -- command completed
busy : out std_logic; -- i2c bus busy
al : out std_logic; -- arbitration lost
 
din : in std_logic;
dout : out std_logic;
141,23 → 145,15
signal c_state : states;
 
signal iscl_oen, isda_oen : std_logic; -- internal I2C lines
signal sda_chk : std_logic; -- check SDA status (multi-master arbitration)
signal dscl_oen : std_logic; -- delayed scl_oen signals
signal sSCL, sSDA : std_logic; -- synchronized SCL and SDA inputs
signal dscl_oen : std_logic; -- delayed scl_oen signals
 
signal clk_en, slave_wait :std_logic; -- clock generation signals
-- signal cnt : unsigned(15 downto 0) := clk_cnt; -- clock divider counter (simulation)
signal cnt : unsigned(15 downto 0); -- clock divider counter (synthesis)
 
begin
-- synchronize SCL and SDA inputs
synch_scl_sda: process(clk)
begin
if (clk'event and clk = '1') then
sSCL <= scl_i;
sSDA <= sda_i;
end if;
end process synch_SCL_SDA;
 
-- whenever the slave is not ready it can delay the cycle by pulling SCL low
-- delay scl_oen
process (clk)
begin
165,8 → 161,6
dscl_oen <= iscl_oen;
end if;
end process;
 
-- whenever the slave is not ready it can delay the cycle by pulling SCL low
slave_wait <= dscl_oen and not sSCL;
 
-- generate clk enable signal
181,8 → 175,13
clk_en <= '1';
else
if ( (cnt = 0) or (ena = '0') ) then
clk_en <= '1';
cnt <= clk_cnt;
if (slave_wait = '0') then
cnt <= clk_cnt;
clk_en <= '1';
else
cnt <= cnt;
clk_en <= '0';
end if;
else
if (slave_wait = '0') then
cnt <= cnt -1;
196,25 → 195,35
 
-- generate bus status controller
bus_status_ctrl: block
signal dSDA : std_logic;
signal sta_condition : std_logic;
signal sto_condition : std_logic;
signal dSCL, dSDA : std_logic; -- delayes sSCL and sSDA
signal sta_condition : std_logic; -- start detected
signal sto_condition : std_logic; -- stop detected
signal cmd_stop, dcmd_stop : std_logic; -- STOP command
signal ibusy : std_logic; -- internal busy signal
begin
-- synchronize SCL and SDA inputs
synch_scl_sda: process(clk)
begin
if (clk'event and clk = '1') then
sSCL <= scl_i;
sSDA <= sda_i;
 
signal ibusy : std_logic;
begin
dSCL <= sSCL;
dSDA <= sSDA;
end if;
end process synch_SCL_SDA;
 
-- detect start condition => detect falling edge on SDA while SCL is high
-- detect stop condition => detect rising edge on SDA while SCL is high
detect_sta_sto: process(clk)
begin
if (clk'event and clk = '1') then
dSDA <= sSDA; -- generate a delayed version of sSDA
 
sta_condition <= (not sSDA and dSDA) and sSCL;
sto_condition <= (sSDA and not dSDA) and sSCL;
end if;
end process detect_sta_sto;
 
-- generate bus busy signal
-- generate i2c-bus busy signal
gen_busy: process(clk, nReset)
begin
if (nReset = '0') then
227,9 → 236,33
end if;
end if;
end process gen_busy;
busy <= ibusy;
 
-- assign output
busy <= ibusy;
 
-- generate arbitration lost signal
gen_al: process(clk)
begin
if (clk'event and clk = '1') then
if (cmd = I2C_CMD_STOP) then
cmd_stop <= '1';
else
cmd_stop <= '0';
end if;
dcmd_stop <= cmd_stop;
 
al <= (sda_chk and not sSDA and isda_oen) or (sto_condition and not dcmd_stop);
end if;
end process gen_al;
-- generate dout signal, store dout on rising edge of SCL
gen_dout: process(clk)
begin
if (clk'event and clk = '1') then
if (sSCL = '1' and dSCL = '0') then
dout <= sSDA;
end if;
end if;
end process gen_dout;
end block bus_status_ctrl;
 
 
239,16 → 272,16
if (nReset = '0') then
c_state <= idle;
cmd_ack <= '0';
dout <= '0';
iscl_oen <= '1';
isda_oen <= '1';
sda_chk <= '0';
elsif (clk'event and clk = '1') then
if (rst = '1') then
c_state <= idle;
cmd_ack <= '0';
dout <= '0';
iscl_oen <= '1';
isda_oen <= '1';
sda_chk <= '0';
else
cmd_ack <= '0'; -- default no acknowledge
 
266,6 → 299,7
 
iscl_oen <= iscl_oen; -- keep SCL in same state
isda_oen <= isda_oen; -- keep SDA in same state
sda_chk <= '0'; -- don't check SDA
 
-- start
when start_a =>
272,21 → 306,25
c_state <= start_b;
iscl_oen <= iscl_oen; -- keep SCL in same state (for repeated start)
isda_oen <= '1'; -- set SDA high
sda_chk <= '0'; -- don't check SDA
 
when start_b =>
c_state <= start_c;
iscl_oen <= '1'; -- set SCL high
isda_oen <= '1'; -- keep SDA high
sda_chk <= '0'; -- don't check SDA
 
when start_c =>
c_state <= start_d;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '0'; -- set SDA low
sda_chk <= '0'; -- don't check SDA
 
when start_d =>
c_state <= start_e;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '0'; -- keep SDA low
sda_chk <= '0'; -- don't check SDA
 
when start_e =>
c_state <= idle;
293,22 → 331,26
cmd_ack <= '1'; -- command completed
iscl_oen <= '0'; -- set SCL low
isda_oen <= '0'; -- keep SDA low
sda_chk <= '0'; -- don't check SDA
 
-- stop
when stop_a =>
c_state <= stop_b;
iscl_oen <= '0'; -- keep SCL disabled
iscl_oen <= '0'; -- keep SCL low
isda_oen <= '0'; -- set SDA low
sda_chk <= '0'; -- don't check SDA
 
when stop_b =>
c_state <= stop_c;
iscl_oen <= '1'; -- set SCL high
isda_oen <= '0'; -- keep SDA low
sda_chk <= '0'; -- don't check SDA
 
when stop_c =>
c_state <= stop_d;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '0'; -- keep SDA low
sda_chk <= '0'; -- don't check SDA
 
when stop_d =>
c_state <= idle;
315,6 → 357,7
cmd_ack <= '1'; -- command completed
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '1'; -- set SDA high
sda_chk <= '0'; -- don't check SDA
 
-- read
when rd_a =>
321,17 → 364,19
c_state <= rd_b;
iscl_oen <= '0'; -- keep SCL low
isda_oen <= '1'; -- tri-state SDA
sda_chk <= '0'; -- don't check SDA
 
when rd_b =>
c_state <= rd_c;
iscl_oen <= '1'; -- set SCL high
isda_oen <= '1'; -- tri-state SDA
sda_chk <= '0'; -- don't check SDA
 
when rd_c =>
c_state <= rd_d;
dout <= sSDA;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= '1'; -- tri-state SDA
sda_chk <= '0'; -- don't check SDA
 
when rd_d =>
c_state <= idle;
338,6 → 383,7
cmd_ack <= '1'; -- command completed
iscl_oen <= '0'; -- set SCL low
isda_oen <= '1'; -- tri-state SDA
sda_chk <= '0'; -- don't check SDA
 
-- write
when wr_a =>
344,16 → 390,19
c_state <= wr_b;
iscl_oen <= '0'; -- keep SCL low
isda_oen <= din; -- set SDA
sda_chk <= '0'; -- don't check SDA (SCL low)
 
when wr_b =>
c_state <= wr_c;
iscl_oen <= '1'; -- set SCL high
isda_oen <= din; -- keep SDA
sda_chk <= '1'; -- check SDA
 
when wr_c =>
c_state <= wr_d;
iscl_oen <= '1'; -- keep SCL high
isda_oen <= din; -- keep SDA
sda_chk <= '1'; -- check SDA
 
when wr_d =>
c_state <= idle;
360,6 → 409,7
cmd_ack <= '1'; -- command completed
iscl_oen <= '0'; -- set SCL low
isda_oen <= din; -- keep SDA
sda_chk <= '0'; -- don't check SDA (SCL low)
 
when others =>
 
/trunk/rtl/vhdl/i2c_master_top.vhd
37,10 → 37,10
 
-- CVS Log
--
-- $Id: i2c_master_top.vhd,v 1.3 2002-11-30 22:24:37 rherveille Exp $
-- $Id: i2c_master_top.vhd,v 1.4 2002-12-26 16:05:47 rherveille Exp $
--
-- $Date: 2002-11-30 22:24:37 $
-- $Revision: 1.3 $
-- $Date: 2002-12-26 16:05:47 $
-- $Revision: 1.4 $
-- $Author: rherveille $
-- $Locker: $
-- $State: Exp $
47,6 → 47,9
--
-- Change History:
-- $Log: not supported by cvs2svn $
-- Revision 1.3 2002/11/30 22:24:37 rherveille
-- Cleaned up code
--
-- Revision 1.2 2001/11/10 10:52:44 rherveille
-- Changed PRER reset value from 0x0000 to 0xffff, conform specs.
--
106,6 → 109,7
cmd_ack : out std_logic;
ack_out : out std_logic;
i2c_busy : out std_logic;
i2c_al : out std_logic;
dout : out std_logic_vector(7 downto 0);
 
-- i2c lines
129,6 → 133,9
-- internal reset signal
signal rst_i : std_logic;
 
-- wishbone write access
signal wb_wacc : std_logic;
 
-- internal acknowledge signal
signal iack_o : std_logic;
 
138,15 → 145,15
-- command register signals
signal sta, sto, rd, wr, ack, iack : std_logic;
 
-- core enable signal
signal core_en : std_logic;
signal ien : std_logic;
signal core_en : std_logic; -- core enable signal
signal ien : std_logic; -- interrupt enable signal
 
-- status register signals
signal irxack, rxack : std_logic; -- received aknowledge from slave
signal tip : std_logic; -- transfer in progress
signal irq_flag : std_logic; -- interrupt pending flag
signal i2c_busy : std_logic; -- bus busy (start signal detected)
signal tip : std_logic; -- transfer in progress
signal irq_flag : std_logic; -- interrupt pending flag
signal i2c_busy : std_logic; -- i2c bus busy (start signal detected)
signal i2c_al, al : std_logic; -- arbitration lost
 
begin
-- generate internal reset signal
159,10 → 166,12
iack_o <= wb_cyc_i and wb_stb_i and not iack_o; -- because timing is always honored
end if;
end process gen_ack_o;
 
wb_ack_o <= iack_o;
-- generate wishbone write access signal
wb_wacc <= wb_cyc_i and wb_stb_i and wb_we_i;
 
 
-- assign wb_dat_o
assign_dato : process(wb_clk_i)
begin
186,58 → 195,63
end process assign_dato;
 
 
-- registers block
regs_block: process(rst_i, wb_clk_i)
-- generate registers (CR, SR see below)
gen_regs: process(rst_i, wb_clk_i)
begin
if (rst_i = '0') then
prer <= (others => '1');
ctr <= (others => '0');
txr <= (others => '0');
cr <= (others => '0');
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
prer <= (others => '1');
ctr <= (others => '0');
txr <= (others => '0');
cr <= (others => '0');
else
if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_we_i = '1') then
if (wb_adr_i(2) = '0') then
case wb_adr_i(1 downto 0) is
when "00" => prer( 7 downto 0) <= unsigned(wb_dat_i);
when "01" => prer(15 downto 8) <= unsigned(wb_dat_i);
when "10" => ctr <= wb_dat_i;
when "11" => txr <= wb_dat_i;
elsif (wb_wacc = '1') then
case wb_adr_i is
when "000" => prer( 7 downto 0) <= unsigned(wb_dat_i);
when "001" => prer(15 downto 8) <= unsigned(wb_dat_i);
when "010" => ctr <= wb_dat_i;
when "011" => txr <= wb_dat_i;
 
-- illegal cases, for simulation only
when others =>
report ("Illegal write address, setting all registers to unknown.");
prer <= (others => 'X');
ctr <= (others => 'X');
txr <= (others => 'X');
end case;
elsif ( (core_en = '1') and (wb_adr_i(1 downto 0) = 0) ) then
-- only take new commands when i2c ore enabled
-- pending commands are finished
cr <= wb_dat_i;
end if;
else
-- clear command bits when done
if (done = '1') then
cr(7 downto 4) <= (others => '0');
end if;
-- illegal cases, for simulation only
when others =>
report ("Illegal write address, setting all registers to unknown.");
prer <= (others => 'X');
ctr <= (others => 'X');
txr <= (others => 'X');
end case;
end if;
end if;
end process gen_regs;
 
-- reserved bits
cr(2 downto 1) <= (others => '0');
 
-- clear iack when irq_flag cleared
cr(0) <= cr(0) and irq_flag;
end if;
-- generate command register
gen_cr: process(rst_i, wb_clk_i)
begin
if (rst_i = '0') then
cr <= (others => '0');
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
cr <= (others => '0');
elsif (wb_wacc = '1') then
if ( (core_en = '1') and (wb_adr_i = 4) ) then
-- only take new commands when i2c core enabled
-- pending commands are finished
cr <= wb_dat_i;
end if;
else
if (done = '1' or i2c_al = '1') then
cr(7 downto 4) <= (others => '0'); -- clear command bits when command done
-- or arbitration lost
end if;
 
cr(2 downto 1) <= (others => '0'); -- reserved bits, always '0'
cr(0) <= '0'; -- clear IRQ_ACK bit
end if;
end if;
end process regs_block;
end process gen_cr;
 
 
-- decode command register
sta <= cr(7);
sto <= cr(6);
251,7 → 265,7
ien <= ctr(6);
 
-- hookup byte controller block
u1: i2c_master_byte_ctrl port map (
byte_ctrl: i2c_master_byte_ctrl port map (
clk => wb_clk_i,
rst => wb_rst_i,
nReset => rst_i,
263,6 → 277,7
write => wr,
ack_in => ack,
i2c_busy => i2c_busy,
i2c_al => i2c_al,
din => txr,
cmd_ack => done,
ack_out => irxack,
283,20 → 298,23
gen_sr_bits: process (wb_clk_i, rst_i)
begin
if (rst_i = '0') then
al <= '0';
rxack <= '0';
tip <= '0';
irq_flag <= '0';
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
al <= '0';
rxack <= '0';
tip <= '0';
irq_flag <= '0';
else
al <= i2c_al or (al and not sta);
rxack <= irxack;
tip <= (rd or wr);
 
-- interrupt request flag is always generated
irq_flag <= (done or irq_flag) and not iack;
irq_flag <= (done or i2c_al or irq_flag) and not iack;
end if;
end if;
end process gen_sr_bits;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.