123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- //////////////////////////////////////////////////////////////////////
- //// ////
- //// i2cSlave.v ////
- //// ////
- //// This file is part of the i2cSlave opencores effort.
- //// <http://www.opencores.org/cores//> ////
- //// ////
- //// Module Description: ////
- //// You will need to modify this file to implement your
- //// interface.
- //// ////
- //// To Do: ////
- ////
- //// ////
- //// Author(s): ////
- //// - Steve Fielding, sfielding@base2designs.com ////
- //// ////
- //////////////////////////////////////////////////////////////////////
- //// ////
- //// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG ////
- //// ////
- //// This source file may be used and distributed without ////
- //// restriction provided that this copyright statement is not ////
- //// removed from the file and that any derivative work contains ////
- //// the original copyright notice and the associated disclaimer. ////
- //// ////
- //// 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.opencores.org/lgpl.shtml> ////
- //// ////
- //////////////////////////////////////////////////////////////////////
- //
- `include "i2cSlave_define.v"
-
-
- module i2cSlave (
- clk,
- rst,
- sda,
- scl,
- tb_readEn,
- tb_writeEn,
- tb_addr,
- tb_dataIn,
- tb_dataOut
- );
-
- input clk;
- input rst;
- inout sda;
- input scl;
-
- // tb interface
- input tb_readEn;
- input tb_writeEn;
- input [15:0] tb_addr;
- input [15:0] tb_dataIn;
- output [15:0] tb_dataOut;
-
- // local wires and regs
- reg sdaDeb;
- reg sclDeb;
- reg [`DEB_I2C_LEN-1:0] sdaPipe;
- reg [`DEB_I2C_LEN-1:0] sclPipe;
-
- reg [`SCL_DEL_LEN-1:0] sclDelayed;
- reg [`SDA_DEL_LEN-1:0] sdaDelayed;
- reg [1:0] startStopDetState;
- wire clearStartStopDet;
- wire sdaOut;
- wire sdaIn;
- wire [15:0] regAddr;
- wire [7:0] dataToRegIF;
- wire writeEn;
- wire [7:0] dataFromRegIF;
- reg [1:0] rstPipe;
- wire rstSyncToClk;
- reg startEdgeDet;
-
- assign sda = (sdaOut == 1'b0) ? 1'b0 : 1'bz;
- assign sdaIn = sda;
-
- // sync rst rsing edge to clk
- always @(posedge clk) begin
- if (rst == 1'b1)
- rstPipe <= 2'b11;
- else
- rstPipe <= {rstPipe[0], 1'b0};
- end
-
- assign rstSyncToClk = rstPipe[1];
-
- // debounce sda and scl
- always @(posedge clk) begin
- if (rstSyncToClk == 1'b1) begin
- sdaPipe <= {`DEB_I2C_LEN{1'b1}};
- sdaDeb <= 1'b1;
- sclPipe <= {`DEB_I2C_LEN{1'b1}};
- sclDeb <= 1'b1;
- end
- else begin
- sdaPipe <= {sdaPipe[`DEB_I2C_LEN-2:0], sdaIn};
- sclPipe <= {sclPipe[`DEB_I2C_LEN-2:0], scl};
- if (&sclPipe[`DEB_I2C_LEN-1:1] == 1'b1)
- sclDeb <= 1'b1;
- else if (|sclPipe[`DEB_I2C_LEN-1:1] == 1'b0)
- sclDeb <= 1'b0;
- if (&sdaPipe[`DEB_I2C_LEN-1:1] == 1'b1)
- sdaDeb <= 1'b1;
- else if (|sdaPipe[`DEB_I2C_LEN-1:1] == 1'b0)
- sdaDeb <= 1'b0;
- end
- end
-
-
- // delay scl and sda
- // sclDelayed is used as a delayed sampling clock
- // sdaDelayed is only used for start stop detection
- // Because sda hold time from scl falling is 0nS
- // sda must be delayed with respect to scl to avoid incorrect
- // detection of start/stop at scl falling edge.
- always @(posedge clk) begin
- if (rstSyncToClk == 1'b1) begin
- sclDelayed <= {`SCL_DEL_LEN{1'b1}};
- sdaDelayed <= {`SDA_DEL_LEN{1'b1}};
- end
- else begin
- sclDelayed <= {sclDelayed[`SCL_DEL_LEN-2:0], sclDeb};
- sdaDelayed <= {sdaDelayed[`SDA_DEL_LEN-2:0], sdaDeb};
- end
- end
-
- // start stop detection
- always @(posedge clk) begin
- if (rstSyncToClk == 1'b1) begin
- startStopDetState <= `NULL_DET;
- startEdgeDet <= 1'b0;
- end
- else begin
- if (sclDeb == 1'b1 && sdaDelayed[`SDA_DEL_LEN-2] == 1'b0 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b1)
- startEdgeDet <= 1'b1;
- else
- startEdgeDet <= 1'b0;
- if (clearStartStopDet == 1'b1)
- startStopDetState <= `NULL_DET;
- else if (sclDeb == 1'b1) begin
- if (sdaDelayed[`SDA_DEL_LEN-2] == 1'b1 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b0)
- startStopDetState <= `STOP_DET;
- else if (sdaDelayed[`SDA_DEL_LEN-2] == 1'b0 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b1)
- startStopDetState <= `START_DET;
- end
- end
- end
-
-
- registerInterface u_registerInterface(
- .clk(clk),
- .addr(regAddr),
- .dataIn(dataToRegIF),
- .writeEn(writeEn),
- .dataOut(dataFromRegIF),
- .tb_readEn(tb_readEn),
- .tb_writeEn(tb_writeEn),
- .tb_addr(tb_addr),
- .tb_dataIn(tb_dataIn),
- .tb_dataOut(tb_dataOut)
- );
-
- serialInterface u_serialInterface (
- .clk(clk),
- .rst(rstSyncToClk | startEdgeDet),
- .dataIn(dataFromRegIF),
- .dataOut(dataToRegIF),
- .writeEn(writeEn),
- .regAddr(regAddr),
- .scl(sclDelayed[`SCL_DEL_LEN-1]),
- .sdaIn(sdaDeb),
- .sdaOut(sdaOut),
- .startStopDetState(startStopDetState),
- .clearStartStopDet(clearStartStopDet)
- );
-
-
- endmodule
-
-
-
|