forked from M-Labs/artiq-zynq
frameline GW: add roi proto
This commit is contained in:
parent
d6a0b4644c
commit
2cd588df35
@ -9,6 +9,7 @@ from src.gateware.cxp_pipeline import * # for sim only
|
|||||||
|
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from math import lcm
|
from math import lcm
|
||||||
|
from operator import or_, add
|
||||||
|
|
||||||
pixel_width = 16
|
pixel_width = 16
|
||||||
pixel4x_layout = [
|
pixel4x_layout = [
|
||||||
@ -558,7 +559,7 @@ class Pixel_Parser(Module):
|
|||||||
self.pixel4x.append(Record([
|
self.pixel4x.append(Record([
|
||||||
("x", res_width),
|
("x", res_width),
|
||||||
("y", res_width),
|
("y", res_width),
|
||||||
("d", pixel_width),
|
("gray", pixel_width),
|
||||||
("stb", 1),
|
("stb", 1),
|
||||||
("eof", 1), # end of frame
|
("eof", 1), # end of frame
|
||||||
]))
|
]))
|
||||||
@ -588,10 +589,98 @@ class Pixel_Parser(Module):
|
|||||||
pix.stb.eq(self.sink.valid[i]),
|
pix.stb.eq(self.sink.valid[i]),
|
||||||
pix.x.eq(x_r),
|
pix.x.eq(x_r),
|
||||||
pix.y.eq(y_r),
|
pix.y.eq(y_r),
|
||||||
pix.d.eq(self.sink.data[pixel_width*i:pixel_width*(i+1)]),
|
pix.gray.eq(self.sink.data[pixel_width*i:pixel_width*(i+1)]),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class ROI(Module):
|
||||||
|
"""
|
||||||
|
ROI Engine. For each frame, accumulates pixels values within a
|
||||||
|
rectangular region of interest, and reports the total.
|
||||||
|
"""
|
||||||
|
def __init__(self, pixel_4x, count_len):
|
||||||
|
assert count_len <= 31
|
||||||
|
assert len(pixel_4x) == 4
|
||||||
|
|
||||||
|
self.cfg = Record([
|
||||||
|
("x0", len(pixel_4x[0].x)),
|
||||||
|
("y0", len(pixel_4x[0].y)),
|
||||||
|
("x1", len(pixel_4x[0].x)),
|
||||||
|
("y1", len(pixel_4x[0].y)),
|
||||||
|
])
|
||||||
|
|
||||||
|
self.out = Record([
|
||||||
|
("update", 1),
|
||||||
|
("count", count_len),
|
||||||
|
])
|
||||||
|
|
||||||
|
# # #
|
||||||
|
#
|
||||||
|
|
||||||
|
self.roi_4x = []
|
||||||
|
for _ in range(4):
|
||||||
|
self.roi_4x.append(Record([
|
||||||
|
("x_good", 1),
|
||||||
|
("y_good", 1),
|
||||||
|
("gray", len(pixel_4x[0].gray)),
|
||||||
|
("stb", 1),
|
||||||
|
("count", count_len),
|
||||||
|
]))
|
||||||
|
|
||||||
|
|
||||||
|
# x_good = [Signal() for _ in range(4)]
|
||||||
|
# y_good = [Signal() for _ in range(4)]
|
||||||
|
# gray = [Signal(len(pixel_4x[0].gray)) for _ in range(4)]
|
||||||
|
# stb = [Signal() for _ in range(4)]
|
||||||
|
# count = [Signal(count_len) for _ in range(4)]
|
||||||
|
|
||||||
|
for pix, roi in zip(pixel_4x, self.roi_4x):
|
||||||
|
self.sync += [
|
||||||
|
# stage 1 - generate "good" (in-ROI) signals
|
||||||
|
If(pix.x == self.cfg.x0,
|
||||||
|
roi.x_good.eq(1)
|
||||||
|
),
|
||||||
|
# NOTE: this gate doens't work as 4 pixes are coming in
|
||||||
|
If(pix.x >= self.cfg.x1,
|
||||||
|
roi.x_good.eq(0)
|
||||||
|
),
|
||||||
|
|
||||||
|
# This is fine because 4x pixel are on the same line
|
||||||
|
If(pix.y == self.cfg.y0,
|
||||||
|
roi.y_good.eq(1)
|
||||||
|
),
|
||||||
|
If(pix.y == self.cfg.y1,
|
||||||
|
roi.y_good.eq(0)
|
||||||
|
),
|
||||||
|
If(pix.eof,
|
||||||
|
roi.x_good.eq(0),
|
||||||
|
roi.y_good.eq(0)
|
||||||
|
),
|
||||||
|
roi.gray.eq(pix.gray),
|
||||||
|
roi.stb.eq(pix.stb),
|
||||||
|
|
||||||
|
# stage 2 - accumulate
|
||||||
|
If((roi.stb & roi.x_good & roi.y_good),
|
||||||
|
roi.count.eq(roi.count + roi.gray)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
eof = Signal()
|
||||||
|
# stage 3 - update
|
||||||
|
self.sync += [
|
||||||
|
eof.eq(reduce(or_, [pix.eof for pix in pixel_4x])),
|
||||||
|
|
||||||
|
self.out.update.eq(0),
|
||||||
|
If(eof,
|
||||||
|
[roi.count.eq(0) for roi in self.roi_4x],
|
||||||
|
self.out.update.eq(1),
|
||||||
|
self.out.count.eq(reduce(add, [roi.count for roi in self.roi_4x]))
|
||||||
|
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Frame_Deserializer(Module):
|
class Frame_Deserializer(Module):
|
||||||
@ -628,6 +717,7 @@ class Frame_Deserializer(Module):
|
|||||||
|
|
||||||
self.submodules.parser = parser = Pixel_Parser(res_width)
|
self.submodules.parser = parser = Pixel_Parser(res_width)
|
||||||
self.sync += parser.y_size.eq(self.y_size)
|
self.sync += parser.y_size.eq(self.y_size)
|
||||||
|
self.pixel4x = parser.pixel4x
|
||||||
|
|
||||||
mux_cases = {
|
mux_cases = {
|
||||||
"default": [
|
"default": [
|
||||||
@ -646,8 +736,8 @@ class Frame_Deserializer(Module):
|
|||||||
|
|
||||||
|
|
||||||
class ROI_Pipeline(Module):
|
class ROI_Pipeline(Module):
|
||||||
# TODO: but header xsize/ysize is only 24bits, change this to 24?
|
# largest x/y pixel size supported by frame header are 24 bits
|
||||||
def __init__(self, res_width=32):
|
def __init__(self, res_width=24):
|
||||||
|
|
||||||
# NOTE: csr need to stay outside since this module need to be cdr in the CXP_FRAME_Pipeline module
|
# NOTE: csr need to stay outside since this module need to be cdr in the CXP_FRAME_Pipeline module
|
||||||
# NOTE: TapGeo other than 1X-1Y are not supported
|
# NOTE: TapGeo other than 1X-1Y are not supported
|
||||||
@ -658,6 +748,8 @@ class ROI_Pipeline(Module):
|
|||||||
self.submodules.header_decoder = header_decoder = Frame_Header_Decoder()
|
self.submodules.header_decoder = header_decoder = Frame_Header_Decoder()
|
||||||
self.submodules.deserializer = deserializer = Frame_Deserializer(res_width)
|
self.submodules.deserializer = deserializer = Frame_Deserializer(res_width)
|
||||||
|
|
||||||
|
self.submodules.roi = ROI(deserializer.pixel4x, 31)
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
deserializer.new_frame.eq(header_decoder.new_frame),
|
deserializer.new_frame.eq(header_decoder.new_frame),
|
||||||
deserializer.l_size.eq(header_decoder.metadata.l_size),
|
deserializer.l_size.eq(header_decoder.metadata.l_size),
|
||||||
|
Loading…
Reference in New Issue
Block a user