• Techo

[IC design] 使用ps2 protocal的keyboard通訊協定的verilog code

因為網路上都沒有一個真正可以動的 ps2 uart 接收鍵盤按鍵的 verilog 程式

找到後來我乾脆自己寫了一個

ps2的接頭有自己的clock rate

所以不用管 uart 通訊的 baud rate 是多少

由於 ps2_clk 的速度非常慢

所以接收 uart 的 code 不應該用高速的 system clock 來做

應該使用 ps2_clk來接收資料即可

至於接收到的資料要讓高速 clock 使用就必須使用 clock domain crossing

CDC的方式就不在這篇提了 我以前好像有寫過



module ps2_keyboard_listener (

input rst_n,

input ps2_clk,

input ps2_data,

output reg [2:0] kb_enter,

output reg[7:0] ps2_byte_r,

output reg ps2_vld

);


reg[7:0] byte_tmp;

wire [7:0] rx_data;

wire data_vld;

rx urx (

.clk(ps2_clk),

.reset_n(rst_n),

.din(ps2_data),

.data(rx_data),

.data_vld(data_vld),

.parity_error(),

.protocal_error()

);



always @(posedge ps2_clk or negedge rst_n) begin

if(~rst_n) begin

byte_tmp <= 0;

end else if (data_vld) begin

byte_tmp <= rx_data;

end

end


wire kb_vld = (rx_data == 8'hf0) & data_vld;

always @(posedge ps2_clk or negedge rst_n) begin

if(~rst_n) begin

ps2_byte_r <= 0;

end else if (kb_vld) begin

ps2_byte_r <= byte_tmp;

end

end


always @(posedge ps2_clk or negedge rst_n) begin

if(~rst_n) begin

ps2_vld <= 0;

end else if (ps2_vld) begin

ps2_vld <= 0;

end else if (kb_vld) begin

ps2_vld <= 1'b1;

end

end


parameter A = 3'b001;

parameter B = 3'b010;

parameter C = 3'b011;

parameter D = 3'b100;

parameter E = 3'b101;

parameter F = 3'b110;

always@(ps2_byte_r)

begin

case( ps2_byte_r)

8'h1c://a

kb_enter = A;

8'h32://b

kb_enter = B;

8'h21://c

kb_enter = C;

8'h23://d

kb_enter = D;

8'h24://e

kb_enter = E;

8'h2b://f

kb_enter = F;

default:

kb_enter = 3'b000;

endcase

end


endmodule


module rx(

input clk,

input reset_n,

input din,

output reg [7:0]data,

output data_vld,

output reg parity_error,

output reg protocal_error

);


reg [3:0]count;

wire [3:0] count_nx;

wire start;

wire parity;

wire stop;

wire [7:0]data_nx;

wire parity_error_nx;

wire protocal_error_nx;



assign start = (count == 4'd0) & (~din);

assign tras = (count > 4'd0) & (count < 4'd9);

assign parity = count == 4'd9;

assign stop = count == 4'd10;

assign count_nx = (start) ? 4'd1 :

(tras | parity) ? (count + 4'd1) :

(stop) ? 4'd0 : count;


assign data_nx = (tras) ? {din, data[7:1]}: data;

assign parity_error_nx = (parity) ? ^data: 1'd0;

assign protocal_error_nx = (stop & (~din));


always @(posedge clk or negedge reset_n) begin

if(~reset_n) begin

data <= 8'd0;

count <= 4'd0;

end else begin

data <= data_nx;

count <= count_nx;

end

end




always @(posedge clk or negedge reset_n) begin

if(~reset_n) begin

parity_error <= 1'd0;

end else if(~parity_error) begin

parity_error <= parity_error_nx;

end

end




always @(posedge clk or negedge reset_n) begin

if(~reset_n) begin

protocal_error <= 1'd0;

end else if(~protocal_error) begin

protocal_error <= protocal_error_nx;

end

end


assign data_vld = count == 4'd9;

endmodule : rx

150 次瀏覽0 則留言
Logo2020.JPG