1 --------------------------------------------------------------------- 3 ---- WISHBONE revB2 I2C Master Core; bit-controller ---- 6 ---- Author: Richard Herveille ---- 7 ---- richard@asics.ws ---- 10 ---- Downloaded from: http://www.opencores.org/projects/i2c/ ---- 12 --------------------------------------------------------------------- 14 ---- Copyright (C) 2000 Richard Herveille ---- 15 ---- richard@asics.ws ---- 17 ---- This source file may be used and distributed without ---- 18 ---- restriction provided that this copyright statement is not ---- 19 ---- removed from the file and that any derivative work contains ---- 20 ---- the original copyright notice and the associated disclaimer.---- 22 ---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ---- 23 ---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ---- 24 ---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ---- 25 ---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ---- 26 ---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ---- 27 ---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ---- 28 ---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ---- 29 ---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ---- 30 ---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ---- 31 ---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ---- 32 ---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ---- 33 ---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ---- 34 ---- POSSIBILITY OF SUCH DAMAGE. ---- 36 --------------------------------------------------------------------- 40 -- $Id: i2c_master_bit_ctrl.vhd,v 1.14 2006/10/11 12:10:13 rherveille Exp $ 42 -- $Date: 2006/10/11 12:10:13 $ 44 -- $Author: rherveille $ 49 -- $Log: i2c_master_bit_ctrl.vhd,v $ 50 -- Revision 1.14 2006/10/11 12:10:13 rherveille 51 -- Added missing semicolons ';' on endif 53 -- Revision 1.13 2006/10/06 10:48:24 rherveille 54 -- fixed short scl high pulse after clock stretch 56 -- Revision 1.12 2004/05/07 11:53:31 rherveille 57 -- Fixed previous fix :) Made a variable vs signal mistake. 59 -- Revision 1.11 2004/05/07 11:04:00 rherveille 60 -- Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit. 62 -- Revision 1.10 2004/02/27 07:49:43 rherveille 63 -- Fixed a bug in the arbitration-lost signal generation. VHDL version only. 65 -- Revision 1.9 2003/08/12 14:48:37 rherveille 66 -- Forgot an 'end if' :-/ 68 -- Revision 1.8 2003/08/09 07:01:13 rherveille 69 -- Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. 70 -- Fixed a potential bug in the byte controller's host-acknowledge generation. 72 -- Revision 1.7 2003/02/05 00:06:02 rherveille 73 -- Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles. 75 -- Revision 1.6 2003/02/01 02:03:06 rherveille 76 -- Fixed a few 'arbitration lost' bugs. VHDL version only. 78 -- Revision 1.5 2002/12/26 16:05:47 rherveille 79 -- Core is now a Multimaster I2C controller. 81 -- Revision 1.4 2002/11/30 22:24:37 rherveille 84 -- Revision 1.3 2002/10/30 18:09:53 rherveille 85 -- Fixed some reported minor start/stop generation timing issuess. 87 -- Revision 1.2 2002/06/15 07:37:04 rherveille 88 -- Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment. 90 -- Revision 1.1 2001/11/05 12:02:33 rherveille 92 --! @ingroup protocols_i2c 93 -- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version. 94 -- Code updated, is now up-to-date to doc. rev.0.4. 97 -- Modified by Jan Andersson (jan@gaisler.com): 99 -- * Added two start states to fulfill Set-up time for 100 -- repeated START condition. 101 -- * Modified synchronization of SCL and SDA. START and STOP detection 102 -- is now performed after a two stage synchronizer and is also 104 -- * Changed evaluation order of 'slave_wait', 'en' and 'cnt' in 105 -- generation of clk_en signal to prevent clk_en assertion when 106 -- slave_wait is asserted. 107 -- * Needed to differentiate between slave clock stretching and master 108 -- clock synchronization. 109 -- * Added register s_state which contains the next state in case 110 -- of clock synchronization 111 -- * Incorporated change in wr_b state from SVN rev. 72 of 112 -- original OC version (delay check of SDA). 113 -- * Added 'filter' generic that determines length of filter. 114 -- Original OC core has a median filter implemented. The solution 115 -- implemented in this version is a plain shift register with a 116 -- length determined by the new generic. All samples in this 117 -- register must be equal, otherwise the SCL or SDA value used by 118 -- the core will not be changed. Every SCL/SDA transition that is 119 -- not stable for 'filter' system clock cycles is disregarded. 120 -- This solution is potentially more vulnerable against short 121 -- periods of relatively quick fluctuations on the line, however 122 -- it should do a better job of ignoring 50 ns pulses and still 123 -- allow us to respond quickly to events on the line - assuming 124 -- that the core has been correctly configured. 125 -- Core revision has been increased to 2 (in GRLIB PnP) 126 -- * Added 'dynfilt' generic to allow dynamic adjustment of the 127 -- filter. This component takes in a filt vector that is used to 128 -- reload a filter counter. The filt vector is assigned via the 129 -- core's APB interface. 130 -- Reorganized parts of the code, moving signals into blocks. 131 -- Core revision increased to 3. 133 ------------------------------------- 134 -- Bit controller section 135 ------------------------------------ 137 -- Translate simple commands into SCL/SDA transitions 138 -- Each command has 5 states, A/B/C/D/idle 140 -- start: SCL ~~~~~~~~~~~~~~\____ 141 -- SDA XX/~~~~~~~\______ 142 -- x | A | B | C | D | i 144 -- repstart SCL ______/~~~~~~~\___ 145 -- SDA __/~~~~~~~\______ 146 -- x | A | B | C | D | i 148 -- stop SCL _______/~~~~~~~~~~~ 149 -- SDA ==\___________/~~~~~ 150 -- x | A | B | C | D | i 152 --- write SCL ______/~~~~~~~\____ 153 -- SDA XXX===============XX 154 -- x | A | B | C | D | i 156 --- read SCL ______/~~~~~~~\____ 157 -- SDA XXXXXXX=XXXXXXXXXXX 158 -- x | A | B | C | D | i 161 -- Timing: Normal mode Fast mode 162 ----------------------------------------------------------------- 163 -- Fscl 100KHz 400KHz 164 -- Th_scl 4.0us 0.6us High period of SCL 165 -- Tl_scl 4.7us 1.3us Low period of SCL 166 -- Tsu:sta 4.7us 0.6us setup time for a repeated start condition 167 -- Tsu:sto 4.0us 0.6us setup time for a stop conditon 168 -- Tbuf 4.7us 1.3us Bus free time between a stop and start condition 182 ena : in ;
-- core enable signal 184 clk_cnt : in (15 downto 0);
-- clock prescale value 189 al : out ;
-- arbitration lost 197 scl_i : in ;
-- i2c clock line input 198 scl_o : out ;
-- i2c clock line output 199 scl_oen : out ;
-- i2c clock line output enable, active low 201 sda_o : out ;
-- i2c data line output 202 sda_oen : out -- i2c data line output enable, active low 204 end entity i2c_master_bit_ctrl;
213 type states is (idle, start_a, start_b, start_c, start_d, start_e, start_f, start_g, 214 stop_a, stop_b, stop_c, stop_d, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d);
218 signal sda_chk : ;
-- check SDA status (multi-master arbitration) 219 signal fSCL, fSDA : (1 downto 0);
-- Filtered SCL and SDA inputs 221 signal ial : ;
-- internal arbitration lost signal 222 signal cnt : (15 downto 0);
-- clock divider counter 223 signal csync : ;
-- Need to synchronize clock with other master 226 -- generate clk enable signal 230 cnt <= (others => '0');
232 elsif (clk'event and clk = '1') then 234 cnt <= (others => '0');
236 elsif (ena = '0' or csync = '1') then 242 elsif (cnt = X"0000") then 250 end process gen_clken;
253 -- generate bus status controller 254 bus_status_ctrl: block 258 signal ibusy : ;
-- internal busy signal 263 staticfilt : if dynfilt = 0 generate 265 constant FR : := filter;
-- Filter range MSb 266 constant DR : := filter + 1;
-- Delayed SCL/SDA range MSb 268 signal sSCL, sSDA : (FR downto 0);
-- synchronized SCL and SDA inputs 269 signal discl_oen : (DR downto 0);
-- delayed scl_oen signal 270 signal disda_oen : (DR downto 0);
-- delayed isda_oen 272 -- synchronize SCL and SDA inputs 276 sSCL <= (others => '1');
277 sSDA <= (others => '1');
278 fSCL <= (others => '1');
279 fSDA <= (others => '1');
280 elsif (clk'event and clk = '1') then 282 sSCL <= (others => '1');
283 sSDA <= (others => '1');
284 fSCL <= (others => '1');
285 fSDA <= (others => '1');
290 if andv(sSCL(FR downto 1)) = '1' then 292 elsif orv(sSCL(FR downto 1)) = '0' then 297 if andv(sSDA(FR downto 1)) = '1' then 299 elsif orv(sSDA(FR downto 1)) = '0' then 306 end process synch_SCL_SDA;
308 -- whenever the slave is not ready it can delay the cycle by pulling SCL low 312 if (clk'event and clk = '1') then 317 -- Keep SCL output enable values 319 -- Disable slave stretch detection when other device drives SCL 320 -- H->L (only a master should to this). 325 -- SCL forced low after master tried to assert, slave is stretching clock 327 -- SCL HIGH time cut short, master clock synchronization 330 -- generate arbitration lost signal 331 -- aribitration lost when: 332 -- 1) master drives SDA high, but the i2c bus is low 333 -- 2) stop detected while not requested (detect during 'idle' state) 340 elsif (clk'event and clk = '1') then 365 end generate staticfilt;
368 dynamicfilt : if dynfilt /= 0 generate 372 signal sSCL, sSDA : (1 downto 0);
-- synchronized SCL and SDA inputs 373 signal fiscl_oen : (1 downto 0);
-- "filtered" scl_oen signal 374 signal fisda_oen : ;
-- "filtered" sda_oen signal 376 signal discl_oen : ;
-- delayed scl_oen signal 377 signal disda_oen : ;
-- delayed sda_oen signal 379 -- Provides filtered signals for SCL and SDA, and corresponding 380 -- output enable signals. 382 variable scl_chg, sda_chg, iscl_oen_chg, isda_oen_chg : ;
388 fSCL <= (others => '1');
fSDA <= (others => '1');
392 elsif (clk'event and clk = '1') then 393 if (rst = '1') or (ena = '0') then 395 fSCL <= (others => '1');
fSDA <= (others => '1');
400 if (sSCL(1) xor fSCL(0)) = '0' then scl_chg := '0';
end if;
401 if (sSDA(1) xor fSDA(0)) = '0' then sda_chg := '0';
end if;
426 end process sync_SCL_SDA;
428 -- whenever the slave is not ready it can delay the cycle by pulling SCL low 432 if (clk'event and clk = '1') then 437 -- Keep SCL output enable values 439 -- Disable slave stretch detection when other device drives SCL 440 -- H->L (only a master should to this). 445 -- SCL forced low after master tried to assert, slave is stretching clock 447 -- SCL HIGH time cut short, master clock synchronization 450 -- generate arbitration lost signal 451 -- aribitration lost when: 452 -- 1) master drives SDA high, but the i2c bus is low 453 -- 2) stop detected while not requested (detect during 'idle' state) 460 elsif (clk'event and clk = '1') then 484 end generate dynamicfilt;
488 -- detect start condition => detect falling edge on SDA while SCL is high 489 -- detect stop condition => detect rising edge on SDA while SCL is high 495 elsif (clk'event and clk = '1') then 512 end process detect_sta_sto;
514 -- generate i2c-bus busy signal 519 elsif (clk'event and clk = '1') then 526 end process gen_busy;
529 -- generate dout signal, store dout on rising edge of SCL 532 if (clk'event and clk = '1') then 537 end process gen_dout;
538 end block bus_status_ctrl;
541 -- generate statemachine 551 elsif (clk'event and clk = '1') then 552 if (rst = '1' or ial = '1') then 558 elsif csync = '1' then 562 cmd_ack <= '0';
-- default no acknowledge 564 -- csync is always '0' here, but including it in the expression 565 -- appears to let some compilers optimize the design more... 580 when others => c_state <= idle;
-- NOP command 586 sda_chk <= '0';
-- don't check SDA 593 sda_chk <= '0';
-- don't check SDA 599 sda_chk <= '0';
-- don't check SDA 605 sda_chk <= '0';
-- don't check SDA 611 sda_chk <= '0';
-- don't check SDA 617 sda_chk <= '0';
-- don't check SDA 623 sda_chk <= '0';
-- don't check SDA 627 cmd_ack <= '1';
-- command completed 630 sda_chk <= '0';
-- don't check SDA 638 sda_chk <= '0';
-- don't check SDA 644 sda_chk <= '0';
-- don't check SDA 650 sda_chk <= '0';
-- don't check SDA 654 cmd_ack <= '1';
-- command completed 657 sda_chk <= '0';
-- don't check SDA 665 sda_chk <= '0';
-- don't check SDA 671 sda_chk <= '0';
-- don't check SDA 677 sda_chk <= '0';
-- don't check SDA 681 cmd_ack <= '1';
-- command completed 684 sda_chk <= '0';
-- don't check SDA 692 sda_chk <= '0';
-- don't check SDA (SCL low) 698 sda_chk <= '0';
-- don't check SDA (allow signals to settle) 708 cmd_ack <= '1';
-- command completed 711 sda_chk <= '0';
-- don't check SDA (SCL low) 720 end process nxt_state_decoder;
728 end architecture structural;
std_logic_vector( 3 downto 0) := "0000" I2C_CMD_NOP
std_logic_vector( DR downto 0) discl_oen
std_logic_vector( filter- 1 downto 0) filtcnt
std_logic_vector( 15 downto 0) cnt
std_logic_vector( 1 downto 0) fiscl_oen
std_logic_vector( 3 downto 0) := "0010" I2C_CMD_STOP
std_logic_vector( 1 downto 0) fSCL
std_logic_vector( DR downto 0) disda_oen
std_logic_vector( FR downto 0) sSDA
std_logic_vector( 3 downto 0) := "1000" I2C_CMD_WRITE
(idle,start_a,start_b,start_c,start_d,start_e,start_f,start_g,stop_a,stop_b,stop_c,stop_d,rd_a,rd_b,rd_c,rd_d,wr_a,wr_b,wr_c,wr_d) states
in clk_cntstd_logic_vector( 15 downto 0)
in filtstd_logic_vector(( filter- 1)* dynfilt downto 0)
std_logic_vector( 3 downto 0) := "0001" I2C_CMD_START
std_logic_vector( 1 downto 0) fSDA
std_logic_vector( 3 downto 0) := "0100" I2C_CMD_READ
in cmdstd_logic_vector( 3 downto 0)
std_logic_vector( FR downto 0) sSCL