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