Update scaler.

This commit is contained in:
sorgelig
2018-12-31 07:09:18 +08:00
parent f554a0fc97
commit 047ef649e4
5 changed files with 819 additions and 583 deletions

File diff suppressed because it is too large Load Diff

239
sys/pll_hdmi_adj.vhd Normal file
View File

@@ -0,0 +1,239 @@
--------------------------------------------------------------------------------
-- HDMI PLL Adjust
--------------------------------------------------------------------------------
-- Changes the HDMI PLL frequency according to the scaler suggestions.
--------------------------------------------
-- LLTUNE :
-- 15 : Toggle
-- 14 : Unused
-- 13 : Sign phase difference
-- 12:8 : Phase difference. Log (0=Large 31=Small)
-- 7:6 : Unused
-- 5 : Sign period difference.
-- 4:0 : Period difference. Log (0=Large 31=Small)
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY pll_hdmi_adj IS
PORT (
-- Scaler
llena : IN std_logic; -- 0=Disabled 1=Enabled
lltune : IN unsigned(15 DOWNTO 0); -- Outputs from scaler
-- Signals from reconfig commands
i_waitrequest : OUT std_logic;
i_write : IN std_logic;
i_address : IN unsigned(5 DOWNTO 0);
i_writedata : IN unsigned(31 DOWNTO 0);
-- Outputs to PLL_HDMI_CFG
o_waitrequest : IN std_logic;
o_write : OUT std_logic;
o_address : OUT unsigned(5 DOWNTO 0);
o_writedata : OUT unsigned(31 DOWNTO 0);
------------------------------------
clk : IN std_logic;
reset_na : IN std_logic
);
BEGIN
END ENTITY pll_hdmi_adj;
--##############################################################################
ARCHITECTURE rtl OF pll_hdmi_adj IS
SIGNAL pwrite : std_logic;
SIGNAL paddress : unsigned(5 DOWNTO 0);
SIGNAL pdata : unsigned(31 DOWNTO 0);
TYPE enum_state IS (sIDLE,sW1,sW2,sW3);
SIGNAL state : enum_state;
SIGNAL lltune_sync,lltune_sync2,lltune_sync3 : unsigned(15 DOWNTO 0);
SIGNAL mfrac,mfrac_mem : unsigned(31 DOWNTO 0);
SIGNAL sign,sign_pre : std_logic;
SIGNAL up,modo,phm,dir : std_logic;
SIGNAL fcpt : natural RANGE 0 TO 3;
SIGNAL cptx : natural RANGE 0 TO 3;
SIGNAL cpt : natural RANGE 0 TO 4095;
SIGNAL phcor : natural RANGE 0 TO 3;
SIGNAL diff : unsigned(31 DOWNTO 0);
TYPE enum_tstate IS (sWAIT,sADJ,sADJ2);
SIGNAL tstate : enum_tstate;
BEGIN
----------------------------------------------------------------------------
-- 000010 : Start reg "Write either 0 or 1 to start fractional PLL reconf.
-- 000111 : M counter Fractional Value
Comb:PROCESS(i_write,i_address,
i_writedata,pwrite,paddress,pdata) IS
BEGIN
IF i_write='1' THEN
o_write <=i_write;
o_address <=i_address;
o_writedata <=i_writedata;
ELSE
o_write <=pwrite;
o_address <=paddress;
o_writedata<=pdata;
END IF;
END PROCESS Comb;
i_waitrequest<=o_waitrequest WHEN state=sIDLE ELSE '0';
----------------------------------------------------------------------------
Schmurtz:PROCESS(clk,reset_na) IS
VARIABLE off,ofp : natural RANGE 0 TO 63;
VARIABLE dif : unsigned(31 DOWNTO 0);
BEGIN
IF reset_na='0' THEN
modo<='0';
state<=sIDLE;
ELSIF rising_edge(clk) THEN
IF i_address="000111" AND i_write='1' THEN
mfrac<=i_writedata;
mfrac_mem<=i_writedata;
modo<='1';
END IF;
lltune_sync<=lltune; -- <ASYNC>
lltune_sync2<=lltune_sync;
lltune_sync3<=lltune_sync2;
off:=to_integer('0' & lltune_sync(4 DOWNTO 0));
ofp:=to_integer('0' & lltune_sync(12 DOWNTO 8));
IF lltune_sync(15)/=lltune_sync2(15) THEN
fcpt<=fcpt+1;
IF fcpt=2 THEN fcpt<=0; END IF;
END IF;
CASE tstate IS
WHEN sWAIT =>
cpt<=0;
IF lltune_sync3(15)/=lltune_sync2(15) AND llena='1' THEN
IF llena='0' THEN
-- Recover original freq when disabling low lag mode
phm<='0';
IF modo='1' THEN
mfrac<=mfrac_mem;
up<='1';
modo<='0';
END IF;
ELSIF phm='0' AND fcpt=2 THEN
-- Frequency adjust
IF off<10 THEN off:=10; END IF;
dif:=shift_right(mfrac,off + 1);
diff<=dif;
sign<=lltune_sync(5);
IF off>=18 THEN
phm<='1';
ELSE
tstate<=sADJ;
END IF;
cptx<=0;
ELSIF phm='1' THEN
-- Phase adjust
IF ofp<5 THEN ofp:=5; END IF;
dif:=shift_right(mfrac,ofp + 3 + 1);
IF (ofp>=18 OR off<16) AND fcpt=2 AND phcor=0 THEN
phm<='0';
END IF;
IF phcor=0 THEN
IF cptx=0 THEN
sign<=NOT lltune_sync(13);
sign_pre<=sign;
diff<=dif;
IF sign_pre/=NOT lltune_sync(13) THEN
diff<='0' & dif(31 DOWNTO 1);
END IF;
END IF;
cptx<=cptx+1;
IF cptx=2 THEN
cptx<=0;
sign<=NOT sign;
phcor<=1;
END IF;
tstate<=sADJ;
ELSIF phcor=1 THEN
cptx<=cptx+1;
IF cptx=2 THEN
cptx<=0;
phcor<=2;
tstate<=sADJ;
END IF;
ELSIF fcpt=2 THEN
phcor<=0;
cptx<=0;
END IF;
END IF;
END IF;
WHEN sADJ =>
IF sign='0' THEN
mfrac<=mfrac + diff(31 DOWNTO 8);
ELSE
mfrac<=mfrac - diff(31 DOWNTO 8);
END IF;
IF up='0' THEN
up<='1';
tstate<=sADJ2;
END IF;
WHEN sADJ2 =>
cpt<=cpt+1;
IF cpt=1023 THEN
tstate<=sWAIT;
ELSE
tstate<=sADJ;
END IF;
END CASE;
------------------------------------------------------
CASE state IS
WHEN sIDLE =>
pwrite<='0';
IF up='1' THEN
up<='0';
state<=sW1;
pdata<=mfrac;
paddress<="000111";
pwrite<='1';
END IF;
WHEN sW1 =>
IF pwrite='1' AND o_waitrequest='0' THEN
state<=sW2;
pwrite<='0';
END IF;
WHEN sW2 =>
pdata<=x"0000_0001";
paddress<="000010";
pwrite<='1';
state<=sW3;
WHEN sW3 =>
IF pwrite='1' AND o_waitrequest='0' THEN
pwrite<='0';
state<=sIDLE;
END IF;
END CASE;
END IF;
END PROCESS Schmurtz;
----------------------------------------------------------------------------
END ARCHITECTURE rtl;

