Rev 905 | 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 |
| 2 | // |
||
| 155 | lvd | 3 | // ATM-like memory pager (it pages specific 16kb region) |
| 152 | lvd | 4 | // with additions to support 4m addressable memory |
| 5 | // and pent1m mode. |
||
| 6 | // |
||
| 677 | lvd | 7 | // contain ports xFF7, x7F7, xBF7 |
| 152 | lvd | 8 | |
| 668 | lvd | 9 | /* |
| 10 | This file is part of ZX-Evo Base Configuration firmware. |
||
| 11 | |||
| 12 | ZX-Evo Base Configuration firmware is free software: |
||
| 13 | you can redistribute it and/or modify it under the terms of |
||
| 14 | the GNU General Public License as published by |
||
| 15 | the Free Software Foundation, either version 3 of the License, or |
||
| 16 | (at your option) any later version. |
||
| 17 | |||
| 18 | ZX-Evo Base Configuration firmware is distributed in the hope that |
||
| 19 | it will be useful, but WITHOUT ANY WARRANTY; without even |
||
| 20 | the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
| 21 | See the GNU General Public License for more details. |
||
| 22 | |||
| 23 | You should have received a copy of the GNU General Public License |
||
| 24 | along with ZX-Evo Base Configuration firmware. |
||
| 25 | If not, see <http://www.gnu.org/licenses/>. |
||
| 26 | */ |
||
| 27 | |||
| 155 | lvd | 28 | `include "../include/tune.v" |
| 29 | |||
| 152 | lvd | 30 | module atm_pager( |
| 31 | |||
| 32 | input wire rst_n, |
||
| 33 | |||
| 34 | input wire fclk, |
||
| 35 | input wire zpos, |
||
| 36 | input wire zneg, |
||
| 37 | |||
| 38 | |||
| 39 | input wire [15:0] za, // Z80 address bus |
||
| 40 | |||
| 41 | input wire [ 7:0] zd, // Z80 data bus - for latching port data |
||
| 42 | |||
| 161 | lvd | 43 | input wire mreq_n,rd_n,m1_n, // to track DOS turn on/turn off |
| 152 | lvd | 44 | |
| 153 | lvd | 45 | |
| 152 | lvd | 46 | input wire pager_off, // PEN as in ATM2: turns off memory paging, service ROM is everywhere |
| 47 | |||
| 48 | |||
| 49 | input wire pent1m_ROM, // for memory maps switching: d4 of 7ffd |
||
| 50 | input wire [ 5:0] pent1m_page, // 1 megabyte from pentagon1024 addressing, from 7FFD port |
||
| 51 | input wire pent1m_ram0_0, // RAM0 to the window 0 from pentagon1024 mode |
||
| 52 | input wire pent1m_1m_on, // 1 meg addressing of pent1m mode on |
||
| 53 | |||
| 425 | lvd | 54 | input wire in_nmi, // when we are in nmi, in 0000-3FFF must be last (FFth) |
| 55 | // RAM page. analoguous to pent1m_ram0_0 |
||
| 56 | // but has higher priority |
||
| 152 | lvd | 57 | |
| 859 | lvd | 58 | input wire in_trdemu, // like 'in_nmi', page 0xFE |
| 929 | lvd | 59 | input wire trdemu_wr_disable, // disable writes to page FE when trdemu is active |
| 859 | lvd | 60 | |
| 158 | lvd | 61 | input wire atmF7_wr, // write strobe for the xxF7 ATM port |
| 152 | lvd | 62 | |
| 63 | |||
| 64 | input wire dos, // indicates state of computer: also determines ROM mapping |
||
| 65 | |||
| 66 | |||
| 67 | output wire dos_turn_on, // turns on or off DOS signal |
||
| 68 | output wire dos_turn_off, // |
||
| 69 | |||
| 70 | output wire zclk_stall, // stall Z80 clock during DOS turning on |
||
| 71 | |||
| 72 | output reg [ 7:0] page, |
||
| 425 | lvd | 73 | output reg romnram, |
| 674 | lvd | 74 | output reg wrdisable, |
| 425 | lvd | 75 | |
| 76 | // output for xxBE port read |
||
| 77 | output wire [ 7:0] rd_page0, |
||
| 78 | output wire [ 7:0] rd_page1, |
||
| 79 | output wire [ 1:0] rd_dos7ffd, |
||
| 674 | lvd | 80 | output wire [ 1:0] rd_ramnrom, |
| 81 | output wire [ 1:0] rd_wrdisables |
||
| 152 | lvd | 82 | ); |
| 83 | parameter ADDR = 2'b00; |
||
| 84 | |||
| 85 | |||
| 86 | reg [ 7:0] pages [0:1]; // 2 pages for each map - switched by pent1m_ROM |
||
| 87 | |||
| 88 | reg [ 1:0] ramnrom; // ram(=1) or rom(=0) |
||
| 89 | reg [ 1:0] dos_7ffd; // =1 7ffd bits (ram) or DOS enter mode (rom) for given page |
||
| 90 | |||
| 674 | lvd | 91 | reg [ 1:0] wrdisables; // for each map |
| 92 | |||
| 684 | lvd | 93 | reg mreq_n_reg, rd_n_reg, m1_n_reg; |
| 152 | lvd | 94 | |
| 153 | lvd | 95 | wire dos_exec_stb, ram_exec_stb; |
| 152 | lvd | 96 | |
| 97 | |||
| 153 | lvd | 98 | reg [2:0] stall_count; |
| 152 | lvd | 99 | |
| 153 | lvd | 100 | |
| 425 | lvd | 101 | |
| 102 | // output data for port xxBE |
||
| 103 | assign rd_page0 = pages[0]; |
||
| 104 | assign rd_page1 = pages[1]; |
||
| 105 | // |
||
| 106 | assign rd_dos7ffd = dos_7ffd; |
||
| 107 | assign rd_ramnrom = ramnrom; |
||
| 674 | lvd | 108 | assign rd_wrdisables = wrdisables; |
| 425 | lvd | 109 | |
| 110 | |||
| 684 | lvd | 111 | |
| 152 | lvd | 112 | // paging function, does not set pages, ramnrom, dos_7ffd |
| 113 | // |
||
| 114 | always @(posedge fclk) |
||
| 115 | begin |
||
| 116 | if( pager_off ) |
||
| 117 | begin // atm no pager mode - each window has same ROM |
||
| 674 | lvd | 118 | romnram <= 1'b1; |
| 119 | page <= 8'hFF; |
||
| 120 | wrdisable <= 1'b0; |
||
| 152 | lvd | 121 | end |
| 122 | else // pager on |
||
| 123 | begin |
||
| 859 | lvd | 124 | if( (ADDR==2'b00) && (pent1m_ram0_0 || in_nmi || in_trdemu) ) |
| 152 | lvd | 125 | begin |
| 929 | lvd | 126 | wrdisable <= trdemu_wr_disable; |
| 684 | lvd | 127 | |
| 859 | lvd | 128 | if( in_nmi || in_trdemu ) |
| 425 | lvd | 129 | begin |
| 130 | romnram <= 1'b0; |
||
| 859 | lvd | 131 | page <= { 7'h7F, in_nmi }; |
| 425 | lvd | 132 | end |
| 133 | else // if( pent1m_ram0_0 ) |
||
| 134 | begin |
||
| 135 | romnram <= 1'b0; |
||
| 136 | page <= 8'd0; |
||
| 137 | end |
||
| 152 | lvd | 138 | end |
| 139 | else |
||
| 140 | begin |
||
| 675 | lvd | 141 | wrdisable <= wrdisables[ pent1m_ROM ]; |
| 684 | lvd | 142 | |
| 152 | lvd | 143 | romnram <= ~ramnrom[ pent1m_ROM ]; |
| 144 | |||
| 145 | if( dos_7ffd[ pent1m_ROM ] ) // 7ffd memmap switching |
||
| 146 | begin |
||
| 147 | if( ramnrom[ pent1m_ROM ] ) |
||
| 148 | begin // ram map |
||
| 149 | if( pent1m_1m_on ) |
||
| 150 | begin // map whole Mb from 7ffd to atm pages |
||
| 151 | page <= { pages[ pent1m_ROM ][7:6], pent1m_page[5:0] }; |
||
| 152 | end |
||
| 153 | else //128k like in atm2 |
||
| 154 | begin |
||
| 155 | page <= { pages[ pent1m_ROM ][7:3], pent1m_page[2:0] }; |
||
| 156 | end |
||
| 157 | end |
||
| 158 | else // rom map with dos |
||
| 159 | begin |
||
| 160 | page <= { pages[ pent1m_ROM ][7:1], dos }; |
||
| 161 | end |
||
| 162 | end |
||
| 163 | else // no 7ffd impact |
||
| 164 | begin |
||
| 165 | page <= pages[ pent1m_ROM ]; |
||
| 166 | end |
||
| 167 | end |
||
| 168 | end |
||
| 169 | end |
||
| 170 | |||
| 171 | |||
| 155 | lvd | 172 | |
| 158 | lvd | 173 | |
| 152 | lvd | 174 | // port reading: sets pages, ramnrom, dos_7ffd |
| 175 | // |
||
| 676 | lvd | 176 | always @(posedge fclk, negedge rst_n) |
| 177 | if( !rst_n ) |
||
| 152 | lvd | 178 | begin |
| 674 | lvd | 179 | wrdisables <= 2'b00; |
| 180 | end |
||
| 181 | else if( atmF7_wr ) |
||
| 182 | begin |
||
| 684 | lvd | 183 | if( za[15:14]==ADDR ) |
| 674 | lvd | 184 | case( {za[11],za[10]} ) |
| 676 | lvd | 185 | 2'b10: begin // xxBF7 port -- ROM/RAM readonly bit |
| 186 | wrdisables[ pent1m_ROM ] <= zd[0]; |
||
| 187 | end |
||
| 188 | |||
| 189 | default: begin |
||
| 190 | // nothing |
||
| 191 | end |
||
| 192 | endcase |
||
| 193 | end |
||
| 684 | lvd | 194 | // |
| 676 | lvd | 195 | always @(posedge fclk) |
| 196 | if( atmF7_wr ) |
||
| 197 | begin |
||
| 198 | if( za[15:14]==ADDR ) |
||
| 199 | case( {za[11],za[10]} ) |
||
| 674 | lvd | 200 | 2'b11: begin // xFF7 port |
| 201 | pages [ pent1m_ROM ] <= ~{ 2'b11, zd[5:0] }; |
||
| 202 | ramnrom [ pent1m_ROM ] <= zd[6]; |
||
| 203 | dos_7ffd[ pent1m_ROM ] <= zd[7]; |
||
| 204 | end |
||
| 205 | |||
| 206 | 2'b01: begin // x7F7 port |
||
| 207 | pages [ pent1m_ROM ] <= ~zd; |
||
| 208 | ramnrom [ pent1m_ROM ] <= 1'b1; // RAM on |
||
| 209 | // dos_7ffd - UNCHANGED!!! (possibility to use 7ffd 1m and 128k addressing in the whole 4m!) |
||
| 210 | end |
||
| 211 | |||
| 212 | default: begin |
||
| 213 | // nothing |
||
| 214 | end |
||
| 215 | |||
| 676 | lvd | 216 | endcase |
| 217 | end |
||
| 218 | |||
| 152 | lvd | 219 | |
| 153 | lvd | 220 | // DOS turn on/turn off |
| 221 | // |
||
| 152 | lvd | 222 | |
| 169 | lvd | 223 | `ifdef SIMULATE |
| 224 | initial |
||
| 225 | begin |
||
| 226 | m1_n_reg = 1'b1; |
||
| 227 | mreq_n_reg = 1'b1; |
||
| 228 | rd_n_reg = 1'b1; |
||
| 229 | |||
| 230 | stall_count = 3'b000; |
||
| 231 | end |
||
| 232 | `endif |
||
| 233 | |||
| 153 | lvd | 234 | always @(posedge fclk) if( zpos ) |
| 235 | begin |
||
| 236 | m1_n_reg <= m1_n; |
||
| 237 | end |
||
| 152 | lvd | 238 | |
| 153 | lvd | 239 | always @(posedge fclk) if( zneg ) |
| 240 | begin |
||
| 241 | mreq_n_reg <= mreq_n; |
||
| 242 | end |
||
| 152 | lvd | 243 | |
| 244 | |||
| 153 | lvd | 245 | |
| 171 | lvd | 246 | assign dos_exec_stb = zneg && (za[15:14]==ADDR) && |
| 153 | lvd | 247 | (!m1_n_reg) && (!mreq_n) && mreq_n_reg && |
| 248 | (za[13:8]==6'h3D) && |
||
| 249 | dos_7ffd[1'b1] && (!ramnrom[1'b1]) && pent1m_ROM; |
||
| 250 | |||
| 171 | lvd | 251 | assign ram_exec_stb = zneg && (za[15:14]==ADDR) && |
| 153 | lvd | 252 | (!m1_n_reg) && (!mreq_n) && mreq_n_reg && |
| 171 | lvd | 253 | ramnrom[pent1m_ROM]; |
| 153 | lvd | 254 | |
| 255 | assign dos_turn_on = dos_exec_stb; |
||
| 256 | assign dos_turn_off = ram_exec_stb; |
||
| 257 | |||
| 258 | |||
| 259 | // stall Z80 for some time when dos turning on to allow ROM chip to supply new data |
||
| 155 | lvd | 260 | // this can be important at 7 or even 14 mhz. minimum stall time is |
| 261 | // 3 clocks @ 28 MHz |
||
| 153 | lvd | 262 | always @(posedge fclk) |
| 263 | begin |
||
| 674 | lvd | 264 | // переключение в ДОС пзу происходит за полтакта z80 до того, как |
| 265 | // z80 считает данные. т.е. у пзу полтакта для выдачи новых данных. |
||
| 266 | // 3.5мгц - 140 нан, 7мгц - 70 нан, 14мгц - 35 нан. |
||
| 267 | // для пзухи 120нс на 14мгц надо еще 3 полтакта добавить, или другими |
||
| 268 | // словами, добавить к любой задержке на любой частоте минимум 3 такта |
||
| 269 | // 28 мгц. |
||
| 155 | lvd | 270 | if( dos_turn_on ) |
| 271 | begin |
||
| 272 | stall_count[2] <= 1'b1; // count: 000(stop) -> 101 -> 110 -> 111 -> 000(stop) |
||
| 158 | lvd | 273 | stall_count[0] <= 1'b1; |
| 155 | lvd | 274 | end |
| 275 | else if( stall_count[2] ) |
||
| 276 | begin |
||
| 277 | stall_count[2:0] <= stall_count[2:0] + 3'd1; |
||
| 278 | end |
||
| 158 | lvd | 279 | |
| 153 | lvd | 280 | end |
| 281 | |||
| 155 | lvd | 282 | assign zclk_stall = dos_turn_on | stall_count[2]; |
| 153 | lvd | 283 | |
| 155 | lvd | 284 | |
| 285 | |||
| 152 | lvd | 286 | endmodule |
| 287 |