make pll_reconfig more robust

This commit is contained in:
marqs 2019-10-12 20:16:22 +03:00
parent 8e7236dc00
commit 85c295c5e2
8 changed files with 7454 additions and 7358 deletions

View File

@ -26,7 +26,9 @@ typedef union {
struct {
alt_u8 reset:1;
alt_u8 update:1;
alt_u32 pll_reconfig_rsv:29;
alt_u8 t_config_id:4;
alt_u32 pll_reconfig_rsv:21;
alt_u8 c_config_id:4;
alt_u8 busy:1;
} __attribute__((packed, __may_alias__));
alt_u32 data;

View File

@ -56,10 +56,12 @@ reg [1:0] state;
reg scan_shift;
reg scandone_prev;
reg configupdate_pre;
reg [7:0] ctr;
reg [7:0] shift_ctr;
wire pll_reset = pll_config_status[0];
wire start_update = pll_config_status[1];
wire [3:0] t_config_id = pll_config_status[5:2];
wire [3:0] c_config_id = pll_config_status[30:27];
wire config_busy = pll_config_status[31];
assign areset = pll_reset | areset_strobe;
@ -141,7 +143,7 @@ begin
if (start_update) begin
pll_config_status[31] <= 1'b1;
scanclkena <= 1'b1;
ctr <= PLL_CONFIG_DATA_BITS;
shift_ctr <= PLL_CONFIG_DATA_BITS;
state <= STATE_SHIFT;
end else begin
pll_config_status[31] <= 1'b0;
@ -150,22 +152,23 @@ begin
STATE_SHIFT:
begin
scan_shift <= 1'b1;
if (ctr > 0) begin
ctr <= ctr - 1'b1;
if (shift_ctr > 0) begin
shift_ctr <= shift_ctr - 1'b1;
end else begin
scan_shift <= 1'b0;
scanclkena <= 1'b0;
configupdate_pre <= 1'b1;
ctr <= 8'hff;
state <= STATE_WAITRESP;
end
end
STATE_WAITRESP:
begin
configupdate_pre <= 1'b0;
ctr <= ctr - 1'b1;
if (scandone_prev | (ctr == 8'h0)) begin
if (pll_reset) begin
state <= STATE_IDLE;
end else if (scandone_prev) begin
areset_strobe <= 1'b1;
pll_config_status[30:27] <= t_config_id;
state <= STATE_IDLE;
end
end

View File

@ -106,7 +106,7 @@ wire osd_enable = osd_enable_pre & ~lt_active;
wire [10:0] xpos, xpos_sc, xpos_vg;
wire [10:0] ypos, ypos_sc, ypos_vg;
wire pll_areset, pll_scanclk, pll_scanclkena, pll_configupdate, pll_scandata, pll_scandone;
wire pll_areset, pll_scanclk, pll_scanclkena, pll_configupdate, pll_scandata, pll_scandone, pll_activeclock;
// Latch inputs from TVP7002 (synchronized to PCLK_in)
@ -236,7 +236,7 @@ sys sys_inst(
.i2c_opencores_1_export_sda_pad_io (SD_CMD),
.i2c_opencores_1_export_spi_miso_pad_i (SD_DAT[0]),
.pio_0_sys_ctrl_out_export (sys_ctrl),
.pio_1_controls_in_export ({ir_code_cnt, 5'b00000, HDMI_TX_MODE_LL, btn_LL, ir_code}),
.pio_1_controls_in_export ({ir_code_cnt, 4'b0000, pll_activeclock, HDMI_TX_MODE_LL, btn_LL, ir_code}),
.sc_config_0_sc_if_sc_status_i ({vsync_flag, 2'b00, vmax_tvp, fpga_vsyncgen, 4'h0, ilace_flag, vmax}),
.sc_config_0_sc_if_sc_status2_i ({12'h000, pcnt_frame}),
.sc_config_0_sc_if_lt_status_i ({lt_finished, 3'h0, lt_stb_result, lt_lat_result}),
@ -300,7 +300,8 @@ scanconverter scanconverter_inst (
.pll_scanclkena (pll_scanclkena),
.pll_configupdate (pll_configupdate),
.pll_scandata (pll_scandata),
.pll_scandone (pll_scandone)
.pll_scandone (pll_scandone),
.pll_activeclock (pll_activeclock)
);
ir_rcv ir0 (

View File

@ -118,7 +118,8 @@ module scanconverter (
input pll_scanclkena,
input pll_configupdate,
input pll_scandata,
output pll_scandone
output pll_scandone,
output pll_activeclock
);
//clock-related signals and registers
@ -126,7 +127,6 @@ wire pclk_act;
wire pclk_1x, pclk_2x, pclk_3x, pclk_4x, pclk_5x;
wire [1:0] pclk_mux_sel;
wire pll_lock;
wire pll_activeclock;
reg pll_clkswitch;
//RGB signals&registers: 8 bits per component -> 16.7M colors

File diff suppressed because it is too large Load Diff

View File

@ -71,7 +71,7 @@ alt_u8 stable_frames;
alt_u8 update_cur_vm;
alt_u8 profile_sel, profile_sel_menu, input_profiles[AV_LAST], lt_sel, def_input, profile_link, lcd_bl_timeout;
alt_u8 osd_enable, osd_enable_pre=1, osd_status_timeout, osd_status_timeout_pre;
alt_u8 osd_enable, osd_enable_pre=1, osd_status_timeout, osd_status_timeout_pre=1;
alt_u8 auto_input, auto_av1_ypbpr, auto_av2_ypbpr = 1, auto_av3_ypbpr;
char row1[LCD_ROW_LEN+1], row2[LCD_ROW_LEN+1], menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
@ -97,9 +97,9 @@ alt_u32 read_it2(alt_u32 regaddr);
// 8. Compare your MIF/HEX to the captured scan chain and update it accordingly
// 9. Dump the updated scan chain data to an array like below (last 16 bits are 0)
// 10. PLL can be then reconfigured with custom pll_reconfig as shown in program_mode()
const alt_u32 pll_config_default_data[] = {0x0d806000, 0x00402010, 0x08040220, 0x00004022, 0x00000000};
const alt_u32 pll_config_2x_5x_data[] = {0x0dc06000, 0x00783c11, 0x070180e0, 0x0000180e, 0x00000000};
const alt_u32 pll_config_3x_4x_data[] = {0x0d806000, 0x00301804, 0x02014060, 0x00001406, 0x00000000};
const pll_config_t pll_configs[] = { {{0x0d806000, 0x00402010, 0x08040220, 0x00004022, 0x00000000}}, // 1x, 1x (default)
{{0x0dc06000, 0x00783c11, 0x070180e0, 0x0000180e, 0x00000000}}, // 2x, 5x
{{0x0d806000, 0x00301804, 0x02014060, 0x00001406, 0x00000000}} }; // 3x, 4x
volatile sc_regs *sc = (volatile sc_regs*)SC_CONFIG_0_BASE;
volatile osd_regs *osd = (volatile osd_regs*)OSD_GENERATOR_0_BASE;
@ -165,6 +165,41 @@ inline void TX_enable(tx_mode_t mode)
SetAVMute(FALSE);
}
void pll_reconfigure(alt_u8 id)
{
if ((id < sizeof(pll_configs)/sizeof(pll_config_t)) && (id != pll_reconfig->pll_config_status.c_config_id)) {
memcpy((void*)pll_reconfig->pll_config_data.data, pll_configs[id].data, sizeof(pll_config_t));
pll_reconfig->pll_config_status.t_config_id = id;
printf("Reconfiguring PLL to config %u\n", id);
// Try switching to fixed reference clock as otherwise reconfig may hang or corrupt configuration
if (cm.avinput != AV_TESTPAT) {
sys_ctrl &= ~VIDGEN_OFF;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
usleep(10);
}
// Do not reconfigure if clock switch failed
if ((IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & PLL_ACTIVECLK_MASK) == 0) {
// reset state machine if previous reconfigure hanged (should not occur with stable refclk)
if (pll_reconfig->pll_config_status.busy) {
pll_reconfig->pll_config_status.reset = 1;
usleep(1);
}
pll_reconfig->pll_config_status.reset = 0;
pll_reconfig->pll_config_status.update = 1;
usleep(10);
}
if (cm.avinput != AV_TESTPAT) {
sys_ctrl |= VIDGEN_OFF;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
}
}
}
void set_lpf(alt_u8 lpf)
{
alt_u32 pclk;
@ -330,6 +365,9 @@ status_t get_status(tvp_sync_input_t syncinput)
if ((tc.s400p_mode != cm.cc.s400p_mode) && (video_modes[cm.id].v_total == 449))
status = (status < MODE_CHANGE) ? MODE_CHANGE : status;
if (cm.pll_config != pll_reconfig->pll_config_status.c_config_id)
status = (status < MODE_CHANGE) ? MODE_CHANGE : status;
if (update_cur_vm) {
cm.h_mult_total = (video_modes[cm.id].h_total*cm.sample_mult) + ((cm.sample_mult*video_modes[cm.id].h_total_adj*5 + 50) / 100);
tvp_setup_hpll(cm.h_mult_total, clkcnt, cm.cc.tvp_hpll2x && (video_modes[cm.id].flags & MODE_PLLDIVBY2));
@ -576,7 +614,7 @@ void update_sc_config()
// Configure TVP7002 and scan converter logic based on the video mode
void program_mode()
{
alt_u8 h_syncinlen, v_syncinlen, hdmitx_pclk_level, osd_x_size, osd_y_size, pll_config;
alt_u8 h_syncinlen, v_syncinlen, hdmitx_pclk_level, osd_x_size, osd_y_size;
alt_u32 h_hz, v_hz_x100, h_synclen_px;
// Mark as stable (needed after sync up to avoid unnecessary mode switch)
@ -629,30 +667,21 @@ void program_mode()
set_csc(cm.cc.ypbpr_cs);
cm.sample_sel = tvp_set_hpll_phase(video_modes[cm.id].sampler_phase, cm.sample_mult);
pll_reconfig->pll_config_status.reset = (cm.fpga_vmultmode == FPGA_V_MULTMODE_1X);
switch (cm.fpga_vmultmode) {
case FPGA_V_MULTMODE_2X:
case FPGA_V_MULTMODE_5X:
pll_config = PLL_CONFIG_2X_5X;
cm.pll_config = PLL_CONFIG_2X_5X;
break;
case FPGA_V_MULTMODE_3X:
case FPGA_V_MULTMODE_4X:
pll_config = PLL_CONFIG_3X_4X;
cm.pll_config = PLL_CONFIG_3X_4X;
break;
default:
pll_config = cm.pll_config;
break;
}
while (pll_reconfig->pll_config_status.busy) {}
pll_reconfig->pll_config_status.reset = (cm.fpga_vmultmode == FPGA_V_MULTMODE_1X);
if (cm.pll_config != pll_config) {
if (pll_config == PLL_CONFIG_2X_5X)
memcpy((void*)pll_reconfig->pll_config_data.data, pll_config_2x_5x_data, sizeof(pll_config_2x_5x_data));
else
memcpy((void*)pll_reconfig->pll_config_data.data, pll_config_3x_4x_data, sizeof(pll_config_3x_4x_data));
pll_reconfig->pll_config_status.update = 1;
cm.pll_config = pll_config;
}
pll_reconfigure(cm.pll_config);
if (cm.fpga_vmultmode == FPGA_V_MULTMODE_1X) {
osd_x_size = (video_modes[cm.id].v_active > 700) ? 1 : 0;
@ -748,8 +777,7 @@ int init_hw()
// Reload initial PLL config (needed after jtagm_reset_req if config has changed).
// Note that test pattern gets restored only if pclk was active before jtagm_reset_req assertion.
memcpy((void*)pll_reconfig->pll_config_data.data, pll_config_default_data, sizeof(pll_config_default_data));
pll_reconfig->pll_config_status.update = 1;
pll_reconfigure(PLL_CONFIG_VG);
//wait >500ms for SD card interface to be stable
//over 200ms and LCD may be buggy?
@ -893,10 +921,10 @@ int latency_test() {
// Enable chip outputs
void enable_outputs()
{
// program video mode
program_mode();
// enable TVP output
tvp_enable_output();
// program video mode
program_mode();
// enable and unmute TX
TX_enable(tc.tx_mode);

View File

@ -44,6 +44,8 @@
// HDMI_TX definitions
#define HDMITX_MODE_MASK 0x00040000
#define PLL_ACTIVECLK_MASK 0x00080000
#define TX_PIXELREP_DISABLE 0
#define TX_PIXELREP_2X 1
#define TX_PIXELREP_4X 3
@ -84,6 +86,10 @@ typedef enum {
TX_DVI = 2
} tx_mode_t;
typedef struct {
alt_u32 data[5];
} pll_config_t;
//TODO: transform binary values into flags
typedef struct {
alt_u32 totlines;

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<EnsembleReport name="sys" kind="sys" version="1.0" fabric="QSYS">
<!-- Format version 17.1 590 (Future versions may contain additional information.) -->
<!-- 2019.10.10.00:51:29 -->
<!-- 2019.10.12.20:50:18 -->
<!-- A collection of modules and connections -->
<parameter name="AUTO_GENERATION_ID">
<type>java.lang.Integer</type>
<value>1570657889</value>
<value>1570902617</value>
<derived>false</derived>
<enabled>true</enabled>
<visible>false</visible>