252 lines
4.8 KiB
Verilog
252 lines
4.8 KiB
Verilog
// scancode2.v
|
|
|
|
//
|
|
// simple AT style keyboard scancode to ascii convertion
|
|
// keeps track of shift, capslock and control keys
|
|
// inputs scancodes and outputs ascii
|
|
//
|
|
// implicit state machine version
|
|
//
|
|
|
|
`include "scancode_rom.v"
|
|
|
|
module scancode_convert(clock,
|
|
reset_n,
|
|
scancode,
|
|
ascii,
|
|
key_up,
|
|
strobe_in,
|
|
strobe_out);
|
|
|
|
input clock;
|
|
input reset_n;
|
|
input [7:0] scancode;
|
|
output reg [7:0] ascii;
|
|
output reg key_up;
|
|
input strobe_in;
|
|
output reg strobe_out;
|
|
|
|
reg release_prefix;
|
|
reg shift;
|
|
reg ctrl;
|
|
reg capslock;
|
|
|
|
reg [6:0] sc;
|
|
wire [7:0] rom_data;
|
|
wire raise;
|
|
|
|
scancode_rom scancode_rom(.addr({raise,sc}),
|
|
.data(rom_data));
|
|
|
|
assign raise = shift | capslock | ctrl;
|
|
|
|
always @(posedge clock or negedge reset_n)
|
|
if (~reset_n)
|
|
begin
|
|
shift <= 0;
|
|
ctrl <= 0;
|
|
capslock <= 0;
|
|
release_prefix <= 0;
|
|
key_up <= 0;
|
|
strobe_out <= 0;
|
|
end
|
|
else
|
|
begin
|
|
if (strobe_in)
|
|
begin
|
|
strobe_out <= 0;
|
|
|
|
sc = scancode[6:0];
|
|
case (scancode)
|
|
8'hf0: /* release prefix */
|
|
begin
|
|
@(posedge clock) release_prefix <= 1;
|
|
end
|
|
|
|
8'h58: /* caps lock */
|
|
begin
|
|
if (~release_prefix)
|
|
@(posedge clock) capslock = ~capslock;
|
|
end
|
|
|
|
8'h12, /* left shift */
|
|
8'h59: /* right shift */
|
|
begin
|
|
@(posedge clock) shift = release_prefix ? 0 : 1;
|
|
end
|
|
|
|
8'h14: /* left ctrl */
|
|
begin
|
|
@(posedge clock) ctrl = release_prefix ? 0 : 1;
|
|
end
|
|
|
|
default:
|
|
begin
|
|
if (release_prefix)
|
|
begin
|
|
@(posedge clock)
|
|
begin
|
|
ascii = ctrl ? (rom_data - 8'h40) : rom_data;
|
|
strobe_out <= 1;
|
|
end
|
|
@(posedge clock) strobe_out <= 1;
|
|
@(posedge clock)
|
|
begin
|
|
strobe_out <= 0;
|
|
release_prefix <= 0;
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
@(posedge clock)
|
|
begin
|
|
/*
|
|
ascii = ctrl ? (rom_data - 8'h40) : rom_data;
|
|
strobe_out <= 1;
|
|
*/
|
|
key_up <= 1;
|
|
end
|
|
@(posedge clock) strobe_out <= 0;
|
|
@(posedge clock)
|
|
begin
|
|
strobe_out <= 0;
|
|
release_prefix <= 0;
|
|
end
|
|
end
|
|
end
|
|
endcase // case(scancode)
|
|
|
|
end // if (strobe_in)
|
|
end // else: !if(~reset_n)
|
|
|
|
endmodule
|
|
|
|
|
|
///*
|
|
|
|
|
|
// ------------------
|
|
|
|
`timescale 1ns / 1ns
|
|
|
|
module test;
|
|
|
|
reg clk, reset_n;
|
|
reg [7:0] testcode;
|
|
wire [7:0] kb_ascii;
|
|
reg kb_rdy;
|
|
wire kb_release;
|
|
wire kb_ascii_rdy;
|
|
|
|
scancode_convert scancode_convert(.clock(clk),
|
|
.reset_n(reset_n),
|
|
.scancode(testcode),
|
|
.ascii(kb_ascii),
|
|
.key_up(kb_release),
|
|
.strobe_in(kb_rdy),
|
|
.strobe_out(kb_ascii_rdy));
|
|
|
|
|
|
initial
|
|
begin
|
|
$timeformat(-9, 0, "ns", 7);
|
|
|
|
$dumpfile("scancode.vcd");
|
|
$dumpvars(0, test.scancode_convert);
|
|
end
|
|
|
|
initial
|
|
begin
|
|
clk = 0;
|
|
reset_n = 0;
|
|
kb_rdy = 0;
|
|
|
|
#200 begin
|
|
reset_n = 1;
|
|
end
|
|
|
|
// press "a"
|
|
#10 begin kb_rdy = 1; testcode = 8'h1c; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'hf0; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'h1c; end
|
|
#80 kb_rdy = 0;
|
|
|
|
// press "b"
|
|
#1000 begin kb_rdy = 1; testcode = 8'h32; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'hf0; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'h32; end
|
|
#80 kb_rdy = 0;
|
|
|
|
// enter
|
|
#1000 begin kb_rdy = 1; testcode = 8'h5a; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'hf0; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'h5a; end
|
|
#80 kb_rdy = 0;
|
|
|
|
// shift "a"
|
|
#1000 begin kb_rdy = 1; testcode = 8'h12; end
|
|
#80 kb_rdy = 0;
|
|
|
|
#1000 begin kb_rdy = 1; testcode = 8'h1c; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'hf0; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'h1c; end
|
|
#80 kb_rdy = 0;
|
|
|
|
#1000 begin kb_rdy = 1; testcode = 8'hf0; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'h12; end
|
|
#80 kb_rdy = 0;
|
|
|
|
// press "c"
|
|
#1000 begin kb_rdy = 1; testcode = 8'h21; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'hf0; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'h21; end
|
|
#80 kb_rdy = 0;
|
|
|
|
// ctrl "a"
|
|
#1000 begin kb_rdy = 1; testcode = 8'h14; end
|
|
#80 kb_rdy = 0;
|
|
|
|
#1000 begin kb_rdy = 1; testcode = 8'h1c; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'hf0; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'h1c; end
|
|
#80 kb_rdy = 0;
|
|
|
|
#1000 begin kb_rdy = 1; testcode = 8'hf0; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'h14; end
|
|
#80 kb_rdy = 0;
|
|
|
|
// press "d"
|
|
#1000 begin kb_rdy = 1; testcode = 8'h23; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'hf0; end
|
|
#80 kb_rdy = 0;
|
|
#1000 begin kb_rdy = 1; testcode = 8'h23; end
|
|
#80 kb_rdy = 0;
|
|
|
|
|
|
#5000 $finish;
|
|
end
|
|
|
|
always
|
|
begin
|
|
#40 clk = 0;
|
|
#40 clk = 1;
|
|
end
|
|
|
|
endmodule
|
|
|
|
//*/
|