1
\$\begingroup\$

I have been trying to connect the ADS1115 ADC with my Microchip PolarFire SoC discovery kit FPGA board, I have written the FSM for I2C master by collecting the code from various sources because I am not very good at Verilog. The issue is I am sending the ADS (slave) address it shows on the DSO if i connect one to the SDA line but there are some extra bits coming in it like the address is 1001000 then there must be a ACK bit but I am seeing another 2 0 bit in the SDA line one of them I am considering as ACK, this is if I don't add specifically in the code to release the SDA line after sending the address, if I do add it the extra 0 bit I was getting turns to 1 the one I was considering as ACK stay 0.

I thought of the that 1 extra bit as some delay, so then I sent the configuration register address which is 00000001 here this get uglier instead of 7 zero bits I am seeing 8 then there are 2 1's maybe NCAK and the last bit but again if a define ACK checking state explicitly there are three 1's. The code is not going ahead of this. also there is something wrong with my 12c frequency I have set it to 200 kHz but it shows around 37-40 or sometimes 50 kHz only.

MY DSO OUTPUT

Please help in ways I can understand, I am too new to Verilog and FPGAs :) below is the code Read part I have commented out, cuz write is not working so.

module ads1115 ( input clk, input rst, input enable, output reg [15:0] data_out, // Final 16-bit ADC output output reg ack, output wire ready, inout sda, inout scl); // I2C parameters parameter IDLE = 0; parameter START = 1; parameter SEND_ADDR_W = 2; parameter ADDR_ACK = 3; parameter LOAD_CONFIG_ADDR = 4; parameter WRITE_CONFIG_ADDR = 5; parameter PTR_ACK = 6; parameter LOAD_CONFIG_MSB = 7; parameter WRITE_CONFIG_MSB = 8; parameter CONFIG_MSB_ACK = 9; parameter LOAD_CONFIG_LSB = 10; parameter WRITE_CONFIG_LSB = 11; parameter CONFIG_LSB_ACK = 12; parameter RESTART = 13; parameter SEND_ADDR_R = 14; parameter READ_ADDR_ACK = 15; parameter READ_MSB = 16; parameter READ_LSB = 17; parameter STOP = 18; parameter DONE = 19; parameter div_const = 10; reg [4:0] state = IDLE; reg [7:0] counter1 = 0; reg i2c_scl_enable = 0; reg i2c_clk = 0; reg [7:0] temp_data; reg [7:0] data_msb, data_lsb; reg wr_enb = 1; reg sda_out = 1; reg [7:0] byte_data; reg [3:0] bit_cnt = 7; wire [6:0] addr_7bit = 7'b1001000; // ADDR = GND ? 0x48 wire [7:0] addr_w = {addr_7bit, 1'b0}; // write address wire [7:0] addr_r = {addr_7bit, 1'b1}; // read address always @(posedge clk or posedge rst) begin if (rst) begin counter1 <= 0; i2c_clk <= 1; end else begin if (counter1 == div_const - 1) begin i2c_clk <= ~i2c_clk; counter1 <= 0; end else begin counter1 <= counter1 + 1; end end end always @(posedge i2c_clk or posedge rst) begin if (rst) i2c_scl_enable <= 0; else if (state == IDLE || state == START || state == STOP) i2c_scl_enable <= 0; else i2c_scl_enable <= 1; end assign scl = (i2c_scl_enable == 0) ? 1'b1 : i2c_clk; assign sda = wr_enb ? sda_out : 1'bz; assign ready = (state == IDLE); // FSM for I2C always @(posedge i2c_clk or posedge rst) begin if (rst) begin state <= IDLE; data_out <= 0; data_msb <= 0; data_lsb <= 0; ack <= 0; wr_enb <= 1; sda_out <= 1; bit_cnt <= 7; end else begin case (state) IDLE: begin wr_enb <= 1; sda_out <= 1; if (enable) begin state <= START; bit_cnt <= 7; end end START: begin wr_enb <= 1; sda_out <= 0; state <= SEND_ADDR_W; byte_data <= addr_w; end SEND_ADDR_W: begin wr_enb <= 1; sda_out <= byte_data[bit_cnt]; if (bit_cnt == 0) begin state <= ADDR_ACK; wr_enb <= 0; // Release SDA for ACK end else begin bit_cnt <= bit_cnt - 1; end end ADDR_ACK: begin //wr_enb <= 0; // Let slave control SDA if (sda == 0) begin ack <= 1; state <= LOAD_CONFIG_ADDR; end else begin ack <= 0; state <= STOP; end end LOAD_CONFIG_ADDR: begin byte_data <= 8'h01; // Config register address bit_cnt <= 7; wr_enb <= 1; state <= WRITE_CONFIG_ADDR; end WRITE_CONFIG_ADDR: begin wr_enb <= 1; sda_out <= byte_data[bit_cnt]; if (bit_cnt == 0) begin state <= PTR_ACK; wr_enb <= 0; end else begin bit_cnt <= bit_cnt - 1; end end PTR_ACK: begin wr_enb <= 0; if (sda == 0) begin ack <= 1; state <= LOAD_CONFIG_MSB; end else begin ack <= 0; state <= STOP; end end LOAD_CONFIG_MSB: begin byte_data <= 8'b01000010; bit_cnt <= 7; wr_enb <= 1; state <= WRITE_CONFIG_MSB; end WRITE_CONFIG_MSB: begin wr_enb <= 1; sda_out <= byte_data[bit_cnt]; if (bit_cnt == 0) begin state <= CONFIG_MSB_ACK; wr_enb <= 0; end else begin bit_cnt <= bit_cnt - 1; end end CONFIG_MSB_ACK: begin wr_enb <= 0; if (sda == 0) begin ack <= 1; state <= LOAD_CONFIG_LSB; end else begin ack <= 0; state <= STOP; end end LOAD_CONFIG_LSB: begin byte_data <= 8'b11100011; bit_cnt <= 7; wr_enb <= 1; state <= WRITE_CONFIG_LSB; end WRITE_CONFIG_LSB: begin wr_enb <= 1; sda_out <= byte_data[bit_cnt]; if (bit_cnt == 0) begin state <= CONFIG_LSB_ACK; wr_enb <= 0; end else begin bit_cnt <= bit_cnt - 1; end end CONFIG_LSB_ACK: begin wr_enb <= 0; if (sda == 0) begin ack <= 1; state <= IDLE; end else begin ack <= 0; state <= STOP; end end //RESTART: begin //wr_enb <= 1; //sda_out <= 1; //state <= START; //byte_data <= 8'h00; //end //SEND_ADDR_R: begin //wr_enb <= 1; //sda_out <= byte_data[bit_cnt]; //if (bit_cnt == 0) begin //state <= READ_ADDR_ACK; //wr_enb <= 0; //end else begin //bit_cnt <= bit_cnt - 1; //end //end //READ_ADDR_ACK: begin //wr_enb <= 0; //if (sda == 0) begin //ack <= 1; //state <= READ_MSB; //bit_cnt <= 7; //end else begin //ack <= 0; //state <= STOP; //end //end //READ_MSB: begin //wr_enb <= 0; // Let slave drive SDA //data_msb[bit_cnt] <= sda; //if (bit_cnt == 0) begin //bit_cnt <= 7; //state <= READ_LSB; //// Send ACK //wr_enb <= 1; //sda_out <= 0; //end else begin //bit_cnt <= bit_cnt - 1; //end //end //READ_LSB: begin //wr_enb <= 0; // Let slave drive SDA //data_lsb[bit_cnt] <= sda; //if (bit_cnt == 0) begin //state <= STOP; //// Send NACK (don't drive SDA low) //wr_enb <= 1; //sda_out <= 1; //end else begin //bit_cnt <= bit_cnt - 1; //end //end STOP: begin wr_enb <= 1; sda_out <= 0; state <= DONE; end //DONE: begin //wr_enb <= 1; //sda_out <= 1; // Complete stop condition //data_out <= {data_msb, data_lsb}; //state <= IDLE; //end default: state <= IDLE; endcase end end endmodule 
\$\endgroup\$
0

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.