View File

@@ -4,6 +4,7 @@ set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) p
set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ]
set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi_cfg.qip ]
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 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) scanlines.v ]

View File

@@ -8,6 +8,7 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) p
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg/altera_pll_reconfig_core.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) pll_hdmi_cfg/altera_pll_reconfig_top.v ]
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 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) scanlines.v ]

View File

@@ -216,6 +216,7 @@ reg coef_set = 0;
wire [7:0] ARX, ARY;
reg [11:0] VSET = 0;
reg [2:0] scaler_flt;
reg lowlat = 0;
always@(posedge clk_sys) begin
reg [7:0] cmd;
@@ -273,8 +274,9 @@ always@(posedge clk_sys) begin
if(cnt[1:0]==2) begin
cfg_custom_p2[31:16] <= io_din;
cfg_custom_t <= ~cfg_custom_t;
cnt[1:0] <= 0;
cnt[2:0] <= 3'b100;
end
if(cnt == 8) lowlat <= io_din[15];
end
end
if(cmd == 'h25) {led_overtake, led_state} <= io_din;
@@ -434,6 +436,12 @@ vip_config vip_config
.writedata(ctl_writedata),
.waitrequest(ctl_waitrequest)
);
assign cfg_write = adj_write;
assign cfg_address = adj_address;
assign cfg_data = adj_data;
assign adj_waitrequest = cfg_waitrequest;
`endif
@@ -523,6 +531,7 @@ ascal
(
.reset_na (~reset_req),
.run (1),
.freeze (0),
.i_clk (clk_vid),
.i_ce (ce_pix),
@@ -560,7 +569,7 @@ ascal
.vmin (vmin),
.vmax (vmax),
.mode ({1'b1,scaler_flt ? 3'd6 : 3'd0}),
.mode ({~lowlat,|scaler_flt,2'b00}),
.poly_clk (clk_sys),
.poly_a (coef_addr),
.poly_dw (coef_data),
@@ -609,6 +618,23 @@ always @(posedge clk_vid) begin
endcase
end
pll_hdmi_adj pll_hdmi_adj
(
.clk(FPGA_CLK1_50),
.reset_na(~reset_req),
.llena(lowlat),
.lltune(lltune),
.i_waitrequest(adj_waitrequest),
.i_write(adj_write),
.i_address(adj_address),
.i_writedata(adj_data),
.o_waitrequest(cfg_waitrequest),
.o_write(cfg_write),
.o_address(cfg_address),
.o_writedata(cfg_data)
);
`endif
@@ -635,10 +661,10 @@ reg [11:0] VBP = 36;
wire [63:0] reconfig_to_pll;
wire [63:0] reconfig_from_pll;
wire cfg_waitrequest;
reg cfg_write;
reg [5:0] cfg_address;
reg [31:0] cfg_data;
wire cfg_waitrequest,adj_waitrequest;
reg cfg_write,adj_write;
reg [5:0] cfg_address,adj_address;
reg [31:0] cfg_data,adj_data;
pll_hdmi_cfg pll_hdmi_cfg
(
@@ -664,24 +690,24 @@ always @(posedge FPGA_CLK1_50) begin
gotd <= cfg_got;
gotd2 <= gotd;
cfg_write <= 0;
adj_write <= 0;
custd <= cfg_custom_t;
custd2 <= custd;
if(custd2 != custd & ~gotd) begin
cfg_address <= cfg_custom_p1;
cfg_data <= cfg_custom_p2;
cfg_write <= 1;
adj_address <= cfg_custom_p1;
adj_data <= cfg_custom_p2;
adj_write <= 1;
end
if(~gotd2 & gotd) begin
cfg_address <= 2;
cfg_data <= 0;
cfg_write <= 1;
adj_address <= 2;
adj_data <= 0;
adj_write <= 1;
end
old_wait <= cfg_waitrequest;
if(old_wait & ~cfg_waitrequest & gotd) cfg_ready <= 1;
old_wait <= adj_waitrequest;
if(old_wait & ~adj_waitrequest & gotd) cfg_ready <= 1;
end
hdmi_config hdmi_config
@@ -883,6 +909,7 @@ wire [1:0] audio_mix;
wire [7:0] r_out, g_out, b_out;
wire vs, hs, de, f1;
wire [1:0] scanlines;
wire [15:0] lltune;
wire clk_sys, clk_vid, ce_pix;
wire ram_clk;