diff --git a/cores/Spectrum/coreid.v b/cores/Spectrum/coreid.v
index 48efb2d..3f814f9 100644
--- a/cores/Spectrum/coreid.v
+++ b/cores/Spectrum/coreid.v
@@ -37,12 +37,12 @@ module coreid (
text[i] = 8'h00;
text[ 0] = "T";
text[ 1] = "1";
- text[ 2] = "8";
+ text[ 2] = "9";
text[ 3] = "-";
text[ 4] = "0";
text[ 5] = "3";
- text[ 6] = "0";
- text[ 7] = "7";
+ text[ 6] = "1";
+ text[ 7] = "0";
text[ 8] = "2";
text[ 9] = "0";
text[10] = "1";
diff --git a/cores/Spectrum/pines_zxuno.ucf b/cores/Spectrum/pines_zxuno.ucf
index 5c8c899..8e5da71 100644
--- a/cores/Spectrum/pines_zxuno.ucf
+++ b/cores/Spectrum/pines_zxuno.ucf
@@ -2,7 +2,7 @@
NET "clk50mhz" LOC="P55" | IOSTANDARD = LVCMOS33;
NET "testled" LOC="P10" | IOSTANDARD = LVCMOS33;
NET "clk50mhz" PERIOD=20 ns;
-#NET "sysclk" PERIOD=35 ns;
+NET "sysclk" PERIOD=35 ns;
# Video output
NET "r<2>" LOC="P93" | IOSTANDARD = LVCMOS33;
diff --git a/cores/Spectrum/ps2_keyb.v b/cores/Spectrum/ps2_keyb.v
index b7f243a..e6e9409 100644
--- a/cores/Spectrum/ps2_keyb.v
+++ b/cores/Spectrum/ps2_keyb.v
@@ -63,6 +63,7 @@ module ps2_keyb(
wire ps2busy;
wire kberror;
wire nueva_tecla;
+ wire no_hay_teclas_pulsadas;
wire extended;
wire released;
assign scancode_dout = kbcode;
@@ -95,6 +96,16 @@ module ps2_keyb(
.extended(extended)
);
+ keyboard_pressed_status teclado_limpio (
+ .clk(clk),
+ .rst(1'b0),
+ .scan_received(nueva_tecla),
+ .scancode(kbcode),
+ .extended(extended),
+ .released(released),
+ .kbclean(no_hay_teclas_pulsadas)
+ );
+
scancode_to_speccy traductor (
.clk(clk),
.rst(1'b0),
@@ -102,6 +113,7 @@ module ps2_keyb(
.scan(kbcode),
.extended(extended),
.released(released),
+ .kbclean(no_hay_teclas_pulsadas),
.sp_row(rows),
.sp_col(cols),
.joyup(joy[3]),
diff --git a/cores/Spectrum/scancode_to_speccy.v b/cores/Spectrum/scancode_to_speccy.v
index 42f5ac2..dbcf454 100644
--- a/cores/Spectrum/scancode_to_speccy.v
+++ b/cores/Spectrum/scancode_to_speccy.v
@@ -26,6 +26,7 @@ module scancode_to_speccy (
input wire [7:0] scan,
input wire extended,
input wire released,
+ input wire kbclean,
//------------------------
input wire [7:0] sp_row,
output wire [4:0] sp_col,
@@ -128,7 +129,7 @@ module scancode_to_speccy (
always @(posedge clk) begin
if (scan_received == 1'b1)
key_is_pending <= 1'b1;
- if (rst == 1'b1)
+ if (rst == 1'b1 || (kbclean == 1'b1 && state == IDLE && key_is_pending == 1'b0))
state <= CLEANMATRIX;
else begin
case (state)
@@ -216,12 +217,11 @@ module scancode_to_speccy (
else
ruser_toggles <= ruser_toggles & ~togglestate;
- //state <= UPDCOUNTERS1;
state <= IDLE;
end
CPUTIME: begin
if (rewind == 1'b1) begin
- cpuaddr = 14'h0000;
+ cpuaddr <= 14'h0000;
state <= IDLE;
end
else if (cpuread == 1'b1) begin
@@ -249,19 +249,6 @@ module scancode_to_speccy (
state <= IDLE;
end
end
- // else if (state == UPDCOUNTERS1) begin
- // if (~released)
- // keycount <= keycount + 4'b0001; // suma 1 al contador de pulsaciones
- // else if (released && keycount != 4'b0000)
- // keycount <= keycount + 4'b1111; // o le resta 1 al contador de pulsaciones, pero sin bajar de 0
- // state <= UPDCOUNTERS2;
- // end
- // else if (state == UPDCOUNTERS2) begin
- // if (keycount == 4'b0000) // si es la última tecla soltada, limpia la matriz de teclado del Spectrum
- // state <= CLEANMATRIX;
- // else
- // state <= IDLE;
- // end
default: begin
state <= IDLE;
end
@@ -269,3 +256,147 @@ module scancode_to_speccy (
end
end
endmodule
+
+module keyboard_pressed_status (
+ input wire clk,
+ input wire rst,
+ input wire scan_received,
+ input wire [7:0] scancode,
+ input wire extended,
+ input wire released,
+ output reg kbclean
+ );
+
+ parameter
+ RESETTING = 2'd0,
+ UPDATING = 2'd1,
+ SCANNING = 2'd2;
+
+ reg [7:0] addrscan = 8'h00; // keymap bit address
+ reg keypressed_ne = 1'b0; // there is at least one key pressed
+ reg keypressed_ex = 1'b0; // there is at least one extended key pressed
+ reg [1:0] state = RESETTING;
+
+ integer i;
+ initial begin
+ kbclean = 1'b1;
+ end
+
+ reg [7:0] addrkeybstat;
+ reg we_key_ne, we_key_ex;
+ reg din_key_ne, din_key_ex;
+ wire dout_key_ne, dout_key_ex;
+
+ keystatmem vector_kb_clean (
+ .clk(clk),
+ .a(addrkeybstat),
+ .we1(we_key_ne),
+ .we2(we_key_ex),
+ .din1(din_key_ne),
+ .din2(din_key_ex),
+ .dout1(dout_key_ne),
+ .dout2(dout_key_ex)
+ );
+
+ always @* begin
+ addrkeybstat = 8'h00;
+ we_key_ne = 1'b0;
+ we_key_ex = 1'b0;
+ din_key_ne = 1'b0;
+ din_key_ex = 1'b0;
+ case (state)
+ RESETTING:
+ begin
+ addrkeybstat = addrscan;
+ we_key_ne = 1'b1;
+ we_key_ex = 1'b1;
+ end
+ UPDATING:
+ begin
+ addrkeybstat = scancode;
+ we_key_ne = ~extended;
+ we_key_ex = extended;
+ din_key_ne = ~released;
+ din_key_ex = ~released;
+ end
+ SCANNING:
+ begin
+ addrkeybstat = addrscan;
+ end
+ endcase
+ end
+
+ always @(posedge clk) begin
+ if (rst == 1'b1) begin
+ state <= RESETTING;
+ addrscan <= 8'h00;
+ end
+ else begin
+ case (state)
+ RESETTING:
+ begin
+ if (addrscan == 8'hFF) begin
+ addrscan <= 8'h00;
+ state <= SCANNING;
+ kbclean <= 1'b1;
+ end
+ else begin
+ addrscan <= addrscan + 8'd1;
+ end
+ end
+ UPDATING:
+ begin
+ state <= SCANNING;
+ addrscan <= 8'h00;
+ kbclean <= 1'b0;
+ keypressed_ne <= 1'b0;
+ keypressed_ex <= 1'b0;
+ end
+ SCANNING:
+ begin
+ if (scan_received == 1'b1)
+ state <= UPDATING;
+ addrscan <= addrscan + 8'd1;
+ if (addrscan == 8'hFF) begin
+ kbclean <= ~(keypressed_ne | keypressed_ex);
+ keypressed_ne <= 1'b0;
+ keypressed_ex <= 1'b0;
+ end
+ else begin
+ keypressed_ne <= keypressed_ne | dout_key_ne;
+ keypressed_ex <= keypressed_ex | dout_key_ex;
+ end
+ end
+ default:
+ begin
+ state <= SCANNING;
+ end
+ endcase
+ end
+ end
+endmodule
+
+module keystatmem (
+ input wire clk,
+ input wire [7:0] a,
+ input wire we1,
+ input wire we2,
+ input wire din1,
+ input wire din2,
+ output reg dout1,
+ output reg dout2
+ );
+
+ reg keybstat_ne[0:255]; // non extended keymap
+ reg keybstat_ex[0:255]; // extended keymap
+
+ always @(posedge clk) begin
+ if (we1 == 1'b1)
+ keybstat_ne[a] <= din1;
+ if (we2 == 1'b1)
+ keybstat_ex[a] <= din2;
+ dout1 <= keybstat_ne[a];
+ dout2 <= keybstat_ex[a];
+ end
+endmodule
+
\ No newline at end of file
diff --git a/cores/Spectrum/scancode_to_speccy_unaversion.v b/cores/Spectrum/scancode_to_speccy_unaversion.v
new file mode 100644
index 0000000..f719b2f
--- /dev/null
+++ b/cores/Spectrum/scancode_to_speccy_unaversion.v
@@ -0,0 +1,342 @@
+`timescale 1ns / 1ps
+`default_nettype none
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 17:42:40 06/01/2015
+// Design Name:
+// Module Name: scancode_to_speccy
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module scancode_to_speccy (
+ input wire clk, // el mismo clk de ps/2
+ input wire rst,
+ input wire scan_received,
+ input wire [7:0] scan,
+ input wire extended,
+ input wire released,
+ input wire kbclean,
+ //------------------------
+ input wire [7:0] sp_row,
+ output wire [4:0] sp_col,
+ output wire user_reset,
+ output wire master_reset,
+ output wire user_nmi,
+ output wire joyup,
+ output wire joydown,
+ output wire joyleft,
+ output wire joyright,
+ output wire joyfire,
+ output wire [4:0] user_toggles,
+ //------------------------
+ input wire [7:0] din,
+ output reg [7:0] dout,
+ input wire cpuwrite,
+ input wire cpuread,
+ input wire rewind
+ );
+
+ // las 40 teclas del Spectrum. Se inicializan a "no pulsadas".
+ reg [4:0] row[0:7];
+ initial begin
+ row[0] = 5'b11111;
+ row[1] = 5'b11111;
+ row[2] = 5'b11111;
+ row[3] = 5'b11111;
+ row[4] = 5'b11111;
+ row[5] = 5'b11111;
+ row[6] = 5'b11111;
+ row[7] = 5'b11111;
+ end
+
+ // El gran mapa de teclado y sus registros de acceso
+ reg [7:0] keymap[0:16383]; // 16K x 8 bits
+ reg [13:0] addr = 14'h0000;
+ reg [13:0] cpuaddr = 14'h0000; // Dirección E/S desde la CPU. Se autoincrementa en cada acceso
+ initial begin
+ $readmemh ("keyb_es_hex.txt", keymap);
+ end
+
+ reg [2:0] keyrow1 = 3'h0;
+ reg [4:0] keycol1 = 5'h00;
+ reg [2:0] keyrow2 = 3'h0;
+ reg [4:0] keycol2 = 5'h00;
+ reg [2:0] keymodifiers = 3'b000;
+ reg [2:0] signalstate = 3'b000;
+ reg [4:0] joystate = 5'b00000;
+ reg [4:0] togglestate = 5'h00;
+
+ reg rmaster_reset = 1'b0, ruser_reset = 1'b0, ruser_nmi = 1'b0;
+ reg rjoyup = 1'b0, rjoydown = 1'b0, rjoyleft = 1'b0, rjoyright = 1'b0, rjoyfire = 1'b0;
+ reg [4:0] ruser_toggles = 5'h00;
+ assign joyup = rjoyup;
+ assign joydown = rjoydown;
+ assign joyleft = rjoyleft;
+ assign joyright = rjoyright;
+ assign joyfire = rjoyfire;
+ assign master_reset = rmaster_reset;
+ assign user_reset = ruser_reset;
+ assign user_nmi = ruser_nmi;
+ assign user_toggles = ruser_toggles;
+
+ // Asi funciona la matriz de teclado cuando se piden semifilas
+ // desde la CPU.
+ // Un always @* hubiera quedado más claro en la descripción
+ // pero por algun motivo, el XST no lo ha admitido en este caso
+ assign sp_col = ((sp_row[0] == 1'b0)? row[0] : 5'b11111) &
+ ((sp_row[1] == 1'b0)? row[1] : 5'b11111) &
+ ((sp_row[2] == 1'b0)? row[2] : 5'b11111) &
+ ((sp_row[3] == 1'b0)? row[3] : 5'b11111) &
+ ((sp_row[4] == 1'b0)? row[4] : 5'b11111) &
+ ((sp_row[5] == 1'b0)? row[5] : 5'b11111) &
+ ((sp_row[6] == 1'b0)? row[6] : 5'b11111) &
+ ((sp_row[7] == 1'b0)? row[7] : 5'b11111);
+
+ reg [2:0] modifiers = 3'b000;
+ reg [3:0] keycount = 4'b0000;
+
+ parameter
+ CLEANMATRIX = 4'd0,
+ IDLE = 4'd1,
+ ADDR0PUT = 4'd2,
+ ADDR1PUT = 4'd3,
+ ADDR2PUT = 4'd4,
+ ADDR3PUT = 4'd5,
+ TRANSLATE1 = 4'd6,
+ TRANSLATE2 = 4'd7,
+ TRANSLATE3 = 4'd8,
+ CPUTIME = 4'd9,
+ CPUREAD = 4'd10,
+ CPUWRITE = 4'd11,
+ CPUINCADD = 4'd12,
+ UPDCOUNTERS1= 4'd13,
+ UPDCOUNTERS2= 4'd14;
+
+ reg [3:0] state = CLEANMATRIX;
+ reg key_is_pending = 1'b0;
+
+ always @(posedge clk) begin
+ if (scan_received == 1'b1)
+ key_is_pending <= 1'b1;
+ if (rst == 1'b1 || (kbclean == 1'b1 && state == IDLE && key_is_pending == 1'b0))
+ state <= CLEANMATRIX;
+ else begin
+ case (state)
+ CLEANMATRIX: begin
+ modifiers <= 3'b000;
+ keycount <= 4'b0000;
+ row[0] <= 5'b11111;
+ row[1] <= 5'b11111;
+ row[2] <= 5'b11111;
+ row[3] <= 5'b11111;
+ row[4] <= 5'b11111;
+ row[5] <= 5'b11111;
+ row[6] <= 5'b11111;
+ row[7] <= 5'b11111;
+ state <= IDLE;
+ end
+ IDLE: begin
+ if (key_is_pending == 1'b1) begin
+ addr <= {modifiers, extended, scan, 2'b00}; // 1 scan tiene 8 bits + 1 bit para indicar scan extendido + 3 bits para el modificador usado
+ state <= ADDR0PUT;
+ key_is_pending <= 1'b0;
+ end
+ else if (cpuread == 1'b1 || cpuwrite == 1'b1 || rewind == 1'b1)
+ state <= CPUTIME;
+ end
+ ADDR0PUT: begin
+ {keyrow1,keycol1} <= keymap[addr];
+ addr <= {modifiers, extended, scan, 2'b01};
+ state <= ADDR1PUT;
+ end
+ ADDR1PUT: begin
+ {keyrow2,keycol2} <= keymap[addr];
+ addr <= {modifiers, extended, scan, 2'b10};
+ state <= ADDR2PUT;
+ end
+ ADDR2PUT: begin
+ {signalstate,joystate} <= keymap[addr];
+ addr <= {modifiers, extended, scan, 2'b11};
+ state <= ADDR3PUT;
+ end
+ ADDR3PUT: begin
+ {keymodifiers,togglestate} <= keymap[addr];
+ state <= TRANSLATE1;
+ end
+ TRANSLATE1: begin
+ // Actualiza las 8 semifilas del teclado con la primera tecla
+ if (~released) begin
+ row[keyrow1] <= row[keyrow1] & ~keycol1;
+ end
+ else begin
+ row[keyrow1] <= row[keyrow1] | keycol1;
+ end
+ state <= TRANSLATE2;
+ end
+ TRANSLATE2: begin
+ // Actualiza las 8 semifilas del teclado con la segunda tecla
+ if (~released) begin
+ row[keyrow2] <= row[keyrow2] & ~keycol2;
+ end
+ else begin
+ row[keyrow2] <= row[keyrow2] | keycol2;
+ end
+ state <= TRANSLATE3;
+ end
+ TRANSLATE3: begin
+ // Actualiza modificadores
+ if (~released)
+ modifiers <= modifiers | keymodifiers;
+ else
+ modifiers <= modifiers & ~keymodifiers;
+
+ // Y de la misma forma tendria que actualizar el joystick, resets y los user_toogles
+ if (~released)
+ {rjoyup,rjoydown,rjoyleft,rjoyright,rjoyfire} <= {rjoyup,rjoydown,rjoyleft,rjoyright,rjoyfire} | joystate;
+ else
+ {rjoyup,rjoydown,rjoyleft,rjoyright,rjoyfire} <= {rjoyup,rjoydown,rjoyleft,rjoyright,rjoyfire} & ~joystate;
+
+ if (~released)
+ {rmaster_reset,ruser_reset,ruser_nmi} <= {rmaster_reset,ruser_reset,ruser_nmi} | signalstate;
+ else
+ {rmaster_reset,ruser_reset,ruser_nmi} <= {rmaster_reset,ruser_reset,ruser_nmi} & ~signalstate;
+
+ if (~released)
+ ruser_toggles <= ruser_toggles | togglestate;
+ else
+ ruser_toggles <= ruser_toggles & ~togglestate;
+
+ state <= IDLE;
+ end
+ CPUTIME: begin
+ if (rewind == 1'b1) begin
+ cpuaddr <= 14'h0000;
+ state <= IDLE;
+ end
+ else if (cpuread == 1'b1) begin
+ addr <= cpuaddr;
+ state <= CPUREAD;
+ end
+ else if (cpuwrite == 1'b1) begin
+ addr <= cpuaddr;
+ state <= CPUWRITE;
+ end
+ else
+ state <= IDLE;
+ end
+ CPUREAD: begin // CPU wants to read from keymap
+ dout <= keymap[addr];
+ state <= CPUINCADD;
+ end
+ CPUWRITE: begin
+ keymap[addr] <= din;
+ state <= CPUINCADD;
+ end
+ CPUINCADD: begin
+ if (cpuread == 1'b0 && cpuwrite == 1'b0) begin
+ cpuaddr <= cpuaddr + 1;
+ state <= IDLE;
+ end
+ end
+ default: begin
+ state <= IDLE;
+ end
+ endcase
+ end
+ end
+endmodule
+
+module keyboard_pressed_status (
+ input wire clk,
+ input wire rst,
+ input wire scan_received,
+ input wire [7:0] scancode,
+ input wire extended,
+ input wire released,
+ output reg kbclean
+ );
+
+ parameter
+ RESETTING = 2'd0,
+ UPDATING = 2'd1,
+ SCANNING = 2'd2;
+
+ reg keybstat_ne[0:255]; // non extended keymap
+ reg keybstat_ex[0:255]; // extended keymap
+ reg [7:0] addrscan = 8'h00; // keymap bit address
+ reg keypressed_ne = 1'b0; // there is at least one key pressed
+ reg keypressed_ex = 1'b0; // there is at least one extended key pressed
+ reg [1:0] state = RESETTING;
+
+ integer i;
+ initial begin
+ kbclean = 1'b1;
+ for (i=0;i<256;i=i+1) begin
+ keybstat_ne[i] = 1'b0;
+ keybstat_ex[i] = 1'b0;
+ end
+ end
+
+ always @(posedge clk) begin
+ if (rst == 1'b1) begin
+ state <= RESETTING;
+ addrscan <= 8'h00;
+ end
+ else begin
+ case (state)
+ RESETTING:
+ begin
+ if (addrscan == 8'hFF) begin
+ addrscan <= 8'h00;
+ state <= SCANNING;
+ kbclean <= 1'b1;
+ end
+ else begin
+ keybstat_ne[addrscan] <= 1'b0;
+ keybstat_ex[addrscan] <= 1'b0;
+ addrscan <= addrscan + 8'd1;
+ end
+ end
+ UPDATING:
+ begin
+ state <= SCANNING;
+ addrscan <= 8'h00;
+ kbclean <= 1'b0;
+ keypressed_ne <= 1'b0;
+ keypressed_ex <= 1'b0;
+ if (extended == 1'b0)
+ keybstat_ne[scancode] <= ~released;
+ else
+ keybstat_ex[scancode] <= ~released;
+ end
+ SCANNING:
+ begin
+ if (scan_received == 1'b1)
+ state <= UPDATING;
+ addrscan <= addrscan + 8'd1;
+ if (addrscan == 8'hFF) begin
+ kbclean <= ~(keypressed_ne | keypressed_ex);
+ keypressed_ne <= 1'b0;
+ keypressed_ex <= 1'b0;
+ end
+ else begin
+ keypressed_ne <= keypressed_ne | keybstat_ne[addrscan];
+ keypressed_ex <= keypressed_ex | keybstat_ex[addrscan];
+ end
+ end
+ endcase
+ end
+ end
+endmodule
+
\ No newline at end of file
diff --git a/cores/Spectrum/zxuno.xise b/cores/Spectrum/zxuno.xise
index 701b0a2..064fc49 100644
--- a/cores/Spectrum/zxuno.xise
+++ b/cores/Spectrum/zxuno.xise
@@ -187,10 +187,10 @@
-
-
+
+
-
+
@@ -198,7 +198,7 @@
-
+
@@ -215,7 +215,7 @@
-
+
@@ -416,7 +416,7 @@
-
+
@@ -434,7 +434,7 @@
-
+