144 lines
2.9 KiB
Systemverilog
144 lines
2.9 KiB
Systemverilog
//
|
|
// video freeze with sync
|
|
// (C) Alexey Melnikov
|
|
//
|
|
//
|
|
// This program 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 2 of the License, or (at your option)
|
|
// any later version.
|
|
//
|
|
// This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
|
|
module video_freezer
|
|
(
|
|
input clk,
|
|
|
|
output sync,
|
|
input freeze,
|
|
|
|
input hs_in,
|
|
input vs_in,
|
|
input hbl_in,
|
|
input vbl_in,
|
|
|
|
output hs_out,
|
|
output vs_out,
|
|
output hbl_out,
|
|
output vbl_out
|
|
);
|
|
|
|
sync_lock #(33) vs_lock
|
|
(
|
|
.clk(clk),
|
|
.sync_in(vs_in),
|
|
.sync_out(vs_out),
|
|
.de_in(vbl_in),
|
|
.de_out(vbl_out),
|
|
.freeze(freeze)
|
|
);
|
|
|
|
wire sync_pt;
|
|
sync_lock #(21) hs_lock
|
|
(
|
|
.clk(clk),
|
|
.sync_in(hs_in),
|
|
.sync_out(hs_out),
|
|
.de_in(hbl_in),
|
|
.de_out(hbl_out),
|
|
.freeze(freeze),
|
|
.sync_pt(sync_pt)
|
|
);
|
|
|
|
reg sync_o;
|
|
always @(posedge clk) begin
|
|
reg old_hs, old_vs;
|
|
reg vs_sync;
|
|
|
|
old_vs <= vs_out;
|
|
|
|
if(~old_vs & vs_out) vs_sync <= 1;
|
|
if(sync_pt & vs_sync) begin
|
|
vs_sync <= 0;
|
|
sync_o <= ~sync_o;
|
|
end
|
|
end
|
|
|
|
assign sync = sync_o;
|
|
|
|
endmodule
|
|
|
|
|
|
module sync_lock #(parameter WIDTH)
|
|
(
|
|
input clk,
|
|
|
|
input sync_in,
|
|
input de_in,
|
|
|
|
output sync_out,
|
|
output de_out,
|
|
|
|
input freeze,
|
|
output sync_pt,
|
|
output valid
|
|
);
|
|
|
|
reg [WIDTH-1:0] f_len, s_len, de_start, de_end;
|
|
reg sync_valid;
|
|
|
|
reg old_sync;
|
|
always @(posedge clk) old_sync <= sync_in;
|
|
|
|
always @(posedge clk) begin
|
|
reg [WIDTH-1:0] cnti;
|
|
reg f_valid;
|
|
reg old_de;
|
|
|
|
cnti <= cnti + 1'd1;
|
|
if(~old_sync & sync_in) begin
|
|
if(sync_valid) f_len <= cnti;
|
|
f_valid <= 1;
|
|
sync_valid <= f_valid;
|
|
cnti <= 0;
|
|
end
|
|
|
|
if(old_sync & ~sync_in & sync_valid) s_len <= cnti;
|
|
|
|
old_de <= de_in;
|
|
if(~old_de & de_in & sync_valid) de_start <= cnti;
|
|
if(old_de & ~de_in & sync_valid) de_end <= cnti;
|
|
|
|
if(freeze) {f_valid, sync_valid} <= 0;
|
|
end
|
|
|
|
reg sync_o, de_o, sync_o_pre;
|
|
always @(posedge clk) begin
|
|
reg [WIDTH-1:0] cnto;
|
|
|
|
cnto <= cnto + 1'd1;
|
|
if(old_sync & ~sync_in & sync_valid) cnto <= s_len + 2'd2;
|
|
if(cnto == f_len) cnto <= 0;
|
|
|
|
sync_o_pre <= (cnto == (s_len>>1)); // middle in sync
|
|
if(cnto == f_len) sync_o <= 1;
|
|
if(cnto == s_len) sync_o <= 0;
|
|
if(cnto == de_start) de_o <= 1;
|
|
if(cnto == de_end) de_o <= 0;
|
|
end
|
|
|
|
assign sync_out = freeze ? sync_o : sync_in;
|
|
assign valid = sync_valid;
|
|
assign sync_pt = sync_o_pre;
|
|
assign de_out = freeze ? de_o : de_in;
|
|
|
|
endmodule
|