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

Subversion Repositories i2c_slave

[/] [i2c_slave/] [web_uploads/] [iic_slave_3.v] - Rev 6

Compare with Previous | Blame | View Log

// WARNING: Do NOT edit the input and output ports in this file in a text
// editor if you plan to continue editing the block that represents it in
// the Block Editor! File corruption is VERY likely to occur.
 
// Copyright (C) 1991-2003 Altera Corporation
// Any  megafunction  design,  and related netlist (encrypted  or  decrypted),
// support information,  device programming or simulation file,  and any other
// associated  documentation or information  provided by  Altera  or a partner
// under  Altera's   Megafunction   Partnership   Program  may  be  used  only
// to program  PLD  devices (but not masked  PLD  devices) from  Altera.   Any
// other  use  of such  megafunction  design,  netlist,  support  information,
// device programming or simulation file,  or any other  related documentation
// or information  is prohibited  for  any  other purpose,  incrluding, but not
// limited to  modification,  reverse engineering,  de-compiling, or use  with
// any other  silicon devices,  unless such use is  explicitly  licensed under
// a separate agreement with  Altera  or a megafunction partner.  Title to the
// intellectual property,  incrluding patents,  copyrights,  trademarks,  trade
// secrets,  or maskworks,  embodied in any such megafunction design, netlist,
// support  information,  device programming or simulation file,  or any other
// related documentation or information provided by  Altera  or a megafunction
// partner, remains with Altera, the megafunction partner, or their respective
// licensors. No other licenses, incrluding any licenses needed under any third
// party's intellectual property, are provided herein.
 
 
// Generated by Quartus II Version 2.2 (Build Build 176 02/04/2003)
// Created on Tue May 13 14:49:34 2003
 
//  Module Declaration
module iic_slave_3
(
	// {{ALTERA_ARGS_BEGIN}} DO NOT REMOVE THIS LINE!
	scl, sda, send1, send2, send3, reset, rw, i2cadr1, i2cadr2, i2cadr3, slave_ack1, slave_ack2, slave_ack3, regout1, regout2, regout3, sreg, rd_clk1, rd_clk2, rd_clk3, wr_clk1, wr_clk2, wr_clk3, incr
	// {{ALTERA_ARGS_END}} DO NOT REMOVE THIS LINE!
);
// Port Declaration
 
	// {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!
	input scl;
	inout sda;
	// busses for read transfer, slave --> master
	input [7:0] send1;
	input [7:0] send2;
	input [7:0] send3;
	input reset;
	// read (1) or write (0) status
	output rw;
	// I2C address indicators
	output i2cadr1;
	output i2cadr2;
	output i2cadr3;
	// slave acknowledge
	output slave_ack1;
	output slave_ack2;
	output slave_ack3;
	// busses for write transfers, master --> slave
	output [7:0] regout1;
	output [7:0] regout2;
	output [7:0] regout3;
	// common shift register output 
	output [7:0] sreg;
	// read clock 
	output rd_clk1;
	output rd_clk2;
	output rd_clk3;
	// write clock 
	output wr_clk1;
	output wr_clk2;
	output wr_clk3;
	output incr; // counter output, not used
 
	// {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!
// STATES
parameter IDLE 	 = 3'b000;
parameter SLAVE  = 3'b001;
parameter SL_ACK = 3'b010;
parameter READ   = 3'b011;
parameter RD_ACK = 3'b100;
parameter WRITE  = 3'b101;
parameter WR_ACK = 3'b110;
parameter STOP   = 3'b111; // obsolete?
 
// IIC ADDRESS, edit to change
parameter I2C_ADR1 = 7'b001_0000;	// h10, 1st address
parameter I2C_ADR2 = 7'b011_0100;	// h34, 2nd address
parameter I2C_ADR3 = 7'b011_0101;	// h35, 3rd address
 
reg sda;
reg start;
reg stop;
reg slave_ack1;
reg slave_ack2;
reg slave_ack3;
reg write_ack;
wire read_ack;
wire rw;
reg [2:0] state; 
reg [3:0] bit_cnt;
wire reset;
reg incr;	// for external counters.
 
reg [7:0] send; // temp 
wire cnt4;
wire cnt8;
wire cnt9;
wire this_adr1;	// EQUAL
wire this_adr2;	// EQUAL
wire this_adr3;	// EQUAL
wire sda_low;
wire slave_ack_n;
wire write_ack_n;
wire load_send;
wire [7:0] sreg;	// for output  
wire load;  
reg [8:0] sr;       // 9 bit shift register RECEIVE
reg [7:0] sr_tx;    // 8 bit shift register SEND
reg [7:0] regout1;		// output data #1
reg [7:0] regout2;		// output data #2
reg [7:0] regout3;		// output data #3
 
reg clear_rws;
reg read_pulse;
reg slave_pulse1;
reg slave_pulse2;
reg slave_pulse3;
reg write_pulse;
 
