mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-05 23:54:41 +00:00
Archie: optional scandoubler for 15kHz modes
This commit is contained in:
@@ -178,8 +178,10 @@ set_global_assignment -name SEED 1
|
||||
set_global_assignment -name ENABLE_DRC_SETTINGS OFF
|
||||
set_location_assignment PLL_1 -to CLOCKS|altpll_component|auto_generated|pll1
|
||||
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT NORMAL
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
set_global_assignment -name VERILOG_FILE archimedes_mist_top.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rgb2ypbpr.sv
|
||||
set_global_assignment -name VERILOG_FILE scandoubler.v
|
||||
set_global_assignment -name VERILOG_FILE sigma_delta_dac.v
|
||||
set_global_assignment -name VERILOG_FILE audio.v
|
||||
set_global_assignment -name VERILOG_FILE data_io.v
|
||||
@@ -226,5 +228,4 @@ set_global_assignment -name QIP_FILE pll_reconfig.qip
|
||||
set_global_assignment -name QIP_FILE rom_reconfig_36.qip
|
||||
set_global_assignment -name QIP_FILE pll_vidc.qip
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/vidc.stp
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/sd.stp
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/sd.stp
|
||||
@@ -256,11 +256,32 @@ always @(posedge clk_pix) begin
|
||||
{ r_adj, g_adj, b_adj } <= 12'h0;
|
||||
end
|
||||
|
||||
wire vs = vs_adj;
|
||||
wire hs = hs_adj;
|
||||
wire [5:0] r = { r_adj, r_adj[3:2] };
|
||||
wire [5:0] g = { g_adj, g_adj[3:2] };
|
||||
wire [5:0] b = { b_adj, b_adj[3:2] };
|
||||
wire [5:0] sd_r, sd_g, sd_b;
|
||||
wire sd_hs;
|
||||
wire sd_vs;
|
||||
|
||||
scandoubler #(11, 4) scandoubler
|
||||
(
|
||||
.clk_sys ( clk_pix ),
|
||||
.scanlines ( 2'b00 ),
|
||||
.ce_divider ( 1'b1 ),
|
||||
.hs_in ( hs_adj ),
|
||||
.vs_in ( vs_adj ),
|
||||
.r_in ( r_adj ),
|
||||
.g_in ( g_adj ),
|
||||
.b_in ( b_adj ),
|
||||
.hs_out ( sd_hs ),
|
||||
.vs_out ( sd_vs ),
|
||||
.r_out ( sd_r ),
|
||||
.g_out ( sd_g ),
|
||||
.b_out ( sd_b )
|
||||
);
|
||||
|
||||
wire vs = scandoubler_en ? sd_vs : core_vs;
|
||||
wire hs = scandoubler_en ? sd_hs : core_hs;
|
||||
wire [5:0] r = scandoubler_en ? sd_r : { r_adj, r_adj[3:2] };
|
||||
wire [5:0] g = scandoubler_en ? sd_g : { g_adj, g_adj[3:2] };
|
||||
wire [5:0] b = scandoubler_en ? sd_b : { b_adj, b_adj[3:2] };
|
||||
|
||||
wire [5:0] osd_r_o, osd_g_o, osd_b_o;
|
||||
|
||||
@@ -295,13 +316,14 @@ rgb2ypbpr rgb2ypbpr
|
||||
.pr ( Pr )
|
||||
);
|
||||
|
||||
wire scandoubler_en = ~scandoubler_disable && pixbaseclk_select[0] == pixbaseclk_select[1];
|
||||
assign VGA_R = ypbpr?Pr:osd_r_o;
|
||||
assign VGA_G = ypbpr? Y:osd_g_o;
|
||||
assign VGA_B = ypbpr?Pb:osd_b_o;
|
||||
wire CSync = ~(hs ^ vs);
|
||||
//24 MHz modes get composite sync automatically
|
||||
assign VGA_HS = ((pixbaseclk_select[0] == pixbaseclk_select[1]) | ypbpr) ? CSync : hs;
|
||||
assign VGA_VS = ((pixbaseclk_select[0] == pixbaseclk_select[1]) | ypbpr) ? 1'b1 : vs;
|
||||
assign VGA_HS = ((pixbaseclk_select[0] == pixbaseclk_select[1] && scandoubler_disable) | ypbpr) ? CSync : hs;
|
||||
assign VGA_VS = ((pixbaseclk_select[0] == pixbaseclk_select[1] && scandoubler_disable) | ypbpr) ? 1'b1 : vs;
|
||||
|
||||
wire [31:0] sd_lba;
|
||||
wire [1:0] sd_rd;
|
||||
@@ -486,7 +508,7 @@ sdram_top SDRAM(
|
||||
.sd_cas_n ( DRAM_CAS_N ),
|
||||
.sd_ready ( ram_ready )
|
||||
);
|
||||
|
||||
|
||||
i2cSlaveTop CMOS (
|
||||
.clk ( clk_sys ),
|
||||
.rst ( ~pll_ready ),
|
||||
|
||||
216
cores/archie/fpga/mist/scandoubler.v
Normal file
216
cores/archie/fpga/mist/scandoubler.v
Normal file
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// scandoubler.v
|
||||
//
|
||||
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
|
||||
//
|
||||
// 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
|
||||
// by the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This source file 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// TODO: Delay vsync one line
|
||||
|
||||
module scandoubler
|
||||
(
|
||||
// system interface
|
||||
input clk_sys,
|
||||
|
||||
// scanlines (00-none 01-25% 10-50% 11-75%)
|
||||
input [1:0] scanlines,
|
||||
input ce_divider, // 0 - 4, 1 - 2
|
||||
|
||||
// shifter video interface
|
||||
input hs_in,
|
||||
input vs_in,
|
||||
input [COLOR_DEPTH-1:0] r_in,
|
||||
input [COLOR_DEPTH-1:0] g_in,
|
||||
input [COLOR_DEPTH-1:0] b_in,
|
||||
|
||||
// output interface
|
||||
output reg hs_out,
|
||||
output reg vs_out,
|
||||
output reg [5:0] r_out,
|
||||
output reg [5:0] g_out,
|
||||
output reg [5:0] b_out
|
||||
);
|
||||
|
||||
parameter HCNT_WIDTH = 9;
|
||||
parameter COLOR_DEPTH = 6;
|
||||
|
||||
// try to detect changes in input signal and lock input clock gate
|
||||
// it
|
||||
|
||||
reg [1:0] i_div;
|
||||
|
||||
reg ce_x1, ce_x2;
|
||||
|
||||
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
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
reg last_hs_in;
|
||||
last_hs_in <= hs_in;
|
||||
if(last_hs_in & !hs_in) begin
|
||||
i_div <= 2'b00;
|
||||
end else begin
|
||||
i_div <= i_div + 2'd1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// --------------------- create output signals -----------------
|
||||
// latch everything once more to make it glitch free and apply scanline effect
|
||||
reg scanline;
|
||||
reg [5:0] r;
|
||||
reg [5:0] g;
|
||||
reg [5:0] b;
|
||||
|
||||
always @(*) begin
|
||||
if (COLOR_DEPTH == 6) begin
|
||||
b = sd_out[5:0];
|
||||
g = sd_out[11:6];
|
||||
r = sd_out[17:12];
|
||||
end else if (COLOR_DEPTH == 2) begin
|
||||
b = {3{sd_out[1:0]}};
|
||||
g = {3{sd_out[3:2]}};
|
||||
r = {3{sd_out[5:4]}};
|
||||
end else if (COLOR_DEPTH == 1) begin
|
||||
b = {6{sd_out[0]}};
|
||||
g = {6{sd_out[1]}};
|
||||
r = {6{sd_out[2]}};
|
||||
end else begin
|
||||
b = { sd_out[COLOR_DEPTH-1:0], sd_out[COLOR_DEPTH-1 -:(6-COLOR_DEPTH)] };
|
||||
g = { sd_out[COLOR_DEPTH*2-1:COLOR_DEPTH], sd_out[COLOR_DEPTH*2-1 -:(6-COLOR_DEPTH)] };
|
||||
r = { sd_out[COLOR_DEPTH*3-1:COLOR_DEPTH*2], sd_out[COLOR_DEPTH*3-1 -:(6-COLOR_DEPTH)] };
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
if(ce_x2) begin
|
||||
hs_out <= hs_sd;
|
||||
vs_out <= vs_in;
|
||||
|
||||
// reset scanlines at every new screen
|
||||
if(vs_out != vs_in) scanline <= 0;
|
||||
|
||||
// toggle scanlines at begin of every hsync
|
||||
if(hs_out && !hs_sd) scanline <= !scanline;
|
||||
|
||||
// if no scanlines or not a scanline
|
||||
if(!scanline || !scanlines) begin
|
||||
r_out <= r;
|
||||
g_out <= g;
|
||||
b_out <= b;
|
||||
end else begin
|
||||
case(scanlines)
|
||||
1: begin // reduce 25% = 1/2 + 1/4
|
||||
r_out <= {1'b0, r[5:1]} + {2'b00, r[5:2] };
|
||||
g_out <= {1'b0, g[5:1]} + {2'b00, g[5:2] };
|
||||
b_out <= {1'b0, b[5:1]} + {2'b00, b[5:2] };
|
||||
end
|
||||
|
||||
2: begin // reduce 50% = 1/2
|
||||
r_out <= {1'b0, r[5:1]};
|
||||
g_out <= {1'b0, g[5:1]};
|
||||
b_out <= {1'b0, b[5:1]};
|
||||
end
|
||||
|
||||
3: begin // reduce 75% = 1/4
|
||||
r_out <= {2'b00, r[5:2]};
|
||||
g_out <= {2'b00, g[5:2]};
|
||||
b_out <= {2'b00, b[5:2]};
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// scan doubler output register
|
||||
reg [COLOR_DEPTH*3-1:0] sd_out;
|
||||
|
||||
// ==================================================================
|
||||
// ======================== the line buffers ========================
|
||||
// ==================================================================
|
||||
|
||||
// 2 lines of 2**HCNT_WIDTH pixels 3*COLOR_DEPTH bit RGB
|
||||
(* ramstyle = "no_rw_check" *) reg [COLOR_DEPTH*3-1:0] sd_buffer[2*2**HCNT_WIDTH];
|
||||
|
||||
// use alternating sd_buffers when storing/reading data
|
||||
reg line_toggle;
|
||||
|
||||
// total hsync time (in 16MHz cycles), hs_total reaches 1024
|
||||
reg [HCNT_WIDTH-1:0] hs_max;
|
||||
reg [HCNT_WIDTH-1:0] hs_rise;
|
||||
reg [HCNT_WIDTH-1:0] hcnt;
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
reg hsD, vsD;
|
||||
|
||||
if(ce_x1) begin
|
||||
hsD <= hs_in;
|
||||
|
||||
// falling edge of hsync indicates start of line
|
||||
if(hsD && !hs_in) begin
|
||||
hs_max <= hcnt;
|
||||
hcnt <= 0;
|
||||
end else begin
|
||||
hcnt <= hcnt + 1'd1;
|
||||
end
|
||||
|
||||
// save position of rising edge
|
||||
if(!hsD && hs_in) hs_rise <= hcnt;
|
||||
|
||||
vsD <= vs_in;
|
||||
if(vsD != vs_in) line_toggle <= 0;
|
||||
|
||||
// begin of incoming hsync
|
||||
if(hsD && !hs_in) line_toggle <= !line_toggle;
|
||||
|
||||
sd_buffer[{line_toggle, hcnt}] <= {r_in, g_in, b_in};
|
||||
end
|
||||
end
|
||||
|
||||
// ==================================================================
|
||||
// ==================== output timing generation ====================
|
||||
// ==================================================================
|
||||
|
||||
reg [HCNT_WIDTH-1:0] sd_hcnt;
|
||||
reg hs_sd;
|
||||
|
||||
// timing generation runs 32 MHz (twice the input signal analysis speed)
|
||||
always @(posedge clk_sys) begin
|
||||
reg hsD;
|
||||
|
||||
if(ce_x2) begin
|
||||
hsD <= hs_in;
|
||||
|
||||
// output counter synchronous to input and at twice the rate
|
||||
sd_hcnt <= sd_hcnt + 1'd1;
|
||||
if(hsD && !hs_in) sd_hcnt <= hs_max;
|
||||
if(sd_hcnt == hs_max) sd_hcnt <= 0;
|
||||
|
||||
// replicate horizontal sync at twice the speed
|
||||
if(sd_hcnt == hs_max) hs_sd <= 0;
|
||||
if(sd_hcnt == hs_rise) hs_sd <= 1;
|
||||
|
||||
// read data from line sd_buffer
|
||||
sd_out <= sd_buffer[{~line_toggle, sd_hcnt}];
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user