rearrange code and remove datapath for now
This commit is contained in:
parent
22ea5b08b0
commit
fa509b3365
|
@ -1,74 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
from lib.sata.k7satagtx import SATAGTX
|
||||
|
||||
K28_5 = Signal(8, reset=0xBC)
|
||||
|
||||
class K7SATAPHY(Module):
|
||||
def __init__(self, pads, dw=16):
|
||||
self.sata_gtx = SATAGTX(pads)
|
||||
|
||||
self.sink = Sink([("d", dw)], True)
|
||||
self.source = Source([("d", dw)], True)
|
||||
|
||||
rx_chariscomma = self.sata_gtx.channel.rxchariscomma
|
||||
rx_chariscomma_d = Signal(dw//8)
|
||||
rx_data = self.sata_gtx.channel.rxdata
|
||||
|
||||
tx_charisk = self.sata_gtx.channel.txcharisk
|
||||
tx_data = self.sata_gtx.channel.txdata
|
||||
|
||||
# link ready (same chariscomma for N times) #FIXME see how to do it for SATA
|
||||
self.link_ready = Signal()
|
||||
link_ready_cnt = Signal(8, reset=16-1)
|
||||
self.sync.sata_rx += [
|
||||
If(rx_chariscomma != 0,
|
||||
If(rx_chariscomma == rx_chariscomma_d,
|
||||
If(~link_ready, link_ready_cnt.eq(link_ready_cnt-1))
|
||||
).Else(
|
||||
link_ready_cnt.eq(8-1)
|
||||
),
|
||||
rx_chariscomma_d.eq(rx_chariscomma)
|
||||
)
|
||||
]
|
||||
self.comb += self.link_ready.eq(link_ready_cnt==0)
|
||||
|
||||
# Send K28_5 on start of frame #FIXME see how to do it for SATA
|
||||
self.comb += [
|
||||
If(self.sink.sop,
|
||||
tx_charisk.eq(1),
|
||||
tx_data.eq(Cat(K28_5, self.sink.dat[8:]))
|
||||
).Else(
|
||||
tx_charisk.eq(0),
|
||||
tx_data.eq(self.sink.dat)
|
||||
),
|
||||
self.sink.ack.eq(1)
|
||||
]
|
||||
|
||||
# Realign rx data and drive source #FIXME see how to do it for SATA
|
||||
rx_data_r = Signal(dw)
|
||||
rx_chariscomma_r = Signal(dw//8)
|
||||
rx_data_realigned = Signal(dw)
|
||||
rx_chariscomma_realigned = Signal(dw)
|
||||
|
||||
self.sync += [
|
||||
rx_data_r.eq(rx_data),
|
||||
rx_chariscomma_r.eq(rx_chariscomma)
|
||||
]
|
||||
|
||||
cases = {}
|
||||
cases[1<<0] = [
|
||||
rx_data_realigned.eq(rx_data_r[0:dw]),
|
||||
rx_chariscomma_realigned.eq(rx_chariscomma_r[0:dw//8])
|
||||
]
|
||||
for i in range(1, dw//8):
|
||||
cases[1<<i] = [
|
||||
rx_data_realigned.eq(Cat(rx_data[8*i:dw], rx_data_r[0:8*i])),
|
||||
rx_chariscomma_realigned.eq(Cat(rx_chariscomma[i:dw//8], rx_chariscomma_r[0:i]))
|
||||
]
|
||||
self.comb += Case(rx_chariscomma_d, cases)
|
||||
|
||||
self.comb += [
|
||||
self.source.stb.eq(link_ready),
|
||||
self.source.sop.eq(rx_chariscomma_realigned != 0),
|
||||
self.source.dat.eq(rx_data_realigned)
|
||||
]
|
|
@ -0,0 +1,15 @@
|
|||
from migen.fhdl.std import *
|
||||
|
||||
from lib.sata.k7sataphy.std import *
|
||||
from lib.sata.k7sataphy.gtx import GTXE2_CHANNEL
|
||||
from lib.sata.k7sataphy.clocking import K7SATAPHYClocking
|
||||
|
||||
class K7SATAPHY(Module):
|
||||
def __init__(self, pads, dw=16):
|
||||
self.sink = Sink([("d", dw)], True)
|
||||
self.source = Source([("d", dw)], True)
|
||||
|
||||
self.submodules.gtx = GTXE2_CHANNEL(pads, "SATA3")
|
||||
self.submodules.clocking = K7SATAPHYClocking(pads, self.gtx)
|
||||
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
|
||||
class K7SATAPHYReconfig(Module):
|
||||
def __init__(self, channel_drp, mmcm_drp):
|
||||
self.speed = Signal(3)
|
||||
###
|
||||
speed_r = Signal(3)
|
||||
speed_change = Signal()
|
||||
self.sync += speed_r.eq(speed)
|
||||
self.comb += speed_change.eq(speed != speed_r)
|
||||
|
||||
drp_sel = Signal()
|
||||
drp = DRPBus()
|
||||
self.comb += \
|
||||
If(sel,
|
||||
Record.connect(drp, mmcm_drp),
|
||||
).Else(
|
||||
Record.connect(drp, channel_drp)
|
||||
)
|
||||
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
|
||||
# Todo
|
||||
fsm.act("IDLE",
|
||||
sel.eq(0),
|
||||
)
|
||||
|
||||
class K7SATAPHYClocking(Module):
|
||||
def __init__(self, pads, gtx):
|
||||
self.reset = Signal()
|
||||
self.transceiver_reset = Signal()
|
||||
|
||||
self.cd_sata_tx = ClockDomain()
|
||||
self.cd_sata_rx = ClockDomain()
|
||||
|
||||
# TX clocking
|
||||
refclk = Signal()
|
||||
self.specials += Instance("IBUFDS_GTE2",
|
||||
i_I=pads.refclk_p,
|
||||
i_IB=pads.refclk_n,
|
||||
o_O=refclk
|
||||
)
|
||||
mmcm_reset = Signal()
|
||||
mmcm_locked = Signal()
|
||||
mmcm_drp = DRP()
|
||||
mmcm_fb = Signal()
|
||||
mmcm_clk_i = Signal()
|
||||
mmcm_clk_o = Signal()
|
||||
self.specials += [
|
||||
Instance("BUFG", i_I=refclk, o_O=mmcm_clk_i),
|
||||
Instance("MMCME2_ADV",
|
||||
p_BANDWIDTH="HIGH", p_COMPENSATION="ZHOLD", i_RST=mmcm_reset, o_LOCKED=mmcm_locked,
|
||||
|
||||
# DRP
|
||||
i_DCLK=mmcm_drp.clk, i_DEN=mmcm_drp.den, o_DRDY=mmcm_drp.rdy, i_DWE=mmcm_drp.we,
|
||||
i_DADDR=mmcm_drp.addr, i_DI=mmcm_drp.di, i_DO=mmcm_drp.do,
|
||||
|
||||
# VCO
|
||||
p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=5.0,
|
||||
p_CLKFBOUT_MULT_F=8.000, CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=2,
|
||||
i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb,
|
||||
|
||||
# CLK0
|
||||
p_CLKOUT0_DIVIDE_F=4.000, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk_o,
|
||||
),
|
||||
Instance("BUFG", i_I=mmcm_clk_o, o_O=self.cd_sata_tx.clk),
|
||||
]
|
||||
|
||||
# RX clocking
|
||||
self.specials += [
|
||||
Instance("BUFG", i_I=gtx.rxoutclk, o_O=self.cd_sata_rx.clk),
|
||||
]
|
||||
self.comb += [
|
||||
gtx.rxusrclk.eq(self.cd_sata_rx.clk),
|
||||
gtx.rxusrclk2.eq(self.cd_sata_rx.clk)
|
||||
]
|
||||
|
||||
# TX buffer bypass logic
|
||||
self.comb += [
|
||||
self.txphdlyreset.eq(0),
|
||||
self.txphalignen.eq(0),
|
||||
self.txdlyen.eq(0),
|
||||
self.txphalign.eq(0),
|
||||
self.txphinit.eq(0)
|
||||
]
|
||||
|
||||
# once channel TX is reseted, reset TX buffer
|
||||
txbuffer_reseted = Signal()
|
||||
self.sync += \
|
||||
If(gtx.txresetdone,
|
||||
If(~txbuffer_reseted,
|
||||
gtx.txdlyreset.eq(1),
|
||||
txbuffer_reseted.eq(1)
|
||||
).Else(
|
||||
gtx.txdlyreset.eq(0)
|
||||
)
|
||||
)
|
||||
|
||||
# RX buffer bypass logic
|
||||
self.comb += [
|
||||
gtx.rxphdlyreset.eq(0),
|
||||
gtx.rxdlyen.eq(0),
|
||||
gtx.rxphalign.eq(0),
|
||||
gtx.rxphalignen.eq(0),
|
||||
]
|
||||
|
||||
# wait till CDR is locked
|
||||
cdr_cnt = Signal(14, reset=0b10011100010000)
|
||||
cdr_locked = Signal()
|
||||
self.sync += \
|
||||
If(cdr_cnt != 0,
|
||||
cdr_cnt.eq(cdr_cnt - 1)
|
||||
).Else(
|
||||
cdr_locked.eq(1)
|
||||
)
|
||||
|
||||
# once CDR is locked and channel RX reseted, reset RX buffer
|
||||
rxbuffer_reseted = Signal()
|
||||
self.sync += \
|
||||
If(cdr_locked & gtx.rxresetdone,
|
||||
If(~rxbuffer_reseted,
|
||||
gtx.rxdlyreset.eq(1),
|
||||
rxbuffer_reseted.eq(1)
|
||||
).Else(
|
||||
gtx.rxdlyreset.eq(0)
|
||||
)
|
||||
)
|
||||
|
||||
# Reset
|
||||
self.comb += [
|
||||
# GTXE2
|
||||
gtx.rxuserrdy.eq(gtx.cplllock),
|
||||
gtx.txuserrdy.eq(gtx.cplllock),
|
||||
# TX
|
||||
gtx.gttxreset.eq(self.reset | self.transceiver_reset | ~gtx.cplllock),
|
||||
# RX
|
||||
gtx.gtrxreset.eq(self.reset | self.transceiver_reset | ~gtx.cplllock),
|
||||
# PLL
|
||||
gtx.pllreset.eq(self.reset)
|
||||
]
|
||||
# SATA TX/RX clock domains
|
||||
self.specials += [
|
||||
AsyncResetSynchronizer(self.cd_sata_tx, ~mmcm_locked | ~gtx.txresetdone),
|
||||
AsyncResetSynchronizer(self.cd_sata_rx, ~gtx.cplllock | ~gtx.rxphaligndone),
|
||||
]
|
||||
|
||||
# Dynamic Reconfiguration
|
||||
self.submodules.reconfig = K7SATAPHYReconfig(mmcm_drp, gtx.drp)
|
|
@ -1,30 +1,10 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from migen.genlib.record import *
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
from migen.flow.actor import Sink, Source
|
||||
|
||||
_K28_5 = 0b1010000011
|
||||
|
||||
def _ones(width):
|
||||
return 2**width-1
|
||||
|
||||
class DRPBus(Record):
|
||||
def __init__(self):
|
||||
layout = [
|
||||
("clk", 1, DIR_M_TO_S),
|
||||
("en", 1, DIR_M_TO_S),
|
||||
("rdy", 1, DIR_S_TO_M),
|
||||
("we", 1, DIR_M_TO_S)
|
||||
("addr", 8, DIR_M_TO_S),
|
||||
("di", 16, DIR_M_TO_S),
|
||||
("do", 16, DIR_S_TO_M)
|
||||
]
|
||||
Record.__init__(self, layout)
|
||||
from lib.sata.k7sataphy.std import *
|
||||
|
||||
class GTXE2_CHANNEL(Module):
|
||||
def __init__(self, pads, default_speed="SATA3"):
|
||||
self.drp = DRP()
|
||||
self.drp = DRPBus()
|
||||
|
||||
# Channel
|
||||
self.qpllclk = Signal()
|
||||
|
@ -158,9 +138,9 @@ class GTXE2_CHANNEL(Module):
|
|||
p_ALIGN_COMMA_ENABLE=_ones(10),
|
||||
p_ALIGN_COMMA_WORD=2,
|
||||
p_ALIGN_MCOMMA_DET="TRUE",
|
||||
p_ALIGN_MCOMMA_VALUE=_K28_5,
|
||||
p_ALIGN_MCOMMA_VALUE=K28_5,
|
||||
p_ALIGN_PCOMMA_DET="TRUE",
|
||||
p_ALIGN_PCOMMA_VALUE=~_K28_5,
|
||||
p_ALIGN_PCOMMA_VALUE=~K28_5,
|
||||
p_SHOW_REALIGN_COMMA="FALSE",
|
||||
p_RXSLIDE_AUTO_WAIT=7,
|
||||
p_RXSLIDE_MODE="OFF",
|
||||
|
@ -779,154 +759,3 @@ class GTXE2_CHANNEL(Module):
|
|||
#o_TXQPISENN=,
|
||||
#o_TXQPISENP=
|
||||
)
|
||||
|
||||
class K7SATAGTXReconfig(Module):
|
||||
def __init__(self, channel_drp, mmcm_drp):
|
||||
self.speed = Signal(3)
|
||||
###
|
||||
speed_r = Signal(3)
|
||||
speed_change = Signal()
|
||||
self.sync += speed_r.eq(speed)
|
||||
self.comb += speed_change.eq(speed != speed_r)
|
||||
|
||||
drp_sel = Signal()
|
||||
drp = DRPBus()
|
||||
self.comb += \
|
||||
If(sel,
|
||||
Record.connect(drp, mmcm_drp),
|
||||
).Else(
|
||||
Record.connect(drp, channel_drp)
|
||||
)
|
||||
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
|
||||
# Todo
|
||||
fsm.act("IDLE",
|
||||
sel.eq(0),
|
||||
)
|
||||
|
||||
class K7SATAGTX(Module):
|
||||
def __init__(self, pads):
|
||||
self.reset = Signal()
|
||||
self.transceiver_reset = Signal()
|
||||
|
||||
self.cd_sata_tx = ClockDomain()
|
||||
self.cd_sata_rx = ClockDomain()
|
||||
|
||||
self.submodules.channel = GTXE2_CHANNEL(pads, "SATA3")
|
||||
|
||||
# TX clocking
|
||||
refclk = Signal()
|
||||
self.specials += Instance("IBUFDS_GTE2",
|
||||
i_I=pads.refclk_p,
|
||||
i_IB=pads.refclk_n,
|
||||
o_O=refclk
|
||||
)
|
||||
mmcm_reset = Signal()
|
||||
mmcm_locked = Signal()
|
||||
mmcm_drp = DRP()
|
||||
mmcm_fb = Signal()
|
||||
mmcm_clk_i = Signal()
|
||||
mmcm_clk_o = Signal()
|
||||
self.specials += [
|
||||
Instance("BUFG", i_I=refclk, o_O=mmcm_clk_i),
|
||||
Instance("MMCME2_ADV",
|
||||
p_BANDWIDTH="HIGH", p_COMPENSATION="ZHOLD", i_RST=mmcm_reset, o_LOCKED=mmcm_locked,
|
||||
|
||||
# DRP
|
||||
i_DCLK=mmcm_drp.clk, i_DEN=mmcm_drp.den, o_DRDY=mmcm_drp.rdy, i_DWE=mmcm_drp.we,
|
||||
i_DADDR=mmcm_drp.addr, i_DI=mmcm_drp.di, i_DO=mmcm_drp.do,
|
||||
|
||||
# VCO
|
||||
p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=5.0,
|
||||
p_CLKFBOUT_MULT_F=8.000, CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=2,
|
||||
i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb,
|
||||
|
||||
# CLK0
|
||||
p_CLKOUT0_DIVIDE_F=4.000, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk_o,
|
||||
),
|
||||
Instance("BUFG", i_I=mmcm_clk_o, o_O=self.cd_sata_tx.clk),
|
||||
]
|
||||
|
||||
# RX clocking
|
||||
self.specials += [
|
||||
Instance("BUFG", i_I=self.channel.rxoutclk, o_O=self.cd_sata_rx.clk),
|
||||
]
|
||||
self.comb += [
|
||||
self.channel.RXUSRCLK.eq(self.cd_sata_rx.clk),
|
||||
self.channel.RXUSRCLK2.eq(self.cd_sata_rx.clk)
|
||||
]
|
||||
|
||||
# TX buffer bypass logic
|
||||
self.comb += [
|
||||
self.txphdlyreset.eq(0),
|
||||
self.txphalignen.eq(0),
|
||||
self.txdlyen.eq(0),
|
||||
self.txphalign.eq(0),
|
||||
self.txphinit.eq(0)
|
||||
]
|
||||
|
||||
# once channel TX is reseted, reset TX buffer
|
||||
txbuffer_reseted = Signal()
|
||||
self.sync += \
|
||||
If(self.channel.txresetdone,
|
||||
If(~txbuffer_reseted,
|
||||
self.channel.txdlyreset.eq(1),
|
||||
txbuffer_reseted.eq(1)
|
||||
).Else(
|
||||
self.channel.txdlyreset.eq(0)
|
||||
)
|
||||
)
|
||||
|
||||
# RX buffer bypass logic
|
||||
self.comb += [
|
||||
self.channel.rxphdlyreset.eq(0),
|
||||
self.channel.rxdlyen.eq(0),
|
||||
self.channel.rxphalign.eq(0),
|
||||
self.channel.rxphalignen.eq(0),
|
||||
]
|
||||
|
||||
# wait till CDR is locked
|
||||
cdr_cnt = Signal(14, reset=0b10011100010000)
|
||||
cdr_locked = Signal()
|
||||
self.sync += \
|
||||
If(cdr_cnt != 0,
|
||||
cdr_cnt.eq(cdr_cnt - 1)
|
||||
).Else(
|
||||
cdr_locked.eq(1)
|
||||
)
|
||||
|
||||
# once CDR is locked and channel RX reseted, reset RX buffer
|
||||
rxbuffer_reseted = Signal()
|
||||
self.sync += \
|
||||
If(cdr_locked & self.channel.rxresetdone,
|
||||
If(~rxbuffer_reseted,
|
||||
self.channel.rxdlyreset.eq(1),
|
||||
rxbuffer_reseted.eq(1)
|
||||
).Else(
|
||||
self.channel.rxdlyreset.eq(0)
|
||||
)
|
||||
)
|
||||
|
||||
# Reset
|
||||
self.comb += [
|
||||
# GTXE2
|
||||
self.channel.rxuserrdy.eq(self.channel.cplllock),
|
||||
self.channel.txuserrdy.eq(self.channel.cplllock),
|
||||
# TX
|
||||
self.channel.gttxreset.eq(self.reset | self.transceiver_reset | ~self.channel.cplllock),
|
||||
# RX
|
||||
self.channel.gtrxreset.eq(self.reset | self.transceiver_reset | ~self.channel.cplllock),
|
||||
# PLL
|
||||
self.channel.pllreset.eq(self.reset)
|
||||
]
|
||||
# SATA TX/RX clock domains
|
||||
self.specials += [
|
||||
AsyncResetSynchronizer(self.cd_sata_tx, ~mmcm_locked | ~self.channel.txresetdone),
|
||||
AsyncResetSynchronizer(self.cd_sata_rx, ~self.channel.cplllock | ~self.channel.rxphaligndone),
|
||||
]
|
||||
|
||||
|
||||
# Dynamic Reconfiguration
|
||||
self.submodules.reconfig = K7SATAGTXReconfig(mmcm_drp, self.channel.drp)
|
|
@ -0,0 +1,19 @@
|
|||
from migen.fhdl.std import *
|
||||
|
||||
K28_5 = 0b1010000011
|
||||
|
||||
def _ones(width):
|
||||
return 2**width-1
|
||||
|
||||
class DRPBus(Record):
|
||||
def __init__(self):
|
||||
layout = [
|
||||
("clk", 1, DIR_M_TO_S),
|
||||
("en", 1, DIR_M_TO_S),
|
||||
("rdy", 1, DIR_S_TO_M),
|
||||
("we", 1, DIR_M_TO_S)
|
||||
("addr", 8, DIR_M_TO_S),
|
||||
("di", 16, DIR_M_TO_S),
|
||||
("do", 16, DIR_S_TO_M)
|
||||
]
|
||||
Record.__init__(self, layout)
|
Loading…
Reference in New Issue