Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
hdl/csc: add ycbcr422to444 and ycbcr444to422
- Loading branch information
1 parent
8c238f5
commit b868b68
Showing
9 changed files
with
225 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,6 @@ rgb2ycbcr_tb: | |
|
||
ycbcr2rgb_tb: | ||
$(CMD) ycbcr2rgb_tb.py | ||
|
||
ycbcr_resampling_tb: | ||
$(CMD) ycbcr_resampling_tb.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
from migen.fhdl.std import * | ||
from migen.sim.generic import run_simulation | ||
from migen.flow.actor import EndpointDescription | ||
|
||
from hdl.csc.common import * | ||
from hdl.csc.ycbcr444to422 import YCbCr444to422 | ||
from hdl.csc.ycbcr422to444 import YCbCr422to444 | ||
|
||
from hdl.csc.test.common import * | ||
|
||
|
||
class TB(Module): | ||
def __init__(self): | ||
self.submodules.streamer = PacketStreamer(EndpointDescription([("data", 24)], packetized=True)) | ||
self.submodules.ycbcr444to422 = YCbCr444to422() | ||
self.submodules.ycbcr422to444 = YCbCr422to444() | ||
self.submodules.logger = PacketLogger(EndpointDescription([("data", 24)], packetized=True)) | ||
|
||
self.comb += [ | ||
self.ycbcr444to422.sink.stb.eq(self.streamer.source.stb), | ||
self.ycbcr444to422.sink.sop.eq(self.streamer.source.sop), | ||
self.ycbcr444to422.sink.eop.eq(self.streamer.source.eop), | ||
self.ycbcr444to422.sink.payload.y.eq(self.streamer.source.data[16:24]), | ||
self.ycbcr444to422.sink.payload.cb.eq(self.streamer.source.data[8:16]), | ||
self.ycbcr444to422.sink.payload.cr.eq(self.streamer.source.data[0:8]), | ||
self.streamer.source.ack.eq(self.ycbcr444to422.sink.ack), | ||
|
||
Record.connect(self.ycbcr444to422.source, self.ycbcr422to444.sink), | ||
|
||
self.logger.sink.stb.eq(self.ycbcr422to444.source.stb), | ||
self.logger.sink.sop.eq(self.ycbcr422to444.source.sop), | ||
self.logger.sink.eop.eq(self.ycbcr422to444.source.eop), | ||
self.logger.sink.data[16:24].eq(self.ycbcr422to444.source.y), | ||
self.logger.sink.data[8:16].eq(self.ycbcr422to444.source.cb), | ||
self.logger.sink.data[0:8].eq(self.ycbcr422to444.source.cr), | ||
self.ycbcr422to444.source.ack.eq(self.logger.sink.ack) | ||
] | ||
|
||
|
||
def gen_simulation(self, selfp): | ||
for i in range(16): | ||
yield | ||
|
||
# chain ycbcr444to422 and ycbcr422to444 | ||
raw_image = RAWImage(None, "lena.png", 64) | ||
raw_image.rgb2ycbcr() | ||
raw_image.pack_ycbcr() | ||
packet = Packet(raw_image.data) | ||
self.streamer.send(packet) | ||
yield from self.logger.receive() | ||
raw_image.set_data(self.logger.packet) | ||
raw_image.unpack_ycbcr() | ||
raw_image.ycbcr2rgb() | ||
raw_image.save("lena_resampling.png") | ||
|
||
if __name__ == "__main__": | ||
run_simulation(TB(), ncycles=8192, vcd_name="my.vcd", keep_files=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# ycbcr422to444 | ||
|
||
from migen.fhdl.std import * | ||
from migen.genlib.record import * | ||
from migen.flow.actor import * | ||
|
||
from hdl.csc.common import * | ||
|
||
datapath_latency = 2 | ||
|
||
@DecorateModule(InsertCE) | ||
class YCbCr422to444Datapath(Module): | ||
"""YCbCr 422 to 444 | ||
Input: Output: | ||
Y0 Y1 Y2 Y3 Y0 Y1 Y2 Y3 | ||
Cb01 Cr01 Cb23 Cr23 --> Cb01 Cb01 Cb23 Cb23 | ||
Cr01 Cr01 Cr23 Cr23 | ||
""" | ||
def __init__(self, dw): | ||
self.sink = sink = Record(ycbcr422_layout(dw)) | ||
self.source = source = Record(ycbcr444_layout(dw)) | ||
self.start = Signal() | ||
|
||
# # # | ||
|
||
# delay ycbcr signals | ||
ycbcr_delayed = [sink] | ||
for i in range(datapath_latency): | ||
ycbcr_n = Record(ycbcr422_layout(dw)) | ||
for name in ["y", "cb_cr"]: | ||
self.sync += getattr(ycbcr_n, name).eq(getattr(ycbcr_delayed[-1], name)) | ||
ycbcr_delayed.append(ycbcr_n) | ||
|
||
# parity | ||
parity = Signal() | ||
self.sync += If(self.start, parity.eq(1)).Else(parity.eq(~parity)) | ||
|
||
# output | ||
self.sync += [ | ||
If(parity, | ||
self.source.y.eq(ycbcr_delayed[1].y), | ||
self.source.cb.eq(ycbcr_delayed[1].cb_cr), | ||
self.source.cr.eq(sink.cb_cr), | ||
).Else( | ||
self.source.y.eq(ycbcr_delayed[1].y), | ||
self.source.cb.eq(ycbcr_delayed[2].cb_cr), | ||
self.source.cr.eq(ycbcr_delayed[1].cb_cr) | ||
) | ||
] | ||
|
||
class YCbCr422to444(PipelinedActor, Module): | ||
def __init__(self, dw=8): | ||
self.sink = sink = Sink(EndpointDescription(ycbcr422_layout(dw), packetized=True)) | ||
self.source = source = Source(EndpointDescription(ycbcr444_layout(dw), packetized=True)) | ||
PipelinedActor.__init__(self, datapath_latency) | ||
self.latency = datapath_latency | ||
|
||
# # # | ||
|
||
self.submodules.datapath = YCbCr422to444Datapath(dw) | ||
self.comb += self.datapath.ce.eq(self.pipe_ce) | ||
for name in ["y", "cb_cr"]: | ||
self.comb += getattr(self.datapath.sink, name).eq(getattr(sink, name)) | ||
for name in ["y", "cb", "cr"]: | ||
self.comb += getattr(source, name).eq(getattr(self.datapath.source, name)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# ycbcr444to422 | ||
|
||
from migen.fhdl.std import * | ||
from migen.genlib.record import * | ||
from migen.flow.actor import * | ||
|
||
from hdl.csc.common import * | ||
|
||
datapath_latency = 3 | ||
|
||
@DecorateModule(InsertCE) | ||
class YCbCr444to422Datapath(Module): | ||
"""YCbCr 444 to 422 | ||
Input: Output: | ||
Y0 Y1 Y2 Y3 Y0 Y1 Y2 Y3 | ||
Cb0 Cb1 Cb2 Cb3 --> Cb01 Cr01 Cb23 Cr23 | ||
Cr0 Cr1 Cr2 Cr3 | ||
""" | ||
def __init__(self, dw): | ||
self.sink = sink = Record(ycbcr444_layout(dw)) | ||
self.source = source = Record(ycbcr422_layout(dw)) | ||
self.start = Signal() | ||
|
||
# # # | ||
|
||
# delay data signals | ||
ycbcr_delayed = [sink] | ||
for i in range(datapath_latency): | ||
ycbcr_n = Record(ycbcr444_layout(dw)) | ||
for name in ["y", "cb", "cr"]: | ||
self.sync += getattr(ycbcr_n, name).eq(getattr(ycbcr_delayed[-1], name)) | ||
ycbcr_delayed.append(ycbcr_n) | ||
|
||
# parity | ||
parity = Signal() | ||
self.sync += If(self.start, parity.eq(1)).Else(parity.eq(~parity)) | ||
|
||
# compute mean of cb and cr compoments | ||
cb_sum = Signal(dw+1) | ||
cr_sum = Signal(dw+1) | ||
cb_mean = Signal(dw) | ||
cr_mean = Signal(dw) | ||
|
||
self.comb += [ | ||
cb_mean.eq(cb_sum[1:]), | ||
cr_mean.eq(cr_sum[1:]) | ||
] | ||
|
||
self.sync += [ | ||
If(parity, | ||
cb_sum.eq(sink.cb + ycbcr_delayed[1].cb), | ||
cr_sum.eq(sink.cr + ycbcr_delayed[1].cr) | ||
) | ||
] | ||
|
||
# output | ||
self.sync += [ | ||
If(parity, | ||
self.source.y.eq(ycbcr_delayed[2].y), | ||
self.source.cb_cr.eq(cr_mean) | ||
).Else( | ||
self.source.y.eq(ycbcr_delayed[2].y), | ||
self.source.cb_cr.eq(cb_mean) | ||
) | ||
] | ||
|
||
|
||
class YCbCr444to422(PipelinedActor, Module): | ||
def __init__(self, dw=8): | ||
self.sink = sink = Sink(EndpointDescription(ycbcr444_layout(dw), packetized=True)) | ||
self.source = source = Source(EndpointDescription(ycbcr422_layout(dw), packetized=True)) | ||
PipelinedActor.__init__(self, datapath_latency) | ||
self.latency = datapath_latency | ||
|
||
# # # | ||
|
||
self.submodules.datapath = YCbCr444to422Datapath(dw) | ||
self.comb += [ | ||
self.datapath.start.eq(self.sink.stb & sink.sop), | ||
self.datapath.ce.eq(self.pipe_ce), | ||
] | ||
for name in ["y", "cb", "cr"]: | ||
self.comb += getattr(self.datapath.sink, name).eq(getattr(sink, name)) | ||
for name in ["y", "cb_cr"]: | ||
self.comb += getattr(source, name).eq(getattr(self.datapath.source, name)) |