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 |
| 134 | ddp | 2 | // |
| 3 | // generates horizontal sync, blank and video start strobe, horizontal window |
||
| 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 | |||
| 134 | ddp | 24 | // |
| 25 | // =\ /=========||... |
||
| 26 | // ==\ /==========||... |
||
| 27 | // ====--- -------===========||... |
||
| 28 | // | \ / | | |
||
| 29 | // | --- | | |
||
| 30 | // | | | | | |
||
| 31 | // 0 t1 | t3 t4 |
||
| 32 | // t2 |
||
| 33 | // at 0, video ends and blank begins |
||
| 34 | // t1 = 10 clocks (@7MHz), sync begins |
||
| 35 | // t2-t1 = 33 clocks |
||
| 36 | // t3-t2 = 41 clocks, then video starts |
||
| 37 | // |
||
| 38 | // repetition period = 448 clocks |
||
| 39 | |||
| 668 | lvd | 40 | `include "../include/tune.v" |
| 134 | ddp | 41 | |
| 317 | lvd | 42 | module video_sync_h( |
| 134 | ddp | 43 | |
| 282 | lvd | 44 | input wire clk, |
| 134 | ddp | 45 | |
| 282 | lvd | 46 | input wire init, // one-pulse strobe read at cend==1, initializes phase |
| 47 | // this is mainly for phasing with CPU clock 3.5/7 MHz |
||
| 48 | // still not used, but this may change anytime |
||
| 134 | ddp | 49 | |
| 282 | lvd | 50 | input wire cend, // working strobes from DRAM controller (7MHz) |
| 51 | input wire pre_cend, |
||
| 134 | ddp | 52 | |
| 53 | |||
| 354 | lvd | 54 | // modes inputs |
| 282 | lvd | 55 | input wire mode_atm_n_pent, |
| 354 | lvd | 56 | input wire mode_a_text, |
| 134 | ddp | 57 | |
| 684 | lvd | 58 | input wire [ 1:0] modes_raster, |
| 59 | input wire mode_contend_type, |
||
| 134 | ddp | 60 | |
| 282 | lvd | 61 | output reg hblank, |
| 62 | output reg hsync, |
||
| 134 | ddp | 63 | |
| 282 | lvd | 64 | output reg line_start, // 1 video cycle prior to actual start of visible line |
| 65 | output reg hsync_start, // 1 cycle prior to beginning of hsync: used in frame sync/blank generation |
||
| 66 | // these signals coincide with cend |
||
| 134 | ddp | 67 | |
| 282 | lvd | 68 | output reg hint_start, // horizontal position of INT start, for fine tuning |
| 134 | ddp | 69 | |
| 282 | lvd | 70 | output reg scanin_start, |
| 71 | |||
| 684 | lvd | 72 | input wire vpix, |
| 318 | lvd | 73 | output reg hpix, // marks gate during which pixels are outting |
| 282 | lvd | 74 | |
| 684 | lvd | 75 | output reg contend, // for 48k/128k CPU contention |
| 76 | |||
| 77 | output reg border_sync, // for 48k/128k 4t border emulation |
||
| 78 | |||
| 318 | lvd | 79 | // these signals turn on and turn off 'go' signal |
| 80 | output reg fetch_start, // 18 cycles earlier than hpix, coincide with cend |
||
| 81 | output reg fetch_end // --//-- |
||
| 82 | |||
| 134 | ddp | 83 | ); |
| 84 | |||
| 85 | |||
| 86 | localparam HBLNK_BEG = 9'd00; |
||
| 87 | localparam HSYNC_BEG = 9'd10; |
||
| 88 | localparam HSYNC_END = 9'd43; |
||
| 89 | localparam HBLNK_END = 9'd88; |
||
| 90 | |||
| 282 | lvd | 91 | // pentagon (x256) |
| 92 | localparam HPIX_BEG_PENT = 9'd140; // 52 cycles from line_start to pixels beginning |
||
| 93 | localparam HPIX_END_PENT = 9'd396; |
||
| 134 | ddp | 94 | |
| 282 | lvd | 95 | // atm (x320) |
| 96 | localparam HPIX_BEG_ATM = 9'd108; // 52 cycles from line_start to pixels beginning |
||
| 97 | localparam HPIX_END_ATM = 9'd428; |
||
| 98 | |||
| 99 | |||
| 318 | lvd | 100 | localparam FETCH_FOREGO = 9'd18; // consistent with older go_start in older fetch.v: |
| 101 | // actual data starts fetching 2 dram cycles after |
||
| 102 | // 'go' goes to 1, screen output starts another |
||
| 103 | // 16 cycles after 1st data bundle is fetched |
||
| 104 | |||
| 105 | |||
| 134 | ddp | 106 | localparam SCANIN_BEG = 9'd88; // when scan-doubler starts pixel storing |
| 107 | |||
| 108 | |||
| 684 | lvd | 109 | localparam HINT_BEG = 9'd2; |
| 110 | localparam HINT_BEG_48K = 9'd126; |
||
| 111 | localparam HINT_BEG_128K = 9'd130; |
||
| 134 | ddp | 112 | |
| 113 | |||
| 684 | lvd | 114 | localparam HPERIOD_224 = 9'd448; |
| 115 | localparam HPERIOD_228 = 9'd456; |
||
| 134 | ddp | 116 | |
| 684 | lvd | 117 | |
| 118 | localparam CONTEND_START = 9'd127; // fixed for correct contend phase: coincides with positive edge of z80 clock |
||
| 119 | //localparam CONTEND_START_48K = 9'd132; |
||
| 120 | //localparam CONTEND_START_128K = 9'd132; |
||
| 121 | |||
| 122 | |||
| 123 | localparam BORDER_PHASE = 3'd4; |
||
| 124 | |||
| 125 | |||
| 134 | ddp | 126 | reg [8:0] hcount; |
| 127 | |||
| 684 | lvd | 128 | reg [8:0] contend_ctr; |
| 134 | ddp | 129 | |
| 318 | lvd | 130 | // for simulation only |
| 131 | // |
||
| 134 | ddp | 132 | initial |
| 133 | begin |
||
| 134 | hcount = 9'd0; |
||
| 135 | hblank = 1'b0; |
||
| 136 | hsync = 1'b0; |
||
| 137 | line_start = 1'b0; |
||
| 138 | hsync_start = 1'b0; |
||
| 139 | hpix = 1'b0; |
||
| 140 | end |
||
| 141 | |||
| 318 | lvd | 142 | |
| 143 | |||
| 144 | |||
| 134 | ddp | 145 | always @(posedge clk) if( cend ) |
| 146 | begin |
||
| 684 | lvd | 147 | if( init || hcount==( (modes_raster==2'b11) ? (HPERIOD_228-9'd1) : (HPERIOD_224-9'd1) ) ) |
| 134 | ddp | 148 | hcount <= 9'd0; |
| 149 | else |
||
| 150 | hcount <= hcount + 9'd1; |
||
| 151 | end |
||
| 152 | |||
| 153 | |||
| 154 | |||
| 155 | always @(posedge clk) if( cend ) |
||
| 156 | begin |
||
| 157 | if( hcount==HBLNK_BEG ) |
||
| 158 | hblank <= 1'b1; |
||
| 159 | else if( hcount==HBLNK_END ) |
||
| 160 | hblank <= 1'b0; |
||
| 161 | |||
| 162 | |||
| 163 | if( hcount==HSYNC_BEG ) |
||
| 164 | hsync <= 1'b1; |
||
| 165 | else if( hcount==HSYNC_END ) |
||
| 166 | hsync <= 1'b0; |
||
| 167 | end |
||
| 168 | |||
| 169 | |||
| 170 | always @(posedge clk) |
||
| 171 | begin |
||
| 172 | if( pre_cend ) |
||
| 173 | begin |
||
| 174 | if( hcount==HSYNC_BEG ) |
||
| 175 | hsync_start <= 1'b1; |
||
| 176 | |||
| 177 | if( hcount==HBLNK_END ) |
||
| 178 | line_start <= 1'b1; |
||
| 179 | |||
| 180 | if( hcount==SCANIN_BEG ) |
||
| 181 | scanin_start <= 1'b1; |
||
| 318 | lvd | 182 | |
| 134 | ddp | 183 | end |
| 184 | else |
||
| 185 | begin |
||
| 318 | lvd | 186 | hsync_start <= 1'b0; |
| 187 | line_start <= 1'b0; |
||
| 134 | ddp | 188 | scanin_start <= 1'b0; |
| 189 | end |
||
| 190 | end |
||
| 191 | |||
| 192 | |||
| 354 | lvd | 193 | |
| 194 | wire fetch_start_time, fetch_start_condition; |
||
| 355 | lvd | 195 | wire fetch_end_condition; |
| 354 | lvd | 196 | |
| 197 | reg [3:0] fetch_start_wait; |
||
| 198 | |||
| 355 | lvd | 199 | |
| 200 | assign fetch_start_time = (mode_atm_n_pent ? |
||
| 354 | lvd | 201 | (HPIX_BEG_ATM -FETCH_FOREGO-9'd4) : |
| 355 | lvd | 202 | (HPIX_BEG_PENT-FETCH_FOREGO-9'd4) ) == hcount; |
| 354 | lvd | 203 | |
| 204 | always @(posedge clk) if( cend ) |
||
| 205 | fetch_start_wait[3:0] <= { fetch_start_wait[2:0], fetch_start_time }; |
||
| 206 | |||
| 355 | lvd | 207 | assign fetch_start_condition = mode_a_text ? fetch_start_time : fetch_start_wait[3]; |
| 354 | lvd | 208 | |
| 134 | ddp | 209 | always @(posedge clk) |
| 354 | lvd | 210 | if( pre_cend && fetch_start_condition ) |
| 211 | fetch_start <= 1'b1; |
||
| 212 | else |
||
| 213 | fetch_start <= 1'b0; |
||
| 214 | |||
| 215 | |||
| 216 | |||
| 217 | |||
| 355 | lvd | 218 | assign fetch_end_time = (mode_atm_n_pent ? |
| 219 | (HPIX_END_ATM -FETCH_FOREGO) : |
||
| 220 | (HPIX_END_PENT-FETCH_FOREGO) ) == hcount; |
||
| 354 | lvd | 221 | |
| 222 | always @(posedge clk) |
||
| 355 | lvd | 223 | if( pre_cend && fetch_end_time ) |
| 224 | fetch_end <= 1'b1; |
||
| 225 | else |
||
| 226 | fetch_end <= 1'b0; |
||
| 227 | |||
| 228 | |||
| 229 | |||
| 230 | |||
| 231 | |||
| 232 | always @(posedge clk) |
||
| 134 | ddp | 233 | begin |
| 684 | lvd | 234 | if( pre_cend && hcount==( modes_raster[1] ? (modes_raster[0] ? HINT_BEG_128K : HINT_BEG_48K) : HINT_BEG ) ) |
| 134 | ddp | 235 | hint_start <= 1'b1; |
| 236 | else |
||
| 237 | hint_start <= 1'b0; |
||
| 238 | end |
||
| 239 | |||
| 240 | |||
| 241 | always @(posedge clk) if( cend ) |
||
| 242 | begin |
||
| 282 | lvd | 243 | if( hcount==(mode_atm_n_pent ? HPIX_BEG_ATM : HPIX_BEG_PENT) ) |
| 134 | ddp | 244 | hpix <= 1'b1; |
| 282 | lvd | 245 | else if( hcount==(mode_atm_n_pent ? HPIX_END_ATM : HPIX_END_PENT) ) |
| 134 | ddp | 246 | hpix <= 1'b0; |
| 247 | end |
||
| 248 | |||
| 249 | |||
| 318 | lvd | 250 | |
| 684 | lvd | 251 | // contention generator |
| 252 | initial |
||
| 253 | contend_ctr <=9'h100; |
||
| 254 | // |
||
| 255 | always @(posedge clk) if( cend ) |
||
| 256 | begin |
||
| 257 | if( hcount == CONTEND_START ) |
||
| 258 | contend_ctr <= 9'd0; |
||
| 259 | else if( !contend_ctr[8] ) |
||
| 260 | contend_ctr <= contend_ctr + 9'd1; |
||
| 261 | end |
||
| 262 | // |
||
| 263 | // |
||
| 264 | always @(posedge clk) if( cend ) |
||
| 265 | begin |
||
| 266 | if( contend_ctr[8] || !vpix ) |
||
| 267 | contend <= 1'b0; |
||
| 268 | else if( !mode_contend_type ) |
||
| 269 | // 48k type contention |
||
| 270 | case( contend_ctr[3:1] ) |
||
| 271 | 3'd6, |
||
| 272 | 3'd7: contend <= 1'b0; |
||
| 273 | default: contend <= 1'b1; |
||
| 274 | endcase |
||
| 275 | else |
||
| 276 | // +2a/+3 type contention |
||
| 277 | case( contend_ctr[3:1] ) |
||
| 278 | 3'd1: contend <= 1'b0; |
||
| 279 | default: contend <= 1'b1; |
||
| 280 | endcase |
||
| 281 | // |
||
| 282 | // warning! probably +2a/+3 contention pattern is incorrect, it begins with 1 cycle contention but probably should end |
||
| 283 | // with one extra contention cycle. Anyway this is left as TODO. |
||
| 284 | // |
||
| 285 | end |
||
| 318 | lvd | 286 | |
| 287 | |||
| 684 | lvd | 288 | |
| 289 | // border sync signal gen |
||
| 290 | always @(posedge clk) |
||
| 291 | if( pre_cend && hcount[2:0]==BORDER_PHASE ) |
||
| 292 | border_sync <= 1'b1; |
||
| 293 | else |
||
| 294 | border_sync <= 1'b0; |
||
| 295 | |||
| 296 | |||
| 297 | |||
| 134 | ddp | 298 | endmodule |
| 299 |