mirror of
https://github.com/MiSTer-devel/ColecoVision_MiSTer.git
synced 2026-05-17 03:03:31 +00:00
Update API.
This commit is contained in:
102
sys/osd.v
102
sys/osd.v
@@ -7,7 +7,7 @@ module osd
|
||||
|
||||
input io_osd,
|
||||
input io_strobe,
|
||||
input [7:0] io_din,
|
||||
input [15:0] io_din,
|
||||
|
||||
input clk_video,
|
||||
input [23:0] din,
|
||||
@@ -23,14 +23,16 @@ parameter OSD_Y_OFFSET = 12'd0;
|
||||
localparam OSD_WIDTH = 12'd256;
|
||||
localparam OSD_HEIGHT = 12'd64;
|
||||
|
||||
// this core supports only the display related OSD commands
|
||||
// of the minimig v1
|
||||
reg osd_enable;
|
||||
(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[4096]; // the OSD buffer itself
|
||||
(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[4096];
|
||||
|
||||
reg highres = 0;
|
||||
reg highres = 0;
|
||||
reg info = 0;
|
||||
reg [8:0] infoh;
|
||||
reg [8:0] infow;
|
||||
reg [11:0] infox;
|
||||
reg [21:0] infoy;
|
||||
|
||||
// the OSD has its own SPI interface to the io controller
|
||||
always@(posedge clk_sys) begin
|
||||
reg [11:0] bcnt;
|
||||
reg [7:0] cmd;
|
||||
@@ -42,24 +44,37 @@ always@(posedge clk_sys) begin
|
||||
if(~io_osd) begin
|
||||
bcnt <= 0;
|
||||
has_cmd <= 0;
|
||||
cmd <= 0;
|
||||
if(cmd[7:4] == 4) osd_enable <= cmd[0];
|
||||
end else begin
|
||||
if(~old_strobe & io_strobe) begin
|
||||
if(!has_cmd) begin
|
||||
has_cmd <= 1;
|
||||
cmd <= io_din;
|
||||
cmd <= io_din[7:0];
|
||||
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
|
||||
if(io_din[7:4] == 4'b0100) begin
|
||||
osd_enable <= io_din[0];
|
||||
if(io_din[7:4] == 4) begin
|
||||
if(!io_din[0]) highres <= 0;
|
||||
info <= io_din[2];
|
||||
bcnt <= 0;
|
||||
end
|
||||
bcnt <= {io_din[3:0], 8'h00};
|
||||
if(io_din[7:3] == 5'b00101) highres <= 1;
|
||||
end else begin
|
||||
// command 0x20: OSDCMDWRITE
|
||||
if(cmd[7:4] == 4'b0010) begin
|
||||
osd_buffer[bcnt] <= io_din;
|
||||
bcnt <= bcnt + 1'd1;
|
||||
if(io_din[7:4] == 2) begin
|
||||
if(io_din[3]) highres <= 1;
|
||||
bcnt <= {io_din[3:0], 8'h00};
|
||||
end
|
||||
end else begin
|
||||
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
|
||||
if(cmd[7:4] == 4) begin
|
||||
if(bcnt == 0) infox <= io_din[11:0];
|
||||
if(bcnt == 1) infoy <= io_din[11:0];
|
||||
if(bcnt == 2) infow <= {io_din[5:0], 3'b000};
|
||||
if(bcnt == 3) infoh <= {io_din[5:0], 3'b000};
|
||||
end
|
||||
|
||||
// command 0x20: OSDCMDWRITE
|
||||
if(cmd[7:4] == 2) osd_buffer[bcnt] <= io_din[7:0];
|
||||
|
||||
bcnt <= bcnt + 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -94,7 +109,8 @@ reg [7:0] osd_byte;
|
||||
reg [21:0] osd_vcnt;
|
||||
reg [21:0] fheight;
|
||||
|
||||
wire [21:0] hrheight = (OSD_HEIGHT<<highres);
|
||||
reg [21:0] finfoy;
|
||||
wire [21:0] hrheight = info ? infoh : (OSD_HEIGHT<<highres);
|
||||
|
||||
always @(posedge clk_video) begin
|
||||
reg deD;
|
||||
@@ -115,22 +131,31 @@ always @(posedge clk_video) begin
|
||||
if(h_cnt > {dsp_width, 2'b00}) begin
|
||||
v_cnt <= 0;
|
||||
dsp_height <= v_cnt;
|
||||
|
||||
if(v_cnt<320) begin
|
||||
multiscan <= 0;
|
||||
fheight <= hrheight;
|
||||
end
|
||||
else if(v_cnt<640) begin
|
||||
multiscan <= 1;
|
||||
fheight <= hrheight << 1;
|
||||
end
|
||||
else if(v_cnt<960) begin
|
||||
multiscan <= 2;
|
||||
fheight <= hrheight + (hrheight<<1);
|
||||
|
||||
if(osd_enable) begin
|
||||
if(v_cnt<320) begin
|
||||
multiscan <= 0;
|
||||
fheight <= hrheight;
|
||||
finfoy <= infoy;
|
||||
end
|
||||
else if(v_cnt<640) begin
|
||||
multiscan <= 1;
|
||||
fheight <= hrheight << 1;
|
||||
finfoy <= infoy << 1;
|
||||
end
|
||||
else if(v_cnt<960) begin
|
||||
multiscan <= 2;
|
||||
fheight <= hrheight + (hrheight<<1);
|
||||
finfoy <= infoy + (infoy << 1);
|
||||
end
|
||||
else begin
|
||||
multiscan <= 3;
|
||||
fheight <= hrheight << 2;
|
||||
finfoy <= infoy << 2;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
multiscan <= 3;
|
||||
fheight <= hrheight << 2;
|
||||
fheight <= 0;
|
||||
end
|
||||
end
|
||||
h_cnt <= 0;
|
||||
@@ -148,28 +173,19 @@ always @(posedge clk_video) begin
|
||||
end
|
||||
|
||||
// area in which OSD is being displayed
|
||||
wire [21:0] h_osd_start = ((dsp_width - OSD_WIDTH)>>1) + OSD_X_OFFSET;
|
||||
wire [21:0] h_osd_end = h_osd_start + OSD_WIDTH;
|
||||
wire [21:0] v_osd_start = ((dsp_height- fheight)>>1) + OSD_Y_OFFSET;
|
||||
wire [21:0] h_osd_start = info ? infox : ((dsp_width - OSD_WIDTH)>>1) + OSD_X_OFFSET;
|
||||
wire [21:0] h_osd_end = info ? (h_osd_start + infow) : (h_osd_start + OSD_WIDTH);
|
||||
wire [21:0] v_osd_start = info ? finfoy : ((dsp_height- fheight)>>1) + OSD_Y_OFFSET;
|
||||
wire [21:0] v_osd_end = v_osd_start + fheight;
|
||||
|
||||
wire [21:0] osd_hcnt = h_cnt[21:0] - h_osd_start + 1'd1;
|
||||
|
||||
wire osd_de = osd_enable &&
|
||||
wire osd_de = osd_enable && fheight &&
|
||||
(h_cnt >= h_osd_start) && (h_cnt < h_osd_end) &&
|
||||
(v_cnt >= v_osd_start) && (v_cnt < v_osd_end);
|
||||
|
||||
wire osd_pixel = osd_byte[osd_vcnt[2:0]];
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// Pipeline one cycle to improve timing
|
||||
//
|
||||
//assign dout = !osd_de ? din : {{osd_pixel, osd_pixel, OSD_COLOR[2], din[23:19]},
|
||||
// {osd_pixel, osd_pixel, OSD_COLOR[1], din[15:11]},
|
||||
// {osd_pixel, osd_pixel, OSD_COLOR[0], din[7:3]}};
|
||||
|
||||
reg [23:0] rdout;
|
||||
assign dout = rdout;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# Specify root clocks
|
||||
create_clock -period "50.0 MHz" [get_ports FPGA_CLK1_50]
|
||||
create_clock -period "50.0 MHz" [get_ports FPGA_CLK2_50]
|
||||
create_clock -period "50.0 MHz" [get_ports FPGA_CLK3_50]
|
||||
@@ -5,6 +6,7 @@ create_clock -period "100.0 MHz" [get_pins -compatibility_mode *|h2f_user0_clk]
|
||||
|
||||
derive_pll_clocks
|
||||
|
||||
# Specify PLL-generated clock(s)
|
||||
#create_generated_clock -source [get_pins -compatibility_mode {*|pll|pll_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk}] \
|
||||
-name SDRAM_CLK [get_ports {SDRAM_CLK}]
|
||||
|
||||
@@ -18,6 +20,7 @@ create_generated_clock -source [get_pins { pll_hdmi|pll_hdmi_inst|altera_pll_i|c
|
||||
derive_clock_uncertainty
|
||||
|
||||
|
||||
# Set acceptable delays for SDRAM chip (See correspondent chip datasheet)
|
||||
#set_input_delay -max -clock SDRAM_CLK 6.4ns [get_ports SDRAM_DQ[*]]
|
||||
#set_input_delay -min -clock SDRAM_CLK 3.7ns [get_ports SDRAM_DQ[*]]
|
||||
|
||||
@@ -28,6 +31,7 @@ derive_clock_uncertainty
|
||||
#set_output_delay -max -clock SDRAM_CLK 1.6ns [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
|
||||
#set_output_delay -min -clock SDRAM_CLK -0.9ns [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}]
|
||||
|
||||
# Decouple different clock groups (to simplify routing)
|
||||
set_clock_groups -asynchronous \
|
||||
-group [get_clocks { *|pll|pll_inst|altera_pll_i|general[*].gpll~PLL_OUTPUT_COUNTER|divclk}] \
|
||||
-group [get_clocks { pll_hdmi|pll_hdmi_inst|altera_pll_i|cyclonev_pll|counter[0].output_counter|divclk VID_CLK}] \
|
||||
@@ -37,8 +41,13 @@ set_clock_groups -asynchronous \
|
||||
set_output_delay -max -clock HDMI_CLK 2.0ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}]
|
||||
set_output_delay -min -clock HDMI_CLK -1.5ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}]
|
||||
|
||||
# Put constraints on input ports
|
||||
set_false_path -from [get_ports {KEY*}] -to *
|
||||
set_false_path -from [get_ports {BTN_*}] -to *
|
||||
|
||||
# Put constraints on output ports
|
||||
set_false_path -from * -to [get_ports {LED_*}]
|
||||
set_false_path -from * -to [get_ports {BTN_*}]
|
||||
set_false_path -from * -to [get_ports {VGA_*}]
|
||||
set_false_path -from * -to [get_ports {AUDIO_SPDIF}]
|
||||
set_false_path -from * -to [get_ports {AUDIO_L}]
|
||||
set_false_path -from * -to [get_ports {AUDIO_R}]
|
||||
|
||||
@@ -190,6 +190,7 @@ cyclonev_hps_interface_mpu_general_purpose h2f_gp
|
||||
reg [15:0] cfg;
|
||||
|
||||
reg cfg_got = 0;
|
||||
reg cfg_set = 0;
|
||||
//wire [2:0] hdmi_res = cfg[10:8];
|
||||
wire dvi_mode = cfg[7];
|
||||
wire audio_96k = cfg[6];
|
||||
@@ -205,6 +206,7 @@ reg [31:0] cfg_custom_p2;
|
||||
|
||||
reg [4:0] vol_att = 0;
|
||||
|
||||
reg vip_newcfg = 0;
|
||||
always@(posedge clk_sys) begin
|
||||
reg [7:0] cmd;
|
||||
reg has_cmd;
|
||||
@@ -224,21 +226,22 @@ always@(posedge clk_sys) begin
|
||||
else begin
|
||||
if(cmd == 1) begin
|
||||
cfg <= io_din;
|
||||
cfg_got <= 1;
|
||||
cfg_set <= 1;
|
||||
end
|
||||
if(cmd == 'h20) begin
|
||||
cfg_got <= 0;
|
||||
cfg_set <= 0;
|
||||
cnt <= cnt + 1'd1;
|
||||
if(cnt<8) begin
|
||||
if(!cnt) vip_newcfg <= ~cfg_ready;
|
||||
case(cnt)
|
||||
0: WIDTH <= io_din[11:0];
|
||||
1: HFP <= io_din[11:0];
|
||||
2: HS <= io_din[11:0];
|
||||
3: HBP <= io_din[11:0];
|
||||
4: HEIGHT <= io_din[11:0];
|
||||
5: VFP <= io_din[11:0];
|
||||
6: VS <= io_din[11:0];
|
||||
7: VBP <= io_din[11:0];
|
||||
0: if(WIDTH != io_din[11:0]) begin WIDTH <= io_din[11:0]; vip_newcfg <= 1; end
|
||||
1: if(HFP != io_din[11:0]) begin HFP <= io_din[11:0]; vip_newcfg <= 1; end
|
||||
2: if(HS != io_din[11:0]) begin HS <= io_din[11:0]; vip_newcfg <= 1; end
|
||||
3: if(HBP != io_din[11:0]) begin HBP <= io_din[11:0]; vip_newcfg <= 1; end
|
||||
4: if(HEIGHT != io_din[11:0]) begin HEIGHT <= io_din[11:0]; vip_newcfg <= 1; end
|
||||
5: if(VFP != io_din[11:0]) begin VFP <= io_din[11:0]; vip_newcfg <= 1; end
|
||||
6: if(VS != io_din[11:0]) begin VS <= io_din[11:0]; vip_newcfg <= 1; end
|
||||
7: if(VBP != io_din[11:0]) begin VBP <= io_din[11:0]; vip_newcfg <= 1; end
|
||||
endcase
|
||||
if(cnt == 1) begin
|
||||
cfg_custom_p1 <= 0;
|
||||
@@ -263,6 +266,16 @@ always@(posedge clk_sys) begin
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
reg vsd, vsd2;
|
||||
if(~cfg_ready || ~cfg_set) cfg_got <= cfg_set;
|
||||
else begin
|
||||
vsd <= HDMI_TX_VS;
|
||||
vsd2 <= vsd;
|
||||
if(~vsd2 & vsd) cfg_got <= cfg_set;
|
||||
end
|
||||
end
|
||||
|
||||
/////////////////////////// RESET ///////////////////////////////////
|
||||
|
||||
reg reset_req = 0;
|
||||
@@ -368,7 +381,7 @@ vip_config vip_config
|
||||
|
||||
.ARX(ARX),
|
||||
.ARY(ARY),
|
||||
.CFG_SET(cfg_got),
|
||||
.CFG_SET(vip_newcfg & cfg_got),
|
||||
|
||||
.WIDTH(WIDTH),
|
||||
.HFP(HFP),
|
||||
@@ -652,7 +665,7 @@ osd hdmi_osd
|
||||
|
||||
.io_osd(io_osd),
|
||||
.io_strobe(io_strobe),
|
||||
.io_din(io_din[7:0]),
|
||||
.io_din(io_din),
|
||||
|
||||
.clk_video(iHdmiClk),
|
||||
.din(hdmi_data),
|
||||
@@ -687,7 +700,7 @@ osd vga_osd
|
||||
|
||||
.io_osd(io_osd),
|
||||
.io_strobe(io_strobe),
|
||||
.io_din(io_din[7:0]),
|
||||
.io_din(io_din),
|
||||
|
||||
.clk_video(clk_vid),
|
||||
.din(de ? {r_out, g_out, b_out} : 24'd0),
|
||||
|
||||
@@ -25,58 +25,69 @@ module vip_config
|
||||
input waitrequest
|
||||
);
|
||||
|
||||
reg [31:0] wcalc;
|
||||
reg [31:0] hcalc;
|
||||
|
||||
wire [31:0] videow = (!VSET && (wcalc > WIDTH)) ? WIDTH : wcalc;
|
||||
wire [31:0] videoh = VSET ? VSET : (hcalc > HEIGHT) ? HEIGHT : hcalc;
|
||||
|
||||
wire [31:0] posx = (WIDTH - videow)>>1;
|
||||
wire [31:0] posy = (HEIGHT- videoh)>>1;
|
||||
|
||||
reg newres = 1;
|
||||
|
||||
wire [21:0] init[23] =
|
||||
'{
|
||||
//video mode
|
||||
{newres, 2'd2, 7'd04, 12'd0 }, //Bank
|
||||
{newres, 2'd2, 7'd30, 12'd0 }, //Valid
|
||||
{newres, 2'd2, 7'd05, 12'd0 }, //Progressive/Interlaced
|
||||
{newres, 2'd2, 7'd06, WIDTH }, //Active pixel count
|
||||
{newres, 2'd2, 7'd07, HEIGHT }, //Active line count
|
||||
{newres, 2'd2, 7'd09, HFP }, //Horizontal Front Porch
|
||||
{newres, 2'd2, 7'd10, HS }, //Horizontal Sync Length
|
||||
{newres, 2'd2, 7'd11, HFP+HBP+HS }, //Horizontal Blanking (HFP+HBP+HSync)
|
||||
{newres, 2'd2, 7'd12, VFP }, //Vertical Front Porch
|
||||
{newres, 2'd2, 7'd13, VS }, //Vertical Sync Length
|
||||
{newres, 2'd2, 7'd14, VFP+VBP+VS }, //Vertical blanking (VFP+VBP+VSync)
|
||||
{newres, 2'd2, 7'd30, 12'd1 }, //Valid
|
||||
{newres, 2'd2, 7'd00, 12'd1 }, //Go
|
||||
{newres, 2'd2, 7'd04, 12'd0 }, //Bank
|
||||
{newres, 2'd2, 7'd30, 12'd0 }, //Valid
|
||||
{newres, 2'd2, 7'd05, 12'd0 }, //Progressive/Interlaced
|
||||
{newres, 2'd2, 7'd06, w }, //Active pixel count
|
||||
{newres, 2'd2, 7'd07, h }, //Active line count
|
||||
{newres, 2'd2, 7'd09, hfp }, //Horizontal Front Porch
|
||||
{newres, 2'd2, 7'd10, hs }, //Horizontal Sync Length
|
||||
{newres, 2'd2, 7'd11, hb }, //Horizontal Blanking (HFP+HBP+HSync)
|
||||
{newres, 2'd2, 7'd12, vfp }, //Vertical Front Porch
|
||||
{newres, 2'd2, 7'd13, vs }, //Vertical Sync Length
|
||||
{newres, 2'd2, 7'd14, vb }, //Vertical blanking (VFP+VBP+VSync)
|
||||
{newres, 2'd2, 7'd30, 12'd1 }, //Valid
|
||||
{newres, 2'd2, 7'd00, 12'd1 }, //Go
|
||||
|
||||
//mixer
|
||||
{ 1'd1, 2'd1, 7'd03, WIDTH }, //Bkg Width
|
||||
{ 1'd1, 2'd1, 7'd04, HEIGHT }, //Bkg Height
|
||||
{ 1'd1, 2'd1, 7'd08, posx[11:0] }, //Pos X
|
||||
{ 1'd1, 2'd1, 7'd09, posy[11:0] }, //Pos Y
|
||||
{ 1'd1, 2'd1, 7'd10, 12'd1 }, //Enable Video 0
|
||||
{ 1'd1, 2'd1, 7'd00, 12'd1 }, //Go
|
||||
{ 1'd1, 2'd1, 7'd03, w }, //Bkg Width
|
||||
{ 1'd1, 2'd1, 7'd04, h }, //Bkg Height
|
||||
{ 1'd1, 2'd1, 7'd08, posx }, //Pos X
|
||||
{ 1'd1, 2'd1, 7'd09, posy }, //Pos Y
|
||||
{ 1'd1, 2'd1, 7'd10, 12'd1 }, //Enable Video 0
|
||||
{ 1'd1, 2'd1, 7'd00, 12'd1 }, //Go
|
||||
|
||||
//scaler
|
||||
{ 1'd1, 2'd0, 7'd03, videow[11:0] }, //Output Width
|
||||
{ 1'd1, 2'd0, 7'd04, videoh[11:0] }, //Output Height
|
||||
{ 1'd1, 2'd0, 7'd00, 12'd1 }, //Go
|
||||
{ 1'd1, 2'd0, 7'd03, videow }, //Output Width
|
||||
{ 1'd1, 2'd0, 7'd04, videoh }, //Output Height
|
||||
{ 1'd1, 2'd0, 7'd00, 12'd1 }, //Go
|
||||
|
||||
22'h3FFFFF
|
||||
};
|
||||
|
||||
reg [11:0] w;
|
||||
reg [11:0] hfp;
|
||||
reg [11:0] hbp;
|
||||
reg [11:0] hs;
|
||||
reg [11:0] hb;
|
||||
reg [11:0] h;
|
||||
reg [11:0] vfp;
|
||||
reg [11:0] vbp;
|
||||
reg [11:0] vs;
|
||||
reg [11:0] vb;
|
||||
|
||||
reg [11:0] videow;
|
||||
reg [11:0] videoh;
|
||||
|
||||
reg [11:0] posx;
|
||||
reg [11:0] posy;
|
||||
|
||||
always @(posedge clk) begin
|
||||
reg [7:0] state = 0;
|
||||
reg [7:0] arx, ary;
|
||||
reg [7:0] arxd, aryd;
|
||||
reg [11:0] vset, vsetd;
|
||||
reg cfg, cfgd;
|
||||
integer timeout = 0;
|
||||
|
||||
reg [31:0] wcalc;
|
||||
reg [31:0] hcalc;
|
||||
reg [12:0] timeout = 0;
|
||||
|
||||
arxd <= ARX;
|
||||
aryd <= ARY;
|
||||
vsetd <= VSET;
|
||||
@@ -89,23 +100,47 @@ always @(posedge clk) begin
|
||||
arx <= arxd;
|
||||
ary <= aryd;
|
||||
vset <= vsetd;
|
||||
timeout <= 10000;
|
||||
timeout <= '1;
|
||||
state <= 0;
|
||||
if(reset || (~cfgd && cfg)) newres <= 1;
|
||||
end
|
||||
else
|
||||
if(timeout > 0)
|
||||
begin
|
||||
timeout <= timeout - 1;
|
||||
timeout <= timeout - 1'd1;
|
||||
state <= 1;
|
||||
if(!(timeout & 'h1f)) case(timeout>>5)
|
||||
5: begin
|
||||
w <= WIDTH;
|
||||
hfp <= HFP;
|
||||
hbp <= HBP;
|
||||
hs <= HS;
|
||||
h <= HEIGHT;
|
||||
vfp <= VFP;
|
||||
vbp <= VBP;
|
||||
vs <= VS;
|
||||
end
|
||||
4: begin
|
||||
hb <= hfp+hbp+hs;
|
||||
vb <= vfp+vbp+vs;
|
||||
end
|
||||
3: begin
|
||||
wcalc <= vset ? (vset*arx)/ary : (h*arx)/ary;
|
||||
hcalc <= (w*ary)/arx;
|
||||
end
|
||||
2: begin
|
||||
videow <= (!vset && (wcalc > w)) ? w : wcalc[11:0];
|
||||
videoh <= vset ? vset : (hcalc > h) ? h : hcalc[11:0];
|
||||
end
|
||||
1: begin
|
||||
posx <= (w - videow)>>1;
|
||||
posy <= (h - videoh)>>1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
else
|
||||
if(~waitrequest && state)
|
||||
begin
|
||||
if(state == 1) begin
|
||||
wcalc <= VSET ? (VSET*arx)/ary : (HEIGHT*arx)/ary;
|
||||
hcalc <= (WIDTH*ary)/arx;
|
||||
end
|
||||
state <= state + 1'd1;
|
||||
write <= 0;
|
||||
if((state&3)==3) begin
|
||||
|
||||
Reference in New Issue
Block a user