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 |