mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-01-23 18:56:46 +00:00
194 lines
4.5 KiB
Verilog
194 lines
4.5 KiB
Verilog
// A video pipeline for MiST. Just insert between the core video output and the VGA pins
|
|
// Provides an optional scandoubler, a rotateable OSD and (optional) RGb->YPbPr conversion
|
|
|
|
module mist_video
|
|
(
|
|
// master clock
|
|
// it should be 4x (or 2x) pixel clock for the scandoubler
|
|
input clk_sys,
|
|
|
|
// OSD SPI interface
|
|
input SPI_SCK,
|
|
input SPI_SS3,
|
|
input SPI_DI,
|
|
|
|
// scanlines (00-none 01-25% 10-50% 11-75%)
|
|
input [1:0] scanlines,
|
|
|
|
// non-scandoubled pixel clock divider 0 - clk_sys/4, 1 - clk_sys/2
|
|
input ce_divider,
|
|
|
|
// 0 = HVSync 31KHz, 1 = CSync 15KHz
|
|
input scandoubler_disable,
|
|
// disable csync without scandoubler
|
|
input no_csync,
|
|
// YPbPr always uses composite sync
|
|
input ypbpr,
|
|
// Rotate OSD [0] - rotate [1] - left or right
|
|
input [1:0] rotate,
|
|
// composite-like blending
|
|
input blend,
|
|
|
|
// video in
|
|
input [COLOR_DEPTH-1:0] R,
|
|
input [COLOR_DEPTH-1:0] G,
|
|
input [COLOR_DEPTH-1:0] B,
|
|
|
|
input HSync,
|
|
input VSync,
|
|
|
|
// MiST video output signals
|
|
output [5:0] VGA_R,
|
|
output [5:0] VGA_G,
|
|
output [5:0] VGA_B,
|
|
output VGA_VS,
|
|
output VGA_HS
|
|
);
|
|
|
|
parameter OSD_COLOR = 3'd4;
|
|
parameter OSD_X_OFFSET = 10'd0;
|
|
parameter OSD_Y_OFFSET = 10'd0;
|
|
parameter SD_HCNT_WIDTH = 9;
|
|
parameter COLOR_DEPTH = 6; // 1-6
|
|
parameter OSD_AUTO_CE = 1'b1;
|
|
|
|
wire [5:0] SD_R_O;
|
|
wire [5:0] SD_G_O;
|
|
wire [5:0] SD_B_O;
|
|
wire SD_HS_O;
|
|
wire SD_VS_O;
|
|
|
|
reg [5:0] R_full;
|
|
reg [5:0] G_full;
|
|
reg [5:0] B_full;
|
|
|
|
always @(*) begin
|
|
if (COLOR_DEPTH == 6) begin
|
|
R_full = R;
|
|
G_full = G;
|
|
B_full = B;
|
|
end else if (COLOR_DEPTH == 2) begin
|
|
R_full = {3{R}};
|
|
G_full = {3{G}};
|
|
B_full = {3{B}};
|
|
end else if (COLOR_DEPTH == 1) begin
|
|
R_full = {6{R}};
|
|
G_full = {6{G}};
|
|
B_full = {6{B}};
|
|
end else begin
|
|
R_full = { R, R[COLOR_DEPTH-1 -:(6-COLOR_DEPTH)] };
|
|
G_full = { G, G[COLOR_DEPTH-1 -:(6-COLOR_DEPTH)] };
|
|
B_full = { B, B[COLOR_DEPTH-1 -:(6-COLOR_DEPTH)] };
|
|
end
|
|
end
|
|
|
|
reg [1:0] i_div;
|
|
reg ce_x1, ce_x2;
|
|
|
|
always @(posedge clk_sys) begin
|
|
reg last_hs_in;
|
|
last_hs_in <= HSync;
|
|
if(last_hs_in & !HSync) begin
|
|
i_div <= 2'b00;
|
|
end else begin
|
|
i_div <= i_div + 2'd1;
|
|
end
|
|
end
|
|
|
|
always @(*) begin
|
|
if (!ce_divider) begin
|
|
ce_x1 = (i_div == 2'b01);
|
|
ce_x2 = i_div[0];
|
|
end else begin
|
|
ce_x1 = i_div[0];
|
|
ce_x2 = 1'b1;
|
|
end
|
|
end
|
|
|
|
scandoubler #(SD_HCNT_WIDTH, COLOR_DEPTH) scandoubler
|
|
(
|
|
.clk_sys ( clk_sys ),
|
|
.scanlines ( scanlines ),
|
|
.ce_x1 ( ce_x1 ),
|
|
.ce_x2 ( ce_x2 ),
|
|
.hs_in ( HSync ),
|
|
.vs_in ( VSync ),
|
|
.r_in ( R ),
|
|
.g_in ( G ),
|
|
.b_in ( B ),
|
|
.hs_out ( SD_HS_O ),
|
|
.vs_out ( SD_VS_O ),
|
|
.r_out ( SD_R_O ),
|
|
.g_out ( SD_G_O ),
|
|
.b_out ( SD_B_O )
|
|
);
|
|
|
|
wire [5:0] osd_r_o;
|
|
wire [5:0] osd_g_o;
|
|
wire [5:0] osd_b_o;
|
|
|
|
osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR, OSD_AUTO_CE) osd
|
|
(
|
|
.clk_sys ( clk_sys ),
|
|
.rotate ( rotate ),
|
|
.ce ( scandoubler_disable ? ce_x1 : ce_x2 ),
|
|
.SPI_DI ( SPI_DI ),
|
|
.SPI_SCK ( SPI_SCK ),
|
|
.SPI_SS3 ( SPI_SS3 ),
|
|
.R_in ( scandoubler_disable ? R_full : SD_R_O ),
|
|
.G_in ( scandoubler_disable ? G_full : SD_G_O ),
|
|
.B_in ( scandoubler_disable ? B_full : SD_B_O ),
|
|
.HSync ( scandoubler_disable ? HSync : SD_HS_O ),
|
|
.VSync ( scandoubler_disable ? VSync : SD_VS_O ),
|
|
.R_out ( osd_r_o ),
|
|
.G_out ( osd_g_o ),
|
|
.B_out ( osd_b_o )
|
|
);
|
|
|
|
wire [5:0] cofi_r, cofi_g, cofi_b;
|
|
wire cofi_hs, cofi_vs;
|
|
|
|
cofi cofi (
|
|
.clk ( clk_sys ),
|
|
.pix_ce ( scandoubler_disable ? ce_x1 : ce_x2 ),
|
|
.enable ( blend ),
|
|
.hblank ( ~(scandoubler_disable ? HSync : SD_HS_O) ),
|
|
.hs ( scandoubler_disable ? HSync : SD_HS_O ),
|
|
.vs ( scandoubler_disable ? VSync : SD_VS_O ),
|
|
.red ( osd_r_o ),
|
|
.green ( osd_g_o ),
|
|
.blue ( osd_b_o ),
|
|
.hs_out ( cofi_hs ),
|
|
.vs_out ( cofi_vs ),
|
|
.red_out ( cofi_r ),
|
|
.green_out( cofi_g ),
|
|
.blue_out( cofi_b )
|
|
);
|
|
|
|
wire [5:0] y, pb, pr;
|
|
|
|
rgb2ypbpr rgb2ypbpr
|
|
(
|
|
.red ( cofi_r ),
|
|
.green ( cofi_g ),
|
|
.blue ( cofi_b ),
|
|
.y ( y ),
|
|
.pb ( pb ),
|
|
.pr ( pr )
|
|
);
|
|
|
|
assign VGA_R = ypbpr?pr:cofi_r;
|
|
assign VGA_G = ypbpr? y:cofi_g;
|
|
assign VGA_B = ypbpr?pb:cofi_b;
|
|
|
|
wire cs = ~(cofi_hs ^ cofi_vs);
|
|
wire hs = cofi_hs;
|
|
wire vs = cofi_vs;
|
|
|
|
// a minimig vga->scart cable expects a composite sync signal on the VGA_HS output.
|
|
// and VCC on VGA_VS (to switch into rgb mode)
|
|
assign VGA_HS = ((~no_csync & scandoubler_disable) || ypbpr)? cs : hs;
|
|
assign VGA_VS = ((~no_csync & scandoubler_disable) || ypbpr)? 1'b1 : vs;
|
|
|
|
endmodule
|