*.bin
*.fbi
tools/flterm
-tools/mkmscimg
tools/byteswap
software/include/generated/*.h
software/include/generated/*.ld
software/include/generated/*.mak
-software/videomixer/dvisampler0.c
-software/videomixer/dvisampler0.h
-software/videomixer/dvisampler1.c
-software/videomixer/dvisampler1.h
+++ /dev/null
-import collections
-
-from migen.fhdl.std import *
-from migen.bank.description import *
-from migen.genlib.misc import optree
-from migen.genlib.cdc import MultiReg
-
-class CounterADC(Module, AutoCSR):
- def __init__(self, charge, sense, width=24):
- if not isinstance(sense, collections.Iterable):
- sense = [sense]
-
- channels = len(sense)
-
- self._start_busy = CSR()
- self._overflow = CSRStatus(channels)
- self._polarity = CSRStorage()
-
- count = Signal(width)
- busy = Signal(channels)
-
- res = []
- for i in range(channels):
- res.append(CSRStatus(width, name="res"+str(i)))
- setattr(self, "_res"+str(i), res[-1])
-
- any_busy = Signal()
- self.comb += [
- any_busy.eq(optree("|",
- [busy[i] for i in range(channels)])),
- self._start_busy.w.eq(any_busy)
- ]
-
- carry = Signal()
-
- self.sync += [
- If(self._start_busy.re,
- count.eq(0),
- busy.eq((1 << channels)-1),
- self._overflow.status.eq(0),
- charge.eq(~self._polarity.storage)
- ).Elif(any_busy,
- Cat(count, carry).eq(count + 1),
- If(carry,
- self._overflow.status.eq(busy),
- busy.eq(0)
- )
- ).Else(
- charge.eq(self._polarity.storage)
- )
- ]
-
- for i in range(channels):
- sense_synced = Signal()
- self.specials += MultiReg(sense[i], sense_synced)
- self.sync += If(busy[i],
- If(sense_synced != self._polarity.storage,
- res[i].status.eq(count),
- busy[i].eq(0)
- )
- )
+++ /dev/null
-from migen.fhdl.std import *
-from migen.bank.description import AutoCSR
-
-from misoclib.dvisampler.edid import EDID
-from misoclib.dvisampler.clocking import Clocking
-from misoclib.dvisampler.datacapture import DataCapture
-from misoclib.dvisampler.charsync import CharSync
-from misoclib.dvisampler.wer import WER
-from misoclib.dvisampler.decoding import Decoding
-from misoclib.dvisampler.chansync import ChanSync
-from misoclib.dvisampler.analysis import SyncPolarity, ResolutionDetection, FrameExtraction
-from misoclib.dvisampler.dma import DMA
-
-class DVISampler(Module, AutoCSR):
- def __init__(self, pads, lasmim, n_dma_slots=2):
- self.submodules.edid = EDID(pads)
- self.submodules.clocking = Clocking(pads)
-
- for datan in range(3):
- name = "data" + str(datan)
-
- cap = DataCapture(getattr(pads, name + "_p"), getattr(pads, name + "_n"), 8)
- setattr(self.submodules, name + "_cap", cap)
- self.comb += cap.serdesstrobe.eq(self.clocking.serdesstrobe)
-
- charsync = CharSync()
- setattr(self.submodules, name + "_charsync", charsync)
- self.comb += charsync.raw_data.eq(cap.d)
-
- wer = WER()
- setattr(self.submodules, name + "_wer", wer)
- self.comb += wer.data.eq(charsync.data)
-
- decoding = Decoding()
- setattr(self.submodules, name + "_decod", decoding)
- self.comb += [
- decoding.valid_i.eq(charsync.synced),
- decoding.input.eq(charsync.data)
- ]
-
- self.submodules.chansync = ChanSync()
- self.comb += [
- self.chansync.valid_i.eq(self.data0_decod.valid_o & \
- self.data1_decod.valid_o & self.data2_decod.valid_o),
- self.chansync.data_in0.eq(self.data0_decod.output),
- self.chansync.data_in1.eq(self.data1_decod.output),
- self.chansync.data_in2.eq(self.data2_decod.output),
- ]
-
- self.submodules.syncpol = SyncPolarity()
- self.comb += [
- self.syncpol.valid_i.eq(self.chansync.chan_synced),
- self.syncpol.data_in0.eq(self.chansync.data_out0),
- self.syncpol.data_in1.eq(self.chansync.data_out1),
- self.syncpol.data_in2.eq(self.chansync.data_out2)
- ]
-
- self.submodules.resdetection = ResolutionDetection()
- self.comb += [
- self.resdetection.valid_i.eq(self.syncpol.valid_o),
- self.resdetection.de.eq(self.syncpol.de),
- self.resdetection.vsync.eq(self.syncpol.vsync)
- ]
-
- self.submodules.frame = FrameExtraction(24*lasmim.dw//32)
- self.comb += [
- self.frame.valid_i.eq(self.syncpol.valid_o),
- self.frame.de.eq(self.syncpol.de),
- self.frame.vsync.eq(self.syncpol.vsync),
- self.frame.r.eq(self.syncpol.r),
- self.frame.g.eq(self.syncpol.g),
- self.frame.b.eq(self.syncpol.b)
- ]
-
- self.submodules.dma = DMA(lasmim, n_dma_slots)
- self.comb += self.frame.frame.connect(self.dma.frame)
- self.ev = self.dma.ev
-
- autocsr_exclude = {"ev"}
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg, PulseSynchronizer
-from migen.genlib.fifo import AsyncFIFO
-from migen.genlib.record import Record
-from migen.bank.description import *
-from migen.flow.actor import *
-
-from misoclib.dvisampler.common import channel_layout
-
-class SyncPolarity(Module):
- def __init__(self):
- self.valid_i = Signal()
- self.data_in0 = Record(channel_layout)
- self.data_in1 = Record(channel_layout)
- self.data_in2 = Record(channel_layout)
-
- self.valid_o = Signal()
- self.de = Signal()
- self.hsync = Signal()
- self.vsync = Signal()
- self.r = Signal(8)
- self.g = Signal(8)
- self.b = Signal(8)
-
- ###
-
- de = self.data_in0.de
- de_r = Signal()
- c = self.data_in0.c
- c_polarity = Signal(2)
- c_out = Signal(2)
-
- self.comb += [
- self.de.eq(de_r),
- self.hsync.eq(c_out[0]),
- self.vsync.eq(c_out[1])
- ]
-
- self.sync.pix += [
- self.valid_o.eq(self.valid_i),
- self.r.eq(self.data_in2.d),
- self.g.eq(self.data_in1.d),
- self.b.eq(self.data_in0.d),
-
- de_r.eq(de),
- If(de_r & ~de,
- c_polarity.eq(c),
- c_out.eq(0)
- ).Else(
- c_out.eq(c ^ c_polarity)
- )
- ]
-
-class ResolutionDetection(Module, AutoCSR):
- def __init__(self, nbits=11):
- self.valid_i = Signal()
- self.vsync = Signal()
- self.de = Signal()
-
- self._hres = CSRStatus(nbits)
- self._vres = CSRStatus(nbits)
-
- ###
-
- # Detect DE transitions
- de_r = Signal()
- pn_de = Signal()
- self.sync.pix += de_r.eq(self.de)
- self.comb += pn_de.eq(~self.de & de_r)
-
- # HRES
- hcounter = Signal(nbits)
- self.sync.pix += If(self.valid_i & self.de,
- hcounter.eq(hcounter + 1)
- ).Else(
- hcounter.eq(0)
- )
-
- hcounter_st = Signal(nbits)
- self.sync.pix += If(self.valid_i,
- If(pn_de, hcounter_st.eq(hcounter))
- ).Else(
- hcounter_st.eq(0)
- )
- self.specials += MultiReg(hcounter_st, self._hres.status)
-
- # VRES
- vsync_r = Signal()
- p_vsync = Signal()
- self.sync.pix += vsync_r.eq(self.vsync),
- self.comb += p_vsync.eq(self.vsync & ~vsync_r)
-
- vcounter = Signal(nbits)
- self.sync.pix += If(self.valid_i & p_vsync,
- vcounter.eq(0)
- ).Elif(pn_de,
- vcounter.eq(vcounter + 1)
- )
-
- vcounter_st = Signal(nbits)
- self.sync.pix += If(self.valid_i,
- If(p_vsync, vcounter_st.eq(vcounter))
- ).Else(
- vcounter_st.eq(0)
- )
- self.specials += MultiReg(vcounter_st, self._vres.status)
-
-class FrameExtraction(Module, AutoCSR):
- def __init__(self, word_width):
- # in pix clock domain
- self.valid_i = Signal()
- self.vsync = Signal()
- self.de = Signal()
- self.r = Signal(8)
- self.g = Signal(8)
- self.b = Signal(8)
-
- # in sys clock domain
- word_layout = [("sof", 1), ("pixels", word_width)]
- self.frame = Source(word_layout)
- self.busy = Signal()
-
- self._r_overflow = CSR()
-
- ###
-
- # start of frame detection
- vsync_r = Signal()
- new_frame = Signal()
- self.comb += new_frame.eq(self.vsync & ~vsync_r)
- self.sync.pix += vsync_r.eq(self.vsync)
-
- # pack pixels into words
- cur_word = Signal(word_width)
- cur_word_valid = Signal()
- encoded_pixel = Signal(24)
- self.comb += encoded_pixel.eq(Cat(self.b, self.g, self.r))
- pack_factor = word_width//24
- assert(pack_factor & (pack_factor - 1) == 0) # only support powers of 2
- pack_counter = Signal(max=pack_factor)
- self.sync.pix += [
- cur_word_valid.eq(0),
- If(new_frame,
- cur_word_valid.eq(pack_counter == (pack_factor - 1)),
- pack_counter.eq(0),
- ).Elif(self.valid_i & self.de,
- [If(pack_counter == (pack_factor-i-1),
- cur_word[24*i:24*(i+1)].eq(encoded_pixel)) for i in range(pack_factor)],
- cur_word_valid.eq(pack_counter == (pack_factor - 1)),
- pack_counter.eq(pack_counter + 1)
- )
- ]
-
- # FIFO
- fifo = RenameClockDomains(AsyncFIFO(word_layout, 512),
- {"write": "pix", "read": "sys"})
- self.submodules += fifo
- self.comb += [
- fifo.din.pixels.eq(cur_word),
- fifo.we.eq(cur_word_valid)
- ]
- self.sync.pix += \
- If(new_frame,
- fifo.din.sof.eq(1)
- ).Elif(cur_word_valid,
- fifo.din.sof.eq(0)
- )
- self.comb += [
- self.frame.stb.eq(fifo.readable),
- self.frame.payload.eq(fifo.dout),
- fifo.re.eq(self.frame.ack),
- self.busy.eq(0)
- ]
-
- # overflow detection
- pix_overflow = Signal()
- pix_overflow_reset = Signal()
- self.sync.pix += [
- If(fifo.we & ~fifo.writable,
- pix_overflow.eq(1)
- ).Elif(pix_overflow_reset,
- pix_overflow.eq(0)
- )
- ]
-
- sys_overflow = Signal()
- self.specials += MultiReg(pix_overflow, sys_overflow)
- self.submodules.overflow_reset = PulseSynchronizer("sys", "pix")
- self.submodules.overflow_reset_ack = PulseSynchronizer("pix", "sys")
- self.comb += [
- pix_overflow_reset.eq(self.overflow_reset.o),
- self.overflow_reset_ack.i.eq(pix_overflow_reset)
- ]
-
- overflow_mask = Signal()
- self.comb += [
- self._r_overflow.w.eq(sys_overflow & ~overflow_mask),
- self.overflow_reset.i.eq(self._r_overflow.re)
- ]
- self.sync += \
- If(self._r_overflow.re,
- overflow_mask.eq(1)
- ).Elif(self.overflow_reset_ack.o,
- overflow_mask.eq(0)
- )
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg
-from migen.genlib.fifo import _inc
-from migen.genlib.record import Record, layout_len
-from migen.genlib.misc import optree
-from migen.bank.description import *
-
-from misoclib.dvisampler.common import channel_layout
-
-class _SyncBuffer(Module):
- def __init__(self, width, depth):
- self.din = Signal(width)
- self.dout = Signal(width)
- self.re = Signal()
-
- ###
-
- produce = Signal(max=depth)
- consume = Signal(max=depth)
- storage = Memory(width, depth)
- self.specials += storage
-
- wrport = storage.get_port(write_capable=True)
- self.specials += wrport
- self.comb += [
- wrport.adr.eq(produce),
- wrport.dat_w.eq(self.din),
- wrport.we.eq(1)
- ]
- self.sync += _inc(produce, depth)
-
- rdport = storage.get_port(async_read=True)
- self.specials += rdport
- self.comb += [
- rdport.adr.eq(consume),
- self.dout.eq(rdport.dat_r)
- ]
- self.sync += If(self.re, _inc(consume, depth))
-
-class ChanSync(Module, AutoCSR):
- def __init__(self, nchan=3, depth=8):
- self.valid_i = Signal()
- self.chan_synced = Signal()
-
- self._r_channels_synced = CSRStatus()
-
- lst_control = []
- all_control = Signal()
- for i in range(nchan):
- name = "data_in" + str(i)
- data_in = Record(channel_layout, name=name)
- setattr(self, name, data_in)
- name = "data_out" + str(i)
- data_out = Record(channel_layout, name=name)
- setattr(self, name, data_out)
-
- ###
-
- syncbuffer = RenameClockDomains(_SyncBuffer(layout_len(channel_layout), depth), "pix")
- self.submodules += syncbuffer
- self.comb += [
- syncbuffer.din.eq(data_in.raw_bits()),
- data_out.raw_bits().eq(syncbuffer.dout)
- ]
- is_control = Signal()
- self.comb += [
- is_control.eq(~data_out.de),
- syncbuffer.re.eq(~is_control | all_control)
- ]
- lst_control.append(is_control)
-
- some_control = Signal()
- self.comb += [
- all_control.eq(optree("&", lst_control)),
- some_control.eq(optree("|", lst_control))
- ]
- self.sync.pix += If(~self.valid_i,
- self.chan_synced.eq(0)
- ).Else(
- If(some_control,
- If(all_control,
- self.chan_synced.eq(1)
- ).Else(
- self.chan_synced.eq(0)
- )
- )
- )
- self.specials += MultiReg(self.chan_synced, self._r_channels_synced.status)
-
-class _TB(Module):
- def __init__(self, test_seq_it):
- self.test_seq_it = test_seq_it
-
- self.submodules.chansync = RenameClockDomains(ChanSync(), {"pix": "sys"})
- self.comb += self.chansync.valid_i.eq(1)
-
- def do_simulation(self, selfp):
- try:
- de0, de1, de2 = next(self.test_seq_it)
- except StopIteration:
- raise StopSimulation
-
- selfp.chansync.data_in0.de = de0
- selfp.chansync.data_in1.de = de1
- selfp.chansync.data_in2.de = de2
- selfp.chansync.data_in0.d = selfp.simulator.cycle_counter
- selfp.chansync.data_in1.d = selfp.simulator.cycle_counter
- selfp.chansync.data_in2.d = selfp.simulator.cycle_counter
-
- out0 = selfp.chansync.data_out0.d
- out1 = selfp.chansync.data_out1.d
- out2 = selfp.chansync.data_out2.d
-
- print("{0:5} {1:5} {2:5}".format(out0, out1, out2))
-
-if __name__ == "__main__":
- from migen.sim.generic import run_simulation
-
- test_seq = [
- (1, 1, 1),
- (1, 1, 0),
- (0, 0, 0),
- (0, 0, 0),
- (0, 0, 1),
- (1, 1, 1),
- (1, 1, 1),
- ]
- tb = _TB(iter(test_seq*2))
- run_simulation(tb)
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg
-from migen.genlib.misc import optree
-from migen.bank.description import *
-
-from misoclib.dvisampler.common import control_tokens
-
-class CharSync(Module, AutoCSR):
- def __init__(self, required_controls=8):
- self.raw_data = Signal(10)
- self.synced = Signal()
- self.data = Signal(10)
-
- self._r_char_synced = CSRStatus()
- self._r_ctl_pos = CSRStatus(bits_for(9))
-
- ###
-
- raw_data1 = Signal(10)
- self.sync.pix += raw_data1.eq(self.raw_data)
- raw = Signal(20)
- self.comb += raw.eq(Cat(raw_data1, self.raw_data))
-
- found_control = Signal()
- control_position = Signal(max=10)
- self.sync.pix += found_control.eq(0)
- for i in range(10):
- self.sync.pix += If(optree("|", [raw[i:i+10] == t for t in control_tokens]),
- found_control.eq(1),
- control_position.eq(i)
- )
-
- control_counter = Signal(max=required_controls)
- previous_control_position = Signal(max=10)
- word_sel = Signal(max=10)
- self.sync.pix += [
- If(found_control & (control_position == previous_control_position),
- If(control_counter == (required_controls - 1),
- control_counter.eq(0),
- self.synced.eq(1),
- word_sel.eq(control_position)
- ).Else(
- control_counter.eq(control_counter + 1)
- )
- ).Else(
- control_counter.eq(0)
- ),
- previous_control_position.eq(control_position)
- ]
- self.specials += MultiReg(self.synced, self._r_char_synced.status)
- self.specials += MultiReg(word_sel, self._r_ctl_pos.status)
-
- self.sync.pix += self.data.eq(raw >> word_sel)
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg
-from migen.bank.description import *
-
-class Clocking(Module, AutoCSR):
- 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()
- self.clock_domains._cd_pix2x = ClockDomain()
- self.clock_domains._cd_pix10x = ClockDomain(reset_less=True)
-
- ###
-
- clk_se = Signal()
- self.specials += Instance("IBUFDS", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=clk_se)
-
- clkfbout = Signal()
- pll_locked = Signal()
- pll_clk0 = Signal()
- pll_clk1 = Signal()
- pll_clk2 = 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_ADV",
- p_CLKFBOUT_MULT=10,
- p_CLKOUT0_DIVIDE=1, # pix10x
- p_CLKOUT1_DIVIDE=5, # pix2x
- p_CLKOUT2_DIVIDE=10, # pix
- p_COMPENSATION="INTERNAL",
-
- 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,
-
- 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 += [
- 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),
- Instance("BUFG", i_I=pll_clk1, o_O=self._cd_pix2x.clk),
- Instance("BUFG", i_I=pll_clk2, o_O=self._cd_pix.clk),
- MultiReg(locked_async, self.locked, "sys")
- ]
- self.comb += self._r_locked.status.eq(self.locked)
-
- # sychronize pix+pix2x reset
- pix_rst_n = 1
- for i in range(2):
- new_pix_rst_n = Signal()
- self.specials += Instance("FDCE", i_D=pix_rst_n, i_CE=1, i_C=ClockSignal("pix"),
- i_CLR=~locked_async, o_Q=new_pix_rst_n)
- pix_rst_n = new_pix_rst_n
- self.comb += self._cd_pix.rst.eq(~pix_rst_n), self._cd_pix2x.rst.eq(~pix_rst_n)
+++ /dev/null
-control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011]
-channel_layout = [("d", 8), ("c", 2), ("de", 1)]
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg, PulseSynchronizer
-from migen.bank.description import *
-
-class DataCapture(Module, AutoCSR):
- def __init__(self, pad_p, pad_n, ntbits):
- self.serdesstrobe = Signal()
- self.d = Signal(10)
-
- self._r_dly_ctl = CSR(6)
- self._r_dly_busy = CSRStatus(2)
- self._r_phase = CSRStatus(2)
- self._r_phase_reset = CSR()
-
- ###
-
- # IO
- pad_se = Signal()
- self.specials += Instance("IBUFDS", i_I=pad_p, i_IB=pad_n, o_O=pad_se)
-
- pad_delayed_master = Signal()
- pad_delayed_slave = Signal()
- delay_inc = Signal()
- delay_ce = Signal()
- delay_master_cal = Signal()
- delay_master_rst = Signal()
- delay_master_busy = Signal()
- delay_slave_cal = Signal()
- delay_slave_rst = Signal()
- delay_slave_busy = Signal()
- self.specials += Instance("IODELAY2",
- p_SERDES_MODE="MASTER",
- p_DELAY_SRC="IDATAIN", p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
- p_COUNTER_WRAPAROUND="STAY_AT_LIMIT", p_DATA_RATE="SDR",
-
- i_IDATAIN=pad_se, o_DATAOUT=pad_delayed_master,
- i_CLK=ClockSignal("pix2x"), i_IOCLK0=ClockSignal("pix10x"),
-
- i_INC=delay_inc, i_CE=delay_ce,
- i_CAL=delay_master_cal, i_RST=delay_master_rst, o_BUSY=delay_master_busy,
- i_T=1)
- self.specials += Instance("IODELAY2",
- p_SERDES_MODE="SLAVE",
- p_DELAY_SRC="IDATAIN", p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
- p_COUNTER_WRAPAROUND="WRAPAROUND", p_DATA_RATE="SDR",
-
- i_IDATAIN=pad_se, o_DATAOUT=pad_delayed_slave,
- i_CLK=ClockSignal("pix2x"), i_IOCLK0=ClockSignal("pix10x"),
-
- i_INC=delay_inc, i_CE=delay_ce,
- i_CAL=delay_slave_cal, i_RST=delay_slave_rst, o_BUSY=delay_slave_busy,
- i_T=1)
-
- dsr2 = Signal(5)
- pd_valid = Signal()
- pd_incdec = Signal()
- pd_edge = Signal()
- pd_cascade = Signal()
- self.specials += Instance("ISERDES2",
- p_SERDES_MODE="MASTER",
- p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=5,
- p_INTERFACE_TYPE="RETIMED",
-
- i_D=pad_delayed_master,
- o_Q4=dsr2[4], o_Q3=dsr2[3], o_Q2=dsr2[2], o_Q1=dsr2[1],
-
- i_BITSLIP=0, i_CE0=1, i_RST=0,
- i_CLK0=ClockSignal("pix10x"), i_CLKDIV=ClockSignal("pix2x"),
- i_IOCE=self.serdesstrobe,
-
- o_VALID=pd_valid, o_INCDEC=pd_incdec,
- i_SHIFTIN=pd_edge, o_SHIFTOUT=pd_cascade)
- self.specials += Instance("ISERDES2",
- p_SERDES_MODE="SLAVE",
- p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=5,
- p_INTERFACE_TYPE="RETIMED",
-
- i_D=pad_delayed_slave,
- o_Q4=dsr2[0],
-
- i_BITSLIP=0, i_CE0=1, i_RST=0,
- i_CLK0=ClockSignal("pix10x"), i_CLKDIV=ClockSignal("pix2x"),
- i_IOCE=self.serdesstrobe,
-
- i_SHIFTIN=pd_cascade, o_SHIFTOUT=pd_edge)
-
- # Phase error accumulator
- lateness = Signal(ntbits, reset=2**(ntbits - 1))
- too_late = Signal()
- too_early = Signal()
- reset_lateness = Signal()
- self.comb += [
- too_late.eq(lateness == (2**ntbits - 1)),
- too_early.eq(lateness == 0)
- ]
- self.sync.pix2x += [
- If(reset_lateness,
- lateness.eq(2**(ntbits - 1))
- ).Elif(~delay_master_busy & ~delay_slave_busy & ~too_late & ~too_early,
- If(pd_valid & pd_incdec, lateness.eq(lateness - 1)),
- If(pd_valid & ~pd_incdec, lateness.eq(lateness + 1))
- )
- ]
-
- # Delay control
- self.submodules.delay_master_done = PulseSynchronizer("pix2x", "sys")
- delay_master_pending = Signal()
- self.sync.pix2x += [
- self.delay_master_done.i.eq(0),
- If(~delay_master_pending,
- If(delay_master_cal | delay_ce, delay_master_pending.eq(1))
- ).Else(
- If(~delay_master_busy,
- self.delay_master_done.i.eq(1),
- delay_master_pending.eq(0)
- )
- )
- ]
- self.submodules.delay_slave_done = PulseSynchronizer("pix2x", "sys")
- delay_slave_pending = Signal()
- self.sync.pix2x += [
- self.delay_slave_done.i.eq(0),
- If(~delay_slave_pending,
- If(delay_slave_cal | delay_ce, delay_slave_pending.eq(1))
- ).Else(
- If(~delay_slave_busy,
- self.delay_slave_done.i.eq(1),
- delay_slave_pending.eq(0)
- )
- )
- ]
-
- self.submodules.do_delay_master_cal = PulseSynchronizer("sys", "pix2x")
- self.submodules.do_delay_master_rst = PulseSynchronizer("sys", "pix2x")
- self.submodules.do_delay_slave_cal = PulseSynchronizer("sys", "pix2x")
- self.submodules.do_delay_slave_rst = PulseSynchronizer("sys", "pix2x")
- self.submodules.do_delay_inc = PulseSynchronizer("sys", "pix2x")
- self.submodules.do_delay_dec = PulseSynchronizer("sys", "pix2x")
- self.comb += [
- delay_master_cal.eq(self.do_delay_master_cal.o),
- delay_master_rst.eq(self.do_delay_master_rst.o),
- delay_slave_cal.eq(self.do_delay_slave_cal.o),
- delay_slave_rst.eq(self.do_delay_slave_rst.o),
- delay_inc.eq(self.do_delay_inc.o),
- delay_ce.eq(self.do_delay_inc.o | self.do_delay_dec.o),
- ]
-
- sys_delay_master_pending = Signal()
- self.sync += [
- If(self.do_delay_master_cal.i | self.do_delay_inc.i | self.do_delay_dec.i,
- sys_delay_master_pending.eq(1)
- ).Elif(self.delay_master_done.o,
- sys_delay_master_pending.eq(0)
- )
- ]
- sys_delay_slave_pending = Signal()
- self.sync += [
- If(self.do_delay_slave_cal.i | self.do_delay_inc.i | self.do_delay_dec.i,
- sys_delay_slave_pending.eq(1)
- ).Elif(self.delay_slave_done.o,
- sys_delay_slave_pending.eq(0)
- )
- ]
-
- self.comb += [
- self.do_delay_master_cal.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[0]),
- self.do_delay_master_rst.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[1]),
- self.do_delay_slave_cal.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[2]),
- self.do_delay_slave_rst.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[3]),
- self.do_delay_inc.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[4]),
- self.do_delay_dec.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[5]),
- self._r_dly_busy.status.eq(Cat(sys_delay_master_pending, sys_delay_slave_pending))
- ]
-
- # Phase detector control
- self.specials += MultiReg(Cat(too_late, too_early), self._r_phase.status)
- self.submodules.do_reset_lateness = PulseSynchronizer("sys", "pix2x")
- self.comb += [
- reset_lateness.eq(self.do_reset_lateness.o),
- self.do_reset_lateness.i.eq(self._r_phase_reset.re)
- ]
-
- # 5:10 deserialization
- dsr = Signal(10)
- self.sync.pix2x += dsr.eq(Cat(dsr[5:], dsr2))
- self.sync.pix += self.d.eq(dsr)
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.fifo import AsyncFIFO
-from migen.genlib.record import layout_len
-from migen.bank.description import AutoCSR
-from migen.actorlib import structuring, dma_lasmi, spi
-
-from misoclib.dvisampler.edid import EDID
-from misoclib.dvisampler.clocking import Clocking
-from misoclib.dvisampler.datacapture import DataCapture
-
-class RawDVISampler(Module, AutoCSR):
- def __init__(self, pads, asmiport):
- self.submodules.edid = EDID(pads)
- self.submodules.clocking = Clocking(pads)
-
- invert = False
- try:
- s = getattr(pads, "data0")
- except AttributeError:
- s = getattr(pads, "data0_n")
- invert = True
- self.submodules.data0_cap = DataCapture(8, invert)
- self.comb += [
- self.data0_cap.pad.eq(s),
- self.data0_cap.serdesstrobe.eq(self.clocking.serdesstrobe)
- ]
-
- fifo = RenameClockDomains(AsyncFIFO(10, 256),
- {"write": "pix", "read": "sys"})
- self.submodules += fifo
- self.comb += [
- fifo.din.eq(self.data0_cap.d),
- fifo.we.eq(1)
- ]
-
- pack_factor = asmiport.hub.dw//16
- self.submodules.packer = structuring.Pack([("word", 10), ("pad", 6)], pack_factor)
- self.submodules.cast = structuring.Cast(self.packer.source.payload.layout, asmiport.hub.dw)
- self.submodules.dma = spi.DMAWriteController(dma_lasmi.Writer(lasmim), spi.MODE_SINGLE_SHOT)
- self.comb += [
- self.packer.sink.stb.eq(fifo.readable),
- fifo.re.eq(self.packer.sink.ack),
- self.packer.sink.payload.word.eq(fifo.dout),
- self.packer.source.connect_flat(self.cast.sink),
- self.cast.source.connect_flat(self.dma.data)
- ]
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.record import Record
-
-from misoclib.dvisampler.common import control_tokens, channel_layout
-
-class Decoding(Module):
- def __init__(self):
- self.valid_i = Signal()
- self.input = Signal(10)
- self.valid_o = Signal()
- self.output = Record(channel_layout)
-
- ###
-
- self.sync.pix += self.output.de.eq(1)
- for i, t in enumerate(control_tokens):
- self.sync.pix += If(self.input == t,
- self.output.de.eq(0),
- self.output.c.eq(i)
- )
- self.sync.pix += self.output.d[0].eq(self.input[0] ^ self.input[9])
- for i in range(1, 8):
- self.sync.pix += self.output.d[i].eq(self.input[i] ^ self.input[i-1] ^ ~self.input[8])
- self.sync.pix += self.valid_o.eq(self.valid_i)
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.fsm import FSM, NextState
-from migen.bank.description import *
-from migen.bank.eventmanager import *
-from migen.flow.actor import *
-from migen.actorlib import dma_lasmi
-
-# Slot status: EMPTY=0 LOADED=1 PENDING=2
-class _Slot(Module, AutoCSR):
- def __init__(self, addr_bits, alignment_bits):
- self.ev_source = EventSourceLevel()
- self.address = Signal(addr_bits)
- self.address_reached = Signal(addr_bits)
- self.address_valid = Signal()
- self.address_done = Signal()
-
- self._r_status = CSRStorage(2, write_from_dev=True)
- self._r_address = CSRStorage(addr_bits + alignment_bits, alignment_bits=alignment_bits, write_from_dev=True)
-
- ###
-
- self.comb += [
- self.address.eq(self._r_address.storage),
- self.address_valid.eq(self._r_status.storage[0]),
- self._r_status.dat_w.eq(2),
- self._r_status.we.eq(self.address_done),
- self._r_address.dat_w.eq(self.address_reached),
- self._r_address.we.eq(self.address_done),
- self.ev_source.trigger.eq(self._r_status.storage[1])
- ]
-
-class _SlotArray(Module, AutoCSR):
- def __init__(self, nslots, addr_bits, alignment_bits):
- self.submodules.ev = EventManager()
- self.address = Signal(addr_bits)
- self.address_reached = Signal(addr_bits)
- self.address_valid = Signal()
- self.address_done = Signal()
-
- ###
-
- slots = [_Slot(addr_bits, alignment_bits) for i in range(nslots)]
- for n, slot in enumerate(slots):
- setattr(self.submodules, "slot"+str(n), slot)
- setattr(self.ev, "slot"+str(n), slot.ev_source)
- self.ev.finalize()
-
- change_slot = Signal()
- current_slot = Signal(max=nslots)
- self.sync += If(change_slot, [If(slot.address_valid, current_slot.eq(n)) for n, slot in reversed(list(enumerate(slots)))])
- self.comb += change_slot.eq(~self.address_valid | self.address_done)
-
- self.comb += [
- self.address.eq(Array(slot.address for slot in slots)[current_slot]),
- self.address_valid.eq(Array(slot.address_valid for slot in slots)[current_slot])
- ]
- self.comb += [slot.address_reached.eq(self.address_reached) for slot in slots]
- self.comb += [slot.address_done.eq(self.address_done & (current_slot == n)) for n, slot in enumerate(slots)]
-
-class DMA(Module):
- def __init__(self, lasmim, nslots):
- bus_aw = lasmim.aw
- bus_dw = lasmim.dw
- alignment_bits = bits_for(bus_dw//8) - 1
-
- fifo_word_width = 24*bus_dw//32
- self.frame = Sink([("sof", 1), ("pixels", fifo_word_width)])
- self._r_frame_size = CSRStorage(bus_aw + alignment_bits, alignment_bits=alignment_bits)
- self.submodules._slot_array = _SlotArray(nslots, bus_aw, alignment_bits)
- self.ev = self._slot_array.ev
-
- ###
-
- # address generator + maximum memory word count to prevent DMA buffer overrun
- reset_words = Signal()
- count_word = Signal()
- last_word = Signal()
- current_address = Signal(bus_aw)
- mwords_remaining = Signal(bus_aw)
- self.comb += [
- self._slot_array.address_reached.eq(current_address),
- last_word.eq(mwords_remaining == 1)
- ]
- self.sync += [
- If(reset_words,
- current_address.eq(self._slot_array.address),
- mwords_remaining.eq(self._r_frame_size.storage)
- ).Elif(count_word,
- current_address.eq(current_address + 1),
- mwords_remaining.eq(mwords_remaining - 1)
- )
- ]
-
- # 24bpp -> 32bpp
- memory_word = Signal(bus_dw)
- pixbits = []
- for i in range(bus_dw//32):
- for j in range(3):
- b = (i*3+j)*8
- pixbits.append(self.frame.payload.pixels[b+6:b+8])
- pixbits.append(self.frame.payload.pixels[b:b+8])
- pixbits.append(0)
- pixbits.append(0)
- self.comb += memory_word.eq(Cat(*pixbits))
-
- # bus accessor
- self.submodules._bus_accessor = dma_lasmi.Writer(lasmim)
- self.comb += [
- self._bus_accessor.address_data.payload.a.eq(current_address),
- self._bus_accessor.address_data.payload.d.eq(memory_word)
- ]
-
- # control FSM
- fsm = FSM()
- self.submodules += fsm
-
- fsm.act("WAIT_SOF",
- reset_words.eq(1),
- self.frame.ack.eq(~self._slot_array.address_valid | ~self.frame.payload.sof),
- If(self._slot_array.address_valid & self.frame.payload.sof & self.frame.stb, NextState("TRANSFER_PIXELS"))
- )
- fsm.act("TRANSFER_PIXELS",
- self.frame.ack.eq(self._bus_accessor.address_data.ack),
- If(self.frame.stb,
- self._bus_accessor.address_data.stb.eq(1),
- If(self._bus_accessor.address_data.ack,
- count_word.eq(1),
- If(last_word, NextState("EOF"))
- )
- )
- )
- fsm.act("EOF",
- If(~self._bus_accessor.busy,
- self._slot_array.address_done.eq(1),
- NextState("WAIT_SOF")
- )
- )
-
- def get_csrs(self):
- return [self._r_frame_size] + self._slot_array.get_csrs()
+++ /dev/null
-from migen.fhdl.std import *
-from migen.fhdl.specials import Tristate
-from migen.genlib.cdc import MultiReg
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.misc import chooser
-from migen.bank.description import CSRStorage, CSRStatus, AutoCSR
-
-_default_edid = [
- 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3D, 0x17, 0x32, 0x12, 0x2A, 0x6A, 0xBF, 0x00,
- 0x05, 0x17, 0x01, 0x03, 0x80, 0x28, 0x1E, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xB2, 0x0C, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88,
- 0x36, 0x00, 0x28, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x4D, 0x31, 0x20,
- 0x44, 0x56, 0x49, 0x20, 0x6D, 0x69, 0x78, 0x65, 0x72, 0x0A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34,
-]
-
-class EDID(Module, AutoCSR):
- def __init__(self, pads, default=_default_edid):
- self._r_hpd_notif = CSRStatus()
- self._r_hpd_en = CSRStorage()
- self.specials.mem = Memory(8, 128, init=default)
-
- ###
-
- # HPD
- if hasattr(pads, "hpd_notif"):
- self.specials += MultiReg(pads.hpd_notif, self._r_hpd_notif.status)
- else:
- self.comb += self._r_hpd_notif.status.eq(1)
- if hasattr(pads, "hpd_en"):
- self.comb += pads.hpd_en.eq(self._r_hpd_en.storage)
-
- # EDID
- scl_raw = Signal()
- sda_i = Signal()
- sda_drv = Signal()
- _sda_drv_reg = Signal()
- _sda_i_async = Signal()
- self.sync += _sda_drv_reg.eq(sda_drv)
- self.specials += [
- MultiReg(pads.scl, scl_raw),
- Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async),
- MultiReg(_sda_i_async, sda_i)
- ]
-
- scl_i = Signal()
- samp_count = Signal(6)
- samp_carry = Signal()
- self.sync += [
- Cat(samp_count, samp_carry).eq(samp_count + 1),
- If(samp_carry, scl_i.eq(scl_raw))
- ]
-
- scl_r = Signal()
- sda_r = Signal()
- scl_rising = Signal()
- sda_rising = Signal()
- sda_falling = Signal()
- self.sync += [
- scl_r.eq(scl_i),
- sda_r.eq(sda_i)
- ]
- self.comb += [
- scl_rising.eq(scl_i & ~scl_r),
- sda_rising.eq(sda_i & ~sda_r),
- sda_falling.eq(~sda_i & sda_r)
- ]
-
- start = Signal()
- self.comb += start.eq(scl_i & sda_falling)
-
- din = Signal(8)
- counter = Signal(max=9)
- self.sync += [
- If(start, counter.eq(0)),
- If(scl_rising,
- If(counter == 8,
- counter.eq(0)
- ).Else(
- counter.eq(counter + 1),
- din.eq(Cat(sda_i, din[:7]))
- )
- )
- ]
-
- is_read = Signal()
- update_is_read = Signal()
- self.sync += If(update_is_read, is_read.eq(din[0]))
-
- offset_counter = Signal(max=128)
- oc_load = Signal()
- oc_inc = Signal()
- self.sync += [
- If(oc_load,
- offset_counter.eq(din)
- ).Elif(oc_inc,
- offset_counter.eq(offset_counter + 1)
- )
- ]
- rdport = self.mem.get_port()
- self.specials += rdport
- self.comb += rdport.adr.eq(offset_counter)
- data_bit = Signal()
-
- zero_drv = Signal()
- data_drv = Signal()
- self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit))
-
- data_drv_en = Signal()
- data_drv_stop = Signal()
- self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0))
- self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True))
-
- fsm = FSM()
- self.submodules += fsm
-
- fsm.act("WAIT_START")
- fsm.act("RCV_ADDRESS",
- If(counter == 8,
- If(din[1:] == 0x50,
- update_is_read.eq(1),
- NextState("ACK_ADDRESS0")
- ).Else(
- NextState("WAIT_START")
- )
- )
- )
- fsm.act("ACK_ADDRESS0",
- If(~scl_i, NextState("ACK_ADDRESS1"))
- )
- fsm.act("ACK_ADDRESS1",
- zero_drv.eq(1),
- If(scl_i, NextState("ACK_ADDRESS2"))
- )
- fsm.act("ACK_ADDRESS2",
- zero_drv.eq(1),
- If(~scl_i,
- If(is_read,
- NextState("READ")
- ).Else(
- NextState("RCV_OFFSET")
- )
- )
- )
-
- fsm.act("RCV_OFFSET",
- If(counter == 8,
- oc_load.eq(1),
- NextState("ACK_OFFSET0")
- )
- )
- fsm.act("ACK_OFFSET0",
- If(~scl_i, NextState("ACK_OFFSET1"))
- )
- fsm.act("ACK_OFFSET1",
- zero_drv.eq(1),
- If(scl_i, NextState("ACK_OFFSET2"))
- )
- fsm.act("ACK_OFFSET2",
- zero_drv.eq(1),
- If(~scl_i, NextState("RCV_ADDRESS"))
- )
-
- fsm.act("READ",
- If(~scl_i,
- If(counter == 8,
- data_drv_stop.eq(1),
- NextState("ACK_READ")
- ).Else(
- data_drv_en.eq(1)
- )
- )
- )
- fsm.act("ACK_READ",
- If(scl_rising,
- oc_inc.eq(1),
- If(sda_i,
- NextState("WAIT_START")
- ).Else(
- NextState("READ")
- )
- )
- )
-
- for state in fsm.actions.keys():
- fsm.act(state, If(start, NextState("RCV_ADDRESS")))
- fsm.act(state, If(~self._r_hpd_en.storage, NextState("WAIT_START")))
+++ /dev/null
-from migen.fhdl.std import *
-from migen.bank.description import *
-from migen.genlib.misc import optree
-from migen.genlib.cdc import PulseSynchronizer
-
-from misoclib.dvisampler.common import control_tokens
-
-class WER(Module, AutoCSR):
- def __init__(self, period_bits=24):
- self.data = Signal(10)
- self._r_update = CSR()
- self._r_value = CSRStatus(period_bits)
-
- ###
-
- # pipeline stage 1
- # we ignore the 10th (inversion) bit, as it is independent of the transition minimization
- data_r = Signal(9)
- self.sync.pix += data_r.eq(self.data[:9])
-
- # pipeline stage 2
- transitions = Signal(8)
- self.comb += [transitions[i].eq(data_r[i] ^ data_r[i+1]) for i in range(8)]
- transition_count = Signal(max=9)
- self.sync.pix += transition_count.eq(optree("+", [transitions[i] for i in range(8)]))
-
- is_control = Signal()
- self.sync.pix += is_control.eq(optree("|", [data_r == ct for ct in control_tokens]))
-
- # pipeline stage 3
- is_error = Signal()
- self.sync.pix += is_error.eq((transition_count > 4) & ~is_control)
-
- # counter
- period_counter = Signal(period_bits)
- period_done = Signal()
- self.sync.pix += Cat(period_counter, period_done).eq(period_counter + 1)
-
- wer_counter = Signal(period_bits)
- wer_counter_r = Signal(period_bits)
- wer_counter_r_updated = Signal()
- self.sync.pix += [
- wer_counter_r_updated.eq(period_done),
- If(period_done,
- wer_counter_r.eq(wer_counter),
- wer_counter.eq(0)
- ).Elif(is_error,
- wer_counter.eq(wer_counter + 1)
- )
- ]
-
- # sync to system clock domain
- wer_counter_sys = Signal(period_bits)
- self.submodules.ps_counter = PulseSynchronizer("pix", "sys")
- self.comb += self.ps_counter.i.eq(wer_counter_r_updated)
- self.sync += If(self.ps_counter.o, wer_counter_sys.eq(wer_counter_r))
-
- # register interface
- self.sync += If(self._r_update.re, self._r_value.status.eq(wer_counter_sys))
from migen.fhdl.std import *
-from migen.flow.actor import *
from migen.flow.network import *
from migen.flow import plumbing
-from migen.bank.description import CSRStorage, AutoCSR
-from migen.actorlib import dma_lasmi, structuring, sim, misc
+from migen.bank.description import AutoCSR
+from migen.actorlib import dma_lasmi, structuring, misc
from misoclib.framebuffer.format import bpp, pixel_layout, FrameInitiator, VTG
from misoclib.framebuffer.phy import Driver
class Framebuffer(Module, AutoCSR):
- def __init__(self, pads_vga, pads_dvi, lasmim, simulation=False):
+ def __init__(self, pads_vga, pads_dvi, lasmim):
pack_factor = lasmim.dw//bpp
g = DataFlowGraph()
g.add_connection(cast, vtg, sink_ep="pixels")
g.add_connection(vtg, self.driver)
self.submodules += CompositeActor(g)
-
-class Blender(PipelinedActor, AutoCSR):
- def __init__(self, nimages, pack_factor, latency):
- epixel_layout = pixel_layout(pack_factor)
- sink_layout = [("i"+str(i), epixel_layout) for i in range(nimages)]
- self.sink = Sink(sink_layout)
- self.source = Source(epixel_layout)
- factors = []
- for i in range(nimages):
- name = "f"+str(i)
- csr = CSRStorage(8, name=name)
- setattr(self, name, csr)
- factors.append(csr.storage)
- PipelinedActor.__init__(self, latency)
-
- ###
-
- sink_registered = Record(sink_layout)
- self.sync += If(self.pipe_ce, sink_registered.eq(self.sink.payload))
-
- imgs = [getattr(sink_registered, "i"+str(i)) for i in range(nimages)]
- outval = Record(epixel_layout)
- for e in epixel_layout:
- name = e[0]
- inpixs = [getattr(img, name) for img in imgs]
- outpix = getattr(outval, name)
- for component in ["r", "g", "b"]:
- incomps = [getattr(pix, component) for pix in inpixs]
- outcomp = getattr(outpix, component)
- outcomp_full = Signal(19)
- self.comb += [
- outcomp_full.eq(sum(incomp*factor for incomp, factor in zip(incomps, factors))),
- If(outcomp_full[18],
- outcomp.eq(2**10 - 1) # saturate on overflow
- ).Else(
- outcomp.eq(outcomp_full[8:18])
- )
- ]
-
- pipe_stmts = []
- for i in range(latency-1):
- new_outval = Record(epixel_layout)
- pipe_stmts.append(new_outval.eq(outval))
- outval = new_outval
- self.sync += If(self.pipe_ce, pipe_stmts)
- self.comb += self.source.payload.eq(outval)
-
-class MixFramebuffer(Module, AutoCSR):
- def __init__(self, pads_vga, pads_dvi, *lasmims, blender_latency=5):
- assert(all(lasmim.aw == lasmims[0].aw and lasmim.dw == lasmims[0].dw
- for lasmim in lasmims))
- pack_factor = lasmims[0].dw//bpp
-
- self.fi = FrameInitiator(lasmims[0].aw, pack_factor, len(lasmims))
- self.blender = Blender(len(lasmims), pack_factor, blender_latency)
- self.driver = Driver(pack_factor, pads_vga, pads_dvi)
-
- g = DataFlowGraph()
- epixel_layout = pixel_layout(pack_factor)
- for n, lasmim in enumerate(lasmims):
- intseq = misc.IntSequence(lasmim.aw, lasmim.aw)
- dma_out = AbstractActor(plumbing.Buffer)
- g.add_connection(self.fi, intseq, source_subr=self.fi.dma_subr(n))
- g.add_pipeline(intseq, AbstractActor(plumbing.Buffer), dma_lasmi.Reader(lasmim), dma_out)
-
- cast = structuring.Cast(lasmim.dw, epixel_layout, reverse_to=True)
- g.add_connection(dma_out, cast)
- g.add_connection(cast, self.blender, sink_subr=["i"+str(n)])
-
- vtg = VTG(pack_factor)
- g.add_connection(self.fi, vtg, source_subr=self.fi.timing_subr, sink_ep="timing")
- g.add_connection(self.blender, vtg, sink_ep="pixels")
- g.add_connection(vtg, self.driver)
- self.submodules += CompositeActor(g)
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.fsm import *
-from migen.genlib.record import Record
-from migen.genlib.misc import optree
-from migen.sim.generic import run_simulation
-
-class Chopper(Module):
- def __init__(self, frac_bits):
- self.p = Signal(frac_bits)
- self.q = Signal(frac_bits)
- self.chopper = Signal(reset=1)
-
- ###
-
- acc = Signal(frac_bits)
- self.sync += If(acc + self.p >= Cat(self.q, 0), # FIXME
- acc.eq(acc + self.p - self.q),
- self.chopper.eq(1)
- ).Else(
- acc.eq(acc + self.p),
- self.chopper.eq(0)
- )
-
-class _ChopperTB(Module):
- def __init__(self):
- self.submodules.dut = Chopper(16)
- self.comb += self.dut.p.eq(320), self.dut.q.eq(681)
-
- def gen_simulation(self, selfp):
- ones = 0
- niter = 681
- for i in range(niter):
- ones += selfp.dut.chopper
- yield
- print("Ones: {} (expected: {})".format(ones, selfp.dut.p*niter//selfp.dut.q))
-
-class MultiChopper(Module):
- def __init__(self, N, frac_bits):
- self.init = Signal()
- self.ready = Signal()
- self.next = Signal()
- self.p = Signal(frac_bits)
- self.q = Signal(frac_bits)
- self.chopper = Signal(N)
-
- ###
-
- # initialization counter
- ic = Signal(frac_bits)
- ic_overflow = Signal()
- ic_inc = Signal()
- self.sync += \
- If(self.init,
- ic.eq(0),
- ic_overflow.eq(1)
- ).Elif(ic_inc,
- If(ic + self.p >= self.q,
- ic.eq(ic + self.p - self.q),
- ic_overflow.eq(1)
- ).Else(
- ic.eq(ic + self.p),
- ic_overflow.eq(0)
- )
- )
-
- # computed N*p mod q
- Np = Signal(frac_bits)
- load_np = Signal()
- self.sync += If(load_np, Np.eq(ic))
-
- fsm = FSM()
- self.submodules += fsm
- fsm.act("IDLE",
- self.ready.eq(1),
- If(self.init, NextState(0))
- )
-
- prev_acc_r = Signal(frac_bits)
- prev_acc = prev_acc_r
- for i in range(N):
- acc = Signal(frac_bits)
-
- # pipeline stage 1: update accumulators
- load_init_acc = Signal()
- self.sync += \
- If(load_init_acc,
- acc.eq(ic)
- ).Elif(self.next,
- If(acc + Np >= Cat(self.q, 0), # FIXME: workaround for imbecilic Verilog extension rules, needs to be put in Migen backend
- acc.eq(acc + Np - self.q),
- ).Else(
- acc.eq(acc + Np)
- )
- )
-
- # pipeline stage 2: detect overflows and generate chopper signal
- load_init_chopper = Signal()
- self.sync += \
- If(load_init_chopper,
- self.chopper[i].eq(ic_overflow)
- ).Elif(self.next,
- self.chopper[i].eq(prev_acc >= acc)
- )
- if i == N-1:
- self.sync += \
- If(load_init_chopper,
- prev_acc_r.eq(ic)
- ).Elif(self.next,
- prev_acc_r.eq(acc)
- )
- prev_acc = acc
-
- # initialize stage 2
- fsm.act(i,
- load_init_chopper.eq(1),
- ic_inc.eq(1),
- NextState(i + 1)
- )
- # initialize stage 1
- fsm.act(N + i,
- load_init_acc.eq(1),
- ic_inc.eq(1),
- NextState(N + i + 1) if i < N-1 else NextState("IDLE")
- )
- # initialize Np
- fsm.act(N, load_np.eq(1))
-
-def _count_ones(n):
- r = 0
- while n:
- if n & 1:
- r += 1
- n >>= 1
- return r
-
-class _MultiChopperTB(Module):
- def __init__(self):
- self.submodules.dut = MultiChopper(4, 16)
-
- def gen_simulation(self, selfp):
- dut = selfp.dut
-
- print("initializing chopper...")
- dut.init = 1
- dut.p = 320
- dut.q = 681
- yield
- dut.init = 0
- yield
- while not dut.ready:
- yield
- print("done")
-
- dut.next = 1
- yield
- ones = 0
- niter = 681
- for i in range(niter):
- #print("{:04b}".format(dut.chopper))
- ones += _count_ones(dut.chopper)
- yield
- print("Ones: {} (expected: {})".format(ones, dut.p*niter*4//dut.q))
-
-class Compacter(Module):
- def __init__(self, base_layout, N):
- self.i = Record([("w"+str(i), base_layout) for i in range(N)])
- self.sel = Signal(N)
-
- self.o = Record([("w"+str(i), base_layout) for i in range(N)])
- self.count = Signal(max=N+1)
-
- ###
-
- def set_word(wn, selstart):
- if wn >= N or selstart >= N:
- return
- r = None
- for i in reversed(range(selstart, N)):
- r = If(self.sel[i],
- getattr(self.o, "w"+str(wn)).eq(getattr(self.i, "w"+str(i))),
- set_word(wn+1, i+1)
- ).Else(r)
- return r
- self.sync += set_word(0, 0)
- self.sync += self.count.eq(optree("+", [self.sel[i] for i in range(N)]))
-
-class Packer(Module):
- def __init__(self, base_layout, N):
- assert(N & (N - 1) == 0) # only support powers of 2
-
- self.i = Record([("w"+str(i), base_layout) for i in range(N)])
- self.count = Signal(max=N+1)
-
- self.o = Record([("w"+str(i), base_layout) for i in range(N)])
- self.stb = Signal()
-
- ###
-
- buf = Record([("w"+str(i), base_layout) for i in range(2*N)])
-
- wrp = Signal(max=2*N)
- wrp_next = Signal(max=2*N)
- self.comb += wrp_next.eq(wrp + self.count)
- self.sync += [
- wrp.eq(wrp_next), self.stb.eq(wrp_next[-1] ^ wrp[-1]),
- Case(wrp, {i: [getattr(buf, "w"+str(j + i & 2*N - 1)).eq(getattr(self.i, "w"+str(j))) for j in range(N)] for i in range(2*N)})
- ]
-
- rdp = Signal()
- self.sync += If(self.stb, rdp.eq(~rdp))
- self.comb += If(rdp,
- [getattr(self.o, "w"+str(i)).eq(getattr(buf, "w"+str(i+N))) for i in range(N)]
- ).Else(
- [getattr(self.o, "w"+str(i)).eq(getattr(buf, "w"+str(i))) for i in range(N)]
- )
-
-class _CompacterPackerTB(Module):
- def __init__(self):
- self.test_seq = [
- (42, 0), (32, 1), ( 4, 1), (21, 0),
- (43, 1), (11, 1), ( 5, 1), (18, 0),
- (71, 0), (70, 1), (30, 1), (12, 1),
- ( 3, 1), (12, 1), (21, 1), (10, 0),
- ( 1, 1), (87, 0), (72, 0), (12, 0)
- ]
- self.input_it = iter(self.test_seq)
- self.output = []
- self.end_cycle = -1
-
- self.submodules.compacter = Compacter(16, 4)
- self.submodules.packer = Packer(16, 4)
- self.comb += self.packer.i.eq(self.compacter.o), self.packer.count.eq(self.compacter.count)
-
- def do_simulation(self, selfp):
- if selfp.simulator.cycle_counter == self.end_cycle:
- print("got: " + str(self.output))
- print("expected: " + str([value for value, keep in self.test_seq if keep]))
- raise StopSimulation
-
- # push values
- sel = 0
- for i in range(4):
- try:
- value, keep = next(self.input_it)
- except StopIteration:
- value, keep = 0, 0
- if self.end_cycle == -1:
- self.end_cycle = selfp.simulator.cycle_counter + 3
- sel |= int(keep) << i
- setattr(selfp.compacter.i, "w"+str(i), value)
- selfp.compacter.sel = sel
-
- # pull values
- if selfp.packer.stb:
- for i in range(4):
- self.output.append(getattr(selfp.packer.o, "w"+str(i)))
-
-class DownscalerCore(Module):
- def __init__(self, base_layout, N, res_bits):
- self.init = Signal()
- self.ready = Signal()
- self.ce = Signal()
-
- self.hres_in = Signal(res_bits)
- self.vres_in = Signal(res_bits)
- self.i = Record([("w"+str(i), base_layout) for i in range(N)])
-
- self.hres_out = Signal(res_bits)
- self.vres_out = Signal(res_bits)
- self.o = Record([("w"+str(i), base_layout) for i in range(N)])
- self.stb = Signal()
-
- ###
-
- packbits = log2_int(N)
- hcounter = Signal(res_bits-packbits)
- self.sync += If(self.init,
- hcounter.eq(self.hres_in[packbits:] - 1)
- ).Elif(self.ce,
- If(hcounter == 0,
- hcounter.eq(self.hres_in[packbits:] - 1)
- ).Else(
- hcounter.eq(hcounter - 1)
- )
- )
- self.submodules.vselector = InsertReset(InsertCE(Chopper(res_bits)))
- self.comb += [
- self.vselector.reset.eq(self.init),
- self.vselector.ce.eq(self.ce & (hcounter == 0)),
- self.vselector.p.eq(self.vres_out),
- self.vselector.q.eq(self.vres_in)
- ]
-
- self.submodules.hselector = MultiChopper(N, res_bits)
- self.comb += [
- self.hselector.init.eq(self.init),
- self.ready.eq(self.hselector.ready),
- self.hselector.next.eq(self.ce),
- self.hselector.p.eq(self.hres_out),
- self.hselector.q.eq(self.hres_in)
- ]
-
- self.submodules.compacter = InsertReset(InsertCE(Compacter(base_layout, N)))
- self.submodules.packer = InsertReset(InsertCE(Packer(base_layout, N)))
- self.comb += [
- self.compacter.reset.eq(self.init),
- self.packer.reset.eq(self.init),
- self.compacter.ce.eq(self.ce),
- self.packer.ce.eq(self.ce),
-
- self.compacter.i.eq(self.i),
- self.compacter.sel.eq(self.hselector.chopper & Replicate(self.vselector.chopper, N)),
- self.packer.i.eq(self.compacter.o),
- self.packer.count.eq(self.compacter.count),
- self.o.eq(self.packer.o),
- self.stb.eq(self.packer.stb)
- ]
-
-def _img_iter(img):
- for y in range(img.size[1]):
- for x in range(img.size[0]):
- newpix = yield img.getpixel((x, y))
- if newpix is not None:
- img.putpixel((x, y), newpix)
-
-class _DownscalerCoreTB(Module):
- def __init__(self):
- layout = [("r", 8), ("g", 8), ("b", 8)]
- self.submodules.dut = DownscalerCore(layout, 4, 11)
-
- def gen_simulation(self, selfp):
- from PIL import Image
- import subprocess
- dut = selfp.dut
- im_in = Image.open("testpic_in.jpg")
- im_out = Image.new("RGB", (320, 240))
-
- print("initializing downscaler...")
- dut.init = 1
- dut.hres_in, dut.vres_in = im_in.size
- dut.hres_out, dut.vres_out = im_out.size
- yield
- dut.init = 0
- yield
- while not dut.ready:
- yield
- print("done")
-
- dut.ce = 1
- it_in, it_out = _img_iter(im_in), _img_iter(im_out)
- it_out.send(None)
- while True:
- try:
- for i in range(4):
- w = getattr(dut.i, "w"+str(i))
- w.r, w.g, w.b = next(it_in)
- except StopIteration:
- pass
- if dut.stb:
- try:
- for i in range(4):
- w = getattr(dut.o, "w"+str(i))
- it_out.send((w.r, w.g, w.b))
- except StopIteration:
- break
- yield
-
- im_out.save("testpic_out.png")
- try:
- subprocess.call(["tycat", "testpic_out.png"])
- except OSError:
- print("Image saved as testpic_out.png, but could not be displayed.")
- pass
-
-if __name__ == "__main__":
- print("*** Testing chopper ***")
- run_simulation(_ChopperTB())
-
- print("*** Testing multichopper ***")
- run_simulation(_MultiChopperTB())
-
- print("*** Testing compacter and packer ***")
- run_simulation(_CompacterPackerTB())
-
- print("*** Testing downscaler core ***")
- run_simulation(_DownscalerCoreTB())
+++ /dev/null
-MSCDIR=../..
-include $(MSCDIR)/software/common.mak
-
-OBJECTS=isr.o processor.o dvisampler0.o dvisampler1.o edid.o pll.o ci.o config.o main.o
-
-all: videomixer.bin videomixer.fbi
-
-# pull in dependency info for *existing* .o files
--include $(OBJECTS:.o=.d)
-
-%.bin: %.elf
- $(OBJCOPY) -O binary $< $@
- chmod -x $@
-
-%.fbi: %.bin
- $(MSCDIR)/mkmscimg.py -f -o $@ $<
-
-videomixer.elf: $(OBJECTS) libs
-
-%.elf:
- $(LD) $(LDFLAGS) \
- -T $(MSCDIR)/software/libbase/linker-sdram.ld \
- -N -o $@ \
- $(MSCDIR)/software/libbase/crt0-$(CPU).o \
- $(OBJECTS) \
- -L$(MSCDIR)/software/libbase \
- -L$(MSCDIR)/software/libcompiler-rt \
- -lbase -lcompiler-rt
- chmod -x $@
-
-main.o: main.c
- $(compile-dep)
-
-%.o: %.c
- $(compile-dep)
-
-%.o: %.S
- $(assemble)
-
-define gen0
-@echo " GEN " $@
-@sed -e "s/dvisamplerX/dvisampler0/g;s/DVISAMPLERX/DVISAMPLER0/g;s/fb_fi_baseX/fb_fi_base0/g" $< > $@
-endef
-
-define gen1
-@echo " GEN " $@
-@sed -e "s/dvisamplerX/dvisampler1/g;s/DVISAMPLERX/DVISAMPLER1/g;s/fb_fi_baseX/fb_fi_base1/g" $< > $@
-endef
-
-dvisampler0.c: dvisamplerX.c
- $(gen0)
-dvisampler0.h: dvisamplerX.h
- $(gen0)
-dvisampler1.c: dvisamplerX.c
- $(gen1)
-dvisampler1.h: dvisamplerX.h
- $(gen1)
-
-isr.o: dvisampler0.h dvisampler1.h
-main.o: dvisampler0.h dvisampler1.h
-dvisampler0.o: dvisampler0.h
-dvisampler1.o: dvisampler1.h
-
-libs:
- $(MAKE) -C $(MSCDIR)/software/libcompiler-rt
- $(MAKE) -C $(MSCDIR)/software/libbase
-
-load: videomixer.bin
- $(MAKE) -C $(MSCDIR)/tools
- $(MSCDIR)/tools/flterm --port /dev/ttyUSB0 --kernel videomixer.bin
-
-flash: videomixer.fbi
- $(MSCDIR)/flash_extra.py mixxeo videomixer.fbi 0x001a0000
-
-clean:
- $(RM) $(OBJECTS) $(OBJECTS:.o=.d) videomixer.elf videomixer.bin videomixer.fbi
- $(RM) .*~ *~
- $(RM) dvisampler0.h dvisampler0.c dvisampler1.h dvisampler1.c
-
-.PHONY: all main.o clean libs load
+++ /dev/null
-#include <stdio.h>
-
-#include <console.h>
-#include <generated/csr.h>
-
-#include "config.h"
-#include "dvisampler0.h"
-#include "dvisampler1.h"
-#include "processor.h"
-#include "pll.h"
-#include "ci.h"
-
-static void print_mem_bandwidth(void)
-{
- unsigned long long int nr, nw;
- unsigned long long int f;
- unsigned int rdb, wrb;
-
- lasmicon_bandwidth_update_write(1);
- nr = lasmicon_bandwidth_nreads_read();
- nw = lasmicon_bandwidth_nwrites_read();
- f = identifier_frequency_read();
- rdb = (nr*f >> (24 - 7))/1000000ULL;
- wrb = (nw*f >> (24 - 7))/1000000ULL;
- printf("read:%5dMbps write:%5dMbps all:%5dMbps\n", rdb, wrb, rdb + wrb);
-}
-
-static void list_video_modes(void)
-{
- char mode_descriptors[PROCESSOR_MODE_COUNT*PROCESSOR_MODE_DESCLEN];
- int i;
-
- processor_list_modes(mode_descriptors);
- printf("==== Available video modes ====\n");
- for(i=0;i<PROCESSOR_MODE_COUNT;i++)
- printf(" %d: %s\n", i, &mode_descriptors[i*PROCESSOR_MODE_DESCLEN]);
- printf("===============================\n");
-}
-
-void ci_service(void)
-{
- int c;
-
- if(readchar_nonblock()) {
- c = readchar();
- if((c >= '0') && (c <= '9')) {
- int m;
-
- m = c - '0';
- if(m < PROCESSOR_MODE_COUNT) {
- config_set(CONFIG_KEY_RESOLUTION, m);
- processor_start(m);
- }
- }
- switch(c) {
- case 'l':
- list_video_modes();
- break;
- case 'D':
- dvisampler0_debug = dvisampler1_debug = 1;
- printf("DVI sampler debug is ON\n");
- break;
- case 'd':
- dvisampler0_debug = dvisampler1_debug = 0;
- printf("DVI sampler debug is OFF\n");
- break;
- case 'F':
- fb_fi_enable_write(1);
- printf("framebuffer is ON\n");
- break;
- case 'f':
- fb_fi_enable_write(0);
- printf("framebuffer is OFF\n");
- break;
- case 'm':
- print_mem_bandwidth();
- break;
- case 'p':
- pll_dump();
- break;
- }
- }
-}
+++ /dev/null
-#ifndef __CI_H
-#define __CI_H
-
-void ci_service(void);
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <generated/mem.h>
-
-#include "config.h"
-
-#define FLASH_BLOCK_SIZE (128*1024)
-#define FLASH_OFFSET_CONFIG (FLASH_BOOT_ADDRESS + FLASH_BLOCK_SIZE)
-
-static volatile unsigned short *flash_config = (unsigned short *)(0x80000000 | FLASH_OFFSET_CONFIG);
-
-static void wait_program(void)
-{
- while(!(*flash_config & 0x0080)); /* Read status register */
- *flash_config = 0x0050; /* Clear status register */
- *flash_config = 0x00ff; /* Go to Read Array mode */
-}
-
-static void config_erase_block(void)
-{
- *flash_config = 0x0020; /* Setup Erase */
- *flash_config = 0x00d0; /* Confirm Erase */
- wait_program();
-}
-
-static void config_write(int offset, unsigned short data)
-{
- flash_config[offset] = 0x0040; /* Word Program */
- flash_config[offset] = data;
- wait_program();
-}
-
-static const unsigned char config_defaults[CONFIG_KEY_COUNT] = CONFIG_DEFAULTS;
-static int config_record_count;
-static unsigned char config_values[CONFIG_KEY_COUNT];
-
-static int config_process_record(unsigned char key, unsigned char value)
-{
- if(key >= CONFIG_KEY_COUNT)
- return 0;
- config_record_count++;
- config_values[key] = value;
- return 1;
-}
-
-void config_init(void)
-{
- volatile unsigned int *flash_config32 = (unsigned int *)flash_config;
- int i;
- unsigned int flash_word;
-
- memcpy(config_values, config_defaults, CONFIG_KEY_COUNT);
-
- for(i=0;i<FLASH_BLOCK_SIZE/4;i++) {
- flash_word = flash_config32[i];
- if(!config_process_record((flash_word >> 24) & 0xff, (flash_word >> 16) & 0xff))
- break;
- if(!config_process_record((flash_word >> 8) & 0xff, flash_word & 0xff))
- break;
- }
-}
-
-void config_write_all(void)
-{
- int i;
-
- config_erase_block();
- config_record_count = 0;
- for(i=0;i<CONFIG_KEY_COUNT;i++) {
- if(config_values[i] != config_defaults[i]) {
- config_write(config_record_count, (i << 8) | config_values[i]);
- config_record_count++;
- }
- }
-}
-
-unsigned char config_get(unsigned char key)
-{
- return config_values[key];
-}
-
-void config_set(unsigned char key, unsigned char value)
-{
- if(config_values[key] == value)
- return;
- config_values[key] = value;
- if(config_record_count < FLASH_BLOCK_SIZE/2)
- config_write(config_record_count++, (key << 8) | value);
- else
- config_write_all();
-}
+++ /dev/null
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-enum {
- CONFIG_KEY_RESOLUTION = 0,
- CONFIG_KEY_BLEND_USER1,
- CONFIG_KEY_BLEND_USER2,
- CONFIG_KEY_BLEND_USER3,
- CONFIG_KEY_BLEND_USER4,
-
- CONFIG_KEY_COUNT
-};
-
-#define CONFIG_DEFAULTS { 6, 1, 2, 3, 4 }
-
-void config_init(void);
-void config_write_all(void);
-unsigned char config_get(unsigned char key);
-void config_set(unsigned char key, unsigned char value);
-
-#endif /* __CONFIG_H */
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <irq.h>
-#include <uart.h>
-#include <time.h>
-#include <system.h>
-#include <generated/csr.h>
-#include <hw/flags.h>
-
-#include "dvisamplerX.h"
-
-int dvisamplerX_debug;
-
-#define FRAMEBUFFER_COUNT 4
-#define FRAMEBUFFER_MASK (FRAMEBUFFER_COUNT - 1)
-
-static unsigned int dvisamplerX_framebuffers[FRAMEBUFFER_COUNT][1280*720] __attribute__((aligned(16)));
-static int dvisamplerX_fb_slot_indexes[2];
-static int dvisamplerX_next_fb_index;
-static int dvisamplerX_hres, dvisamplerX_vres;
-
-void dvisamplerX_isr(void)
-{
- int fb_index = -1;
- int length;
- int expected_length;
- unsigned int address_min, address_max;
-
- address_min = (unsigned int)dvisamplerX_framebuffers & 0x0fffffff;
- address_max = address_min + sizeof(dvisamplerX_framebuffers);
- if((dvisamplerX_dma_slot0_status_read() == DVISAMPLER_SLOT_PENDING)
- && ((dvisamplerX_dma_slot0_address_read() < address_min) || (dvisamplerX_dma_slot0_address_read() > address_max)))
- printf("dvisamplerX: slot0: stray DMA\n");
- if((dvisamplerX_dma_slot1_status_read() == DVISAMPLER_SLOT_PENDING)
- && ((dvisamplerX_dma_slot1_address_read() < address_min) || (dvisamplerX_dma_slot1_address_read() > address_max)))
- printf("dvisamplerX: slot1: stray DMA\n");
-
- if((dvisamplerX_resdetection_hres_read() != dvisamplerX_hres)
- || (dvisamplerX_resdetection_vres_read() != dvisamplerX_vres)) {
- /* Dump frames until we get the expected resolution */
- if(dvisamplerX_dma_slot0_status_read() == DVISAMPLER_SLOT_PENDING) {
- dvisamplerX_dma_slot0_address_write((unsigned int)dvisamplerX_framebuffers[dvisamplerX_fb_slot_indexes[0]]);
- dvisamplerX_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED);
- }
- if(dvisamplerX_dma_slot1_status_read() == DVISAMPLER_SLOT_PENDING) {
- dvisamplerX_dma_slot1_address_write((unsigned int)dvisamplerX_framebuffers[dvisamplerX_fb_slot_indexes[1]]);
- dvisamplerX_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED);
- }
- return;
- }
-
- expected_length = dvisamplerX_hres*dvisamplerX_vres*4;
- if(dvisamplerX_dma_slot0_status_read() == DVISAMPLER_SLOT_PENDING) {
- length = dvisamplerX_dma_slot0_address_read() - ((unsigned int)dvisamplerX_framebuffers[dvisamplerX_fb_slot_indexes[0]] & 0x0fffffff);
- if(length == expected_length) {
- fb_index = dvisamplerX_fb_slot_indexes[0];
- dvisamplerX_fb_slot_indexes[0] = dvisamplerX_next_fb_index;
- dvisamplerX_next_fb_index = (dvisamplerX_next_fb_index + 1) & FRAMEBUFFER_MASK;
- } else
- printf("dvisamplerX: slot0: unexpected frame length: %d\n", length);
- dvisamplerX_dma_slot0_address_write((unsigned int)dvisamplerX_framebuffers[dvisamplerX_fb_slot_indexes[0]]);
- dvisamplerX_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED);
- }
- if(dvisamplerX_dma_slot1_status_read() == DVISAMPLER_SLOT_PENDING) {
- length = dvisamplerX_dma_slot1_address_read() - ((unsigned int)dvisamplerX_framebuffers[dvisamplerX_fb_slot_indexes[1]] & 0x0fffffff);
- if(length == expected_length) {
- fb_index = dvisamplerX_fb_slot_indexes[1];
- dvisamplerX_fb_slot_indexes[1] = dvisamplerX_next_fb_index;
- dvisamplerX_next_fb_index = (dvisamplerX_next_fb_index + 1) & FRAMEBUFFER_MASK;
- } else
- printf("dvisamplerX: slot1: unexpected frame length: %d\n", length);
- dvisamplerX_dma_slot1_address_write((unsigned int)dvisamplerX_framebuffers[dvisamplerX_fb_slot_indexes[1]]);
- dvisamplerX_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED);
- }
-
- if(fb_index != -1)
- fb_fi_baseX_write((unsigned int)dvisamplerX_framebuffers[fb_index]);
-}
-
-static int dvisamplerX_connected;
-static int dvisamplerX_locked;
-
-void dvisamplerX_init_video(int hres, int vres)
-{
- unsigned int mask;
-
- dvisamplerX_clocking_pll_reset_write(1);
- dvisamplerX_connected = dvisamplerX_locked = 0;
- dvisamplerX_hres = hres; dvisamplerX_vres = vres;
-
- dvisamplerX_dma_frame_size_write(hres*vres*4);
- dvisamplerX_fb_slot_indexes[0] = 0;
- dvisamplerX_dma_slot0_address_write((unsigned int)dvisamplerX_framebuffers[0]);
- dvisamplerX_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED);
- dvisamplerX_fb_slot_indexes[1] = 1;
- dvisamplerX_dma_slot1_address_write((unsigned int)dvisamplerX_framebuffers[1]);
- dvisamplerX_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED);
- dvisamplerX_next_fb_index = 2;
-
- dvisamplerX_dma_ev_pending_write(dvisamplerX_dma_ev_pending_read());
- dvisamplerX_dma_ev_enable_write(0x3);
- mask = irq_getmask();
- mask |= 1 << DVISAMPLERX_INTERRUPT;
- irq_setmask(mask);
-
- fb_fi_baseX_write((unsigned int)dvisamplerX_framebuffers[3]);
-}
-
-void dvisamplerX_disable(void)
-{
- unsigned int mask;
-
- mask = irq_getmask();
- mask &= ~(1 << DVISAMPLERX_INTERRUPT);
- irq_setmask(mask);
-
- 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)
-{
- memset(&dvisamplerX_framebuffers, 0, sizeof(dvisamplerX_framebuffers));
- flush_l2_cache();
-}
-
-static int dvisamplerX_d0, dvisamplerX_d1, dvisamplerX_d2;
-
-void dvisamplerX_print_status(void)
-{
- dvisamplerX_data0_wer_update_write(1);
- dvisamplerX_data1_wer_update_write(1);
- dvisamplerX_data2_wer_update_write(1);
- printf("dvisamplerX: ph:%4d %4d %4d // charsync:%d%d%d [%d %d %d] // WER:%3d %3d %3d // chansync:%d // res:%dx%d\n",
- dvisamplerX_d0, dvisamplerX_d1, dvisamplerX_d2,
- dvisamplerX_data0_charsync_char_synced_read(),
- dvisamplerX_data1_charsync_char_synced_read(),
- dvisamplerX_data2_charsync_char_synced_read(),
- dvisamplerX_data0_charsync_ctl_pos_read(),
- dvisamplerX_data1_charsync_ctl_pos_read(),
- dvisamplerX_data2_charsync_ctl_pos_read(),
- dvisamplerX_data0_wer_value_read(),
- dvisamplerX_data1_wer_value_read(),
- dvisamplerX_data2_wer_value_read(),
- dvisamplerX_chansync_channels_synced_read(),
- dvisamplerX_resdetection_hres_read(),
- dvisamplerX_resdetection_vres_read());
-}
-
-static int wait_idelays(void)
-{
- int ev;
-
- ev = 0;
- elapsed(&ev, 1);
- while(dvisamplerX_data0_cap_dly_busy_read()
- || dvisamplerX_data1_cap_dly_busy_read()
- || dvisamplerX_data2_cap_dly_busy_read()) {
- if(elapsed(&ev, identifier_frequency_read() >> 6) == 0) {
- printf("dvisamplerX: IDELAY busy timeout\n");
- return 0;
- }
- }
- return 1;
-}
-
-int dvisamplerX_calibrate_delays(void)
-{
- dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_CAL|DVISAMPLER_DELAY_SLAVE_CAL);
- dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_CAL|DVISAMPLER_DELAY_SLAVE_CAL);
- dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_CAL|DVISAMPLER_DELAY_SLAVE_CAL);
- if(!wait_idelays())
- return 0;
- dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_RST|DVISAMPLER_DELAY_SLAVE_RST);
- dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_RST|DVISAMPLER_DELAY_SLAVE_RST);
- dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_RST|DVISAMPLER_DELAY_SLAVE_RST);
- dvisamplerX_data0_cap_phase_reset_write(1);
- dvisamplerX_data1_cap_phase_reset_write(1);
- dvisamplerX_data2_cap_phase_reset_write(1);
- dvisamplerX_d0 = dvisamplerX_d1 = dvisamplerX_d2 = 0;
- return 1;
-}
-
-int dvisamplerX_adjust_phase(void)
-{
- switch(dvisamplerX_data0_cap_phase_read()) {
- case DVISAMPLER_TOO_LATE:
- dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
- if(!wait_idelays())
- return 0;
- dvisamplerX_d0--;
- dvisamplerX_data0_cap_phase_reset_write(1);
- break;
- case DVISAMPLER_TOO_EARLY:
- dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
- if(!wait_idelays())
- return 0;
- dvisamplerX_d0++;
- dvisamplerX_data0_cap_phase_reset_write(1);
- break;
- }
- switch(dvisamplerX_data1_cap_phase_read()) {
- case DVISAMPLER_TOO_LATE:
- dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
- if(!wait_idelays())
- return 0;
- dvisamplerX_d1--;
- dvisamplerX_data1_cap_phase_reset_write(1);
- break;
- case DVISAMPLER_TOO_EARLY:
- dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
- if(!wait_idelays())
- return 0;
- dvisamplerX_d1++;
- dvisamplerX_data1_cap_phase_reset_write(1);
- break;
- }
- switch(dvisamplerX_data2_cap_phase_read()) {
- case DVISAMPLER_TOO_LATE:
- dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
- if(!wait_idelays())
- return 0;
- dvisamplerX_d2--;
- dvisamplerX_data2_cap_phase_reset_write(1);
- break;
- case DVISAMPLER_TOO_EARLY:
- dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
- if(!wait_idelays())
- return 0;
- dvisamplerX_d2++;
- dvisamplerX_data2_cap_phase_reset_write(1);
- break;
- }
- return 1;
-}
-
-int dvisamplerX_init_phase(void)
-{
- int o_d0, o_d1, o_d2;
- int i, j;
-
- for(i=0;i<100;i++) {
- o_d0 = dvisamplerX_d0;
- o_d1 = dvisamplerX_d1;
- o_d2 = dvisamplerX_d2;
- for(j=0;j<1000;j++) {
- if(!dvisamplerX_adjust_phase())
- return 0;
- }
- if((abs(dvisamplerX_d0 - o_d0) < 4) && (abs(dvisamplerX_d1 - o_d1) < 4) && (abs(dvisamplerX_d2 - o_d2) < 4))
- return 1;
- }
- return 0;
-}
-
-int dvisamplerX_phase_startup(void)
-{
- int ret;
- int attempts;
-
- attempts = 0;
- while(1) {
- attempts++;
- dvisamplerX_calibrate_delays();
- if(dvisamplerX_debug)
- printf("dvisamplerX: delays calibrated\n");
- ret = dvisamplerX_init_phase();
- if(ret) {
- if(dvisamplerX_debug)
- printf("dvisamplerX: phase init OK\n");
- return 1;
- } else {
- printf("dvisamplerX: phase init failed\n");
- if(attempts > 3) {
- printf("dvisamplerX: giving up\n");
- dvisamplerX_calibrate_delays();
- return 0;
- }
- }
- }
-}
-
-static void dvisamplerX_check_overflow(void)
-{
- if(dvisamplerX_frame_overflow_read()) {
- printf("dvisamplerX: FIFO overflow\n");
- dvisamplerX_frame_overflow_write(1);
- }
-}
-
-static int dvisamplerX_clocking_locked_filtered(void)
-{
- static int lock_start_time;
- static int lock_status;
-
- if(dvisamplerX_clocking_locked_read()) {
- switch(lock_status) {
- case 0:
- elapsed(&lock_start_time, -1);
- lock_status = 1;
- break;
- case 1:
- if(elapsed(&lock_start_time, identifier_frequency_read()/4))
- lock_status = 2;
- break;
- case 2:
- return 1;
- }
- } else
- lock_status = 0;
- return 0;
-}
-
-void dvisamplerX_service(void)
-{
- static int last_event;
-
- if(dvisamplerX_connected) {
- if(!dvisamplerX_edid_hpd_notif_read()) {
- if(dvisamplerX_debug)
- printf("dvisamplerX: disconnected\n");
- dvisamplerX_connected = 0;
- dvisamplerX_locked = 0;
- dvisamplerX_clocking_pll_reset_write(1);
- dvisamplerX_clear_framebuffers();
- } else {
- if(dvisamplerX_locked) {
- if(dvisamplerX_clocking_locked_filtered()) {
- if(elapsed(&last_event, identifier_frequency_read()/2)) {
- dvisamplerX_adjust_phase();
- if(dvisamplerX_debug)
- dvisamplerX_print_status();
- }
- } else {
- if(dvisamplerX_debug)
- printf("dvisamplerX: lost PLL lock\n");
- dvisamplerX_locked = 0;
- dvisamplerX_clear_framebuffers();
- }
- } else {
- if(dvisamplerX_clocking_locked_filtered()) {
- if(dvisamplerX_debug)
- printf("dvisamplerX: PLL locked\n");
- dvisamplerX_phase_startup();
- if(dvisamplerX_debug)
- dvisamplerX_print_status();
- dvisamplerX_locked = 1;
- }
- }
- }
- } else {
- if(dvisamplerX_edid_hpd_notif_read()) {
- if(dvisamplerX_debug)
- printf("dvisamplerX: connected\n");
- dvisamplerX_connected = 1;
- dvisamplerX_clocking_pll_reset_write(0);
- }
- }
- dvisamplerX_check_overflow();
-}
+++ /dev/null
-#ifndef __DVISAMPLERX_H
-#define __DVISAMPLERX_H
-
-extern int dvisamplerX_debug;
-
-void dvisamplerX_isr(void);
-void dvisamplerX_init_video(int hres, int vres);
-void dvisamplerX_disable(void);
-void dvisamplerX_clear_framebuffers(void);
-void dvisamplerX_print_status(void);
-int dvisamplerX_calibrate_delays(void);
-int dvisamplerX_adjust_phase(void);
-int dvisamplerX_init_phase(void);
-int dvisamplerX_phase_startup(void);
-void dvisamplerX_service(void);
-
-#endif
+++ /dev/null
-#include <stdint.h>
-#include <string.h>
-
-#include "edid.h"
-
-struct edid {
- uint8_t header[8];
-
- uint8_t manufacturer[2];
- uint8_t product_code[2];
- uint8_t serial_number[4];
- uint8_t manufacture_week;
- uint8_t manufacture_year;
-
- uint8_t edid_version;
- uint8_t edid_revision;
-
- uint8_t video_input;
- uint8_t h_image_size;
- uint8_t v_image_size;
- uint8_t gamma;
- uint8_t feature_support;
-
- uint8_t cc_rg_l;
- uint8_t cc_bw_l;
- uint8_t cc_rx_h;
- uint8_t cc_ry_h;
- uint8_t cc_gx_h;
- uint8_t cc_gy_h;
- uint8_t cc_bx_h;
- uint8_t cc_by_h;
- uint8_t cc_wx_h;
- uint8_t cc_wy_h;
-
- uint8_t est_timings_1;
- uint8_t est_timings_2;
- uint8_t rsv_timings;
-
- uint8_t timings_std[16];
-
- uint8_t data_blocks[4][18];
-
- uint8_t ext_block_count;
-
- uint8_t checksum;
-} __attribute__((packed));
-
-struct edid_timing {
- uint8_t pixel_clock[2];
-
- uint8_t h_active_l;
- uint8_t h_blanking_l;
- uint8_t h_active_blanking_h;
-
- uint8_t v_active_l;
- uint8_t v_blanking_l;
- uint8_t v_active_blanking_h;
-
- uint8_t h_sync_offset_l;
- uint8_t h_sync_width_l;
- uint8_t v_sync_offset_width_l;
- uint8_t hv_sync_offset_width_h;
-
- uint8_t h_image_size_l;
- uint8_t v_image_size_l;
- uint8_t hv_image_size_h;
-
- uint8_t h_border;
- uint8_t v_border;
-
- uint8_t flags;
-} __attribute__((packed));
-
-struct edid_descriptor {
- uint8_t flag0;
- uint8_t flag1;
- uint8_t flag2;
- uint8_t data_type;
- uint8_t flag3;
- uint8_t data[13];
-} __attribute__((packed));
-
-static const char correct_header[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
-
-static uint8_t compute_checksum(struct edid *e)
-{
- uint8_t *p = (uint8_t *)e;
- uint8_t sum;
- int i;
-
- sum = 0;
- for(i=0;i<127;i++)
- sum += p[i];
- return -sum;
-}
-
-int validate_edid(const void *buf)
-{
- struct edid *e = (struct edid *)buf;
-
- if(memcmp(e->header, correct_header, 8) != 0)
- return 0;
- if(compute_checksum(e) != e->checksum)
- return 0;
- return 1;
-}
-
-void get_monitor_name(const void *buf, char *name)
-{
- struct edid *e = (struct edid *)buf;
- int i;
- uint8_t *data_block;
- char *c;
-
- name[0] = 0;
-
- data_block = NULL;
- for(i=0;i<4;i++)
- if((e->data_blocks[i][0] == 0x00)
- && (e->data_blocks[i][1] == 0x00)
- && (e->data_blocks[i][2] == 0x00)
- && (e->data_blocks[i][3] == 0xfc)) {
- data_block = e->data_blocks[i];
- break;
- }
- if(!data_block)
- return;
-
- name[MAX_MONITOR_NAME_LEN] = 0;
- memcpy(name, &data_block[5], MAX_MONITOR_NAME_LEN);
- c = strchr(name, '\n');
- if(c)
- *c = 0;
-}
-
-static void generate_edid_timing(uint8_t *data_block, const struct video_timing *timing)
-{
- struct edid_timing *t = (struct edid_timing *)data_block;
- unsigned int h_image_size, v_image_size;
-
- t->pixel_clock[0] = timing->pixel_clock & 0xff;
- t->pixel_clock[1] = timing->pixel_clock >> 8;
-
- t->h_active_l = timing->h_active & 0xff;
- t->h_blanking_l = timing->h_blanking & 0xff;
- t->h_active_blanking_h = ((timing->h_active >> 8) << 4) | (timing->h_blanking >> 8);
-
- t->v_active_l = timing->v_active & 0xff;
- t->v_blanking_l = timing->v_blanking & 0xff;
- t->v_active_blanking_h = ((timing->v_active >> 8) << 4) | (timing->v_blanking >> 8);
-
- t->h_sync_offset_l = timing->h_sync_offset & 0xff;
- t->h_sync_width_l = timing->h_sync_width & 0xff;
- t->v_sync_offset_width_l = timing->v_sync_offset & 0xff;
- t->hv_sync_offset_width_h = ((timing->h_sync_offset >> 8) << 6) | ((timing->h_sync_width >> 8) << 4)
- | ((timing->v_sync_offset >> 8) << 2) | (timing->v_sync_width >> 8);
-
- h_image_size = 10*timing->h_active/64;
- v_image_size = 10*timing->v_active/64;
- t->h_image_size_l = h_image_size & 0xff;
- t->v_image_size_l = v_image_size & 0xff;
- t->hv_image_size_h = ((h_image_size >> 8) << 4) | (v_image_size >> 8);
-
- t->h_border = 0;
- t->v_border = 0;
-
- t->flags = 0x1e;
-}
-
-static void generate_monitor_name(uint8_t *data_block, const char *name)
-{
- struct edid_descriptor *d = (struct edid_descriptor *)data_block;
- int i;
-
- d->flag0 = d->flag1 = d->flag2 = d->flag3 = 0;
- d->data_type = 0xfc;
- for(i=0;i<12;i++) {
- if(!name[i])
- break;
- d->data[i] = name[i];
- }
- d->data[i++] = 0x0a;
- for(;i<13;i++)
- d->data[i] = 0x20;
-}
-
-static void generate_unused(uint8_t *data_block)
-{
- struct edid_descriptor *d = (struct edid_descriptor *)data_block;
-
- memset(d, 0, sizeof(struct edid_descriptor));
- d->data_type = 0x10;
-}
-
-void generate_edid(void *out,
- const char mfg_name[3], const char product_code[2], int year,
- const char *name,
- const struct video_timing *timing)
-{
- struct edid *e = (struct edid *)out;
- int i, j, k;
-
- memcpy(e->header, correct_header, 8);
-
- i = mfg_name[0] - 'A' + 1;
- j = mfg_name[1] - 'A' + 1;
- k = mfg_name[2] - 'A' + 1;
- e->manufacturer[0] = (i << 2) | (j >> 3);
- e->manufacturer[1] = ((j & 0x07) << 5) | k;
- e->product_code[0] = product_code[0]; e->product_code[1] = product_code[1];
- e->serial_number[0] = e->serial_number[1] = e->serial_number[2] = e->serial_number[3] = 0;
- e->manufacture_week = 0;
- e->manufacture_year = year - 1990;
-
- e->edid_version = 1;
- e->edid_revision = 3;
-
- e->video_input = 0x80; /* digital */
- e->h_image_size = timing->h_active/64;
- e->v_image_size = timing->v_active/64;
- e->gamma = 0xff;
- e->feature_support = 0x06;
-
- e->cc_rg_l = 0;
- e->cc_bw_l = 0;
- e->cc_rx_h = 0;
- e->cc_ry_h = 0;
- e->cc_gx_h = 0;
- e->cc_gy_h = 0;
- e->cc_bx_h = 0;
- e->cc_by_h = 0;
- e->cc_wx_h = 0;
- e->cc_wy_h = 0;
-
- e->est_timings_1 = timing->established_timing >> 8;
- e->est_timings_2 = timing->established_timing & 0xff;
- e->rsv_timings = 0;
- memset(e->timings_std, 0x01, 16);
-
- generate_edid_timing(e->data_blocks[0], timing);
- generate_monitor_name(e->data_blocks[1], name);
- generate_unused(e->data_blocks[2]);
- generate_unused(e->data_blocks[3]);
-
- e->ext_block_count = 0;
-
- e->checksum = compute_checksum(e);
-}
+++ /dev/null
-#ifndef __EDID_H
-#define __EDID_H
-
-#define MAX_MONITOR_NAME_LEN 13
-
-struct video_timing {
- unsigned int pixel_clock; /* in tens of kHz */
-
- unsigned int h_active;
- unsigned int h_blanking;
- unsigned int h_sync_offset;
- unsigned int h_sync_width;
-
- unsigned int v_active;
- unsigned int v_blanking;
- unsigned int v_sync_offset;
- unsigned int v_sync_width;
-
- unsigned int established_timing;
-};
-
-int validate_edid(const void *buf);
-void get_monitor_name(const void *buf, char *name);
-void generate_edid(void *out,
- const char mfg_name[3], const char product_code[2], int year,
- const char *name,
- const struct video_timing *timing);
-
-#endif
+++ /dev/null
-#include <generated/csr.h>
-#include <irq.h>
-#include <uart.h>
-
-#include "dvisampler0.h"
-#include "dvisampler1.h"
-
-void isr(void);
-void isr(void)
-{
- unsigned int irqs;
-
- irqs = irq_pending() & irq_getmask();
-
- if(irqs & (1 << UART_INTERRUPT))
- uart_isr();
- if(irqs & (1 << DVISAMPLER0_INTERRUPT))
- dvisampler0_isr();
- if(irqs & (1 << DVISAMPLER1_INTERRUPT))
- dvisampler1_isr();
-}
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <irq.h>
-#include <uart.h>
-#include <time.h>
-#include <generated/csr.h>
-#include <hw/flags.h>
-#include <console.h>
-
-#include "config.h"
-#include "ci.h"
-#include "processor.h"
-
-#ifdef POTS_BASE
-static int scale_pot(int raw, int range)
-{
- int pot_min = 64000;
- int pot_max = 103000;
- int scaled;
-
- scaled = range*(raw - pot_min)/(pot_max - pot_min);
- if(scaled < 0)
- scaled = 0;
- if(scaled > range)
- scaled = range;
- return scaled;
-}
-
-static void regular_blend(int p0, int p1)
-{
- int blackout;
- int crossfade;
-
- blackout = scale_pot(p0, 256);
- crossfade = scale_pot(p1, 255);
-
- fb_blender_f0_write(crossfade*blackout >> 8);
- fb_blender_f1_write((255-crossfade)*blackout >> 8);
-}
-
-static void additive_blend(int p0, int p1)
-{
- fb_blender_f0_write(scale_pot(p0, 255));
- fb_blender_f1_write(scale_pot(p1, 255));
-}
-
-static void ui_service(void)
-{
- static int last_event;
- static int additive_blend_enabled;
- static int old_btn;
- int btn;
- int p0, p1;
-
- if(elapsed(&last_event, identifier_frequency_read()/32)) {
- btn = buttons_in_read() & 0x1;
- if(btn && !old_btn) {
- additive_blend_enabled = !additive_blend_enabled;
- if(additive_blend_enabled)
- leds_out_write(leds_out_read() | 0x1);
- else
- leds_out_write(leds_out_read() & ~0x1);
- }
- old_btn = btn;
-
- pots_start_busy_write(1);
- while(pots_start_busy_read());
- p0 = pots_res0_read();
- p1 = pots_res1_read();
- if(!additive_blend_enabled)
- regular_blend(p0, p1);
- else
- additive_blend(p0, p1);
- }
-}
-
-#else
-
-static void ui_service(void)
-{
- fb_blender_f0_write(0xff);
- fb_blender_f1_write(0xff);
-}
-
-#endif
-
-int main(void)
-{
- irq_setmask(0);
- irq_setie(1);
- uart_init();
-
- printf("Mixxeo software rev. %08x built "__DATE__" "__TIME__"\n\n", MSC_GIT_ID);
-
- config_init();
- time_init();
- processor_start(config_get(CONFIG_KEY_RESOLUTION));
-
- while(1) {
- processor_service();
- ui_service();
- ci_service();
- }
-
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-#include <generated/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");
-}
+++ /dev/null
-#ifndef __PLL_H
-#define __PLL_H
-
-void pll_config_for_clock(int freq);
-void pll_dump(void);
-
-#endif
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <generated/csr.h>
-#include <hw/flags.h>
-
-#include "dvisampler0.h"
-#include "dvisampler1.h"
-#include "edid.h"
-#include "pll.h"
-#include "processor.h"
-
-/* reference: http://martin.hinner.info/vga/timing.html */
-static const struct video_timing video_modes[PROCESSOR_MODE_COUNT] = {
- {
- .pixel_clock = 3150,
-
- .h_active = 640,
- .h_blanking = 192,
- .h_sync_offset = 24,
- .h_sync_width = 40,
-
- .v_active = 480,
- .v_blanking = 40,
- .v_sync_offset = 9,
- .v_sync_width = 3,
-
- .established_timing = 0x0800
- },
- {
- .pixel_clock = 3150,
-
- .h_active = 640,
- .h_blanking = 200,
- .h_sync_offset = 16,
- .h_sync_width = 64,
-
- .v_active = 480,
- .v_blanking = 20,
- .v_sync_offset = 1,
- .v_sync_width = 3,
-
- .established_timing = 0x0400
- },
- {
- .pixel_clock = 3600,
-
- .h_active = 800,
- .h_blanking = 224,
- .h_sync_offset = 24,
- .h_sync_width = 72,
-
- .v_active = 600,
- .v_blanking = 25,
- .v_sync_offset = 1,
- .v_sync_width = 2,
-
- .established_timing = 0x0200
- },
- {
- .pixel_clock = 4000,
-
- .h_active = 800,
- .h_blanking = 256,
- .h_sync_offset = 40,
- .h_sync_width = 128,
-
- .v_active = 600,
- .v_blanking = 28,
- .v_sync_offset = 1,
- .v_sync_width = 4,
-
- .established_timing = 0x0100
- },
- {
- .pixel_clock = 5000,
-
- .h_active = 800,
- .h_blanking = 240,
- .h_sync_offset = 56,
- .h_sync_width = 120,
-
- .v_active = 600,
- .v_blanking = 66,
- .v_sync_offset = 37,
- .v_sync_width = 6,
-
- .established_timing = 0x0080
- },
- {
- .pixel_clock = 4950,
-
- .h_active = 800,
- .h_blanking = 256,
- .h_sync_offset = 16,
- .h_sync_width = 80,
-
- .v_active = 600,
- .v_blanking = 25,
- .v_sync_offset = 1,
- .v_sync_width = 3,
-
- .established_timing = 0x0040
- },
- {
- .pixel_clock = 6500,
-
- .h_active = 1024,
- .h_blanking = 320,
- .h_sync_offset = 24,
- .h_sync_width = 136,
-
- .v_active = 768,
- .v_blanking = 38,
- .v_sync_offset = 3,
- .v_sync_width = 6,
-
- .established_timing = 0x0008
- },
- {
- .pixel_clock = 7500,
-
- .h_active = 1024,
- .h_blanking = 304,
- .h_sync_offset = 24,
- .h_sync_width = 136,
-
- .v_active = 768,
- .v_blanking = 38,
- .v_sync_offset = 3,
- .v_sync_width = 6,
-
- .established_timing = 0x0004
- },
- {
- .pixel_clock = 7880,
-
- .h_active = 1024,
- .h_blanking = 288,
- .h_sync_offset = 16,
- .h_sync_width = 96,
-
- .v_active = 768,
- .v_blanking = 32,
- .v_sync_offset = 1,
- .v_sync_width = 3,
-
- .established_timing = 0x0002
- },
- {
- .pixel_clock = 7425,
-
- .h_active = 1280,
- .h_blanking = 370,
- .h_sync_offset = 220,
- .h_sync_width = 40,
-
- .v_active = 720,
- .v_blanking = 30,
- .v_sync_offset = 20,
- .v_sync_width = 5
- }
-};
-
-void processor_list_modes(char *mode_descriptors)
-{
- int i;
- unsigned int refresh_span;
- unsigned int refresh_rate;
-
- for(i=0;i<PROCESSOR_MODE_COUNT;i++) {
- refresh_span = (video_modes[i].h_active + video_modes[i].h_blanking)*(video_modes[i].v_active + video_modes[i].v_blanking);
- refresh_rate = video_modes[i].pixel_clock*10000/refresh_span;
- sprintf(&mode_descriptors[PROCESSOR_MODE_DESCLEN*i],
- "%ux%u @%uHz", video_modes[i].h_active, video_modes[i].v_active, refresh_rate);
- }
-}
-
-static void fb_clkgen_write(int cmd, int data)
-{
- int word;
-
- word = (data << 2) | cmd;
- fb_driver_clocking_cmd_data_write(word);
- fb_driver_clocking_send_cmd_data_write(1);
- while(fb_driver_clocking_status_read() & CLKGEN_STATUS_BUSY);
-}
-
-static void fb_get_clock_md(unsigned int pixel_clock, unsigned int *best_m, unsigned int *best_d)
-{
- unsigned int ideal_m, ideal_d;
- unsigned int bm, bd;
- unsigned int m, d;
- unsigned int diff_current;
- unsigned int diff_tested;
-
- ideal_m = pixel_clock;
- ideal_d = 5000;
-
- bm = 1;
- bd = 0;
- for(d=1;d<=256;d++)
- for(m=2;m<=256;m++) {
- /* common denominator is d*bd*ideal_d */
- diff_current = abs(d*ideal_d*bm - d*bd*ideal_m);
- diff_tested = abs(bd*ideal_d*m - d*bd*ideal_m);
- if(diff_tested < diff_current) {
- bm = m;
- bd = d;
- }
- }
- *best_m = bm;
- *best_d = bd;
-}
-
-static void fb_set_mode(const struct video_timing *mode)
-{
- unsigned int clock_m, clock_d;
-
- fb_get_clock_md(mode->pixel_clock, &clock_m, &clock_d);
-
- fb_fi_hres_write(mode->h_active);
- fb_fi_hsync_start_write(mode->h_active + mode->h_sync_offset);
- fb_fi_hsync_end_write(mode->h_active + mode->h_sync_offset + mode->h_sync_width);
- fb_fi_hscan_write(mode->h_active + mode->h_blanking);
- fb_fi_vres_write(mode->v_active);
- fb_fi_vsync_start_write(mode->v_active + mode->v_sync_offset);
- fb_fi_vsync_end_write(mode->v_active + mode->v_sync_offset + mode->v_sync_width);
- fb_fi_vscan_write(mode->v_active + mode->v_blanking);
-
- fb_fi_length_write(mode->h_active*mode->v_active*4);
-
- fb_clkgen_write(0x1, clock_d-1);
- fb_clkgen_write(0x3, clock_m-1);
- fb_driver_clocking_send_go_write(1);
- while(!(fb_driver_clocking_status_read() & CLKGEN_STATUS_PROGDONE));
- while(!(fb_driver_clocking_status_read() & CLKGEN_STATUS_LOCKED));
-}
-
-static void edid_set_mode(const struct video_timing *mode)
-{
- unsigned char edid[128];
- int i;
-
- generate_edid(&edid, "OHW", "MX", 2013, "Mixxeo ch.A", mode);
- for(i=0;i<sizeof(edid);i++)
- MMPTR(DVISAMPLER0_EDID_MEM_BASE+4*i) = edid[i];
- generate_edid(&edid, "OHW", "MX", 2013, "Mixxeo ch.B", mode);
- for(i=0;i<sizeof(edid);i++)
- MMPTR(DVISAMPLER1_EDID_MEM_BASE+4*i) = edid[i];
-}
-
-void processor_start(int mode)
-{
- const struct video_timing *m = &video_modes[mode];
-
- fb_fi_enable_write(0);
- fb_driver_clocking_pll_reset_write(1);
- dvisampler0_edid_hpd_en_write(0);
- dvisampler1_edid_hpd_en_write(0);
-
- dvisampler0_disable();
- dvisampler1_disable();
- 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_fi_enable_write(1);
- dvisampler0_edid_hpd_en_write(1);
- dvisampler1_edid_hpd_en_write(1);
-}
-
-void processor_service(void)
-{
- dvisampler0_service();
- dvisampler1_service();
-}
+++ /dev/null
-#ifndef __PROCESSOR_H
-#define __PROCESSOR_H
-
-#define PROCESSOR_MODE_COUNT 10
-#define PROCESSOR_MODE_DESCLEN 32
-
-void processor_list_modes(char *mode_descriptors);
-void processor_start(int mode);
-void processor_service(void);
-
-#endif /* __VIDEOMODE_H */
from migen.fhdl.std import *
from mibuild.generic_platform import ConstraintError
-from misoclib import lasmicon, mxcrg, norflash16, minimac3, framebuffer, dvisampler, gpio
+from misoclib import lasmicon, mxcrg, norflash16, minimac3, framebuffer, gpio
from misoclib.sdramphy import s6ddrphy
from misoclib.gensoc import SDRAMSoC
self.eth_rx_clk = eth_clocks.rx
self.eth_tx_clk = eth_clocks.tx
-class MiniSoC(SDRAMSoC):
+class BaseSoC(SDRAMSoC):
default_platform = "mixxeo" # also supports m1
- csr_map = {
- "minimac": 10,
- "fb": 11,
- "dvisampler0": 12,
- "dvisampler0_edid_mem": 13,
- "dvisampler1": 14,
- "dvisampler1_edid_mem": 15,
- }
- csr_map.update(SDRAMSoC.csr_map)
-
- interrupt_map = {
- "minimac": 2,
- "dvisampler0": 3,
- "dvisampler1": 4,
- }
- interrupt_map.update(SDRAMSoC.interrupt_map)
-
def __init__(self, platform, **kwargs):
SDRAMSoC.__init__(self, platform,
clk_freq=(83 + Fraction(1, 3))*1000000,
rd_bitslip=0, wr_bitslip=3, dqs_ddr_alignment="C1")
self.register_sdram_phy(self.ddrphy.dfi, self.ddrphy.phy_settings, sdram_geom, sdram_timing)
- # Wishbone
self.submodules.norflash = norflash16.NorFlash16(platform.request("norflash"),
self.ns(110), self.ns(50))
self.flash_boot_address = 0x001a0000
self.register_rom(self.norflash.bus)
- self.submodules.minimac = minimac3.MiniMAC(platform.request("eth"))
- self.add_wb_slave(lambda a: a[26:29] == 3, self.minimac.membus)
- self.add_cpu_memory_region("minimac_mem", 0xb0000000, 0x1800)
-
- # CSR
self.submodules.crg = mxcrg.MXCRG(_MXClockPads(platform), self.clk_freq)
- if platform.name == "mixxeo":
- self.submodules.leds = gpio.GPIOOut(platform.request("user_led"))
- if platform.name == "m1":
- self.submodules.buttons = gpio.GPIOIn(Cat(platform.request("user_btn", 0), platform.request("user_btn", 2)))
- self.submodules.leds = gpio.GPIOOut(Cat(platform.request("user_led", i) for i in range(2)))
-
- # Clock glue
self.comb += [
self.ddrphy.clk4x_wr_strb.eq(self.crg.clk4x_wr_strb),
self.ddrphy.clk4x_rd_strb.eq(self.crg.clk4x_rd_strb)
PIN "mxcrg/bufg_x1.O" CLOCK_DEDICATED_ROUTE = FALSE;
""")
+ platform.add_source_dir(os.path.join("verilog", "mxcrg"))
+
+class MiniSoC(BaseSoC):
+ csr_map = {
+ "minimac": 10,
+ }
+ csr_map.update(BaseSoC.csr_map)
+
+ interrupt_map = {
+ "minimac": 2,
+ }
+ interrupt_map.update(BaseSoC.interrupt_map)
+
+ def __init__(self, platform, **kwargs):
+ BaseSoC.__init__(self, platform, **kwargs)
+
+ if platform.name == "mixxeo":
+ self.submodules.leds = gpio.GPIOOut(platform.request("user_led"))
+ if platform.name == "m1":
+ self.submodules.buttons = gpio.GPIOIn(Cat(platform.request("user_btn", 0), platform.request("user_btn", 2)))
+ self.submodules.leds = gpio.GPIOOut(Cat(platform.request("user_led", i) for i in range(2)))
- # add Verilog sources
- for d in ["mxcrg", "minimac3"]:
- platform.add_source_dir(os.path.join("verilog", d))
-
-def _get_vga_dvi(platform):
+ self.submodules.minimac = minimac3.MiniMAC(platform.request("eth"))
+ self.add_wb_slave(lambda a: a[26:29] == 3, self.minimac.membus)
+ self.add_cpu_memory_region("minimac_mem", 0xb0000000, 0x1800)
+ platform.add_source_dir(os.path.join("verilog", "minimac3"))
+
+def get_vga_dvi(platform):
try:
pads_vga = platform.request("vga_out")
except ConstraintError:
""")
return pads_vga, pads_dvi
-def _add_vga_tig(platform, fb):
+def add_vga_tig(platform, fb):
platform.add_platform_command("""
NET "{vga_clk}" TNM_NET = "GRPvga_clk";
NET "sys_clk" TNM_NET = "GRPsys_clk";
""", vga_clk=fb.driver.clocking.cd_pix.clk)
class FramebufferSoC(MiniSoC):
+ csr_map = {
+ "fb": 11,
+ }
+ csr_map.update(MiniSoC.csr_map)
+
def __init__(self, platform, **kwargs):
MiniSoC.__init__(self, platform, **kwargs)
- pads_vga, pads_dvi = _get_vga_dvi(platform)
+ pads_vga, pads_dvi = get_vga_dvi(platform)
self.submodules.fb = framebuffer.Framebuffer(pads_vga, pads_dvi, self.lasmixbar.get_master())
- _add_vga_tig(platform, self.fb)
+ add_vga_tig(platform, self.fb)
-class VideomixerSoC(MiniSoC):
- def __init__(self, platform, **kwargs):
- MiniSoC.__init__(self, platform, **kwargs)
- pads_vga, pads_dvi = _get_vga_dvi(platform)
- self.submodules.fb = framebuffer.MixFramebuffer(pads_vga, pads_dvi,
- self.lasmixbar.get_master(), self.lasmixbar.get_master())
- _add_vga_tig(platform, self.fb)
- self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 2), self.lasmixbar.get_master())
- self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 3), self.lasmixbar.get_master())
-
-default_subtarget = VideomixerSoC
+default_subtarget = FramebufferSoC
--- /dev/null
+from fractions import Fraction
+
+from migen.fhdl.std import *
+
+from misoclib import lasmicon, spiflash
+from misoclib.sdramphy import gensdrphy
+from misoclib.gensoc import SDRAMSoC
+
+class _CRG(Module):
+ def __init__(self, platform, clk_freq):
+ self.clock_domains.cd_sys = ClockDomain()
+ self.clock_domains.cd_sys_ps = ClockDomain()
+
+ f0 = 32*1000*1000
+ clk32 = platform.request("clk32")
+ clk32a = Signal()
+ self.specials += Instance("IBUFG", i_I=clk32, o_O=clk32a)
+ clk32b = Signal()
+ self.specials += Instance("BUFIO2", p_DIVIDE=1,
+ p_DIVIDE_BYPASS="TRUE", p_I_INVERT="FALSE",
+ i_I=clk32a, o_DIVCLK=clk32b)
+ f = Fraction(int(clk_freq), int(f0))
+ n, m, p = f.denominator, f.numerator, 8
+ assert f0/n*m == clk_freq
+ pll_lckd = Signal()
+ pll_fb = Signal()
+ pll = Signal(6)
+ self.specials.pll = Instance("PLL_ADV", p_SIM_DEVICE="SPARTAN6",
+ p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="INTERNAL",
+ p_REF_JITTER=.01, p_CLK_FEEDBACK="CLKFBOUT",
+ i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_RST=0, i_REL=0,
+ p_DIVCLK_DIVIDE=1, p_CLKFBOUT_MULT=m*p//n, p_CLKFBOUT_PHASE=0.,
+ i_CLKIN1=clk32b, i_CLKIN2=0, i_CLKINSEL=1,
+ p_CLKIN1_PERIOD=1/f0, p_CLKIN2_PERIOD=0.,
+ i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, o_LOCKED=pll_lckd,
+ o_CLKOUT0=pll[0], p_CLKOUT0_DUTY_CYCLE=.5,
+ o_CLKOUT1=pll[1], p_CLKOUT1_DUTY_CYCLE=.5,
+ o_CLKOUT2=pll[2], p_CLKOUT2_DUTY_CYCLE=.5,
+ o_CLKOUT3=pll[3], p_CLKOUT3_DUTY_CYCLE=.5,
+ o_CLKOUT4=pll[4], p_CLKOUT4_DUTY_CYCLE=.5,
+ o_CLKOUT5=pll[5], p_CLKOUT5_DUTY_CYCLE=.5,
+ p_CLKOUT0_PHASE=0., p_CLKOUT0_DIVIDE=p//1,
+ p_CLKOUT1_PHASE=0., p_CLKOUT1_DIVIDE=p//1,
+ p_CLKOUT2_PHASE=0., p_CLKOUT2_DIVIDE=p//1,
+ p_CLKOUT3_PHASE=0., p_CLKOUT3_DIVIDE=p//1,
+ p_CLKOUT4_PHASE=0., p_CLKOUT4_DIVIDE=p//1, # sys
+ p_CLKOUT5_PHASE=270., p_CLKOUT5_DIVIDE=p//1, # sys_ps
+ )
+ self.specials += Instance("BUFG", i_I=pll[4], o_O=self.cd_sys.clk)
+ self.specials += Instance("BUFG", i_I=pll[5], o_O=self.cd_sys_ps.clk)
+ self.specials += Instance("FD", p_INIT=1, i_D=~pll_lckd,
+ i_C=self.cd_sys.clk, o_Q=self.cd_sys.rst)
+
+ self.specials += Instance("ODDR2", p_DDR_ALIGNMENT="NONE",
+ p_INIT=0, p_SRTYPE="SYNC",
+ i_D0=0, i_D1=1, i_S=0, i_R=0, i_CE=1,
+ i_C0=self.cd_sys.clk, i_C1=~self.cd_sys.clk,
+ o_Q=platform.request("sdram_clock"))
+
+class BaseSoC(SDRAMSoC):
+ default_platform = "papilio_pro"
+
+ def __init__(self, platform, **kwargs):
+ clk_freq = 80*1000*1000
+ SDRAMSoC.__init__(self, platform, clk_freq,
+ cpu_reset_address=0x160000, **kwargs)
+
+ self.submodules.crg = _CRG(platform, clk_freq)
+
+ sdram_geom = lasmicon.GeomSettings(
+ bank_a=2,
+ row_a=12,
+ col_a=8
+ )
+ sdram_timing = lasmicon.TimingSettings(
+ tRP=self.ns(15),
+ tRCD=self.ns(15),
+ tWR=self.ns(14),
+ tWTR=2,
+ tREFI=self.ns(64*1000*1000/4096, False),
+ tRFC=self.ns(66),
+ req_queue_size=8,
+ read_time=32,
+ write_time=16
+ )
+ self.submodules.sdrphy = gensdrphy.GENSDRPHY(platform.request("sdram"))
+ self.register_sdram_phy(self.sdrphy.dfi, self.sdrphy.phy_settings, sdram_geom, sdram_timing)
+
+ # BIOS is in SPI flash
+ self.submodules.spiflash = spiflash.SpiFlash(platform.request("spiflash2x"),
+ cmd=0xefef, cmd_width=16, addr_width=24, dummy=4, div=4)
+ self.flash_boot_address = 0x70000
+ self.register_rom(self.spiflash.bus)
+
+default_subtarget = BaseSoC
+++ /dev/null
-from fractions import Fraction
-
-from migen.fhdl.std import *
-
-from misoclib import lasmicon, spiflash
-from misoclib.sdramphy import gensdrphy
-from misoclib.gensoc import SDRAMSoC
-
-class _CRG(Module):
- def __init__(self, platform, clk_freq):
- self.clock_domains.cd_sys = ClockDomain()
- self.clock_domains.cd_sys_ps = ClockDomain()
-
- f0 = 32*1000*1000
- clk32 = platform.request("clk32")
- clk32a = Signal()
- self.specials += Instance("IBUFG", i_I=clk32, o_O=clk32a)
- clk32b = Signal()
- self.specials += Instance("BUFIO2", p_DIVIDE=1,
- p_DIVIDE_BYPASS="TRUE", p_I_INVERT="FALSE",
- i_I=clk32a, o_DIVCLK=clk32b)
- f = Fraction(int(clk_freq), int(f0))
- n, m, p = f.denominator, f.numerator, 8
- assert f0/n*m == clk_freq
- pll_lckd = Signal()
- pll_fb = Signal()
- pll = Signal(6)
- self.specials.pll = Instance("PLL_ADV", p_SIM_DEVICE="SPARTAN6",
- p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="INTERNAL",
- p_REF_JITTER=.01, p_CLK_FEEDBACK="CLKFBOUT",
- i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_RST=0, i_REL=0,
- p_DIVCLK_DIVIDE=1, p_CLKFBOUT_MULT=m*p//n, p_CLKFBOUT_PHASE=0.,
- i_CLKIN1=clk32b, i_CLKIN2=0, i_CLKINSEL=1,
- p_CLKIN1_PERIOD=1/f0, p_CLKIN2_PERIOD=0.,
- i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, o_LOCKED=pll_lckd,
- o_CLKOUT0=pll[0], p_CLKOUT0_DUTY_CYCLE=.5,
- o_CLKOUT1=pll[1], p_CLKOUT1_DUTY_CYCLE=.5,
- o_CLKOUT2=pll[2], p_CLKOUT2_DUTY_CYCLE=.5,
- o_CLKOUT3=pll[3], p_CLKOUT3_DUTY_CYCLE=.5,
- o_CLKOUT4=pll[4], p_CLKOUT4_DUTY_CYCLE=.5,
- o_CLKOUT5=pll[5], p_CLKOUT5_DUTY_CYCLE=.5,
- p_CLKOUT0_PHASE=0., p_CLKOUT0_DIVIDE=p//1,
- p_CLKOUT1_PHASE=0., p_CLKOUT1_DIVIDE=p//1,
- p_CLKOUT2_PHASE=0., p_CLKOUT2_DIVIDE=p//1,
- p_CLKOUT3_PHASE=0., p_CLKOUT3_DIVIDE=p//1,
- p_CLKOUT4_PHASE=0., p_CLKOUT4_DIVIDE=p//1, # sys
- p_CLKOUT5_PHASE=270., p_CLKOUT5_DIVIDE=p//1, # sys_ps
- )
- self.specials += Instance("BUFG", i_I=pll[4], o_O=self.cd_sys.clk)
- self.specials += Instance("BUFG", i_I=pll[5], o_O=self.cd_sys_ps.clk)
- self.specials += Instance("FD", p_INIT=1, i_D=~pll_lckd,
- i_C=self.cd_sys.clk, o_Q=self.cd_sys.rst)
-
- self.specials += Instance("ODDR2", p_DDR_ALIGNMENT="NONE",
- p_INIT=0, p_SRTYPE="SYNC",
- i_D0=0, i_D1=1, i_S=0, i_R=0, i_CE=1,
- i_C0=self.cd_sys.clk, i_C1=~self.cd_sys.clk,
- o_Q=platform.request("sdram_clock"))
-
-class SimpleSoC(SDRAMSoC):
- default_platform = "papilio_pro"
-
- def __init__(self, platform, **kwargs):
- clk_freq = 80*1000*1000
- SDRAMSoC.__init__(self, platform, clk_freq,
- cpu_reset_address=0x160000, **kwargs)
-
- self.submodules.crg = _CRG(platform, clk_freq)
-
- sdram_geom = lasmicon.GeomSettings(
- bank_a=2,
- row_a=12,
- col_a=8
- )
- sdram_timing = lasmicon.TimingSettings(
- tRP=self.ns(15),
- tRCD=self.ns(15),
- tWR=self.ns(14),
- tWTR=2,
- tREFI=self.ns(64*1000*1000/4096, False),
- tRFC=self.ns(66),
- req_queue_size=8,
- read_time=32,
- write_time=16
- )
- self.submodules.sdrphy = gensdrphy.GENSDRPHY(platform.request("sdram"))
- self.register_sdram_phy(self.sdrphy.dfi, self.sdrphy.phy_settings, sdram_geom, sdram_timing)
-
- # BIOS is in SPI flash
- self.submodules.spiflash = spiflash.SpiFlash(platform.request("spiflash2x"),
- cmd=0xefef, cmd_width=16, addr_width=24, dummy=4, div=4)
- self.flash_boot_address = 0x70000
- self.register_rom(self.spiflash.bus)
-
-default_subtarget = SimpleSoC