wire start_n;
wire stop_pulse;
wire sda_n;
wire stop_n;
wire scl_n;
wire count_bits;
wire read_TX;
wire stop_reset_n;
 
wire bit_zero;
wire reset_bit_cnt_n;
wire reset_start_n;
wire reset_stop_n;
// OUTPUT REG
	reg i2cadr1;
	reg i2cadr2;
	reg i2cadr3;
 
wire reset_adress_n;
 
assign sda_n = ~sda;
assign scl_n = ~scl;
//assign sr_tx_out = sr_tx[7];
assign read_TX = state == READ ? ~sr_tx[7]: 1'b0;
 
//assign sda_low = ~read_ack && (slave_ack || write_ack || read_TX);
 
assign slave_ack_n = ~(slave_ack1 || slave_ack2 || slave_ack3);
assign write_ack_n = ~write_ack;	// sda_oe = 1, sda = 0
assign read_ack = (state == RD_ACK);	// sda_oe = 0, read ACK/NACK
assign this_adr1 = (sr[7:1] == I2C_ADR1) && cnt8; 
assign this_adr2 = (sr[7:1] == I2C_ADR2) && cnt8; 
assign this_adr3 = (sr[7:1] == I2C_ADR3) && cnt8; 
 
//assign sda_low = slave_ack1 || slave_ack2 || slave_ack3 || write_ack || read_TX;
//assign sda = sda_low ? 1'b0 : 1'bz;
 
assign sreg = sr[7:0];
assign start_n = ~start;
 
assign wr_clk1 = state == WR_ACK && i2cadr1 && write_pulse ? 1'b1: 1'b0;
assign wr_clk2 = state == WR_ACK && i2cadr2 && write_pulse ? 1'b1: 1'b0;
assign wr_clk3 = state == WR_ACK && i2cadr3 && write_pulse ? 1'b1: 1'b0;
assign rd_clk1 = state == RD_ACK && i2cadr1 && read_pulse ? 1'b1: 1'b0;
assign rd_clk2 = state == RD_ACK && i2cadr2 && read_pulse ? 1'b1: 1'b0;
assign rd_clk3 = state == RD_ACK && i2cadr3 && read_pulse ? 1'b1: 1'b0;
//assign i2cadr1 = state == SLAVE ? this_adr1: i2cadr1;	 // latch 
//assign i2cadr2 = state == SLAVE ? this_adr2: i2cadr2;	 // latch 
//assign i2cadr3 = state == SLAVE ? this_adr3: i2cadr3;	 // latch 
assign rw = (this_adr1 || this_adr2 || this_adr3) && (state == SLAVE)? sr[0]: rw; // latch
assign cnt4 = bit_cnt == 4'b0100;
assign cnt8 = bit_cnt == 4'b1000;
assign cnt9 = bit_cnt == 4'b1001;
assign bit_zero = bit_cnt == 4'b0000 ? 1'b0: 1'b1;
 
