Skip to content

Commit

Permalink
Merge pull request #188 from timvideos/encoder_buffer
Browse files Browse the repository at this point in the history
Use new encoder buffer
  • Loading branch information
enjoy-digital committed Jan 25, 2016
2 parents a6bf3bb + b040d1b commit b9e390c
Show file tree
Hide file tree
Showing 22 changed files with 785 additions and 483 deletions.
14 changes: 9 additions & 5 deletions firmware/lm32/encoder.c
Expand Up @@ -182,11 +182,15 @@ void encoder_service(void) {
if(elapsed(&last_event, identifier_frequency_read()/encoder_target_fps))
can_start = 1;
if(can_start & encoder_done()) {
encoder_init(encoder_quality);
encoder_start(processor_h_active, processor_v_active);
encoder_reader_dma_length_write(processor_h_active*processor_v_active*2);
encoder_reader_dma_shoot_write(1);
frame_cnt++;
encoder_init(encoder_quality);
encoder_start(processor_h_active, processor_v_active);
can_start = 0;
frame_cnt++;
}
if(encoder_reader_done_read()) {
encoder_reader_h_width_write(processor_h_active);
encoder_reader_v_width_write(processor_v_active);
encoder_reader_start_write(1);
}
if(elapsed(&last_fps_event, identifier_frequency_read())) {
encoder_fps = frame_cnt;
Expand Down
2 changes: 1 addition & 1 deletion firmware/lm32/hdmi_in0.c
Expand Up @@ -21,7 +21,7 @@ int hdmi_in0_fb_index;
#define FRAMEBUFFER_MASK (FRAMEBUFFER_COUNT - 1)

#define HDMI_IN0_FRAMEBUFFERS_BASE 0x00000000
#define HDMI_IN0_FRAMEBUFFERS_SIZE 1280*720*2
#define HDMI_IN0_FRAMEBUFFERS_SIZE 1920*1080*2

unsigned int hdmi_in0_framebuffer_base(char n) {
return HDMI_IN0_FRAMEBUFFERS_BASE + n*HDMI_IN0_FRAMEBUFFERS_SIZE;
Expand Down
2 changes: 1 addition & 1 deletion firmware/lm32/hdmi_in1.c
Expand Up @@ -21,7 +21,7 @@ int hdmi_in1_fb_index;
#define FRAMEBUFFER_MASK (FRAMEBUFFER_COUNT - 1)

#define HDMI_IN1_FRAMEBUFFERS_BASE 0x01000000
#define HDMI_IN1_FRAMEBUFFERS_SIZE 1280*720*2
#define HDMI_IN1_FRAMEBUFFERS_SIZE 1920*1080*2

unsigned int hdmi_in1_framebuffer_base(char n) {
return HDMI_IN1_FRAMEBUFFERS_BASE + n*HDMI_IN1_FRAMEBUFFERS_SIZE;
Expand Down
20 changes: 17 additions & 3 deletions firmware/lm32/processor.c
Expand Up @@ -252,6 +252,20 @@ static const struct video_timing video_modes[PROCESSOR_MODE_COUNT] = {
.v_blanking = 30,
.v_sync_offset = 5,
.v_sync_width = 5
},
// 1920x1080 @ 30.00 Hz ModeLine "1920x1080" 89.01 1920 2448 2492 2640 1080 1084 1089 1125 +HSync +VSync
{
.pixel_clock = 8901,

.h_active = 1920,
.h_blanking = 720,
.h_sync_offset = 528,
.h_sync_width = 44,

.v_active = 1080,
.v_blanking = 45,
.v_sync_offset = 4,
.v_sync_width = 5
}
};

Expand Down Expand Up @@ -487,16 +501,16 @@ void processor_update(void)
/* encoder */
#ifdef CSR_HDMI_IN0_BASE
if(processor_encoder_source == VIDEO_IN_HDMI_IN0) {
encoder_reader_dma_base_write((hdmi_in0_framebuffer_base(hdmi_in0_fb_index)));
encoder_reader_base_write((hdmi_in0_framebuffer_base(hdmi_in0_fb_index)));
}
#endif
#ifdef CSR_HDMI_IN1_BASE
if(processor_encoder_source == VIDEO_IN_HDMI_IN1) {
encoder_reader_dma_base_write((hdmi_in1_framebuffer_base(hdmi_in1_fb_index)));
encoder_reader_base_write((hdmi_in1_framebuffer_base(hdmi_in1_fb_index)));
}
#endif
if(processor_encoder_source == VIDEO_IN_PATTERN)
encoder_reader_dma_base_write(pattern_framebuffer_base());
encoder_reader_base_write(pattern_framebuffer_base());
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion firmware/lm32/processor.h
@@ -1,7 +1,7 @@
#ifndef __PROCESSOR_H
#define __PROCESSOR_H

#define PROCESSOR_MODE_COUNT 11
#define PROCESSOR_MODE_COUNT 12
#define PROCESSOR_MODE_DESCLEN 32

enum {
Expand Down
113 changes: 54 additions & 59 deletions gateware/encoder/__init__.py
Expand Up @@ -3,51 +3,15 @@
from migen.fhdl.std import *
from migen.bus import wishbone
from migen.genlib.record import *
from migen.genlib.cdc import MultiReg
from migen.bank.description import *
from migen.flow.actor import *
from migen.flow.network import *
from migen.actorlib.fifo import SyncFIFO
from migen.actorlib import structuring, spi
from migen.bank.eventmanager import *

from misoclib.mem.sdram.frontend import dma_lasmi

from gateware.csc.ycbcr422to444 import YCbCr422to444
from gateware.csc.ymodulator import YModulator


class EncoderReader(Module, AutoCSR):
def __init__(self, lasmim):
self.source = source = Source(EndpointDescription([("data", 16)], packetized=True))

reader = dma_lasmi.Reader(lasmim)
self.dma = spi.DMAReadController(reader, mode=spi.MODE_SINGLE_SHOT)

pack_factor = lasmim.dw//16
packed_dat = structuring.pack_layout(16, pack_factor)
cast = structuring.Cast(lasmim.dw, packed_dat)
unpack = structuring.Unpack(pack_factor, [("data", 16)], reverse=True)


# graph
g = DataFlowGraph()
g.add_pipeline(self.dma, cast, unpack)
self.submodules += CompositeActor(g)
self.comb += Record.connect(unpack.source, source)

self.sync += \
If(self.dma._busy.status == 0,
source.sop.eq(1),
).Elif(source.stb & source.ack,
source.sop.eq(0)
)

# irq
self.submodules.ev = EventManager()
self.ev.done = EventSourceProcess()
self.ev.finalize()
self.comb += self.ev.done.trigger.eq(self.dma._busy.status)


class EncoderBandwidth(Module, AutoCSR):
Expand Down Expand Up @@ -78,46 +42,74 @@ def __init__(self, platform):
# # #

# chroma upsampler
self.submodules.chroma_upsampler = chroma_upsampler = YCbCr422to444()
chroma_upsampler = RenameClockDomains(YCbCr422to444(), "encoder")
self.submodules += chroma_upsampler
self.comb += [
Record.connect(self.sink, chroma_upsampler.sink, leave_out=["data"]),
chroma_upsampler.sink.y.eq(self.sink.data[:8]),
chroma_upsampler.sink.cb_cr.eq(self.sink.data[8:])
]

# encoder fifo
encoder_fifo_full = Signal()
self.comb += chroma_upsampler.source.ack.eq(~encoder_fifo_full)

# output fifo
output_fifo_almost_full = Signal()
self.submodules.output_fifo = output_fifo = SyncFIFO([("data", 8)], 1024)
output_fifo = RenameClockDomains(SyncFIFO([("data", 8)], 1024), "encoder")
self.submodules += output_fifo
self.comb += [
output_fifo_almost_full.eq(output_fifo.fifo.level > 1024-128),
Record.connect(output_fifo.source, self.source)
]

# Wishbone cross domain crossing
jpeg_bus = wishbone.Interface()
self.specials += Instance("wb_async_reg",
i_wbm_clk=ClockSignal(),
i_wbm_rst=ResetSignal(),
i_wbm_adr_i=self.bus.adr,
i_wbm_dat_i=self.bus.dat_w,
o_wbm_dat_o=self.bus.dat_r,
i_wbm_we_i=self.bus.we,
i_wbm_sel_i=self.bus.sel,
i_wbm_stb_i=self.bus.stb,
o_wbm_ack_o=self.bus.ack,
o_wbm_err_o=self.bus.err,
#o_wbm_rty_o=,
i_wbm_cyc_i=self.bus.cyc,

i_wbs_clk=ClockSignal("encoder"),
i_wbs_rst=ResetSignal("encoder"),
o_wbs_adr_o=jpeg_bus.adr,
i_wbs_dat_i=jpeg_bus.dat_r,
o_wbs_dat_o=jpeg_bus.dat_w,
o_wbs_we_o=jpeg_bus.we,
o_wbs_sel_o=jpeg_bus.sel,
o_wbs_stb_o=jpeg_bus.stb,
i_wbs_ack_i=jpeg_bus.ack,
i_wbs_err_i=jpeg_bus.err,
i_wbs_rty_i=0,
o_wbs_cyc_o=jpeg_bus.cyc)


# encoder
self.specials += Instance("JpegEnc",
i_CLK=ClockSignal(),
i_RST=ResetSignal(),

i_OPB_ABus=Cat(Signal(2), self.bus.adr) & 0x3ff,
i_OPB_BE=self.bus.sel,
i_OPB_DBus_in=self.bus.dat_w,
i_OPB_RNW=~self.bus.we,
i_OPB_select=self.bus.stb & self.bus.cyc,
o_OPB_DBus_out=self.bus.dat_r,
o_OPB_XferAck=self.bus.ack,
i_CLK=ClockSignal("encoder"),
i_RST=ResetSignal("encoder"),

i_OPB_ABus=Cat(Signal(2), jpeg_bus.adr) & 0x3ff,
i_OPB_BE=jpeg_bus.sel,
i_OPB_DBus_in=jpeg_bus.dat_w,
i_OPB_RNW=~jpeg_bus.we,
i_OPB_select=jpeg_bus.stb & jpeg_bus.cyc,
o_OPB_DBus_out=jpeg_bus.dat_r,
o_OPB_XferAck=jpeg_bus.ack,
#o_OPB_retry=,
#o_OPB_toutSup=,
o_OPB_errAck=self.bus.err,
o_OPB_errAck=jpeg_bus.err,

i_iram_wdata=Cat(chroma_upsampler.source.y,
chroma_upsampler.source.cb,
chroma_upsampler.source.cr),
i_iram_wren=chroma_upsampler.source.stb & ~encoder_fifo_full,
o_iram_fifo_afull=encoder_fifo_full,
i_fdct_ack=chroma_upsampler.source.ack,
i_fdct_stb=chroma_upsampler.source.stb,
i_fdct_data=Cat(chroma_upsampler.source.y,
chroma_upsampler.source.cb,
chroma_upsampler.source.cr),

o_ram_byte=output_fifo.sink.data,
o_ram_wren=output_fifo.sink.stb,
Expand All @@ -127,6 +119,9 @@ def __init__(self, platform):
# add vhdl sources
platform.add_source_dir(os.path.join(platform.soc_ext_path, "gateware", "encoder", "vhdl"))

# add verilog sources
platform.add_source(os.path.join(platform.soc_ext_path, "gateware", "encoder", "verilog", "wb_async_reg.v"))

# bandwidth
self.submodules.bandwidth = EncoderBandwidth()
self.submodules.bandwidth = EncoderBandwidth() # XXX add CDC
self.comb += self.bandwidth.nbytes_inc.eq(self.source.stb & self.source.ack)
123 changes: 123 additions & 0 deletions gateware/encoder/buffer.py
@@ -0,0 +1,123 @@
from migen.fhdl.std import *
from migen.genlib.record import *
from migen.genlib.fsm import FSM, NextState
from migen.genlib.misc import chooser
from migen.flow.actor import *

class EncoderBuffer(Module):
def __init__(self):
self.sink = sink = Sink(EndpointDescription([("data", 128)], packetized=True))
self.source = source = Source(EndpointDescription([("data", 16)], packetized=True))

# # #

# mem
mem = Memory(128, 16)
write_port = mem.get_port(write_capable=True)
read_port = mem.get_port(async_read=True)
self.specials += mem, write_port, read_port

write_sel = Signal()
write_swap = Signal()
read_sel = Signal(reset=1)
read_swap = Signal()
self.sync += [
If(write_swap,
write_sel.eq(~write_sel)
),
If(read_swap,
read_sel.eq(~read_sel)
)
]


# write path
v_write_clr = Signal()
v_write_inc = Signal()
v_write = Signal(3)
self.sync += \
If(v_write_clr,
v_write.eq(0)
).Elif(v_write_inc,
v_write.eq(v_write + 1)
)

self.comb += [
write_port.adr.eq(v_write),
write_port.adr[-1].eq(write_sel),
write_port.dat_w.eq(sink.data),
write_port.we.eq(sink.stb & sink.ack)
]

self.submodules.write_fsm = write_fsm = FSM(reset_state="IDLE")
write_fsm.act("IDLE",
v_write_clr.eq(1),
If(write_sel != read_sel,
NextState("WRITE")
)
)
write_fsm.act("WRITE",
sink.ack.eq(1),
If(sink.stb,
If(v_write == 7,
write_swap.eq(1),
NextState("IDLE")
).Else(
v_write_inc.eq(1)
)
)
)

# read path
h_read_clr = Signal()
h_read_inc = Signal()
h_read = Signal(3)
self.sync += \
If(h_read_clr,
h_read.eq(0)
).Elif(h_read_inc,
h_read.eq(h_read + 1)
)

v_read_clr = Signal()
v_read_inc = Signal()
v_read = Signal(3)
self.sync += \
If(v_read_clr,
v_read.eq(0)
).Elif(v_read_inc,
v_read.eq(v_read + 1)
)

self.comb += [
read_port.adr.eq(v_read),
read_port.adr[-1].eq(read_sel),
chooser(read_port.dat_r, h_read, source.data, reverse=True)
]

self.submodules.read_fsm = read_fsm = FSM(reset_state="IDLE")
read_fsm.act("IDLE",
h_read_clr.eq(1),
v_read_clr.eq(1),
If(read_sel == write_sel,
read_swap.eq(1),
NextState("READ")
)
)
read_fsm.act("READ",
source.stb.eq(1),
source.sop.eq((h_read == 0) & (v_read == 0)),
source.eop.eq((h_read == 7) & (v_read == 7)),
If(source.ack,
If(h_read == 7,
h_read_clr.eq(1),
If(v_read == 7,
NextState("IDLE")
).Else(
v_read_inc.eq(1)
)
).Else(
h_read_inc.eq(1)
)
)
)

0 comments on commit b9e390c

Please sign in to comment.