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 |