-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cmv12k remapper #34
base: main
Are you sure you want to change the base?
Cmv12k remapper #34
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very, very nice work. I cant say that I understand everything fully bug I roughly get it, thatks to your very nice comments :).
My remarks are a bit bike-shed-y, sorry for that 🙈
# | 2 | 2 | 18 | | 4082 | | ||
# | ... | | | | | | ||
# | 7 | 15 | 31 | | 4095 | | ||
# Note, that we have half as many output channels as input channels. We provide valid data on every clock cycle. (Almost, there will be some cycles where the data is not valid). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I haz some line wrapping for that?
# Concretely this produces a pattern like this (for `n_channels = 8`) | ||
# The sensor output is sturctured into bursts of 128 pixels, so we need to pay attention to the burst boundaries, as after a burst some overhead cycles take place | ||
# channel written: | ||
# | clock -> | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand what bram v is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also why does this start with clock 2
# And a single channel gets 1 pixel per clock cycle, for a total of 4096 / n_channel pixels. For example for 8 channels (per side): 512 pixels. | ||
# This means we read out all of the 512 pixels in 32 cycles, so we can start the read out process with 32 pixels left. | ||
# The next row will start soon after the first, so we store two rows and ping pong the buffers | ||
# TODO(robin): this is fucked because of OH, no? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???
"""Remaps one output port (if top and bottom outputs of the cmv12k are used, instantiate this twice!) to provide a linear output. | ||
def __init__(self, input: ImageStream, n_bits=12, two_sided_readout=True): | ||
assert two_sided_readout == True, "single sided readout is not supported" | ||
assert n_bits == 12, "bit depth other than 12 is not supported" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice way to do this :)
class Cmv12kPixelRemapper(Elaboratable): | ||
"""Remaps one output port (if top and bottom outputs of the cmv12k are used, instantiate this twice!) to provide a linear output. | ||
def __init__(self, input: ImageStream, n_bits=12, two_sided_readout=True): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is the input an image stream though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and are input and output domains the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, input and output domains are the same.
This is a ImageStream
, because the cmv12k rx core outputs an ImageStream
, I just built something that plugs into this.
But of course we could change this. We do not have a "clear" definition of ImageStream
currently and the rx core also output line_last
and frame_last
, so it kind of makes sense to have its output be an ImageStream
, but of course the pixel ordering is a bit "weird".
wr_enable = Signal() | ||
|
||
# write address, write data and rea data is independent for each memory. | ||
wr_address = [Signal(self.addr_width, name=f"wr_address_{i:02}") for i in range(self.n_mem)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bikeshed: maybe we should rather store the ports here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, don't have a strong feeling either way.
# first step: double up the input words. We want to do this with as few FFs as possible. So | ||
# we use the knowledge that we write the first fourth of channel immediately and only need to store a single pixel | ||
# for the middle fourths we need to store two pixels, as we need to wait atleast one cycle more | ||
# for the last forth we need to store three pixels, as a new one comes in before we can write the ol pixel data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ye good 'ol pixel data
channel_number = rd_address_delayed[bits_for(self.channel_block_size - 1) :] | ||
|
||
# for debugging | ||
m.d.comb += Signal(16, name="channel_number").eq(channel_number) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe do that directly above (as it also yields nicer rtlil?)
@pytest.mark.parametrize("channels_per_side", [4, 8, 16, 32]) | ||
def test_cmv12k_pixel_remapper(channels_per_side): | ||
platform = SimPlatform() | ||
# fixed for now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???
@@ -24,7 +24,8 @@ def __init__(self, filename=None): | |||
caller_path = "" | |||
stack = inspect.stack() | |||
for frame in stack[1:]: | |||
if "unittest" in frame.filename: | |||
print(frame, frame.filename) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🖨️
This adds a remapper, that reorders the pixels coming from the cmv12k to follow the
ImageStream
convention, though notably with more than a single pixel per cycle.Untested in hw, but tested in sim.