assign stop_n = ~stop;
assign count_bits = (state == SLAVE || state == READ || state == WRITE || state == RD_ACK || state == WR_ACK) ? 1'b1: 1'b0;
assign stop_reset_n = ~(stop || ~reset);
assign load_send = slave_ack1 || slave_ack2 || slave_ack3 || read_ack;
assign reset_bit_cnt_n = ~(stop || start || bit_cnt == 4'b1001);
assign reset_start_n = ~start;
assign reset_stop_n = ~stop;
assign reset_adress_n = ~(start || stop);
 
 
// SDA OUT
//assign sda_low = slave_ack1 || slave_ack2 || slave_ack3 || write_ack || read_TX;
//assign sda = sda_low ? 1'b0 : 1'bz;
 
always@(posedge scl_n or negedge reset_adress_n)
begin
	if(!reset_adress_n)
		sda = 1'bz;
	else if(slave_ack1 || slave_ack2 || slave_ack3 || write_ack || read_TX)
		sda = 1'b0;
	else
		sda = 1'bz;
end
 
// ADDRESS LATCH
always@(posedge scl_n or negedge reset_adress_n)
begin
	if(!reset_adress_n)
	begin
		i2cadr1 = 0;
		i2cadr2 = 0;
		i2cadr3 = 0;
	end
	else if(state == SLAVE)
	begin
		i2cadr1 = this_adr1;
		i2cadr2 = this_adr2;
		i2cadr3 = this_adr3;
	end 
	else
	begin
		i2cadr1 = i2cadr1;
		i2cadr2 = i2cadr2;
		i2cadr3 = i2cadr3;
	end 
end
 
// INCR EXT.
always@(posedge scl)
begin
	if((state == READ || state == WRITE) && cnt4)
		incr = 1'b1;
	else
		incr = 1'b0;
end
 
// MUX for send register
always@(i2cadr1 or i2cadr2 or i2cadr3 or send1 or send2 or send3)
begin
	casex({i2cadr1, i2cadr2, i2cadr3})
	3'b000: send = send; // latch?
	3'b001: send = send3;
	3'b010: send = send2;
	3'b100: send = send1;
	endcase
end
 
// Shift register with load for output (I2C READ) #1
always @(negedge scl)
begin
	if(load_send)
		sr_tx = send;
	else
		sr_tx = {sr_tx[6:0], 1'b0};	
end
 
// Shift register with load for input (I2C WRITE & ADDRESS)
always @(posedge scl)
begin
	sr = {sr[6:0], sda};
end
// Received data #1
always @(negedge scl)
begin
	if((state == WRITE) && cnt8 && i2cadr1)
	regout1 = sr[7:0];
end
 
// Received data #2
always @(negedge scl)
begin
	if((state == WRITE) && cnt8 && i2cadr2)
	regout2 = sr[7:0];
end
 
// Received data #3
always @(negedge scl)
begin
	if((state == WRITE) && cnt8 && i2cadr3)
	regout3 = sr[7:0];
end
 
// clear_rws
always@(posedge scl)
begin
	if(read_pulse || write_pulse || slave_pulse1 || slave_pulse2 || slave_pulse3)
		clear_rws = 1'b0;
	else
		clear_rws = 1'b1;
end
 
// read pulse
always@(posedge read_ack or negedge clear_rws)
begin
	if(!clear_rws)
		read_pulse = 1'b0;
	else
		read_pulse = 1'b1;
end
// slave pulse #1
always@(posedge slave_ack1 or negedge clear_rws)
begin
	if(!clear_rws)
		slave_pulse1 = 1'b0;
	else
		slave_pulse1 = 1'b1;
end
// slave pulse #2
always@(posedge slave_ack2 or negedge clear_rws)
begin
	if(!clear_rws)
		slave_pulse2 = 1'b0;
	else
		slave_pulse2 = 1'b1;
end
// slave pulse #3
always@(posedge slave_ack3 or negedge clear_rws)
begin
	if(!clear_rws)
		slave_pulse3 = 1'b0;
	else
		slave_pulse3 = 1'b1;
end
 
 
 
// write pulse
always@(posedge write_ack or negedge clear_rws)
begin
	if(!clear_rws)
		write_pulse = 1'b0;
	else
		write_pulse = 1'b1;
end
 
// bit counter
always@(posedge scl or negedge reset_bit_cnt_n)
begin
	if(!reset_bit_cnt_n)
		bit_cnt = 0;
	else
		bit_cnt = bit_cnt + 1'b1;
end
 
// slave acknowledge #1
always@(negedge scl)
begin
	if((state == SLAVE) && this_adr1) // && bit_cnt == 8
		slave_ack1 = 1'b1;
	else
		slave_ack1 = 1'b0;
end
// slave acknowledge #2
always@(negedge scl)
begin
	if((state == SLAVE) && this_adr2)
		slave_ack2 = 1'b1;
	else
		slave_ack2 = 1'b0;
end
// slave acknowledge #3
always@(negedge scl)
begin
	if((state == SLAVE) && this_adr3)
		slave_ack3 = 1'b1;
	else
		slave_ack3 = 1'b0;
end
 
 
// write acknowledge internal, always issued due to STATE MACHINE implementation.
always@(negedge scl)
begin
	if((state == WRITE) && cnt8)
		write_ack = 1'b1;
	else
		write_ack = 1'b0;
end
 
// START
always@(posedge sda_n or negedge reset_start_n)
begin
	if(!reset_start_n)
		start = 1'b0;
	else
		start = scl;
end
 
// STOP
always@(posedge sda or negedge reset_stop_n)
begin
	if(!reset_stop_n)
		stop = 1'b0;
	else
		stop = scl;
end
 
always@(posedge scl_n or negedge stop_reset_n or negedge start_n)
begin
	if(!stop_reset_n)
		state = IDLE;
	else if(!start_n)
		state = SLAVE;
	else 
	begin
	case(state)
	IDLE: 	begin if(start)									// 00
			state = SLAVE; 
			else state = IDLE; end // dead end
	SLAVE: 	begin if(bit_cnt < 8) 							// 01
			state = SLAVE;
			else if(this_adr1 || this_adr2 || this_adr3)
			state = SL_ACK; 	
			else state = IDLE; end
	SL_ACK:	begin if(rw) state = READ; 						// 02
			else if(!rw) state = WRITE;
			else state = IDLE; end		
	READ: 	begin if(bit_cnt < 8) state = READ;				// 03
			else state = RD_ACK; end
	RD_ACK: begin if(sr[0]) state = IDLE; 					// 04	
			else state = READ; end
	WRITE:	begin if(bit_cnt < 8) state = WRITE;			// 05 
			else state = WR_ACK; end
	WR_ACK: begin if(scl_n) state = IDLE;					// 05 
			else state = WRITE; end 						// 06 		
		//	else state = WRITE; end
	STOP: 	begin state = IDLE; end							// 07
	endcase
	end
end
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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