1 ------------------------------------------------------------------------------ 2 -- This file is a part of the GRLIB VHDL IP LIBRARY 3 -- Copyright (C) 2003 - 2008, Gaisler Research 4 -- Copyright (C) 2008 - 2012, Aeroflex Gaisler 6 -- This program is free software; you can redistribute it and/or modify 7 -- it under the terms of the GNU General Public License as published by 8 -- the Free Software Foundation; either version 2 of the License, or 9 -- (at your option) any later version. 11 -- This program is distributed in the hope that it will be useful, 12 -- but WITHOUT ANY WARRANTY; without even the implied warranty of 13 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 -- GNU General Public License for more details. 16 -- You should have received a copy of the GNU General Public License 17 -- along with this program; if not, write to the Free Software 18 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 ------------------------------------------------------------------------------- 22 -- Author: Jan Andersson - Gaisler Research 25 -- Documentation of generics: 28 -- Support for ten bit addresses. 31 -- The slave's i2c address. 33 -- [OUTPUT_EN_POLARITY_G] 34 -- Output enable polarity 37 -- Length of filters used on SCL and SDA. 38 -- This generic should specify, in number of system clock cycles plus one, 39 -- the time of the shortest pulse on the I2C bus to be registered as a valid 40 -- value. For instance, to disregard any pulse that is 50 ns or shorter in 41 -- a system with a system frequency of 54 MHz this generic should be set to: 42 -- ((pulse time) / (clock period)) + 1 = (50 ns) / ((1/(54 MHz)) + 1 = 3.7 43 -- The value from this calculation should always be rounded up. 44 -- In other words an appropriate filter length for a 54 MHz system is 4. 46 -- The slave has four different modes operation. The mode is defined by the 47 -- value of the bits RMODE and TMODE. 48 -- RMODE TMODE I2CSLAVE Mode 55 -- The slave accepts one byte and NAKs all other transfers until software has 56 -- acknowledged the received byte. 58 -- The slave accepts one byte and keeps SCL low until software has acknowledged 61 -- The slave transmits the same byte to all if the master requests more than 62 -- one byte in the transfer. The slave then NAKs all read requests unless the 63 -- Transmit Always Valid (TAV) bit in the control register is set. 65 -- The slave transmits one byte and then keeps SCL low until software has 66 -- acknowledged that the byte has been transmitted. 67 ---------------------------------------------------------------------------------------------------- 68 -- Modified by Benjamin Reese <bareese@slac.stanford.edu> 69 -- Removed APB interface and replaced with generic IO. 73 use ieee.std_logic_1164.
all;
81 --! @ingroup protocols_i2c 94 sRst : in := '0';
-- Synchronous Reset - active high 95 aRst : in := '0';
-- Asynchronous Reset - active high 107 ----------------------------------------------------------------------------- 109 ----------------------------------------------------------------------------- 110 -- Core configuration 111 constant I2C_ADDR_LEN_C : := 7 + TENBIT_G*3;
112 constant I2C_SLAVE_ADDR_C : ((I2C_ADDR_LEN_C-1) downto 0) := 113 conv_std_logic_vector(I2C_ADDR_G, I2C_ADDR_LEN_C);
116 constant I2C_READ_C : := '1';
-- R/Wn bit 117 constant I2C_WRITE_C : := '0';
121 constant I2C_LOW_C : := OEPOL_LEVEL_C;
-- OE 122 constant I2C_HIZ_C : := not OEPOL_LEVEL_C;
124 constant I2C_ACK_C : := '0';
126 constant TENBIT_ADDR_START_C : (4 downto 0) := "11110";
128 ----------------------------------------------------------------------------- 130 ----------------------------------------------------------------------------- 133 type slv_state_type is (idle, checkaddr, check10bitaddr, sclhold, 134 movebyte, handshake);
136 type i2cslv_reg_type is record 137 slvstate : slv_state_type;
141 -- transmit : boolean; 142 -- receive : boolean; 146 -- Synchronizers for inputs SCL and SDA 153 -- Registered Outputs 157 constant REG_INIT_C : i2cslv_reg_type := ( 161 sreg => (others => '0'), 162 cnt => (others => '0'), 170 ----------------------------------------------------------------------------- 172 ----------------------------------------------------------------------------- 173 -- purpose: Compares the first byte of a received address with the slave's 174 -- address. The tba input determines if the slave is using a ten bit address. 175 function compaddr1stb (
176 ibyte : (
7 downto 0))
-- I2C byte 179 variable correct : (7 downto 1);
180 begin -- compaddr1stb 182 correct(7 downto 3) := TENBIT_ADDR_START_C;
183 correct(2 downto 1) := I2C_SLAVE_ADDR_C((I2C_ADDR_LEN_C-1) downto (I2C_ADDR_LEN_C-2));
185 correct(7 downto 1) := I2C_SLAVE_ADDR_C(6 downto 0);
187 return ibyte(7 downto 1) = correct(7 downto 1);
190 -- purpose: Compares the 2nd byte of a ten bit address with the slave address 191 function compaddr2ndb (
192 ibyte : (
7 downto 0))
-- I2C byte 194 begin -- compaddr2ndb 195 return ibyte((I2C_ADDR_LEN_C-3) downto 0) = I2C_SLAVE_ADDR_C((I2C_ADDR_LEN_C-3) downto 0);
198 ----------------------------------------------------------------------------- 200 ----------------------------------------------------------------------------- 202 -- Register interface 203 signal r : i2cslv_reg_type := REG_INIT_C;
204 signal rin : i2cslv_reg_type;
209 variable v : i2cslv_reg_type;
210 variable sclfilt : (FILTER_G-1 downto 0);
211 variable sdafilt : (FILTER_G-1 downto 0);
212 begin -- process comb 217 ---------------------------------------------------------------------------- 219 ---------------------------------------------------------------------------- 223 if andv(sclfilt) = '1' then v.scl := '1';
end if;
224 if orv(sclfilt) = '0' then v.scl := '0';
end if;
225 if andv(sdafilt) = '1' then v.sda := '1';
end if;
226 if orv(sdafilt) = '0' then v.sda := '0';
end if;
228 -- txAck pulsed for 1 clock only when set by state machine below. 231 -- Reset rxValid when ack'd from IO 236 --------------------------------------------------------------------------- 237 -- I2C slave control FSM 238 --------------------------------------------------------------------------- 242 if (r.scl and not v.scl) = '1' then 247 if compaddr1stb(r.sreg) then 248 if r.sreg(0) = I2C_READ_C then 253 v.slvstate := handshake;
255 -- No data to transmit, NAK 260 -- Ten bit address with R/Wn = 1 and slave not previously 266 v.slvstate := handshake;
269 -- Slave address did not match 275 when check10bitaddr => 276 if compaddr2ndb(r.sreg) then 277 -- Slave has been addressed with a matching 10 bit address 278 -- If we receive a repeated start condition, matching address 279 -- and R/Wn = 1 we will transmit data. Without start condition we 280 -- will receive data. 284 v.slvstate := handshake;
290 -- This state is used when the device has been addressed to see if SCL 291 -- should be kept low until the receive register is free or the 292 -- transmit register is filled. It is also used when a data byte has 293 -- been transmitted or received to SCL low until software acknowledges 295 if (r.scl and not v.scl) = '1' then 299 -- Ack has happened and rxValid set back to '0' 302 v.slvstate := movebyte;
304 -- Falling edge that should be detected in movebyte may have passed 306 v.sdaoen := r.sreg(7) xor OEPOL_LEVEL_C;
312 if (r.scl and not v.scl) = '1' then 314 v.sdaoen := r.sreg(7) xor OEPOL_LEVEL_C;
319 if (not r.scl and v.scl) = '1' then 320 v.sreg := r.sreg(6 downto 0) & r.sda;
321 if r.cnt = "111" then 323 v.slvstate := checkaddr;
325 v.slvstate := check10bitaddr;
327 v.slvstate := handshake;
329 v.cnt := (others => '0');
337 if (r.scl and not v.scl) = '1' then 341 -- Receive, send ACK/NAK 342 -- Acknowledge byte if core has room in receive register 343 -- This code assumes that the core's receive register is free if we are 344 -- in RMODE 1. This should always be the case unless software has 345 -- reconfigured the core during operation. 351 -- NAK the byte, the master must abort the transfer 356 -- Transmit, release bus 358 -- Byte transmitted, ack it. 366 if (not r.scl and v.scl) = '1' then 368 v.slvstate := movebyte;
371 -- RMODE 0: Be ready to accept one more byte which will be NAK'd if 372 -- software has not read the receive register 373 -- RMODE 1: Keep SCL low until software has acknowledged received byte 375 v.slvstate := movebyte;
377 v.slvstate := sclhold;
380 -- Transmit, check ACK/NAK from master 381 -- If the master NAKs the transmitted byte the transfer has ended and 382 -- we should wait for the master's next action. If the master ACKs the 383 -- byte the core will act depending on tmode: 385 -- If the master ACKs the byte we must continue to transmit and will 386 -- transmit the same byte on all requests. 388 -- IF the master ACKs the byte we will keep SCL low until software has 389 -- put new transmit data into the transmit register. 390 if r.sda = I2C_ACK_C then 392 v.slvstate := movebyte;
394 v.slvstate := sclhold;
415 -- START or repeated START condition 417 v.slvstate := movebyte;
418 v.cnt := (others => '0');
425 ---------------------------------------------------------------------------- 426 -- Reset and idle operation 427 ---------------------------------------------------------------------------- 435 v.sreg := (others => '0');
436 v.cnt := (others => '0');
439 v.o.rxData := (others => '0');
446 ---------------------------------------------------------------------------- 447 -- Signal assignments 448 ---------------------------------------------------------------------------- 465 r.slvstate <= idle after TPD_G;
467 r.active <= false after TPD_G;
470 r.sreg <= (others => '0') after TPD_G;
471 r.cnt <= (others => '0') after TPD_G;
478 elsif rising_edge(clk) then 479 r <= rin after TPD_G;
484 end architecture rtl;
I2C_ADDR_Ginteger range 0 to 1023:= 0
RMODE_Ginteger range 0 to 1:= 0
TMODE_Ginteger range 0 to 1:= 0
FILTER_Ginteger range 2 to 512:= 4
I2cSlaveOutType :=(rxActive => '0',rxValid => '0',rxData =>( others => '0'),txActive => '0',txAck => '0',nack => '0') I2C_SLAVE_OUT_INIT_C
OUTPUT_EN_POLARITY_Ginteger range 0 to 1:= 0
in i2cSlaveInI2cSlaveInType
array(natural range <> ) of i2c_in_type i2c_in_array
TENBIT_Ginteger range 0 to 1:= 0
out i2cSlaveOutI2cSlaveOutType