crg: support VGA pixel clock reprogramming
This commit is contained in:
parent
1e860c7472
commit
8fd092ca12
|
@ -3,8 +3,9 @@ from fractions import Fraction
|
|||
from migen.fhdl.structure import *
|
||||
from migen.fhdl.specials import Instance
|
||||
from migen.fhdl.module import Module
|
||||
from migen.bank.description import *
|
||||
|
||||
class M1CRG(Module):
|
||||
class M1CRG(Module, AutoReg):
|
||||
def __init__(self, pads, outfreq1x):
|
||||
self.clock_domains.cd_sys = ClockDomain()
|
||||
self.clock_domains.cd_sys2x_270 = ClockDomain()
|
||||
|
@ -17,12 +18,22 @@ class M1CRG(Module):
|
|||
self.clk4x_wr_strb = Signal()
|
||||
self.clk4x_rd_strb = Signal()
|
||||
|
||||
self._r_cmd_data = RegisterField(10)
|
||||
self._r_send_cmd_data = RegisterRaw()
|
||||
self._r_send_go = RegisterRaw()
|
||||
self._r_status = RegisterField(3, READ_ONLY, WRITE_ONLY)
|
||||
|
||||
###
|
||||
|
||||
infreq = 50*1000000
|
||||
ratio = Fraction(outfreq1x)/Fraction(infreq)
|
||||
in_period = float(Fraction(1000000000)/Fraction(infreq))
|
||||
|
||||
vga_progdata = Signal()
|
||||
vga_progen = Signal()
|
||||
vga_progdone = Signal()
|
||||
vga_locked = Signal()
|
||||
|
||||
self.specials += Instance("m1crg",
|
||||
Instance.Parameter("in_period", in_period),
|
||||
Instance.Parameter("f_mult", ratio.numerator),
|
||||
|
@ -48,4 +59,40 @@ class M1CRG(Module):
|
|||
Instance.Output("ddr_clk_pad_p", pads.ddr_clk_p),
|
||||
Instance.Output("ddr_clk_pad_n", pads.ddr_clk_n),
|
||||
Instance.Output("eth_phy_clk_pad", pads.eth_phy_clk),
|
||||
Instance.Output("vga_clk_pad", pads.vga_clk))
|
||||
Instance.Output("vga_clk_pad", pads.vga_clk),
|
||||
|
||||
Instance.Input("vga_progclk", ClockSignal()),
|
||||
Instance.Input("vga_progdata", vga_progdata),
|
||||
Instance.Input("vga_progen", vga_progen),
|
||||
Instance.Output("vga_progdone", vga_progdone),
|
||||
Instance.Output("vga_locked", vga_locked))
|
||||
|
||||
remaining_bits = Signal(max=11)
|
||||
transmitting = Signal()
|
||||
self.comb += transmitting.eq(remaining_bits != 0)
|
||||
sr = Signal(10)
|
||||
self.sync += [
|
||||
If(self._r_send_cmd_data.re,
|
||||
remaining_bits.eq(10),
|
||||
sr.eq(self._r_cmd_data.field.r)
|
||||
).Elif(transmitting,
|
||||
remaining_bits.eq(remaining_bits - 1),
|
||||
sr.eq(sr[1:])
|
||||
)
|
||||
]
|
||||
self.comb += [
|
||||
vga_progdata.eq(transmitting & sr[0]),
|
||||
vga_progen.eq(transmitting | self._r_send_go.re)
|
||||
]
|
||||
|
||||
# enforce gap between commands
|
||||
busy_counter = Signal(max=14)
|
||||
busy = Signal()
|
||||
self.comb += busy.eq(busy_counter != 0)
|
||||
self.sync += If(self._r_send_cmd_data.re,
|
||||
busy_counter.eq(13)
|
||||
).Elif(busy,
|
||||
busy_counter.eq(busy_counter - 1)
|
||||
)
|
||||
|
||||
self.comb += self._r_status.field.w.eq(Cat(busy, vga_progdone, vga_locked))
|
||||
|
|
|
@ -18,4 +18,8 @@
|
|||
#define MINIMAC_EV_RX1 0x2
|
||||
#define MINIMAC_EV_TX 0x4
|
||||
|
||||
#define CLKGEN_STATUS_BUSY 0x1
|
||||
#define CLKGEN_STATUS_PROGDONE 0x2
|
||||
#define CLKGEN_STATUS_LOCKED 0x4
|
||||
|
||||
#endif /* __HW_FLAGS_H */
|
||||
|
|
25
top.py
25
top.py
|
@ -65,17 +65,18 @@ class M1ClockPads:
|
|||
class SoC(Module):
|
||||
csr_base = 0xe0000000
|
||||
csr_map = {
|
||||
"uart": 0,
|
||||
"dfii": 1,
|
||||
"identifier": 2,
|
||||
"timer0": 3,
|
||||
"minimac": 4,
|
||||
"fb": 5,
|
||||
"asmiprobe": 6,
|
||||
"dvisampler0": 7,
|
||||
"dvisampler0_edid_mem": 8,
|
||||
"dvisampler1": 9,
|
||||
"dvisampler1_edid_mem": 10,
|
||||
"crg": 0,
|
||||
"uart": 1,
|
||||
"dfii": 2,
|
||||
"identifier": 3,
|
||||
"timer0": 4,
|
||||
"minimac": 5,
|
||||
"fb": 6,
|
||||
"asmiprobe": 7,
|
||||
"dvisampler0": 8,
|
||||
"dvisampler0_edid_mem": 9,
|
||||
"dvisampler1": 10,
|
||||
"dvisampler1_edid_mem": 11,
|
||||
}
|
||||
|
||||
interrupt_map = {
|
||||
|
@ -134,6 +135,7 @@ class SoC(Module):
|
|||
#
|
||||
# CSR
|
||||
#
|
||||
self.submodules.crg = m1crg.M1CRG(M1ClockPads(platform), clk_freq)
|
||||
self.submodules.uart = uart.UART(platform.request("serial"), clk_freq, baud=115200)
|
||||
self.submodules.identifier = identifier.Identifier(0x4D31, version, int(clk_freq))
|
||||
self.submodules.timer0 = timer.Timer()
|
||||
|
@ -155,7 +157,6 @@ class SoC(Module):
|
|||
#
|
||||
# Clocking
|
||||
#
|
||||
self.submodules.crg = m1crg.M1CRG(M1ClockPads(platform), clk_freq)
|
||||
self.comb += [
|
||||
self.ddrphy.clk4x_wr_strb.eq(self.crg.clk4x_wr_strb),
|
||||
self.ddrphy.clk4x_rd_strb.eq(self.crg.clk4x_rd_strb)
|
||||
|
|
|
@ -33,7 +33,14 @@ module m1crg #(
|
|||
|
||||
/* VGA clock */
|
||||
output vga_clk, /* < buffered, to internal clock network */
|
||||
output vga_clk_pad /* < forwarded through ODDR2, to I/O */
|
||||
output vga_clk_pad, /* < forwarded through ODDR2, to I/O */
|
||||
|
||||
/* VGA clock control */
|
||||
input vga_progclk,
|
||||
input vga_progdata,
|
||||
input vga_progen,
|
||||
output vga_progdone,
|
||||
output vga_locked
|
||||
);
|
||||
|
||||
/*
|
||||
|
@ -257,7 +264,6 @@ assign eth_tx_clk = eth_tx_clk_pad;
|
|||
* VGA clock
|
||||
*/
|
||||
|
||||
// TODO: hook up the reprogramming interface
|
||||
DCM_CLKGEN #(
|
||||
.CLKFXDV_DIVIDE(2),
|
||||
.CLKFX_DIVIDE(4),
|
||||
|
@ -270,15 +276,15 @@ DCM_CLKGEN #(
|
|||
.CLKFX(vga_clk),
|
||||
.CLKFX180(),
|
||||
.CLKFXDV(),
|
||||
.LOCKED(),
|
||||
.PROGDONE(),
|
||||
.STATUS(),
|
||||
.CLKIN(pllout4),
|
||||
.FREEZEDCM(1'b0),
|
||||
.PROGCLK(1'b0),
|
||||
.PROGDATA(),
|
||||
.PROGEN(1'b0),
|
||||
.RST(1'b0)
|
||||
.PROGCLK(vga_progclk),
|
||||
.PROGDATA(vga_progdata),
|
||||
.PROGEN(vga_progen),
|
||||
.PROGDONE(vga_progdone),
|
||||
.LOCKED(vga_locked),
|
||||
.RST(~pll_lckd)
|
||||
);
|
||||
|
||||
ODDR2 #(
|
||||
|
|
Loading…
Reference in New Issue