summaryrefslogtreecommitdiff
path: root/tests/i2c_bench/i2c_master_byte_ctrl.v
diff options
context:
space:
mode:
Diffstat (limited to 'tests/i2c_bench/i2c_master_byte_ctrl.v')
-rw-r--r--tests/i2c_bench/i2c_master_byte_ctrl.v344
1 files changed, 344 insertions, 0 deletions
diff --git a/tests/i2c_bench/i2c_master_byte_ctrl.v b/tests/i2c_bench/i2c_master_byte_ctrl.v
new file mode 100644
index 00000000..513953a8
--- /dev/null
+++ b/tests/i2c_bench/i2c_master_byte_ctrl.v
@@ -0,0 +1,344 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// WISHBONE rev.B2 compliant I2C Master byte-controller ////
+//// ////
+//// ////
+//// Author: Richard Herveille ////
+//// richard@asics.ws ////
+//// www.asics.ws ////
+//// ////
+//// Downloaded from: http://www.opencores.org/projects/i2c/ ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2001 Richard Herveille ////
+//// richard@asics.ws ////
+//// ////
+//// 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 SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
+//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
+//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
+//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
+//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
+//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
+//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
+//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
+//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
+//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
+//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
+//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
+//// POSSIBILITY OF SUCH DAMAGE. ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+
+// CVS Log
+//
+// $Id: i2c_master_byte_ctrl.v,v 1.8 2009-01-19 20:29:26 rherveille Exp $
+//
+// $Date: 2009-01-19 20:29:26 $
+// $Revision: 1.8 $
+// $Author: rherveille $
+// $Locker: $
+// $State: Exp $
+//
+// Change History:
+// $Log: not supported by cvs2svn $
+// Revision 1.7 2004/02/18 11:40:46 rherveille
+// Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command.
+//
+// Revision 1.6 2003/08/09 07:01:33 rherveille
+// Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
+// Fixed a potential bug in the byte controller's host-acknowledge generation.
+//
+// Revision 1.5 2002/12/26 15:02:32 rherveille
+// Core is now a Multimaster I2C controller
+//
+// Revision 1.4 2002/11/30 22:24:40 rherveille
+// Cleaned up code
+//
+// Revision 1.3 2001/11/05 11:59:25 rherveille
+// Fixed wb_ack_o generation bug.
+// Fixed bug in the byte_controller statemachine.
+// Added headers.
+//
+
+// synopsys translate_off
+`include "timescale.v"
+// synopsys translate_on
+
+`include "i2c_master_defines.v"
+
+module i2c_master_byte_ctrl (
+ clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din,
+ cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen );
+
+ //
+ // inputs & outputs
+ //
+ input clk; // master clock
+ input rst; // synchronous active high reset
+ input nReset; // asynchronous active low reset
+ input ena; // core enable signal
+
+ input [15:0] clk_cnt; // 4x SCL
+
+ // control inputs
+ input start;
+ input stop;
+ input read;
+ input write;
+ input ack_in;
+ input [7:0] din;
+
+ // status outputs
+ output cmd_ack;
+ reg cmd_ack;
+ output ack_out;
+ reg ack_out;
+ output i2c_busy;
+ output i2c_al;
+ output [7:0] dout;
+
+ // I2C signals
+ input scl_i;
+ output scl_o;
+ output scl_oen;
+ input sda_i;
+ output sda_o;
+ output sda_oen;
+
+
+ //
+ // Variable declarations
+ //
+
+ // statemachine
+ parameter [4:0] ST_IDLE = 5'b0_0000;
+ parameter [4:0] ST_START = 5'b0_0001;
+ parameter [4:0] ST_READ = 5'b0_0010;
+ parameter [4:0] ST_WRITE = 5'b0_0100;
+ parameter [4:0] ST_ACK = 5'b0_1000;
+ parameter [4:0] ST_STOP = 5'b1_0000;
+
+ // signals for bit_controller
+ reg [3:0] core_cmd;
+ reg core_txd;
+ wire core_ack, core_rxd;
+
+ // signals for shift register
+ reg [7:0] sr; //8bit shift register
+ reg shift, ld;
+
+ // signals for state machine
+ wire go;
+ reg [2:0] dcnt;
+ wire cnt_done;
+
+ //
+ // Module body
+ //
+
+ // hookup bit_controller
+ i2c_master_bit_ctrl bit_controller (
+ .clk ( clk ),
+ .rst ( rst ),
+ .nReset ( nReset ),
+ .ena ( ena ),
+ .clk_cnt ( clk_cnt ),
+ .cmd ( core_cmd ),
+ .cmd_ack ( core_ack ),
+ .busy ( i2c_busy ),
+ .al ( i2c_al ),
+ .din ( core_txd ),
+ .dout ( core_rxd ),
+ .scl_i ( scl_i ),
+ .scl_o ( scl_o ),
+ .scl_oen ( scl_oen ),
+ .sda_i ( sda_i ),
+ .sda_o ( sda_o ),
+ .sda_oen ( sda_oen )
+ );
+
+ // generate go-signal
+ assign go = (read | write | stop) & ~cmd_ack;
+
+ // assign dout output to shift-register
+ assign dout = sr;
+
+ // generate shift register
+ always @(posedge clk or negedge nReset)
+ if (!nReset)
+ sr <= 8'h0;
+ else if (rst)
+ sr <= 8'h0;
+ else if (ld)
+ sr <= din;
+ else if (shift)
+ sr <= {sr[6:0], core_rxd};
+
+ // generate counter
+ always @(posedge clk or negedge nReset)
+ if (!nReset)
+ dcnt <= 3'h0;
+ else if (rst)
+ dcnt <= 3'h0;
+ else if (ld)
+ dcnt <= 3'h7;
+ else if (shift)
+ dcnt <= dcnt - 3'h1;
+
+ assign cnt_done = ~(|dcnt);
+
+ //
+ // state machine
+ //
+ reg [4:0] c_state; // synopsys enum_state
+
+ always @(posedge clk or negedge nReset)
+ if (!nReset)
+ begin
+ core_cmd <= `I2C_CMD_NOP;
+ core_txd <= 1'b0;
+ shift <= 1'b0;
+ ld <= 1'b0;
+ cmd_ack <= 1'b0;
+ c_state <= ST_IDLE;
+ ack_out <= 1'b0;
+ end
+ else if (rst | i2c_al)
+ begin
+ core_cmd <= `I2C_CMD_NOP;
+ core_txd <= 1'b0;
+ shift <= 1'b0;
+ ld <= 1'b0;
+ cmd_ack <= 1'b0;
+ c_state <= ST_IDLE;
+ ack_out <= 1'b0;
+ end
+ else
+ begin
+ // initially reset all signals
+ core_txd <= sr[7];
+ shift <= 1'b0;
+ ld <= 1'b0;
+ cmd_ack <= 1'b0;
+
+ case (c_state) // synopsys full_case parallel_case
+ ST_IDLE:
+ if (go)
+ begin
+ if (start)
+ begin
+ c_state <= ST_START;
+ core_cmd <= `I2C_CMD_START;
+ end
+ else if (read)
+ begin
+ c_state <= ST_READ;
+ core_cmd <= `I2C_CMD_READ;
+ end
+ else if (write)
+ begin
+ c_state <= ST_WRITE;
+ core_cmd <= `I2C_CMD_WRITE;
+ end
+ else // stop
+ begin
+ c_state <= ST_STOP;
+ core_cmd <= `I2C_CMD_STOP;
+ end
+
+ ld <= 1'b1;
+ end
+
+ ST_START:
+ if (core_ack)
+ begin
+ if (read)
+ begin
+ c_state <= ST_READ;
+ core_cmd <= `I2C_CMD_READ;
+ end
+ else
+ begin
+ c_state <= ST_WRITE;
+ core_cmd <= `I2C_CMD_WRITE;
+ end
+
+ ld <= 1'b1;
+ end
+
+ ST_WRITE:
+ if (core_ack)
+ if (cnt_done)
+ begin
+ c_state <= ST_ACK;
+ core_cmd <= `I2C_CMD_READ;
+ end
+ else
+ begin
+ c_state <= ST_WRITE; // stay in same state
+ core_cmd <= `I2C_CMD_WRITE; // write next bit
+ shift <= 1'b1;
+ end
+
+ ST_READ:
+ if (core_ack)
+ begin
+ if (cnt_done)
+ begin
+ c_state <= ST_ACK;
+ core_cmd <= `I2C_CMD_WRITE;
+ end
+ else
+ begin
+ c_state <= ST_READ; // stay in same state
+ core_cmd <= `I2C_CMD_READ; // read next bit
+ end
+
+ shift <= 1'b1;
+ core_txd <= ack_in;
+ end
+
+ ST_ACK:
+ if (core_ack)
+ begin
+ if (stop)
+ begin
+ c_state <= ST_STOP;
+ core_cmd <= `I2C_CMD_STOP;
+ end
+ else
+ begin
+ c_state <= ST_IDLE;
+ core_cmd <= `I2C_CMD_NOP;
+
+ // generate command acknowledge signal
+ cmd_ack <= 1'b1;
+ end
+
+ // assign ack_out output to bit_controller_rxd (contains last received bit)
+ ack_out <= core_rxd;
+
+ core_txd <= 1'b1;
+ end
+ else
+ core_txd <= ack_in;
+
+ ST_STOP:
+ if (core_ack)
+ begin
+ c_state <= ST_IDLE;
+ core_cmd <= `I2C_CMD_NOP;
+
+ // generate command acknowledge signal
+ cmd_ack <= 1'b1;
+ end
+
+ endcase
+ end
+endmodule