Subversion Repositories pentevo

Rev

Details | 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
// vg93 interface
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
 
4 lvd 24
// #1F - vg93 command/state reg {0,0} - not here!
25
// #3F - vg93 track register    {0,1} - not here!
26
// #5F - vg93 sector register   {1,0} - not here!
27
// #7F - vg93 data register     {1,1} - not here!
28
// #FF - output "system" reg/input (DRQ+IRQ) reg
29
//   output: d6 - FM/MFM               - NOT USED ANYWHERE! -> skipped
30
//           d4 - disk side            - inverted out
31
//           d3 - head load            - for HRDY pin of vg93
32
//           d2 - /RESET for vg93      - must be zero at system reset
33
//           d1:d0 - disk drive select - to the 74138
34
//    input: d7 - /INTRQ - resynced at CPU clock
35
//           d6 - /DRQ   - .....................
36
//
37
// current limitations:
38
//  1. read clock regenerator is made of simple counter, as in pentagon128
39
//  1. write precompensation is based only on SL/SR/TR43 signals
40
 
668 lvd 41
`include "../include/tune.v"
42
 
4 lvd 43
module vg93(
44
 
45
        input zclk, // Z80 cpu clock
46
        input rst_n,
47
        input fclk, // fpga 28 MHz clock
48
 
49
        output vg_clk,
50
        output reg vg_res_n,
51
 
52
        input [7:0] din,  // data input from CPU
53
        output intrq,drq, // output signals for the read #FF (not here)
856 lvd 54
        input vg_wrFF_fclk, // when TRDOS port #FF written - positive strobe
4 lvd 55
 
56
 
492 lvd 57
        output reg  vg_hrdy,
58
        output wire vg_rclk,
59
        output wire vg_rawr,
60
        output reg  [1:0] vg_a, // disk drive selection
61
        output reg  vg_wrd,
62
        output reg  vg_side,
4 lvd 63
 
64
        input step, // step signal from VG93
65
        input vg_sl,vg_sr,vg_tr43,
66
        input rdat_n,
67
        input vg_wf_de,
68
        input vg_drq,
69
        input vg_irq,
70
        input vg_wd
71
);
72
 
73
 
74
        localparam WRDELAY_OUTER_LEFT  = 4'd4;
75
        localparam WRDELAY_OUTER_RIGHT = 4'd11;
76
        localparam WRDELAY_INNER_LEFT  = 4'd0;  // minimal delay is for maximum shift left
77
        localparam WRDELAY_INNER_RIGHT = 4'd14; // maximal delay is for maximum shift right
78
        localparam WRDELAY_STANDARD    = 4'd7;  // no-shift
79
 
80
 
81
 
82
 
83
        reg [2:0] vgclk_div7;
84
        wire vgclk_strobe7;
85
        reg [1:0] vgclk_div4;
86
 
87
        reg [2:0] step_pulse;
88
        reg [2:0] drq_pulse;
89
        wire step_pospulse;
90
        wire  drq_pospulse;
91
        reg turbo_state;
92
 
93
        reg [1:0] intrq_sync;
94
        reg [1:0] drq_sync;
95
 
96
        reg [1:0] sl_sync,sr_sync,tr43_sync;
97
        reg [2:0] wd_sync;
98
        wire sl,sr,tr43,wd;
99
 
100
        reg [3:0] wrdelay_cnt;
101
        wire delay_end;
102
 
103
        reg [3:0] wrwidth_cnt;
104
        wire wrwidth_ena;
105
 
106
 
481 chrv 107
//      reg [4:0] rdat_sync;
108
//      reg rdat_edge1, rdat_edge2;
109
//      wire rdat;
4 lvd 110
 
481 chrv 111
//      reg [3:0] rwidth_cnt;
112
//      wire rwidth_ena;
113
//      reg [5:0] rclk_cnt;
114
//      wire rclk_strobe;
4 lvd 115
 
116
 
117
 
118
        // VG93 clocking and turbo-mode
119
 
120
        always @(posedge fclk)
121
        begin
122
                step_pulse[2:0] <= { step_pulse[1:0], step};
123
                 drq_pulse[2:0] <= {  drq_pulse[1:0], vg_drq};
124
        end
125
 
126
        assign step_pospulse = ( step_pulse[1] & (~step_pulse[2]) );
127
        assign  drq_pospulse = (  drq_pulse[1] & ( ~drq_pulse[2]) );
128
 
856 lvd 129
        always @(posedge fclk, negedge rst_n)
4 lvd 130
        begin
131
                if( !rst_n )
132
                        turbo_state <= 1'b0;
133
                else
134
                begin
135
                        if( drq_pospulse )
136
                                turbo_state <= 1'b0;
137
                        else if( step_pospulse )
138
                                turbo_state <= 1'b1;
139
                end
140
        end
141
 
142
 
143
 
144
        assign vgclk_strobe7 = (vgclk_div7[2:1] == 2'b11); // 28/7=4MHz freq strobe
145
 
146
        always @(posedge fclk)
147
        begin
148
                if( vgclk_strobe7 )
149
                        vgclk_div7 <= 3'd0;
150
                else
151
                        vgclk_div7 <= vgclk_div7 + 3'd1;
152
        end
153
 
154
        always @(posedge fclk)
155
        begin
156
                if( vgclk_strobe7 )
157
                begin
158
                        vgclk_div4[0] <= ~vgclk_div4[1];
159
 
160
                        if( turbo_state )
161
                                vgclk_div4[1] <= ~vgclk_div4[1];
162
                        else
163
                                vgclk_div4[1] <= vgclk_div4[0];
164
                end
165
        end
166
 
167
        assign vg_clk = vgclk_div4[1];
168
 
169
 
170
        // input/output for TR-DOS port #FF
171
 
856 lvd 172
        always @(posedge fclk, negedge rst_n) // CHANGE IF GO TO THE positive/negative strobes instead of zclk!
4 lvd 173
        begin
174
                if( !rst_n )
175
                        vg_res_n <= 1'b0;
856 lvd 176
                else if( vg_wrFF_fclk )
4 lvd 177
                        { vg_side, vg_hrdy, vg_res_n, vg_a } <= { (~din[4]),din[3],din[2],din[1:0] };
178
        end
179
 
180
        always @(posedge zclk)
181
        begin
182
                intrq_sync[1:0] <= {intrq_sync[0],vg_irq};
183
                drq_sync[1:0] <= {drq_sync[0],vg_drq};
184
        end
185
 
186
        assign intrq = intrq_sync[1];
187
        assign drq   =   drq_sync[1];
188
 
189
 
190
 
191
 
192
        // write precompensation
193
        // delay times are as in WRDELAY_* parameters, vg_wrd width is always 7 clocks
194
 
195
        always @(posedge fclk)
196
        begin
197
                  sl_sync[1:0] <= {   sl_sync[0],   vg_sl   };
198
                  sr_sync[1:0] <= {   sr_sync[0],   vg_sr   };
199
                tr43_sync[1:0] <= { tr43_sync[0],   vg_tr43 };
200
                  wd_sync[2:0] <= {   wd_sync[1:0], vg_wd   };
201
        end
202
 
203
        assign   sl =   sl_sync[1]; // just state signals
204
        assign   sr =   sr_sync[1]; //
205
        assign tr43 = tr43_sync[1]; //
206
 
207
        assign   wd =   wd_sync[1] & (~wd_sync[2]); // strobe: beginning of vg_wd
208
 
209
 
210
        // make delay
211
        always @(posedge fclk)
212
        begin
213
                if( wd )
214
                        case( {sl, tr43, sr} )
215
                        3'b100:  // shift left, outer tracks
216
                                wrdelay_cnt <= WRDELAY_OUTER_LEFT;
217
                        3'b001:  // shift right, outer tracks
218
                                wrdelay_cnt <= WRDELAY_OUTER_RIGHT;
219
                        3'b110:  // shift left, inner tracks
220
                                wrdelay_cnt <= WRDELAY_INNER_LEFT;
221
                        3'b011:  // shift right, inner tracks
222
                                wrdelay_cnt <= WRDELAY_INNER_RIGHT;
223
                        default: // no shift
224
                                wrdelay_cnt <= WRDELAY_STANDARD;
225
                        endcase
226
                else if( !delay_end )
227
                        wrdelay_cnt <= wrdelay_cnt - 4'd1;
228
        end
229
 
230
        assign delay_end = (wrdelay_cnt==4'd0);
231
 
232
 
233
        // make vg_wdr impulse after a delay
234
 
235
        always @(posedge fclk)
236
                if( wrwidth_ena )
237
                begin
238
                        if( wd )
239
                                wrwidth_cnt <= 4'd0;
240
                        else
241
                                wrwidth_cnt <= wrwidth_cnt + 4'd1;
242
                end
243
 
244
        assign wrwidth_ena = wd | ( delay_end & (~wrwidth_cnt[3]) );
245
 
246
        always @(posedge fclk)
247
                vg_wrd <= | wrwidth_cnt[2:0]; // only 7 clocks is the lendth of vg_wrd
248
 
249
 
250
 
251
 
492 lvd 252
/*      fapch_counter dpll
253
        (
254
                .fclk   (fclk   ),
4 lvd 255
 
492 lvd 256
                .rdat_n (rdat_n ),
4 lvd 257
 
492 lvd 258
                .vg_rclk(vg_rclk),
259
                .vg_rawr(vg_rawr)
260
        );
261
*/
4 lvd 262
 
492 lvd 263
        fapch_zek     dpll
264
        (
265
                .fclk   (fclk   ),
4 lvd 266
 
492 lvd 267
                .rdat_n (rdat_n ),
4 lvd 268
 
492 lvd 269
                .vg_rclk(vg_rclk),
270
                .vg_rawr(vg_rawr)
271
        );
4 lvd 272
 
273
 
274
 
275
 
276
endmodule
277