forked from M-Labs/artiq-zynq
frameline GW: fix gearbox on 10bits
This commit is contained in:
parent
d509d4e606
commit
1a24dbcdff
@ -401,7 +401,7 @@ class Frame_Header_Decoder(Module):
|
||||
|
||||
class Custom_Pixel_Gearbox(Module):
|
||||
def __init__(self, size):
|
||||
assert size in [8, 16]
|
||||
assert size in [8, 10, 16]
|
||||
|
||||
self.x_size = Signal(3*char_width)
|
||||
|
||||
@ -421,19 +421,19 @@ class Custom_Pixel_Gearbox(Module):
|
||||
# Control interface
|
||||
|
||||
reset_reg = Signal()
|
||||
level = Signal(max=shift_reg_size)
|
||||
we = Signal()
|
||||
re = Signal()
|
||||
self.level = Signal(max=shift_reg_size)
|
||||
self.w_cnt = Signal(max=shift_reg_size//sink_dw)
|
||||
self.r_cnt = Signal(max=shift_reg_size//source_dw)
|
||||
|
||||
self.sync += [
|
||||
If(reset_reg,
|
||||
level.eq(level.reset),
|
||||
self.level.eq(self.level.reset),
|
||||
).Else(
|
||||
If(we & ~re, level.eq(level + sink_dw)),
|
||||
If(~we & re, level.eq(level - source_dw)),
|
||||
If(we & re, level.eq(level + sink_dw - source_dw)),
|
||||
If(we & ~re, self.level.eq(self.level + sink_dw)),
|
||||
If(~we & re, self.level.eq(self.level - source_dw)),
|
||||
If(we & re, self.level.eq(self.level + sink_dw - source_dw)),
|
||||
),
|
||||
|
||||
If(reset_reg,
|
||||
@ -456,28 +456,81 @@ 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
|
||||
|
||||
# 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)
|
||||
|
||||
|
||||
self.submodules.fsm = fsm = FSM(reset_state="COPY")
|
||||
# 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(
|
||||
"COPY",
|
||||
"COPY_ALIGNED",
|
||||
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),
|
||||
re.eq((self.source.stb & self.source.ack)),
|
||||
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()
|
||||
fsm.act(
|
||||
"NEWLINE",
|
||||
self.source.stb.eq(1),
|
||||
reset_reg.eq(1),
|
||||
valid_stb.eq(1),
|
||||
self.source.stb.eq(1),
|
||||
NextState("COPY"),
|
||||
NextState("COPY_ALIGNED"),
|
||||
)
|
||||
|
||||
# Data path
|
||||
@ -533,7 +586,10 @@ class Frame_Deserializer(Module):
|
||||
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.comb += eol_inserter.source.connect(gearbox.sink)
|
||||
|
Loading…
Reference in New Issue
Block a user