Rev 668 | 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 |
4 | lvd | 2 | // |
3 | // Z80 clocking module, also contains some wait-stating when 14MHz |
||
668 | lvd | 4 | |
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 | |||
24 | |||
4 | lvd | 25 | // |
40 | lvd | 26 | // IDEAL: |
27 | // fclk _/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\ |
||
28 | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
||
29 | // zclk /```\___/```\___/```\___/```````\_______/```````\_______/```````````````\_______________/```````````````\_______________/` |
||
30 | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
||
31 | // zpos `\___/```\___/```\___/```\___________/```\___________/```\___________________________/```\___________________________/```\ |
||
32 | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
||
33 | // zneg _/```\___/```\___/```\_______/```\___________/```\___________________/```\___________________________/```\________________ |
||
4 | lvd | 34 | |
40 | lvd | 35 | // clock phasing: |
36 | // cend must be zpos for 7mhz, therefore post_cbeg - zneg |
||
37 | // for 3.5 mhz, cend is both zpos and zneg (alternating) |
||
4 | lvd | 38 | |
39 | |||
467 | lvd | 40 | // 14MHz rulez: |
41 | // 1. do variable stalls for memory access. |
||
42 | // 2. do fallback on 7mhz for external IO accesses |
||
43 | // 3. clock switch 14-7-3.5 only at RFSH |
||
44 | |||
45 | |||
30 | lvd | 46 | `include "../include/tune.v" |
4 | lvd | 47 | |
48 | module zclock( |
||
49 | |||
684 | lvd | 50 | input wire fclk, |
51 | input wire rst_n, |
||
4 | lvd | 52 | |
684 | lvd | 53 | input wire zclk, // Z80 clock, buffered via act04 and returned back to the FPGA |
4 | lvd | 54 | |
684 | lvd | 55 | input wire [15:0] a, // for contention |
41 | lvd | 56 | |
684 | lvd | 57 | input wire [ 1:0] modes_raster, |
58 | input wire mode_contend_type, |
||
59 | input wire mode_contend_ena, |
||
60 | input wire [ 2:0] mode_7ffd_bits, // low 3 bits of 7FFD for 128k contention |
||
41 | lvd | 61 | |
684 | lvd | 62 | input wire contend, |
4 | lvd | 63 | |
684 | lvd | 64 | input wire mreq_n, |
65 | input wire iorq_n, |
||
66 | input wire m1_n, |
||
67 | input wire rfsh_n, // switch turbo modes in RFSH part of m1 |
||
40 | lvd | 68 | |
69 | |||
684 | lvd | 70 | output reg zclk_out, // generated Z80 clock - passed through inverter externally! |
200 | lvd | 71 | |
684 | lvd | 72 | output reg zpos, |
73 | output reg zneg, |
||
200 | lvd | 74 | |
75 | |||
684 | lvd | 76 | input wire zclk_stall, |
200 | lvd | 77 | |
4 | lvd | 78 | |
79 | |||
467 | lvd | 80 | |
684 | lvd | 81 | input wire [ 1:0] turbo, // 2'b00 - 3.5 MHz |
82 | // 2'b01 - 7.0 MHz |
||
83 | // 2'b1x - 14.0 MHz |
||
84 | |||
85 | output reg [ 1:0] int_turbo, // internal turbo, switched on /RFSH |
||
86 | |||
87 | |||
467 | lvd | 88 | // input signals for 14MHz external IORQ waits |
684 | lvd | 89 | input wire external_port, |
467 | lvd | 90 | |
91 | |||
684 | lvd | 92 | input wire cbeg, |
93 | input wire pre_cend // syncing signals, taken from arbiter.v and dram.v |
||
4 | lvd | 94 | ); |
95 | |||
96 | |||
97 | reg precend_cnt; |
||
40 | lvd | 98 | wire h_precend_1; // to take every other pulse of pre_cend |
99 | wire h_precend_2; // to take every other pulse of pre_cend |
||
4 | lvd | 100 | |
101 | reg [2:0] zcount; // counter for generating 3.5 and 7 MHz z80 clocks |
||
102 | |||
41 | lvd | 103 | reg old_rfsh_n; |
104 | |||
467 | lvd | 105 | wire stall; |
41 | lvd | 106 | |
467 | lvd | 107 | reg clk14_src; // source for 14MHz clock |
200 | lvd | 108 | |
467 | lvd | 109 | wire pre_zpos_35, |
110 | pre_zneg_35; |
||
111 | |||
112 | wire pre_zpos_70, |
||
113 | pre_zneg_70; |
||
114 | |||
115 | wire pre_zpos_140, |
||
116 | pre_zneg_140; |
||
117 | |||
118 | |||
684 | lvd | 119 | reg r_mreq_n; |
120 | wire iorq_n_a; |
||
121 | reg r_iorq_n_a; |
||
122 | wire contend_wait; |
||
123 | wire contend_mem; |
||
124 | wire contend_io; |
||
125 | wire contend_addr; |
||
467 | lvd | 126 | |
684 | lvd | 127 | reg [2:0] p7ffd; // resync to 14MHz |
467 | lvd | 128 | |
684 | lvd | 129 | |
40 | lvd | 130 | `ifdef SIMULATE |
4 | lvd | 131 | initial // simulation... |
132 | begin |
||
133 | precend_cnt = 1'b0; |
||
41 | lvd | 134 | int_turbo = 2'b00; |
135 | old_rfsh_n = 1'b1; |
||
467 | lvd | 136 | clk14_src = 1'b0; |
137 | |||
138 | zclk_out = 1'b0; |
||
4 | lvd | 139 | end |
40 | lvd | 140 | `endif |
4 | lvd | 141 | |
467 | lvd | 142 | // switch clock only at predefined time |
200 | lvd | 143 | always @(posedge fclk) if(zpos) |
144 | begin |
||
145 | old_rfsh_n <= rfsh_n; |
||
146 | |||
147 | if( old_rfsh_n && !rfsh_n ) |
||
148 | int_turbo <= turbo; |
||
149 | end |
||
150 | |||
151 | |||
684 | lvd | 152 | // resync p7ffd |
153 | always @(posedge fclk) |
||
154 | p7ffd <= mode_7ffd_bits; |
||
200 | lvd | 155 | |
467 | lvd | 156 | |
684 | lvd | 157 | |
467 | lvd | 158 | // make 14MHz iorq wait |
159 | reg [3:0] io_wait_cnt; |
||
160 | |||
161 | reg io_wait; |
||
162 | |||
163 | wire io; |
||
164 | reg io_r; |
||
165 | |||
166 | assign io = (~iorq_n) & m1_n & external_port; |
||
167 | |||
168 | always @(posedge fclk) |
||
169 | if( zpos ) |
||
170 | io_r <= io; |
||
171 | |||
172 | always @(posedge fclk, negedge rst_n) |
||
173 | if( ~rst_n ) |
||
174 | io_wait_cnt <= 4'd0; |
||
175 | else if( io && (!io_r) && zpos && int_turbo[1] ) |
||
176 | io_wait_cnt[3] <= 1'b1; |
||
177 | else if( io_wait_cnt[3] ) |
||
178 | io_wait_cnt <= io_wait_cnt + 4'd1; |
||
179 | |||
180 | always @(posedge fclk) |
||
181 | case( io_wait_cnt ) |
||
182 | 4'b1000: io_wait <= 1'b1; |
||
183 | 4'b1001: io_wait <= 1'b1; |
||
184 | 4'b1010: io_wait <= 1'b1; |
||
185 | 4'b1011: io_wait <= 1'b1; |
||
186 | 4'b1100: io_wait <= 1'b1; |
||
187 | 4'b1101: io_wait <= 1'b0; |
||
188 | 4'b1110: io_wait <= 1'b1; |
||
189 | 4'b1111: io_wait <= 1'b0; |
||
190 | default: io_wait <= 1'b0; |
||
191 | endcase |
||
192 | |||
193 | |||
194 | |||
195 | |||
684 | lvd | 196 | assign stall = zclk_stall | io_wait | contend_wait; |
467 | lvd | 197 | |
198 | |||
199 | |||
200 | // 14MHz clocking |
||
201 | always @(posedge fclk) |
||
202 | if( !stall ) |
||
203 | clk14_src <= ~clk14_src; |
||
204 | // |
||
205 | assign pre_zpos_140 = clk14_src ; |
||
206 | assign pre_zneg_140 = (~clk14_src); |
||
207 | |||
208 | |||
209 | |||
4 | lvd | 210 | // take every other pulse of pre_cend (make half pre_cend) |
211 | always @(posedge fclk) if( pre_cend ) |
||
212 | precend_cnt <= ~precend_cnt; |
||
213 | |||
40 | lvd | 214 | assign h_precend_1 = precend_cnt && pre_cend; |
215 | assign h_precend_2 = !precend_cnt && pre_cend; |
||
4 | lvd | 216 | |
217 | |||
467 | lvd | 218 | assign pre_zpos_35 = h_precend_2; |
219 | assign pre_zneg_35 = h_precend_1; |
||
41 | lvd | 220 | |
467 | lvd | 221 | assign pre_zpos_70 = pre_cend; |
222 | assign pre_zneg_70 = cbeg; |
||
41 | lvd | 223 | |
4 | lvd | 224 | |
467 | lvd | 225 | assign pre_zpos = int_turbo[1] ? pre_zpos_140 : ( int_turbo[0] ? pre_zpos_70 : pre_zpos_35 ); |
226 | assign pre_zneg = int_turbo[1] ? pre_zneg_140 : ( int_turbo[0] ? pre_zneg_70 : pre_zneg_35 ); |
||
227 | |||
228 | |||
229 | |||
40 | lvd | 230 | always @(posedge fclk) |
231 | begin |
||
467 | lvd | 232 | zpos <= (~stall) & pre_zpos & zclk_out; |
40 | lvd | 233 | end |
234 | |||
235 | always @(posedge fclk) |
||
236 | begin |
||
467 | lvd | 237 | zneg <= (~stall) & pre_zneg & (~zclk_out); |
40 | lvd | 238 | end |
239 | |||
467 | lvd | 240 | |
40 | lvd | 241 | |
242 | |||
243 | |||
467 | lvd | 244 | |
4 | lvd | 245 | // make Z80 clock: account for external inversion and make some leading of clock |
246 | // 9.5 ns propagation delay: from fclk posedge to zclk returned back any edge |
||
247 | // (1/28)/2=17.9ns half a clock lead |
||
248 | // 2.6ns lag because of non-output register emitting of zclk_out |
||
249 | // total: 5.8 ns lead of any edge of zclk relative to posedge of fclk => ACCOUNT FOR THIS WHEN DOING INTER-CLOCK DATA TRANSFERS |
||
250 | // |
||
251 | |||
40 | lvd | 252 | always @(negedge fclk) |
253 | begin |
||
254 | if( zpos ) |
||
255 | zclk_out <= 1'b0; |
||
4 | lvd | 256 | |
40 | lvd | 257 | if( zneg ) |
258 | zclk_out <= 1'b1; |
||
259 | end |
||
4 | lvd | 260 | |
40 | lvd | 261 | |
684 | lvd | 262 | |
263 | |||
264 | |||
265 | // contention emulation -- only 48k by now, TODO 128k pages and +2a/+3! |
||
266 | // |
||
267 | assign iorq_n_a = iorq_n || (a[0]==1'b1); |
||
268 | // |
||
269 | always @(posedge fclk) |
||
270 | if( zpos ) |
||
271 | begin |
||
272 | r_mreq_n <= mreq_n; |
||
273 | r_iorq_n_a <= iorq_n_a; |
||
274 | end |
||
275 | // |
||
276 | assign contend_addr = (modes_raster[0]==1'b0) ? ( a[15:14]==2'b01 ) : // 48k mode |
||
277 | ( a[15:14]==2'b01 || (a[15:14]==2'b11 && p7ffd[0]) ) ; // 128k mode (yet only 128/+2) |
||
278 | // |
||
279 | assign contend_mem = contend_addr && r_mreq_n; |
||
280 | assign contend_io = !iorq_n_a && r_iorq_n_a; |
||
281 | // |
||
282 | assign contend_wait = contend && (contend_mem || contend_io) && !int_turbo && modes_raster[1] && mode_contend_ena; |
||
283 | // |
||
284 | // TODO: contend is 28MHz signal, while we'd better have here |
||
285 | // 3.5MHz-synced r_contend signal, which should be synced |
||
286 | // to free-running 3.5MHz zpos/zneg sequence (not affected by stall) |
||
287 | |||
4 | lvd | 288 | endmodule |
289 |