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 |