Subversion Repositories pentevo

Rev

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