From: Sebastien Bourdeauducq Date: Sun, 3 Aug 2014 04:30:15 +0000 (+0800) Subject: Keep only basic SoC designs in MiSoC X-Git-Tag: 24jan2021_ls180~2691 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=213cb43ae54175e8cdd0848435a6d88863861789;p=litex.git Keep only basic SoC designs in MiSoC --- diff --git a/.gitignore b/.gitignore index 0ce6c634..36ca43f7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,12 +7,7 @@ build/* *.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 diff --git a/misoclib/counteradc/__init__.py b/misoclib/counteradc/__init__.py deleted file mode 100644 index 9df83c35..00000000 --- a/misoclib/counteradc/__init__.py +++ /dev/null @@ -1,61 +0,0 @@ -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) - ) - ) diff --git a/misoclib/dvisampler/__init__.py b/misoclib/dvisampler/__init__.py deleted file mode 100644 index 612e9141..00000000 --- a/misoclib/dvisampler/__init__.py +++ /dev/null @@ -1,79 +0,0 @@ -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"} diff --git a/misoclib/dvisampler/analysis.py b/misoclib/dvisampler/analysis.py deleted file mode 100644 index 05d26880..00000000 --- a/misoclib/dvisampler/analysis.py +++ /dev/null @@ -1,205 +0,0 @@ -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) - ) diff --git a/misoclib/dvisampler/chansync.py b/misoclib/dvisampler/chansync.py deleted file mode 100644 index c8475608..00000000 --- a/misoclib/dvisampler/chansync.py +++ /dev/null @@ -1,129 +0,0 @@ -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) diff --git a/misoclib/dvisampler/charsync.py b/misoclib/dvisampler/charsync.py deleted file mode 100644 index 99ea9aaa..00000000 --- a/misoclib/dvisampler/charsync.py +++ /dev/null @@ -1,53 +0,0 @@ -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) diff --git a/misoclib/dvisampler/clocking.py b/misoclib/dvisampler/clocking.py deleted file mode 100644 index 4f2babdf..00000000 --- a/misoclib/dvisampler/clocking.py +++ /dev/null @@ -1,79 +0,0 @@ -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) diff --git a/misoclib/dvisampler/common.py b/misoclib/dvisampler/common.py deleted file mode 100644 index 7fb9a420..00000000 --- a/misoclib/dvisampler/common.py +++ /dev/null @@ -1,2 +0,0 @@ -control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011] -channel_layout = [("d", 8), ("c", 2), ("de", 1)] diff --git a/misoclib/dvisampler/datacapture.py b/misoclib/dvisampler/datacapture.py deleted file mode 100644 index d7888433..00000000 --- a/misoclib/dvisampler/datacapture.py +++ /dev/null @@ -1,186 +0,0 @@ -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) diff --git a/misoclib/dvisampler/debug.py b/misoclib/dvisampler/debug.py deleted file mode 100644 index 555d3eea..00000000 --- a/misoclib/dvisampler/debug.py +++ /dev/null @@ -1,46 +0,0 @@ -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) - ] diff --git a/misoclib/dvisampler/decoding.py b/misoclib/dvisampler/decoding.py deleted file mode 100644 index 73a6718a..00000000 --- a/misoclib/dvisampler/decoding.py +++ /dev/null @@ -1,24 +0,0 @@ -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) diff --git a/misoclib/dvisampler/dma.py b/misoclib/dvisampler/dma.py deleted file mode 100644 index 114a5397..00000000 --- a/misoclib/dvisampler/dma.py +++ /dev/null @@ -1,140 +0,0 @@ -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() diff --git a/misoclib/dvisampler/edid.py b/misoclib/dvisampler/edid.py deleted file mode 100644 index b4afb4eb..00000000 --- a/misoclib/dvisampler/edid.py +++ /dev/null @@ -1,189 +0,0 @@ -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"))) diff --git a/misoclib/dvisampler/wer.py b/misoclib/dvisampler/wer.py deleted file mode 100644 index 6be35abf..00000000 --- a/misoclib/dvisampler/wer.py +++ /dev/null @@ -1,59 +0,0 @@ -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)) diff --git a/misoclib/framebuffer/__init__.py b/misoclib/framebuffer/__init__.py index 7b8015f1..a3e17ab9 100644 --- a/misoclib/framebuffer/__init__.py +++ b/misoclib/framebuffer/__init__.py @@ -1,15 +1,14 @@ 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() @@ -30,77 +29,3 @@ class Framebuffer(Module, AutoCSR): 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) diff --git a/misoclib/videostream/downscaler.py b/misoclib/videostream/downscaler.py deleted file mode 100644 index 7744f2d6..00000000 --- a/misoclib/videostream/downscaler.py +++ /dev/null @@ -1,386 +0,0 @@ -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()) diff --git a/misoclib/videostream/testpic_in.jpg b/misoclib/videostream/testpic_in.jpg deleted file mode 100644 index 49e65a8c..00000000 Binary files a/misoclib/videostream/testpic_in.jpg and /dev/null differ diff --git a/software/videomixer/Makefile b/software/videomixer/Makefile deleted file mode 100644 index 86be97fe..00000000 --- a/software/videomixer/Makefile +++ /dev/null @@ -1,80 +0,0 @@ -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 diff --git a/software/videomixer/ci.c b/software/videomixer/ci.c deleted file mode 100644 index 2f91e380..00000000 --- a/software/videomixer/ci.c +++ /dev/null @@ -1,83 +0,0 @@ -#include - -#include -#include - -#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= '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; - } - } -} diff --git a/software/videomixer/ci.h b/software/videomixer/ci.h deleted file mode 100644 index 63400feb..00000000 --- a/software/videomixer/ci.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __CI_H -#define __CI_H - -void ci_service(void); - -#endif \ No newline at end of file diff --git a/software/videomixer/config.c b/software/videomixer/config.c deleted file mode 100644 index b1292efa..00000000 --- a/software/videomixer/config.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include - -#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> 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 -#include -#include - -#include -#include -#include -#include -#include -#include - -#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(); -} diff --git a/software/videomixer/dvisamplerX.h b/software/videomixer/dvisamplerX.h deleted file mode 100644 index 13422dce..00000000 --- a/software/videomixer/dvisamplerX.h +++ /dev/null @@ -1,17 +0,0 @@ -#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 diff --git a/software/videomixer/edid.c b/software/videomixer/edid.c deleted file mode 100644 index 10f9931e..00000000 --- a/software/videomixer/edid.c +++ /dev/null @@ -1,248 +0,0 @@ -#include -#include - -#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); -} diff --git a/software/videomixer/edid.h b/software/videomixer/edid.h deleted file mode 100644 index 975d9c0a..00000000 --- a/software/videomixer/edid.h +++ /dev/null @@ -1,29 +0,0 @@ -#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 diff --git a/software/videomixer/isr.c b/software/videomixer/isr.c deleted file mode 100644 index db878a39..00000000 --- a/software/videomixer/isr.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include - -#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(); -} diff --git a/software/videomixer/main.c b/software/videomixer/main.c deleted file mode 100644 index 375a1a00..00000000 --- a/software/videomixer/main.c +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/software/videomixer/pll.c b/software/videomixer/pll.c deleted file mode 100644 index 843a0276..00000000 --- a/software/videomixer/pll.c +++ /dev/null @@ -1,107 +0,0 @@ -#include -#include - -#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"); -} diff --git a/software/videomixer/pll.h b/software/videomixer/pll.h deleted file mode 100644 index 3c4a626b..00000000 --- a/software/videomixer/pll.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __PLL_H -#define __PLL_H - -void pll_config_for_clock(int freq); -void pll_dump(void); - -#endif diff --git a/software/videomixer/processor.c b/software/videomixer/processor.c deleted file mode 100644 index 07e73a38..00000000 --- a/software/videomixer/processor.c +++ /dev/null @@ -1,283 +0,0 @@ -#include -#include - -#include -#include - -#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;ipixel_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;ipixel_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(); -} diff --git a/software/videomixer/processor.h b/software/videomixer/processor.h deleted file mode 100644 index cd121b19..00000000 --- a/software/videomixer/processor.h +++ /dev/null @@ -1,11 +0,0 @@ -#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 */ diff --git a/targets/mlabs_video.py b/targets/mlabs_video.py index 1b7a1806..79ad4ae3 100644 --- a/targets/mlabs_video.py +++ b/targets/mlabs_video.py @@ -4,7 +4,7 @@ from fractions import Fraction 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 @@ -25,26 +25,9 @@ class _MXClockPads: 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, @@ -72,25 +55,12 @@ class MiniSoC(SDRAMSoC): 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) @@ -101,12 +71,34 @@ INST "mxcrg/rd_bufpll" LOC = "BUFPLL_X0Y3"; 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: @@ -121,7 +113,7 @@ PIN "dviout_pix_bufg.O" CLOCK_DEDICATED_ROUTE = FALSE; """) 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"; @@ -130,20 +122,15 @@ TIMESPEC "TSise_sucks2" = FROM "GRPsys_clk" TO "GRPvga_clk" TIG; """, 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 diff --git a/targets/ppro.py b/targets/ppro.py new file mode 100644 index 00000000..5416316c --- /dev/null +++ b/targets/ppro.py @@ -0,0 +1,95 @@ +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 diff --git a/targets/simple.py b/targets/simple.py deleted file mode 100644 index 2f4d3734..00000000 --- a/targets/simple.py +++ /dev/null @@ -1,95 +0,0 @@ -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