'de' reaches the PHY, so add inframe to cover the whole screen and stabilize the windowboxed modes

This commit is contained in:
Romain Dolbeau 2022-09-21 23:57:00 +02:00
parent f722c396c9
commit d0d98f1390
2 changed files with 37 additions and 4 deletions

View File

@ -12,11 +12,26 @@ from litex.build.io import SDROutput, DDROutput
from litex.soc.cores.video import * from litex.soc.cores.video import *
video_timing_nohwcursor_layout = [
# Synchronization signals.
("hsync", 1),
("vsync", 1),
("de", 1),
("inframe", 1),
# Extended/Optional synchronization signals.
("hres", hbits),
("vres", vbits),
("hcount", hbits),
("vcount", vbits),
]
video_timing_hwcursor_layout = [ video_timing_hwcursor_layout = [
# Synchronization signals. # Synchronization signals.
("hsync", 1), ("hsync", 1),
("vsync", 1), ("vsync", 1),
("de", 1), ("de", 1),
("inframe", 1),
("hwcursor", 1), ("hwcursor", 1),
("hwcursorx", 5), ("hwcursorx", 5),
("hwcursory", 5), ("hwcursory", 5),
@ -72,7 +87,7 @@ class FBVideoTimingGenerator(Module, AutoCSR):
self.specials += MultiReg(self.hwcursor_x, _hwcursor_x) self.specials += MultiReg(self.hwcursor_x, _hwcursor_x)
self.specials += MultiReg(self.hwcursor_y, _hwcursor_y) self.specials += MultiReg(self.hwcursor_y, _hwcursor_y)
else: else:
self.source = source = stream.Endpoint(video_timing_layout) self.source = source = stream.Endpoint(video_timing_nohwcursor_layout)
# # # # # #
@ -106,8 +121,12 @@ class FBVideoTimingGenerator(Module, AutoCSR):
self.specials += MultiReg(self._vres_end, vres_end) self.specials += MultiReg(self._vres_end, vres_end)
# Generate timings. # Generate timings.
# whether we're in the visible frame
hactive = Signal() hactive = Signal()
vactive = Signal() vactive = Signal()
# whether we're in the picture (including non-visible part of frame for windowboxing)
hinframe = Signal()
vinframe = Signal()
fsm = FSM(reset_state="IDLE") fsm = FSM(reset_state="IDLE")
fsm = ResetInserter()(fsm) fsm = ResetInserter()(fsm)
self.submodules.fsm = fsm self.submodules.fsm = fsm
@ -115,6 +134,8 @@ class FBVideoTimingGenerator(Module, AutoCSR):
fsm.act("IDLE", fsm.act("IDLE",
NextValue(hactive, 0), NextValue(hactive, 0),
NextValue(vactive, 0), NextValue(vactive, 0),
NextValue(hinframe, 0),
NextValue(vinframe, 0),
NextValue(source.hres, hres), NextValue(source.hres, hres),
NextValue(source.vres, vres), NextValue(source.vres, vres),
NextValue(source.hcount, 0), NextValue(source.hcount, 0),
@ -122,6 +143,7 @@ class FBVideoTimingGenerator(Module, AutoCSR):
NextState("RUN") NextState("RUN")
) )
self.comb += source.de.eq(hactive & vactive) # DE when both HActive and VActive. self.comb += source.de.eq(hactive & vactive) # DE when both HActive and VActive.
self.comb += source.inframe.eq(hinframe & vinframe) # InFrame when both HInFrame and VInFrame.
self.sync += source.first.eq((source.hcount == 0) & (source.vcount == 0)), self.sync += source.first.eq((source.hcount == 0) & (source.vcount == 0)),
self.sync += source.last.eq( (source.hcount == hscan) & (source.vcount == vscan)), self.sync += source.last.eq( (source.hcount == hscan) & (source.vcount == vscan)),
fsm.act("RUN", fsm.act("RUN",
@ -132,6 +154,8 @@ class FBVideoTimingGenerator(Module, AutoCSR):
# Generate HActive / HSync. # Generate HActive / HSync.
If(source.hcount == hres_start, NextValue(hactive, 1)), # Start of HActive. If(source.hcount == hres_start, NextValue(hactive, 1)), # Start of HActive.
If(source.hcount == hres_end, NextValue(hactive, 0)), # End of HActive. If(source.hcount == hres_end, NextValue(hactive, 0)), # End of HActive.
If(source.hcount == 0, NextValue(hinframe, 1)), # Start of HInFrame.
If(source.hcount == hres, NextValue(hinframe, 0)), # End of HInFrame.
If(source.hcount == hsync_start, NextValue(source.hsync, 1)), # Start of HSync. If(source.hcount == hsync_start, NextValue(source.hsync, 1)), # Start of HSync.
If(source.hcount == hsync_end, NextValue(source.hsync, 0)), # End of HSync. If(source.hcount == hsync_end, NextValue(source.hsync, 0)), # End of HSync.
# End of HScan. # End of HScan.
@ -142,7 +166,9 @@ class FBVideoTimingGenerator(Module, AutoCSR):
NextValue(source.vcount, source.vcount + 1), NextValue(source.vcount, source.vcount + 1),
# Generate VActive / VSync. # Generate VActive / VSync.
If(source.vcount == vres_start, NextValue(vactive, 1)), # Start of VActive. If(source.vcount == vres_start, NextValue(vactive, 1)), # Start of VActive.
If(source.vcount == vres_end, NextValue(vactive, 0)), # End of HActive. If(source.vcount == vres_end, NextValue(vactive, 0)), # End of VActive.
If(source.vcount == 0, NextValue(vinframe, 1)), # Start of VInFrame.
If(source.vcount == vres, NextValue(vinframe, 0)), # End of VInFrame.
If(source.vcount == vsync_start, NextValue(source.vsync, 1)), # Start of VSync. If(source.vcount == vsync_start, NextValue(source.vsync, 1)), # Start of VSync.
If(source.vcount == vsync_end, NextValue(source.vsync, 0)), # End of VSync. If(source.vcount == vsync_end, NextValue(source.vsync, 0)), # End of VSync.
# End of VScan. # End of VScan.

View File

@ -79,7 +79,7 @@ class VideoFrameBufferMultiDepth(Module, AutoCSR):
) )
] ]
else: else:
self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout) self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_nohwcursor_layout)
@ -89,6 +89,7 @@ class VideoFrameBufferMultiDepth(Module, AutoCSR):
#source_buf_ready = Signal() #source_buf_ready = Signal()
source_buf_valid = Signal() source_buf_valid = Signal()
source_buf_de = Signal() source_buf_de = Signal()
source_buf_inframe = Signal()
source_buf_hsync = Signal() source_buf_hsync = Signal()
source_buf_vsync = Signal() source_buf_vsync = Signal()
data_buf_index = Signal(8) data_buf_index = Signal(8)
@ -100,6 +101,7 @@ class VideoFrameBufferMultiDepth(Module, AutoCSR):
source_buf_b_valid = Signal() source_buf_b_valid = Signal()
source_buf_b_de = Signal() source_buf_b_de = Signal()
source_buf_b_inframe = Signal()
source_buf_b_hsync = Signal() source_buf_b_hsync = Signal()
source_buf_b_vsync = Signal() source_buf_b_vsync = Signal()
data_buf_b_index = Signal(8) data_buf_b_index = Signal(8)
@ -111,6 +113,7 @@ class VideoFrameBufferMultiDepth(Module, AutoCSR):
#source_out_ready = Signal() #source_out_ready = Signal()
source_out_valid = Signal() source_out_valid = Signal()
source_out_de = Signal() source_out_de = Signal()
source_out_inframe = Signal()
source_out_hsync = Signal() source_out_hsync = Signal()
source_out_vsync = Signal() source_out_vsync = Signal()
source_out_r = Signal(8) source_out_r = Signal(8)
@ -264,6 +267,7 @@ class VideoFrameBufferMultiDepth(Module, AutoCSR):
vtg_sink.ready.eq(source_buf_valid & source.ready), vtg_sink.ready.eq(source_buf_valid & source.ready),
), ),
source_buf_de.eq(vtg_sink.de), source_buf_de.eq(vtg_sink.de),
source_buf_inframe.eq(vtg_sink.inframe),
source_buf_hsync.eq(vtg_sink.hsync), source_buf_hsync.eq(vtg_sink.hsync),
source_buf_vsync.eq(vtg_sink.vsync), source_buf_vsync.eq(vtg_sink.vsync),
Case(self.indexed_mode, { Case(self.indexed_mode, {
@ -284,8 +288,10 @@ class VideoFrameBufferMultiDepth(Module, AutoCSR):
hwcursorx_buf.eq(vtg_sink.hwcursorx), hwcursorx_buf.eq(vtg_sink.hwcursorx),
hwcursory_buf.eq(vtg_sink.hwcursory), hwcursory_buf.eq(vtg_sink.hwcursory),
] ]
vga_sync += [ vga_sync += [
source_buf_b_de.eq(source_buf_de), source_buf_b_de.eq(source_buf_de),
source_buf_b_inframe.eq(source_buf_inframe),
source_buf_b_hsync.eq(source_buf_hsync), source_buf_b_hsync.eq(source_buf_hsync),
source_buf_b_vsync.eq(source_buf_vsync), source_buf_b_vsync.eq(source_buf_vsync),
source_buf_b_valid.eq(source_buf_valid), source_buf_b_valid.eq(source_buf_valid),
@ -303,6 +309,7 @@ class VideoFrameBufferMultiDepth(Module, AutoCSR):
vga_sync += [ vga_sync += [
source_out_de.eq(source_buf_b_de), source_out_de.eq(source_buf_b_de),
source_out_inframe.eq(source_buf_b_inframe),
source_out_hsync.eq(source_buf_b_hsync), source_out_hsync.eq(source_buf_b_hsync),
source_out_vsync.eq(source_buf_b_vsync), source_out_vsync.eq(source_buf_b_vsync),
source_out_valid.eq(source_buf_b_valid), source_out_valid.eq(source_buf_b_valid),
@ -344,7 +351,7 @@ class VideoFrameBufferMultiDepth(Module, AutoCSR):
] ]
self.comb += [ self.comb += [
source.de.eq(source_out_de), source.de.eq(source_out_inframe), # inframe, not de
source.hsync.eq(source_out_hsync), source.hsync.eq(source_out_hsync),
source.vsync.eq(source_out_vsync), source.vsync.eq(source_out_vsync),
source.valid.eq(source_out_valid), source.valid.eq(source_out_valid),