forked from M-Labs/artiq-zynq
frameline: add pixeldata layout & add docs
This commit is contained in:
parent
3a03d7c52c
commit
f6ad1ee97a
@ -21,19 +21,17 @@ pixel4x_layout = [
|
||||
("data", pixel_width*4),
|
||||
("valid", 4),
|
||||
]
|
||||
pixeldata_layout = [("data", word_width)] # pixel data don't need k code
|
||||
|
||||
# TODO: rename this to signalify eol marker & kcode/other data dropper
|
||||
class End_Of_Line_Marker(Module):
|
||||
class End_of_line_Marker(Module):
|
||||
"""
|
||||
Repurpose eop to indicate end of line
|
||||
And drop the K codes and Duplicate char
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
self.l_size = Signal(3*char_width)
|
||||
|
||||
self.sink = Endpoint(word_layout_dchar)
|
||||
self.source = Endpoint([("data", word_width)]) # pixel data don't need k code
|
||||
self.sink = Endpoint(pixeldata_layout)
|
||||
self.source = Endpoint(pixeldata_layout)
|
||||
|
||||
# # #
|
||||
|
||||
@ -46,7 +44,7 @@ class End_Of_Line_Marker(Module):
|
||||
cnt = Signal.like(self.l_size, reset=1)
|
||||
self.sync += [
|
||||
If((~self.source.stb | self.source.ack),
|
||||
self.sink.connect(self.source, omit={"ack", "eop", "k", "dchar", "dchar_k"}),
|
||||
self.sink.connect(self.source, omit={"ack", "eop"}),
|
||||
If(self.sink.stb,
|
||||
If(cnt == 1,
|
||||
cnt.eq(self.l_size)
|
||||
@ -127,9 +125,8 @@ class CXPCRC32(Module):
|
||||
]
|
||||
|
||||
class CXPCRC32_Checker(Module):
|
||||
"""Verify crc in stream data packet"""
|
||||
"""Verify crc in stream packet"""
|
||||
def __init__(self):
|
||||
# TODO: handle the error into a counter
|
||||
self.error = Signal()
|
||||
|
||||
self.sink = Endpoint(word_layout_dchar)
|
||||
@ -267,7 +264,7 @@ class Stream_Broadcaster(Module):
|
||||
|
||||
class Frame_Header_Reader(Module):
|
||||
"""
|
||||
Extract the frame header information
|
||||
Extract the frame header information and pass pixel data downstream
|
||||
"""
|
||||
def __init__(self):
|
||||
self.decode_err = Signal()
|
||||
@ -291,11 +288,11 @@ class Frame_Header_Reader(Module):
|
||||
]
|
||||
assert layout_len(img_header_layout) == n_metadata_chars*char_width
|
||||
|
||||
self.sink = Endpoint(word_layout_dchar)
|
||||
self.source = Endpoint(pixeldata_layout)
|
||||
|
||||
# # #
|
||||
|
||||
self.sink = Endpoint(word_layout_dchar)
|
||||
self.source = Endpoint(word_layout_dchar)
|
||||
|
||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||
|
||||
@ -312,7 +309,7 @@ class Frame_Header_Reader(Module):
|
||||
self.sink.ack.eq(1),
|
||||
NextState("DECODE"),
|
||||
).Else(
|
||||
self.sink.connect(self.source),
|
||||
self.sink.connect(self.source, omit={"k", "dchar", "dchar_k"}),
|
||||
)
|
||||
)
|
||||
|
||||
@ -370,7 +367,7 @@ class Frame_Header_Reader(Module):
|
||||
setattr(self.metadata, name, switch_endianness(packet_buffer[idx:idx+size]))
|
||||
idx += size
|
||||
|
||||
class Pixel_Gearbox(Module):
|
||||
class Pixel_Unpacker(Module):
|
||||
"""Convert 32 bits word into 4x pixel"""
|
||||
def __init__(self, size):
|
||||
assert size <= pixel_width
|
||||
@ -378,12 +375,12 @@ class Pixel_Gearbox(Module):
|
||||
|
||||
self.x_size = Signal(3*char_width)
|
||||
|
||||
sink_dw, source_dw = word_width, size*4
|
||||
self.sink = Endpoint([("data", sink_dw)])
|
||||
self.sink = Endpoint(pixeldata_layout)
|
||||
self.source = Endpoint(pixel4x_layout)
|
||||
|
||||
# # #
|
||||
|
||||
sink_dw, source_dw = layout_len(pixeldata_layout), size*4
|
||||
ring_buf_size = lcm(sink_dw, source_dw)
|
||||
# ensure the shift register is at least twice the size of sink/source dw
|
||||
if (ring_buf_size//sink_dw) < 2:
|
||||
@ -831,14 +828,14 @@ class Pixel_Parser(Module):
|
||||
# inserter Tracker w/ coord
|
||||
#
|
||||
|
||||
self.submodules.eol_inserter = eol_inserter = End_Of_Line_Marker()
|
||||
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
|
||||
|
||||
|
||||
gearboxes = {}
|
||||
for s in [8, 10, 12, 14, 16]:
|
||||
gearbox = Pixel_Gearbox(s)
|
||||
gearbox = Pixel_Unpacker(s)
|
||||
gearboxes["mono"+str(s)] = gearbox
|
||||
self.submodules += gearbox
|
||||
self.sync += gearbox.x_size.eq(self.x_size),
|
||||
@ -921,36 +918,33 @@ class Stream2Pixel4x_Converter(Module):
|
||||
"""
|
||||
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
|
||||
# 32+8(dchar) 32 4x pixel
|
||||
# sink ────/────> crc checker ─────> frame header ───/───> eol inserter ─────> 8, 10, 12, 14, 16 bits ───/───> pixel coordinate ─────> 4x pixel with
|
||||
# reader pixel unpacker tracker coordinate
|
||||
#
|
||||
|
||||
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.submodules.formatter = formatter = End_of_line_Marker()
|
||||
self.sync += formatter.l_size.eq(header_reader.metadata.l_size)
|
||||
self.sink = formatter.sink
|
||||
|
||||
|
||||
self.pipeline = [crc_checker, header_reader, eol_inserter]
|
||||
self.pipeline = [crc_checker, header_reader, formatter]
|
||||
for s, d in zip(self.pipeline, self.pipeline[1:]):
|
||||
self.comb += s.source.connect(d.sink)
|
||||
self.sink = self.pipeline[0].sink
|
||||
|
||||
|
||||
gearboxes = {}
|
||||
unpackers = {}
|
||||
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),
|
||||
unpacker = Pixel_Unpacker(s)
|
||||
unpackers["mono"+str(s)] = unpacker
|
||||
self.submodules += unpacker
|
||||
self.sync += unpacker.x_size.eq(header_reader.metadata.x_size),
|
||||
|
||||
# From Table 34 (CXP-001-2021)
|
||||
pix_fmt = {
|
||||
@ -966,11 +960,11 @@ class Stream2Pixel4x_Converter(Module):
|
||||
self.pixel4x = tracker.pixel4x
|
||||
|
||||
# discard unknown pixel format
|
||||
mux_cases = {"default": [eol_inserter.source.ack.eq(1)]}
|
||||
mux_cases = {"default": [formatter.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),
|
||||
formatter.source.connect(unpackers[fmt].sink),
|
||||
unpackers[fmt].source.connect(tracker.sink),
|
||||
]
|
||||
|
||||
self.comb += Case(header_reader.metadata.pixel_format, mux_cases)
|
||||
|
Loading…
Reference in New Issue
Block a user