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 |