1 |
8 |
gdevic |
//============================================================================
|
2 |
|
|
// Sinclair ZX Spectrum host board
|
3 |
|
|
//
|
4 |
|
|
// Copyright (C) 2014-2016 Goran Devic
|
5 |
|
|
//
|
6 |
|
|
// This program is free software; you can redistribute it and/or modify it
|
7 |
|
|
// under the terms of the GNU General Public License as published by the Free
|
8 |
|
|
// Software Foundation; either version 2 of the License, or (at your option)
|
9 |
|
|
// any later version.
|
10 |
|
|
//
|
11 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
12 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
13 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
14 |
|
|
// more details.
|
15 |
|
|
//
|
16 |
|
|
// You should have received a copy of the GNU General Public License along
|
17 |
|
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
18 |
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
19 |
|
|
//============================================================================
|
20 |
|
|
module zxspectrum_board
|
21 |
|
|
(
|
22 |
|
|
//-------- Clocks and reset -----------------
|
23 |
|
|
input wire CLOCK_27, // Input clock 27 MHz
|
24 |
|
|
input wire CLOCK_24, // Input clock 24 MHz
|
25 |
10 |
gdevic |
input wire KEY0, // RESET button; on DE1, keys are active low!
|
26 |
8 |
gdevic |
input wire KEY1, // NMI button
|
27 |
|
|
|
28 |
|
|
//-------- PS/2 Keyboard --------------------
|
29 |
|
|
input wire PS2_CLK,
|
30 |
|
|
input wire PS2_DAT,
|
31 |
|
|
|
32 |
|
|
//-------- Audio (Tape player) --------------
|
33 |
|
|
inout wire I2C_SCLK,
|
34 |
|
|
inout wire I2C_SDAT,
|
35 |
|
|
output wire AUD_XCK,
|
36 |
|
|
output wire AUD_ADCLRCK,
|
37 |
|
|
output wire AUD_DACLRCK,
|
38 |
|
|
output wire AUD_BCLK,
|
39 |
|
|
output wire AUD_DACDAT,
|
40 |
|
|
input wire AUD_ADCDAT,
|
41 |
|
|
|
42 |
|
|
//-------- VGA connector --------------------
|
43 |
|
|
output wire [3:0] VGA_R,
|
44 |
|
|
output wire [3:0] VGA_G,
|
45 |
|
|
output wire [3:0] VGA_B,
|
46 |
|
|
output reg VGA_HS,
|
47 |
|
|
output reg VGA_VS,
|
48 |
|
|
|
49 |
|
|
//-------- Flash memory interface -----------
|
50 |
|
|
output wire [21:0] FL_ADDR,
|
51 |
|
|
input wire [7:0] FL_DQ,
|
52 |
|
|
output wire FL_CE_N,
|
53 |
|
|
output wire FL_OE_N,
|
54 |
|
|
output wire FL_WE_N,
|
55 |
|
|
output wire FL_RST_N,
|
56 |
|
|
|
57 |
|
|
//-------- SRAM memory interface ------------
|
58 |
|
|
output wire [17:0] SRAM_ADDR,
|
59 |
|
|
inout reg [15:0] SRAM_DQ,
|
60 |
|
|
output wire SRAM_CE_N,
|
61 |
|
|
output wire SRAM_OE_N,
|
62 |
|
|
output wire SRAM_WE_N,
|
63 |
|
|
output wire SRAM_UB_N,
|
64 |
|
|
output wire SRAM_LB_N,
|
65 |
|
|
|
66 |
11 |
gdevic |
//-------- Atari joystick mapped as Kempston
|
67 |
|
|
input wire [4:0] kempston, // Input with weak pull-up
|
68 |
|
|
output wire kempston_gnd, // Helps mapping to DB9 cable
|
69 |
8 |
gdevic |
output wire [4:0] LEDG, // Show the joystick state
|
70 |
|
|
|
71 |
|
|
//-------- Misc and debug -------------------
|
72 |
|
|
input wire SW0, // ROM selection
|
73 |
|
|
input wire SW1, // Enable/disable interrupts
|
74 |
|
|
input wire SW2, // Turbo speed (3.5 MHz x 2 = 7.0 MHz)
|
75 |
|
|
output wire [2:0] LEDR, // Shows the switch selection
|
76 |
|
|
output wire [31:0] GPIO_1, // Exports CPU chip pins
|
77 |
|
|
output wire [2:0] LEDGTOP // Show additional information visually
|
78 |
|
|
);
|
79 |
|
|
`default_nettype none
|
80 |
|
|
|
81 |
|
|
wire reset;
|
82 |
|
|
wire locked;
|
83 |
|
|
assign reset = locked & KEY0;
|
84 |
|
|
|
85 |
|
|
// Export selected pins to the extension connector
|
86 |
|
|
assign GPIO_1[15:0] = A[15:0];
|
87 |
|
|
assign GPIO_1[23:16] = D[7:0];
|
88 |
|
|
assign GPIO_1[31:24] = {nM1,nMREQ,nIORQ,nRD,nWR,nRFSH,nHALT,nBUSACK};
|
89 |
11 |
gdevic |
assign kempston_gnd = 0;
|
90 |
8 |
gdevic |
|
91 |
|
|
// Top 3 green LEDs show various states:
|
92 |
|
|
assign LEDGTOP[2] = 0; // Reserved for future use
|
93 |
|
|
assign LEDGTOP[1] = beeper; // Show the beeper state
|
94 |
|
|
assign LEDGTOP[0] = pressed; // Show when a key is being pressed
|
95 |
|
|
|
96 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
97 |
|
|
// Internal buses and address map selection logic
|
98 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
99 |
|
|
wire [15:0] A; // Global address bus
|
100 |
|
|
wire [7:0] D; // CPU data bus
|
101 |
|
|
|
102 |
|
|
wire [7:0] ram_data; // Internal 16K RAM data
|
103 |
|
|
wire RamWE;
|
104 |
|
|
assign RamWE = A[15:14]==2'b01 && nIORQ==1 && nRD==1 && nWR==0;
|
105 |
|
|
|
106 |
|
|
wire ExtRamWE; // Extended (and external) 32K RAM
|
107 |
|
|
assign ExtRamWE = A[15]==1 && nIORQ==1 && nRD==1 && nWR==0;
|
108 |
|
|
assign SRAM_DQ[15:0] = ExtRamWE? {8'b0,D[7:0]} : {16{1'bz}};
|
109 |
|
|
|
110 |
|
|
wire [7:0] ula_data; // ULA
|
111 |
|
|
wire io_we;
|
112 |
|
|
assign io_we = nIORQ==0 && nRD==1 && nWR==0;
|
113 |
|
|
|
114 |
|
|
// Memory map:
|
115 |
|
|
// 0000 - 3FFF 16K ROM (mapped to the external Flash memory)
|
116 |
|
|
// 4000 - 7FFF 16K dual-port RAM
|
117 |
|
|
// 8000 - FFFF 32K RAM (mapped to the external SRAM memory)
|
118 |
|
|
always @(*) // always_comb
|
119 |
|
|
begin
|
120 |
|
|
case ({nIORQ,nRD,nWR})
|
121 |
|
|
// -------------------------------- Memory read --------------------------------
|
122 |
|
|
3'b101: begin
|
123 |
|
|
casez (A[15:14])
|
124 |
|
|
2'b00: D[7:0] = FL_DQ;
|
125 |
|
|
2'b01: D[7:0] = ram_data;
|
126 |
|
|
2'b1?: D[7:0] = SRAM_DQ[7:0];
|
127 |
|
|
endcase
|
128 |
|
|
end
|
129 |
|
|
// ---------------------------------- IO read ----------------------------------
|
130 |
|
|
3'b001: begin
|
131 |
|
|
// Normally data supplied by the ULA
|
132 |
|
|
D[7:0] = ula_data;
|
133 |
|
|
|
134 |
11 |
gdevic |
// Kempston joystick at the IO address 0x1F; active bits are high:
|
135 |
|
|
// FIRE UP DOWN LEFT RIGHT
|
136 |
8 |
gdevic |
if (A[7:0]==8'h1F) begin
|
137 |
11 |
gdevic |
D[7:0] = { 3'b0, !kempston[4],!kempston[0],!kempston[1],!kempston[2],!kempston[3] };
|
138 |
8 |
gdevic |
end
|
139 |
|
|
end
|
140 |
|
|
default:
|
141 |
|
|
D[7:0] = {8{1'bz}};
|
142 |
|
|
endcase
|
143 |
|
|
end
|
144 |
|
|
|
145 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
146 |
|
|
// 16K of the original ZX Spectrum ROM is in the flash at the address 0
|
147 |
|
|
// 16K of The GOSH WONDERFUL ZX Spectrum ROM is in the flash following it
|
148 |
|
|
// http://www.wearmouth.demon.co.uk/gw03/gw03info.htm
|
149 |
|
|
// SW0 selectes which ROM is going to be used by feeding the address bit 14
|
150 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
151 |
|
|
assign FL_ADDR[13:0] = A[13:0];
|
152 |
|
|
assign FL_ADDR[14] = SW0;
|
153 |
|
|
assign LEDR[0] = SW0; // Glow red when using alternate ROM
|
154 |
|
|
assign FL_ADDR[21:15] = 0;
|
155 |
|
|
assign FL_RST_N = KEY0;
|
156 |
|
|
assign FL_CE_N = 0;
|
157 |
|
|
assign FL_OE_N = 0;
|
158 |
|
|
assign FL_WE_N = 1;
|
159 |
|
|
|
160 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
161 |
|
|
// Instantiate 16K dual-port RAM
|
162 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
163 |
|
|
wire clk_vram;
|
164 |
|
|
// "A" port is the CPU side, "B" port is the VGA image generator in the ULA
|
165 |
|
|
ram16 ram16_(
|
166 |
|
|
.clock (clk_vram), // RAM connects to the higher, pixel clock rate
|
167 |
|
|
|
168 |
|
|
.address_a (A[13:0]), // Address in to the RAM from the CPU side
|
169 |
|
|
.data_a (D), // Data in to the RAM from the CPU side
|
170 |
|
|
.q_a (ram_data), // Data out from the RAM into the data bus selector
|
171 |
|
|
.wren_a (RamWE),
|
172 |
|
|
|
173 |
|
|
.address_b ({1'b0, vram_address}),
|
174 |
|
|
.data_b (8'b0),
|
175 |
|
|
.q_b (vram_data),
|
176 |
|
|
.wren_b ('0));
|
177 |
|
|
|
178 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
179 |
|
|
// 32K of ZX Spectrum extended RAM is using the external SRAM memory
|
180 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
181 |
|
|
assign SRAM_ADDR[14:0] = A[14:0];
|
182 |
|
|
assign SRAM_ADDR[17:15] = 0;
|
183 |
|
|
assign SRAM_CE_N = 0;
|
184 |
|
|
assign SRAM_OE_N = 0;
|
185 |
|
|
assign SRAM_WE_N = !ExtRamWE;
|
186 |
|
|
assign SRAM_UB_N = 1;
|
187 |
|
|
assign SRAM_LB_N = 0;
|
188 |
|
|
|
189 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
190 |
|
|
// Instantiate ULA
|
191 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
192 |
|
|
wire clk_cpu; // Global CPU clock of 3.5 MHz
|
193 |
|
|
assign LEDR[2] = SW2; // Glow red when in turbo mode (7.0 MHz)
|
194 |
|
|
wire [12:0] vram_address; // ULA video block requests a byte from the video RAM
|
195 |
|
|
wire [7:0] vram_data; // ULA video block reads a byte from the video RAM
|
196 |
|
|
wire vs_nintr; // Generates a vertical retrace interrupt
|
197 |
|
|
wire pressed; // Show that a key is being pressed
|
198 |
|
|
wire beeper; // Show the beeper state
|
199 |
|
|
|
200 |
|
|
ula ula_(
|
201 |
|
|
//-------- Clocks and reset -----------------
|
202 |
|
|
.CLOCK_27 (CLOCK_27), // Input clock 27 MHz
|
203 |
|
|
.CLOCK_24 (CLOCK_24), // Input clock 24 MHz
|
204 |
|
|
.turbo (SW2), // Turbo speed (3.5 MHz x 2 = 7.0 MHz)
|
205 |
|
|
.clk_vram (clk_vram),
|
206 |
10 |
gdevic |
.nreset (reset), // KEY0 is reset; on DE1, keys are active low!
|
207 |
8 |
gdevic |
.locked (locked), // PLL is locked signal
|
208 |
|
|
|
209 |
|
|
//-------- CPU control ----------------------
|
210 |
|
|
.clk_cpu (clk_cpu), // Generates CPU clock of 3.5 MHz
|
211 |
|
|
.vs_nintr (vs_nintr), // Generates a vertical retrace interrupt
|
212 |
|
|
|
213 |
|
|
//-------- Address and data buses -----------
|
214 |
|
|
.A (A), // Input address bus
|
215 |
|
|
.D (D), // Input data bus
|
216 |
|
|
.ula_data (ula_data), // Output data
|
217 |
|
|
.io_we (io_we), // Write enable to data register through IO
|
218 |
|
|
|
219 |
|
|
.vram_address (vram_address),// ULA video block requests a byte from the video RAM
|
220 |
|
|
.vram_data (vram_data), // ULA video block reads a byte from the video RAM
|
221 |
|
|
|
222 |
|
|
//-------- PS/2 Keyboard --------------------
|
223 |
|
|
.PS2_CLK (PS2_CLK),
|
224 |
|
|
.PS2_DAT (PS2_DAT),
|
225 |
|
|
.pressed (pressed),
|
226 |
|
|
|
227 |
|
|
//-------- Audio (Tape player) --------------
|
228 |
|
|
.I2C_SCLK (I2C_SCLK),
|
229 |
|
|
.I2C_SDAT (I2C_SDAT),
|
230 |
|
|
.AUD_XCK (AUD_XCK),
|
231 |
|
|
.AUD_ADCLRCK (AUD_ADCLRCK),
|
232 |
|
|
.AUD_DACLRCK (AUD_DACLRCK),
|
233 |
|
|
.AUD_BCLK (AUD_BCLK),
|
234 |
|
|
.AUD_DACDAT (AUD_DACDAT),
|
235 |
|
|
.AUD_ADCDAT (AUD_ADCDAT),
|
236 |
|
|
.beeper (beeper),
|
237 |
|
|
|
238 |
|
|
//-------- VGA connector --------------------
|
239 |
|
|
.VGA_R (VGA_R),
|
240 |
|
|
.VGA_G (VGA_G),
|
241 |
|
|
.VGA_B (VGA_B),
|
242 |
|
|
.VGA_HS (VGA_HS),
|
243 |
|
|
.VGA_VS (VGA_VS)
|
244 |
|
|
);
|
245 |
|
|
|
246 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
247 |
|
|
// Instantiate A-Z80 CPU
|
248 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
249 |
|
|
wire nM1;
|
250 |
|
|
wire nMREQ;
|
251 |
|
|
wire nIORQ;
|
252 |
|
|
wire nRD;
|
253 |
|
|
wire nWR;
|
254 |
|
|
wire nRFSH;
|
255 |
|
|
wire nHALT;
|
256 |
|
|
wire nBUSACK;
|
257 |
|
|
|
258 |
|
|
wire nWAIT = 1;
|
259 |
|
|
wire nINT = (SW1==0)? vs_nintr : '1;// SW1 disables interrupts and, hence, keyboard
|
260 |
|
|
assign LEDR[1] = SW1; // Glow red when interrupts are *disabled*
|
261 |
|
|
wire nNMI = KEY1; // Pressing KEY1 issues a NMI
|
262 |
|
|
wire nBUSRQ = 1;
|
263 |
|
|
|
264 |
|
|
z80_top_direct_n z80_(
|
265 |
|
|
.nM1 (nM1),
|
266 |
|
|
.nMREQ (nMREQ),
|
267 |
|
|
.nIORQ (nIORQ),
|
268 |
|
|
.nRD (nRD),
|
269 |
|
|
.nWR (nWR),
|
270 |
|
|
.nRFSH (nRFSH),
|
271 |
|
|
.nHALT (nHALT),
|
272 |
|
|
.nBUSACK (nBUSACK),
|
273 |
|
|
|
274 |
|
|
.nWAIT (nWAIT),
|
275 |
|
|
.nINT (nINT),
|
276 |
|
|
.nNMI (nNMI),
|
277 |
|
|
.nRESET (reset),
|
278 |
|
|
.nBUSRQ (nBUSRQ),
|
279 |
|
|
|
280 |
|
|
.CLK (clk_cpu),
|
281 |
|
|
.A (A),
|
282 |
|
|
.D (D)
|
283 |
|
|
);
|
284 |
|
|
|
285 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
286 |
|
|
// Lit green LEDs to show activity on a Kempston compatible joystick
|
287 |
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
288 |
11 |
gdevic |
assign LEDG[0] = !kempston[0]; // UP
|
289 |
|
|
assign LEDG[1] = !kempston[1]; // DOWN
|
290 |
|
|
assign LEDG[2] = !kempston[2]; // LEFT
|
291 |
|
|
assign LEDG[3] = !kempston[3]; // RIGHT
|
292 |
|
|
assign LEDG[4] = !kempston[4]; // FIRE
|
293 |
8 |
gdevic |
|
294 |
|
|
endmodule
|