Line 252... |
Line 252... |
// Input "synchronizing" logic -- synchronizes the inputs to the state
|
// Input "synchronizing" logic -- synchronizes the inputs to the state
|
// machine clock, thus avoiding errors related to
|
// machine clock, thus avoiding errors related to
|
// spurious state machine transitions.
|
// spurious state machine transitions.
|
always @(posedge clk)
|
always @(posedge clk)
|
begin
|
begin
|
ps2_clk_ms <= ps2_clk_i;
|
ps2_clk_ms <= #1 ps2_clk_i;
|
ps2_data_ms <= ps2_data_i;
|
ps2_data_ms <= #1 ps2_data_i;
|
|
|
ps2_clk_s <= ps2_clk_ms;
|
ps2_clk_s <= #1 ps2_clk_ms;
|
ps2_data_s <= ps2_data_ms;
|
ps2_data_s <= #1 ps2_data_ms;
|
|
|
end
|
end
|
|
|
// State register
|
// State register
|
always @(posedge clk or posedge reset)
|
always @(posedge clk or posedge reset)
|
begin : m1_state_register
|
begin : m1_state_register
|
if (reset) m1_state <= m1_rx_clk_h;
|
if (reset) m1_state <= #1 m1_rx_clk_h;
|
else m1_state <= m1_next_state;
|
else m1_state <= #1 m1_next_state;
|
end
|
end
|
|
|
// State transition logic
|
// State transition logic
|
always @(m1_state
|
always @(m1_state
|
or q
|
or q
|
Line 280... |
Line 280... |
or timer_5usec_done
|
or timer_5usec_done
|
)
|
)
|
begin : m1_state_logic
|
begin : m1_state_logic
|
|
|
// Output signals default to this value, unless changed in a state condition.
|
// Output signals default to this value, unless changed in a state condition.
|
ps2_clk_hi_z <= 1;
|
ps2_clk_hi_z <= #1 1;
|
ps2_data_hi_z <= 1;
|
ps2_data_hi_z <= #1 1;
|
tx_error_no_keyboard_ack <= 0;
|
tx_error_no_keyboard_ack <= #1 1'b0;
|
enable_timer_60usec <= 0;
|
enable_timer_60usec <= #1 0;
|
enable_timer_5usec <= 0;
|
enable_timer_5usec <= #1 0;
|
|
|
case (m1_state)
|
case (m1_state)
|
|
|
m1_rx_clk_h :
|
m1_rx_clk_h :
|
begin
|
begin
|
enable_timer_60usec <= 1;
|
enable_timer_60usec <= #1 1;
|
if (tx_write) m1_next_state <= m1_tx_reset_timer;
|
if (tx_write) m1_next_state <= #1 m1_tx_reset_timer;
|
else if (~ps2_clk_s) m1_next_state <= m1_rx_falling_edge_marker;
|
else if (~ps2_clk_s) m1_next_state <= #1 m1_rx_falling_edge_marker;
|
else m1_next_state <= m1_rx_clk_h;
|
else m1_next_state <= #1 m1_rx_clk_h;
|
end
|
end
|
|
|
m1_rx_falling_edge_marker :
|
m1_rx_falling_edge_marker :
|
begin
|
begin
|
enable_timer_60usec <= 0;
|
enable_timer_60usec <= #1 0;
|
m1_next_state <= m1_rx_clk_l;
|
m1_next_state <= #1 m1_rx_clk_l;
|
end
|
end
|
|
|
m1_rx_rising_edge_marker :
|
m1_rx_rising_edge_marker :
|
begin
|
begin
|
enable_timer_60usec <= 0;
|
enable_timer_60usec <= #1 0;
|
m1_next_state <= m1_rx_clk_h;
|
m1_next_state <= #1 m1_rx_clk_h;
|
end
|
end
|
|
|
|
|
m1_rx_clk_l :
|
m1_rx_clk_l :
|
begin
|
begin
|
enable_timer_60usec <= 1;
|
enable_timer_60usec <= #1 1;
|
if (tx_write) m1_next_state <= m1_tx_reset_timer;
|
if (tx_write) m1_next_state <= #1 m1_tx_reset_timer;
|
else if (ps2_clk_s) m1_next_state <= m1_rx_rising_edge_marker;
|
else if (ps2_clk_s) m1_next_state <= #1 m1_rx_rising_edge_marker;
|
else m1_next_state <= m1_rx_clk_l;
|
else m1_next_state <= #1 m1_rx_clk_l;
|
end
|
end
|
|
|
m1_tx_reset_timer:
|
m1_tx_reset_timer:
|
begin
|
begin
|
enable_timer_60usec <= 0;
|
enable_timer_60usec <= #1 0;
|
m1_next_state <= m1_tx_force_clk_l;
|
m1_next_state <= #1 m1_tx_force_clk_l;
|
end
|
end
|
|
|
m1_tx_force_clk_l :
|
m1_tx_force_clk_l :
|
begin
|
begin
|
enable_timer_60usec <= 1;
|
enable_timer_60usec <= #1 1;
|
ps2_clk_hi_z <= 0; // Force the ps2_clk line low.
|
ps2_clk_hi_z <= #1 0; // Force the ps2_clk line low.
|
if (timer_60usec_done) m1_next_state <= m1_tx_first_wait_clk_h;
|
if (timer_60usec_done) m1_next_state <= #1 m1_tx_first_wait_clk_h;
|
else m1_next_state <= m1_tx_force_clk_l;
|
else m1_next_state <= #1 m1_tx_force_clk_l;
|
end
|
end
|
|
|
m1_tx_first_wait_clk_h :
|
m1_tx_first_wait_clk_h :
|
begin
|
begin
|
enable_timer_5usec <= 1;
|
enable_timer_5usec <= #1 1;
|
ps2_data_hi_z <= 0; // Start bit.
|
ps2_data_hi_z <= #1 0; // Start bit.
|
if (~ps2_clk_s && timer_5usec_done)
|
if (~ps2_clk_s && timer_5usec_done)
|
m1_next_state <= m1_tx_clk_l;
|
m1_next_state <= #1 m1_tx_clk_l;
|
else
|
else
|
m1_next_state <= m1_tx_first_wait_clk_h;
|
m1_next_state <= #1 m1_tx_first_wait_clk_h;
|
end
|
end
|
|
|
// This state must be included because the device might possibly
|
// This state must be included because the device might possibly
|
// delay for up to 10 milliseconds before beginning its clock pulses.
|
// delay for up to 10 milliseconds before beginning its clock pulses.
|
// During that waiting time, we cannot drive the data (q[0]) because it
|
// 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
|
// is possibly 1, which would cause the keyboard to abort its receive
|
// and the expected clocks would then never be generated.
|
// and the expected clocks would then never be generated.
|
m1_tx_first_wait_clk_l :
|
m1_tx_first_wait_clk_l :
|
begin
|
begin
|
ps2_data_hi_z <= 0;
|
ps2_data_hi_z <= #1 0;
|
if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
|
if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l;
|
else m1_next_state <= m1_tx_first_wait_clk_l;
|
else m1_next_state <= #1 m1_tx_first_wait_clk_l;
|
end
|
end
|
|
|
m1_tx_wait_clk_h :
|
m1_tx_wait_clk_h :
|
begin
|
begin
|
enable_timer_5usec <= 1;
|
enable_timer_5usec <= #1 1;
|
ps2_data_hi_z <= q[0];
|
ps2_data_hi_z <= #1 q[0];
|
if (ps2_clk_s && timer_5usec_done)
|
if (ps2_clk_s && timer_5usec_done)
|
m1_next_state <= m1_tx_rising_edge_marker;
|
m1_next_state <= #1 m1_tx_rising_edge_marker;
|
else
|
else
|
m1_next_state <= m1_tx_wait_clk_h;
|
m1_next_state <= #1 m1_tx_wait_clk_h;
|
end
|
end
|
|
|
m1_tx_rising_edge_marker :
|
m1_tx_rising_edge_marker :
|
begin
|
begin
|
ps2_data_hi_z <= q[0];
|
ps2_data_hi_z <= #1 q[0];
|
m1_next_state <= m1_tx_clk_h;
|
m1_next_state <= #1 m1_tx_clk_h;
|
end
|
end
|
|
|
m1_tx_clk_h :
|
m1_tx_clk_h :
|
begin
|
begin
|
ps2_data_hi_z <= q[0];
|
ps2_data_hi_z <= #1 q[0];
|
if (tx_shifting_done) m1_next_state <= m1_tx_wait_keyboard_ack;
|
if (tx_shifting_done) m1_next_state <= #1 m1_tx_wait_keyboard_ack;
|
else if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
|
else if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l;
|
else m1_next_state <= m1_tx_clk_h;
|
else m1_next_state <= #1 m1_tx_clk_h;
|
end
|
end
|
|
|
m1_tx_clk_l :
|
m1_tx_clk_l :
|
begin
|
begin
|
ps2_data_hi_z <= q[0];
|
ps2_data_hi_z <= #1 q[0];
|
if (ps2_clk_s) m1_next_state <= m1_tx_wait_clk_h;
|
if (ps2_clk_s) m1_next_state <= #1 m1_tx_wait_clk_h;
|
else m1_next_state <= m1_tx_clk_l;
|
else m1_next_state <= #1 m1_tx_clk_l;
|
end
|
end
|
|
|
m1_tx_wait_keyboard_ack :
|
m1_tx_wait_keyboard_ack :
|
begin
|
begin
|
if (~ps2_clk_s && ps2_data_s)
|
if (~ps2_clk_s && ps2_data_s)
|
m1_next_state <= m1_tx_error_no_keyboard_ack;
|
m1_next_state <= #1 m1_tx_error_no_keyboard_ack;
|
else if (~ps2_clk_s && ~ps2_data_s)
|
else if (~ps2_clk_s && ~ps2_data_s)
|
m1_next_state <= m1_tx_done_recovery;
|
m1_next_state <= #1 m1_tx_done_recovery;
|
else m1_next_state <= m1_tx_wait_keyboard_ack;
|
else m1_next_state <= #1 m1_tx_wait_keyboard_ack;
|
end
|
end
|
|
|
m1_tx_done_recovery :
|
m1_tx_done_recovery :
|
begin
|
begin
|
if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
|
if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h;
|
else m1_next_state <= m1_tx_done_recovery;
|
else m1_next_state <= #1 m1_tx_done_recovery;
|
end
|
end
|
|
|
m1_tx_error_no_keyboard_ack :
|
m1_tx_error_no_keyboard_ack :
|
begin
|
begin
|
tx_error_no_keyboard_ack <= 1;
|
tx_error_no_keyboard_ack <= #1 1;
|
if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
|
if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h;
|
else m1_next_state <= m1_tx_error_no_keyboard_ack;
|
else m1_next_state <= #1 m1_tx_error_no_keyboard_ack;
|
end
|
end
|
|
|
default : m1_next_state <= m1_rx_clk_h;
|
default : m1_next_state <= #1 m1_rx_clk_h;
|
endcase
|
endcase
|
end
|
end
|
|
|
// State register
|
// State register
|
always @(posedge clk or posedge reset)
|
always @(posedge clk or posedge reset)
|
begin : m2_state_register
|
begin : m2_state_register
|
if (reset) m2_state <= m2_rx_data_ready_ack;
|
if (reset) m2_state <= #1 m2_rx_data_ready_ack;
|
else m2_state <= m2_next_state;
|
else m2_state <= #1 m2_next_state;
|
end
|
end
|
|
|
// State transition logic
|
// State transition logic
|
always @(m2_state or rx_output_strobe or rx_read)
|
always @(m2_state or rx_output_strobe or rx_read)
|
begin : m2_state_logic
|
begin : m2_state_logic
|
case (m2_state)
|
case (m2_state)
|
m2_rx_data_ready_ack:
|
m2_rx_data_ready_ack:
|
begin
|
begin
|
rx_data_ready <= 1'b0;
|
rx_data_ready <= #1 1'b0;
|
if (rx_output_strobe) m2_next_state <= m2_rx_data_ready;
|
if (rx_output_strobe) m2_next_state <= #1 m2_rx_data_ready;
|
else m2_next_state <= m2_rx_data_ready_ack;
|
else m2_next_state <= #1 m2_rx_data_ready_ack;
|
end
|
end
|
m2_rx_data_ready:
|
m2_rx_data_ready:
|
begin
|
begin
|
rx_data_ready <= 1'b1;
|
rx_data_ready <= #1 1'b1;
|
if (rx_read) m2_next_state <= m2_rx_data_ready_ack;
|
if (rx_read) m2_next_state <= #1 m2_rx_data_ready_ack;
|
else m2_next_state <= m2_rx_data_ready;
|
else m2_next_state <= #1 m2_rx_data_ready;
|
end
|
end
|
default : m2_next_state <= m2_rx_data_ready_ack;
|
default : m2_next_state <= #1 m2_rx_data_ready_ack;
|
endcase
|
endcase
|
end
|
end
|
|
|
// This is the bit counter
|
// This is the bit counter
|
always @(posedge clk or posedge reset)
|
always @(posedge clk or posedge reset)
|
begin
|
begin
|
if ( reset) bit_count <= 0;
|
if ( reset) bit_count <= #1 0;
|
else if ( rx_shifting_done || (m1_state == m1_tx_wait_keyboard_ack) // After tx is done.
|
else if ( rx_shifting_done || (m1_state == m1_tx_wait_keyboard_ack) // After tx is done.
|
) bit_count <= 0; // normal reset
|
) bit_count <= #1 0; // normal reset
|
else if (timer_60usec_done
|
else if (timer_60usec_done
|
&& (m1_state == m1_rx_clk_h)
|
&& (m1_state == m1_rx_clk_h)
|
&& (ps2_clk_s)
|
&& (ps2_clk_s)
|
) bit_count <= 0; // rx watchdog timer reset
|
) bit_count <= #1 0; // rx watchdog timer reset
|
else if ( (m1_state == m1_rx_falling_edge_marker) // increment for rx
|
else if ( (m1_state == m1_rx_falling_edge_marker) // increment for rx
|
||(m1_state == m1_tx_rising_edge_marker) // increment for tx
|
||(m1_state == m1_tx_rising_edge_marker) // increment for tx
|
)
|
)
|
bit_count <= bit_count + 1;
|
bit_count <= #1 bit_count + 1;
|
end
|
end
|
// This signal is high for one clock at the end of the timer count.
|
// This signal is high for one clock at the end of the timer count.
|
assign rx_shifting_done = (bit_count == `TOTAL_BITS);
|
assign rx_shifting_done = (bit_count == `TOTAL_BITS);
|
assign tx_shifting_done = (bit_count == `TOTAL_BITS-1);
|
assign tx_shifting_done = (bit_count == `TOTAL_BITS-1);
|
|
|
Line 468... |
Line 468... |
assign tx_parity_bit = ~^tx_data;
|
assign tx_parity_bit = ~^tx_data;
|
|
|
// This is the shift register
|
// This is the shift register
|
always @(posedge clk or posedge reset)
|
always @(posedge clk or posedge reset)
|
begin
|
begin
|
if (reset) q <= 0;
|
if (reset) q <= #1 0;
|
else if (tx_write_ack_o) q <= {1'b1,tx_parity_bit,tx_data,1'b0};
|
else if (tx_write_ack_o) q <= #1 {1'b1,tx_parity_bit,tx_data,1'b0};
|
else if ( (m1_state == m1_rx_falling_edge_marker)
|
else if ( (m1_state == m1_rx_falling_edge_marker)
|
||(m1_state == m1_tx_rising_edge_marker) )
|
||(m1_state == m1_tx_rising_edge_marker) )
|
q <= {ps2_data_s,q[`TOTAL_BITS-1:1]};
|
q <= #1 {ps2_data_s,q[`TOTAL_BITS-1:1]};
|
end
|
end
|
|
|
// This is the 60usec timer counter
|
// This is the 60usec timer counter
|
always @(posedge clk)
|
always @(posedge clk)
|
begin
|
begin
|
if (~enable_timer_60usec) timer_60usec_count <= 0;
|
if (~enable_timer_60usec) timer_60usec_count <= #1 0;
|
else if ( timer_done && !timer_60usec_done)
|
else if ( timer_done && !timer_60usec_done)
|
timer_60usec_count<= timer_60usec_count +1;
|
timer_60usec_count<= #1 timer_60usec_count +1;
|
end
|
end
|
assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP ));
|
assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP ));
|
|
|
|
|
|
|
always @(posedge clk or posedge reset)
|
always @(posedge clk or posedge reset)
|
if (reset) timer_5usec <= 1;
|
if (reset) timer_5usec <= #1 1;
|
else if (!enable_timer_60usec) timer_5usec <= 1;
|
else if (!enable_timer_60usec) timer_5usec <= #1 1;
|
else if (timer_5usec == devide_reg_i)
|
else if (timer_5usec == devide_reg_i)
|
begin
|
begin
|
timer_5usec <= 1;
|
timer_5usec <= #1 1;
|
timer_done <= 1;
|
timer_done <= #1 1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
timer_5usec<= timer_5usec +1;
|
timer_5usec<= #1 timer_5usec +1;
|
timer_done <= 0;
|
timer_done <= #1 0;
|
end
|
end
|
|
|
// This is the 5usec timer counter
|
// This is the 5usec timer counter
|
always @(posedge clk)
|
always @(posedge clk)
|
begin
|
begin
|
if (~enable_timer_5usec) timer_5usec_count <= 0;
|
if (~enable_timer_5usec) timer_5usec_count <= #1 0;
|
else if (~timer_5usec_done) timer_5usec_count <= timer_5usec_count + 1;
|
else if (~timer_5usec_done) timer_5usec_count <= #1 timer_5usec_count + 1;
|
end
|
end
|
assign timer_5usec_done = (timer_5usec_count == devide_reg_i -1);
|
assign timer_5usec_done = (timer_5usec_count == devide_reg_i -1);
|
|
|
|
|
// Create the signals which indicate special scan codes received.
|
// Create the signals which indicate special scan codes received.
|
Line 518... |
Line 518... |
// Store the special scan code status bits
|
// Store the special scan code status bits
|
// Not the final output, but an intermediate storage place,
|
// Not the final output, but an intermediate storage place,
|
// until the entire set of output data can be assembled.
|
// until the entire set of output data can be assembled.
|
always @(posedge clk or posedge reset)
|
always @(posedge clk or posedge reset)
|
begin
|
begin
|
if (reset) hold_released <= 0;
|
if (reset) hold_released <= #1 0;
|
else if (rx_output_event)
|
else if (rx_output_event)
|
begin
|
begin
|
hold_released <= 0;
|
hold_released <= #1 0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (rx_shifting_done && released) hold_released <= 1;
|
if (rx_shifting_done && released) hold_released <= #1 1;
|
end
|
end
|
end
|
end
|
|
|
// Output the special scan code flags, the scan code and the ascii
|
// Output the special scan code flags, the scan code and the ascii
|
always @(posedge clk or posedge reset)
|
always @(posedge clk or posedge reset)
|
begin
|
begin
|
if (reset)
|
if (reset)
|
begin
|
begin
|
rx_released <= 0;
|
rx_released <= #1 0;
|
rx_scan_code <= 0;
|
rx_scan_code <= #1 0;
|
end
|
end
|
else if (rx_output_strobe)
|
else if (rx_output_strobe)
|
begin
|
begin
|
rx_released <= hold_released;
|
rx_released <= #1 hold_released;
|
rx_scan_code <= q[8:1];
|
rx_scan_code <= #1 q[8:1];
|
end
|
end
|
end
|
end
|
|
|
// Store the final rx output data only when all extend and release codes
|
// Store the final rx output data only when all extend and release codes
|
// are received and the next (actual key) scan code is also ready.
|
// are received and the next (actual key) scan code is also ready.
|