Guest User

Untitled

a guest
Jun 2nd, 2016
263
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module i2c_slave(sda, scl);
  2. inout sda;
  3. input scl;
  4.  
  5. localparam I2C_ADR = 7'h27;
  6.  
  7. reg adr_match; // флажок совпадения адреса устройства
  8. reg [2:0] phase; // 01 - проверка адреса устройства, 10 - запись адреса регистра, 00 - запись значения регистра
  9. reg [7:0] reg_mem; // значение адреса регистра
  10. reg [7:0] val_mem; // значение регистра
  11. reg [3:0] bitcnt; // счетчик битов
  12. reg start;
  13.  
  14. // устанавливаем start = 1 при обнаружении START последовательности
  15. // другие события устанавливают start = 0
  16. always @(negedge sda or negedge scl) if(~sda) start <= scl; else start <= 0;
  17.  
  18. always @(negedge scl or posedge start)
  19. if(start) begin // start = 1, сработал триггер posedge start
  20.     bitcnt <= 4'h8; // инициируем счетчик битов
  21.     phase = 2'b01; // переходим к проверки адреса устройства
  22. end else begin // start = 0, сработал триггер negedge scl
  23.     if(bitcnt[3]) begin // считали последний бит
  24.         bitcnt <= 4'h8; // инициируем счетчик битов
  25.         phase <= phase << 1; // переходим к записи либо адреса либо значения регистра
  26.     end else
  27.         bitcnt <= bitcnt - 4'h1; // уменьшаем счетчик битов
  28. end
  29.  
  30.  
  31. always @(posedge scl)
  32. begin
  33. // проверка адреса устройства
  34. // первый бит адреса, если совпадают - поднимаем флажок совпадения
  35. // если хотя бы один бит не совпадает - сбрасываем флажок совпадения
  36. if(phase[0] & bitcnt == 7) adr_match <= (sda == I2C_ADR[6]);
  37. if(phase[0] & bitcnt == 6 & sda != I2C_ADR[5]) adr_match <= 1'b0;
  38. if(phase[0] & bitcnt == 5 & sda != I2C_ADR[4]) adr_match <= 1'b0;
  39. if(phase[0] & bitcnt == 4 & sda != I2C_ADR[3]) adr_match <= 1'b0;
  40. if(phase[0] & bitcnt == 3 & sda != I2C_ADR[2]) adr_match <= 1'b0;
  41. if(phase[0] & bitcnt == 2 & sda != I2C_ADR[1]) adr_match <= 1'b0;
  42. if(phase[0] & bitcnt == 1 & sda != I2C_ADR[0]) adr_match <= 1'b0;
  43. // запись адреса регистра, только если адрес устройства совпадает
  44. if(phase[1] & adr_match) reg_mem[bitcnt] <= sda;
  45. // запись значения регистра, только если адрес устройства совпадает
  46. if(phase == 2'b00 & adr_match) val_mem[bitcnt] <= sda;
  47. end
  48. // переполнение счетчика, считали последний бит
  49. // если адрес устройства совпадает, прижимаем sda
  50. // иначе позволяем прижать другому устройству
  51. assign sda = (bitcnt[3] & adr_match) ? 1'b0 : 1'bz;
  52.  
  53. endmodule
Add Comment
Please, Sign In to add comment