// ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014
//
// generates vertical blank, sync and window.
/*
This file is part of ZX-Evo Base Configuration firmware.
ZX-Evo Base Configuration firmware is free software:
you can redistribute it and/or modify it under the terms of
the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ZX-Evo Base Configuration firmware is distributed in the hope that
it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ZX-Evo Base Configuration firmware.
If not, see <http://www.gnu.org/licenses/>.
*/
// H is period of horizontal sync;
// from the last non-blanked line:
// 3H is pre-blank,
// 2.xxH is vertical sync (slightly more than 2H, all hsync edges preserved)
// vblank is total of 25H
`include "../include/tune.v"
module video_sync_v(
input wire clk,
input wire hsync_start, // synchronizing signal
input wire line_start, // to end vsync some time after hsync has ended
input wire hint_start,
// atm video mode input
input wire mode_atm_n_pent,
input wire [ 1:0] modes_raster,
output reg vblank,
output reg vsync,
output reg int_start, // one-shot positive pulse marking beginning of INT for Z80
output reg vpix // vertical picture marker: active when there is line with pixels in it, not just a border. changes with hsync edge
);
localparam VBLNK_BEG = 9'd00;
localparam VSYNC_BEG_50HZ = 9'd08;
localparam VSYNC_END_50HZ = 9'd11;
localparam VBLNK_END_50HZ = 9'd32;
localparam VSYNC_BEG_60HZ = 9'd04;
localparam VSYNC_END_60HZ = 9'd07;
localparam VBLNK_END_60HZ = 9'd22;
/* // pentagon (x192)
localparam VPIX_BEG_PENT = 9'd080;
localparam VPIX_END_PENT = 9'd272;
// ATM (x200)
localparam VPIX_BEG_ATM = 9'd076;
localparam VPIX_END_ATM = 9'd276;
*/
localparam VPIX_BEG_PENTAGON = 9'd076; // for pentagon raster: actual begin is for x200 s, add 4 for x192 modes
localparam VPIX_END_PENTAGON = 9'd272; // actual end is for x192 modes, add 4 for x200 modes.
localparam VPIX_BEG_60HZ = 9'd042;
localparam VPIX_END_60HZ = 9'd238;
localparam VPIX_BEG_48K = 9'd060;
localparam VPIX_END_48K = 9'd256;
localparam VPIX_BEG_128K = 9'd059;
localparam VPIX_END_128K = 9'd255;
/* // ntsc
// pentagon (x192)
localparam VPIX60_BEG_PENT = 9'd046;
localparam VPIX60_END_PENT = 9'd238;
// ATM (x200)
localparam VPIX60_BEG_ATM = 9'd042;
localparam VPIX60_END_ATM = 9'd242;
*/ //
localparam VPERIOD_PENTAGON = 9'd320;
localparam VPERIOD_60HZ = 9'd262;
localparam VPERIOD_48K = 9'd312;
localparam VPERIOD_128K = 9'd311;
localparam INT_BEG = 9'd0;
localparam INT_BEG_48K = 9'd1;
localparam INT_BEG_128K = 9'd1;
reg [8:0] vcount;
reg [8:0] vperiod;
reg [8:0] vpix_beg;
reg [8:0] vpix_end;
initial // for simulation only
begin
vcount = 9'd0;
vsync = 1'b0;
vblank = 1'b0;
vpix = 1'b0;
int_start = 1'b0;
vperiod = 'd0;
vpix_beg = 'd0;
vpix_end = 'd0;
end
always @(posedge clk)
case( modes_raster )
default: vperiod <= VPERIOD_PENTAGON - 9'd1;
2'b01: vperiod <= VPERIOD_60HZ - 9'd1;
2'b10: vperiod <= VPERIOD_48K - 9'd1;
2'b11: vperiod <= VPERIOD_128K - 9'd1;
endcase
always @(posedge clk)
case( modes_raster )
default: vpix_beg <= VPIX_BEG_PENTAGON;
2'b01: vpix_beg <= VPIX_BEG_60HZ ;
2'b10: vpix_beg <= VPIX_BEG_48K ;
2'b11: vpix_beg <= VPIX_BEG_128K ;
endcase
always @(posedge clk)
case( modes_raster )
default: vpix_end <= VPIX_END_PENTAGON;
2'b01: vpix_end <= VPIX_END_60HZ ;
2'b10: vpix_end <= VPIX_END_48K ;
2'b11: vpix_end <= VPIX_END_128K ;
endcase
always @(posedge clk) if( hsync_start )
begin
if( vcount==vperiod )
begin
vcount <= 9'd0;
end
else
vcount <= vcount + 9'd1;
end
always @(posedge clk) if( hsync_start )
begin
if( vcount==VBLNK_BEG )
vblank <= 1'b1;
else if( vcount==( (modes_raster==2'b01) ? VBLNK_END_60HZ : VBLNK_END_50HZ ) )
vblank <= 1'b0;
end
always @(posedge clk)
begin
if( vcount==( modes_raster==2'b01 ? VSYNC_BEG_60HZ : VSYNC_BEG_50HZ ) && hsync_start )
vsync <= 1'b1;
else if( vcount==( modes_raster==2'b01 ? VSYNC_END_60HZ : VSYNC_END_50HZ ) && line_start )
vsync <= 1'b0;
end
always @(posedge clk)
begin
//if( hint_start && vcount==( modes_raster[1] ? (modes_raster[0] ? INT_BEG_128K : INT_BEG_48K) : INT_BEG ) )
if( hint_start && vcount==( modes_raster[1] ? (modes_raster[0] ? INT_BEG_128K : INT_BEG_48K) : INT_BEG ) )
int_start <= 1'b1;
else
int_start <= 1'b0;
end
always @(posedge clk) if( hsync_start )
begin
if( vcount==(vpix_beg + (9'd4 & {9{~mode_atm_n_pent}})) )
vpix <= 1'b1;
else if( vcount==(vpix_end + (9'd4 & {9{mode_atm_n_pent}})) )
vpix <= 1'b0;
end
endmodule