§ TOP-схема
Тактировать на 25 мгц, но в целом, можно на любой близкой частоте.Эта версия отличается от предыдущей тем, что здесь учтена проверка бита четности, а также истечение таймаута для предотвращения зависания в статусе чтения, улучшена установка done на негативном фронте.
1wire [ 7:0] ps_data; 2wire ps_done; 3 4ps2 Keyb 5( 6 .clock (clock_25), 7 .ps_clock (PS2_CLK), 8 .ps_data (PS2_DAT), 9 .done (ps_done), 10 .data (ps_data) 11); 12 13// Пример имплементации 14reg [7:0] new_data; 15always @(posedge clock_25) 16 if (ps_done) 17 new_data <= ps_data;
§ Код ps2.v
1module ps2 2( 3 input clock, 4 input ps_clock, 5 input ps_data, 6 7 output reg done, 8 output reg [7:0] data 9); 10 11reg kbusy = 1'b0; 12reg kdone = 1'b0; 13reg [1:0] klatch = 2'b00; 14reg [3:0] kcount = 1'b0; 15reg [9:0] kin = 1'b0; 16reg [19:0] kout = 1'b0; 17 18initial begin data = 8'h00; done = 1'b0; end 19 20// Для повышения точности 21always @(negedge clock) done <= kdone; 22 23// Основная логика работы контроллера 24always @(posedge clock) begin 25 26 kdone <= 1'b0; 27 28 // Процесс приема сигнала 29 if (kbusy) begin 30 31 // Позитивный фронт 32 if (klatch == 2'b01) begin 33 34 // Завершающий такт 35 if (kcount == 4'hA) begin 36 37 data <= kin[8:1]; 38 kbusy <= 1'b0; 39 kdone <= ^kin[9:1]; // =1 Если четность совпадает 40 41 end 42 43 kcount <= kcount + 1'b1; 44 kin <= {ps_data, kin[9:1]}; 45 46 end 47 48 // Считать "зависший процесс" 49 kout <= ps_clock ? kout + 1 : 1'b0; 50 51 // И если прошло более 20 мс, то перевести в состояние ожидания 52 if (kout > 25000*20) kbusy <= 1'b0; 53 54 end else begin 55 56 // Обнаружен негативный фронт \__ 57 if (klatch == 2'b10) begin 58 59 kbusy <= 1'b1; // Активировать прием данных 60 kcount <= 1'b0; 61 kout <= 1'b0; 62 63 end 64 65 end 66 67 klatch <= {klatch[0], ps_clock}; 68 69end 70 71endmodule