module test3(inout sda, input scl); localparam I2C_ADR = 7'h27; reg adr_match; // флажок совпадения адреса устройства reg [1:0] phase; // b10 или b00 - проверка адреса устройства, b01 - запись адреса регистра, b11 - запись значения регистра reg [7:0] reg_mem; // значение адреса регистра reg [7:0] val_mem; // значение регистра reg [3:0] bitcnt; // счетчик битов reg start; // устанавливаем start = 1 при обнаружении START последовательности // другие события устанавливают start = 0 always @(negedge sda or negedge scl) if(~sda) start <= scl; else start <= 0; always @(negedge scl or posedge start) if(start) begin // start = 1, сработал триггер posedge start bitcnt <= 4'h0; // инициируем счетчик битов phase <= 2'b00; // переходим к проверки адреса устройства end else begin // start = 0, сработал триггер negedge scl if(bitcnt[3]) begin // считали последний бит bitcnt <= 4'h0; // инициируем счетчик битов phase <= (~phase[0]) ? 2'b01 : 2'b11 ; // переходим к записи либо адреса либо значения регистра end else bitcnt <= bitcnt + 4'h1; // инкрементируем счетчик битов end always @(posedge scl) begin if(~phase[0]) begin // проверка адреса устройства if(bitcnt == 4'h1) adr_match <= (sda == I2C_ADR[6]); // поднимаем флажок если первые биты совпадают else if(bitcnt < 4'h8 && sda != I2C_ADR[4'h7 - bitcnt]) adr_match <= 1'b0; // сбрасываем, если хотя бы один не совпал end else if(~phase[1] && adr_match) reg_mem[4'h8 - bitcnt] <= sda; // запись адреса регистра else if(adr_match) val_mem[4'h8 - bitcnt] <= sda; // запись значения регистра end // переполнение счетчика, считали последний бит // если адрес устройства совпадает, устанавливаем sda = 0 // иначе устанавливаем sda в режим high impedance assign sda = (bitcnt[3] && adr_match) ? 1'b0 : 1'bz; endmodule