Update API.

This commit is contained in:
sorgelig
2018-03-05 17:01:32 +08:00
parent b1ac401404
commit d5e11c35c7
4 changed files with 168 additions and 95 deletions

102
sys/osd.v
View File

@@ -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;

View File

@@ -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}]

View File

@@ -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),

View File

@@ -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