mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-18 23:01:37 +03:00
Update sys. HV-Integer scale. Vertical crop.
This commit is contained in:
42
TSConf.sv
42
TSConf.sv
@ -39,8 +39,9 @@ module emu
|
|||||||
output CE_PIXEL,
|
output CE_PIXEL,
|
||||||
|
|
||||||
//Video aspect ratio for HDMI. Most retro systems have ratio 4:3.
|
//Video aspect ratio for HDMI. Most retro systems have ratio 4:3.
|
||||||
output [11:0] VIDEO_ARX,
|
//if VIDEO_ARX[12] or VIDEO_ARY[12] is set then [11:0] contains scaled size instead of aspect ratio.
|
||||||
output [11:0] VIDEO_ARY,
|
output [12:0] VIDEO_ARX,
|
||||||
|
output [12:0] VIDEO_ARY,
|
||||||
|
|
||||||
output [7:0] VGA_R,
|
output [7:0] VGA_R,
|
||||||
output [7:0] VGA_G,
|
output [7:0] VGA_G,
|
||||||
@ -52,6 +53,9 @@ module emu
|
|||||||
output [1:0] VGA_SL,
|
output [1:0] VGA_SL,
|
||||||
output VGA_SCALER, // Force VGA scaler
|
output VGA_SCALER, // Force VGA scaler
|
||||||
|
|
||||||
|
input [11:0] HDMI_WIDTH,
|
||||||
|
input [11:0] HDMI_HEIGHT,
|
||||||
|
|
||||||
`ifdef USE_FB
|
`ifdef USE_FB
|
||||||
// Use framebuffer in DDRAM (USE_FB=1 in qsf)
|
// Use framebuffer in DDRAM (USE_FB=1 in qsf)
|
||||||
// FB_FORMAT:
|
// FB_FORMAT:
|
||||||
@ -181,9 +185,23 @@ assign BUTTONS = 0;
|
|||||||
assign VGA_SCALER= 0;
|
assign VGA_SCALER= 0;
|
||||||
|
|
||||||
wire [1:0] ar = status[33:32];
|
wire [1:0] ar = status[33:32];
|
||||||
|
wire vcrop_en = status[34];
|
||||||
|
reg en270p;
|
||||||
|
always @(posedge CLK_VIDEO) begin
|
||||||
|
en270p <= ((HDMI_WIDTH == 1920) && (HDMI_HEIGHT == 1080) && !forced_scandoubler && !scale);
|
||||||
|
end
|
||||||
|
|
||||||
assign VIDEO_ARX = (!ar) ? 12'd4 : (ar - 1'd1);
|
wire vga_de;
|
||||||
assign VIDEO_ARY = (!ar) ? 12'd3 : 12'd0;
|
video_freak video_freak
|
||||||
|
(
|
||||||
|
.*,
|
||||||
|
.VGA_DE_IN(vga_de),
|
||||||
|
.ARX((!ar) ? 12'd4 : (ar - 1'd1)),
|
||||||
|
.ARY((!ar) ? 12'd3 : 12'd0),
|
||||||
|
.CROP_SIZE((en270p & vcrop_en) ? 10'd270 : 10'd0),
|
||||||
|
.CROP_OFF(0),
|
||||||
|
.SCALE(status[36:35])
|
||||||
|
);
|
||||||
|
|
||||||
`include "build_id.v"
|
`include "build_id.v"
|
||||||
localparam CONF_STR = {
|
localparam CONF_STR = {
|
||||||
@ -193,6 +211,9 @@ localparam CONF_STR = {
|
|||||||
"o01,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];",
|
"o01,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];",
|
||||||
"O12,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
|
"O12,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
|
||||||
"-;",
|
"-;",
|
||||||
|
"d0o2,Vertical Crop,Disabled,270p(5x);",
|
||||||
|
"o34,Scale,Normal,V-Integer,Narrower HV-Integer,Wider HV-Integer;",
|
||||||
|
"-;",
|
||||||
"O34,Stereo mix,None,25%,50%,100%;",
|
"O34,Stereo mix,None,25%,50%,100%;",
|
||||||
"OST,General Sound,512KB,1MB,2MB;",
|
"OST,General Sound,512KB,1MB,2MB;",
|
||||||
"-;",
|
"-;",
|
||||||
@ -231,13 +252,12 @@ assign CMOSCfg[27:25]= status[27:25] + 1'd1;
|
|||||||
|
|
||||||
//////////////////// CLOCKS ///////////////////
|
//////////////////// CLOCKS ///////////////////
|
||||||
wire clk_sys;
|
wire clk_sys;
|
||||||
wire clk_vid;
|
|
||||||
|
|
||||||
pll pll
|
pll pll
|
||||||
(
|
(
|
||||||
.refclk(CLK_50M),
|
.refclk(CLK_50M),
|
||||||
.outclk_0(clk_sys),
|
.outclk_0(clk_sys),
|
||||||
.outclk_1(clk_vid)
|
.outclk_1(CLK_VIDEO)
|
||||||
);
|
);
|
||||||
|
|
||||||
reg ce_28m;
|
reg ce_28m;
|
||||||
@ -297,6 +317,7 @@ hps_io #(.STRLEN($size(CONF_STR)>>3)) hps_io
|
|||||||
|
|
||||||
.buttons(buttons),
|
.buttons(buttons),
|
||||||
.status(status),
|
.status(status),
|
||||||
|
.status_menumask({en270p}),
|
||||||
.forced_scandoubler(forced_scandoubler),
|
.forced_scandoubler(forced_scandoubler),
|
||||||
.gamma_bus(gamma_bus),
|
.gamma_bus(gamma_bus),
|
||||||
|
|
||||||
@ -425,15 +446,13 @@ assign AUDIO_S = 1;
|
|||||||
assign AUDIO_MIX = status[4:3];
|
assign AUDIO_MIX = status[4:3];
|
||||||
|
|
||||||
reg ce_pix;
|
reg ce_pix;
|
||||||
always @(posedge clk_vid) begin
|
always @(posedge CLK_VIDEO) begin
|
||||||
reg old_ce;
|
reg old_ce;
|
||||||
|
|
||||||
old_ce <= ce_vid;
|
old_ce <= ce_vid;
|
||||||
ce_pix <= ~old_ce & ce_vid;
|
ce_pix <= ~old_ce & ce_vid;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign CLK_VIDEO = clk_vid;
|
|
||||||
|
|
||||||
reg VSync, HSync;
|
reg VSync, HSync;
|
||||||
always @(posedge CLK_VIDEO) begin
|
always @(posedge CLK_VIDEO) begin
|
||||||
HSync <= HS;
|
HSync <= HS;
|
||||||
@ -447,12 +466,9 @@ assign VGA_SL = {scale == 3, scale == 2};
|
|||||||
video_mixer #(.GAMMA(1)) video_mixer
|
video_mixer #(.GAMMA(1)) video_mixer
|
||||||
(
|
(
|
||||||
.*,
|
.*,
|
||||||
.ce_pix_out(CE_PIXEL),
|
|
||||||
|
|
||||||
.scanlines(0),
|
|
||||||
.scandoubler(scale || forced_scandoubler),
|
.scandoubler(scale || forced_scandoubler),
|
||||||
.hq2x(scale==1),
|
.hq2x(scale==1),
|
||||||
.mono(0)
|
.VGA_DE(vga_de)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,9 +112,9 @@ wire scandoubler = fx || forced_scandoubler;
|
|||||||
|
|
||||||
video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer
|
video_mixer #(.LINE_LENGTH(WIDTH+4), .HALF_DEPTH(DW!=24), .GAMMA(GAMMA)) video_mixer
|
||||||
(
|
(
|
||||||
.clk_vid(CLK_VIDEO),
|
.CLK_VIDEO(CLK_VIDEO),
|
||||||
.ce_pix(CE),
|
.ce_pix(CE),
|
||||||
.ce_pix_out(CE_PIXEL),
|
.CE_PIXEL(CE_PIXEL),
|
||||||
|
|
||||||
.scandoubler(scandoubler),
|
.scandoubler(scandoubler),
|
||||||
.hq2x(fx==1),
|
.hq2x(fx==1),
|
||||||
|
@ -429,7 +429,7 @@ ARCHITECTURE rtl OF ascal IS
|
|||||||
SIGNAL o_readdataack,o_readdataack_sync,o_readdataack_sync2 : std_logic;
|
SIGNAL o_readdataack,o_readdataack_sync,o_readdataack_sync2 : std_logic;
|
||||||
SIGNAL o_copyv : unsigned(0 TO 8);
|
SIGNAL o_copyv : unsigned(0 TO 8);
|
||||||
SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address
|
SIGNAL o_adrs : unsigned(31 DOWNTO 0); -- Avalon address
|
||||||
SIGNAL o_adrs_pre : natural RANGE 0 TO 2**23-1;
|
SIGNAL o_adrs_pre : natural RANGE 0 TO 2**24-1;
|
||||||
SIGNAL o_stride : unsigned(13 DOWNTO 0);
|
SIGNAL o_stride : unsigned(13 DOWNTO 0);
|
||||||
SIGNAL o_adrsa,o_adrsb,o_rline : std_logic;
|
SIGNAL o_adrsa,o_adrsb,o_rline : std_logic;
|
||||||
SIGNAL o_ad,o_ad1,o_ad2,o_ad3 : natural RANGE 0 TO 2*BLEN-1;
|
SIGNAL o_ad,o_ad1,o_ad2,o_ad3 : natural RANGE 0 TO 2*BLEN-1;
|
||||||
@ -1519,7 +1519,7 @@ BEGIN
|
|||||||
avl_read_sync<=o_read; -- <ASYNC>
|
avl_read_sync<=o_read; -- <ASYNC>
|
||||||
avl_read_sync2<=avl_read_sync;
|
avl_read_sync2<=avl_read_sync;
|
||||||
avl_read_pulse<=avl_read_sync XOR avl_read_sync2;
|
avl_read_pulse<=avl_read_sync XOR avl_read_sync2;
|
||||||
avl_radrs <=o_adrs AND (RAMSIZE - 1); -- <ASYNC>
|
avl_radrs <=o_adrs; -- <ASYNC>
|
||||||
avl_rline <=o_rline; -- <ASYNC>
|
avl_rline <=o_rline; -- <ASYNC>
|
||||||
|
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
109
sys/math.sv
Normal file
109
sys/math.sv
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
// result = num/div
|
||||||
|
module sys_udiv
|
||||||
|
#(
|
||||||
|
parameter NB_NUM,
|
||||||
|
parameter NB_DIV
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input clk,
|
||||||
|
input start,
|
||||||
|
output busy,
|
||||||
|
|
||||||
|
input [NB_NUM-1:0] num,
|
||||||
|
input [NB_DIV-1:0] div,
|
||||||
|
output reg [NB_NUM-1:0] result,
|
||||||
|
output reg [NB_DIV-1:0] remainder
|
||||||
|
);
|
||||||
|
|
||||||
|
reg run;
|
||||||
|
assign busy = run;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
reg [5:0] cpt;
|
||||||
|
reg [NB_NUM+NB_DIV+1:0] rem;
|
||||||
|
|
||||||
|
if (start) begin
|
||||||
|
cpt <= 0;
|
||||||
|
run <= 1;
|
||||||
|
rem <= num;
|
||||||
|
end
|
||||||
|
else if (run) begin
|
||||||
|
cpt <= cpt + 1'd1;
|
||||||
|
run <= (cpt != NB_NUM + 1'd1);
|
||||||
|
remainder <= rem[NB_NUM+NB_DIV:NB_NUM+1];
|
||||||
|
if (!rem[NB_DIV + NB_NUM + 1'd1])
|
||||||
|
rem <= {rem[NB_DIV+NB_NUM:0] - (div << NB_NUM),1'b0};
|
||||||
|
else
|
||||||
|
rem <= {rem[NB_DIV+NB_NUM:0] + (div << NB_NUM),1'b0};
|
||||||
|
result <= {result[NB_NUM-2:0], !rem[NB_DIV + NB_NUM + 1'd1]};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// result = mul1*mul2
|
||||||
|
module sys_umul
|
||||||
|
#(
|
||||||
|
parameter NB_MUL1,
|
||||||
|
parameter NB_MUL2
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input clk,
|
||||||
|
input start,
|
||||||
|
output busy,
|
||||||
|
|
||||||
|
input [NB_MUL1-1:0] mul1,
|
||||||
|
input [NB_MUL2-1:0] mul2,
|
||||||
|
output reg [NB_MUL1+NB_MUL2-1:0] result
|
||||||
|
);
|
||||||
|
|
||||||
|
reg run;
|
||||||
|
assign busy = run;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
reg [NB_MUL1+NB_MUL2-1:0] add;
|
||||||
|
reg [NB_MUL2-1:0] map;
|
||||||
|
|
||||||
|
if (start) begin
|
||||||
|
run <= 1;
|
||||||
|
result <= 0;
|
||||||
|
add <= mul1;
|
||||||
|
map <= mul2;
|
||||||
|
end
|
||||||
|
else if (run) begin
|
||||||
|
if(!map) run <= 0;
|
||||||
|
if(map[0]) result <= result + add;
|
||||||
|
add <= add << 1;
|
||||||
|
map <= map >> 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// result = (mul1*mul2)/div
|
||||||
|
module sys_umuldiv
|
||||||
|
#(
|
||||||
|
parameter NB_MUL1,
|
||||||
|
parameter NB_MUL2,
|
||||||
|
parameter NB_DIV
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input clk,
|
||||||
|
input start,
|
||||||
|
output busy,
|
||||||
|
|
||||||
|
input [NB_MUL1-1:0] mul1,
|
||||||
|
input [NB_MUL2-1:0] mul2,
|
||||||
|
input [NB_DIV-1:0] div,
|
||||||
|
output [NB_MUL1+NB_MUL2-1:0] result,
|
||||||
|
output [NB_DIV-1:0] remainder
|
||||||
|
);
|
||||||
|
|
||||||
|
wire mul_run;
|
||||||
|
wire [NB_MUL1+NB_MUL2-1:0] mul_res;
|
||||||
|
sys_umul #(NB_MUL1,NB_MUL2) umul(clk,start,mul_run,mul1,mul2,mul_res);
|
||||||
|
|
||||||
|
sys_udiv #(NB_MUL1+NB_MUL2,NB_DIV) udiv(clk,start|mul_run,busy,mul_res,div,result,remainder);
|
||||||
|
|
||||||
|
endmodule
|
@ -2,7 +2,7 @@
|
|||||||
// scandoubler.v
|
// scandoubler.v
|
||||||
//
|
//
|
||||||
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
|
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
|
||||||
// Copyright (c) 2017-2019 Sorgelig
|
// Copyright (c) 2017-2021 Alexey Melnikov
|
||||||
//
|
//
|
||||||
// This source file is free software: you can redistribute it and/or modify
|
// This source file is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published
|
// it under the terms of the GNU General Public License as published
|
||||||
@ -23,23 +23,20 @@ module scandoubler #(parameter LENGTH, parameter HALF_DEPTH)
|
|||||||
(
|
(
|
||||||
// system interface
|
// system interface
|
||||||
input clk_vid,
|
input clk_vid,
|
||||||
input ce_pix,
|
|
||||||
output ce_pix_out,
|
|
||||||
|
|
||||||
input hq2x,
|
input hq2x,
|
||||||
|
|
||||||
// shifter video interface
|
// shifter video interface
|
||||||
|
input ce_pix,
|
||||||
input hs_in,
|
input hs_in,
|
||||||
input vs_in,
|
input vs_in,
|
||||||
input hb_in,
|
input hb_in,
|
||||||
input vb_in,
|
input vb_in,
|
||||||
|
|
||||||
input [DWIDTH:0] r_in,
|
input [DWIDTH:0] r_in,
|
||||||
input [DWIDTH:0] g_in,
|
input [DWIDTH:0] g_in,
|
||||||
input [DWIDTH:0] b_in,
|
input [DWIDTH:0] b_in,
|
||||||
input mono,
|
|
||||||
|
|
||||||
// output interface
|
// output interface
|
||||||
|
output ce_pix_out,
|
||||||
output reg hs_out,
|
output reg hs_out,
|
||||||
output vs_out,
|
output vs_out,
|
||||||
output hb_out,
|
output hb_out,
|
||||||
@ -109,7 +106,6 @@ Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x
|
|||||||
|
|
||||||
.ce_in(ce_x4i),
|
.ce_in(ce_x4i),
|
||||||
.inputpixel({b_d,g_d,r_d}),
|
.inputpixel({b_d,g_d,r_d}),
|
||||||
.mono(mono),
|
|
||||||
.disable_hq2x(~hq2x),
|
.disable_hq2x(~hq2x),
|
||||||
.reset_frame(vb_in),
|
.reset_frame(vb_in),
|
||||||
.reset_line(req_line_reset),
|
.reset_line(req_line_reset),
|
||||||
|
27
sys/spdif.v
27
sys/spdif.v
@ -67,7 +67,7 @@ reg spdif_out_q;
|
|||||||
|
|
||||||
reg [5:0] parity_count_q;
|
reg [5:0] parity_count_q;
|
||||||
|
|
||||||
reg channel_status_bit;
|
reg channel_status_bit_q;
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// Subframe Counter
|
// Subframe Counter
|
||||||
@ -144,19 +144,20 @@ assign subframe_w[28] = 1'b0; // Valid
|
|||||||
assign subframe_w[29] = 1'b0;
|
assign subframe_w[29] = 1'b0;
|
||||||
|
|
||||||
// Timeslots 30 = Channel status bit
|
// Timeslots 30 = Channel status bit
|
||||||
assign subframe_w[30] = channel_status_bit ; //was constant 1'b0 enabling copy-bit;
|
assign subframe_w[30] = channel_status_bit_q ; //was constant 1'b0 enabling copy-bit;
|
||||||
|
|
||||||
// Timeslots 31 = Even Parity bit (31:4)
|
// Timeslots 31 = Even Parity bit (31:4)
|
||||||
assign subframe_w[31] = 1'b0;
|
assign subframe_w[31] = 1'b0;
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// Preamble
|
// Preamble and Channel status bit
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
localparam PREAMBLE_Z = 8'b00010111; // "B" channel A data at start of block
|
localparam PREAMBLE_Z = 8'b00010111; // "B" channel A data at start of block
|
||||||
localparam PREAMBLE_Y = 8'b00100111; // "W" channel B data
|
localparam PREAMBLE_Y = 8'b00100111; // "W" channel B data
|
||||||
localparam PREAMBLE_X = 8'b01000111; // "M" channel A data not at start of block
|
localparam PREAMBLE_X = 8'b01000111; // "M" channel A data not at start of block
|
||||||
|
|
||||||
reg [7:0] preamble_r;
|
reg [7:0] preamble_r;
|
||||||
|
reg channel_status_bit_r;
|
||||||
|
|
||||||
always @ *
|
always @ *
|
||||||
begin
|
begin
|
||||||
@ -172,20 +173,28 @@ begin
|
|||||||
preamble_r = PREAMBLE_X; // X(M)
|
preamble_r = PREAMBLE_X; // X(M)
|
||||||
|
|
||||||
if (subframe_count_q[8:1] == 8'd2) // frame 2 => subframes 4 and 5 => 0 = copy inhibited, 1 = copy permitted
|
if (subframe_count_q[8:1] == 8'd2) // frame 2 => subframes 4 and 5 => 0 = copy inhibited, 1 = copy permitted
|
||||||
channel_status_bit = 1'b1;
|
channel_status_bit_r = 1'b1;
|
||||||
else if (subframe_count_q[8:1] == 8'd15) // frame 15 => 0 = no indication, 1 = original media
|
else if (subframe_count_q[8:1] == 8'd15) // frame 15 => 0 = no indication, 1 = original media
|
||||||
channel_status_bit = 1'b1;
|
channel_status_bit_r = 1'b1;
|
||||||
else if (subframe_count_q[8:1] == 8'd25) // frame 24 to 27 => sample frequency, 0100 = 48kHz, 0000 = 44kHz (l2r)
|
else if (subframe_count_q[8:1] == 8'd25) // frame 24 to 27 => sample frequency, 0100 = 48kHz, 0000 = 44kHz (l2r)
|
||||||
channel_status_bit = 1'b1;
|
channel_status_bit_r = 1'b1;
|
||||||
else
|
else
|
||||||
channel_status_bit = 1'b0; // everything else defaults to 0
|
channel_status_bit_r = 1'b0; // everything else defaults to 0
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (posedge rst_i or posedge clk_i )
|
always @ (posedge rst_i or posedge clk_i )
|
||||||
if (rst_i == 1'b1)
|
begin
|
||||||
|
if (rst_i == 1'b1)
|
||||||
|
begin
|
||||||
preamble_q <= 8'h00;
|
preamble_q <= 8'h00;
|
||||||
else if (load_subframe_q)
|
channel_status_bit_q <= 1'b0;
|
||||||
|
end
|
||||||
|
else if (load_subframe_q)
|
||||||
|
begin
|
||||||
preamble_q <= preamble_r;
|
preamble_q <= preamble_r;
|
||||||
|
channel_status_bit_q <= channel_status_bit_r;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
// Parity Counter
|
// Parity Counter
|
||||||
|
@ -3,12 +3,14 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) s
|
|||||||
set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) sys_top.sdc ]
|
set_global_assignment -name SDC_FILE [file join $::quartus(qip_path) sys_top.sdc ]
|
||||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ]
|
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) ascal.vhd ]
|
||||||
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ]
|
set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) pll_hdmi_adj.vhd ]
|
||||||
|
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) math.sv ]
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ]
|
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ]
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ]
|
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ]
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) gamma_corr.sv ]
|
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) gamma_corr.sv ]
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ]
|
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ]
|
||||||
|
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_freak.sv ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) arcade_video.v ]
|
||||||
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ]
|
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) osd.v ]
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ]
|
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) vga_out.sv ]
|
||||||
|
@ -32,7 +32,7 @@ set_false_path -to {cfg[*]}
|
|||||||
set_false_path -from {cfg[*]}
|
set_false_path -from {cfg[*]}
|
||||||
set_false_path -from {VSET[*]}
|
set_false_path -from {VSET[*]}
|
||||||
set_false_path -to {wcalc[*] hcalc[*]}
|
set_false_path -to {wcalc[*] hcalc[*]}
|
||||||
set_false_path -to {width[*] height[*]}
|
set_false_path -to {hdmi_width[*] hdmi_height[*]}
|
||||||
|
|
||||||
set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2
|
set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2
|
||||||
set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1
|
set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1
|
||||||
@ -62,3 +62,8 @@ set_false_path -from {ascal|o_ivsize*}
|
|||||||
set_false_path -from {ascal|o_format*}
|
set_false_path -from {ascal|o_format*}
|
||||||
set_false_path -from {ascal|o_hdown}
|
set_false_path -from {ascal|o_hdown}
|
||||||
set_false_path -from {ascal|o_vdown}
|
set_false_path -from {ascal|o_vdown}
|
||||||
|
set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax*}
|
||||||
|
set_false_path -from {ascal|o_hdisp* ascal|o_vdisp*}
|
||||||
|
set_false_path -from {ascal|o_htotal* ascal|o_vtotal*}
|
||||||
|
set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*}
|
||||||
|
set_false_path -from {ascal|o_hsize* ascal|o_vsize*}
|
||||||
|
143
sys/sys_top.v
143
sys/sys_top.v
@ -316,7 +316,7 @@ reg [6:0] coef_addr;
|
|||||||
reg [8:0] coef_data;
|
reg [8:0] coef_data;
|
||||||
reg coef_wr = 0;
|
reg coef_wr = 0;
|
||||||
|
|
||||||
wire[11:0] ARX, ARY;
|
wire[12:0] ARX, ARY;
|
||||||
reg [11:0] VSET = 0, HSET = 0;
|
reg [11:0] VSET = 0, HSET = 0;
|
||||||
reg FREESCALE = 0;
|
reg FREESCALE = 0;
|
||||||
reg [2:0] scaler_flt;
|
reg [2:0] scaler_flt;
|
||||||
@ -337,10 +337,10 @@ reg [23:0] acy0 = -24'd6216759;
|
|||||||
reg [23:0] acy1 = 24'd6143386;
|
reg [23:0] acy1 = 24'd6143386;
|
||||||
reg [23:0] acy2 = -24'd2023767;
|
reg [23:0] acy2 = -24'd2023767;
|
||||||
reg areset = 0;
|
reg areset = 0;
|
||||||
reg [11:0] arc1x = 0;
|
reg [12:0] arc1x = 0;
|
||||||
reg [11:0] arc1y = 0;
|
reg [12:0] arc1y = 0;
|
||||||
reg [11:0] arc2x = 0;
|
reg [12:0] arc2x = 0;
|
||||||
reg [11:0] arc2y = 0;
|
reg [12:0] arc2y = 0;
|
||||||
|
|
||||||
always@(posedge clk_sys) begin
|
always@(posedge clk_sys) begin
|
||||||
reg [7:0] cmd;
|
reg [7:0] cmd;
|
||||||
@ -430,6 +430,7 @@ always@(posedge clk_sys) begin
|
|||||||
6: LFB_HMAX <= io_din[11:0];
|
6: LFB_HMAX <= io_din[11:0];
|
||||||
7: LFB_VMIN <= io_din[11:0];
|
7: LFB_VMIN <= io_din[11:0];
|
||||||
8: LFB_VMAX <= io_din[11:0];
|
8: LFB_VMAX <= io_din[11:0];
|
||||||
|
9: LFB_STRIDE <= io_din[13:0];
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
if(cmd == 'h25) {led_overtake, led_state} <= io_din;
|
if(cmd == 'h25) {led_overtake, led_state} <= io_din;
|
||||||
@ -462,10 +463,10 @@ always@(posedge clk_sys) begin
|
|||||||
if(cmd == 'h3A) begin
|
if(cmd == 'h3A) begin
|
||||||
cnt <= cnt + 1'd1;
|
cnt <= cnt + 1'd1;
|
||||||
case(cnt[3:0])
|
case(cnt[3:0])
|
||||||
0: arc1x <= io_din[11:0];
|
0: arc1x <= io_din[12:0];
|
||||||
1: arc1y <= io_din[11:0];
|
1: arc1y <= io_din[12:0];
|
||||||
2: arc2x <= io_din[11:0];
|
2: arc2x <= io_din[12:0];
|
||||||
3: arc2y <= io_din[11:0];
|
3: arc2y <= io_din[12:0];
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -747,6 +748,7 @@ reg [11:0] LFB_HMAX = 0;
|
|||||||
reg [11:0] LFB_VMIN = 0;
|
reg [11:0] LFB_VMIN = 0;
|
||||||
reg [11:0] LFB_VMAX = 0;
|
reg [11:0] LFB_VMAX = 0;
|
||||||
reg [31:0] LFB_BASE = 0;
|
reg [31:0] LFB_BASE = 0;
|
||||||
|
reg [13:0] LFB_STRIDE = 0;
|
||||||
|
|
||||||
reg FB_EN = 0;
|
reg FB_EN = 0;
|
||||||
reg [5:0] FB_FMT = 0;
|
reg [5:0] FB_FMT = 0;
|
||||||
@ -762,7 +764,7 @@ always @(posedge clk_sys) begin
|
|||||||
FB_WIDTH <= LFB_WIDTH;
|
FB_WIDTH <= LFB_WIDTH;
|
||||||
FB_HEIGHT <= LFB_HEIGHT;
|
FB_HEIGHT <= LFB_HEIGHT;
|
||||||
FB_BASE <= LFB_BASE;
|
FB_BASE <= LFB_BASE;
|
||||||
FB_STRIDE <= 0;
|
FB_STRIDE <= LFB_STRIDE;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
FB_FMT <= fb_fmt;
|
FB_FMT <= fb_fmt;
|
||||||
@ -778,74 +780,123 @@ reg fb_vbl;
|
|||||||
always @(posedge clk_vid) fb_vbl <= hdmi_vbl;
|
always @(posedge clk_vid) fb_vbl <= hdmi_vbl;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
reg ar_md_start;
|
||||||
|
wire ar_md_busy;
|
||||||
|
reg [11:0] ar_md_mul1, ar_md_mul2, ar_md_div;
|
||||||
|
wire [11:0] ar_md_res;
|
||||||
|
|
||||||
|
sys_umuldiv #(12,12,12) ar_muldiv
|
||||||
|
(
|
||||||
|
.clk(clk_vid),
|
||||||
|
.start(ar_md_start),
|
||||||
|
.busy(ar_md_busy),
|
||||||
|
|
||||||
|
.mul1(ar_md_mul1),
|
||||||
|
.mul2(ar_md_mul2),
|
||||||
|
.div(ar_md_div),
|
||||||
|
.result(ar_md_res)
|
||||||
|
);
|
||||||
|
|
||||||
reg [11:0] hmin;
|
reg [11:0] hmin;
|
||||||
reg [11:0] hmax;
|
reg [11:0] hmax;
|
||||||
reg [11:0] vmin;
|
reg [11:0] vmin;
|
||||||
reg [11:0] vmax;
|
reg [11:0] vmax;
|
||||||
|
reg [11:0] hdmi_height;
|
||||||
|
reg [11:0] hdmi_width;
|
||||||
|
|
||||||
always @(posedge clk_vid) begin
|
always @(posedge clk_vid) begin
|
||||||
reg [31:0] wcalc;
|
reg [11:0] hmini,hmaxi,vmini,vmaxi;
|
||||||
reg [31:0] hcalc;
|
reg [11:0] wcalc,videow,arx;
|
||||||
|
reg [11:0] hcalc,videoh,ary;
|
||||||
reg [2:0] state;
|
reg [2:0] state;
|
||||||
reg [11:0] videow;
|
reg xy;
|
||||||
reg [11:0] videoh;
|
|
||||||
reg [11:0] height;
|
|
||||||
reg [11:0] width;
|
|
||||||
reg [11:0] arx;
|
|
||||||
reg [11:0] ary;
|
|
||||||
|
|
||||||
height <= (VSET && (VSET < HEIGHT)) ? VSET : HEIGHT;
|
hdmi_height <= (VSET && (VSET < HEIGHT)) ? VSET : HEIGHT;
|
||||||
width <= (HSET && (HSET < WIDTH)) ? HSET : WIDTH;
|
hdmi_width <= (HSET && (HSET < WIDTH)) ? HSET : WIDTH;
|
||||||
|
|
||||||
if(!ARY) begin
|
if(!ARY) begin
|
||||||
if(ARX == 1) begin
|
if(ARX == 1) begin
|
||||||
arx <= arc1x;
|
arx <= arc1x[11:0];
|
||||||
ary <= arc1y;
|
ary <= arc1y[11:0];
|
||||||
|
xy <= arc1x[12] | arc1y[12];
|
||||||
end
|
end
|
||||||
else if(ARX == 2) begin
|
else if(ARX == 2) begin
|
||||||
arx <= arc2x;
|
arx <= arc2x[11:0];
|
||||||
ary <= arc2y;
|
ary <= arc2y[11:0];
|
||||||
|
xy <= arc2x[12] | arc2y[12];
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
arx <= 0;
|
arx <= 0;
|
||||||
ary <= 0;
|
ary <= 0;
|
||||||
|
xy <= 0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
arx <= ARX;
|
arx <= ARX[11:0];
|
||||||
ary <= ARY;
|
ary <= ARY[11:0];
|
||||||
|
xy <= ARX[12] | ARY[12];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ar_md_start <= 0;
|
||||||
state <= state + 1'd1;
|
state <= state + 1'd1;
|
||||||
case(state)
|
case(state)
|
||||||
0: if(LFB_EN) begin
|
0: if(LFB_EN) begin
|
||||||
hmin <= LFB_HMIN;
|
hmini <= LFB_HMIN;
|
||||||
vmin <= LFB_VMIN;
|
vmini <= LFB_VMIN;
|
||||||
hmax <= LFB_HMAX;
|
hmaxi <= LFB_HMAX;
|
||||||
vmax <= LFB_VMAX;
|
vmaxi <= LFB_VMAX;
|
||||||
state<= 0;
|
state <= 0;
|
||||||
end
|
end
|
||||||
else if(FREESCALE || !arx || !ary) begin
|
else if(FREESCALE || !arx || !ary) begin
|
||||||
wcalc <= width;
|
wcalc <= hdmi_width;
|
||||||
hcalc <= height;
|
hcalc <= hdmi_height;
|
||||||
|
state <= 6;
|
||||||
end
|
end
|
||||||
else begin
|
else if(xy) begin
|
||||||
wcalc <= (height*arx)/ary;
|
wcalc <= arx;
|
||||||
hcalc <= (width*ary)/arx;
|
hcalc <= ary;
|
||||||
|
state <= 6;
|
||||||
|
end
|
||||||
|
|
||||||
|
1: begin
|
||||||
|
ar_md_mul1 <= hdmi_height;
|
||||||
|
ar_md_mul2 <= arx;
|
||||||
|
ar_md_div <= ary;
|
||||||
|
ar_md_start<= 1;
|
||||||
|
end
|
||||||
|
2: begin
|
||||||
|
wcalc <= ar_md_res;
|
||||||
|
if(ar_md_start | ar_md_busy) state <= 2;
|
||||||
|
end
|
||||||
|
|
||||||
|
3: begin
|
||||||
|
ar_md_mul1 <= hdmi_width;
|
||||||
|
ar_md_mul2 <= ary;
|
||||||
|
ar_md_div <= arx;
|
||||||
|
ar_md_start<= 1;
|
||||||
|
end
|
||||||
|
4: begin
|
||||||
|
hcalc <= ar_md_res;
|
||||||
|
if(ar_md_start | ar_md_busy) state <= 4;
|
||||||
end
|
end
|
||||||
|
|
||||||
6: begin
|
6: begin
|
||||||
videow <= (wcalc > width) ? width : wcalc[11:0];
|
videow <= (wcalc > hdmi_width) ? hdmi_width : wcalc[11:0];
|
||||||
videoh <= (hcalc > height) ? height : hcalc[11:0];
|
videoh <= (hcalc > hdmi_height) ? hdmi_height : hcalc[11:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
7: begin
|
7: begin
|
||||||
hmin <= ((WIDTH - videow)>>1);
|
hmini <= ((WIDTH - videow)>>1);
|
||||||
hmax <= ((WIDTH - videow)>>1) + videow - 1'd1;
|
hmaxi <= ((WIDTH - videow)>>1) + videow - 1'd1;
|
||||||
vmin <= ((HEIGHT - videoh)>>1);
|
vmini <= ((HEIGHT - videoh)>>1);
|
||||||
vmax <= ((HEIGHT - videoh)>>1) + videoh - 1'd1;
|
vmaxi <= ((HEIGHT - videoh)>>1) + videoh - 1'd1;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
hmin <= hmini;
|
||||||
|
hmax <= hmaxi;
|
||||||
|
vmin <= vmini;
|
||||||
|
vmax <= vmaxi;
|
||||||
end
|
end
|
||||||
|
|
||||||
`ifndef DEBUG_NOHDMI
|
`ifndef DEBUG_NOHDMI
|
||||||
@ -1483,7 +1534,10 @@ emu emu
|
|||||||
(
|
(
|
||||||
.CLK_50M(FPGA_CLK2_50),
|
.CLK_50M(FPGA_CLK2_50),
|
||||||
.RESET(reset),
|
.RESET(reset),
|
||||||
.HPS_BUS({f1, HDMI_TX_VS, clk_100m, clk_ihdmi, ce_hpix, hde_emu, hhs_fix, hvs_fix, io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}),
|
.HPS_BUS({f1, HDMI_TX_VS,
|
||||||
|
clk_100m, clk_ihdmi,
|
||||||
|
ce_hpix, hde_emu, hhs_fix, hvs_fix,
|
||||||
|
io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}),
|
||||||
|
|
||||||
.VGA_R(r_out),
|
.VGA_R(r_out),
|
||||||
.VGA_G(g_out),
|
.VGA_G(g_out),
|
||||||
@ -1494,6 +1548,9 @@ emu emu
|
|||||||
.VGA_F1(f1),
|
.VGA_F1(f1),
|
||||||
.VGA_SCALER(vga_force_scaler),
|
.VGA_SCALER(vga_force_scaler),
|
||||||
|
|
||||||
|
.HDMI_WIDTH(direct_video ? 12'd0 : hdmi_width),
|
||||||
|
.HDMI_HEIGHT(direct_video ? 12'd0 : hdmi_height),
|
||||||
|
|
||||||
.CLK_VIDEO(clk_vid),
|
.CLK_VIDEO(clk_vid),
|
||||||
.CE_PIXEL(ce_pix),
|
.CE_PIXEL(ce_pix),
|
||||||
.VGA_SL(scanlines),
|
.VGA_SL(scanlines),
|
||||||
|
231
sys/video_freak.sv
Normal file
231
sys/video_freak.sv
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
//
|
||||||
|
//
|
||||||
|
// Video crop
|
||||||
|
// Copyright (c) 2020 Grabulosaure, (c) 2021 Alexey Melnikov
|
||||||
|
//
|
||||||
|
// Integer scaling
|
||||||
|
// Copyright (c) 2021 Alexey Melnikov
|
||||||
|
//
|
||||||
|
// This program is GPL Licensed. See COPYING for the full license.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
module video_freak
|
||||||
|
(
|
||||||
|
input CLK_VIDEO,
|
||||||
|
input CE_PIXEL,
|
||||||
|
input VGA_VS,
|
||||||
|
input [11:0] HDMI_WIDTH,
|
||||||
|
input [11:0] HDMI_HEIGHT,
|
||||||
|
output VGA_DE,
|
||||||
|
output reg [12:0] VIDEO_ARX,
|
||||||
|
output reg [12:0] VIDEO_ARY,
|
||||||
|
|
||||||
|
input VGA_DE_IN,
|
||||||
|
input [11:0] ARX,
|
||||||
|
input [11:0] ARY,
|
||||||
|
input [11:0] CROP_SIZE,
|
||||||
|
input [4:0] CROP_OFF,
|
||||||
|
input [1:0] SCALE
|
||||||
|
);
|
||||||
|
|
||||||
|
reg vde;
|
||||||
|
reg [11:0] arxo,aryo;
|
||||||
|
reg [11:0] vsize;
|
||||||
|
reg [11:0] hsize;
|
||||||
|
|
||||||
|
always @(posedge CLK_VIDEO) begin
|
||||||
|
reg old_de, old_vs,vcalc,ovde;
|
||||||
|
reg [11:0] vtot,vcpt,vcrop,voff;
|
||||||
|
reg [11:0] hcpt;
|
||||||
|
reg [11:0] vadj;
|
||||||
|
reg [23:0] ARXG,ARYG,arx,ary;
|
||||||
|
|
||||||
|
if (CE_PIXEL) begin
|
||||||
|
old_de <= VGA_DE_IN;
|
||||||
|
old_vs <= VGA_VS;
|
||||||
|
if (VGA_VS & ~old_vs) begin
|
||||||
|
vcpt <= 0;
|
||||||
|
vtot <= vcpt;
|
||||||
|
vcalc <= 1;
|
||||||
|
vcrop <= ((CROP_SIZE >= vcpt) || !CROP_SIZE) ? 12'd0 : CROP_SIZE;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (VGA_DE_IN) hcpt <= hcpt + 1'd1;
|
||||||
|
if (~VGA_DE_IN & old_de) begin
|
||||||
|
vcpt <= vcpt + 1'd1;
|
||||||
|
if(!vcpt) hsize <= hcpt;
|
||||||
|
hcpt <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
arx <= ARX;
|
||||||
|
ary <= ARY;
|
||||||
|
|
||||||
|
vsize <= vcrop;
|
||||||
|
|
||||||
|
if(!vcrop || !ary || !arx) begin
|
||||||
|
arxo <= arx[11:0];
|
||||||
|
aryo <= ary[11:0];
|
||||||
|
vsize <= vtot;
|
||||||
|
end
|
||||||
|
else if (vcalc) begin
|
||||||
|
ARXG <= arx * vtot;
|
||||||
|
ARYG <= ary * vcrop;
|
||||||
|
vcalc <= 0;
|
||||||
|
end
|
||||||
|
else if (ARXG[23] | ARYG[23]) begin
|
||||||
|
arxo <= ARXG[23:12];
|
||||||
|
aryo <= ARYG[23:12];
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
ARXG <= ARXG << 1;
|
||||||
|
ARYG <= ARYG << 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
vadj <= (vtot-vcrop) + {{6{CROP_OFF[4]}},CROP_OFF,1'b0};
|
||||||
|
voff <= vadj[11] ? 12'd0 : ((vadj[11:1] + vcrop) > vtot) ? vtot-vcrop : vadj[11:1];
|
||||||
|
ovde <= ((vcpt >= voff) && (vcpt < (vcrop + voff))) || !vcrop;
|
||||||
|
vde <= ovde;
|
||||||
|
end
|
||||||
|
|
||||||
|
assign VGA_DE = vde & VGA_DE_IN;
|
||||||
|
|
||||||
|
video_scale_int scale
|
||||||
|
(
|
||||||
|
.CLK_VIDEO(CLK_VIDEO),
|
||||||
|
.HDMI_WIDTH(HDMI_WIDTH),
|
||||||
|
.HDMI_HEIGHT(HDMI_HEIGHT),
|
||||||
|
.hsize(hsize),
|
||||||
|
.vsize(vsize),
|
||||||
|
.arx_i(arxo),
|
||||||
|
.ary_i(aryo),
|
||||||
|
.scale(SCALE),
|
||||||
|
.arx_o(VIDEO_ARX),
|
||||||
|
.ary_o(VIDEO_ARY)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
|
||||||
|
module video_scale_int
|
||||||
|
(
|
||||||
|
input CLK_VIDEO,
|
||||||
|
|
||||||
|
input [11:0] HDMI_WIDTH,
|
||||||
|
input [11:0] HDMI_HEIGHT,
|
||||||
|
|
||||||
|
input [11:0] hsize,
|
||||||
|
input [11:0] vsize,
|
||||||
|
|
||||||
|
input [11:0] arx_i,
|
||||||
|
input [11:0] ary_i,
|
||||||
|
|
||||||
|
input [1:0] scale,
|
||||||
|
|
||||||
|
output reg [12:0] arx_o,
|
||||||
|
output reg [12:0] ary_o
|
||||||
|
);
|
||||||
|
|
||||||
|
reg div_start;
|
||||||
|
wire div_run;
|
||||||
|
reg [23:0] div_num;
|
||||||
|
reg [11:0] div_den;
|
||||||
|
wire [23:0] div_res;
|
||||||
|
sys_udiv #(24,12) div(CLK_VIDEO,div_start,div_run, div_num,div_den,div_res);
|
||||||
|
|
||||||
|
reg mul_start;
|
||||||
|
wire mul_run;
|
||||||
|
reg [11:0] mul_arg1, mul_arg2;
|
||||||
|
wire [23:0] mul_res;
|
||||||
|
sys_umul #(12,12) mul(CLK_VIDEO,mul_start,mul_run, mul_arg1,mul_arg2,mul_res);
|
||||||
|
|
||||||
|
wire [11:0] wideres = mul_res[11:0] + hsize;
|
||||||
|
reg [12:0] arxf,aryf;
|
||||||
|
|
||||||
|
always @(posedge CLK_VIDEO) begin
|
||||||
|
reg [11:0] oheight;
|
||||||
|
reg [3:0] cnt;
|
||||||
|
|
||||||
|
div_start <= 0;
|
||||||
|
mul_start <= 0;
|
||||||
|
|
||||||
|
if (!scale || !ary_i || !arx_i) begin
|
||||||
|
arxf <= arx_i;
|
||||||
|
aryf <= ary_i;
|
||||||
|
end
|
||||||
|
else if(~div_start & ~div_run & ~mul_start & ~mul_run) begin
|
||||||
|
cnt <= cnt + 1'd1;
|
||||||
|
case(cnt)
|
||||||
|
0: begin
|
||||||
|
div_num <= HDMI_HEIGHT;
|
||||||
|
div_den <= vsize;
|
||||||
|
div_start <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
1: if(!div_res[11:0]) begin
|
||||||
|
// screen resolution is lower than video resolution.
|
||||||
|
// Integer scaling is impossible.
|
||||||
|
arxf <= arx_i;
|
||||||
|
aryf <= ary_i;
|
||||||
|
cnt <= 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
mul_arg1 <= vsize;
|
||||||
|
mul_arg2 <= div_res[11:0];
|
||||||
|
mul_start <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
2: begin
|
||||||
|
oheight <= mul_res[11:0];
|
||||||
|
mul_arg1 <= mul_res[11:0];
|
||||||
|
mul_arg2 <= arx_i;
|
||||||
|
mul_start <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
3: begin
|
||||||
|
div_num <= mul_res;
|
||||||
|
div_den <= ary_i;
|
||||||
|
div_start <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
4: begin
|
||||||
|
div_num <= div_res;
|
||||||
|
div_den <= hsize;
|
||||||
|
div_start <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
5: begin
|
||||||
|
mul_arg1 <= hsize;
|
||||||
|
mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1;
|
||||||
|
mul_start <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
6: if(mul_res <= HDMI_WIDTH) cnt <= 8;
|
||||||
|
else begin
|
||||||
|
div_num <= HDMI_WIDTH;
|
||||||
|
div_den <= hsize;
|
||||||
|
div_start <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
7: begin
|
||||||
|
mul_arg1 <= hsize;
|
||||||
|
mul_arg2 <= div_res[11:0] ? div_res[11:0] : 12'd1;
|
||||||
|
mul_start <= 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
8: begin
|
||||||
|
arxf <= {1'b1, ~scale[1] ? div_num[11:0] : (scale[0] && (wideres <= HDMI_WIDTH)) ? wideres : mul_res[11:0]};
|
||||||
|
aryf <= {1'b1, oheight};
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
arx_o <= arxf;
|
||||||
|
ary_o <= aryf;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Copyright (c) 2017 Sorgelig
|
// Copyright (c) 2017,2021 Alexey Melnikov
|
||||||
//
|
//
|
||||||
// This program is GPL Licensed. See COPYING for the full license.
|
// This program is GPL Licensed. See COPYING for the full license.
|
||||||
//
|
//
|
||||||
@ -15,8 +15,6 @@
|
|||||||
// May be less if line_start is used.
|
// May be less if line_start is used.
|
||||||
//
|
//
|
||||||
// HALF_DEPTH: If =1 then color dept is 4 bits per component
|
// HALF_DEPTH: If =1 then color dept is 4 bits per component
|
||||||
// For half depth 8 bits monochrome is available with
|
|
||||||
// mono signal enabled and color = {G, R}
|
|
||||||
//
|
//
|
||||||
// altera message_off 10720
|
// altera message_off 10720
|
||||||
// altera message_off 12161
|
// altera message_off 12161
|
||||||
@ -28,32 +26,21 @@ module video_mixer
|
|||||||
parameter GAMMA = 0
|
parameter GAMMA = 0
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
// video clock
|
input CLK_VIDEO, // should be multiple by (ce_pix*4)
|
||||||
// it should be multiple by (ce_pix*4).
|
output reg CE_PIXEL, // output pixel clock enable
|
||||||
input clk_vid,
|
|
||||||
|
|
||||||
// Pixel clock or clock_enable (both are accepted).
|
input ce_pix, // input pixel clock or clock_enable
|
||||||
input ce_pix,
|
|
||||||
output ce_pix_out,
|
|
||||||
|
|
||||||
input scandoubler,
|
input scandoubler,
|
||||||
|
input hq2x, // high quality 2x scaling
|
||||||
|
|
||||||
// scanlines (00-none 01-25% 10-50% 11-75%)
|
inout [21:0] gamma_bus,
|
||||||
input [1:0] scanlines,
|
|
||||||
|
|
||||||
// High quality 2x scaling
|
|
||||||
input hq2x,
|
|
||||||
|
|
||||||
// color
|
// color
|
||||||
input [DWIDTH:0] R,
|
input [DWIDTH:0] R,
|
||||||
input [DWIDTH:0] G,
|
input [DWIDTH:0] G,
|
||||||
input [DWIDTH:0] B,
|
input [DWIDTH:0] B,
|
||||||
|
|
||||||
// Monochrome mode (for HALF_DEPTH only)
|
|
||||||
input mono,
|
|
||||||
|
|
||||||
inout [21:0] gamma_bus,
|
|
||||||
|
|
||||||
// Positive pulses.
|
// Positive pulses.
|
||||||
input HSync,
|
input HSync,
|
||||||
input VSync,
|
input VSync,
|
||||||
@ -75,9 +62,9 @@ localparam HALF_DEPTH_SD = GAMMA ? 0 : HALF_DEPTH;
|
|||||||
|
|
||||||
generate
|
generate
|
||||||
if(GAMMA && HALF_DEPTH) begin
|
if(GAMMA && HALF_DEPTH) begin
|
||||||
wire [7:0] R_in = mono ? {G,R} : {R,R};
|
wire [7:0] R_in = {R,R};
|
||||||
wire [7:0] G_in = mono ? {G,R} : {G,G};
|
wire [7:0] G_in = {G,G};
|
||||||
wire [7:0] B_in = mono ? {G,R} : {B,B};
|
wire [7:0] B_in = {B,B};
|
||||||
end else begin
|
end else begin
|
||||||
wire [DWIDTH:0] R_in = R;
|
wire [DWIDTH:0] R_in = R;
|
||||||
wire [DWIDTH:0] G_in = G;
|
wire [DWIDTH:0] G_in = G;
|
||||||
@ -95,7 +82,7 @@ generate
|
|||||||
assign gamma_bus[21] = 1;
|
assign gamma_bus[21] = 1;
|
||||||
gamma_corr gamma(
|
gamma_corr gamma(
|
||||||
.clk_sys(gamma_bus[20]),
|
.clk_sys(gamma_bus[20]),
|
||||||
.clk_vid(clk_vid),
|
.clk_vid(CLK_VIDEO),
|
||||||
.ce_pix(ce_pix),
|
.ce_pix(ce_pix),
|
||||||
|
|
||||||
.gamma_en(gamma_bus[19]),
|
.gamma_en(gamma_bus[19]),
|
||||||
@ -122,7 +109,6 @@ generate
|
|||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
|
|
||||||
wire [DWIDTH_SD:0] R_sd;
|
wire [DWIDTH_SD:0] R_sd;
|
||||||
wire [DWIDTH_SD:0] G_sd;
|
wire [DWIDTH_SD:0] G_sd;
|
||||||
wire [DWIDTH_SD:0] B_sd;
|
wire [DWIDTH_SD:0] B_sd;
|
||||||
@ -130,7 +116,10 @@ wire hs_sd, vs_sd, hb_sd, vb_sd, ce_pix_sd;
|
|||||||
|
|
||||||
scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH_SD)) sd
|
scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH_SD)) sd
|
||||||
(
|
(
|
||||||
.*,
|
.clk_vid(CLK_VIDEO),
|
||||||
|
.hq2x(hq2x),
|
||||||
|
|
||||||
|
.ce_pix(ce_pix),
|
||||||
.hs_in(hs_g),
|
.hs_in(hs_g),
|
||||||
.vs_in(vs_g),
|
.vs_in(vs_g),
|
||||||
.hb_in(hb_g),
|
.hb_in(hb_g),
|
||||||
@ -153,86 +142,51 @@ wire [DWIDTH_SD:0] rt = (scandoubler ? R_sd : R_gamma);
|
|||||||
wire [DWIDTH_SD:0] gt = (scandoubler ? G_sd : G_gamma);
|
wire [DWIDTH_SD:0] gt = (scandoubler ? G_sd : G_gamma);
|
||||||
wire [DWIDTH_SD:0] bt = (scandoubler ? B_sd : B_gamma);
|
wire [DWIDTH_SD:0] bt = (scandoubler ? B_sd : B_gamma);
|
||||||
|
|
||||||
generate
|
always @(posedge CLK_VIDEO) begin
|
||||||
if(!GAMMA && HALF_DEPTH) begin
|
reg [7:0] r,g,b;
|
||||||
wire [7:0] r = mono ? {gt,rt} : {rt,rt};
|
reg hde,vde,hs,vs, old_vs;
|
||||||
wire [7:0] g = mono ? {gt,rt} : {gt,gt};
|
|
||||||
wire [7:0] b = mono ? {gt,rt} : {bt,bt};
|
|
||||||
end else begin
|
|
||||||
wire [7:0] r = rt;
|
|
||||||
wire [7:0] g = gt;
|
|
||||||
wire [7:0] b = bt;
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
wire hs = (scandoubler ? hs_sd : hs_g);
|
|
||||||
wire vs = (scandoubler ? vs_sd : vs_g);
|
|
||||||
|
|
||||||
assign ce_pix_out = scandoubler ? ce_pix_sd : ce_pix;
|
|
||||||
|
|
||||||
|
|
||||||
reg scanline = 0;
|
|
||||||
always @(posedge clk_vid) begin
|
|
||||||
reg old_hs, old_vs;
|
|
||||||
|
|
||||||
old_hs <= hs;
|
|
||||||
old_vs <= vs;
|
|
||||||
|
|
||||||
if(old_hs && ~hs) scanline <= ~scanline;
|
|
||||||
if(old_vs && ~vs) scanline <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
wire hde = scandoubler ? ~hb_sd : ~hb_g;
|
|
||||||
wire vde = scandoubler ? ~vb_sd : ~vb_g;
|
|
||||||
|
|
||||||
reg [7:0] v_r,v_g,v_b;
|
|
||||||
reg v_vs,v_hs,v_de;
|
|
||||||
always @(posedge clk_vid) begin
|
|
||||||
reg old_hde;
|
reg old_hde;
|
||||||
|
reg old_ce;
|
||||||
|
reg ce_osc, fs_osc;
|
||||||
|
|
||||||
if(ce_pix_out) begin
|
old_ce <= ce_pix;
|
||||||
case(scanlines & {scanline, scanline})
|
ce_osc <= ce_osc | (old_ce ^ ce_pix);
|
||||||
1: begin // reduce 25% = 1/2 + 1/4
|
|
||||||
v_r <= {1'b0, r[7:1]} + {2'b00, r[7:2]};
|
old_vs <= vs;
|
||||||
v_g <= {1'b0, g[7:1]} + {2'b00, g[7:2]};
|
if(~old_vs & vs) begin
|
||||||
v_b <= {1'b0, b[7:1]} + {2'b00, b[7:2]};
|
fs_osc <= ce_osc;
|
||||||
|
ce_osc <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
2: begin // reduce 50% = 1/2
|
CE_PIXEL <= scandoubler ? ce_pix_sd : fs_osc ? (~old_ce & ce_pix) : ce_pix;
|
||||||
v_r <= {1'b0, r[7:1]};
|
|
||||||
v_g <= {1'b0, g[7:1]};
|
if(!GAMMA && HALF_DEPTH) begin
|
||||||
v_b <= {1'b0, b[7:1]};
|
r <= {rt,rt};
|
||||||
|
g <= {gt,gt};
|
||||||
|
b <= {bt,bt};
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
r <= rt;
|
||||||
|
g <= gt;
|
||||||
|
b <= bt;
|
||||||
end
|
end
|
||||||
|
|
||||||
3: begin // reduce 75% = 1/4
|
hde <= scandoubler ? ~hb_sd : ~hb_g;
|
||||||
v_r <= {2'b00, r[7:2]};
|
vde <= scandoubler ? ~vb_sd : ~vb_g;
|
||||||
v_g <= {2'b00, g[7:2]};
|
vs <= scandoubler ? vs_sd : vs_g;
|
||||||
v_b <= {2'b00, b[7:2]};
|
hs <= scandoubler ? hs_sd : hs_g;
|
||||||
end
|
|
||||||
|
|
||||||
default: begin
|
if(CE_PIXEL) begin
|
||||||
v_r <= r;
|
VGA_R <= r;
|
||||||
v_g <= g;
|
VGA_G <= g;
|
||||||
v_b <= b;
|
VGA_B <= b;
|
||||||
end
|
|
||||||
endcase
|
|
||||||
|
|
||||||
v_vs <= vs;
|
VGA_VS <= vs;
|
||||||
v_hs <= hs;
|
VGA_HS <= hs;
|
||||||
|
|
||||||
old_hde <= hde;
|
old_hde <= hde;
|
||||||
if(~old_hde && hde) v_de <= vde;
|
if(old_hde ^ hde) VGA_DE <= vde & hde;
|
||||||
if(old_hde && ~hde) v_de <= 0;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk_vid) if(ce_pix_out) begin
|
|
||||||
VGA_R <= v_r;
|
|
||||||
VGA_G <= v_g;
|
|
||||||
VGA_B <= v_b;
|
|
||||||
VGA_HS <= v_hs;
|
|
||||||
VGA_VS <= v_vs;
|
|
||||||
VGA_DE <= v_de;
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
Reference in New Issue
Block a user