frameline GW: fix gearbox on 10bits

This commit is contained in:
morgan 2025-01-13 11:50:44 +08:00
parent d509d4e606
commit 1a24dbcdff

View File

@ -401,7 +401,7 @@ class Frame_Header_Decoder(Module):
class Custom_Pixel_Gearbox(Module): class Custom_Pixel_Gearbox(Module):
def __init__(self, size): def __init__(self, size):
assert size in [8, 16] assert size in [8, 10, 16]
self.x_size = Signal(3*char_width) self.x_size = Signal(3*char_width)
@ -421,19 +421,19 @@ class Custom_Pixel_Gearbox(Module):
# Control interface # Control interface
reset_reg = Signal() reset_reg = Signal()
level = Signal(max=shift_reg_size)
we = Signal() we = Signal()
re = Signal() re = Signal()
self.level = Signal(max=shift_reg_size)
self.w_cnt = Signal(max=shift_reg_size//sink_dw) self.w_cnt = Signal(max=shift_reg_size//sink_dw)
self.r_cnt = Signal(max=shift_reg_size//source_dw) self.r_cnt = Signal(max=shift_reg_size//source_dw)
self.sync += [ self.sync += [
If(reset_reg, If(reset_reg,
level.eq(level.reset), self.level.eq(self.level.reset),
).Else( ).Else(
If(we & ~re, level.eq(level + sink_dw)), If(we & ~re, self.level.eq(self.level + sink_dw)),
If(~we & re, level.eq(level - source_dw)), If(~we & re, self.level.eq(self.level - source_dw)),
If(we & re, level.eq(level + sink_dw - source_dw)), If(we & re, self.level.eq(self.level + sink_dw - source_dw)),
), ),
If(reset_reg, If(reset_reg,
@ -457,27 +457,80 @@ class Custom_Pixel_Gearbox(Module):
) )
] ]
# FIXME: handle linebreak properly for all bits
# 1) the COPY may or may not stb data out
# 2) the NEWLINE may stb too much
# FIXME: the fsm need to be intellgent enough to know whether it need to stb twice or once at eop
# need a better generic solution
# FIXME: handle last line when the word also are aligned to 4x pixel
self.submodules.fsm = fsm = FSM(reset_state="COPY") # FACT:
# - self.level is only useful for normal ops (i.e. non-linebreak)
# - it should not be used for last pixels
# - extra_stb should be reserved for non aligned data only
# - after last word, fsm may need to stb 0-2 times
# - which are determined by x_size (varies) & pix size (constant)
# - self.valid should be used instead of extra stb when aligned
extra_stb = Signal()
match size:
case 8 | 16:
# no need for extra stb as they are aligned to word boundary no matter what
pass
case 10:
stb_cases = {
5: extra_stb.eq(1),
6: extra_stb.eq(1),
9: extra_stb.eq(1),
}
# mod 16
self.sync += Case(self.x_size[:4], stb_cases)
# case 12:
# stb_cases = {
# 5: extra_stb.eq(1),
# }
# # mod 8
# self.sync += Case(self.x_size[:3], stb_cases)
# NOTE:
# access to levels -> know when 4x pixels are
# access to x_size -> know which pixel at last stb are valid
# access to eop -> know when end of line ares
self.submodules.fsm = fsm = FSM(reset_state="COPY_ALIGNED")
fsm.act( fsm.act(
"COPY", "COPY_ALIGNED",
self.sink.ack.eq(1), self.sink.ack.eq(1),
self.source.stb.eq(level >= source_dw), self.source.stb.eq(self.level >= source_dw),
we.eq(self.sink.stb), we.eq(self.sink.stb),
re.eq((self.source.stb & self.source.ack)), re.eq((self.source.stb & self.source.ack)),
If(self.sink.stb & self.sink.eop, If(self.sink.stb & self.sink.eop,
NextState("NEWLINE"), If(extra_stb,
NextState("EXTRA_STB"),
).Else(
NextState("NEWLINE"),
)
), ),
) )
fsm.act(
"EXTRA_STB",
self.source.stb.eq(self.level >= source_dw),
re.eq((self.source.stb & self.source.ack)),
NextState("NEWLINE"),
)
# determine to stb 1 or 2 times
# only the last stb will use valid_stb
valid_stb = Signal() valid_stb = Signal()
fsm.act( fsm.act(
"NEWLINE", "NEWLINE",
self.source.stb.eq(1),
reset_reg.eq(1), reset_reg.eq(1),
valid_stb.eq(1), valid_stb.eq(1),
self.source.stb.eq(1), NextState("COPY_ALIGNED"),
NextState("COPY"),
) )
# Data path # Data path
@ -533,7 +586,10 @@ class Frame_Deserializer(Module):
self.sync += eol_inserter.l_size.eq(self.l_size), self.sync += eol_inserter.l_size.eq(self.l_size),
self.submodules.gearbox = gearbox = Custom_Pixel_Gearbox(16) # TODO: fix the edge case where 5 x_size is not working
# the issue arises when the 4th pixel is sent with eop (e.g. 10bits & x_size = 5,6)
# eating the rest of the bits
self.submodules.gearbox = gearbox = Custom_Pixel_Gearbox(12)
self.sync += gearbox.x_size.eq(self.x_size), self.sync += gearbox.x_size.eq(self.x_size),
self.comb += eol_inserter.source.connect(gearbox.sink) self.comb += eol_inserter.source.connect(gearbox.sink)