I2C Fails on Arduino MKRZero

I have an Arduino MKRZero that I am trying to use as an I2C slave. I have the same sketch working with an Arduino UNO. The MKRZero is attached to an FPGA with an I2C controller that has been validated. Moreover, with a logic analyzer I can see the proper initial signals (the address) being sent from the FPGA to the arduino. The MKRZero always nacks the address and does not fire the onReceive or onRequest handlers. I have two 2.2kohm pull-up resistors attached to SCL and SDA (attached to 3.3V). I have verified that every connection outputs no more than 3.3V (the high voltage from the FPGA is 1.5 and low is <0.3V, which should be enough for HIGH and LOW logic levels). Here is some relevant code:

void setup() {
	Serial.begin(SERIAL_2_I2C_BAUD_RATE);
	flush();
	Serial.flush();

	// Reset
	pinMode(RESET_PIN, OUTPUT);
	digitalWrite(RESET_PIN, LOW);

	// Debug
	pinMode(3, OUTPUT);
	digitalWrite(3, LOW);
	
	Wire.begin(SERIAL_2_I2C_SLAVE_ADDR);
	Wire.setClock(100000);
	// Wire.setClock(400000);
	Wire.onRequest(handleRequest);
	Wire.onReceive(handleReceive);

	idx = 0;
	valid = false;
	reset = false;
	error = false;
	recieve = false;
	request = false;
}
void handleReceive(int numBytes) {
	receivedLen = numBytes;
	for(int i = 0; i < numBytes; i++) {
		received[i] = Wire.read();
	}
	recieve = true;
}

void handleRequest() {
	uint8_t payload[3];
	payload[0] = valid;
	for(uint8_t i = 0; i < len; i++) {
		payload[i + 1] = requested[i];
	}
	Wire.write(payload, 3);
	request = valid;
}

The entire sketch (please see attached) compiles and runs. Neither handler is ever called (tested this by looking by writing a pin high). I have verified that the I2C address is correct and have also set SD0 to gnd (I don’t know what that would do, but someone suggested it). Any help would be much appreciated.

sample.ino (2.99 KB)

VIH should be at least 0.55 * VDD, that is 0.55 * 3.3 = 1.8 V.

I reverified the voltage... high is 3-3.1V and low is 0.405V well within specifications.

The I2C Slave address with "Wire.begin(0x2D)" is the 7 bit shifted address.
With the logic analyzer you should see 0x5A.

Can you make a small test sketch. No serial, no flush, no reset, no buffers, no SerialEvent, nothing with pin 3, no payload, no non-blocking library.
The handleRequest() could return a single byte. Check with the logic analyzer if you can see that.
Can you show the small test-sketch and a picture of the logic analyzer capture ?

Do you have a expensive apparatus as logic analyzer or a simple USB logic analyzer. Even a simple USB logic analyzer of 20 dollars/euros is much better than a dedicated apparatus.

Is this allowed in 'C' or 'C++': payload[0] = {SERIAL_2_I2C_ACK};
Why do you call serialEvent() ? Arduino has already a function serialEvent(). Are you trying to override the standard Arduino function ? By the way, no one uses serialEvent() because it has no benefits.
When the Master sends more than three bytes, your sketch will have a buffer overflow.
A variable that is used both in a interrupt and in the loop() should be 'volatile'.
If you have to reset the I2C bus, then there is something very wrong.