Spectrum test17

This commit is contained in:
antoniovillena 2016-04-28 14:26:39 +02:00
parent 27832d8152
commit b8da4b137a
17 changed files with 720 additions and 304 deletions

View File

@ -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

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -29,7 +29,7 @@
00
00
00
00
01
00
00
00

Binary file not shown.

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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),

View File

@ -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)

View File

@ -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};

View File

@ -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),

View File

@ -29,10 +29,6 @@
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="mapa_teclado_es.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="T80.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
@ -127,13 +123,6 @@
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="ps2k_av.vhd" xil_pn:type="FILE_VHDL"/>
<file xil_pn:name="ps2k_mcleod.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="ps2k_uk.vhd" xil_pn:type="FILE_VHDL"/>
<file xil_pn:name="mapa_teclado_uk.vhd" xil_pn:type="FILE_VHDL"/>
<file xil_pn:name="ps2_keyb.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
@ -158,6 +147,14 @@
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="nmievents.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="cuatro_relojes.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
</files>
<properties>