mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-06 16:14:42 +00:00
180 lines
5.1 KiB
Verilog
180 lines
5.1 KiB
Verilog
`timescale 1 ns / 1 ns // timescale for following modules
|
|
|
|
// ZX Spectrum for Altera DE1
|
|
//
|
|
// Copyright (c) 2009-2011 Mike Stirling
|
|
//
|
|
// All rights reserved
|
|
//
|
|
// Redistribution and use in source and synthezised forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
//
|
|
// * Redistributions in synthesized form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
//
|
|
// * Neither the name of the author nor the names of other contributors may
|
|
// be used to endorse or promote products derived from this software without
|
|
// specific prior written agreement from the author.
|
|
//
|
|
// * License is granted for non-commercial use only. A fee may not be charged
|
|
// for redistributions as source code or in synthesized/hardware form without
|
|
// specific prior written agreement from the author.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// PS/2 interface (input only)
|
|
// Based loosely on ps2_ctrl.vhd (c) ALSE. http://www.alse-fr.com
|
|
|
|
module ps2_intf (
|
|
input CLK,
|
|
input nRESET,
|
|
input PS2_CLK,
|
|
input PS2_DATA,
|
|
output reg [7:0] DATA,
|
|
output reg VALID,
|
|
output reg ERROR
|
|
);
|
|
|
|
parameter filter_length = 8;
|
|
|
|
reg [filter_length - 1:0] clk_filter;
|
|
reg ps2_clk_in;
|
|
reg ps2_dat_in;
|
|
|
|
// Goes high when a clock falling edge is detected
|
|
reg clk_edge;
|
|
reg [3:0] bit_count;
|
|
reg [8:0] shiftreg;
|
|
reg parity;
|
|
|
|
// Register input signals
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
if (nRESET === 1'b 0) begin
|
|
|
|
ps2_clk_in <= 1'b 1;
|
|
ps2_dat_in <= 1'b 1;
|
|
clk_filter <= {(filter_length - 1 - 0 + 1){1'b 1}};
|
|
clk_edge <= 1'b 0;
|
|
|
|
end else begin
|
|
|
|
// Register inputs (and filter clock)
|
|
ps2_dat_in <= PS2_DATA;
|
|
clk_filter <= {PS2_CLK, clk_filter[7:1]};
|
|
clk_edge <= 1'b 0;
|
|
|
|
if (clk_filter === 1'b 1) begin
|
|
|
|
// Filtered clock is high
|
|
ps2_clk_in <= 1'b 1;
|
|
|
|
end else if (clk_filter === 1'b 0 ) begin
|
|
|
|
// Filter clock is low, check for edge
|
|
if (ps2_clk_in === 1'b 1) begin
|
|
clk_edge <= 1'b 1;
|
|
end
|
|
|
|
ps2_clk_in <= 1'b 0;
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
// Shift in keyboard data
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
if (nRESET === 1'b 0) begin
|
|
|
|
bit_count <= 'd0;
|
|
shiftreg <= 'd0;
|
|
parity <= 1'b0;
|
|
DATA <= 'd0;
|
|
VALID <= 1'b 0;
|
|
ERROR <= 1'b 0;
|
|
|
|
end else begin
|
|
|
|
// Clear flags
|
|
VALID <= 1'b 0;
|
|
ERROR <= 1'b 0;
|
|
|
|
if (clk_edge === 1'b 1) begin
|
|
|
|
// We have a new bit from the keyboard for processing
|
|
if (bit_count === 0) begin
|
|
|
|
// Idle state, check for start bit (0) only and don't
|
|
// start counting bits until we get it
|
|
parity <= 1'b 0;
|
|
|
|
if (ps2_dat_in === 1'b 0) begin
|
|
|
|
// This is a start bit
|
|
bit_count <= bit_count + 'd1;
|
|
end
|
|
|
|
// Running. 8-bit data comes in LSb first followed by
|
|
// a single stop bit (1)
|
|
|
|
end else begin
|
|
|
|
if (bit_count < 10) begin
|
|
|
|
// Shift in data and parity (9 bits)
|
|
bit_count <= bit_count + 1;
|
|
shiftreg <= {ps2_dat_in, shiftreg[8:1]};
|
|
parity <= parity ^ ps2_dat_in;
|
|
// Calculate parity
|
|
|
|
end else if (ps2_dat_in === 1'b 1 ) begin
|
|
|
|
// Valid stop bit received
|
|
bit_count <= 'd0;
|
|
// back to idle
|
|
if (parity === 1'b 1) begin
|
|
|
|
// Parity correct, submit data to host
|
|
DATA <= shiftreg[7:0];
|
|
VALID <= 1'b 1;
|
|
|
|
// Error
|
|
|
|
end else begin
|
|
|
|
ERROR <= 1'b 1;
|
|
|
|
end
|
|
|
|
end else begin // Invalid stop bit
|
|
|
|
bit_count <= 'd0;
|
|
// back to idle
|
|
ERROR <= 1'b 1;
|
|
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule // module ps2_intf
|
|
|