Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 7 commits
  • 8 files changed
  • 0 commit comments
  • 1 contributor
38 misoclib/dvisampler/clocking.py
View
@@ -7,6 +7,14 @@ def __init__(self, pads):
self._r_pll_reset = CSRStorage(reset=1)
self._r_locked = CSRStatus()
+ # DRP
+ self._r_pll_adr = CSRStorage(5)
+ self._r_pll_dat_r = CSRStatus(16)
+ self._r_pll_dat_w = CSRStorage(16)
+ self._r_pll_read = CSR()
+ self._r_pll_write = CSR()
+ self._r_pll_drdy = CSRStatus()
+
self.locked = Signal()
self.serdesstrobe = Signal()
self.clock_domains._cd_pix = ClockDomain()
@@ -23,18 +31,32 @@ def __init__(self, pads):
pll_clk0 = Signal()
pll_clk1 = Signal()
pll_clk2 = Signal()
- self.specials += Instance("PLL_BASE",
- p_CLKIN_PERIOD=26.7,
- p_CLKFBOUT_MULT=20,
- p_CLKOUT0_DIVIDE=2, # pix10x
- p_CLKOUT1_DIVIDE=10, # pix2x
- p_CLKOUT2_DIVIDE=20, # pix
+ pll_drdy = Signal()
+ self.sync += If(self._r_pll_read.re | self._r_pll_write.re,
+ self._r_pll_drdy.status.eq(0)
+ ).Elif(pll_drdy,
+ self._r_pll_drdy.status.eq(1)
+ )
+ self.specials += Instance("PLL_ADV",
+ p_CLKFBOUT_MULT=10,
+ p_CLKOUT0_DIVIDE=1, # pix10x
+ p_CLKOUT1_DIVIDE=5, # pix2x
+ p_CLKOUT2_DIVIDE=10, # pix
p_COMPENSATION="INTERNAL",
- i_CLKIN=clk_se,
+ i_CLKINSEL=1,
+ i_CLKIN1=clk_se,
o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
- o_LOCKED=pll_locked, i_RST=self._r_pll_reset.storage)
+ o_LOCKED=pll_locked, i_RST=self._r_pll_reset.storage,
+
+ i_DADDR=self._r_pll_adr.storage,
+ o_DO=self._r_pll_dat_r.status,
+ i_DI=self._r_pll_dat_w.storage,
+ i_DEN=self._r_pll_read.re | self._r_pll_write.re,
+ i_DWE=self._r_pll_write.re,
+ o_DRDY=pll_drdy,
+ i_DCLK=ClockSignal())
locked_async = Signal()
self.specials += [
39 misoclib/framebuffer/phy.py
View
@@ -58,6 +58,14 @@ def __init__(self, pads_vga, pads_dvi):
self.clock_domains.cd_pix = ClockDomain(reset_less=True)
if pads_dvi is not None:
+ self._r_pll_reset = CSRStorage()
+ self._r_pll_adr = CSRStorage(5)
+ self._r_pll_dat_r = CSRStatus(16)
+ self._r_pll_dat_w = CSRStorage(16)
+ self._r_pll_read = CSR()
+ self._r_pll_write = CSR()
+ self._r_pll_drdy = CSRStatus()
+
self.clock_domains.cd_pix2x = ClockDomain(reset_less=True)
self.clock_domains.cd_pix10x = ClockDomain(reset_less=True)
self.serdesstrobe = Signal()
@@ -124,19 +132,34 @@ def __init__(self, pads_vga, pads_dvi):
pll_clk1 = Signal()
pll_clk2 = Signal()
locked_async = Signal()
+ pll_drdy = Signal()
+ self.sync += If(self._r_pll_read.re | self._r_pll_write.re,
+ self._r_pll_drdy.status.eq(0)
+ ).Elif(pll_drdy,
+ self._r_pll_drdy.status.eq(1)
+ )
self.specials += [
- Instance("PLL_BASE",
- p_CLKIN_PERIOD=26.7,
- p_CLKFBOUT_MULT=20,
- p_CLKOUT0_DIVIDE=2, # pix10x
- p_CLKOUT1_DIVIDE=10, # pix2x
- p_CLKOUT2_DIVIDE=20, # pix
+ Instance("PLL_ADV",
+ p_CLKFBOUT_MULT=10,
+ p_CLKOUT0_DIVIDE=1, # pix10x
+ p_CLKOUT1_DIVIDE=5, # pix2x
+ p_CLKOUT2_DIVIDE=10, # pix
p_COMPENSATION="INTERNAL",
- i_CLKIN=clk_pix_unbuffered,
+ i_CLKINSEL=1,
+ i_CLKIN1=clk_pix_unbuffered,
o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
- o_LOCKED=pll_locked, i_RST=~pix_locked),
+ o_LOCKED=pll_locked,
+ i_RST=~pix_locked | self._r_pll_reset.storage,
+
+ i_DADDR=self._r_pll_adr.storage,
+ o_DO=self._r_pll_dat_r.status,
+ i_DI=self._r_pll_dat_w.storage,
+ i_DEN=self._r_pll_read.re | self._r_pll_write.re,
+ i_DWE=self._r_pll_write.re,
+ o_DRDY=pll_drdy,
+ i_DCLK=ClockSignal()),
Instance("BUFPLL", p_DIVIDE=5,
i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix2x"), i_LOCKED=pll_locked,
o_IOCLK=self.cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe),
2  software/videomixer/Makefile
View
@@ -1,7 +1,7 @@
MSCDIR=../..
include $(MSCDIR)/software/common.mak
-OBJECTS=isr.o processor.o dvisampler0.o dvisampler1.o edid.o ci.o main.o
+OBJECTS=isr.o processor.o dvisampler0.o dvisampler1.o edid.o pll.o ci.o main.o
all: videomixer.bin videomixer.fbi
6 software/videomixer/ci.c
View
@@ -6,6 +6,7 @@
#include "dvisampler0.h"
#include "dvisampler1.h"
#include "processor.h"
+#include "pll.h"
#include "ci.h"
static void print_mem_bandwidth(void)
@@ -71,6 +72,9 @@ void ci_service(void)
case 'm':
print_mem_bandwidth();
break;
- }
+ case 'p':
+ pll_dump();
+ break;
+ }
}
}
1  software/videomixer/dvisamplerX.c
View
@@ -118,6 +118,7 @@ void dvisamplerX_disable(void)
dvisamplerX_dma_slot0_status_write(DVISAMPLER_SLOT_EMPTY);
dvisamplerX_dma_slot1_status_write(DVISAMPLER_SLOT_EMPTY);
+ dvisamplerX_clocking_pll_reset_write(1);
}
void dvisamplerX_clear_framebuffers(void)
107 software/videomixer/pll.c
View
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#include <hw/csr.h>
+
+#include "pll.h"
+
+/*
+ * Despite varying pixel clocks, we must keep the PLL VCO operating
+ * in the specified range of 400MHz - 1000MHz.
+ * This code can program two sets of DRP data:
+ * 1. with VCO operating at 20x the pixel clock (for 20MHz - 50MHz pixel clock)
+ * 2. with VCO operating at 10x the pixel clock (for 40MHz - 100MHz pixel clock)
+ */
+
+static const unsigned short int pll_config_20x[32] = {
+ 0x0006, 0x0008, 0x0000, 0x4400, 0x1708, 0x0097, 0x0501, 0x8288,
+ 0x4201, 0x0d90, 0x00a1, 0x0111, 0x1004, 0x2028, 0x0802, 0x2800,
+ 0x0288, 0x8058, 0x020c, 0x0200, 0x1210, 0x400b, 0xfc21, 0x0b21,
+ 0x7f5f, 0xc0eb, 0x472a, 0xc02a, 0x20b6, 0x0e96, 0x1002, 0xd6ce
+};
+
+static const unsigned short int pll_config_10x[32] = {
+ 0x0006, 0x0008, 0x0000, 0x4400, 0x1708, 0x0097, 0x0901, 0x8118,
+ 0x4181, 0x0d60, 0x00a1, 0x0111, 0x1004, 0x2028, 0x0802, 0x0608,
+ 0x0148, 0x8018, 0x020c, 0x0200, 0x1210, 0x400b, 0xfc21, 0x0b22,
+ 0x5fdf, 0x40eb, 0x472b, 0xc02a, 0x20b6, 0x0e96, 0x1002, 0xd6ce
+};
+
+static void program_data(const unsigned short *data)
+{
+ int i;
+
+ /*
+ * Some bits of words 4 and 5 appear to depend on PLL location,
+ * so we start at word 6.
+ * PLLs also seem to dislike any write to the last words.
+ */
+ for(i=6;i<32-5;i++) {
+ fb_driver_clocking_pll_adr_write(i);
+ fb_driver_clocking_pll_dat_w_write(data[i]);
+ fb_driver_clocking_pll_write_write(1);
+ while(!fb_driver_clocking_pll_drdy_read());
+ }
+ for(i=6;i<32-5;i++) {
+ dvisampler0_clocking_pll_adr_write(i);
+ dvisampler0_clocking_pll_dat_w_write(data[i]);
+ dvisampler0_clocking_pll_write_write(1);
+ while(!dvisampler0_clocking_pll_drdy_read());
+ }
+ for(i=6;i<32-5;i++) {
+ dvisampler1_clocking_pll_adr_write(i);
+ dvisampler1_clocking_pll_dat_w_write(data[i]);
+ dvisampler1_clocking_pll_write_write(1);
+ while(!dvisampler1_clocking_pll_drdy_read());
+ }
+}
+
+void pll_config_for_clock(int freq)
+{
+ /*
+ * FIXME:
+ * 10x configuration causes random IDELAY lockups (at high frequencies it seems)
+ * 20x configuration seems to always work, even with overclocked VCO
+ * Reproducible both with DRP and initial reconfiguration.
+ * Until this spartan6 weirdness is sorted out, just stick to 20x.
+ */
+ program_data(pll_config_20x);
+#ifdef XILINX_SPARTAN6_WORKS_AMAZINGLY_WELL
+ if(freq < 2000)
+ printf("Frequency too low for PLLs\n");
+ else if(freq < 4500)
+ program_data(pll_config_20x);
+ else if(freq < 10000)
+ program_data(pll_config_10x);
+ else
+ printf("Frequency too high for PLLs\n");
+#endif
+}
+
+void pll_dump(void)
+{
+ int i;
+
+ printf("framebuffer PLL:\n");
+ for(i=0;i<32;i++) {
+ fb_driver_clocking_pll_adr_write(i);
+ fb_driver_clocking_pll_read_write(1);
+ while(!fb_driver_clocking_pll_drdy_read());
+ printf("%04x ", fb_driver_clocking_pll_dat_r_read());
+ }
+ printf("\n");
+ printf("dvisampler0 PLL:\n");
+ for(i=0;i<32;i++) {
+ dvisampler0_clocking_pll_adr_write(i);
+ dvisampler0_clocking_pll_read_write(1);
+ while(!dvisampler0_clocking_pll_drdy_read());
+ printf("%04x ", dvisampler0_clocking_pll_dat_r_read());
+ }
+ printf("\n");
+ printf("dvisampler1 PLL:\n");
+ for(i=0;i<32;i++) {
+ dvisampler1_clocking_pll_adr_write(i);
+ dvisampler1_clocking_pll_read_write(1);
+ while(!dvisampler1_clocking_pll_drdy_read());
+ printf("%04x ", dvisampler1_clocking_pll_dat_r_read());
+ }
+ printf("\n");
+}
7 software/videomixer/pll.h
View
@@ -0,0 +1,7 @@
+#ifndef __PLL_H
+#define __PLL_H
+
+void pll_config_for_clock(int freq);
+void pll_dump(void);
+
+#endif
4 software/videomixer/processor.c
View
@@ -7,6 +7,7 @@
#include "dvisampler0.h"
#include "dvisampler1.h"
#include "edid.h"
+#include "pll.h"
#include "processor.h"
/* reference: http://martin.hinner.info/vga/timing.html */
@@ -255,6 +256,7 @@ void processor_start(int mode)
const struct video_timing *m = &video_modes[mode];
fb_enable_write(0);
+ fb_driver_clocking_pll_reset_write(1);
dvisampler0_edid_hpd_en_write(0);
dvisampler1_edid_hpd_en_write(0);
@@ -263,11 +265,13 @@ void processor_start(int mode)
dvisampler0_clear_framebuffers();
dvisampler1_clear_framebuffers();
+ pll_config_for_clock(m->pixel_clock);
fb_set_mode(m);
edid_set_mode(m);
dvisampler0_init_video(m->h_active, m->v_active);
dvisampler1_init_video(m->h_active, m->v_active);
+ fb_driver_clocking_pll_reset_write(0);
fb_enable_write(1);
dvisampler0_edid_hpd_en_write(1);
dvisampler1_edid_hpd_en_write(1);

No commit comments for this range

Something went wrong with that request. Please try again.