📄 ps2_keyboard_interface.vhd
字号:
-- State register
m1_state_register : process( clk, reset, m1_state )
begin
if clk'event and clk='1' then
if (reset = '1') then
m1_state <= m1_rx_clk_h;
else
m1_state <= m1_next_state;
end if;
end if;
end process;
m1_state_logic : process( m1_state, q,
tx_shifting_done, tx_write,
ps2_clk_s, ps2_data_s,
timer_60usec_done, timer_5usec_done )
begin
-- Output signals default to this value, unless changed in a state condition.
ps2_clk_hi_z <= '1';
ps2_data_hi_z <= '1';
tx_error_no_keyboard_ack <= '0';
enable_timer_60usec <= '0';
enable_timer_5usec <= '0';
case (m1_state) is
when m1_rx_clk_h =>
enable_timer_60usec <= '1';
if (tx_write = '1') then
m1_next_state <= m1_tx_reset_timer;
elsif (ps2_clk_s = '0') then
m1_next_state <= m1_rx_falling_edge_marker;
else
m1_next_state <= m1_rx_clk_h;
end if;
when m1_rx_falling_edge_marker =>
enable_timer_60usec <= '0';
m1_next_state <= m1_rx_clk_l;
when m1_rx_rising_edge_marker =>
enable_timer_60usec <= '0';
m1_next_state <= m1_rx_clk_h;
when m1_rx_clk_l =>
enable_timer_60usec <= '1';
if (tx_write = '1') then
m1_next_state <= m1_tx_reset_timer;
elsif (ps2_clk_s = '1') then
m1_next_state <= m1_rx_rising_edge_marker;
else
m1_next_state <= m1_rx_clk_l;
end if;
when m1_tx_reset_timer =>
enable_timer_60usec <= '0';
m1_next_state <= m1_tx_force_clk_l;
when m1_tx_force_clk_l =>
enable_timer_60usec <= '1';
ps2_clk_hi_z <= '0'; -- Force the ps2_clk line low.
if (timer_60usec_done = '1') then
m1_next_state <= m1_tx_first_wait_clk_h;
else
m1_next_state <= m1_tx_force_clk_l;
end if;
when m1_tx_first_wait_clk_h =>
enable_timer_5usec <= '1';
ps2_data_hi_z <= '0'; -- Start bit.
if (ps2_clk_s = '0') and (timer_5usec_done = '1') then
m1_next_state <= m1_tx_clk_l;
else
m1_next_state <= m1_tx_first_wait_clk_h;
end if;
-- This state must be included because the device might possibly
-- delay for up to 10 milliseconds before beginning its clock pulses.
-- During that waiting time, we cannot drive the data (q[0]) because it
-- is possibly 1, which would cause the keyboard to abort its receive
-- and the expected clocks would then never be generated.
when m1_tx_first_wait_clk_l =>
ps2_data_hi_z <= '0';
if (ps2_clk_s = '0') then
m1_next_state <= m1_tx_clk_l;
else
m1_next_state <= m1_tx_first_wait_clk_l;
end if;
when m1_tx_wait_clk_h =>
enable_timer_5usec <= '1';
ps2_data_hi_z <= q(0);
if (ps2_clk_s = '1') and (timer_5usec_done = '1') then
m1_next_state <= m1_tx_rising_edge_marker;
else
m1_next_state <= m1_tx_wait_clk_h;
end if;
when m1_tx_rising_edge_marker =>
ps2_data_hi_z <= q(0);
m1_next_state <= m1_tx_clk_h;
when m1_tx_clk_h =>
ps2_data_hi_z <= q(0);
if (tx_shifting_done = '1') then
m1_next_state <= m1_tx_wait_keyboard_ack;
elsif (ps2_clk_s = '0') then
m1_next_state <= m1_tx_clk_l;
else
m1_next_state <= m1_tx_clk_h;
end if;
when m1_tx_clk_l =>
ps2_data_hi_z <= q(0);
if (ps2_clk_s = '1') then
m1_next_state <= m1_tx_wait_clk_h;
else
m1_next_state <= m1_tx_clk_l;
end if;
when m1_tx_wait_keyboard_ack =>
if (ps2_clk_s = '0') and (ps2_data_s = '1') then
m1_next_state <= m1_tx_error_no_keyboard_ack;
elsif (ps2_clk_s = '0') and (ps2_data_s = '0') then
m1_next_state <= m1_tx_done_recovery;
else
m1_next_state <= m1_tx_wait_keyboard_ack;
end if;
when m1_tx_done_recovery =>
if (ps2_clk_s = '1') and (ps2_data_s = '1') then
m1_next_state <= m1_rx_clk_h;
else
m1_next_state <= m1_tx_done_recovery;
end if;
when m1_tx_error_no_keyboard_ack =>
tx_error_no_keyboard_ack <= '1';
if (ps2_clk_s = '1') and (ps2_data_s ='1') then
m1_next_state <= m1_rx_clk_h;
else
m1_next_state <= m1_tx_error_no_keyboard_ack;
end if;
when others =>
m1_next_state <= m1_rx_clk_h;
end case;
end process;
-- State register
m2_state_register : process( clk )
begin
if clk'event and clk='1' then
if (reset = '1') then
m2_state <= m2_rx_data_ready_ack;
else
m2_state <= m2_next_state;
end if;
end if;
end process;
-- State transition logic
m2_state_logic : process(m2_state, rx_output_strobe, rx_read)
begin
case (m2_state) is
when m2_rx_data_ready_ack =>
rx_data_ready <= '0';
if (rx_output_strobe = '1') then
m2_next_state <= m2_rx_data_ready;
else
m2_next_state <= m2_rx_data_ready_ack;
end if;
when m2_rx_data_ready =>
rx_data_ready <= '1';
if (rx_read = '1') then
m2_next_state <= m2_rx_data_ready_ack;
else
m2_next_state <= m2_rx_data_ready;
end if;
when others =>
m2_next_state <= m2_rx_data_ready_ack;
end case;
end process;
-- This is the bit counter
bit_counter: process(clk, reset, m1_state, bit_count )
begin
if clk'event and clk = '1' then
if ( reset = '1' ) or
( rx_shifting_done = '1' ) or
(m1_state = m1_tx_wait_keyboard_ack) then -- After tx is done.
bit_count <= "0000"; -- normal reset
elsif (timer_60usec_done = '1' ) and
(m1_state = m1_rx_clk_h) and
(ps2_clk_s = '1') then
bit_count <= "0000"; -- rx watchdog timer reset
elsif (m1_state = m1_rx_falling_edge_marker) or -- increment for rx
(m1_state = m1_tx_rising_edge_marker) then -- increment for tx
bit_count <= bit_count + 1;
end if;
end if;
end process;
assign: process( bit_count, tx_write, tx_write_ack_o, m1_state )
begin
if (bit_count = TOTAL_BITS) then
rx_shifting_done <= '1';
else
rx_shifting_done <= '0';
end if;
if (bit_count = (TOTAL_BITS-1)) then
tx_shifting_done <= '1';
else
tx_shifting_done <= '0';
end if;
-- This is the signal which enables loading of the shift register.
-- It also indicates "ack" to the device writing to the transmitter.
if ((tx_write = '1') and (m1_state = m1_rx_clk_h)) or
((tx_write = '1') and (m1_state = m1_rx_clk_l)) then
tx_write_ack_o <= '1';
else
tx_write_ack_o <= '0';
end if;
tx_write_ack <= tx_write_ack_o;
end process;
-- This is the ODD parity bit for the transmitted word.
-- assign tx_parity_bit = ~^tx_data;
--
tx_parity_bit <= not( tx_data(7) xor tx_data(6) xor tx_data(5) xor tx_data(4) xor
tx_data(7) xor tx_data(6) xor tx_data(5) xor tx_data(4) );
-- This is the shift register
q_shift : process(clk, tx_write_ack_o, tx_parity_bit, tx_data,
m1_state, q, ps2_data_s, rx_shifting_done )
begin
if clk'event and clk='1' then
if (reset = '1') then
q <= "00000000000";
elsif (tx_write_ack_o = '1') then
q <= "1" & tx_parity_bit & tx_data & "0";
elsif ( (m1_state = m1_rx_falling_edge_marker) or
(m1_state = m1_tx_rising_edge_marker) ) then
q <= ps2_data_s & q((TOTAL_BITS-1) downto 1);
end if;
end if;
-- Create the signals which indicate special scan codes received.
-- These are the "unlatched versions."
if (q(8 downto 1) = EXTEND_CODE) and (rx_shifting_done = '1') then
extended <= '1';
else
extended <= '0';
end if;
if (q(8 downto 1) = RELEASE_CODE) and (rx_shifting_done = '1') then
released <= '1';
else
released <= '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -