diff --git a/src/gateware/cxp_frame_pipeline.py b/src/gateware/cxp_frame_pipeline.py index 9903131..6d47557 100644 --- a/src/gateware/cxp_frame_pipeline.py +++ b/src/gateware/cxp_frame_pipeline.py @@ -399,7 +399,7 @@ class Frame_Header_Decoder(Module): setattr(self.metadata, name, switch_endianness(packet_buffer[idx:idx+size])) idx += size -class Custom_Pixel_Gearbox(Module): +class Pixel_Gearbox(Module): def __init__(self, size): assert size in [8, 10, 12, 14, 16] @@ -581,8 +581,8 @@ class Frame_Deserializer(Module): self.submodules.eol_inserter = eol_inserter = End_Of_Line_Inserter() self.sync += eol_inserter.l_size.eq(self.l_size), - for i in [8, 10, 12, 14, 16]: - gearbox = Custom_Pixel_Gearbox(i) + for s in [8, 10, 12, 14, 16]: + gearbox = Pixel_Gearbox(s) self.submodules += gearbox self.sync += gearbox.x_size.eq(self.x_size), self.comb += eol_inserter.source.connect(gearbox.sink) @@ -623,81 +623,6 @@ class Frame_Deserializer(Module): # ] -def inc_mod(s, m): - return [s.eq(s + 1), If(s == (m -1), s.eq(0))] - - -class Pixel_Gearbox(Module): - def __init__(self, i_dw, o_dw): - self.sink = sink = stream.Endpoint([("data", i_dw)]) - self.source = source = stream.Endpoint([("data", o_dw)]) - - # # # - - # From Litex - - # TODO: change this to purpose built module - # TODO: handle linebreak stb - # TODO: handle the last line may only contain 1, 2, 3 or 4 pixels - - # Section 10.4.2 (CXP-001-2021) - # the line data need to be fitted inside of 32*nbits where n is integers - # extra bits are padded with zero - # -> perhaps use this as advantage?? it's provided as DsizeL - # -> use DsizeL as another counter to indicate line break? - - io_lcm = lcm(i_dw, o_dw) - if (io_lcm//i_dw) < 2: - io_lcm = io_lcm * 2 - if (io_lcm//o_dw) < 2: - io_lcm = io_lcm * 2 - - # Control path - - level = Signal(max=io_lcm) - i_inc = Signal() - i_count = Signal(max=io_lcm//i_dw) - o_inc = Signal() - o_count = Signal(max=io_lcm//o_dw) - - self.comb += [ - sink.ack.eq(1), - # sink.ack.eq(level < (io_lcm - i_dw)), - source.stb.eq(level >= o_dw), - ] - self.comb += [ - i_inc.eq(sink.stb & sink.ack), - o_inc.eq(source.stb & source.ack) - ] - self.sync += [ - If(i_inc, *inc_mod(i_count, io_lcm//i_dw)), - If(o_inc, *inc_mod(o_count, io_lcm//o_dw)), - If(i_inc & ~o_inc, level.eq(level + i_dw)), - If(~i_inc & o_inc, level.eq(level - o_dw)), - If(i_inc & o_inc, level.eq(level + i_dw - o_dw)), - ] - - # Data path - - shift_register = Signal(io_lcm, reset_less=True) - - i_cases = {} - i_data = Signal(i_dw) - - self.comb += i_data.eq(sink.data) - for i in range(io_lcm//i_dw): - i_cases[i] = shift_register[io_lcm - i_dw*(i+1):io_lcm - i_dw*i].eq(i_data) - self.sync += If(sink.stb & sink.ack, Case(i_count, i_cases)) - - o_cases = {} - o_data = Signal(o_dw) - for i in range(io_lcm//o_dw): - o_cases[i] = o_data.eq(shift_register[io_lcm - o_dw*(i+1):io_lcm - o_dw*i]) - self.comb += Case(o_count, o_cases) - self.comb += source.data.eq(o_data) - - - class ROI_Pipeline(Module): def __init__(self, res_width=32, pixel_size=16):