Rev 674 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
668 | lvd | 1 | // ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014 |
200 | lvd | 2 | // |
3 | // most of pentevo ports are here |
||
4 | |||
668 | lvd | 5 | /* |
6 | This file is part of ZX-Evo Base Configuration firmware. |
||
7 | |||
8 | ZX-Evo Base Configuration firmware is free software: |
||
9 | you can redistribute it and/or modify it under the terms of |
||
10 | the GNU General Public License as published by |
||
11 | the Free Software Foundation, either version 3 of the License, or |
||
12 | (at your option) any later version. |
||
13 | |||
14 | ZX-Evo Base Configuration firmware is distributed in the hope that |
||
15 | it will be useful, but WITHOUT ANY WARRANTY; without even |
||
16 | the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
17 | See the GNU General Public License for more details. |
||
18 | |||
19 | You should have received a copy of the GNU General Public License |
||
20 | along with ZX-Evo Base Configuration firmware. |
||
21 | If not, see <http://www.gnu.org/licenses/>. |
||
22 | */ |
||
23 | |||
30 | lvd | 24 | `include "../include/tune.v" |
25 | |||
4 | lvd | 26 | module zports( |
27 | |||
200 | lvd | 28 | input wire zclk, // z80 clock |
29 | input wire fclk, // global FPGA clock |
||
30 | input wire rst_n, // system reset |
||
4 | lvd | 31 | |
200 | lvd | 32 | input wire zpos, |
33 | input wire zneg, |
||
4 | lvd | 34 | |
35 | |||
200 | lvd | 36 | input wire [ 7:0] din, |
37 | output reg [ 7:0] dout, |
||
38 | output wire dataout, |
||
39 | input wire [15:0] a, |
||
4 | lvd | 40 | |
200 | lvd | 41 | input wire iorq_n, |
42 | input wire mreq_n, |
||
43 | input wire m1_n, |
||
44 | input wire rd_n, |
||
45 | input wire wr_n, |
||
4 | lvd | 46 | |
200 | lvd | 47 | output reg porthit, // when internal port hit occurs, this is 1, else 0; used for iorq1_n iorq2_n on zxbus |
467 | lvd | 48 | output reg external_port, // asserts for AY and VG93 accesses |
4 | lvd | 49 | |
230 | lvd | 50 | output wire [15:0] ideout, |
200 | lvd | 51 | input wire [15:0] idein, |
52 | output wire idedataout, // IDE must IN data from IDE device when idedataout=0, else it OUTs |
||
53 | output wire [ 2:0] ide_a, |
||
54 | output wire ide_cs0_n, |
||
55 | output wire ide_cs1_n, |
||
56 | output wire ide_rd_n, |
||
57 | output wire ide_wr_n, |
||
4 | lvd | 58 | |
59 | |||
200 | lvd | 60 | input wire [ 4:0] keys_in, // keys (port FE) |
61 | input wire [ 7:0] mus_in, // mouse (xxDF) |
||
62 | input wire [ 4:0] kj_in, |
||
4 | lvd | 63 | |
287 | ddp | 64 | output reg [ 3:0] border, |
4 | lvd | 65 | |
284 | lvd | 66 | |
200 | lvd | 67 | input wire dos, |
4 | lvd | 68 | |
69 | |||
200 | lvd | 70 | output wire ay_bdir, |
71 | output wire ay_bc1, |
||
4 | lvd | 72 | |
200 | lvd | 73 | output wire [ 7:0] p7ffd, |
74 | output wire [ 7:0] peff7, |
||
4 | lvd | 75 | |
213 | lvd | 76 | input wire tape_read, |
77 | |||
200 | lvd | 78 | output wire vg_cs_n, |
79 | input wire vg_intrq, |
||
80 | input wire vg_drq, // from vg93 module - drq + irq read |
||
81 | output wire vg_wrFF, // write strobe of #FF port |
||
88 | lvd | 82 | |
543 | lvd | 83 | output wire sd_cs_n_val, |
84 | output wire sd_cs_n_stb, |
||
200 | lvd | 85 | output wire sd_start, |
86 | output wire [ 7:0] sd_datain, |
||
87 | input wire [ 7:0] sd_dataout, |
||
88 | |||
228 | lvd | 89 | // WAIT-ports related |
90 | // |
||
88 | lvd | 91 | output reg [ 7:0] gluclock_addr, |
228 | lvd | 92 | // |
93 | output reg [ 2:0] comport_addr, |
||
94 | // |
||
88 | lvd | 95 | output wire wait_start_gluclock, // begin wait from some ports |
228 | lvd | 96 | output wire wait_start_comport, // |
97 | // |
||
88 | lvd | 98 | output reg wait_rnw, // whether it was read(=1) or write(=0) |
99 | output reg [ 7:0] wait_write, |
||
200 | lvd | 100 | input wire [ 7:0] wait_read, |
101 | |||
102 | |||
103 | output wire atmF7_wr_fclk, // used in atm_pager.v |
||
104 | |||
105 | |||
106 | output reg [ 2:0] atm_scr_mode, // RG0..RG2 in docs |
||
107 | output reg atm_turbo, // turbo mode ON |
||
108 | output reg atm_pen, // pager_off in atm_pager.v, NOT inverted!!! |
||
109 | output reg atm_cpm_n, // permanent dos on |
||
110 | output reg atm_pen2, // PEN2 - fucking palette mode, NOT inverted!!! |
||
111 | |||
112 | output wire romrw_en, // from port BF |
||
113 | |||
114 | |||
115 | output wire pent1m_ram0_0, // d3.eff7 |
||
116 | output wire pent1m_1m_on, // d2.eff7 |
||
117 | output wire [ 5:0] pent1m_page, // full 1 meg page number |
||
340 | lvd | 118 | output wire pent1m_ROM, // d4.7ffd |
200 | lvd | 119 | |
340 | lvd | 120 | |
360 | lvd | 121 | output wire atm_palwr, // palette write strobe |
122 | output wire [ 5:0] atm_paldata, // palette write data |
||
340 | lvd | 123 | |
360 | lvd | 124 | output wire covox_wr, |
394 | tsl | 125 | output wire beeper_wr, |
395 | lvd | 126 | |
425 | lvd | 127 | output wire clr_nmi, |
395 | lvd | 128 | |
425 | lvd | 129 | output wire fnt_wr, // write to font_ram enabled |
130 | |||
131 | // inputs from atm_pagers, to read back its config |
||
132 | input wire [63:0] pages, |
||
133 | input wire [ 7:0] ramnroms, |
||
134 | input wire [ 7:0] dos7ffds, |
||
674 | lvd | 135 | input wire [ 7:0] wrdisables, |
425 | lvd | 136 | |
476 | lvd | 137 | input wire [ 5:0] palcolor, |
543 | lvd | 138 | input wire [ 7:0] fontrom_readback, |
476 | lvd | 139 | |
668 | lvd | 140 | // ulaplus |
141 | output reg up_ena, |
||
142 | output reg [ 5:0] up_paladdr, |
||
143 | output wire [ 7:0] up_paldata, |
||
144 | output wire up_palwr, |
||
476 | lvd | 145 | |
668 | lvd | 146 | |
147 | |||
476 | lvd | 148 | // NMI generation |
576 | lvd | 149 | output reg set_nmi, |
150 | |||
151 | // break enable & address |
||
152 | output reg brk_ena, |
||
153 | output reg [15:0] brk_addr |
||
4 | lvd | 154 | ); |
155 | |||
156 | |||
580 | lvd | 157 | `define IS_NIDE_REGS(x) ( (x[2:0]==3'b000) && (x[3]!=x[4]) ) |
158 | `define IS_NIDE_HIGH(x) ( x[7:0]==8'h11 ) |
||
159 | `define IS_PORT_NIDE(x) ( `IS_NIDE_REGS(x) || `IS_NIDE_HIGH(x) ) |
||
160 | `define NIDE_REGS 8'h10,8'h30,8'h50,8'h70,8'h90,8'hB0,8'hD0,8'hF0, \ |
||
161 | 8'h08,8'h28,8'h48,8'h68,8'h88,8'hA8,8'hC8,8'hE8 |
||
4 | lvd | 162 | |
163 | localparam PORTFE = 8'hFE; |
||
287 | ddp | 164 | localparam PORTF6 = 8'hF6; |
4 | lvd | 165 | localparam PORTF7 = 8'hF7; |
166 | |||
167 | localparam NIDE10 = 8'h10; |
||
168 | localparam NIDE11 = 8'h11; |
||
169 | localparam NIDE30 = 8'h30; |
||
170 | localparam NIDE50 = 8'h50; |
||
171 | localparam NIDE70 = 8'h70; |
||
172 | localparam NIDE90 = 8'h90; |
||
173 | localparam NIDEB0 = 8'hB0; |
||
174 | localparam NIDED0 = 8'hD0; |
||
175 | localparam NIDEF0 = 8'hF0; |
||
176 | localparam NIDEC8 = 8'hC8; |
||
177 | |||
178 | localparam PORTFD = 8'hFD; |
||
179 | |||
180 | localparam VGCOM = 8'h1F; |
||
181 | localparam VGTRK = 8'h3F; |
||
182 | localparam VGSEC = 8'h5F; |
||
183 | localparam VGDAT = 8'h7F; |
||
184 | localparam VGSYS = 8'hFF; |
||
185 | |||
476 | lvd | 186 | localparam SAVPORT1 = 8'h2F; |
187 | localparam SAVPORT2 = 8'h4F; |
||
188 | localparam SAVPORT3 = 8'h6F; |
||
189 | localparam SAVPORT4 = 8'h8F; |
||
190 | |||
4 | lvd | 191 | localparam KJOY = 8'h1F; |
192 | localparam KMOUSE = 8'hDF; |
||
193 | |||
194 | localparam SDCFG = 8'h77; |
||
195 | localparam SDDAT = 8'h57; |
||
196 | |||
200 | lvd | 197 | localparam ATMF7 = 8'hF7; |
198 | localparam ATM77 = 8'h77; |
||
4 | lvd | 199 | |
425 | lvd | 200 | localparam ZXEVBE = 8'hBE; // xxBE config-read and nmi-end port |
200 | lvd | 201 | localparam ZXEVBF = 8'hBF; // xxBF config port |
582 | lvd | 202 | localparam ZXEVBRK = 8'hBD; // xxBD breakpoint address port |
200 | lvd | 203 | |
228 | lvd | 204 | localparam COMPORT = 8'hEF; // F8EF..FFEF - rs232 ports |
205 | |||
206 | |||
360 | lvd | 207 | localparam COVOX = 8'hFB; |
208 | |||
668 | lvd | 209 | |
210 | localparam ULAPLUS = 8'h3B; |
||
360 | lvd | 211 | |
212 | |||
213 | |||
4 | lvd | 214 | reg port_wr; |
215 | reg port_rd; |
||
216 | |||
200 | lvd | 217 | reg iowr_reg; |
218 | reg iord_reg; |
||
4 | lvd | 219 | |
200 | lvd | 220 | |
221 | reg port_wr_fclk, |
||
395 | lvd | 222 | port_rd_fclk, |
223 | mem_wr_fclk; |
||
200 | lvd | 224 | |
225 | reg [1:0] iowr_reg_fclk, |
||
226 | iord_reg_fclk; |
||
227 | |||
395 | lvd | 228 | reg [1:0] memwr_reg_fclk; |
200 | lvd | 229 | |
395 | lvd | 230 | |
4 | lvd | 231 | wire [7:0] loa; |
232 | |||
233 | |||
230 | lvd | 234 | |
235 | |||
4 | lvd | 236 | wire ideout_hi_wr; |
237 | wire idein_lo_rd; |
||
230 | lvd | 238 | reg [7:0] idehiin; // IDE high part read register: low part is read directly to Z80 bus, |
239 | // while high part is remembered here |
||
4 | lvd | 240 | reg ide_ports; // ide ports selected |
241 | |||
230 | lvd | 242 | reg ide_rd_trig; // nemo-divide read trigger |
243 | reg ide_rd_latch; // to save state of trigger during read cycle |
||
244 | |||
245 | reg ide_wrlo_trig, ide_wrhi_trig; // nemo-divide write triggers |
||
246 | reg ide_wrlo_latch, ide_wrhi_latch; // save state during write cycles |
||
247 | |||
248 | |||
249 | |||
250 | reg [15:0] idewrreg; // write register, either low or high part is pre-written here, |
||
251 | // while other part is out directly from Z80 bus |
||
252 | |||
253 | wire [ 7:0] iderdeven; // to control read data from "even" ide ports (all except #11) |
||
254 | wire [ 7:0] iderdodd; // read data from "odd" port (#11) |
||
255 | |||
256 | |||
257 | |||
4 | lvd | 258 | reg pre_bc1,pre_bdir; |
259 | |||
88 | lvd | 260 | wire gluclock_on; |
4 | lvd | 261 | |
262 | |||
88 | lvd | 263 | |
200 | lvd | 264 | reg shadow_en_reg; //bit0.xxBF |
265 | reg romrw_en_reg; //bit1.xxBF |
||
394 | tsl | 266 | reg fntw_en_reg; //bit2.xxBF |
200 | lvd | 267 | |
268 | wire shadow; |
||
269 | |||
270 | |||
271 | |||
425 | lvd | 272 | reg [7:0] portbemux; |
200 | lvd | 273 | |
274 | |||
425 | lvd | 275 | |
476 | lvd | 276 | reg [7:0] savport [3:0]; |
669 | lvd | 277 | reg [5:0] vgFF; |
425 | lvd | 278 | |
279 | |||
684 | lvd | 280 | reg [7:0] up_lastwritten; |
476 | lvd | 281 | |
282 | |||
200 | lvd | 283 | assign shadow = dos || shadow_en_reg; |
284 | |||
285 | |||
286 | |||
287 | |||
288 | |||
289 | |||
4 | lvd | 290 | assign loa=a[7:0]; |
291 | |||
292 | always @* |
||
293 | begin |
||
287 | ddp | 294 | if( (loa==PORTFE) || (loa==PORTF6) || |
684 | lvd | 295 | (loa==PORTFD) || (loa==8'hFC) || |
4 | lvd | 296 | |
580 | lvd | 297 | `IS_PORT_NIDE(loa) || |
298 | // (loa==NIDE10) || (loa==NIDE11) || (loa==NIDE30) || (loa==NIDE50) || (loa==NIDE70) || |
||
299 | // (loa==NIDE90) || (loa==NIDEB0) || (loa==NIDED0) || (loa==NIDEF0) || (loa==NIDEC8) || |
||
4 | lvd | 300 | |
200 | lvd | 301 | (loa==KMOUSE) || |
4 | lvd | 302 | |
200 | lvd | 303 | ( (loa==VGCOM)&&shadow ) || ( (loa==VGTRK)&&shadow ) || ( (loa==VGSEC)&&shadow ) || ( (loa==VGDAT)&&shadow ) || |
304 | ( (loa==VGSYS)&&shadow ) || ( (loa==KJOY)&&(!shadow) ) || |
||
305 | |||
476 | lvd | 306 | ( (loa==SAVPORT1)&&shadow ) || ( (loa==SAVPORT2)&&shadow ) || |
307 | ( (loa==SAVPORT3)&&shadow ) || ( (loa==SAVPORT4)&&shadow ) || |
||
308 | |||
309 | |||
228 | lvd | 310 | ( (loa==PORTF7)&&(!shadow) ) || ( (loa==SDCFG)&&(!shadow) ) || ( (loa==SDDAT) ) || |
200 | lvd | 311 | |
312 | ( (loa==ATMF7)&&shadow ) || ( (loa==ATM77)&&shadow ) || |
||
313 | |||
668 | lvd | 314 | ( loa==ZXEVBF ) || ( loa==ZXEVBE) || ( loa==ZXEVBRK) || ( loa==COMPORT ) || |
315 | |||
316 | ( loa==ULAPLUS) |
||
200 | lvd | 317 | ) |
318 | |||
319 | |||
320 | |||
4 | lvd | 321 | porthit = 1'b1; |
322 | else |
||
323 | porthit = 1'b0; |
||
324 | end |
||
325 | |||
326 | always @* |
||
327 | begin |
||
543 | lvd | 328 | if( ((loa==PORTFD) && a[15]) || // 0xBFFD/0xFFFD ports |
200 | lvd | 329 | (( (loa==VGCOM)&&shadow ) || ( (loa==VGTRK)&&shadow ) || ( (loa==VGSEC)&&shadow ) || ( (loa==VGDAT)&&shadow )) ) // vg93 ports |
4 | lvd | 330 | external_port = 1'b1; |
331 | else |
||
332 | external_port = 1'b0; |
||
333 | end |
||
334 | |||
335 | assign dataout = porthit & (~iorq_n) & (~rd_n) & (~external_port); |
||
336 | |||
337 | |||
338 | |||
200 | lvd | 339 | // this is zclk-synchronous strobes |
340 | always @(posedge zclk) |
||
4 | lvd | 341 | begin |
342 | iowr_reg <= ~(iorq_n | wr_n); |
||
343 | iord_reg <= ~(iorq_n | rd_n); |
||
344 | |||
345 | if( (!iowr_reg) && (!iorq_n) && (!wr_n) ) |
||
346 | port_wr <= 1'b1; |
||
347 | else |
||
348 | port_wr <= 1'b0; |
||
349 | |||
350 | |||
351 | if( (!iord_reg) && (!iorq_n) && (!rd_n) ) |
||
352 | port_rd <= 1'b1; |
||
353 | else |
||
354 | port_rd <= 1'b0; |
||
355 | end |
||
356 | |||
357 | |||
200 | lvd | 358 | |
359 | |||
360 | // fclk-synchronous stobes |
||
361 | // |
||
362 | always @(posedge fclk) if( zpos ) |
||
363 | begin |
||
364 | iowr_reg_fclk[0] <= ~(iorq_n | wr_n); |
||
365 | iord_reg_fclk[0] <= ~(iorq_n | rd_n); |
||
366 | end |
||
367 | |||
368 | always @(posedge fclk) |
||
369 | begin |
||
370 | iowr_reg_fclk[1] <= iowr_reg_fclk[0]; |
||
371 | iord_reg_fclk[1] <= iord_reg_fclk[0]; |
||
372 | end |
||
373 | |||
374 | always @(posedge fclk) |
||
375 | begin |
||
376 | port_wr_fclk <= iowr_reg_fclk[0] && (!iowr_reg_fclk[1]); |
||
377 | port_rd_fclk <= iord_reg_fclk[0] && (!iord_reg_fclk[1]); |
||
378 | end |
||
379 | |||
395 | lvd | 380 | always @(posedge fclk) |
381 | memwr_reg_fclk[1:0] <= { memwr_reg_fclk[0], ~(mreq_n | wr_n) }; |
||
200 | lvd | 382 | |
395 | lvd | 383 | always @(posedge fclk) |
384 | mem_wr_fclk <= memwr_reg_fclk[0] && (!memwr_reg_fclk[1]); |
||
200 | lvd | 385 | |
386 | |||
387 | |||
4 | lvd | 388 | // dout data |
389 | always @* |
||
390 | begin |
||
391 | case( loa ) |
||
392 | PORTFE: |
||
213 | lvd | 393 | dout = { 1'b1, tape_read, 1'b0, keys_in }; |
287 | ddp | 394 | PORTF6: |
395 | dout = { 1'b1, tape_read, 1'b0, keys_in }; |
||
4 | lvd | 396 | |
397 | |||
580 | lvd | 398 | `NIDE_REGS: |
230 | lvd | 399 | dout = iderdeven; |
4 | lvd | 400 | NIDE11: |
230 | lvd | 401 | dout = iderdodd; |
4 | lvd | 402 | |
403 | |||
404 | //PORTFD: |
||
405 | |||
406 | VGSYS: |
||
669 | lvd | 407 | dout = { vg_intrq, vg_drq, vgFF }; // 6'b111111 }; |
4 | lvd | 408 | |
476 | lvd | 409 | SAVPORT1, SAVPORT2, SAVPORT3, SAVPORT4: |
410 | dout = savport[ loa[6:5] ]; |
||
411 | |||
412 | |||
4 | lvd | 413 | KJOY: |
110 | lvd | 414 | dout = {3'b000, kj_in}; |
4 | lvd | 415 | KMOUSE: |
67 | lvd | 416 | dout = mus_in; |
4 | lvd | 417 | |
418 | SDCFG: |
||
228 | lvd | 419 | dout = 8'h00; // always SD inserted, SD is in R/W mode |
4 | lvd | 420 | SDDAT: |
421 | dout = sd_dataout; |
||
422 | |||
423 | |||
88 | lvd | 424 | PORTF7: begin |
270 | lvd | 425 | if( !a[14] && (a[8]^shadow) && gluclock_on ) // $BFF7 - data i/o |
88 | lvd | 426 | dout = wait_read; |
427 | else // any other $xxF7 port |
||
428 | dout = 8'hFF; |
||
429 | end |
||
430 | |||
228 | lvd | 431 | COMPORT: begin |
432 | dout = wait_read; // $F8EF..$FFEF |
||
433 | end |
||
88 | lvd | 434 | |
425 | lvd | 435 | ZXEVBF: begin |
576 | lvd | 436 | dout = { 3'b000, brk_ena, set_nmi, fntw_en_reg, romrw_en_reg, shadow_en_reg }; |
425 | lvd | 437 | end |
228 | lvd | 438 | |
425 | lvd | 439 | ZXEVBE: begin |
440 | dout = portbemux; |
||
441 | end |
||
228 | lvd | 442 | |
669 | lvd | 443 | ULAPLUS: begin |
444 | dout = up_lastwritten; |
||
445 | end |
||
425 | lvd | 446 | |
669 | lvd | 447 | |
4 | lvd | 448 | default: |
449 | dout = 8'hFF; |
||
450 | endcase |
||
451 | end |
||
452 | |||
453 | |||
454 | |||
684 | lvd | 455 | assign portfd_wr = ( (loa==PORTFD || loa==8'hFC) && port_wr); |
4 | lvd | 456 | |
270 | lvd | 457 | // F7 ports (like EFF7) are accessible in shadow mode but at addresses like EEF7, DEF7, BEF7 so that |
458 | // there are no conflicts in shadow mode with ATM xFF7 and x7F7 ports |
||
459 | assign portf7_wr = ( (loa==PORTF7) && (a[8]==1'b1) && port_wr && (!shadow) ) || |
||
460 | ( (loa==PORTF7) && (a[8]==1'b0) && port_wr && shadow ) ; |
||
461 | |||
462 | assign portf7_rd = ( (loa==PORTF7) && (a[8]==1'b1) && port_rd && (!shadow) ) || |
||
463 | ( (loa==PORTF7) && (a[8]==1'b0) && port_rd && shadow ) ; |
||
464 | |||
200 | lvd | 465 | assign vg_wrFF = ( ( (loa==VGSYS)&&shadow ) && port_wr); |
669 | lvd | 466 | always @(posedge zclk) if( vg_wrFF ) |
467 | vgFF <= din[5:0]; |
||
4 | lvd | 468 | |
228 | lvd | 469 | assign comport_wr = ( (loa==COMPORT) && port_wr); |
470 | assign comport_rd = ( (loa==COMPORT) && port_rd); |
||
4 | lvd | 471 | |
576 | lvd | 472 | |
473 | assign zxevbrk_wr_fclk = ( (loa==ZXEVBRK) && port_wr_fclk); |
||
228 | lvd | 474 | |
475 | |||
576 | lvd | 476 | |
477 | |||
478 | |||
479 | // break address write |
||
480 | always @(posedge fclk) |
||
481 | if( zxevbrk_wr_fclk) |
||
482 | begin |
||
483 | if( !a[8] ) |
||
484 | brk_addr[ 7:0] <= din; |
||
485 | else // a[8]==1 |
||
486 | brk_addr[15:8] <= din; |
||
487 | end |
||
488 | |||
489 | |||
490 | |||
491 | |||
492 | |||
360 | lvd | 493 | //border port FE |
494 | wire portwe_wr_fclk; |
||
4 | lvd | 495 | |
684 | lvd | 496 | assign portfe_wr_fclk = (((loa==PORTFE) || (loa==PORTF6) || (loa==8'hFC)) && port_wr_fclk); |
4 | lvd | 497 | |
360 | lvd | 498 | always @(posedge fclk) |
499 | if( portfe_wr_fclk ) |
||
500 | border <= { ~a[3], din[2:0] }; |
||
230 | lvd | 501 | |
502 | |||
503 | |||
232 | lvd | 504 | |
360 | lvd | 505 | |
506 | |||
4 | lvd | 507 | // IDE ports |
508 | |||
234 | lvd | 509 | // IDE physical ports (that go to IDE device) |
510 | always @(loa) |
||
580 | lvd | 511 | if( `IS_NIDE_REGS(loa) ) |
512 | ide_ports = 1'b1; |
||
513 | else |
||
514 | ide_ports = 1'b0; |
||
228 | lvd | 515 | |
234 | lvd | 516 | |
517 | assign idein_lo_rd = port_rd && (loa==NIDE10) && (!ide_rd_trig); |
||
518 | |||
230 | lvd | 519 | // control read & write triggers, which allow nemo-divide mod to work. |
234 | lvd | 520 | // |
521 | // read trigger: |
||
230 | lvd | 522 | always @(posedge zclk) |
234 | lvd | 523 | begin |
524 | if( (loa==NIDE10) && port_rd && !ide_rd_trig ) |
||
525 | ide_rd_trig <= 1'b1; |
||
526 | else if( ( ide_ports || (loa==NIDE11) ) && ( port_rd || port_wr ) ) |
||
527 | ide_rd_trig <= 1'b0; |
||
528 | end |
||
235 | lvd | 529 | // |
530 | // two triggers for write sequence... |
||
234 | lvd | 531 | always @(posedge zclk) |
235 | lvd | 532 | if( ( ide_ports || (loa==NIDE11) ) && ( port_rd || port_wr ) ) |
230 | lvd | 533 | begin |
235 | lvd | 534 | if( (loa==NIDE11) && port_wr ) |
230 | lvd | 535 | ide_wrhi_trig <= 1'b1; |
235 | lvd | 536 | else |
537 | ide_wrhi_trig <= 1'b0; |
||
230 | lvd | 538 | // |
235 | lvd | 539 | if( (loa==NIDE10) && port_wr && !ide_wrhi_trig && !ide_wrlo_trig ) |
540 | ide_wrlo_trig <= 1'b1; |
||
541 | else |
||
230 | lvd | 542 | ide_wrlo_trig <= 1'b0; |
543 | end |
||
544 | |||
545 | // normal read: #10(low), #11(high) |
||
546 | // divide read: #10(low), #10(high) |
||
547 | // |
||
548 | // normal write: #11(high), #10(low) |
||
549 | // divide write: #10(low), #10(high) |
||
550 | |||
232 | lvd | 551 | |
200 | lvd | 552 | always @(posedge zclk) |
4 | lvd | 553 | begin |
230 | lvd | 554 | if( port_wr && (loa==NIDE11) ) |
555 | idewrreg[15:8] <= din; |
||
4 | lvd | 556 | |
243 | lvd | 557 | if( port_wr && (loa==NIDE10) && !ide_wrlo_trig ) |
230 | lvd | 558 | idewrreg[ 7:0] <= din; |
4 | lvd | 559 | end |
560 | |||
230 | lvd | 561 | |
562 | |||
563 | |||
564 | always @(posedge zclk) |
||
565 | if( idein_lo_rd ) |
||
566 | idehiin <= idein[15:8]; |
||
567 | |||
4 | lvd | 568 | |
569 | assign ide_a = a[7:5]; |
||
230 | lvd | 570 | |
571 | |||
572 | // This is unknown shit... Probably need more testing with old WD |
||
573 | // drives WITHOUT this commented fix. |
||
232 | lvd | 574 | // |
4 | lvd | 575 | // trying to fix old WD drives... |
230 | lvd | 576 | //assign ide_cs0_n = iorq_n | (rd_n&wr_n) | (~ide_ports) | (~(loa!=NIDEC8)); |
577 | //assign ide_cs1_n = iorq_n | (rd_n&wr_n) | (~ide_ports) | (~(loa==NIDEC8)); |
||
578 | // fix ends... |
||
579 | |||
580 | |||
4 | lvd | 581 | assign ide_cs0_n = (~ide_ports) | (~(loa!=NIDEC8)); |
582 | assign ide_cs1_n = (~ide_ports) | (~(loa==NIDEC8)); |
||
230 | lvd | 583 | |
584 | |||
585 | // generate read cycles for IDE as usual, except for reading #10 |
||
586 | // instead of #11 for high byte (nemo-divide). I use additional latch |
||
587 | // since 'ide_rd_trig' clears during second Z80 IO read cycle to #10 |
||
588 | always @* if( rd_n ) ide_rd_latch <= ide_rd_trig; |
||
589 | // |
||
232 | lvd | 590 | assign ide_rd_n = iorq_n | rd_n | (~ide_ports) | (ide_rd_latch && (loa==NIDE10)); |
230 | lvd | 591 | |
592 | always @* if( wr_n ) ide_wrlo_latch <= ide_wrlo_trig; // same for write triggers |
||
593 | always @* if( wr_n ) ide_wrhi_latch <= ide_wrhi_trig; // |
||
594 | // |
||
595 | assign ide_wr_n = iorq_n | wr_n | (~ide_ports) | ( (loa==NIDE10) && !ide_wrlo_latch && !ide_wrhi_latch ); |
||
596 | // do NOT generate IDE write, if neither of ide_wrhi|lo latches |
||
597 | // set and writing to NIDE10 |
||
598 | |||
599 | |||
600 | |||
526 | lvd | 601 | // assign idedataout = ide_rd_n; |
602 | assign idedataout = ~ide_wr_n; // shit-fix in try to fix IDE errors |
||
603 | // warning: this fix kinda blind-picking, good way is to |
||
604 | // have idedataout lead wr or rd strobes. also good point to disable data ringing |
||
605 | // on ide data bus while not accessing IDE |
||
4 | lvd | 606 | |
607 | |||
230 | lvd | 608 | // data read by Z80 from IDE |
609 | // |
||
610 | assign iderdodd[ 7:0] = idehiin[ 7:0]; |
||
611 | // |
||
612 | assign iderdeven[ 7:0] = (ide_rd_latch && (loa==NIDE10)) ? idehiin[ 7:0] : idein[ 7:0]; |
||
613 | |||
614 | // data written to IDE from Z80 |
||
615 | // |
||
233 | lvd | 616 | assign ideout[15:8] = ide_wrhi_latch ? idewrreg[15:8] : din[ 7:0]; |
617 | assign ideout[ 7:0] = ide_wrlo_latch ? idewrreg[ 7:0] : din[ 7:0]; |
||
230 | lvd | 618 | |
619 | |||
620 | |||
621 | |||
622 | |||
623 | |||
624 | |||
4 | lvd | 625 | // AY control |
626 | always @* |
||
627 | begin |
||
628 | pre_bc1 = 1'b0; |
||
629 | pre_bdir = 1'b0; |
||
630 | |||
631 | if( loa==PORTFD ) |
||
632 | begin |
||
633 | if( a[15:14]==2'b11 ) |
||
634 | begin |
||
635 | pre_bc1=1'b1; |
||
636 | pre_bdir=1'b1; |
||
637 | end |
||
638 | else if( a[15:14]==2'b10 ) |
||
639 | begin |
||
640 | pre_bc1=1'b0; |
||
641 | pre_bdir=1'b1; |
||
642 | end |
||
643 | end |
||
644 | end |
||
645 | |||
646 | assign ay_bc1 = pre_bc1 & (~iorq_n) & ((~rd_n)|(~wr_n)); |
||
647 | assign ay_bdir = pre_bdir & (~iorq_n) & (~wr_n); |
||
648 | |||
649 | |||
650 | |||
651 | // 7FFD port |
||
652 | reg [7:0] p7ffd_int,peff7_int; |
||
653 | reg p7ffd_rom_int; |
||
654 | wire block7ffd; |
||
655 | wire block1m; |
||
656 | |||
200 | lvd | 657 | always @(posedge zclk, negedge rst_n) |
4 | lvd | 658 | begin |
659 | if( !rst_n ) |
||
660 | p7ffd_int <= 7'h00; |
||
661 | else if( (a[15]==1'b0) && portfd_wr && (!block7ffd) ) |
||
662 | p7ffd_int <= din; // 2..0 - page, 3 - screen, 4 - rom, 5 - block48k, 6..7 - |
||
663 | end |
||
664 | |||
543 | lvd | 665 | always @(posedge zclk, negedge rst_n) |
666 | if( !rst_n ) |
||
667 | p7ffd_rom_int <= 1'b0; |
||
668 | else |
||
669 | if( (a[15]==1'b0) && portfd_wr && (!block7ffd) ) |
||
4 | lvd | 670 | p7ffd_rom_int <= din[4]; |
671 | |||
543 | lvd | 672 | |
4 | lvd | 673 | assign block7ffd=p7ffd_int[5] & block1m; |
674 | |||
200 | lvd | 675 | |
4 | lvd | 676 | // EFF7 port |
200 | lvd | 677 | always @(posedge zclk, negedge rst_n) |
4 | lvd | 678 | begin |
679 | if( !rst_n ) |
||
680 | peff7_int <= 8'h00; |
||
284 | lvd | 681 | else if( !a[12] && portf7_wr && (!shadow) ) // EEF7 in shadow mode is abandoned! |
4 | lvd | 682 | peff7_int <= din; // 4 - turbooff, 0 - p16c on, 2 - block1meg |
683 | end |
||
684 | assign block1m = peff7_int[2]; |
||
685 | |||
39 | ddp | 686 | assign p7ffd = { (block1m ? 3'b0 : p7ffd_int[7:5]),p7ffd_rom_int,p7ffd_int[3:0]}; |
4 | lvd | 687 | |
88 | lvd | 688 | assign peff7 = block1m ? { peff7_int[7], 1'b0, peff7_int[5], peff7_int[4], 3'b000, peff7_int[0] } : peff7_int; |
4 | lvd | 689 | |
690 | |||
200 | lvd | 691 | assign pent1m_ROM = p7ffd_int[4]; |
692 | assign pent1m_page[5:0] = { p7ffd_int[7:5], p7ffd_int[2:0] }; |
||
693 | assign pent1m_1m_on = ~peff7_int[2]; |
||
694 | assign pent1m_ram0_0 = peff7_int[3]; |
||
695 | |||
696 | |||
697 | |||
698 | |||
88 | lvd | 699 | // gluclock ports (bit7:eff7 is above) |
4 | lvd | 700 | |
284 | lvd | 701 | assign gluclock_on = peff7_int[7] || shadow; // in shadow mode EEF7 is abandoned: instead, gluclock access |
702 | // is ON forever in shadow mode. |
||
88 | lvd | 703 | |
200 | lvd | 704 | always @(posedge zclk) |
88 | lvd | 705 | begin |
706 | if( gluclock_on && portf7_wr ) // gluclocks on |
||
707 | begin |
||
708 | if( !a[13] ) // $DFF7 - addr reg |
||
709 | gluclock_addr <= din; |
||
710 | |||
711 | // write to waiting register is not here - in separate section managing wait_write |
||
712 | end |
||
713 | end |
||
714 | |||
715 | |||
228 | lvd | 716 | // comports |
232 | lvd | 717 | |
228 | lvd | 718 | always @(posedge zclk) |
719 | begin |
||
720 | if( comport_wr || comport_rd ) |
||
721 | comport_addr <= a[10:8 ]; |
||
722 | end |
||
88 | lvd | 723 | |
724 | |||
725 | |||
726 | // write to wait registers |
||
200 | lvd | 727 | always @(posedge zclk) |
88 | lvd | 728 | begin |
729 | // gluclocks |
||
730 | if( gluclock_on && portf7_wr && !a[14] ) // $BFF7 - data reg |
||
731 | wait_write <= din; |
||
228 | lvd | 732 | // com ports |
733 | else if( comport_wr ) // $F8EF..$FFEF - comports |
||
734 | wait_write <= din; |
||
88 | lvd | 735 | end |
736 | |||
737 | // wait from wait registers |
||
200 | lvd | 738 | // |
739 | // ACHTUNG!!!! here portxx_wr are ON Z80 CLOCK! logic must change when moving to fclk strobes |
||
740 | // |
||
274 | lvd | 741 | assign wait_start_gluclock = ( gluclock_on && !a[14] && (portf7_rd || portf7_wr) ); // $BFF7 - gluclock r/w |
228 | lvd | 742 | // |
743 | assign wait_start_comport = ( comport_rd || comport_wr ); |
||
744 | // |
||
745 | // |
||
200 | lvd | 746 | always @(posedge zclk) // wait rnw - only meanful during wait |
88 | lvd | 747 | begin |
748 | if( port_wr ) |
||
749 | wait_rnw <= 1'b0; |
||
750 | |||
751 | if( port_rd ) |
||
752 | wait_rnw <= 1'b1; |
||
753 | end |
||
754 | |||
755 | |||
756 | |||
757 | |||
758 | |||
4 | lvd | 759 | // VG93 control |
200 | lvd | 760 | assign vg_cs_n = (~shadow) | iorq_n | (rd_n & wr_n) | ( ~((loa==VGCOM)|(loa==VGTRK)|(loa==VGSEC)|(loa==VGDAT)) ); |
4 | lvd | 761 | |
762 | |||
763 | |||
40 | lvd | 764 | |
4 | lvd | 765 | |
766 | |||
767 | |||
768 | |||
769 | // SD card (z-control¸r compatible) |
||
770 | |||
771 | wire sdcfg_wr,sddat_wr,sddat_rd; |
||
772 | |||
467 | lvd | 773 | assign sdcfg_wr = ( (loa==SDCFG) && port_wr_fclk && (!shadow) ) || |
774 | ( (loa==SDDAT) && port_wr_fclk && shadow && (a[15]==1'b1) ) ; |
||
4 | lvd | 775 | |
467 | lvd | 776 | assign sddat_wr = ( (loa==SDDAT) && port_wr_fclk && (!shadow) ) || |
777 | ( (loa==SDDAT) && port_wr_fclk && shadow && (a[15]==1'b0) ) ; |
||
228 | lvd | 778 | |
467 | lvd | 779 | assign sddat_rd = ( (loa==SDDAT) && port_rd_fclk ); |
228 | lvd | 780 | |
4 | lvd | 781 | // SDCFG write - sdcs_n control |
543 | lvd | 782 | assign sd_cs_n_stb = sdcfg_wr; |
783 | assign sd_cs_n_val = din[1]; |
||
4 | lvd | 784 | |
785 | |||
786 | // start signal for SPI module with resyncing to fclk |
||
787 | |||
467 | lvd | 788 | assign sd_start = sddat_wr || sddat_rd; |
4 | lvd | 789 | |
790 | // data for SPI module |
||
543 | lvd | 791 | assign sd_datain = sddat_rd ? 8'hFF : din; |
4 | lvd | 792 | |
793 | |||
794 | |||
200 | lvd | 795 | |
796 | |||
797 | |||
798 | |||
799 | ///////////////////////////////////////////////////////////////////////////////////////////////// |
||
800 | |||
801 | /////////////// |
||
802 | // ATM ports // |
||
803 | /////////////// |
||
804 | |||
805 | wire atm77_wr_fclk; |
||
806 | wire zxevbf_wr_fclk; |
||
807 | |||
270 | lvd | 808 | assign atmF7_wr_fclk = ( (loa==ATMF7) && (a[8]==1'b1) && shadow && port_wr_fclk ); // xFF7 and x7F7 ports, NOT xEF7! |
200 | lvd | 809 | assign atm77_wr_fclk = ( (loa==ATM77) && shadow && port_wr_fclk ); |
810 | |||
811 | assign zxevbf_wr_fclk = ( (loa==ZXEVBF) && port_wr_fclk ); |
||
812 | |||
813 | |||
814 | // port BF write |
||
815 | // |
||
816 | always @(posedge fclk, negedge rst_n) |
||
817 | if( !rst_n ) |
||
818 | begin |
||
476 | lvd | 819 | shadow_en_reg <= 1'b0; |
820 | romrw_en_reg <= 1'b0; |
||
821 | fntw_en_reg <= 1'b0; |
||
822 | set_nmi <= 1'b0; |
||
576 | lvd | 823 | brk_ena <= 1'b0; |
200 | lvd | 824 | end |
825 | else if( zxevbf_wr_fclk ) |
||
826 | begin |
||
827 | shadow_en_reg <= din[0]; |
||
828 | romrw_en_reg <= din[1]; |
||
394 | tsl | 829 | fntw_en_reg <= din[2]; |
476 | lvd | 830 | set_nmi <= din[3]; |
576 | lvd | 831 | brk_ena <= din[4]; |
200 | lvd | 832 | end |
833 | |||
834 | assign romrw_en = romrw_en_reg; |
||
835 | |||
836 | |||
837 | |||
838 | // port xx77 write |
||
839 | always @(posedge fclk, negedge rst_n) |
||
840 | if( !rst_n ) |
||
841 | begin |
||
842 | atm_scr_mode = 3'b011; |
||
471 | lvd | 843 | atm_turbo = 1'b0; |
262 | lvd | 844 | |
270 | lvd | 845 | atm_pen = 1'b1; // no manager, |
846 | atm_cpm_n = 1'b0; // permanent dosen (shadow ports on) |
||
262 | lvd | 847 | |
848 | |||
200 | lvd | 849 | atm_pen2 = 1'b0; |
850 | end |
||
851 | else if( atm77_wr_fclk ) |
||
852 | begin |
||
853 | atm_scr_mode <= din[2:0]; |
||
854 | atm_turbo <= din[3]; |
||
855 | atm_pen <= ~a[8]; |
||
856 | atm_cpm_n <= a[9]; |
||
857 | atm_pen2 <= ~a[14]; |
||
858 | end |
||
859 | |||
860 | |||
340 | lvd | 861 | // atm palette strobe and data |
360 | lvd | 862 | wire vg_wrFF_fclk; |
200 | lvd | 863 | |
360 | lvd | 864 | assign vg_wrFF_fclk = ( ( (loa==VGSYS)&&shadow ) && port_wr_fclk); |
865 | |||
866 | |||
867 | assign atm_palwr = vg_wrFF_fclk & atm_pen2; |
||
868 | |||
340 | lvd | 869 | assign atm_paldata = { ~din[4], ~din[7], ~din[1], ~din[6], ~din[0], ~din[5] }; |
870 | |||
360 | lvd | 871 | |
872 | |||
425 | lvd | 873 | // port BE write |
874 | assign clr_nmi = ( (loa==ZXEVBE) && port_wr_fclk ); |
||
360 | lvd | 875 | |
876 | |||
877 | |||
425 | lvd | 878 | |
360 | lvd | 879 | // covox/beeper writes |
880 | |||
881 | assign beeper_wr = (loa==PORTFE) && portfe_wr_fclk; |
||
882 | assign covox_wr = (loa==COVOX) && port_wr_fclk; |
||
883 | |||
884 | |||
395 | lvd | 885 | |
886 | // font write enable |
||
887 | assign fnt_wr = fntw_en_reg && mem_wr_fclk; |
||
888 | |||
889 | |||
425 | lvd | 890 | |
891 | // port BE read |
||
892 | |||
893 | always @* |
||
576 | lvd | 894 | case( a[12:8] ) |
425 | lvd | 895 | |
576 | lvd | 896 | 5'h0: portbemux = pages[ 7:0 ]; |
897 | 5'h1: portbemux = pages[15:8 ]; |
||
898 | 5'h2: portbemux = pages[23:16]; |
||
899 | 5'h3: portbemux = pages[31:24]; |
||
900 | 5'h4: portbemux = pages[39:32]; |
||
901 | 5'h5: portbemux = pages[47:40]; |
||
902 | 5'h6: portbemux = pages[55:48]; |
||
903 | 5'h7: portbemux = pages[63:56]; |
||
425 | lvd | 904 | |
576 | lvd | 905 | 5'h8: portbemux = ramnroms; |
906 | 5'h9: portbemux = dos7ffds; |
||
425 | lvd | 907 | |
576 | lvd | 908 | 5'hA: portbemux = p7ffd_int; |
909 | 5'hB: portbemux = peff7_int; |
||
425 | lvd | 910 | |
576 | lvd | 911 | 5'hC: portbemux = { ~atm_pen2, atm_cpm_n, ~atm_pen, dos, atm_turbo, atm_scr_mode }; |
425 | lvd | 912 | |
576 | lvd | 913 | 5'hD: portbemux = { ~palcolor[4], ~palcolor[2], ~palcolor[0], ~palcolor[5], 2'b11, ~palcolor[3], ~palcolor[1] }; |
425 | lvd | 914 | // assign atm_paldata = { ~din[4], ~din[7], ~din[1], ~din[6], ~din[0], ~din[5] }; |
915 | // {GgRrBb} -> {grbG11RB} |
||
916 | // was: 76543210 -> 471605 |
||
917 | // now: 543210 -> 4205xx31 |
||
918 | |||
576 | lvd | 919 | 5'hE: portbemux = fontrom_readback; |
669 | lvd | 920 | 5'hF: portbemux = { 4'bXXXX, border }; |
543 | lvd | 921 | |
576 | lvd | 922 | 5'h10: portbemux = brk_addr[7:0]; |
923 | 5'h11: portbemux = brk_addr[15:8]; |
||
543 | lvd | 924 | |
674 | lvd | 925 | 5'h12: portbemux = wrdisables; |
926 | |||
425 | lvd | 927 | default: portbemux = 8'bXXXXXXXX; |
928 | |||
929 | endcase |
||
930 | |||
931 | |||
932 | |||
933 | |||
934 | |||
476 | lvd | 935 | // savelij ports write |
936 | // |
||
937 | always @(posedge fclk) |
||
938 | if( port_wr_fclk && shadow ) |
||
939 | begin |
||
940 | if( (loa==SAVPORT1) || |
||
941 | (loa==SAVPORT2) || |
||
942 | (loa==SAVPORT3) || |
||
943 | (loa==SAVPORT4) ) |
||
944 | savport[ loa[6:5] ] <= din; |
||
945 | end |
||
946 | |||
947 | |||
948 | |||
668 | lvd | 949 | |
950 | // ULAPLUS ports |
||
951 | reg up_select; // 0 -- ena/dis, 1 -- palette write |
||
952 | // |
||
953 | wire up_wr = port_wr_fclk && (loa==ULAPLUS); |
||
954 | // |
||
955 | always @(posedge fclk) |
||
956 | if( up_wr && !a[14] ) |
||
957 | begin |
||
958 | if( !din[7] && din[6] ) |
||
959 | begin |
||
960 | up_select <= 1'b1; |
||
961 | end |
||
962 | |||
963 | if( !din[7] && !din[6] ) |
||
964 | begin |
||
965 | up_select <= 1'b0; |
||
966 | up_paladdr[5:0] <= din[5:0]; |
||
967 | end |
||
968 | end |
||
969 | // |
||
669 | lvd | 970 | always @(posedge fclk) if( up_wr && a[14] ) |
971 | up_lastwritten <= din; |
||
972 | // |
||
668 | lvd | 973 | assign up_palwr = up_wr && a[14] && !up_select; |
974 | // |
||
975 | always @(posedge fclk, negedge rst_n) |
||
976 | if( !rst_n ) |
||
977 | up_ena <= 1'b0; |
||
978 | else if( up_wr && a[14] && up_select ) |
||
979 | up_ena <= din[0]; |
||
980 | // |
||
981 | assign up_paldata = {din[4:2],din[7:5],din[1:0]}; // G3R3B2 to R3G3B2 |
||
982 | |||
4 | lvd | 983 | endmodule |
200 | lvd | 984 |