def __init__(self, polynom=0x07): self.submodules.crc = LiteEthMACCRCEngine(data_width=8, width=8, polynom=polynom) self.din = Signal(8) self.comb += self.crc.data.eq(self.din[::-1]) self.sync += self.crc.last.eq(self.crc.next)
def __init__(self, n_data, t_clk, n_frame): n_word = n_data*t_clk n_marker = n_frame//2 + 1 n_crc = n_data self.data = Signal(n_data) self.data_stb = Signal() self.end_of_frame = Signal() self.frame = Signal(n_word*n_frame - n_marker - n_crc) self.frame_stb = Signal() self.crc_err = Signal(8) # response bitstream self.miso = Signal(reset_less=True) # response data, latched on end_of_frame self.response = Signal(n_frame*t_clk, reset_less=True) poly = { # 6: 0x27, # CRC-6-CDMA2000-A 6: 0x2f, # CRC-6-GSM }[n_data] self.submodules.crc = LiteEthMACCRCEngine( data_width=n_data, width=n_data, polynom=poly) self.crc.last.reset_less = True crc_good = Signal() crc = Signal.like(self.crc.last, reset_less=True) self.comb += [ crc_good.eq(self.crc.next == 0), # crc_good.eq(1), # TODO # LiteEthMACCRCEngine takes LSB first self.crc.data.eq(self.data[::-1]), ] self.sync += [ self.crc.last.eq(self.crc.next), If(self.end_of_frame | ~self.data_stb, self.crc.last.eq(0), If(~crc_good, self.crc_err.eq(self.crc_err + 1), ), ), ] frame_buf = Signal(n_word*n_frame, reset_less=True) self.sync += [ frame_buf.eq(Cat(self.data, frame_buf)), self.frame_stb.eq(self.end_of_frame & crc_good & self.data_stb), ] frame_parts = [] for i in range(n_frame): if i == 0: offset = n_crc elif i < n_marker + 1: offset = 1 else: offset = 0 frame_parts.append(frame_buf[i*n_word + offset: (i + 1)*n_word]) assert len(Cat(frame_parts)) == len(self.frame) self.comb += self.frame.eq(Cat(frame_parts)) response_sr = Signal.like(self.response) self.comb += self.miso.eq(response_sr[-1]) self.sync += [ response_sr[1:].eq(response_sr), If(self.frame_stb, response_sr.eq(self.response), ) ]
def __init__(self, mems): self.sink = Endpoint(bus_layout) self.source = Endpoint(bus_layout) self.board = Signal(4) # mapped registers self.config = Record([ ("reset", 1), ("clk2x", 1), ("enable", 1), ("trigger", 1), ("aux_miso", 1), ("aux_dac", 3), ]) self.checksum = Signal(8) self.frame = Signal(max=32) ### # CRC8-CCIT crc = LiteEthMACCRCEngine(data_width=8, width=8, polynom=0x07) self.submodules += crc self.comb += [ crc.data.eq(self.sink.data[::-1]), crc.last.eq(self.checksum), ] self.sync += [ If( self.sink.stb & ~self.sink.eop & ~self.source.stb, self.checksum.eq(crc.next), ), ] cmd_layout = [ ("adr", 2), # reg or mem ("is_mem", 1), # is_mem/is_reg_n ("board", 4), # 0xf: broadcast ("we", 1), # write/read_n ] cmd_cur = Record(cmd_layout) self.comb += cmd_cur.raw_bits().eq(self.sink.data) cmd = Record(cmd_layout) reg_map = Array([self.config.raw_bits(), self.checksum, self.frame]) reg_we = Signal() self.sync += [If( reg_we, reg_map[cmd.adr].eq(self.sink.data), )] mems = [ mem.get_port(write_capable=True, we_granularity=8) for mem in mems ] self.specials += mems mem_adr = Signal(16) mem_we = Signal() mem_dat_r = Signal(16) self.comb += [ self.sink.ack.eq(1), [[ mem.adr.eq(mem_adr[1:]), mem.dat_w.eq(Replicate(self.sink.data, 2)), ] for mem in mems], If( mem_we, Array([mem.we for mem in mems ])[cmd.adr].eq(Mux(mem_adr[0], 0b10, 0b01)), ), mem_dat_r.eq(Array([mem.dat_r for mem in mems])[cmd.adr]), ] fsm = ResetInserter()(CEInserter()(FSM(reset_state="CMD"))) self.submodules += fsm self.comb += [ fsm.reset.eq(self.sink.eop), fsm.ce.eq(self.sink.stb), ] fsm.act( "CMD", If( (cmd_cur.board == self.board) | (cmd_cur.board == 0xf), If( cmd_cur.is_mem, NextState("MEM_ADRL"), ).Else(NextState("REG_DO"), ), ).Else(NextState("IGNORE"), ), ) fsm.act("IGNORE", NextState("IGNORE")) fsm.act( "REG_DO", self.source.stb.eq(self.sink.stb & ~cmd.we), reg_we.eq(self.sink.stb & cmd.we), self.source.data.eq(reg_map[cmd.adr]), NextState("IGNORE"), ) fsm.act( "MEM_ADRL", NextState("MEM_ADRH"), ) fsm.act( "MEM_ADRH", NextState("MEM_DO"), ) fsm.act( "MEM_DO", mem_we.eq(self.sink.stb & cmd.we), self.source.stb.eq(self.sink.stb & ~cmd.we), self.source.data.eq(Mux(mem_adr[0], mem_dat_r[8:], mem_dat_r[:8])), ) self.sync += [ If( fsm.before_leaving("CMD"), cmd.raw_bits().eq(self.sink.data), ), If( fsm.before_leaving("MEM_ADRL"), mem_adr[:8].eq(self.sink.data), ), If( fsm.before_leaving("MEM_ADRH"), mem_adr[8:].eq(self.sink.data), ), If( fsm.ongoing("MEM_DO") & self.sink.stb, mem_adr.eq(mem_adr + 1), ), ]
def __init__(self, n_data=8, t_clk=7, d_clk=0b1100011, n_frame=14, n_crc=12, poly=0x80f): """DDR fast link. * One word clock lane with `t_clk` period. * Multiple data lanes at DDR speed. * One return data lane at slower speed. * n_frame//2 - 1 marker bits are used to provide framing. * `n_data` lanes * `t_clk` bits per clk cycle with pattern `d_clk` * `n_frame` words per frame * `n_crc` CRC bits per frame for divisor poly `poly` """ # pins self.data = [Signal(2, reset_less=True) for _ in range(n_data)] n_mosi = n_data - 2 # mosi lanes n_word = n_mosi*t_clk # bits per word t_frame = t_clk*n_frame # frame duration n_marker = n_frame//2 + 1 n_body = n_word*n_frame - n_marker - n_crc t_miso = 0 # miso sampling latency TODO assert n_crc % n_mosi == 0 # frame data self.payload = Signal(n_body) # readback data self.readback = Signal(n_frame, reset_less=True) # data load synchronization event self.stb = Signal() # # # self.submodules.crca = LiteEthMACCRCEngine( data_width=n_mosi, width=n_crc, polynom=poly) self.submodules.crcb = LiteEthMACCRCEngine( data_width=n_mosi, width=n_crc, polynom=poly) words_ = [] j = 0 # build from LSB to MSB because MSB first for i in range(n_frame): # iterate over words if i == 0: # data and checksum words_.append(C(0, n_crc)) k = n_word - n_crc elif i == 1: # marker words_.append(C(1)) k = n_word - 1 elif i < n_frame//2 + 2: # marker words_.append(C(0)) k = n_word - 1 else: # full word k = n_word # append corresponding frame body bits words_.append(self.payload[j:j + k]) j += k words_ = Cat(words_) assert len(words_) == n_frame*n_word words = Signal(len(words_)) self.comb += words.eq(words_) clk = Signal(t_clk, reset=d_clk) i = Signal(max=t_frame//2) # big shift register for mosi and sr = [Signal(t_frame, reset_less=True) for i in range(n_mosi)] assert len(Cat(sr)) == len(words) crc_insert = Cat(([d[0] for d in self.data[1:-1]] + [d[1] for d in self.data[1:-1]])[:n_crc]) miso_sr = Signal(t_frame, reset_less=True) miso_sr_next = Signal.like(miso_sr) self.comb += [ self.stb.eq(i == t_frame//2 - 1), # LiteETHMACCRCEngine takes data LSB first self.crca.data.eq(Cat([sri[-1] for sri in sr[::-1]])), self.crcb.data.eq(Cat([sri[-2] for sri in sr[::-1]])), self.crcb.last.eq(self.crca.next), miso_sr_next.eq(Cat(self.data[-1], miso_sr)), # unload miso # TODO: align to marker self.readback.eq(Cat([miso_sr_next[t_miso + i*t_clk] for i in range(n_frame)])), ] self.sync.rio_phy += [ # shift everything by two bits [di.eq(sri[-2:]) for di, sri in zip(self.data, [clk] + sr)], clk.eq(Cat(clk[-2:], clk)), [sri.eq(Cat(C(0, 2), sri)) for sri in sr], miso_sr.eq(miso_sr_next), self.crca.last.eq(self.crcb.next), i.eq(i + 1), If(self.stb, i.eq(0), clk.eq(clk.reset), self.crca.last.eq(0), # transpose, load [sri.eq(Cat(words[i::n_mosi])) for i, sri in enumerate(sr)], # inject crc for the last cycle crc_insert.eq(self.crca.next if n_crc // n_mosi <= 1 else self.crca.last), ), ]
def __init__(self, n_frame=14): n = 7 * 6 # input word from link self.word = Signal(n) checksum = Signal(12, reset_less=True) self.submodules.crc = LiteEthMACCRCEngine( data_width=n, width=len(checksum), polynom=0x80f) # crc-12 telco # frame body self.body = Signal(n_frame * n - n_frame // 2 - 1 - len(checksum)) self.stb = Signal() self.crc_err = Signal(8) # frame: n_frame = 14 # 0: body(n_word) # ... # n_frame//2 - 4: body(n_word) # ... # n_frame//2 - 3: marker(1), body(n_word - 1) # ... # n_frame - 2: marker(1), body(n_word - 1) # n_frame - 1: crc(n_crc = 12), body(n_word - 12) # n_body = n_frame*n_word - n_frame//2 - 1 - n_crc eof = Signal() frame = Signal(n * n_frame, reset_less=True) crc_good = Signal() body_ = Cat( # checksum in the most recent word frame[len(checksum):n], # skip eof marker bits in the next n_frame//2 + 1 words [frame[1 + i * n:(i + 1) * n] for i in range(1, 2 + n_frame // 2)], # complete words frame[(2 + n_frame // 2) * n:], ) assert len(body_) == len(self.body) self.comb += [ self.crc.last.eq(checksum), # LiteEthMACCRCEngine takes LSB first self.crc.data[::-1].eq(self.word), self.body.eq(body_), # CRC([x, CRC(x)]) == 0 crc_good.eq(self.crc.next == 0), ] self.sync += [ eof.eq( Cat(self.word[0], [frame[i * n] for i in range(n_frame // 2)]) == 1), self.stb.eq(eof & crc_good), frame.eq(Cat(self.word, frame)), checksum.eq(self.crc.next), If( eof, checksum.eq(0), If( ~crc_good, self.crc_err.eq(self.crc_err + 1), ), ), ]
def __init__(self, pins, pins_n): n_bits = 16 # bits per dac data word n_channels = 32 # channels per fastino n_div = 7 # bits per lane and word assert n_div == 7 n_frame = 14 # word per frame n_lanes = len(pins.mosi) # number of data lanes n_checksum = 12 # checksum bits n_addr = 4 # readback address bits n_word = n_lanes*n_div n_body = n_word*n_frame - (n_frame//2 + 1) - n_checksum # dac data words self.dacs = [Signal(n_bits) for i in range(n_channels)] # dac update enable self.enable = Signal(n_channels) # configuration word self.cfg = Signal(20) # readback data self.dat_r = Signal(n_frame//2*(1 << n_addr)) # data load synchronization event self.stb = Signal() # # # # crc-12 telco self.submodules.crc = LiteEthMACCRCEngine( data_width=2*n_lanes, width=n_checksum, polynom=0x80f) addr = Signal(4) body_ = Cat(self.cfg, addr, self.enable, self.dacs) assert len(body_) == n_body body = Signal(n_body) self.comb += body.eq(body_) words_ = [] j = 0 for i in range(n_frame): # iterate over words if i == 0: # data and checksum k = n_word - n_checksum elif i == 1: # marker words_.append(C(1)) k = n_word - 1 elif i < n_frame//2 + 2: # marker words_.append(C(0)) k = n_word - 1 else: # full word k = n_word # append corresponding frame body bits words_.append(body[j:j + k]) j += k words_ = Cat(words_) assert len(words_) == n_frame*n_word - n_checksum words = Signal(len(words_)) self.comb += words.eq(words_) clk = Signal(n_div, reset=0b1100011) clk_stb = Signal() i_frame = Signal(max=n_div*n_frame//2) # DDR frame_stb = Signal() sr = [Signal(n_frame*n_div - n_checksum//n_lanes, reset_less=True) for i in range(n_lanes)] assert len(Cat(sr)) == len(words) # DDR bits for each register ddr_data = Cat([sri[-2] for sri in sr], [sri[-1] for sri in sr]) self.comb += [ # assert one cycle ahead clk_stb.eq(~clk[0] & clk[-1]), # double period because of DDR frame_stb.eq(i_frame == n_div*n_frame//2 - 1), # LiteETHMACCRCEngine takes data LSB first self.crc.data[::-1].eq(ddr_data), self.stb.eq(frame_stb & clk_stb), ] miso = Signal() miso_sr = Signal(n_frame, reset_less=True) self.sync.rio_phy += [ # shift 7 bit clock pattern by two bits each DDR cycle clk.eq(Cat(clk[-2:], clk)), [sri[2:].eq(sri) for sri in sr], self.crc.last.eq(self.crc.next), If(clk[:2] == 0, # TODO: tweak MISO sampling miso_sr.eq(Cat(miso, miso_sr)), ), If(~frame_stb, i_frame.eq(i_frame + 1), ), If(frame_stb & clk_stb, i_frame.eq(0), self.crc.last.eq(0), # transpose, load Cat(sr).eq(Cat(words[mm::n_lanes] for mm in range(n_lanes))), Array([self.dat_r[i*n_frame//2:(i + 1)*n_frame//2] for i in range(1 << len(addr))])[addr].eq(miso_sr), addr.eq(addr + 1), ), If(i_frame == n_div*n_frame//2 - 2, # inject crc ddr_data.eq(self.crc.next), ), ] clk_ddr = Signal() miso0 = Signal() self.specials += [ DDROutput(clk[-1], clk[-2], clk_ddr, ClockSignal("rio_phy")), DifferentialOutput(clk_ddr, pins.clk, pins_n.clk), DifferentialInput(pins.miso, pins_n.miso, miso0), MultiReg(miso0, miso, "rio_phy"), ] for sri, ddr, mp, mn in zip( sr, Signal(n_lanes), pins.mosi, pins_n.mosi): self.specials += [ DDROutput(sri[-1], sri[-2], ddr, ClockSignal("rio_phy")), DifferentialOutput(ddr, mp, mn), ]