class ClockDebug(Elaboratable): def __init__(self, domain_name, reset_less=False): self.domain_name = domain_name self.reset_less = reset_less self.counter = StatusSignal(32) if not self.reset_less: self.is_reset = StatusSignal() def elaborate(self, platform): m = Module() m.d[self.domain_name] += self.counter.eq(self.counter + 1) if not self.reset_less: m.d.comb += self.is_reset.eq(ResetSignal(self.domain_name)) return m @driver_property def mhz(self): from time import sleep, time initial_counter = self.counter start = time() sleep(0.1) counter_difference = (self.counter - initial_counter) return counter_difference * (1 / (time() - start)) / 1e6
class StreamFIFO(Elaboratable): def __init__(self, input: Stream, fifo_type, output_stream_name="fifo_out", **fifo_args): self.input = input self.output = input.clone(name=output_stream_name) if "r_domain" in fifo_args: self.output_domain = fifo_args["r_domain"] self.fifo = fifo_type(width=len(Cat(self.input.payload_signals.values())), **fifo_args) self.depth = fifo_args['depth'] self.r_level = StatusSignal(range(self.fifo.depth + 1)) self.w_level = StatusSignal(range(self.fifo.depth + 1)) def elaborate(self, platform): m = Module() fifo = m.submodules.fifo = self.fifo if self.depth == 0: m.d.comb += self.output.connect_upstream(self.input) else: m.d.comb += self.r_level.eq(fifo.r_level) m.d.comb += self.w_level.eq(fifo.w_level) m.d.comb += self.input.ready.eq(fifo.w_rdy) m.d.comb += fifo.w_data.eq(Cat(self.input.payload_signals.values())) m.d.comb += fifo.w_en.eq(self.input.valid) m.d.comb += Cat(self.output.payload_signals.values()).eq(fifo.r_data) m.d.comb += self.output.valid.eq(fifo.r_rdy) m.d.comb += fifo.r_en.eq(self.output.ready) return m
def __init__(self, domain_name, reset_less=False): self.domain_name = domain_name self.reset_less = reset_less self.counter = StatusSignal(32) if not self.reset_less: self.is_reset = StatusSignal()
def __init__(self, plugin, domain_name="sync"): self.plugin = plugin self.output = BasicStream(32) self.domain_name = domain_name self.trained = ControlSignal() self.valid = StatusSignal()
def __init__(self, lp_pins: TristateIo, hs_pins: TristateDdrIo, ck_domain): self.lp_pins = lp_pins self.hs_pins = hs_pins self.ck_domain = ck_domain self.request_hs = Signal() self.is_hs = StatusSignal()
class Tracer(Elaboratable): def __init__(self, fsm: FSM, trace_length=128): self.fsm = fsm self.trace_length = trace_length self.write_ptr = StatusSignal(range(trace_length)) self.trace_decoder = {} def elaborate(self, platform): m = Module() mem = m.submodules.mem = SocMemory(width=len(self.fsm.state), depth=self.trace_length, soc_write=False) write_port = m.submodules.write_port = mem.write_port(domain="sync") with m.If(Changed(m, self.fsm.state)): m.d.comb += write_port.en.eq(1) m.d.comb += write_port.data.eq(self.fsm.state) m.d.comb += write_port.addr.eq(self.write_ptr) with m.If(self.write_ptr < self.trace_length): m.d.sync += self.write_ptr.eq(self.write_ptr + 1) with m.Else(): m.d.sync += self.write_ptr.eq(0) self.trace_decoder.update(self.fsm.decoding) return m @driver_method def print_trace(self): r = list(range(self.trace_length)) for i in r[self.write_ptr:] + r[:self.write_ptr]: print(self.trace_decoder[self.mem[i]])
def __init__(self, input: Stream, fifo_type, output_stream_name="fifo_out", **fifo_args): self.input = input self.output = input.clone(name=output_stream_name) if "r_domain" in fifo_args: self.output_domain = fifo_args["r_domain"] self.fifo = fifo_type(width=len(Cat(self.input.payload_signals.values())), **fifo_args) self.depth = fifo_args['depth'] self.r_level = StatusSignal(range(self.fifo.depth + 1)) self.w_level = StatusSignal(range(self.fifo.depth + 1))
def __init__(self, input: ImageStream, desired_width, desired_height): self.input = input self.output = input.clone(name="resized") self.output_width = ControlSignal(16, reset=desired_width) self.output_height = ControlSignal(16, reset=desired_height) self.shift_x = ControlSignal(signed(16)) self.shift_y = ControlSignal(signed(16)) self.input_width = StatusSignal(16) self.input_height = StatusSignal(16)
class Ft60xLegalizer(Elaboratable): def __init__(self, input: PacketizedStream, packet_len): self.input = input self.output = BasicStream(input.payload.shape()) # we calculate everything in bytes to make it easier to reason about buffer_size = 2048 * 4 blanking = buffer_size aligned_len = ceil((packet_len + blanking) / buffer_size) * buffer_size print("ft60x paddnig:", (aligned_len - packet_len), (aligned_len - packet_len) // 4) self.padding = ControlSignal(16, reset=(aligned_len - packet_len) // 4) self.frame_len = StatusSignal(32) self.frame_len_changed = StatusSignal(32) def elaborate(self, platform): m = Module() padding_ctr = Signal.like(self.padding) frame_len_ctr = Signal.like(self.frame_len) input_transaction = self.input.ready & self.input.valid with m.FSM(): with m.State("ACTIVE"): m.d.comb += self.input.ready.eq(self.output.ready) m.d.comb += self.output.valid.eq(self.input.valid) with m.If( self.input.payload == 0 ): # we disallow the transfer of 0 to ease the alignment detection TODO: this only really works for 8 bit this way m.d.comb += self.output.payload.eq(1) with m.Else(): m.d.comb += self.output.payload.eq(self.input.payload) with m.If(input_transaction): m.d.sync += frame_len_ctr.eq(frame_len_ctr + 1) with m.If(self.input.last & input_transaction): m.next = "PADDING" m.d.sync += padding_ctr.eq(0) with m.State("PADDING"): m.d.comb += self.output.valid.eq(1) m.d.comb += self.input.ready.eq(0) m.d.comb += self.output.payload.eq(0) with m.If(self.output.ready): with m.If(padding_ctr < self.padding - 1): m.d.sync += padding_ctr.eq(padding_ctr + 1) m.d.sync += frame_len_ctr.eq(frame_len_ctr + 1) with m.Else(): m.next = "ACTIVE" m.d.sync += self.frame_len.eq(frame_len_ctr + 1) with m.If(self.frame_len != frame_len_ctr + 1): m.d.sync += self.frame_len_changed.eq( self.frame_len_changed + 1) m.d.sync += frame_len_ctr.eq(0) return m
def fsm_status_reg(platform, m, fsm: FSM): if isinstance(platform, SocPlatform): fsm_state = StatusSignal( name=f"{fsm.state.name}_reg" ) # TODO: use meaningful shape value here (needs deferring) def signal_fixup_hook(platform, top_fragment: Fragment, sames): fsm_state.width = fsm.state.width fsm_state.decoder = fsm.state.decoder platform.prepare_hooks.insert(0, signal_fixup_hook) m.d.comb += fsm_state.eq(fsm.state)
def __init__(self, input: ImageStream, chunk_width, n_chunks, height): self.chunk_width = chunk_width self.height = height self.n_chunks = n_chunks self.input = input self.x_ctr = StatusSignal(16) self.y_ctr = StatusSignal(16) self.outputs = [ self.input.clone(f'splitter_output_{i}') for i in range(n_chunks) ]
def __init__(self, input: PacketizedStream, max_packet_size=1024): self.max_packet_size = max_packet_size self.reset = ControlSignal() self.write_pointer = StatusSignal(range(self.max_packet_size)) self.packet_done = StatusSignal() self.memory = SocMemory( width=len(input.payload), depth=self.max_packet_size, soc_write=False, attrs=dict(syn_ramstyle="block_ram") ) self.input = input
class ConsolePacketSource(Elaboratable): def __init__(self, data_width=8, max_packet_size=1024): self.max_packet_size = max_packet_size self.reset = ControlSignal() self.packet_length = ControlSignal(range(max_packet_size)) self.read_ptr = StatusSignal(range(max_packet_size)) self.done = StatusSignal(reset=1) self.memory = SocMemory( width=data_width, depth=self.max_packet_size, soc_read=False, attrs=dict(syn_ramstyle="block_ram") ) self.output = PacketizedStream(data_width) def elaborate(self, platform): m = Module() memory = m.submodules.memory = self.memory address_stream = PacketizedStream(bits_for(self.max_packet_size)) with m.If(~self.done): m.d.comb += address_stream.valid.eq(1) m.d.comb += address_stream.last.eq(self.read_ptr == self.packet_length) m.d.comb += address_stream.payload.eq(self.read_ptr) with m.If(address_stream.ready): m.d.sync += self.read_ptr.eq(self.read_ptr + 1) m.d.sync += self.done.eq(self.read_ptr == self.packet_length) reset = Signal() m.submodules += FFSynchronizer(self.reset, reset) with m.If(Changed(m, reset)): m.d.sync += self.read_ptr.eq(0) m.d.sync += self.done.eq(0) reader = m.submodules.reader = StreamMemoryReader(address_stream, memory) buffer = m.submodules.buffer = StreamBuffer(reader.output) m.d.comb += self.output.connect_upstream(buffer.output) return m @driver_method def write_packet(self, packet, timeout=0): from time import sleep for i in range(int(timeout * 10)): if self.done: break sleep(0.1) assert self.done for i, word in enumerate(packet): self.memory[i] = word self.packet_length = len(packet) - 1 self.reset = not self.reset
class AxiWriter(Elaboratable): def __init__(self, address_source: BasicStream, data_source: BasicStream, axi=None): self.address_source = address_source self.data_source = data_source self.axi = axi self.axi_address_ready = StatusSignal() self.axi_data_ready = StatusSignal() self.write_response_ok = StatusSignal(32) self.write_response_err = StatusSignal(32) def elaborate(self, platform): m = Module() burster = m.submodules.burster = AxiWriterBurster( self.address_source, self.data_source) axi = if_none_get_zynq_hp_port(self.axi, m, platform) for fifo_signal_name in [ "write_address_fifo_level", "write_data_fifo_level" ]: if hasattr(axi, fifo_signal_name): axi_fifo_signal = axi[fifo_signal_name] fifo_signal = StatusSignal(axi_fifo_signal.shape(), name=f"axi_{fifo_signal_name}") m.d.comb += fifo_signal.eq(axi_fifo_signal) setattr(self, f"axi_{fifo_signal_name}", fifo_signal) m.d.comb += axi.write_data.connect_upstream(burster.data_output) m.d.comb += axi.write_address.connect_upstream(burster.address_output) # we do not currently care about the write responses m.d.comb += axi.write_response.ready.eq(1) with m.If(axi.write_response.valid): with m.If(axi.write_response.resp == AxiResponse.OKAY): m.d.sync += self.write_response_ok.eq(self.write_response_ok + 1) with m.Else(): m.d.sync += self.write_response_err.eq( self.write_response_err + 1) m.d.comb += self.axi_data_ready.eq(axi.write_data.ready) m.d.comb += self.axi_address_ready.eq(axi.write_address.ready) info_axi_address = m.submodules.info_axi_address = StreamInfo( axi.write_address) info_axi_data = m.submodules.info_axi_data = StreamInfo(axi.write_data) return m
def __init__(self, num_lanes=4, bits=12, hispi_domain="hispi"): assert bits == 12 self.hispi_domain = hispi_domain self.hispi_clk = Signal() self.hispi_lanes = Signal(num_lanes) self.bitslip = [Signal() for _ in range(num_lanes)] self.out = [Signal(12) for _ in range(num_lanes)] self.hispi_x6_in_domain_counter = StatusSignal(32) self.enable_bitslip = ControlSignal(reset=1) self.word_reverse = ControlSignal()
def __init__(self, data_width=8, max_packet_size=1024): self.max_packet_size = max_packet_size self.reset = ControlSignal() self.packet_length = ControlSignal(range(max_packet_size)) self.read_ptr = StatusSignal(range(max_packet_size)) self.done = StatusSignal(reset=1) self.memory = SocMemory( width=data_width, depth=self.max_packet_size, soc_read=False, attrs=dict(syn_ramstyle="block_ram") ) self.output = PacketizedStream(data_width)
class ConsolePacketSink(Elaboratable): def __init__(self, input: PacketizedStream, max_packet_size=1024): self.max_packet_size = max_packet_size self.reset = ControlSignal() self.write_pointer = StatusSignal(range(self.max_packet_size)) self.packet_done = StatusSignal() self.memory = SocMemory( width=len(input.payload), depth=self.max_packet_size, soc_write=False, attrs=dict(syn_ramstyle="block_ram") ) self.input = input def elaborate(self, platform): m = Module() memory = m.submodules.memory = self.memory write_port = m.submodules.write_port = memory.write_port(domain="sync") with m.If(~self.packet_done & (self.write_pointer < self.max_packet_size)): m.d.comb += self.input.ready.eq(1) with m.If(self.input.valid): m.d.comb += write_port.en.eq(1) m.d.comb += write_port.addr.eq(self.write_pointer) m.d.comb += write_port.data.eq(self.input.payload) m.d.sync += self.write_pointer.eq(self.write_pointer + 1) with m.If(self.input.last): m.d.sync += self.packet_done.eq(1) reset = Signal() m.submodules += FFSynchronizer(self.reset, reset) with m.If(Changed(m, reset)): m.d.sync += self.write_pointer.eq(0) m.d.sync += self.packet_done.eq(0) return m @driver_method def read_packet(self, timeout=0): from time import sleep for i in range(int(timeout * 10)): if self.packet_done: break sleep(0.1) if not self.packet_done: return None to_return = [self.memory[i] for i in range(self.write_pointer)] self.reset = not self.reset return to_return
def __init__(self, num_lanes, bits): assert num_lanes <= 32 # the pulse registers cannot be made wider assert bits == 12 # patterns, bitslip counts, and validation need adjusting self.num_lanes = num_lanes self.bits = bits self.lane_pattern = ControlSignal(bits) # registers accessed by host self.data_lane_delay_reset = PulseReg(num_lanes) self.data_lane_delay_inc = PulseReg(num_lanes) self.data_lane_bitslip = PulseReg(num_lanes) self.data_lane_match = StatusSignal(num_lanes) self.data_lane_mismatch = StatusSignal(num_lanes) self.ctrl_lane_delay_reset = PulseReg(2) # control and clock self.ctrl_lane_delay_inc = PulseReg(2) self.ctrl_lane_bitslip = PulseReg(2) self.ctrl_lane_match = StatusSignal(1) self.ctrl_lane_mismatch = StatusSignal(1) self.trained = ControlSignal(1) # signals to/from PHY self.lane_delay_reset = Signal(num_lanes + 1) self.lane_delay_inc = Signal(num_lanes + 1) self.lane_bitslip = Signal(num_lanes + 1) self.outclk_delay_reset = Signal() self.outclk_delay_inc = Signal() self.halfslip = Signal() self.lane_match = Signal(num_lanes + 1) self.lane_mismatch = Signal(num_lanes + 1)
def __init__(self, input: PacketizedStream, packet_len): self.input = input self.output = BasicStream(input.payload.shape()) # we calculate everything in bytes to make it easier to reason about buffer_size = 2048 * 4 blanking = buffer_size aligned_len = ceil((packet_len + blanking) / buffer_size) * buffer_size print("ft60x paddnig:", (aligned_len - packet_len), (aligned_len - packet_len) // 4) self.padding = ControlSignal(16, reset=(aligned_len - packet_len) // 4) self.frame_len = StatusSignal(32) self.frame_len_changed = StatusSignal(32)
def __init__( self, address_source: BasicStream, axi=None, axi_data_width=64, ): self.address_source = address_source self.axi = axi self.output = BasicStream(axi_data_width, name="buffer_reader_output_stream") self.output.payload = Signal(axi_data_width) self.last_resp = StatusSignal(AxiResponse) self.error_count = StatusSignal(32)
class Top(Elaboratable): def __init__(self): self.up_counter = StatusSignal(16) self.down_counter = StatusSignal(16, reset=1000) def elaborate(self, platform): m = Module() m.d.sync += self.up_counter.eq(self.up_counter + 1) m.d.sync += self.down_counter.eq(self.down_counter - 1) add_ila(platform, trace_length=100) probe(m, self.up_counter) probe(m, self.down_counter) trigger(m, self.up_counter > 200) return m
def __init__(self, input, in_testpattern_mode, ddr_domain, bitslip_signal, testpattern=0b00010110): """ Does bit alignment of one lane usig a given testpattern if in_testpattern_mode is high """ self.input = input self.bitslip_signal = bitslip_signal self.in_testpattern_mode = in_testpattern_mode self.ddr_domain = ddr_domain self.testpattern = testpattern self.delay = ControlSignal(5, reset=15) self.error = StatusSignal(32) self.output = StatusSignal(8)
def elaborate(self, platform): m = Module() m.submodules.core = self.core last_fifo_input = BasicStream(self.last_rle_bits) last_fifo = m.submodules.last_fifo = BufferedSyncStreamFIFO( last_fifo_input, self.last_fifo_depth) overflow_word = (2**self.last_rle_bits - 1) rle_input_counter = StatusSignal(self.last_rle_bits) with m.If(self.input.valid & last_fifo_input.ready): m.d.comb += self.core_input.valid.eq(1) m.d.comb += self.core_input.payload.eq(self.input.payload) with m.If(self.core_input.ready): m.d.comb += self.input.ready.eq(1) with m.If(self.input.last | (rle_input_counter == overflow_word - 1)): with m.If(~self.input.last & (rle_input_counter == overflow_word - 1)): m.d.comb += last_fifo_input.payload.eq(overflow_word) with m.Else(): m.d.comb += last_fifo_input.payload.eq( rle_input_counter) m.d.comb += last_fifo_input.valid.eq(1) m.d.sync += rle_input_counter.eq(0) with m.Else(): m.d.sync += rle_input_counter.eq(rle_input_counter + 1) rle_output_counter = StatusSignal(self.last_rle_bits) with m.If(self.core_output.valid): m.d.comb += self.output.valid.eq(1) m.d.comb += self.output.payload.eq(self.core_output.payload) overflow = (last_fifo.output.payload == overflow_word) & ( rle_output_counter == (overflow_word - 1)) with m.If(( (rle_output_counter == last_fifo.output.payload) | overflow) & last_fifo.output.valid): with m.If(~overflow): m.d.comb += self.output.last.eq(1) with m.If(self.output.ready): m.d.sync += rle_output_counter.eq(0) m.d.comb += last_fifo.output.ready.eq(1) m.d.comb += self.core_output.ready.eq(1) with m.Elif((rle_output_counter > last_fifo.output.payload) & last_fifo.output.valid): with m.If(self.output.ready): m.d.comb += self.core_output.ready.eq(1) m.d.sync += self.error.eq(self.error + 1) with m.Else(): with m.If(self.output.ready): m.d.comb += self.core_output.ready.eq(1) m.d.sync += rle_output_counter.eq(rle_output_counter + 1) return m
def __init__( self, address_source: BasicStream, data_source: BasicStream, max_burst_length=16, burst_creation_timeout=31, data_fifo_depth=16, ): self.max_burst_length = max_burst_length self.burst_creation_timeout = burst_creation_timeout self.word_bytes = len(data_source.payload) // 8 self.data_fifo_depth = data_fifo_depth self.address_input = address_source self.data_input = data_source self.written_address_bursts_for_n_wards = StatusSignal(32) self.address_output = AxiAddressStream(addr_bits=len( address_source.payload), lite=False, id_bits=12, data_bytes=self.word_bytes) self.data_output = AxiDataStream(data_bits=len(data_source.payload), read=False, lite=False, id_bits=12)
def __init__(self, input, output_width): self.input = input self.output_width = output_width self.word_alignment = StatusSignal(range(output_width)) self.output = BasicStream(output_width)
def __init__(self, input: PacketizedStream, core_producer, last_fifo_depth=3, last_rle_bits=10): self.last_fifo_depth = last_fifo_depth self.last_rle_bits = last_rle_bits assert hasattr(input, "last") self.input = input self.core_input = BasicStream(input.payload.shape()) self.core = core_producer(self.core_input) self.core_output = self.core.output self.error = StatusSignal(32) self.output = PacketizedStream(len(self.core_output.payload))
def __init__(self, i): self.i = i self.move = ControlSignal() self.direction = ControlSignal() self.at_limit = StatusSignal() self.o = Signal()
class DPhyClockLane(Elaboratable): def __init__(self, lp_pins: TristateIo, hs_pins: TristateDdrIo, ck_domain): self.lp_pins = lp_pins self.hs_pins = hs_pins self.ck_domain = ck_domain self.request_hs = Signal() self.is_hs = StatusSignal() def elaborate(self, platform): m = Module() m.d.comb += self.lp_pins.oe.eq(1) m.d.comb += self.hs_pins.oe.eq(self.is_hs) m.d.comb += self.hs_pins.o_clk.eq(ClockSignal(self.ck_domain)) lp = self.lp_pins.o[::-1] with m.FSM(): with m.State("LP"): m.d.comb += lp.eq(STOP) with m.If(self.request_hs): m.next = "HS_REQUEST" with Process(m, "HS_REQUEST", to="HS") as p: m.d.comb += lp.eq(STOP) p += process_delay( m, 6) # we need to stay in lp state for some minimum time m.d.comb += lp.eq(HS_REQUEST) p += process_delay(m, 6) m.d.comb += lp.eq(BRIDGE) p += process_delay(m, 5) with m.State("HS"): m.d.comb += lp.eq(0) m.d.comb += self.is_hs.eq(1) m.d.comb += self.hs_pins.o0.eq(fake_differential(1)) m.d.comb += self.hs_pins.o1.eq(fake_differential(0)) with m.If(~self.request_hs): m.next = "HS_END" with Process(m, name="HS_END", to="LP") as p: m.d.comb += self.is_hs.eq(1) m.d.comb += lp.eq(0) m.d.comb += self.hs_pins.o0.eq(fake_differential(0)) m.d.comb += self.hs_pins.o1.eq(fake_differential(0)) p += process_delay(m, 2) # delay minimum 60ns return m
def __init__(self, input_freq, vco_mul, vco_div, input_domain="sync"): Pll.is_valid_vco_conf(input_freq, vco_mul, vco_div, exception=True) self._pll = _Pll( clkin1_period=1 / input_freq * 1e9, clkfbout_mult=vco_mul, divclk_divide=vco_div, ) m = self.m = Module() m.d.comb += self._pll.clk.fbin.eq(self._pll.clk.fbout) m.d.comb += self._pll.clk.in_[1].eq(ClockSignal(input_domain)) m.d.comb += self._pll.clk.insel.eq(1) # HIGH for clkin1 self.locked = StatusSignal() self._input_domain = input_domain self._input_freq = input_freq self._vco = Clock(input_freq * vco_mul / vco_div) self._clock_constraints = {}
def __init__(self, input_clock, vco_mul, vco_div, input_domain="sync"): Mmcm.is_valid_vco_conf(input_clock, vco_mul, vco_div, exception=True) self._mmcm = InstanceHelper("+/xilinx/cells_xtra.v", "MMCME2_ADV")( clkin1_period=1 / input_clock * 1e9, clkfbout_mult_f=vco_mul, divclk_divide=vco_div, ) m = self.m = Module() m.d.comb += self._mmcm.clk.fbin.eq(self._mmcm.clk.fbout) m.d.comb += self._mmcm.clk.in_[1].eq(ClockSignal(input_domain)) m.d.comb += self._mmcm.clk.ins.el.eq(1) # HIGH for clkin1 self.locked = StatusSignal() self._input_domain = input_domain self._input_clock = input_clock self._vco = Clock(input_clock * vco_mul / vco_div) self._clock_constraints = {}