📄 ps2_keyboard_interface.v
字号:
m1_next_state <= m1_tx_done_recovery;
end
m1_tx_error_no_keyboard_ack :
begin
tx_error_no_keyboard_ack_r <= 1'b1;
if (ps2_clk_in_r && ps2_data_in_r)
m1_next_state <= m1_rx_clk_h;
else
m1_next_state <= m1_tx_error_no_keyboard_ack;
end
default : m1_next_state <= m1_rx_clk_h;
endcase
end
//**************************************************************************************
//**************************************************************************************
//产生数据输出状态标志rx_data_ready_r = 1 时有数据输出,rx_data_ready_r = 0 时无数据输出
//读取数据时(rx_read = 1)清 rx_data_ready_r为0.
//状态机M2
always @(posedge clock)
begin
if (reset)
m2_state <= m2_rx_data_ready_ack;
else
m2_state <= m2_next_state;
end
//M2状态转换逻辑
always @(m2_state or rx_output_strobe or rx_read)
begin
case (m2_state)
m2_rx_data_ready_ack:
begin
rx_data_ready_r <= 1'b0;
if (rx_output_strobe)
m2_next_state <= m2_rx_data_ready;
else
m2_next_state <= m2_rx_data_ready_ack;
end
m2_rx_data_ready:
begin
rx_data_ready_r <= 1'b1;
if (rx_read)
m2_next_state <= m2_rx_data_ready_ack;
else
m2_next_state <= m2_rx_data_ready;
end
default : m2_next_state <= m2_rx_data_ready_ack;
endcase
end
//**************************************************************************************
//位移位计数器
always @(posedge clock)
begin
if (reset || rx_shifting_done || (m1_state == m1_tx_wait_keyboard_ack))
bit_count <= 4'd0;
else if (timer_400usec_done && (m1_state == m1_rx_clk_h) && (ps2_clk_in_r))
bit_count <= 4'd0;
else if ( (m1_state == m1_rx_falling_edge_marker) ||(m1_state == m1_tx_rising_edge_marker))
bit_count <= bit_count + 4'd1;
end
//指示一帧数据读完或写完
assign rx_shifting_done = (bit_count == `TOTAL_BITS);
assign tx_shifting_done = (bit_count == `TOTAL_BITS-1);
//这个信号用来使能加载要发送到PS/2键盘的数据到移位害存器
//同时也指示指令开始传输
assign tx_write_ack = ( (tx_write && (m1_state == m1_rx_clk_h))
||(tx_write && (m1_state == m1_rx_clk_l))
);
//奇验证位.
assign tx_parity_bit = ~^tx_data;
//串行数据移位寄存器
always @(posedge clock)
begin
if (reset)
q <= 0;
else if (tx_write_ack)
q <= {1'b1,tx_parity_bit,tx_data,1'b0};
else if ( (m1_state == m1_rx_falling_edge_marker) || (m1_state == m1_tx_rising_edge_marker) )
q <= {ps2_data_in_r,q[`TOTAL_BITS-1:1]};
end
//400us定时器计数器
always @(posedge clock)
begin
if (~enable_timer_400usec)
timer_400usec_count <= 0;
else if (~timer_400usec_done)
timer_400usec_count <= timer_400usec_count + 1;
end
assign timer_400usec_done = (timer_400usec_count == (TIMER_400USEC_VALUE - 1));
//5us定时器计数器
always @(posedge clock)
begin
if (~enable_timer_5usec)
timer_5usec_count <= 0;
else if (~timer_5usec_done)
timer_5usec_count <= timer_5usec_count + 1;
end
assign timer_5usec_done = (timer_5usec_count == TIMER_5USEC_VALUE - 1);
//输出扩展码标志及断码标志
assign extended = (q[8:1] == `EXTEND_CODE) && rx_shifting_done;
assign released = (q[8:1] == `RELEASE_CODE) && rx_shifting_done;
//复位或输出有效键码(非0xF0或0xE0)时清零扩展、断码标志位
//输出键码为扩展、断码时置相应标志位
always @(posedge clock)
begin
if (reset || rx_output_event)
begin
hold_extended <= 0;
hold_released <= 0;
end
else
begin
if (rx_shifting_done && extended)
hold_extended <= 1;
if (rx_shifting_done && released)
hold_released <= 1;
end
end
//**************************************************************************************
//shift按键检测
//
//左shift键
always @(posedge clock)
begin
if (reset)
left_shift_key <= 0;
else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && ~hold_released) //shift键通码
left_shift_key <= 1;
else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && hold_released) //shift键断码
left_shift_key <= 0;
end
//右shift键
always @(posedge clock)
begin
if (reset)
right_shift_key <= 0;
else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && ~hold_released) //shift键通码
right_shift_key <= 1;
else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && hold_released) //shift键断码
right_shift_key <= 0;
end
//输出shift状态标志
//输出1:shift键有按住
//输出0:shift键无按住
assign rx_shift_key_on = left_shift_key || right_shift_key;
//**************************************************************************************
//输出特殊扫描码标志位,及扫描码值和ASCII码
//通过rx_extended_r、rx_released_r的值可判断是断码还是通码,还是扩展码
always @(posedge clock)
begin
if (reset)
begin
rx_extended_r <= 1'b0;
rx_released_r <= 1'b0;
rx_scan_code_r <= 8'd0;
rx_ascii_r <= 8'd0;
end
else if (rx_output_strobe)
begin
rx_extended_r <= hold_extended; //载入之前保存的状态值
rx_released_r <= hold_released; //载入之前保存的状态值
rx_scan_code_r <= q[8:1];
rx_ascii_r <= {1'b0,ascii};
end
end
//收到键盘发送过来的键码,且不是0xE0(扩展码前都有0xE0)和0xF0(断码前都有0xF0)
assign rx_output_event = (rx_shifting_done
&& ~extended
&& ~released
);
//收到键盘发送过来的键码,且不是0xE0(扩展码前都有0xE0)和0xF0(断码前都有0xF0)
//而且不是shift的键值
assign rx_output_strobe = (rx_shifting_done
&& ~extended
&& ~released
&& ( (TRAP_SHIFT_KEYS == 0)
|| ( (q[8:1] != `RIGHT_SHIFT)
&&(q[8:1] != `LEFT_SHIFT)
)
)
);
//这部分将键盘的扫描码转找成ASCII码,这里只列了一部分,如果还要
//增加更多的键码,可以找到相关的扫描键码增加到下面CASE语句中。
assign shift_key_plus_code = {rx_shift_key_on,q[8:1]};
//表中9'hXXX最高位为1表示有SHIFT键按下
always @(shift_key_plus_code)
begin
casez (shift_key_plus_code)
9'h?66 : ascii <= 7'h08; // 删除键 "backspace"key
9'h?0d : ascii <= 7'h09; // Tab键
9'h?5a : ascii <= 7'h0d; // 回车键 "enter"key
9'h?76 : ascii <= 7'h1b; // Escape "esc"key
9'h?29 : ascii <= 7'h20; // 空格键"Space"key
9'h116 : ascii <= 7'h21; // !
9'h152 : ascii <= 7'h22; // "
9'h126 : ascii <= 7'h23; // #
9'h125 : ascii <= 7'h24; // $
9'h12e : ascii <= 7'h25; // %
9'h13d : ascii <= 7'h26; // &
9'h052 : ascii <= 7'h27; // '
9'h146 : ascii <= 7'h28; // (
9'h145 : ascii <= 7'h29; // )
9'h13e : ascii <= 7'h2a; // *
9'h155 : ascii <= 7'h2b; // +
9'h041 : ascii <= 7'h2c; // ,
9'h04e : ascii <= 7'h2d; // -
9'h049 : ascii <= 7'h2e; // .
9'h04a : ascii <= 7'h2f; // /
9'h045 : ascii <= 7'h30; // 0
9'h016 : ascii <= 7'h31; // 1
9'h01e : ascii <= 7'h32; // 2
9'h026 : ascii <= 7'h33; // 3
9'h025 : ascii <= 7'h34; // 4
9'h02e : ascii <= 7'h35; // 5
9'h036 : ascii <= 7'h36; // 6
9'h03d : ascii <= 7'h37; // 7
9'h03e : ascii <= 7'h38; // 8
9'h046 : ascii <= 7'h39; // 9
9'h14c : ascii <= 7'h3a; // :
9'h04c : ascii <= 7'h3b; // ;
9'h141 : ascii <= 7'h3c; // <
9'h055 : ascii <= 7'h3d; // =
9'h149 : ascii <= 7'h3e; // >
9'h14a : ascii <= 7'h3f; // ?
9'h11e : ascii <= 7'h40; // @
9'h11c : ascii <= 7'h41; // A
9'h132 : ascii <= 7'h42; // B
9'h121 : ascii <= 7'h43; // C
9'h123 : ascii <= 7'h44; // D
9'h124 : ascii <= 7'h45; // E
9'h12b : ascii <= 7'h46; // F
9'h134 : ascii <= 7'h47; // G
9'h133 : ascii <= 7'h48; // H
9'h143 : ascii <= 7'h49; // I
9'h13b : ascii <= 7'h4a; // J
9'h142 : ascii <= 7'h4b; // K
9'h14b : ascii <= 7'h4c; // L
9'h13a : ascii <= 7'h4d; // M
9'h131 : ascii <= 7'h4e; // N
9'h144 : ascii <= 7'h4f; // O
9'h14d : ascii <= 7'h50; // P
9'h115 : ascii <= 7'h51; // Q
9'h12d : ascii <= 7'h52; // R
9'h11b : ascii <= 7'h53; // S
9'h12c : ascii <= 7'h54; // T
9'h13c : ascii <= 7'h55; // U
9'h12a : ascii <= 7'h56; // V
9'h11d : ascii <= 7'h57; // W
9'h122 : ascii <= 7'h58; // X
9'h135 : ascii <= 7'h59; // Y
9'h11a : ascii <= 7'h5a; // Z
9'h054 : ascii <= 7'h5b; // [
9'h05d : ascii <= 7'h5c; // '\'
9'h05b : ascii <= 7'h5d; // ]
9'h136 : ascii <= 7'h5e; // ^
9'h14e : ascii <= 7'h5f; // _
9'h00e : ascii <= 7'h60; // `
9'h01c : ascii <= 7'h61; // a
9'h032 : ascii <= 7'h62; // b
9'h021 : ascii <= 7'h63; // c
9'h023 : ascii <= 7'h64; // d
9'h024 : ascii <= 7'h65; // e
9'h02b : ascii <= 7'h66; // f
9'h034 : ascii <= 7'h67; // g
9'h033 : ascii <= 7'h68; // h
9'h043 : ascii <= 7'h69; // i
9'h03b : ascii <= 7'h6a; // j
9'h042 : ascii <= 7'h6b; // k
9'h04b : ascii <= 7'h6c; // l
9'h03a : ascii <= 7'h6d; // m
9'h031 : ascii <= 7'h6e; // n
9'h044 : ascii <= 7'h6f; // o
9'h04d : ascii <= 7'h70; // p
9'h015 : ascii <= 7'h71; // q
9'h02d : ascii <= 7'h72; // r
9'h01b : ascii <= 7'h73; // s
9'h02c : ascii <= 7'h74; // t
9'h03c : ascii <= 7'h75; // u
9'h02a : ascii <= 7'h76; // v
9'h01d : ascii <= 7'h77; // w
9'h022 : ascii <= 7'h78; // x
9'h035 : ascii <= 7'h79; // y
9'h01a : ascii <= 7'h7a; // z
9'h154 : ascii <= 7'h7b; // {
9'h15d : ascii <= 7'h7c; // |
9'h15b : ascii <= 7'h7d; // }
9'h10e : ascii <= 7'h7e; // ~
9'h?71 : ascii <= 7'h7f; // Delete键或小键盘的DEL键
default : ascii <= 7'h2e; // '.' 代表其它没列出的字符
endcase
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -