add changes by gitlab.com/emax73g

This commit is contained in:
antoniovillena 2022-05-31 15:23:43 +02:00
parent a8165d9556
commit 4b49d65e54
2 changed files with 286 additions and 276 deletions

View File

@ -1,11 +1,11 @@
`timescale 1ns / 1ps `timescale 1ns / 1ps
`default_nettype none `default_nettype none
// This file is part of the ZXUNO Spectrum core. // This file is part of the ZXUNO Spectrum core.
// Creation date is 20:16:31 2014-12-26 by Miguel Angel Rodriguez Jodar // Creation date is 20:16:31 2014-12-26 by Miguel Angel Rodriguez Jodar
// (c)2014-2020 ZXUNO association. // (c)2014-2020 ZXUNO association.
// ZXUNO official repository: http://svn.zxuno.com/svn/zxuno // ZXUNO official repository: http://svn.zxuno.com/svn/zxuno
// Username: guest Password: zxuno // Username: guest Password: zxuno
// Github repository for this core: https://github.com/mcleod-ideafix/zxuno_spectrum_core // Github repository for this core: https://github.com/mcleod-ideafix/zxuno_spectrum_core
// //
// ZXUNO Spectrum core is free software: you can redistribute it and/or modify // ZXUNO Spectrum core is free software: you can redistribute it and/or modify
@ -19,271 +19,267 @@
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with the ZXUNO Spectrum core. If not, see <https://www.gnu.org/licenses/>. // along with the ZXUNO Spectrum core. If not, see <https://www.gnu.org/licenses/>.
// //
// Any distributed copy of this file must keep this notice intact. // Any distributed copy of this file must keep this notice intact.
module ps2_port ( module ps2_port (
input wire clk, // se recomienda 1 MHz <= clk <= 600 MHz input wire clk, // se recomienda 1 MHz <= clk <= 600 MHz
input wire enable_rcv, // habilitar la maquina de estados de recepcion input wire enable_rcv, // habilitar la maquina de estados de recepcion
input wire kb_or_mouse, // 0: kb, 1: mouse input wire kb_or_mouse, // 0: kb, 1: mouse
input wire ps2clk_ext, input wire ps2clk_ext,
input wire ps2data_ext, input wire ps2data_ext,
output wire kb_interrupt, // a 1 durante 1 clk para indicar nueva tecla recibida output wire kb_interrupt, // a 1 durante 1 clk para indicar nueva tecla recibida
output reg [7:0] scancode, // make o breakcode de la tecla output reg [7:0] scancode, // make o breakcode de la tecla
output wire released, // soltada=1, pulsada=0 output wire released, // soltada=1, pulsada=0
output wire extended // extendida=1, no extendida=0 output wire extended // extendida=1, no extendida=0
); );
localparam RCVSTART = 2'b00, localparam RCVSTART = 2'b00,
RCVDATA = 2'b01, RCVDATA = 2'b01,
RCVPARITY = 2'b10, RCVPARITY = 2'b10,
RCVSTOP = 2'b11; RCVSTOP = 2'b11;
reg [7:0] key = 8'h00; reg [7:0] key = 8'h00;
// Fase de sincronizacion de señales externas con el reloj del sistema // Fase de sincronizacion de señales externas con el reloj del sistema
reg [1:0] ps2clk_synchr; reg [1:0] ps2clk_synchr;
reg [1:0] ps2dat_synchr; reg [1:0] ps2dat_synchr;
wire ps2clk = ps2clk_synchr[1]; wire ps2clk = ps2clk_synchr[1];
wire ps2data = ps2dat_synchr[1]; wire ps2data = ps2dat_synchr[1];
always @(posedge clk) begin always @(posedge clk) begin
ps2clk_synchr[0] <= ps2clk_ext; ps2clk_synchr[0] <= ps2clk_ext;
ps2clk_synchr[1] <= ps2clk_synchr[0]; ps2clk_synchr[1] <= ps2clk_synchr[0];
ps2dat_synchr[0] <= ps2data_ext; ps2dat_synchr[0] <= ps2data_ext;
ps2dat_synchr[1] <= ps2dat_synchr[0]; ps2dat_synchr[1] <= ps2dat_synchr[0];
end end
// De-glitcher. Sólo detecto flanco de bajada // De-glitcher. Sólo detecto flanco de bajada
reg [15:0] negedgedetect = 16'h0000; reg [15:0] negedgedetect = 16'h0000;
always @(posedge clk) begin always @(posedge clk) begin
negedgedetect <= {negedgedetect[14:0], ps2clk}; negedgedetect <= {negedgedetect[14:0], ps2clk};
end end
wire ps2clkedge = (negedgedetect == 16'hF000)? 1'b1 : 1'b0; wire ps2clkedge = (negedgedetect == 16'hF000)? 1'b1 : 1'b0;
// Paridad instantánea de los bits recibidos // Paridad instantánea de los bits recibidos
wire paritycalculated = ^key; wire paritycalculated = ^key;
// Contador de time-out. Al llegar a 16777216 ciclos sin que ocurra // Contador de time-out. Al llegar a 16777216 ciclos sin que ocurra
// un flanco de bajada en PS2CLK, volvemos al estado inicial // un flanco de bajada en PS2CLK, volvemos al estado inicial
reg [23:0] timeoutcnt = 24'h000000; reg [23:0] timeoutcnt = 24'h000000;
reg [1:0] state = RCVSTART; reg [1:0] state = RCVSTART;
reg [1:0] regextended = 2'b00; reg [1:0] regextended = 2'b00;
reg [1:0] regreleased = 2'b00; reg [1:0] regreleased = 2'b00;
reg rkb_interrupt = 1'b0; reg rkb_interrupt = 1'b0;
assign released = regreleased[1]; assign released = regreleased[1];
assign extended = regextended[1]; assign extended = regextended[1];
assign kb_interrupt = rkb_interrupt; assign kb_interrupt = rkb_interrupt;
always @(posedge clk) begin always @(posedge clk) begin
if (rkb_interrupt == 1'b1) begin if (rkb_interrupt == 1'b1) begin
rkb_interrupt <= 1'b0; rkb_interrupt <= 1'b0;
end end
if (ps2clkedge && enable_rcv) begin if (ps2clkedge && enable_rcv) begin
timeoutcnt <= 24'h000000; timeoutcnt <= 24'h000000;
case (state) case (state)
RCVSTART: begin RCVSTART: begin
if (ps2data == 1'b0) begin if (ps2data == 1'b0) begin
state <= RCVDATA; state <= RCVDATA;
key <= 8'h80; key <= 8'h80;
end end
end end
RCVDATA: begin RCVDATA: begin
key <= {ps2data, key[7:1]}; key <= {ps2data, key[7:1]};
if (key[0] == 1'b1) begin if (key[0] == 1'b1) begin
state <= RCVPARITY; state <= RCVPARITY;
end end
end end
RCVPARITY: begin RCVPARITY: begin
if (ps2data^paritycalculated == 1'b1) begin if (ps2data^paritycalculated == 1'b1) begin
state <= RCVSTOP; state <= RCVSTOP;
end end
else begin else begin
state <= RCVSTART; state <= RCVSTART;
end end
end end
RCVSTOP: begin RCVSTOP: begin
state <= RCVSTART; state <= RCVSTART;
if (ps2data == 1'b1) begin if (ps2data == 1'b1) begin
scancode <= key; scancode <= key;
if (kb_or_mouse == 1'b1) begin if (kb_or_mouse == 1'b1) begin
rkb_interrupt <= 1'b1; // no se requiere mirar E0 o F0 rkb_interrupt <= 1'b1; // no se requiere mirar E0 o F0
end end
else begin else begin
if (key == 8'hE0) begin if (key == 8'hE0) begin
regextended <= 2'b01; regextended <= 2'b01;
end end
else if (key == 8'hF0) begin else if (key == 8'hF0) begin
regreleased <= 2'b01; regreleased <= 2'b01;
end end
else begin else begin
regextended <= {regextended[0], 1'b0}; regextended <= {regextended[0], 1'b0};
regreleased <= {regreleased[0], 1'b0}; regreleased <= {regreleased[0], 1'b0};
rkb_interrupt <= 1'b1; rkb_interrupt <= 1'b1;
end end
end end
end end
end end
default: state <= RCVSTART; default: state <= RCVSTART;
endcase endcase
end end
else begin else begin
timeoutcnt <= timeoutcnt + 24'd1; timeoutcnt <= timeoutcnt + 24'd1;
if (timeoutcnt == 24'hFFFFFF) begin if (timeoutcnt == 24'hFFFFFF) begin
state <= RCVSTART; state <= RCVSTART;
end end
end end
end end
endmodule endmodule
module ps2_host_to_kb ( module ps2_host_to_kb (
input wire clk, // calibrado para 28 MHz input wire clk, // calibrado para 28 MHz
inout wire ps2clk_ext, inout wire ps2clk_ext,
inout wire ps2data_ext, inout wire ps2data_ext,
input wire [7:0] data, input wire [7:0] data,
input wire dataload, input wire dataload,
output wire ps2busy, output wire ps2busy,
output wire ps2error output wire ps2error
); );
`define PULLCLKLOW 3'b000 `define PULLCLKLOW 3'b000
`define PULLDATALOW 3'b001 `define PULLCLKDATALOW 3'b001
`define SENDDATA 3'b010 `define PULLDATALOW 3'b010
`define SENDPARITY 3'b011 `define SENDDATA 3'b011
`define RCVACK 3'b100 `define SENDPARITY 3'b100
`define RCVIDLE 3'b101 `define RCVACK 3'b101
`define SENDFINISHED 3'b110 `define RCVIDLE 3'b110
`define SENDFINISHED 3'b111
reg initial_kb_reset = 1'b1;
reg busy = 1'b0; reg busy = 1'b0;
reg error = 1'b0; reg error = 1'b0;
assign ps2busy = busy; assign ps2busy = busy;
assign ps2error = error; assign ps2error = error;
// Fase de sincronizacion de señales externas con el reloj del sistema // Fase de sincronizacion de señales externas con el reloj del sistema
reg [1:0] ps2clk_synchr; reg [1:0] ps2clk_synchr;
reg [1:0] ps2dat_synchr; reg [1:0] ps2dat_synchr;
wire ps2clk = ps2clk_synchr[1]; wire ps2clk = ps2clk_synchr[1];
wire ps2data_in = ps2dat_synchr[1]; wire ps2data_in = ps2dat_synchr[1];
always @(posedge clk) begin always @(posedge clk) begin
ps2clk_synchr[0] <= ps2clk_ext; ps2clk_synchr[0] <= ps2clk_ext;
ps2clk_synchr[1] <= ps2clk_synchr[0]; ps2clk_synchr[1] <= ps2clk_synchr[0];
ps2dat_synchr[0] <= ps2data_ext; ps2dat_synchr[0] <= ps2data_ext;
ps2dat_synchr[1] <= ps2dat_synchr[0]; ps2dat_synchr[1] <= ps2dat_synchr[0];
end end
// De-glitcher. Sólo detecto flanco de bajada // De-glitcher. Sólo detecto flanco de bajada
reg [15:0] edgedetect = 16'h0000; reg [15:0] edgedetect = 16'h0000;
always @(posedge clk) begin always @(posedge clk) begin
edgedetect <= {edgedetect[14:0], ps2clk}; edgedetect <= {edgedetect[14:0], ps2clk};
end end
wire ps2clknedge = (edgedetect == 16'hF000)? 1'b1 : 1'b0; wire ps2clknedge = (edgedetect == 16'hF000)? 1'b1 : 1'b0;
wire ps2clkpedge = (edgedetect == 16'h0FFF)? 1'b1 : 1'b0; wire ps2clkpedge = (edgedetect == 16'h0FFF)? 1'b1 : 1'b0;
// Contador de time-out. Al llegar a 16777216 ciclos sin que ocurra // Contador de time-out. Al llegar a 16777216 ciclos sin que ocurra
// un flanco de bajada en PS2CLK, volvemos al estado inicial // un flanco de bajada en PS2CLK, volvemos al estado inicial
reg [23:0] timeoutcnt = 24'h000000; reg [23:0] timeoutcnt = 24'h000000;
reg [2:0] state = `SENDFINISHED; reg [2:0] state = `SENDFINISHED;
reg [7:0] shiftreg = 8'h00; reg [7:0] shiftreg = 8'h00;
reg [2:0] cntbits = 3'd0; reg [2:0] cntbits = 3'd0;
// Dato a enviar se guarda en rdata // Dato a enviar se guarda en rdata
reg [7:0] rdata = 8'h00; reg [7:0] rdata = 8'h00;
// Paridad instantánea de los bits a enviar // Paridad instantánea de los bits a enviar
wire paritycalculated = ~(^rdata); wire paritycalculated = ~(^rdata);
always @(posedge clk) begin always @(posedge clk) begin
// Carga de rdata desde el exterior // Carga de rdata desde el exterior
`ifdef INITIAL_KB_RESET if (dataload) begin
if (initial_kb_reset) begin // Reset inicial de teclado para establecer el SET 2 rdata <= data;
initial_kb_reset <= 1'b0; busy <= 1'b1;
rdata <= 8'hFF; error <= 1'b0;
busy <= 1'b1; timeoutcnt <= 24'h000000;
error <= 1'b0; state <= `PULLCLKLOW;
timeoutcnt <= 24'h000000; end
state <= `PULLCLKLOW;
end if (!ps2clknedge) begin
`endif timeoutcnt <= timeoutcnt + 24'd1;
if (dataload) begin if (timeoutcnt == 24'hFFFFFF && state != `SENDFINISHED) begin
rdata <= data; error <= 1'b1;
busy <= 1'b1; state <= `SENDFINISHED;
error <= 1'b0; end
timeoutcnt <= 24'h000000; end
state <= `PULLCLKLOW;
end case (state)
`PULLCLKLOW: begin // 280000 cuentas son 10ms para 28 MHz
if (!ps2clknedge) begin if (timeoutcnt >= 24'd3360) begin
timeoutcnt <= timeoutcnt + 24'd1; state <= `PULLCLKDATALOW;
if (timeoutcnt == 24'hFFFFFF && state != `SENDFINISHED) begin timeoutcnt <= 24'h000000;
error <= 1'b1; end
state <= `SENDFINISHED; end
end `PULLCLKDATALOW: begin
end if (timeoutcnt >= 24'd280) begin
state <= `PULLDATALOW;
case (state) shiftreg <= rdata;
`PULLCLKLOW: begin // 280000 cuentas son 10ms para 28 MHz cntbits <= 3'd0;
if (timeoutcnt >= 24'd280000) begin timeoutcnt <= 24'h000000;
state <= `PULLDATALOW; end
shiftreg <= rdata; end
cntbits <= 3'd0; `PULLDATALOW: begin
timeoutcnt <= 24'h000000; if (ps2clknedge) begin
end state <= `SENDDATA;
end timeoutcnt <= 24'h000000;
`PULLDATALOW: begin end
if (ps2clknedge) begin end
state <= `SENDDATA; `SENDDATA: begin
timeoutcnt <= 24'h000000; if (ps2clknedge) begin
end timeoutcnt <= 24'h000000;
end shiftreg <= {1'b0, shiftreg[7:1]};
`SENDDATA: begin cntbits <= cntbits + 1;
if (ps2clknedge) begin if (cntbits == 3'd7)
timeoutcnt <= 24'h000000; state <= `SENDPARITY;
shiftreg <= {1'b0, shiftreg[7:1]}; end
cntbits <= cntbits + 1; end
if (cntbits == 3'd7) `SENDPARITY: begin
state <= `SENDPARITY; if (ps2clknedge) begin
end state <= `RCVIDLE;
end timeoutcnt <= 24'h000000;
`SENDPARITY: begin end
if (ps2clknedge) begin end
state <= `RCVIDLE; `RCVIDLE: begin
timeoutcnt <= 24'h000000; if (ps2clknedge) begin
end state <= `RCVACK;
end timeoutcnt <= 24'h000000;
`RCVIDLE: begin end
if (ps2clknedge) begin end
state <= `RCVACK; `RCVACK: begin
timeoutcnt <= 24'h000000; if (ps2clknedge) begin
end state <= `SENDFINISHED;
end timeoutcnt <= 24'h000000;
`RCVACK: begin end
if (ps2clknedge) begin end
state <= `SENDFINISHED; `SENDFINISHED: begin
timeoutcnt <= 24'h000000; busy <= 1'b0;
end timeoutcnt <= 24'h000000;
end end
`SENDFINISHED: begin default: begin
busy <= 1'b0; timeoutcnt <= timeoutcnt + 1;
timeoutcnt <= 24'h000000; if (timeoutcnt == 24'hFFFFFF && state != `SENDFINISHED) begin
end error <= 1'b1;
default: begin state <= `SENDFINISHED;
timeoutcnt <= timeoutcnt + 1; end
if (timeoutcnt == 24'hFFFFFF && state != `SENDFINISHED) begin end
error <= 1'b1; endcase
state <= `SENDFINISHED; end
end
end assign ps2data_ext = (state == `PULLCLKDATALOW || state == `PULLDATALOW) ? 1'b0 :
endcase (state == `SENDDATA && shiftreg[0] == 1'b0) ? 1'b0 :
end (state == `SENDPARITY && paritycalculated == 1'b0) ? 1'b0 : // si lo que se va a enviar es un 1
1'bZ; // no se manda, sino que se pone la línea a alta impedancia
assign ps2data_ext = (state == `PULLCLKLOW || state == `PULLDATALOW) ? 1'b0 : assign ps2clk_ext = (state == `PULLCLKLOW || state == `PULLCLKDATALOW) ? 1'b0 :
(state == `SENDDATA && shiftreg[0] == 1'b0) ? 1'b0 : 1'bZ;
(state == `SENDPARITY && paritycalculated == 1'b0) ? 1'b0 : // si lo que se va a enviar es un 1 endmodule
1'bZ; // no se manda, sino que se pone la línea a alta impedancia
assign ps2clk_ext = (state == `PULLCLKLOW) ? 1'b0 :
1'bZ;
endmodule

View File

@ -250,6 +250,17 @@ kemp defb $1f, $1e, $1d, $1c, $0d ; Right Left Down Up Enter
start ld bc, chrend-sdtab start ld bc, chrend-sdtab
ldir ldir
wreg scan_code, $f6 ; $f6 = kb set defaults
halt
halt
wreg scan_code, $f0 ; $f0 + 2 = Set scan code set 2
halt
halt
wreg scan_code, $02
ld c, $05 ; 100msec delay
delay1 halt
dec c
jr nz, delay1
IF recovery=0 IF recovery=0
call alto loadch call alto loadch
ld hl, (scanli) ld hl, (scanli)
@ -463,7 +474,10 @@ star16 djnz star18
halt halt
wreg scan_code, $ed ; $ed + 2 = kb set leds + numlock wreg scan_code, $ed ; $ed + 2 = kb set leds + numlock
halt halt
halt
wreg scan_code, $02 wreg scan_code, $02
halt
halt
IF vertical=0 IF vertical=0
ld hl, $0017 ; Si se acaba el temporizador borrar ld hl, $0017 ; Si se acaba el temporizador borrar
ld de, $2001 ; lo de presione Break ld de, $2001 ; lo de presione Break