Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement