MacPlus_MiSTer/sys/video_mixer.sv

220 lines
4.6 KiB
Systemverilog
Raw Permalink Normal View History

2017-10-22 01:22:56 +00:00
//
//
2021-03-03 09:35:46 +00:00
// Copyright (c) 2017,2021 Alexey Melnikov
2017-10-22 01:22:56 +00:00
//
// This program is GPL Licensed. See COPYING for the full license.
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
//
2022-03-07 09:07:01 +00:00
// LINE_LENGTH: Length of display line in pixels when HBlank = 0;
2017-10-22 01:22:56 +00:00
// HALF_DEPTH: If =1 then color dept is 4 bits per component
2020-01-21 16:55:46 +00:00
//
// altera message_off 10720
// altera message_off 12161
2017-10-22 01:22:56 +00:00
module video_mixer
#(
parameter LINE_LENGTH = 768,
2020-01-21 16:55:46 +00:00
parameter HALF_DEPTH = 0,
parameter GAMMA = 0
2017-10-22 01:22:56 +00:00
)
(
2021-03-03 09:35:46 +00:00
input CLK_VIDEO, // should be multiple by (ce_pix*4)
output reg CE_PIXEL, // output pixel clock enable
2020-01-21 16:55:46 +00:00
2021-03-03 09:35:46 +00:00
input ce_pix, // input pixel clock or clock_enable
2017-10-22 01:22:56 +00:00
input scandoubler,
2021-03-03 09:35:46 +00:00
input hq2x, // high quality 2x scaling
2017-10-22 01:22:56 +00:00
2021-03-03 09:35:46 +00:00
inout [21:0] gamma_bus,
2017-10-22 01:22:56 +00:00
// color
input [DWIDTH:0] R,
input [DWIDTH:0] G,
input [DWIDTH:0] B,
// Positive pulses.
input HSync,
input VSync,
input HBlank,
input VBlank,
2022-03-07 09:07:01 +00:00
// Freeze engine
// HDMI: displays last frame
// VGA: black screen with HSync and VSync
input HDMI_FREEZE,
output freeze_sync,
2017-10-22 01:22:56 +00:00
// video output signals
output reg [7:0] VGA_R,
output reg [7:0] VGA_G,
output reg [7:0] VGA_B,
output reg VGA_VS,
output reg VGA_HS,
output reg VGA_DE
);
localparam DWIDTH = HALF_DEPTH ? 3 : 7;
2020-01-21 16:55:46 +00:00
localparam DWIDTH_SD = GAMMA ? 7 : DWIDTH;
localparam HALF_DEPTH_SD = GAMMA ? 0 : HALF_DEPTH;
2022-03-07 09:07:01 +00:00
wire frz_hs, frz_vs;
wire frz_hbl, frz_vbl;
video_freezer freezer
(
.clk(CLK_VIDEO),
.freeze(HDMI_FREEZE),
.hs_in(HSync),
.vs_in(VSync),
.hbl_in(HBlank),
.vbl_in(VBlank),
.sync(freeze_sync),
.hs_out(frz_hs),
.vs_out(frz_vs),
.hbl_out(frz_hbl),
.vbl_out(frz_vbl)
);
reg frz;
always @(posedge CLK_VIDEO) begin
reg frz1;
frz1 <= HDMI_FREEZE;
frz <= frz1;
end
2020-01-21 16:55:46 +00:00
generate
if(GAMMA && HALF_DEPTH) begin
2022-03-07 09:07:01 +00:00
wire [7:0] R_in = frz ? 8'd0 : {R,R};
wire [7:0] G_in = frz ? 8'd0 : {G,G};
wire [7:0] B_in = frz ? 8'd0 : {B,B};
2020-01-21 16:55:46 +00:00
end else begin
2022-03-07 09:07:01 +00:00
wire [DWIDTH:0] R_in = frz ? 1'd0 : R;
wire [DWIDTH:0] G_in = frz ? 1'd0 : G;
wire [DWIDTH:0] B_in = frz ? 1'd0 : B;
2020-01-21 16:55:46 +00:00
end
endgenerate
wire hs_g, vs_g;
wire hb_g, vb_g;
wire [DWIDTH_SD:0] R_gamma, G_gamma, B_gamma;
generate
if(GAMMA) begin
assign gamma_bus[21] = 1;
gamma_corr gamma(
.clk_sys(gamma_bus[20]),
2021-03-03 09:35:46 +00:00
.clk_vid(CLK_VIDEO),
2020-01-21 16:55:46 +00:00
.ce_pix(ce_pix),
.gamma_en(gamma_bus[19]),
.gamma_wr(gamma_bus[18]),
.gamma_wr_addr(gamma_bus[17:8]),
.gamma_value(gamma_bus[7:0]),
2022-03-07 09:07:01 +00:00
.HSync(frz_hs),
.VSync(frz_vs),
.HBlank(frz_hbl),
.VBlank(frz_vbl),
2020-01-21 16:55:46 +00:00
.RGB_in({R_in,G_in,B_in}),
.HSync_out(hs_g),
.VSync_out(vs_g),
.HBlank_out(hb_g),
.VBlank_out(vb_g),
.RGB_out({R_gamma,G_gamma,B_gamma})
);
end else begin
assign gamma_bus[21] = 0;
assign {R_gamma,G_gamma,B_gamma} = {R_in,G_in,B_in};
2022-03-07 09:07:01 +00:00
assign {hs_g, vs_g, hb_g, vb_g} = {frz_hs, frz_vs, frz_hbl, frz_vbl};
2020-01-21 16:55:46 +00:00
end
endgenerate
wire [DWIDTH_SD:0] R_sd;
wire [DWIDTH_SD:0] G_sd;
wire [DWIDTH_SD:0] B_sd;
2017-10-22 01:22:56 +00:00
wire hs_sd, vs_sd, hb_sd, vb_sd, ce_pix_sd;
2020-01-21 16:55:46 +00:00
scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH_SD)) sd
2017-10-22 01:22:56 +00:00
(
2021-03-03 09:35:46 +00:00
.clk_vid(CLK_VIDEO),
.hq2x(hq2x),
.ce_pix(ce_pix),
2020-01-21 16:55:46 +00:00
.hs_in(hs_g),
.vs_in(vs_g),
.hb_in(hb_g),
.vb_in(vb_g),
.r_in(R_gamma),
.g_in(G_gamma),
.b_in(B_gamma),
2017-10-22 01:22:56 +00:00
.ce_pix_out(ce_pix_sd),
.hs_out(hs_sd),
.vs_out(vs_sd),
.hb_out(hb_sd),
.vb_out(vb_sd),
.r_out(R_sd),
.g_out(G_sd),
.b_out(B_sd)
);
2021-03-03 09:35:46 +00:00
wire [DWIDTH_SD:0] rt = (scandoubler ? R_sd : R_gamma);
wire [DWIDTH_SD:0] gt = (scandoubler ? G_sd : G_gamma);
wire [DWIDTH_SD:0] bt = (scandoubler ? B_sd : B_gamma);
2017-10-22 01:22:56 +00:00
2021-03-03 09:35:46 +00:00
always @(posedge CLK_VIDEO) begin
reg [7:0] r,g,b;
reg hde,vde,hs,vs, old_vs;
reg old_hde;
reg old_ce;
reg ce_osc, fs_osc;
old_ce <= ce_pix;
ce_osc <= ce_osc | (old_ce ^ ce_pix);
2017-10-22 01:22:56 +00:00
2021-03-03 09:35:46 +00:00
old_vs <= vs;
if(~old_vs & vs) begin
fs_osc <= ce_osc;
ce_osc <= 0;
end
2017-10-22 01:22:56 +00:00
2021-03-03 09:35:46 +00:00
CE_PIXEL <= scandoubler ? ce_pix_sd : fs_osc ? (~old_ce & ce_pix) : ce_pix;
2017-10-22 01:22:56 +00:00
2021-03-03 09:35:46 +00:00
if(!GAMMA && HALF_DEPTH) begin
r <= {rt,rt};
g <= {gt,gt};
b <= {bt,bt};
end
else begin
r <= rt;
g <= gt;
b <= bt;
end
2017-10-22 01:22:56 +00:00
2021-03-03 09:35:46 +00:00
hde <= scandoubler ? ~hb_sd : ~hb_g;
vde <= scandoubler ? ~vb_sd : ~vb_g;
vs <= scandoubler ? vs_sd : vs_g;
hs <= scandoubler ? hs_sd : hs_g;
2017-10-22 01:22:56 +00:00
2021-03-03 09:35:46 +00:00
if(CE_PIXEL) begin
VGA_R <= r;
VGA_G <= g;
VGA_B <= b;
2017-10-22 01:22:56 +00:00
2021-03-03 09:35:46 +00:00
VGA_VS <= vs;
VGA_HS <= hs;
2020-05-10 18:35:08 +00:00
old_hde <= hde;
2021-03-03 09:35:46 +00:00
if(old_hde ^ hde) VGA_DE <= vde & hde;
2020-05-10 18:35:08 +00:00
end
end
2017-10-22 01:22:56 +00:00
endmodule