Make the PLL arbitrarily configurable
This commit is contained in:
parent
371e425d38
commit
aead41b8b6
|
@ -1,47 +1,90 @@
|
||||||
|
import "/collections/namedtuple"
|
||||||
import "/nmigen/lib/cdc/ResetSynchronizer"
|
import "/nmigen/lib/cdc/ResetSynchronizer"
|
||||||
import "/nmigen_boards.icebreaker/ICEBreakerPlatform"
|
import "/nmigen_boards.icebreaker/ICEBreakerPlatform"
|
||||||
import "/nmigen_dg/*"
|
import "/nmigen_dg/*"
|
||||||
|
import "/subprocess"
|
||||||
import "/sys"
|
import "/sys"
|
||||||
|
import "common/pipeline"
|
||||||
import "resources/pmod"
|
import "resources/pmod"
|
||||||
|
|
||||||
|
|
||||||
|
run_icepll = current target ->
|
||||||
|
current /= 1e6 # Hz -> MHz
|
||||||
|
target /= 1e6 # Hz -> MHz
|
||||||
|
out = subprocess.run ["icepll", "-i", str current, "-o", str target]
|
||||||
|
capture_output: True
|
||||||
|
check: True
|
||||||
|
|
||||||
|
get_field = field substring:None ->
|
||||||
|
pipeline out.stdout.decode!.splitlines!
|
||||||
|
bind filter $ x -> x.startswith field
|
||||||
|
if
|
||||||
|
substring => bind filter $ x -> substring in x
|
||||||
|
otherwise => x -> x # nop
|
||||||
|
head
|
||||||
|
str.split
|
||||||
|
tail
|
||||||
|
head
|
||||||
|
|
||||||
|
(namedtuple "icepll_config" "FEEDBACK FILTER_RANGE DIVR DIVF DIVQ given requested achieved")
|
||||||
|
str$ get_field "FEEDBACK"
|
||||||
|
int$ get_field "FILTER_RANGE"
|
||||||
|
int$ get_field "DIVR"
|
||||||
|
int$ get_field "DIVF"
|
||||||
|
int$ get_field "DIVQ"
|
||||||
|
float$ get_field "F_PLLIN"
|
||||||
|
float$ get_field "F_PLLOUT" "(requested)"
|
||||||
|
float$ get_field "F_PLLOUT" "(achieved)"
|
||||||
|
|
||||||
|
|
||||||
Top = subclass Elaboratable where
|
Top = subclass Elaboratable where
|
||||||
elaborate = platform ~> m where with m = Module! =>
|
elaborate = platform ~> m where with m = Module! =>
|
||||||
reset = if
|
|
||||||
platform.default_rst => platform.request platform.default_rst
|
|
||||||
otherwise => Const 0
|
|
||||||
|
|
||||||
# setup clock
|
# setup clock
|
||||||
|
|
||||||
clk40 = Signal!
|
default_clk = platform.request platform.default_clk dir:"-"
|
||||||
pll_lock = Signal!
|
default_freq = platform.default_clk_frequency
|
||||||
|
default_reset = if
|
||||||
|
platform.default_rst => platform.request platform.default_rst
|
||||||
|
otherwise => Const 1
|
||||||
|
|
||||||
|
pll_config = run_icepll
|
||||||
|
default_freq
|
||||||
|
40e6
|
||||||
|
print dvi.timings
|
||||||
|
print pll_config
|
||||||
|
|
||||||
|
pll_clk, pll_lock = Signal!, Signal!
|
||||||
Submodule.pll$ Instance "SB_PLL40_PAD" # "SB_PLL40_CORE"
|
Submodule.pll$ Instance "SB_PLL40_PAD" # "SB_PLL40_CORE"
|
||||||
i_PACKAGEPIN : (platform.request "clk12" dir:"-") # i_REFERENCECLK
|
i_PACKAGEPIN : default_clk # i_REFERENCECLK
|
||||||
i_BYPASS : (Const 0)
|
i_BYPASS : (Const 0)
|
||||||
i_RESETB : ~reset
|
i_RESETB : default_reset
|
||||||
o_LOCK : pll_lock
|
o_LOCK : pll_lock
|
||||||
o_PLLOUTGLOBAL : clk40
|
o_PLLOUTGLOBAL : pll_clk
|
||||||
# icepll -o 40
|
p_FEEDBACK_PATH : pll_config.FEEDBACK
|
||||||
p_FEEDBACK_PATH : "SIMPLE"
|
p_FILTER_RANGE : pll_config.FILTER_RANGE
|
||||||
p_FILTER_RANGE : 1
|
p_DIVR : pll_config.DIVR
|
||||||
p_DIVR : 0
|
p_DIVF : pll_config.DIVF
|
||||||
p_DIVF : 52
|
p_DIVQ : pll_config.DIVQ
|
||||||
p_DIVQ : 4
|
|
||||||
|
|
||||||
#m.domains.sync = ClockDomain "sync"
|
|
||||||
Domains.sync = ClockDomain "sync"
|
Domains.sync = ClockDomain "sync"
|
||||||
Comb$ ClockSignal "sync" :== clk40
|
Comb$ ClockSignal "sync" :== pll_clk
|
||||||
Submodule$ ResetSynchronizer ~pll_lock domain: "sync"
|
|
||||||
|
|
||||||
|
Submodule.rs$ ResetSynchronizer
|
||||||
|
~pll_lock
|
||||||
|
domain: "sync"
|
||||||
|
|
||||||
|
|
||||||
|
# Simple test to see if the PLL works
|
||||||
state = Signal!
|
state = Signal!
|
||||||
counter = Signal$ range (int plat.default_clk_frequency)
|
counter = Signal$ range (int plat.default_clk_frequency)
|
||||||
Sync$ counter :== counter - 1
|
Sync$ counter :== counter - 1
|
||||||
When (counter==0) $ ->
|
When (counter==0) $ ->
|
||||||
Sync$ counter :== (int plat.default_clk_frequency)
|
Sync$ counter :== int plat.default_clk_frequency
|
||||||
Sync$ state :== ~state
|
Sync$ state :== ~state
|
||||||
Comb$ platform.request "led_r" :== state # blinks at 1hz with default clk, but way faster when at 40MHz
|
Comb$ platform.request "led_r" :== state
|
||||||
Comb$ platform.request "led_g" :== ~state # blinks at 1hz with default clk, but way faster when at 40MHz
|
Comb$ platform.request "led_g" :== ~state
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__" =>
|
if __name__ == "__main__" =>
|
||||||
|
|
Loading…
Reference in New Issue