Skip to content

Commit

Permalink
crg: support VGA pixel clock reprogramming
Browse files Browse the repository at this point in the history
Sebastien Bourdeauducq committed Mar 28, 2013

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 1e860c7 commit 8fd092c
Showing 4 changed files with 81 additions and 23 deletions.
51 changes: 49 additions & 2 deletions milkymist/m1crg/__init__.py
Original file line number Diff line number Diff line change
@@ -3,8 +3,9 @@
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 @@ def __init__(self, pads, outfreq1x):
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 @@ def __init__(self, pads, outfreq1x):
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))
4 changes: 4 additions & 0 deletions software/include/hw/flags.h
Original file line number Diff line number Diff line change
@@ -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 */
27 changes: 14 additions & 13 deletions top.py
Original file line number Diff line number Diff line change
@@ -65,17 +65,18 @@ def __init__(self, platform):
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 @@ def __init__(self, platform):
#
# 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()
@@ -151,11 +153,10 @@ def __init__(self, platform):
#
for k, v in sorted(self.interrupt_map.items(), key=itemgetter(1)):
self.comb += self.cpu.interrupt[v].eq(getattr(self, k).ev.irq)

#
# 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)
22 changes: 14 additions & 8 deletions verilog/m1crg/m1crg.v
Original file line number Diff line number Diff line change
@@ -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 #(

0 comments on commit 8fd092c

Please sign in to comment.