frameline: add single lane pixel converter

This commit is contained in:
morgan 2025-02-06 17:05:41 +08:00
parent b34d68797d
commit 39c4fe5f6e

View File

@ -22,9 +22,10 @@ pixel4x_layout = [
("valid", 4),
]
class End_Of_Line_Inserter(Module):
# TODO: rename this to signalify eol marker & kcode/other data dropper
class End_Of_Line_Marker(Module):
"""
Insert eop to indicate end of line
Repurpose eop to indicate end of line
And drop the K codes and Duplicate char
"""
@ -264,7 +265,10 @@ class Stream_Broadcaster(Module):
NextState("WAIT_HEADER"),
)
class Frame_Header_Decoder(Module):
class Frame_Header_Reader(Module):
"""
Extract the frame header information
"""
def __init__(self):
self.decode_err = Signal()
@ -827,7 +831,7 @@ class Pixel_Parser(Module):
# inserter Tracker w/ coord
#
self.submodules.eol_inserter = eol_inserter = End_Of_Line_Inserter()
self.submodules.eol_inserter = eol_inserter = End_Of_Line_Marker()
self.sync += eol_inserter.l_size.eq(self.l_size)
self.sink = eol_inserter.sink
@ -883,7 +887,7 @@ class Pixel_Pipeline(Module):
self.submodules.buffer = buffer = SyncFIFO(word_layout_dchar, 32, True)
# self.submodules.buffer = buffer = Buffer(word_layout_dchar) # to improve timing from broadcaster
self.submodules.crc_checker = crc_checker = CXPCRC32_Checker()
self.submodules.header_decoder = header_decoder = Frame_Header_Decoder()
self.submodules.header_decoder = header_decoder = Frame_Header_Reader()
self.submodules.parser = parser = Pixel_Parser(res_width)
self.submodules.roi = ROI(parser.pixel4x, count_width)
@ -904,3 +908,70 @@ class Pixel_Pipeline(Module):
# self.pix = self.pipeline[-1].pix
# self.source = self.pipeline[-1].source
# self.comb += self.source.ack.eq(1) # simulated a proper consumer, idk why but without this it will destory timing
class Stream2Pixel4x_Converter(Module):
"""
Convert the raw frame data into pixel data
Currently only support:
- Pixel format: mono8, mono10, mono12, mono14, mono16
- Tap geometry: 1X-1Y
- Scaning mode: area scanning
"""
def __init__(self, res_width, count_width):
# 32+8(dchar)
# ----/----> crc checker ------> frame header ------> eol inserter
# decoder
#
# 32 pixel 4x
# ---/---> 32:8/10/12/14/16 Pixel Gearboxes ----/----> Pixel Coordinate ------> pixel 4x
# Tracker w/ coord
#
self.submodules.crc_checker = crc_checker = CXPCRC32_Checker()
self.submodules.header_reader = header_reader = Frame_Header_Reader()
# Pixel Praser
self.submodules.eol_inserter = eol_inserter = End_Of_Line_Marker()
self.sync += eol_inserter.l_size.eq(header_reader.metadata.l_size)
self.sink = eol_inserter.sink
self.pipeline = [crc_checker, header_reader, eol_inserter]
for s, d in zip(self.pipeline, self.pipeline[1:]):
self.comb += s.source.connect(d.sink)
self.sink = self.pipeline[0].sink
gearboxes = {}
for s in [8, 10, 12, 14, 16]:
gearbox = Pixel_Gearbox(s)
gearboxes["mono"+str(s)] = gearbox
self.submodules += gearbox
self.sync += gearbox.x_size.eq(header_reader.metadata.x_size),
# From Table 34 (CXP-001-2021)
pix_fmt = {
"mono8": 0x0101,
"mono10": 0x0102,
"mono12": 0x0103,
"mono14": 0x0104,
"mono16": 0x0105,
}
self.submodules.tracker = tracker = Pixel_Coordinate_Tracker(res_width)
self.sync += tracker.y_size.eq(header_reader.metadata.y_size)
self.pixel4x = tracker.pixel4x
# discard unknown pixel format
mux_cases = {"default": [eol_inserter.source.ack.eq(1)]}
for fmt in pix_fmt:
mux_cases[pix_fmt[fmt]] = [
eol_inserter.source.connect(gearboxes[fmt].sink),
gearboxes[fmt].source.connect(tracker.sink),
]
self.comb += Case(header_reader.metadata.pixel_format, mux_cases)