From b8da4b137acde3d4fda636bc7d7087ddb9461c4f Mon Sep 17 00:00:00 2001 From: antoniovillena Date: Thu, 28 Apr 2016 14:26:39 +0200 Subject: [PATCH] Spectrum test17 --- cores/Spectrum/bootloader_hex.txt | 51 ++++++ cores/Spectrum/coreid.v | 6 +- cores/Spectrum/cuatro_relojes.v | 162 +++++++++++++++++ cores/Spectrum/genkeybmap_es.c | 12 +- cores/Spectrum/keyb_es_hex.txt | 2 +- cores/Spectrum/keymaps/ES | Bin 16384 -> 16384 bytes cores/Spectrum/memory.v | 15 +- cores/Spectrum/nmievents.v | 88 +++++++++ cores/Spectrum/pines_zxuno.ucf | 2 +- cores/Spectrum/ps2_port.v | 162 ++++++++++------- cores/Spectrum/scancode_to_speccy.v | 266 ++++++++++++++-------------- cores/Spectrum/testnmi.asm | 84 +++++++++ cores/Spectrum/tld_zxuno.v | 26 ++- cores/Spectrum/turbosound.v | 4 +- cores/Spectrum/ula_radas.v | 14 +- cores/Spectrum/zxuno.v | 111 +++++------- cores/Spectrum/zxuno.xise | 19 +- 17 files changed, 720 insertions(+), 304 deletions(-) create mode 100644 cores/Spectrum/cuatro_relojes.v create mode 100644 cores/Spectrum/nmievents.v create mode 100644 cores/Spectrum/testnmi.asm diff --git a/cores/Spectrum/bootloader_hex.txt b/cores/Spectrum/bootloader_hex.txt index 2b12c11..838b2c1 100644 --- a/cores/Spectrum/bootloader_hex.txt +++ b/cores/Spectrum/bootloader_hex.txt @@ -54,3 +54,54 @@ FE ED A3 E9 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +C3 +00 +C0 +ED +45 diff --git a/cores/Spectrum/coreid.v b/cores/Spectrum/coreid.v index 873b4ab..d4877ec 100644 --- a/cores/Spectrum/coreid.v +++ b/cores/Spectrum/coreid.v @@ -37,10 +37,10 @@ module coreid ( text[i] = 8'h00; text[ 0] = "T"; text[ 1] = "1"; - text[ 2] = "6"; + text[ 2] = "7"; text[ 3] = "-"; - text[ 4] = "1"; - text[ 5] = "4"; + text[ 4] = "2"; + text[ 5] = "9"; text[ 6] = "0"; text[ 7] = "6"; text[ 8] = "2"; diff --git a/cores/Spectrum/cuatro_relojes.v b/cores/Spectrum/cuatro_relojes.v new file mode 100644 index 0000000..3656dc1 --- /dev/null +++ b/cores/Spectrum/cuatro_relojes.v @@ -0,0 +1,162 @@ +// file: tres_relojes.v +// +// (c) Copyright 2008 - 2010 Xilinx, Inc. All rights reserved. +// +// This file contains confidential and proprietary information +// of Xilinx, Inc. and is protected under U.S. and +// international copyright and other intellectual property +// laws. +// +// DISCLAIMER +// This disclaimer is not a license and does not grant any +// rights to the materials distributed herewith. Except as +// otherwise provided in a valid license issued to you by +// Xilinx, and to the maximum extent permitted by applicable +// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND +// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES +// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING +// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- +// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and +// (2) Xilinx shall not be liable (whether in contract or tort, +// including negligence, or under any other theory of +// liability) for any loss or damage of any kind or nature +// related to, arising under or in connection with these +// materials, including for any direct, or any indirect, +// special, incidental, or consequential loss or damage +// (including loss of data, profits, goodwill, or any type of +// loss or damage suffered as a result of any action brought +// by a third party) even if such damage or loss was +// reasonably foreseeable or Xilinx had been advised of the +// possibility of the same. +// +// CRITICAL APPLICATIONS +// Xilinx products are not designed or intended to be fail- +// safe, or for use in any application requiring fail-safe +// performance, such as life-support or safety devices or +// systems, Class III medical devices, nuclear facilities, +// applications related to the deployment of airbags, or any +// other applications that could lead to death, personal +// injury, or severe property or environmental damage +// (individually and collectively, "Critical +// Applications"). Customer assumes the sole risk and +// liability of any use of Xilinx products in Critical +// Applications, subject only to applicable laws and +// regulations governing limitations on product liability. +// +// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS +// PART OF THIS FILE AT ALL TIMES. +// +//---------------------------------------------------------------------------- +// User entered comments +//---------------------------------------------------------------------------- +// None +// +//---------------------------------------------------------------------------- +// Output Output Phase Duty Cycle Pk-to-Pk Phase +// Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps) +//---------------------------------------------------------------------------- +// CLK_OUT1 28.000 0.000 50.0 297.991 199.399 +// CLK_OUT2 14.000 180.000 50.0 342.124 199.399 +// CLK_OUT3 7.000 180.000 50.0 391.159 199.399 +// +//---------------------------------------------------------------------------- +// Input Clock Input Freq (MHz) Input Jitter (UI) +//---------------------------------------------------------------------------- +// primary 50 0.010 + +`timescale 1ps/1ps +`default_nettype none + +(* CORE_GENERATION_INFO = "tres_relojes,clk_wiz_v1_8,{component_name=tres_relojes,use_phase_alignment=true,use_min_o_jitter=false,use_max_i_jitter=false,use_dyn_phase_shift=false,use_inclk_switchover=false,use_dyn_reconfig=false,feedback_source=FDBK_AUTO,primtype_sel=PLL_BASE,num_out_clk=3,clkin1_period=20.0,clkin2_period=20.0,use_power_down=false,use_reset=false,use_locked=false,use_inclk_stopped=false,use_status=false,use_freeze=false,use_clk_valid=false,feedback_type=SINGLE,clock_mgr_type=AUTO,manual_override=false}" *) +module cuatro_relojes + (// Clock in ports + input wire CLK_IN1, + // Clock out ports + output wire CLK_OUT1, + output wire CLK_OUT2, + output wire CLK_OUT3, + output wire CLK_OUT4 + ); + + wire clkin1,clkout0,clkout1,clkout2,clkout3; + // Input buffering + //------------------------------------ + IBUFG clkin1_buf + (.O (clkin1), + .I (CLK_IN1)); + + + // Clocking primitive + //------------------------------------ + // Instantiation of the PLL primitive + // * Unused inputs are tied off + // * Unused outputs are labeled unused + wire [15:0] do_unused; + wire drdy_unused; + wire locked_unused; + wire clkfbout; + wire clkfbout_buf; + wire clkout4_unused; + wire clkout5_unused; + + PLL_BASE + #(.BANDWIDTH ("OPTIMIZED"), + .CLK_FEEDBACK ("CLKFBOUT"), + .COMPENSATION ("SYSTEM_SYNCHRONOUS"), + .DIVCLK_DIVIDE (1), + .CLKFBOUT_MULT (9), + .CLKFBOUT_PHASE (0.000), + .CLKOUT0_DIVIDE (16), + .CLKOUT0_PHASE (0.000), + .CLKOUT0_DUTY_CYCLE (0.500), + .CLKOUT1_DIVIDE (32), + .CLKOUT1_PHASE (0.000), + .CLKOUT1_DUTY_CYCLE (0.500), + .CLKOUT2_DIVIDE (64), + .CLKOUT2_PHASE (0.000), + .CLKOUT3_DIVIDE (128), + .CLKOUT3_PHASE (0.000), + .CLKOUT2_DUTY_CYCLE (0.500), + .CLKIN_PERIOD (20.0), + .REF_JITTER (0.010)) + pll_base_inst + // Output clocks + (.CLKFBOUT (clkfbout), + .CLKOUT0 (clkout0), + .CLKOUT1 (clkout1), + .CLKOUT2 (clkout2), + .CLKOUT3 (clkout3), + .CLKOUT4 (clkout4_unused), + .CLKOUT5 (clkout5_unused), + .LOCKED (locked_unused), + .RST (1'b0), + // Input clock control + .CLKFBIN (clkfbout_buf), + .CLKIN (clkin1)); + + + // Output buffering + //----------------------------------- + BUFG clkf_buf + (.O (clkfbout_buf), + .I (clkfbout)); + + + BUFG clkout1_buf + (.O (CLK_OUT1), + .I (clkout0)); + + + BUFG clkout2_buf + (.O (CLK_OUT2), + .I (clkout1)); + + BUFG clkout3_buf + (.O (CLK_OUT3), + .I (clkout2)); + + BUFG clkout4_buf + (.O (CLK_OUT4), + .I (clkout3)); + +endmodule diff --git a/cores/Spectrum/genkeybmap_es.c b/cores/Spectrum/genkeybmap_es.c index c23e45b..edcf822 100644 --- a/cores/Spectrum/genkeybmap_es.c +++ b/cores/Spectrum/genkeybmap_es.c @@ -149,11 +149,11 @@ D+3 : modificadores y se #define JOYRIGHT 0x02 #define JOYFIRE 0x01 -#define USER1 0x10 -#define USER2 0x08 +#define USER5 0x10 +#define USER4 0x08 #define USER3 0x04 -#define USER4 0x02 -#define USER5 0x01 +#define USER2 0x02 +#define USER1 0x01 // End of additional signals // A key can be pressed with up to three key modifiers @@ -421,7 +421,7 @@ int main() MAP(PC_DELETE|MD2|MD3,0,URESET,0); // MAP(PC_KP_DOT|MD2|MD3,0,URESET,0); // Ctrl-Alt-Del for user reset MAP(PC_BKSPACE|MD2|MD3,0,MRESET,0); // Ctrl-Alt-BkSpace for master reset - + //keypad MAPANY(PC_KP_DIVIS,SP_SLASH,0,0); MAPANY(PC_KP_MULT,SP_STAR,0,0); @@ -481,6 +481,8 @@ int main() MAP(MD3|MD2|PC_LESS,SP_NOTEQ,0,0); MAP(MD3|MD2|MD1|PC_LESS,SP_NOTEQ,0,0); + MAP(PC_F12,0,0,USER1); // Evento de usuario 1 + // End of mapping. Save .HEX file for Verilog SAVEMAPHEX("keyb_es_hex.txt"); // And map file for loading from ESXDOS diff --git a/cores/Spectrum/keyb_es_hex.txt b/cores/Spectrum/keyb_es_hex.txt index 1e3405d..d8c1f95 100644 --- a/cores/Spectrum/keyb_es_hex.txt +++ b/cores/Spectrum/keyb_es_hex.txt @@ -29,7 +29,7 @@ 00 00 00 -00 +01 00 00 00 diff --git a/cores/Spectrum/keymaps/ES b/cores/Spectrum/keymaps/ES index e4c371018e75019bea81244c2f7831145cae3234..abc8bc96c43400b7f46e9198ffccf7221f6d9f81 100644 GIT binary patch delta 14 VcmZo@U~Fh$oFLE0xKZJOJpdxA1f&1} delta 16 XcmZo@U~Fh$oFG40o`ZFx${l+EEx`q0 diff --git a/cores/Spectrum/memory.v b/cores/Spectrum/memory.v index 684b71a..0883f43 100644 --- a/cores/Spectrum/memory.v +++ b/cores/Spectrum/memory.v @@ -38,6 +38,7 @@ module memory ( input wire m1_n, input wire rfsh_n, output wire enable_nmi_n, + input wire page_configrom_active, // Interface con la ULA input wire [13:0] vramaddr, @@ -70,6 +71,7 @@ module memory ( reg timming = 1'b0; reg disable_cont = 1'b0; reg masterconf_frozen = 1'b0; + reg [1:0] negedge_configrom = 2'b00; assign issue2_keyboard_enabled = issue2_keyboard; assign in_boot_mode = ~masterconf_frozen; @@ -77,10 +79,19 @@ module memory ( assign disable_contention = disable_cont; always @(posedge clk) begin + negedge_configrom <= {negedge_configrom[0], page_configrom_active}; if (!mrst_n) begin {disable_cont,timming,issue2_keyboard,divmmc_nmi_is_disabled,divmmc_is_enabled,initial_boot_mode} <= 6'b000001; masterconf_frozen <= 1'b0; end + else if (page_configrom_active == 1'b1) begin + masterconf_frozen <= 1'b0; + initial_boot_mode <= 1'b1; + end + else if (negedge_configrom == 2'b10) begin + masterconf_frozen <= 1'b1; + initial_boot_mode <= 1'b0; + end else if (addr==MASTERCONF && iow) begin {disable_cont,timming,issue2_keyboard} <= din[5:3]; if (!masterconf_frozen) begin @@ -123,7 +134,7 @@ module memory ( if (!mreq_n && !rd_n && !m1_n && (a==16'h0000 || a==16'h0008 || a==16'h0038 || - (a==16'h0066 && divmmc_nmi_is_disabled==1'b0) || + (a==16'h0066 && divmmc_nmi_is_disabled==1'b0 && page_configrom_active==1'b0) || a==16'h04C6 || a==16'h0562)) begin // automapper diferido (siguiente ciclo) divmmc_status_after_m1 <= 1'b1; @@ -218,7 +229,7 @@ module memory ( end else if (!amstrad_allram_page_mode) begin // en el modo normal de paginación, hay 4 bancos de ROMs - addr_port2 = {3'b010,banco_rom,a[13:0]}; + addr_port2 = {3'b010,banco_rom,a[13:0]}; // que vienen de los bancos de SRAM del 8 al 11 we2_n = 1'b1; end else begin // en el modo especial de paginación, tenemos el all-RAM diff --git a/cores/Spectrum/nmievents.v b/cores/Spectrum/nmievents.v new file mode 100644 index 0000000..336f9b2 --- /dev/null +++ b/cores/Spectrum/nmievents.v @@ -0,0 +1,88 @@ +`timescale 1ns / 1ps +`default_nettype none + +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 03:05:03 06/28/2015 +// Design Name: +// Module Name: nmievents +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module nmievents ( + input wire clk, + input wire rst_n, + //------------------------------ + input wire [7:0] zxuno_addr, + input wire zxuno_regrd, + //------------------------------ + input wire [4:0] userevents, + //------------------------------ + input wire [15:0] a, + input wire m1_n, + input wire mreq_n, + input wire rd_n, + output wire [7:0] dout, + output wire oe_n, + output reg nmiout_n, + output reg page_configrom_active + ); + + parameter NMIEVENT = 8'h08; + parameter IDLE = 1'd0, + ABOUT_TO_EXIT = 1'd1; + + initial page_configrom_active = 1'b0; + initial nmiout_n = 1'b1; + + reg state = IDLE; + reg [7:0] nmieventreg = 8'h00; + assign dout = nmieventreg; + assign oe_n = ~(zxuno_addr == NMIEVENT && zxuno_regrd == 1'b1); + + always @(posedge clk) begin + if (rst_n == 1'b0) begin + nmieventreg <= 8'h00; + page_configrom_active <= 1'b0; + state <= IDLE; + end + else begin + if (userevents != 5'b00000 && page_configrom_active == 1'b0) begin + nmieventreg <= {3'b000, userevents}; + nmiout_n <= 1'b0; + page_configrom_active <= 1'b1; + state <= IDLE; + end + if (mreq_n == 1'b0 && m1_n == 1'b0 && a == 16'h0066 && page_configrom_active == 1'b1) // ya estamos en NMI + nmiout_n <= 1'b1; // asi que desactivo la señal + + case (state) + IDLE: + begin + if (mreq_n == 1'b0 && m1_n == 1'b0 && rd_n == 1'b0 && a==16'h006A && page_configrom_active == 1'b1) + state <= ABOUT_TO_EXIT; + end + ABOUT_TO_EXIT: + begin + if (m1_n == 1'b1) begin + page_configrom_active <= 1'b0; + nmieventreg <= 8'h00; + state <= IDLE; + end + end + default: state <= IDLE; + endcase + end + end +endmodule diff --git a/cores/Spectrum/pines_zxuno.ucf b/cores/Spectrum/pines_zxuno.ucf index f652ef6..0856bc6 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_port.v b/cores/Spectrum/ps2_port.v index 31eb055..5fd47ff 100644 --- a/cores/Spectrum/ps2_port.v +++ b/cores/Spectrum/ps2_port.v @@ -78,42 +78,47 @@ module ps2_port ( end if (ps2clkedge && enable_rcv) begin timeoutcnt <= 16'h0000; - if (state == `RCVSTART && ps2data == 1'b0) begin - state <= `RCVDATA; - key <= 8'h80; - //rkb_interrupt <= 1'b0; - end - else if (state == `RCVDATA) begin - key <= {ps2data, key[7:1]}; - if (key[0] == 1'b1) begin - state <= `RCVPARITY; + case (state) + `RCVSTART: begin + if (ps2data == 1'b0) begin + state <= `RCVDATA; + key <= 8'h80; + //rkb_interrupt <= 1'b0; + end end - end - else if (state == `RCVPARITY) begin - if (ps2data^paritycalculated == 1'b1) begin - state <= `RCVSTOP; + `RCVDATA: begin + key <= {ps2data, key[7:1]}; + if (key[0] == 1'b1) begin + state <= `RCVPARITY; + end end - else begin - state <= `RCVSTART; + `RCVPARITY: begin + if (ps2data^paritycalculated == 1'b1) begin + state <= `RCVSTOP; + end + else begin + state <= `RCVSTART; + end end - end - else if (state == `RCVSTOP) begin - state <= `RCVSTART; - if (ps2data == 1'b1) begin - scancode <= key; - if (key == 8'hE0) begin - regextended <= 2'b01; - end - else if (key == 8'hF0) begin - regreleased <= 2'b01; - end - else begin - regextended <= {regextended[0], 1'b0}; - regreleased <= {regreleased[0], 1'b0}; - rkb_interrupt <= 1'b1; - end - end - end + `RCVSTOP: begin + state <= `RCVSTART; + if (ps2data == 1'b1) begin + scancode <= key; + if (key == 8'hE0) begin + regextended <= 2'b01; + end + else if (key == 8'hF0) begin + regreleased <= 2'b01; + end + else begin + regextended <= {regextended[0], 1'b0}; + regreleased <= {regreleased[0], 1'b0}; + rkb_interrupt <= 1'b1; + end + end + end + default: state <= `RCVSTART; + endcase end else begin timeoutcnt <= timeoutcnt + 1; @@ -192,47 +197,70 @@ module ps2_host_to_kb ( state <= `PULLCLKLOW; end - if (state == `PULLCLKLOW && timeoutcnt >= 16'd40000) begin // 40000 cuentas es poco más de 10ms - state <= `PULLDATALOW; - shiftreg <= rdata; - cntbits <= 3'd0; - timeoutcnt <= 16'h0000; - end - else if (state == `PULLDATALOW && ps2clknedge) begin - state <= `SENDDATA; - timeoutcnt <= 16'h0000; - end - else if (state == `SENDDATA && ps2clknedge) begin - timeoutcnt <= 16'h0000; - shiftreg <= {1'b0, shiftreg[7:1]}; - cntbits <= cntbits + 1; - if (cntbits == 3'd7) - state <= `SENDPARITY; - end - else if (state == `SENDPARITY && ps2clknedge) begin - state <= `RCVIDLE; - timeoutcnt <= 16'h0000; - end - else if (state == `RCVIDLE && ps2clknedge /*&& ps2data_in == 1'b1*/) begin - state <= `RCVACK; - timeoutcnt <= 16'h0000; - end - else if (state == `RCVACK && ps2clknedge /*&& ps2data_in == 1'b0*/) begin - state <= `SENDFINISHED; - timeoutcnt <= 16'h0000; - end - else if (state == `SENDFINISHED) begin - busy <= 1'b0; - timeoutcnt <= 16'h0000; - end - else begin + if (!ps2clknedge) begin timeoutcnt <= timeoutcnt + 1; if (timeoutcnt == 16'hFFFF && state != `SENDFINISHED) begin error <= 1'b1; state <= `SENDFINISHED; end end + + case (state) + `PULLCLKLOW: begin // 40000 cuentas es poco más de 10ms + if (timeoutcnt >= 16'd40000) begin + state <= `PULLDATALOW; + shiftreg <= rdata; + cntbits <= 3'd0; + timeoutcnt <= 16'h0000; + end + end + `PULLDATALOW: begin + if (ps2clknedge) begin + state <= `SENDDATA; + timeoutcnt <= 16'h0000; + end + end + `SENDDATA: begin + if (ps2clknedge) begin + timeoutcnt <= 16'h0000; + shiftreg <= {1'b0, shiftreg[7:1]}; + cntbits <= cntbits + 1; + if (cntbits == 3'd7) + state <= `SENDPARITY; + end + end + `SENDPARITY: begin + if (ps2clknedge) begin + state <= `RCVIDLE; + timeoutcnt <= 16'h0000; + end + end + `RCVIDLE: begin + if (ps2clknedge) begin + state <= `RCVACK; + timeoutcnt <= 16'h0000; + end + end + `RCVACK: begin + if (ps2clknedge) begin + state <= `SENDFINISHED; + timeoutcnt <= 16'h0000; + end + end + `SENDFINISHED: begin + busy <= 1'b0; + timeoutcnt <= 16'h0000; + end + default: begin + timeoutcnt <= timeoutcnt + 1; + if (timeoutcnt == 16'hFFFF && state != `SENDFINISHED) begin + error <= 1'b1; + state <= `SENDFINISHED; + end + end + endcase end + assign ps2data_ext = (state == `PULLCLKLOW || state == `PULLDATALOW) ? 1'b0 : (state == `SENDDATA && shiftreg[0] == 1'b0) ? 1'b0 : (state == `SENDPARITY && paritycalculated == 1'b0) ? 1'b0 : // si lo que se va a enviar es un 1 diff --git a/cores/Spectrum/scancode_to_speccy.v b/cores/Spectrum/scancode_to_speccy.v index 78711e4..42f5ac2 100644 --- a/cores/Spectrum/scancode_to_speccy.v +++ b/cores/Spectrum/scancode_to_speccy.v @@ -130,138 +130,142 @@ module scancode_to_speccy ( key_is_pending <= 1'b1; if (rst == 1'b1) state <= CLEANMATRIX; - else if (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 - else if (state == 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 - else if (state == ADDR0PUT) begin - {keyrow1,keycol1} <= keymap[addr]; - addr <= {modifiers, extended, scan, 2'b01}; - state <= ADDR1PUT; - end - else if (state == ADDR1PUT) begin - {keyrow2,keycol2} <= keymap[addr]; - addr <= {modifiers, extended, scan, 2'b10}; - state <= ADDR2PUT; - end - else if (state == ADDR2PUT) begin - {signalstate,joystate} <= keymap[addr]; - addr <= {modifiers, extended, scan, 2'b11}; - state <= ADDR3PUT; - end - else if (state == ADDR3PUT) begin - {keymodifiers,togglestate} <= keymap[addr]; - state <= TRANSLATE1; - end - else if (state == 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 - else if (state == 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 - else if (state == 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 <= UPDCOUNTERS1; - state <= IDLE; - end - else if (state == 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 - else if (state == CPUREAD) begin // CPU wants to read from keymap - dout <= keymap[addr]; - state <= CPUINCADD; - end - else if (state == CPUWRITE) begin - keymap[addr] <= din; - state <= CPUINCADD; - end - else if (state == CPUINCADD) begin - if (cpuread == 1'b0 && cpuwrite == 1'b0) begin - cpuaddr <= cpuaddr + 1; - 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 else begin - state <= IDLE; + 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 <= UPDCOUNTERS1; + 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 + // 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 + endcase end end endmodule diff --git a/cores/Spectrum/testnmi.asm b/cores/Spectrum/testnmi.asm new file mode 100644 index 0000000..e0690b4 --- /dev/null +++ b/cores/Spectrum/testnmi.asm @@ -0,0 +1,84 @@ + org 28000 +Main di + ld bc,7ffdh + ld a,16+6 ;pagina 6 de RAM + out (c),a + ld hl,Rom + ld de,0c000h ;Copiar ROM NMI a esta dirección + ld bc,LRom + ldir + ld bc,7ffdh + ld a,16 ;Restablecemos página 0 de RAM + out (c),a + ei + ret + +Rom ;Esto se ejecuta a partir de C000h. + ;Guardar puntero de pila, establecer pila privada y guardar registros + ld (OldSP-Rom+0c000h),sp + ld sp,Stack-Rom+0c000h + push af + push bc + push de + push hl + + ;Salvaguarda zona de atributos + ld hl,22528 + ld de,Buffer-Rom+0c000h + ld bc,768 + ldir + + ;Pon el banner de PAUSE + ld hl,Banner-Rom+0c000h + ld de,22528+32*8+1 + ld b,7 +BucBanner push bc + ld bc,29 + ldir + inc de + inc de + inc de + pop bc + djnz BucBanner + + ;Espera una tecla para terminar pausa +BucWaitKey xor a + in a,(254) + and 31 + cp 31 + jr z,BucWaitKey + + ;Restaura zona de atributos + ld hl,Buffer-Rom+0c000h + ld de,22528 + ld bc,768 + ldir + + ;Restablecer registros y puntero de pila anterior + pop hl + pop de + pop bc + pop af + ld sp,(OldSP-Rom+0c000h) + + ;Saltar a direccion de fin de NMI + jp 0069h + +Banner db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 + db 000,255,255,255,000,000,000,255,255,255,000,000,255,000,000,000,255,000,000,255,255,255,000,000,255,255,255,255,000 + db 000,255,000,000,255,000,255,000,000,000,255,000,255,000,000,000,255,000,255,000,000,000,000,000,255,000,000,000,000 + db 000,255,255,255,000,000,255,255,255,255,255,000,255,000,000,000,255,000,000,255,255,255,000,000,255,255,255,255,000 + db 000,255,000,000,000,000,255,000,000,000,255,000,255,000,000,000,255,000,000,000,000,000,255,000,255,000,000,000,000 + db 000,255,000,000,000,000,255,000,000,000,255,000,000,255,255,255,000,000,000,255,255,255,000,000,255,255,255,255,000 + db 000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 + +OldSP dw 0 + + ds 16 ;16 bytes de pila +Stack equ $ + +Buffer equ $ + +LRom equ $-Rom + end Main + diff --git a/cores/Spectrum/tld_zxuno.v b/cores/Spectrum/tld_zxuno.v index 10970b0..649fdf7 100644 --- a/cores/Spectrum/tld_zxuno.v +++ b/cores/Spectrum/tld_zxuno.v @@ -58,7 +58,7 @@ module tld_zxuno ( input wire joyfire ); - wire wssclk,sysclk; + wire wssclk,sysclk,clk14,clk7,clk3d5; // relojes los_relojes_del_sistema ( // .CLKIN_IN(clk50mhz), // .CLKDV_OUT(wssclk), // 5MHz @@ -71,16 +71,25 @@ module tld_zxuno ( assign wssclk = 1'b0; // de momento, sin WSS assign stdn = 1'b0; // fijar norma PAL assign stdnb = 1'b1; // y conectamos reloj PAL - pll reloj_maestro +// pll reloj_maestro +// (// Clock in ports +// .CLK_IN1 (clk50mhz), // IN +// // Clock out ports +// .CLK_OUT1 (sysclk), // OUT +// // Dynamic reconfiguration ports +// .PROGCLK (1'b0), // IN +// .PROGDATA (1'b0), // IN +// .PROGEN (1'b0), // IN +// .PROGDONE ()); // OUT + + cuatro_relojes relojes_maestros (// Clock in ports .CLK_IN1 (clk50mhz), // IN // Clock out ports .CLK_OUT1 (sysclk), // OUT - // Dynamic reconfiguration ports - .PROGCLK (1'b0), // IN - .PROGDATA (1'b0), // IN - .PROGEN (1'b0), // IN - .PROGDONE ()); // OUT + .CLK_OUT2 (clk14), // OUT + .CLK_OUT3 (clk7), // OUT + .CLK_OUT4 (clk3d5)); // OUT wire audio_out; assign audio_out_left = audio_out; @@ -89,6 +98,9 @@ module tld_zxuno ( zxuno la_maquina ( .clk(sysclk), // 28MHz, reloj base para la memoria de doble puerto, y de ahí, para el resto del circuito .wssclk(wssclk), // 5MHz, reloj para el WSS + .clk14(clk14), + .clk7(clk7), + .clk3d5(clk3d5), .power_on_reset_n(1'b1), // sólo para simulación. Para implementacion, dejar a 1 .r(r), .g(g), diff --git a/cores/Spectrum/turbosound.v b/cores/Spectrum/turbosound.v index 13383a1..884cd5a 100644 --- a/cores/Spectrum/turbosound.v +++ b/cores/Spectrum/turbosound.v @@ -21,7 +21,7 @@ // ////////////////////////////////////////////////////////////////////////////////// module turbosound ( - input wire clk7, + input wire clk, input wire clkay, input wire reset_n, input wire bdir, @@ -34,7 +34,7 @@ module turbosound ( ); reg ay_select = 1'b1; - always @(posedge clk7 or negedge reset_n) begin + always @(posedge clk) begin if (reset_n==1'b0) ay_select <= 1'b1; else if (bdir && bc1 && din[7:1]==7'b1111111) diff --git a/cores/Spectrum/ula_radas.v b/cores/Spectrum/ula_radas.v index 84e54d5..64a2355 100644 --- a/cores/Spectrum/ula_radas.v +++ b/cores/Spectrum/ula_radas.v @@ -24,6 +24,7 @@ module ula_radas ( // Clocks input wire clk14, // 14MHz master clock + input wire clk7, input wire wssclk, // 5MHz WSS clock input wire rst_n, // reset para volver al modo normal @@ -47,9 +48,6 @@ module ula_radas ( input wire [4:0] kbd, output reg mic, output reg spk, - output wire clkay, - output wire clkdac, - output wire clkkbd, input wire issue2_keyboard, input wire timming, input wire disable_contention, @@ -79,13 +77,9 @@ module ula_radas ( wire [8:0] hc; wire [8:0] vc; - reg clk7 = 1'b0; + reg clkhalf14 = 1'b0; always @(posedge clk14) - clk7 <= ~clk7; - - assign clkdac = clk7; - assign clkay = hc[0]; - assign clkkbd = clk7; /* hc[4] */ + clkhalf14 <= ~clkhalf14; pal_sync_generator_sinclair syncs ( .clk(clk7), @@ -173,7 +167,7 @@ module ula_radas ( reg [15:0] BitmapSerializerHR = 8'h00; wire SerialOutputHR = BitmapSerializerHR[15]; always @(posedge clk14) begin - if (SerializerLoad && clk7) // load enable only for a single 14MHz cycle + if (SerializerLoad && clkhalf14) // load enable only for a single 14MHz cycle BitmapSerializerHR <= {BitmapData,AttrData}; else BitmapSerializerHR <= {BitmapSerializerHR[14:0],1'b0}; diff --git a/cores/Spectrum/zxuno.v b/cores/Spectrum/zxuno.v index 6061627..9f2ccfa 100644 --- a/cores/Spectrum/zxuno.v +++ b/cores/Spectrum/zxuno.v @@ -24,7 +24,10 @@ module zxuno ( // Relojes input wire clk, // 28MHz, reloj del sistema input wire wssclk, // 5MHz, reloj de la señal WSS - input wire power_on_reset_n, + input wire clk14, + input wire clk7, + input wire clk3d5, + input wire power_on_reset_n, // E/S output wire [2:0] r, @@ -82,8 +85,6 @@ module zxuno ( wire [7:0] ay_dout; wire bc1,bdir; wire oe_n_ay; - wire clkay; // suministrado por la ULA (3.5MHz) - wire clkdac; // suministrado por la ULA (7MHz) // Señales de acceso a registro de direcciones ZX-Uno wire [7:0] zxuno_addr_to_cpu; // al bus de datos de entrada del Z80 @@ -102,12 +103,11 @@ module zxuno ( wire mic; wire spk; wire [7:0] ay1_audio; - wire [7:0] ay2_audio; + wire [7:0] ay2_audio; // Interfaz de acceso al teclado - wire clkkbd; // suministrado por la ULA (218kHz) wire [4:0] kbdcol; - wire [7:0] kbdrow; + wire [7:0] kbdrow = cpuaddr[15:8]; // las filas del teclado son A8-A15 de la CPU; wire mrst_n,rst_n; // los dos resets suministrados por el teclado wire [7:0] scancode_dout; // scancode original desde el teclado PC wire oe_n_scancode; @@ -115,6 +115,7 @@ module zxuno ( wire oe_n_keymap; wire [7:0] kbstatus_dout; wire oe_n_kbstatus; + wire [4:0] user_toggles; // Interfaz joystick configurable wire oe_n_joystick; @@ -135,8 +136,12 @@ module zxuno ( // Scratch register wire oe_n_scratch; wire [7:0] scratch_dout; - - assign kbdrow = cpuaddr[15:8]; // las filas del teclado son A8-A15 de la CPU + + // NMI events + wire [7:0] nmievents_dout; + wire oe_n_nmievents; + wire nmispecial_n; + wire page_configrom_active; // Asignación de dato para la CPU segun la decodificación de todos los dispositivos // conectados a ella. @@ -150,6 +155,7 @@ module zxuno ( (oe_n_coreid==1'b0)? coreid_dout : (oe_n_keymap==1'b0)? keymap_dout : (oe_n_scratch==1'b0)? scratch_dout : + (oe_n_nmievents==1'b0)? nmievents_dout : ula_dout; tv80n_wrapper el_z80 ( @@ -168,22 +174,17 @@ module zxuno ( .clk(cpuclk), .wait_n(1'b1), .int_n(int_n), - .nmi_n(nmi_n | enable_nmi_n), + .nmi_n((nmi_n | enable_nmi_n) & nmispecial_n), .busrq_n(1'b1), .di(cpudin) ); - reg [1:0] clkdiv = 2'b00; - wire clk14 = clkdiv[0]; - wire clk7 = clkdiv[1]; - always @(posedge clk) - clkdiv <= clkdiv + 1; - ula_radas la_ula ( - // Clocks - .clk14(clk14), // 14MHz master clock - .wssclk(wssclk), // 5MHz WSS clock - .rst_n(mrst_n & rst_n & power_on_reset_n), + // Clocks + .clk14(clk14), // 14MHz master clock + .clk7(clk7), + .wssclk(wssclk), // 5MHz WSS clock + .rst_n(mrst_n & rst_n & power_on_reset_n), // CPU interface .a(cpuaddr), @@ -206,9 +207,6 @@ module zxuno ( .mic(mic), .spk(spk), .kbd(kbdcol_to_ula), - .clkay(clkay), - .clkdac(clkdac), - .clkkbd(clkkbd), .issue2_keyboard(issue2_keyboard), .timming(timming_ula), .disable_contention(disable_contention), @@ -221,7 +219,7 @@ module zxuno ( ); zxunoregs addr_reg_zxuno ( - .clk(clk7), + .clk(clk), .rst_n(rst_n & mrst_n & power_on_reset_n), .a(cpuaddr), .iorq_n(iorq_n), @@ -237,7 +235,7 @@ module zxuno ( ); flash_and_sd cacharros_con_spi ( - .clk(clk7), + .clk(clk), .a(cpuaddr), .iorq_n(iorq_n), .rd_n(rd_n), @@ -263,7 +261,7 @@ module zxuno ( memory bootrom_rom_y_ram ( // Relojes y reset - .clk(clk7), // Reloj del sistema CLK7 + .clk(clk), // Reloj del sistema CLK7 .mclk(clk), // Reloj para el modulo de memoria de doble puerto .mrst_n(mrst_n & power_on_reset_n), .rst_n(rst_n & power_on_reset_n), @@ -280,6 +278,7 @@ module zxuno ( .m1_n(m1_n), // Necesarios para implementar DIVMMC .rfsh_n(rfsh_n), .enable_nmi_n(enable_nmi_n), + .page_configrom_active(page_configrom_active), // Para habilitar la ROM de ayuda y configuración // Interface con la ULA .vramaddr(vram_addr), @@ -301,19 +300,6 @@ module zxuno ( .sram_we_n(sram_we_n) ); -// ps2k el_teclado ( -// .clk(clkkbd), -// .ps2clk(clkps2), -// .ps2data(dataps2), -// .rows(kbdrow), -// .cols(kbdcol), -// .joy(kbd_joy), // Implementación joystick kempston en teclado numerico -// .scancode(scancode), // El scancode original desde el teclado -// .rst(rst_n), // esto son salidas, no entradas -// .nmi(nmi_n), // Señales de reset y NMI -// .mrst(mrst_n) // generadas por pulsaciones especiales del teclado -// ); - ps2_keyb el_teclado ( .clk(clk), .clkps2(clkps2), @@ -324,6 +310,7 @@ module zxuno ( .rst_out_n(rst_n), // esto son salidas, no entradas .nmi_out_n(nmi_n), // Señales de reset y NMI .mrst_out_n(mrst_n), // generadas por pulsaciones especiales del teclado + .user_toggles(user_toggles), // funciones de usuario //---------------------------- .zxuno_addr(zxuno_addr), .zxuno_regrd(zxuno_regrd), @@ -338,7 +325,6 @@ module zxuno ( .oe_n_kbstatus(oe_n_kbstatus) ); - joystick_protocols los_joysticks ( .clk(clk), //-- cpu interface @@ -381,6 +367,25 @@ module zxuno ( .oe_n(oe_n_scratch) ); + nmievents nmi_especial_de_antonio ( + .clk(clk), + .rst_n(rst_n & mrst_n & power_on_reset_n), + //------------------------------ + .zxuno_addr(zxuno_addr), + .zxuno_regrd(zxuno_regrd), + //------------------------------ + .userevents(user_toggles), + //------------------------------ + .a(cpuaddr), + .m1_n(m1_n), + .mreq_n(mreq_n), + .rd_n(rd_n), + .dout(nmievents_dout), + .oe_n(oe_n_nmievents), + .nmiout_n(nmispecial_n), + .page_configrom_active(page_configrom_active) + ); + /////////////////////////////////// // AY-3-8912 SOUND @@ -395,8 +400,8 @@ module zxuno ( assign bc1 = (cpuaddr[15] && cpuaddr[1:0]==2'b01 && cpuaddr[14] && !iorq_n)? 1'b1 : 1'b0; turbosound dos_ays ( - .clk7(clk7), - .clkay(clkay), + .clk(clk), + .clkay(clk3d5), .reset_n(rst_n & mrst_n & power_on_reset_n), .bdir(bdir), .bc1(bc1), @@ -407,34 +412,12 @@ module zxuno ( .audio_out_ay2(ay2_audio) ); -// YM2149 ay1 ( -// .I_DA(cpudout), -// .O_DA(ay_dout), -// .O_DA_OE_L(oe_n_ay), -// .I_A9_L(1'b0), -// .I_A8(1'b1), -// .I_BDIR(bdir), -// .I_BC2(1'b1), -// .I_BC1(bc1), -// .I_SEL_L(1'b0), -// .O_AUDIO(ay1_audio), -// .I_IOA(8'h00), -// .O_IOA(), -// .O_IOA_OE_L(), -// .I_IOB(8'h00), -// .O_IOB(), -// .O_IOB_OE_L(), -// .ENA(1'b1), -// .RESET_L(rst_n & mrst_n & power_on_reset_n), // cualquiera de los dos resets -// .CLK(clkay) -// ); - /////////////////////////////////// // SOUND MIXER /////////////////////////////////// // 8-bit mixer to generate different audio levels according to input sources mixer audio_mix( - .clkdac(clkdac), + .clkdac(clk), .reset(1'b0), .mic(mic), .spk(spk), diff --git a/cores/Spectrum/zxuno.xise b/cores/Spectrum/zxuno.xise index 4877c05..276fd36 100644 --- a/cores/Spectrum/zxuno.xise +++ b/cores/Spectrum/zxuno.xise @@ -29,10 +29,6 @@ - - - - @@ -127,13 +123,6 @@ - - - - - - - @@ -158,6 +147,14 @@ + + + + + + + +