module ps2_host ( input wire clk, input wire rst, input wire ps2_ck, input wire ps2_dat, output reg [7:0] data, output reg valid, input wire ack ); reg prev_ps2_ck; always @(posedge clk) begin if (rst) begin prev_ps2_ck <= 1'b1; end else begin prev_ps2_ck <= ps2_ck; end end wire ck_fallen = !prev_ps2_ck && !ps2_ck; wire ck_risen = prev_ps2_ck && ps2_ck; reg ck_state, prev_ck_state; always @(posedge clk) begin if (rst) begin ck_state <= 1'b1; prev_ck_state <= 1'b1; end else begin if (ck_state && ck_fallen) begin ck_state <= 1'b0; end else if (!ck_state && ck_risen) begin ck_state <= 1'b1; end prev_ck_state <= ck_state; end end wire ck_falling = prev_ck_state && !ck_state; reg [3:0] cntr; always @(posedge clk) begin if (rst) begin cntr <= 4'b0; end else if (ck_falling) begin cntr <= cntr + 4'b1; end else if (cntr == 4'd11) begin cntr <= 4'b0; end end reg [10:0] shr; always @(posedge clk) begin if (rst) begin shr <= 11'b0; end else if (ck_falling) begin shr <= { ps2_dat, shr[10:1] }; end end always @(posedge clk) begin if (rst) begin data <= 8'b0; valid <= 1'b0; end else begin if (valid && ack) begin valid <= 1'b0; end if (cntr == 4'd11) begin data <= shr[8:1]; valid <= 1'b1; end end end endmodule