from migen.bank.description import *
class LiteSATA(Module, AutoCSR):
- def __init__(self, phy, buffer_depth=2*fis_max_dwords,
- with_bist=False, with_bist_csr=False):
- # phy
- self.phy = phy
+ def __init__(self, phy, buffer_depth=2*fis_max_dwords,
+ with_bist=False, with_bist_csr=False):
+ # phy
+ self.phy = phy
- # core
- self.submodules.core = LiteSATACore(self.phy, buffer_depth)
+ # core
+ self.submodules.core = LiteSATACore(self.phy, buffer_depth)
- # frontend
- self.submodules.crossbar = LiteSATACrossbar(self.core)
- if with_bist:
- self.submodules.bist = LiteSATABIST(self.crossbar, with_bist_csr)
+ # frontend
+ self.submodules.crossbar = LiteSATACrossbar(self.core)
+ if with_bist:
+ self.submodules.bist = LiteSATABIST(self.crossbar, with_bist_csr)
from migen.actorlib.structuring import Pipeline, Converter
bitrates = {
- "sata_gen3" : 6.0,
- "sata_gen2" : 3.0,
- "sata_gen1" : 1.5,
+ "sata_gen3" : 6.0,
+ "sata_gen2" : 3.0,
+ "sata_gen1" : 1.5,
}
frequencies = {
- "sata_gen3" : 150.0,
- "sata_gen2" : 75.0,
- "sata_gen1" : 37.5,
+ "sata_gen3" : 150.0,
+ "sata_gen2" : 75.0,
+ "sata_gen1" : 37.5,
}
# PHY / Link Layers
primitives = {
- "ALIGN" : 0x7B4A4ABC,
- "CONT" : 0X9999AA7C,
- "SYNC" : 0xB5B5957C,
- "R_RDY" : 0x4A4A957C,
- "R_OK" : 0x3535B57C,
- "R_ERR" : 0x5656B57C,
- "R_IP" : 0X5555B57C,
- "X_RDY" : 0x5757B57C,
- "CONT" : 0x9999AA7C,
- "WTRM" : 0x5858B57C,
- "SOF" : 0x3737B57C,
- "EOF" : 0xD5D5B57C,
- "HOLD" : 0xD5D5AA7C,
- "HOLDA" : 0X9595AA7C
+ "ALIGN" : 0x7B4A4ABC,
+ "CONT" : 0X9999AA7C,
+ "SYNC" : 0xB5B5957C,
+ "R_RDY" : 0x4A4A957C,
+ "R_OK" : 0x3535B57C,
+ "R_ERR" : 0x5656B57C,
+ "R_IP" : 0X5555B57C,
+ "X_RDY" : 0x5757B57C,
+ "CONT" : 0x9999AA7C,
+ "WTRM" : 0x5858B57C,
+ "SOF" : 0x3737B57C,
+ "EOF" : 0xD5D5B57C,
+ "HOLD" : 0xD5D5AA7C,
+ "HOLDA" : 0X9595AA7C
}
def is_primitive(dword):
- for k, v in primitives.items():
- if dword == v:
- return True
- return False
+ for k, v in primitives.items():
+ if dword == v:
+ return True
+ return False
def decode_primitive(dword):
- for k, v in primitives.items():
- if dword == v:
- return k
- return ""
+ for k, v in primitives.items():
+ if dword == v:
+ return k
+ return ""
def phy_description(dw):
- layout = [
- ("data", dw),
- ("charisk", dw//8),
- ]
- return EndpointDescription(layout, packetized=False)
+ layout = [
+ ("data", dw),
+ ("charisk", dw//8),
+ ]
+ return EndpointDescription(layout, packetized=False)
def link_description(dw):
- layout = [
- ("d", dw),
- ("error", 1)
- ]
- return EndpointDescription(layout, packetized=True)
+ layout = [
+ ("d", dw),
+ ("error", 1)
+ ]
+ return EndpointDescription(layout, packetized=True)
# Transport Layer
fis_max_dwords = 2048
fis_types = {
- "REG_H2D": 0x27,
- "REG_D2H": 0x34,
- "DMA_ACTIVATE_D2H": 0x39,
- "PIO_SETUP_D2H": 0x5F,
- "DATA": 0x46
+ "REG_H2D": 0x27,
+ "REG_D2H": 0x34,
+ "DMA_ACTIVATE_D2H": 0x39,
+ "PIO_SETUP_D2H": 0x5F,
+ "DATA": 0x46
}
class FISField():
- def __init__(self, dword, offset, width):
- self.dword = dword
- self.offset = offset
- self.width = width
+ def __init__(self, dword, offset, width):
+ self.dword = dword
+ self.offset = offset
+ self.width = width
fis_reg_h2d_cmd_len = 5
fis_reg_h2d_layout = {
- "type": FISField(0, 0, 8),
- "pm_port": FISField(0, 8, 4),
- "c": FISField(0, 15, 1),
- "command": FISField(0, 16, 8),
- "features_lsb": FISField(0, 24, 8),
+ "type": FISField(0, 0, 8),
+ "pm_port": FISField(0, 8, 4),
+ "c": FISField(0, 15, 1),
+ "command": FISField(0, 16, 8),
+ "features_lsb": FISField(0, 24, 8),
- "lba_lsb": FISField(1, 0, 24),
- "device": FISField(1, 24, 8),
+ "lba_lsb": FISField(1, 0, 24),
+ "device": FISField(1, 24, 8),
- "lba_msb": FISField(2, 0, 24),
- "features_msb": FISField(2, 24, 8),
+ "lba_msb": FISField(2, 0, 24),
+ "features_msb": FISField(2, 24, 8),
- "count": FISField(3, 0, 16),
- "icc": FISField(3, 16, 8),
- "control": FISField(3, 24, 8)
+ "count": FISField(3, 0, 16),
+ "icc": FISField(3, 16, 8),
+ "control": FISField(3, 24, 8)
}
fis_reg_d2h_cmd_len = 5
fis_reg_d2h_layout = {
- "type": FISField(0, 0, 8),
- "pm_port": FISField(0, 8, 4),
- "i": FISField(0, 14, 1),
- "status": FISField(0, 16, 8),
- "error": FISField(0, 24, 8),
+ "type": FISField(0, 0, 8),
+ "pm_port": FISField(0, 8, 4),
+ "i": FISField(0, 14, 1),
+ "status": FISField(0, 16, 8),
+ "error": FISField(0, 24, 8),
- "lba_lsb": FISField(1, 0, 24),
- "device": FISField(1, 24, 8),
+ "lba_lsb": FISField(1, 0, 24),
+ "device": FISField(1, 24, 8),
- "lba_msb": FISField(2, 0, 24),
+ "lba_msb": FISField(2, 0, 24),
- "count": FISField(3, 0, 16)
+ "count": FISField(3, 0, 16)
}
fis_dma_activate_d2h_cmd_len = 1
fis_dma_activate_d2h_layout = {
- "type": FISField(0, 0, 8),
- "pm_port": FISField(0, 8, 4)
+ "type": FISField(0, 0, 8),
+ "pm_port": FISField(0, 8, 4)
}
fis_pio_setup_d2h_cmd_len = 5
fis_pio_setup_d2h_layout = {
- "type": FISField(0, 0, 8),
- "pm_port": FISField(0, 8, 4),
- "d": FISField(0, 13, 1),
- "i": FISField(0, 14, 1),
- "status": FISField(0, 16, 8),
- "error": FISField(0, 24, 8),
+ "type": FISField(0, 0, 8),
+ "pm_port": FISField(0, 8, 4),
+ "d": FISField(0, 13, 1),
+ "i": FISField(0, 14, 1),
+ "status": FISField(0, 16, 8),
+ "error": FISField(0, 24, 8),
- "lba_lsb": FISField(1, 0, 24),
+ "lba_lsb": FISField(1, 0, 24),
- "lba_msb": FISField(2, 0, 24),
+ "lba_msb": FISField(2, 0, 24),
- "count": FISField(3, 0, 16),
+ "count": FISField(3, 0, 16),
- "transfer_count": FISField(4, 0, 16),
+ "transfer_count": FISField(4, 0, 16),
}
fis_data_cmd_len = 1
fis_data_layout = {
- "type": FISField(0, 0, 8)
+ "type": FISField(0, 0, 8)
}
def transport_tx_description(dw):
- layout = [
- ("type", 8),
- ("pm_port", 4),
- ("c", 1),
- ("command", 8),
- ("features", 16),
- ("lba", 48),
- ("device", 8),
- ("count", 16),
- ("icc", 8),
- ("control", 8),
- ("data", dw)
- ]
- return EndpointDescription(layout, packetized=True)
+ layout = [
+ ("type", 8),
+ ("pm_port", 4),
+ ("c", 1),
+ ("command", 8),
+ ("features", 16),
+ ("lba", 48),
+ ("device", 8),
+ ("count", 16),
+ ("icc", 8),
+ ("control", 8),
+ ("data", dw)
+ ]
+ return EndpointDescription(layout, packetized=True)
def transport_rx_description(dw):
- layout = [
- ("type", 8),
- ("pm_port", 4),
- ("r", 1),
- ("d", 1),
- ("i", 1),
- ("status", 8),
- ("errors", 8),
- ("lba", 48),
- ("device", 8),
- ("count", 16),
- ("transfer_count", 16),
- ("data", dw),
- ("error", 1)
- ]
- return EndpointDescription(layout, packetized=True)
+ layout = [
+ ("type", 8),
+ ("pm_port", 4),
+ ("r", 1),
+ ("d", 1),
+ ("i", 1),
+ ("status", 8),
+ ("errors", 8),
+ ("lba", 48),
+ ("device", 8),
+ ("count", 16),
+ ("transfer_count", 16),
+ ("data", dw),
+ ("error", 1)
+ ]
+ return EndpointDescription(layout, packetized=True)
# Command Layer
regs = {
- "WRITE_DMA_EXT" : 0x35,
- "READ_DMA_EXT" : 0x25,
- "IDENTIFY_DEVICE" : 0xEC
+ "WRITE_DMA_EXT" : 0x35,
+ "READ_DMA_EXT" : 0x25,
+ "IDENTIFY_DEVICE" : 0xEC
}
reg_d2h_status = {
- "bsy" : 7,
- "drdy" : 6,
- "df" : 5,
- "se" : 5,
- "dwe" : 4,
- "drq" : 3,
- "ae" : 2,
- "sns" : 1,
- "cc" : 0,
- "err" : 0
+ "bsy" : 7,
+ "drdy" : 6,
+ "df" : 5,
+ "se" : 5,
+ "dwe" : 4,
+ "drq" : 3,
+ "ae" : 2,
+ "sns" : 1,
+ "cc" : 0,
+ "err" : 0
}
def command_tx_description(dw):
- layout = [
- ("write", 1),
- ("read", 1),
- ("identify", 1),
- ("sector", 48),
- ("count", 16),
- ("data", dw)
- ]
- return EndpointDescription(layout, packetized=True)
+ layout = [
+ ("write", 1),
+ ("read", 1),
+ ("identify", 1),
+ ("sector", 48),
+ ("count", 16),
+ ("data", dw)
+ ]
+ return EndpointDescription(layout, packetized=True)
def command_rx_description(dw):
- layout = [
- ("write", 1),
- ("read", 1),
- ("identify", 1),
- ("last", 1),
- ("failed", 1),
- ("data", dw)
- ]
- return EndpointDescription(layout, packetized=True)
+ layout = [
+ ("write", 1),
+ ("read", 1),
+ ("identify", 1),
+ ("last", 1),
+ ("failed", 1),
+ ("data", dw)
+ ]
+ return EndpointDescription(layout, packetized=True)
def command_rx_cmd_description(dw):
- layout = [
- ("write", 1),
- ("read", 1),
- ("identify", 1),
- ("last", 1),
- ("failed", 1)
- ]
- return EndpointDescription(layout, packetized=False)
+ layout = [
+ ("write", 1),
+ ("read", 1),
+ ("identify", 1),
+ ("last", 1),
+ ("failed", 1)
+ ]
+ return EndpointDescription(layout, packetized=False)
def command_rx_data_description(dw):
- layout = [
- ("data", dw)
- ]
- return EndpointDescription(layout, packetized=True)
+ layout = [
+ ("data", dw)
+ ]
+ return EndpointDescription(layout, packetized=True)
# HDD
logical_sector_size = 512 # constant since all HDDs use this
def dwords2sectors(n):
- return math.ceil(n*4/logical_sector_size)
+ return math.ceil(n*4/logical_sector_size)
def sectors2dwords(n):
- return n*logical_sector_size//4
+ return n*logical_sector_size//4
# Generic modules
class BufferizeEndpoints(ModuleTransformer):
- def __init__(self, *names):
- self.names = names
-
- def transform_instance(self, submodule):
- endpoints = get_endpoints(submodule)
- sinks = {}
- sources = {}
- for name, endpoint in endpoints.items():
- if not self.names or name in self.names:
- if isinstance(endpoint, Sink):
- sinks.update({name : endpoint})
- elif isinstance(endpoint, Source):
- sources.update({name : endpoint})
-
- # add buffer on sinks
- for name, sink in sinks.items():
- buf = Buffer(sink.description)
- submodule.submodules += buf
- setattr(self, name, buf.d)
- submodule.comb += Record.connect(buf.q, sink)
-
- # add buffer on sources
- for name, source in sources.items():
- buf = Buffer(source.description)
- submodule.submodules += buf
- submodule.comb += Record.connect(source, buf.d)
- setattr(self, name, buf.q)
+ def __init__(self, *names):
+ self.names = names
+
+ def transform_instance(self, submodule):
+ endpoints = get_endpoints(submodule)
+ sinks = {}
+ sources = {}
+ for name, endpoint in endpoints.items():
+ if not self.names or name in self.names:
+ if isinstance(endpoint, Sink):
+ sinks.update({name : endpoint})
+ elif isinstance(endpoint, Source):
+ sources.update({name : endpoint})
+
+ # add buffer on sinks
+ for name, sink in sinks.items():
+ buf = Buffer(sink.description)
+ submodule.submodules += buf
+ setattr(self, name, buf.d)
+ submodule.comb += Record.connect(buf.q, sink)
+
+ # add buffer on sources
+ for name, source in sources.items():
+ buf = Buffer(source.description)
+ submodule.submodules += buf
+ submodule.comb += Record.connect(source, buf.d)
+ setattr(self, name, buf.q)
class EndpointPacketStatus(Module):
- def __init__(self, endpoint):
- self.start = Signal()
- self.done = Signal()
- self.ongoing = Signal()
-
- ongoing = Signal()
- self.comb += [
- self.start.eq(endpoint.stb & endpoint.sop & endpoint.ack),
- self.done.eq(endpoint.stb & endpoint.eop & endpoint.ack)
- ]
- self.sync += \
- If(self.start,
- ongoing.eq(1)
- ).Elif(self.done,
- ongoing.eq(0)
- )
- self.comb += self.ongoing.eq((self.start | ongoing) & ~self.done)
+ def __init__(self, endpoint):
+ self.start = Signal()
+ self.done = Signal()
+ self.ongoing = Signal()
+
+ ongoing = Signal()
+ self.comb += [
+ self.start.eq(endpoint.stb & endpoint.sop & endpoint.ack),
+ self.done.eq(endpoint.stb & endpoint.eop & endpoint.ack)
+ ]
+ self.sync += \
+ If(self.start,
+ ongoing.eq(1)
+ ).Elif(self.done,
+ ongoing.eq(0)
+ )
+ self.comb += self.ongoing.eq((self.start | ongoing) & ~self.done)
class PacketBuffer(Module):
- def __init__(self, description, data_depth, cmd_depth=4, almost_full=None):
- self.sink = sink = Sink(description)
- self.source = source = Source(description)
-
- ###
- sink_status = EndpointPacketStatus(self.sink)
- source_status = EndpointPacketStatus(self.source)
- self.submodules += sink_status, source_status
-
- # store incoming packets
- # cmds
- def cmd_description():
- layout = [("error", 1)]
- return EndpointDescription(layout)
- cmd_fifo = SyncFIFO(cmd_description(), cmd_depth)
- self.submodules += cmd_fifo
- self.comb += [
- cmd_fifo.sink.stb.eq(sink_status.done),
- cmd_fifo.sink.error.eq(sink.error)
- ]
-
- # data
- data_fifo = SyncFIFO(description, data_depth, buffered=True)
- self.submodules += data_fifo
- self.comb += [
- Record.connect(self.sink, data_fifo.sink),
- data_fifo.sink.stb.eq(self.sink.stb & cmd_fifo.sink.ack),
- self.sink.ack.eq(data_fifo.sink.ack & cmd_fifo.sink.ack),
- ]
-
- # output packets
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- If(cmd_fifo.source.stb,
- NextState("SEEK_SOP")
- )
- )
- fsm.act("SEEK_SOP",
- If(~data_fifo.source.sop,
- data_fifo.source.ack.eq(1)
- ).Else(
- NextState("OUTPUT")
- )
- )
- fsm.act("OUTPUT",
- Record.connect(data_fifo.source, self.source),
- self.source.error.eq(cmd_fifo.source.error),
- If(source_status.done,
- cmd_fifo.source.ack.eq(1),
- NextState("IDLE")
- )
- )
-
- # compute almost full
- if almost_full is not None:
- self.almost_full = Signal()
- self.comb += self.almost_full.eq(data_fifo.fifo.level > almost_full)
+ def __init__(self, description, data_depth, cmd_depth=4, almost_full=None):
+ self.sink = sink = Sink(description)
+ self.source = source = Source(description)
+
+ ###
+ sink_status = EndpointPacketStatus(self.sink)
+ source_status = EndpointPacketStatus(self.source)
+ self.submodules += sink_status, source_status
+
+ # store incoming packets
+ # cmds
+ def cmd_description():
+ layout = [("error", 1)]
+ return EndpointDescription(layout)
+ cmd_fifo = SyncFIFO(cmd_description(), cmd_depth)
+ self.submodules += cmd_fifo
+ self.comb += [
+ cmd_fifo.sink.stb.eq(sink_status.done),
+ cmd_fifo.sink.error.eq(sink.error)
+ ]
+
+ # data
+ data_fifo = SyncFIFO(description, data_depth, buffered=True)
+ self.submodules += data_fifo
+ self.comb += [
+ Record.connect(self.sink, data_fifo.sink),
+ data_fifo.sink.stb.eq(self.sink.stb & cmd_fifo.sink.ack),
+ self.sink.ack.eq(data_fifo.sink.ack & cmd_fifo.sink.ack),
+ ]
+
+ # output packets
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ If(cmd_fifo.source.stb,
+ NextState("SEEK_SOP")
+ )
+ )
+ fsm.act("SEEK_SOP",
+ If(~data_fifo.source.sop,
+ data_fifo.source.ack.eq(1)
+ ).Else(
+ NextState("OUTPUT")
+ )
+ )
+ fsm.act("OUTPUT",
+ Record.connect(data_fifo.source, self.source),
+ self.source.error.eq(cmd_fifo.source.error),
+ If(source_status.done,
+ cmd_fifo.source.ack.eq(1),
+ NextState("IDLE")
+ )
+ )
+
+ # compute almost full
+ if almost_full is not None:
+ self.almost_full = Signal()
+ self.comb += self.almost_full.eq(data_fifo.fifo.level > almost_full)
from misoclib.mem.litesata.core.command import LiteSATACommand
class LiteSATACore(Module):
- def __init__(self, phy, buffer_depth):
- self.submodules.link = LiteSATALink(phy, buffer_depth)
- self.submodules.transport = LiteSATATransport(self.link)
- self.submodules.command = LiteSATACommand(self.transport)
- self.sink, self.source = self.command.sink, self.command.source
+ def __init__(self, phy, buffer_depth):
+ self.submodules.link = LiteSATALink(phy, buffer_depth)
+ self.submodules.transport = LiteSATATransport(self.link)
+ self.submodules.command = LiteSATACommand(self.transport)
+ self.sink, self.source = self.command.sink, self.command.source
from misoclib.mem.litesata.common import *
tx_to_rx = [
- ("write", 1),
- ("read", 1),
- ("identify", 1),
- ("count", 16)
+ ("write", 1),
+ ("read", 1),
+ ("identify", 1),
+ ("count", 16)
]
rx_to_tx = [
- ("dma_activate", 1),
- ("d2h_error", 1)
+ ("dma_activate", 1),
+ ("d2h_error", 1)
]
class LiteSATACommandTX(Module):
- def __init__(self, transport):
- self.sink = sink = Sink(command_tx_description(32))
- self.to_rx = to_rx = Source(tx_to_rx)
- self.from_rx = from_rx = Sink(rx_to_tx)
+ def __init__(self, transport):
+ self.sink = sink = Sink(command_tx_description(32))
+ self.to_rx = to_rx = Source(tx_to_rx)
+ self.from_rx = from_rx = Sink(rx_to_tx)
- ###
+ ###
- self.comb += [
- transport.sink.pm_port.eq(0),
- transport.sink.features.eq(0),
- transport.sink.lba.eq(sink.sector),
- transport.sink.device.eq(0xe0),
- transport.sink.count.eq(sink.count),
- transport.sink.icc.eq(0),
- transport.sink.control.eq(0),
- transport.sink.data.eq(sink.data)
- ]
+ self.comb += [
+ transport.sink.pm_port.eq(0),
+ transport.sink.features.eq(0),
+ transport.sink.lba.eq(sink.sector),
+ transport.sink.device.eq(0xe0),
+ transport.sink.count.eq(sink.count),
+ transport.sink.icc.eq(0),
+ transport.sink.control.eq(0),
+ transport.sink.data.eq(sink.data)
+ ]
- dwords_counter = Counter(max=fis_max_dwords)
- self.submodules += dwords_counter
+ dwords_counter = Counter(max=fis_max_dwords)
+ self.submodules += dwords_counter
- is_write = Signal()
- is_read = Signal()
- is_identify = Signal()
+ is_write = Signal()
+ is_read = Signal()
+ is_identify = Signal()
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- sink.ack.eq(0),
- If(sink.stb & sink.sop,
- NextState("SEND_CMD")
- ).Else(
- sink.ack.eq(1)
- )
- )
- self.sync += \
- If(fsm.ongoing("IDLE"),
- is_write.eq(sink.write),
- is_read.eq(sink.read),
- is_identify.eq(sink.identify),
- )
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ sink.ack.eq(0),
+ If(sink.stb & sink.sop,
+ NextState("SEND_CMD")
+ ).Else(
+ sink.ack.eq(1)
+ )
+ )
+ self.sync += \
+ If(fsm.ongoing("IDLE"),
+ is_write.eq(sink.write),
+ is_read.eq(sink.read),
+ is_identify.eq(sink.identify),
+ )
- fsm.act("SEND_CMD",
- transport.sink.stb.eq(sink.stb),
- transport.sink.sop.eq(1),
- transport.sink.eop.eq(1),
- transport.sink.c.eq(1),
- If(transport.sink.stb & transport.sink.ack,
- If(is_write,
- NextState("WAIT_DMA_ACTIVATE")
- ).Else(
- sink.ack.eq(1),
- NextState("IDLE")
- )
- )
- )
- fsm.act("WAIT_DMA_ACTIVATE",
- dwords_counter.reset.eq(1),
- If(from_rx.dma_activate,
- NextState("SEND_DATA")
- ).Elif(from_rx.d2h_error,
- sink.ack.eq(1),
- NextState("IDLE")
- )
- )
- fsm.act("SEND_DATA",
- dwords_counter.ce.eq(sink.stb & sink.ack),
+ fsm.act("SEND_CMD",
+ transport.sink.stb.eq(sink.stb),
+ transport.sink.sop.eq(1),
+ transport.sink.eop.eq(1),
+ transport.sink.c.eq(1),
+ If(transport.sink.stb & transport.sink.ack,
+ If(is_write,
+ NextState("WAIT_DMA_ACTIVATE")
+ ).Else(
+ sink.ack.eq(1),
+ NextState("IDLE")
+ )
+ )
+ )
+ fsm.act("WAIT_DMA_ACTIVATE",
+ dwords_counter.reset.eq(1),
+ If(from_rx.dma_activate,
+ NextState("SEND_DATA")
+ ).Elif(from_rx.d2h_error,
+ sink.ack.eq(1),
+ NextState("IDLE")
+ )
+ )
+ fsm.act("SEND_DATA",
+ dwords_counter.ce.eq(sink.stb & sink.ack),
- transport.sink.stb.eq(sink.stb),
- transport.sink.sop.eq(dwords_counter.value == 0),
- transport.sink.eop.eq((dwords_counter.value == (fis_max_dwords-1)) | sink.eop),
+ transport.sink.stb.eq(sink.stb),
+ transport.sink.sop.eq(dwords_counter.value == 0),
+ transport.sink.eop.eq((dwords_counter.value == (fis_max_dwords-1)) | sink.eop),
- sink.ack.eq(transport.sink.ack),
- If(sink.stb & sink.ack,
- If(sink.eop,
- NextState("IDLE")
- ).Elif(dwords_counter.value == (fis_max_dwords-1),
- NextState("WAIT_DMA_ACTIVATE")
- )
- )
- )
- self.comb += \
- If(fsm.ongoing("SEND_DATA"),
- transport.sink.type.eq(fis_types["DATA"]),
- ).Else(
- transport.sink.type.eq(fis_types["REG_H2D"]),
- If(is_write,
- transport.sink.command.eq(regs["WRITE_DMA_EXT"])
- ).Elif(is_read,
- transport.sink.command.eq(regs["READ_DMA_EXT"]),
- ).Else(
- transport.sink.command.eq(regs["IDENTIFY_DEVICE"]),
- )
- )
- self.comb += [
- If(sink.stb,
- to_rx.write.eq(sink.write),
- to_rx.read.eq(sink.read),
- to_rx.identify.eq(sink.identify),
- to_rx.count.eq(sink.count)
- )
- ]
+ sink.ack.eq(transport.sink.ack),
+ If(sink.stb & sink.ack,
+ If(sink.eop,
+ NextState("IDLE")
+ ).Elif(dwords_counter.value == (fis_max_dwords-1),
+ NextState("WAIT_DMA_ACTIVATE")
+ )
+ )
+ )
+ self.comb += \
+ If(fsm.ongoing("SEND_DATA"),
+ transport.sink.type.eq(fis_types["DATA"]),
+ ).Else(
+ transport.sink.type.eq(fis_types["REG_H2D"]),
+ If(is_write,
+ transport.sink.command.eq(regs["WRITE_DMA_EXT"])
+ ).Elif(is_read,
+ transport.sink.command.eq(regs["READ_DMA_EXT"]),
+ ).Else(
+ transport.sink.command.eq(regs["IDENTIFY_DEVICE"]),
+ )
+ )
+ self.comb += [
+ If(sink.stb,
+ to_rx.write.eq(sink.write),
+ to_rx.read.eq(sink.read),
+ to_rx.identify.eq(sink.identify),
+ to_rx.count.eq(sink.count)
+ )
+ ]
class LiteSATACommandRX(Module):
- def __init__(self, transport):
- self.source = source = Source(command_rx_description(32))
- self.to_tx = to_tx = Source(rx_to_tx)
- self.from_tx = from_tx = Sink(tx_to_rx)
+ def __init__(self, transport):
+ self.source = source = Source(command_rx_description(32))
+ self.to_tx = to_tx = Source(rx_to_tx)
+ self.from_tx = from_tx = Sink(tx_to_rx)
- ###
+ ###
- def test_type(name):
- return transport.source.type == fis_types[name]
+ def test_type(name):
+ return transport.source.type == fis_types[name]
- is_identify = Signal()
- is_dma_activate = Signal()
- read_ndwords = Signal(max=sectors2dwords(2**16))
- dwords_counter = Counter(max=sectors2dwords(2**16))
- self.submodules += dwords_counter
- read_done = Signal()
+ is_identify = Signal()
+ is_dma_activate = Signal()
+ read_ndwords = Signal(max=sectors2dwords(2**16))
+ dwords_counter = Counter(max=sectors2dwords(2**16))
+ self.submodules += dwords_counter
+ read_done = Signal()
- self.sync += \
- If(from_tx.read,
- read_ndwords.eq(from_tx.count*sectors2dwords(1)-1)
- )
- self.comb += read_done.eq(dwords_counter.value == read_ndwords)
+ self.sync += \
+ If(from_tx.read,
+ read_ndwords.eq(from_tx.count*sectors2dwords(1)-1)
+ )
+ self.comb += read_done.eq(dwords_counter.value == read_ndwords)
- d2h_error = Signal()
- clr_d2h_error = Signal()
- set_d2h_error = Signal()
- self.sync += \
- If(clr_d2h_error,
- d2h_error.eq(0)
- ).Elif(set_d2h_error,
- d2h_error.eq(1)
- )
+ d2h_error = Signal()
+ clr_d2h_error = Signal()
+ set_d2h_error = Signal()
+ self.sync += \
+ If(clr_d2h_error,
+ d2h_error.eq(0)
+ ).Elif(set_d2h_error,
+ d2h_error.eq(1)
+ )
- read_error = Signal()
- clr_read_error = Signal()
- set_read_error = Signal()
- self.sync += \
- If(clr_read_error,
- read_error.eq(0)
- ).Elif(set_read_error,
- read_error.eq(1)
- )
+ read_error = Signal()
+ clr_read_error = Signal()
+ set_read_error = Signal()
+ self.sync += \
+ If(clr_read_error,
+ read_error.eq(0)
+ ).Elif(set_read_error,
+ read_error.eq(1)
+ )
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- dwords_counter.reset.eq(1),
- transport.source.ack.eq(1),
- clr_d2h_error.eq(1),
- clr_read_error.eq(1),
- If(from_tx.write,
- NextState("WAIT_WRITE_ACTIVATE_OR_REG_D2H")
- ).Elif(from_tx.read,
- NextState("WAIT_READ_DATA_OR_REG_D2H"),
- ).Elif(from_tx.identify,
- NextState("WAIT_PIO_SETUP_D2H"),
- )
- )
- self.sync += \
- If(fsm.ongoing("IDLE"),
- is_identify.eq(from_tx.identify)
- )
- fsm.act("WAIT_WRITE_ACTIVATE_OR_REG_D2H",
- transport.source.ack.eq(1),
- If(transport.source.stb,
- If(test_type("DMA_ACTIVATE_D2H"),
- is_dma_activate.eq(1),
- ).Elif(test_type("REG_D2H"),
- set_d2h_error.eq(transport.source.status[reg_d2h_status["err"]]),
- NextState("PRESENT_WRITE_RESPONSE")
- )
- )
- )
- fsm.act("PRESENT_WRITE_RESPONSE",
- source.stb.eq(1),
- source.sop.eq(1),
- source.eop.eq(1),
- source.write.eq(1),
- source.last.eq(1),
- source.failed.eq(transport.source.error | d2h_error),
- If(source.stb & source.ack,
- NextState("IDLE")
- )
- )
- fsm.act("WAIT_READ_DATA_OR_REG_D2H",
- transport.source.ack.eq(1),
- If(transport.source.stb,
- transport.source.ack.eq(0),
- If(test_type("DATA"),
- NextState("PRESENT_READ_DATA")
- ).Elif(test_type("REG_D2H"),
- NextState("PRESENT_READ_RESPONSE")
- )
- )
- )
- fsm.act("WAIT_PIO_SETUP_D2H",
- transport.source.ack.eq(1),
- If(transport.source.stb,
- transport.source.ack.eq(0),
- If(test_type("PIO_SETUP_D2H"),
- NextState("PRESENT_PIO_SETUP_D2H")
- )
- )
- )
- fsm.act("PRESENT_PIO_SETUP_D2H",
- transport.source.ack.eq(1),
- If(transport.source.stb & transport.source.eop,
- NextState("WAIT_READ_DATA_OR_REG_D2H")
- )
- )
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ dwords_counter.reset.eq(1),
+ transport.source.ack.eq(1),
+ clr_d2h_error.eq(1),
+ clr_read_error.eq(1),
+ If(from_tx.write,
+ NextState("WAIT_WRITE_ACTIVATE_OR_REG_D2H")
+ ).Elif(from_tx.read,
+ NextState("WAIT_READ_DATA_OR_REG_D2H"),
+ ).Elif(from_tx.identify,
+ NextState("WAIT_PIO_SETUP_D2H"),
+ )
+ )
+ self.sync += \
+ If(fsm.ongoing("IDLE"),
+ is_identify.eq(from_tx.identify)
+ )
+ fsm.act("WAIT_WRITE_ACTIVATE_OR_REG_D2H",
+ transport.source.ack.eq(1),
+ If(transport.source.stb,
+ If(test_type("DMA_ACTIVATE_D2H"),
+ is_dma_activate.eq(1),
+ ).Elif(test_type("REG_D2H"),
+ set_d2h_error.eq(transport.source.status[reg_d2h_status["err"]]),
+ NextState("PRESENT_WRITE_RESPONSE")
+ )
+ )
+ )
+ fsm.act("PRESENT_WRITE_RESPONSE",
+ source.stb.eq(1),
+ source.sop.eq(1),
+ source.eop.eq(1),
+ source.write.eq(1),
+ source.last.eq(1),
+ source.failed.eq(transport.source.error | d2h_error),
+ If(source.stb & source.ack,
+ NextState("IDLE")
+ )
+ )
+ fsm.act("WAIT_READ_DATA_OR_REG_D2H",
+ transport.source.ack.eq(1),
+ If(transport.source.stb,
+ transport.source.ack.eq(0),
+ If(test_type("DATA"),
+ NextState("PRESENT_READ_DATA")
+ ).Elif(test_type("REG_D2H"),
+ NextState("PRESENT_READ_RESPONSE")
+ )
+ )
+ )
+ fsm.act("WAIT_PIO_SETUP_D2H",
+ transport.source.ack.eq(1),
+ If(transport.source.stb,
+ transport.source.ack.eq(0),
+ If(test_type("PIO_SETUP_D2H"),
+ NextState("PRESENT_PIO_SETUP_D2H")
+ )
+ )
+ )
+ fsm.act("PRESENT_PIO_SETUP_D2H",
+ transport.source.ack.eq(1),
+ If(transport.source.stb & transport.source.eop,
+ NextState("WAIT_READ_DATA_OR_REG_D2H")
+ )
+ )
- fsm.act("PRESENT_READ_DATA",
- set_read_error.eq(transport.source.error),
- source.stb.eq(transport.source.stb),
- source.sop.eq(transport.source.sop),
- source.eop.eq(transport.source.eop),
- source.read.eq(~is_identify),
- source.identify.eq(is_identify),
- source.failed.eq(transport.source.error),
- source.last.eq(is_identify),
- source.data.eq(transport.source.data),
- transport.source.ack.eq(source.ack),
- If(source.stb & source.ack,
- dwords_counter.ce.eq(~read_done),
- If(source.eop,
- If(is_identify,
- NextState("IDLE")
- ).Else(
- NextState("WAIT_READ_DATA_OR_REG_D2H")
- )
- )
- )
- )
+ fsm.act("PRESENT_READ_DATA",
+ set_read_error.eq(transport.source.error),
+ source.stb.eq(transport.source.stb),
+ source.sop.eq(transport.source.sop),
+ source.eop.eq(transport.source.eop),
+ source.read.eq(~is_identify),
+ source.identify.eq(is_identify),
+ source.failed.eq(transport.source.error),
+ source.last.eq(is_identify),
+ source.data.eq(transport.source.data),
+ transport.source.ack.eq(source.ack),
+ If(source.stb & source.ack,
+ dwords_counter.ce.eq(~read_done),
+ If(source.eop,
+ If(is_identify,
+ NextState("IDLE")
+ ).Else(
+ NextState("WAIT_READ_DATA_OR_REG_D2H")
+ )
+ )
+ )
+ )
- fsm.act("PRESENT_READ_RESPONSE",
- source.stb.eq(1),
- source.sop.eq(1),
- source.eop.eq(1),
- source.read.eq(1),
- source.last.eq(1),
- source.failed.eq(~read_done | read_error | d2h_error),
- If(source.stb & source.ack,
- NextState("IDLE")
- )
- )
+ fsm.act("PRESENT_READ_RESPONSE",
+ source.stb.eq(1),
+ source.sop.eq(1),
+ source.eop.eq(1),
+ source.read.eq(1),
+ source.last.eq(1),
+ source.failed.eq(~read_done | read_error | d2h_error),
+ If(source.stb & source.ack,
+ NextState("IDLE")
+ )
+ )
- self.comb += [
- to_tx.dma_activate.eq(is_dma_activate),
- to_tx.d2h_error.eq(d2h_error)
- ]
+ self.comb += [
+ to_tx.dma_activate.eq(is_dma_activate),
+ to_tx.d2h_error.eq(d2h_error)
+ ]
class LiteSATACommand(Module):
- def __init__(self, transport):
- self.submodules.tx = LiteSATACommandTX(transport)
- self.submodules.rx = LiteSATACommandRX(transport)
- self.comb += [
- self.rx.to_tx.connect(self.tx.from_rx),
- self.tx.to_rx.connect(self.rx.from_tx)
- ]
- self.sink, self.source = self.tx.sink, self.rx.source
+ def __init__(self, transport):
+ self.submodules.tx = LiteSATACommandTX(transport)
+ self.submodules.rx = LiteSATACommandRX(transport)
+ self.comb += [
+ self.rx.to_tx.connect(self.tx.from_rx),
+ self.tx.to_rx.connect(self.rx.from_tx)
+ ]
+ self.sink, self.source = self.tx.sink, self.rx.source
from misoclib.mem.litesata.core.link.cont import LiteSATACONTInserter, LiteSATACONTRemover
from_rx = [
- ("idle", 1),
- ("insert", 32),
- ("det", 32)
+ ("idle", 1),
+ ("insert", 32),
+ ("det", 32)
]
class LiteSATALinkTX(Module):
- def __init__(self, phy):
- self.sink = Sink(link_description(32))
- self.from_rx = Sink(from_rx)
-
- ###
-
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
-
- # insert CRC
- crc = LiteSATACRCInserter(link_description(32))
- self.submodules += crc
-
- # scramble
- scrambler = LiteSATAScrambler(link_description(32))
- self.submodules += scrambler
-
- # connect CRC / scrambler
- self.comb += [
- Record.connect(self.sink, crc.sink),
- Record.connect(crc.source, scrambler.sink)
- ]
-
- # inserter CONT and scrambled data between
- # CONT and next primitive
- cont = BufferizeEndpoints("source")(LiteSATACONTInserter(phy_description(32)))
- self.submodules += cont
-
- # datas / primitives mux
- insert = Signal(32)
- self.comb += [
- If(self.from_rx.insert,
- cont.sink.stb.eq(1),
- cont.sink.data.eq(self.from_rx.insert),
- cont.sink.charisk.eq(0x0001),
- ).
- Elif(insert,
- cont.sink.stb.eq(1),
- cont.sink.data.eq(insert),
- cont.sink.charisk.eq(0x0001),
- ).Elif(fsm.ongoing("COPY"),
- cont.sink.stb.eq(scrambler.source.stb),
- cont.sink.data.eq(scrambler.source.d),
- scrambler.source.ack.eq(cont.sink.ack),
- cont.sink.charisk.eq(0)
- )
- ]
- self.comb += Record.connect(cont.source, phy.sink)
-
- # FSM
- fsm.act("IDLE",
- scrambler.reset.eq(1),
- If(self.from_rx.idle,
- insert.eq(primitives["SYNC"]),
- If(scrambler.source.stb & scrambler.source.sop,
- If(self.from_rx.det == primitives["SYNC"],
- NextState("RDY")
- )
- )
- )
- )
- fsm.act("RDY",
- insert.eq(primitives["X_RDY"]),
- If(~self.from_rx.idle,
- NextState("IDLE")
- ).Elif(self.from_rx.det == primitives["R_RDY"],
- NextState("SOF")
- )
- )
- fsm.act("SOF",
- insert.eq(primitives["SOF"]),
- If(phy.sink.ack,
- NextState("COPY")
- )
- )
- fsm.act("COPY",
- If(self.from_rx.det == primitives["HOLD"],
- insert.eq(primitives["HOLDA"]),
- ).Elif(~scrambler.source.stb,
- insert.eq(primitives["HOLD"]),
- ).Elif(scrambler.source.stb & scrambler.source.eop & scrambler.source.ack,
- NextState("EOF")
- )
- )
- fsm.act("EOF",
- insert.eq(primitives["EOF"]),
- If(phy.sink.ack,
- NextState("WTRM")
- )
- )
- fsm.act("WTRM",
- insert.eq(primitives["WTRM"]),
- If(self.from_rx.det == primitives["R_OK"],
- NextState("IDLE")
- ).Elif(self.from_rx.det == primitives["R_ERR"],
- NextState("IDLE")
- )
- )
+ def __init__(self, phy):
+ self.sink = Sink(link_description(32))
+ self.from_rx = Sink(from_rx)
+
+ ###
+
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+
+ # insert CRC
+ crc = LiteSATACRCInserter(link_description(32))
+ self.submodules += crc
+
+ # scramble
+ scrambler = LiteSATAScrambler(link_description(32))
+ self.submodules += scrambler
+
+ # connect CRC / scrambler
+ self.comb += [
+ Record.connect(self.sink, crc.sink),
+ Record.connect(crc.source, scrambler.sink)
+ ]
+
+ # inserter CONT and scrambled data between
+ # CONT and next primitive
+ cont = BufferizeEndpoints("source")(LiteSATACONTInserter(phy_description(32)))
+ self.submodules += cont
+
+ # datas / primitives mux
+ insert = Signal(32)
+ self.comb += [
+ If(self.from_rx.insert,
+ cont.sink.stb.eq(1),
+ cont.sink.data.eq(self.from_rx.insert),
+ cont.sink.charisk.eq(0x0001),
+ ).
+ Elif(insert,
+ cont.sink.stb.eq(1),
+ cont.sink.data.eq(insert),
+ cont.sink.charisk.eq(0x0001),
+ ).Elif(fsm.ongoing("COPY"),
+ cont.sink.stb.eq(scrambler.source.stb),
+ cont.sink.data.eq(scrambler.source.d),
+ scrambler.source.ack.eq(cont.sink.ack),
+ cont.sink.charisk.eq(0)
+ )
+ ]
+ self.comb += Record.connect(cont.source, phy.sink)
+
+ # FSM
+ fsm.act("IDLE",
+ scrambler.reset.eq(1),
+ If(self.from_rx.idle,
+ insert.eq(primitives["SYNC"]),
+ If(scrambler.source.stb & scrambler.source.sop,
+ If(self.from_rx.det == primitives["SYNC"],
+ NextState("RDY")
+ )
+ )
+ )
+ )
+ fsm.act("RDY",
+ insert.eq(primitives["X_RDY"]),
+ If(~self.from_rx.idle,
+ NextState("IDLE")
+ ).Elif(self.from_rx.det == primitives["R_RDY"],
+ NextState("SOF")
+ )
+ )
+ fsm.act("SOF",
+ insert.eq(primitives["SOF"]),
+ If(phy.sink.ack,
+ NextState("COPY")
+ )
+ )
+ fsm.act("COPY",
+ If(self.from_rx.det == primitives["HOLD"],
+ insert.eq(primitives["HOLDA"]),
+ ).Elif(~scrambler.source.stb,
+ insert.eq(primitives["HOLD"]),
+ ).Elif(scrambler.source.stb & scrambler.source.eop & scrambler.source.ack,
+ NextState("EOF")
+ )
+ )
+ fsm.act("EOF",
+ insert.eq(primitives["EOF"]),
+ If(phy.sink.ack,
+ NextState("WTRM")
+ )
+ )
+ fsm.act("WTRM",
+ insert.eq(primitives["WTRM"]),
+ If(self.from_rx.det == primitives["R_OK"],
+ NextState("IDLE")
+ ).Elif(self.from_rx.det == primitives["R_ERR"],
+ NextState("IDLE")
+ )
+ )
class LiteSATALinkRX(Module):
- def __init__(self, phy):
- self.source = Source(link_description(32))
- self.hold = Signal()
- self.to_tx = Source(from_rx)
-
- ###
-
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
-
- # CONT remover
- cont = BufferizeEndpoints("source")(LiteSATACONTRemover(phy_description(32)))
- self.submodules += cont
- self.comb += Record.connect(phy.source, cont.sink)
-
- # datas / primitives detection
- insert = Signal(32)
- det = Signal(32)
- self.comb += \
- If(cont.source.stb & (cont.source.charisk == 0b0001),
- det.eq(cont.source.data)
- )
-
- # descrambler
- scrambler = LiteSATAScrambler(link_description(32))
- self.submodules += scrambler
-
- # check CRC
- crc = LiteSATACRCChecker(link_description(32))
- self.submodules += crc
-
- sop = Signal()
- eop = Signal()
- self.sync += \
- If(fsm.ongoing("IDLE"),
- sop.eq(1),
- ).Elif(fsm.ongoing("COPY"),
- If(scrambler.sink.stb & scrambler.sink.ack,
- sop.eq(0)
- )
- )
- self.comb += eop.eq(det == primitives["EOF"])
-
- crc_error = Signal()
- self.sync += \
- If(crc.source.stb & crc.source.eop & crc.source.ack,
- crc_error.eq(crc.source.error)
- )
-
- # graph
- self.comb += [
- cont.source.ack.eq(1),
- Record.connect(scrambler.source, crc.sink),
- Record.connect(crc.source, self.source),
- ]
- cont_source_data_d = Signal(32)
- self.sync += \
- If(cont.source.stb & (det == 0),
- scrambler.sink.d.eq(cont.source.data)
- )
-
- # FSM
- fsm.act("IDLE",
- scrambler.reset.eq(1),
- If(det == primitives["X_RDY"],
- NextState("RDY")
- )
- )
- fsm.act("RDY",
- insert.eq(primitives["R_RDY"]),
- If(det == primitives["SOF"],
- NextState("WAIT_FIRST")
- )
- )
- fsm.act("WAIT_FIRST",
- insert.eq(primitives["R_IP"]),
- If(cont.source.stb & (det == 0),
- NextState("COPY")
- )
- )
- self.comb += [
- scrambler.sink.sop.eq(sop),
- scrambler.sink.eop.eq(eop)
- ]
- fsm.act("COPY",
- scrambler.sink.stb.eq(cont.source.stb & ((det == 0) | eop)),
- insert.eq(primitives["R_IP"]),
- If(det == primitives["HOLD"],
- insert.eq(primitives["HOLDA"])
- ).Elif(det == primitives["EOF"],
- NextState("WTRM")
- ).Elif(self.hold,
- insert.eq(primitives["HOLD"])
- )
- )
- fsm.act("EOF",
- insert.eq(primitives["R_IP"]),
- If(det == primitives["WTRM"],
- NextState("WTRM")
- )
- )
- fsm.act("WTRM",
- insert.eq(primitives["R_IP"]),
- If(~crc_error,
- NextState("R_OK")
- ).Else(
- NextState("R_ERR")
- )
- )
- fsm.act("R_OK",
- insert.eq(primitives["R_OK"]),
- If(det == primitives["SYNC"],
- NextState("IDLE")
- )
- )
- fsm.act("R_ERR",
- insert.eq(primitives["R_ERR"]),
- If(det == primitives["SYNC"],
- NextState("IDLE")
- )
- )
-
- # to TX
- self.comb += [
- self.to_tx.idle.eq(fsm.ongoing("IDLE")),
- self.to_tx.insert.eq(insert),
- self.to_tx.det.eq(det)
- ]
+ def __init__(self, phy):
+ self.source = Source(link_description(32))
+ self.hold = Signal()
+ self.to_tx = Source(from_rx)
+
+ ###
+
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+
+ # CONT remover
+ cont = BufferizeEndpoints("source")(LiteSATACONTRemover(phy_description(32)))
+ self.submodules += cont
+ self.comb += Record.connect(phy.source, cont.sink)
+
+ # datas / primitives detection
+ insert = Signal(32)
+ det = Signal(32)
+ self.comb += \
+ If(cont.source.stb & (cont.source.charisk == 0b0001),
+ det.eq(cont.source.data)
+ )
+
+ # descrambler
+ scrambler = LiteSATAScrambler(link_description(32))
+ self.submodules += scrambler
+
+ # check CRC
+ crc = LiteSATACRCChecker(link_description(32))
+ self.submodules += crc
+
+ sop = Signal()
+ eop = Signal()
+ self.sync += \
+ If(fsm.ongoing("IDLE"),
+ sop.eq(1),
+ ).Elif(fsm.ongoing("COPY"),
+ If(scrambler.sink.stb & scrambler.sink.ack,
+ sop.eq(0)
+ )
+ )
+ self.comb += eop.eq(det == primitives["EOF"])
+
+ crc_error = Signal()
+ self.sync += \
+ If(crc.source.stb & crc.source.eop & crc.source.ack,
+ crc_error.eq(crc.source.error)
+ )
+
+ # graph
+ self.comb += [
+ cont.source.ack.eq(1),
+ Record.connect(scrambler.source, crc.sink),
+ Record.connect(crc.source, self.source),
+ ]
+ cont_source_data_d = Signal(32)
+ self.sync += \
+ If(cont.source.stb & (det == 0),
+ scrambler.sink.d.eq(cont.source.data)
+ )
+
+ # FSM
+ fsm.act("IDLE",
+ scrambler.reset.eq(1),
+ If(det == primitives["X_RDY"],
+ NextState("RDY")
+ )
+ )
+ fsm.act("RDY",
+ insert.eq(primitives["R_RDY"]),
+ If(det == primitives["SOF"],
+ NextState("WAIT_FIRST")
+ )
+ )
+ fsm.act("WAIT_FIRST",
+ insert.eq(primitives["R_IP"]),
+ If(cont.source.stb & (det == 0),
+ NextState("COPY")
+ )
+ )
+ self.comb += [
+ scrambler.sink.sop.eq(sop),
+ scrambler.sink.eop.eq(eop)
+ ]
+ fsm.act("COPY",
+ scrambler.sink.stb.eq(cont.source.stb & ((det == 0) | eop)),
+ insert.eq(primitives["R_IP"]),
+ If(det == primitives["HOLD"],
+ insert.eq(primitives["HOLDA"])
+ ).Elif(det == primitives["EOF"],
+ NextState("WTRM")
+ ).Elif(self.hold,
+ insert.eq(primitives["HOLD"])
+ )
+ )
+ fsm.act("EOF",
+ insert.eq(primitives["R_IP"]),
+ If(det == primitives["WTRM"],
+ NextState("WTRM")
+ )
+ )
+ fsm.act("WTRM",
+ insert.eq(primitives["R_IP"]),
+ If(~crc_error,
+ NextState("R_OK")
+ ).Else(
+ NextState("R_ERR")
+ )
+ )
+ fsm.act("R_OK",
+ insert.eq(primitives["R_OK"]),
+ If(det == primitives["SYNC"],
+ NextState("IDLE")
+ )
+ )
+ fsm.act("R_ERR",
+ insert.eq(primitives["R_ERR"]),
+ If(det == primitives["SYNC"],
+ NextState("IDLE")
+ )
+ )
+
+ # to TX
+ self.comb += [
+ self.to_tx.idle.eq(fsm.ongoing("IDLE")),
+ self.to_tx.insert.eq(insert),
+ self.to_tx.det.eq(det)
+ ]
class LiteSATALink(Module):
- def __init__(self, phy, buffer_depth):
- self.submodules.tx_buffer = PacketBuffer(link_description(32), buffer_depth)
- self.submodules.tx = LiteSATALinkTX(phy)
- self.submodules.rx = LiteSATALinkRX(phy)
- self.submodules.rx_buffer = PacketBuffer(link_description(32), buffer_depth, almost_full=3*buffer_depth//4)
- self.comb += [
- Record.connect(self.tx_buffer.source, self.tx.sink),
- Record.connect(self.rx.to_tx, self.tx.from_rx),
- Record.connect(self.rx.source, self.rx_buffer.sink),
- self.rx.hold.eq(self.rx_buffer.almost_full)
- ]
- self.sink, self.source = self.tx_buffer.sink, self.rx_buffer.source
+ def __init__(self, phy, buffer_depth):
+ self.submodules.tx_buffer = PacketBuffer(link_description(32), buffer_depth)
+ self.submodules.tx = LiteSATALinkTX(phy)
+ self.submodules.rx = LiteSATALinkRX(phy)
+ self.submodules.rx_buffer = PacketBuffer(link_description(32), buffer_depth, almost_full=3*buffer_depth//4)
+ self.comb += [
+ Record.connect(self.tx_buffer.source, self.tx.sink),
+ Record.connect(self.rx.to_tx, self.tx.from_rx),
+ Record.connect(self.rx.source, self.rx_buffer.sink),
+ self.rx.hold.eq(self.rx_buffer.almost_full)
+ ]
+ self.sink, self.source = self.tx_buffer.sink, self.rx_buffer.source
from misoclib.mem.litesata.core.link.scrambler import Scrambler
class LiteSATACONTInserter(Module):
- def __init__(self, description):
- self.sink = sink = Sink(description)
- self.source = source = Source(description)
+ def __init__(self, description):
+ self.sink = sink = Sink(description)
+ self.source = source = Source(description)
- ###
+ ###
- counter = Counter(max=4)
- self.submodules += counter
+ counter = Counter(max=4)
+ self.submodules += counter
- is_data = Signal()
- was_data = Signal()
- was_hold = Signal()
- change = Signal()
- self.comb += is_data.eq(sink.charisk == 0)
+ is_data = Signal()
+ was_data = Signal()
+ was_hold = Signal()
+ change = Signal()
+ self.comb += is_data.eq(sink.charisk == 0)
- last_data = Signal(32)
- last_primitive = Signal(32)
- last_charisk = Signal(4)
- self.sync += [
- If(sink.stb & source.ack,
- last_data.eq(sink.data),
- last_charisk.eq(sink.charisk),
- If(~is_data,
- last_primitive.eq(sink.data),
- ),
- was_data.eq(is_data),
- was_hold.eq(last_primitive == primitives["HOLD"])
- )
- ]
- self.comb += change.eq(
- (sink.data != last_data) |
- (sink.charisk != last_charisk) |
- is_data
- )
+ last_data = Signal(32)
+ last_primitive = Signal(32)
+ last_charisk = Signal(4)
+ self.sync += [
+ If(sink.stb & source.ack,
+ last_data.eq(sink.data),
+ last_charisk.eq(sink.charisk),
+ If(~is_data,
+ last_primitive.eq(sink.data),
+ ),
+ was_data.eq(is_data),
+ was_hold.eq(last_primitive == primitives["HOLD"])
+ )
+ ]
+ self.comb += change.eq(
+ (sink.data != last_data) |
+ (sink.charisk != last_charisk) |
+ is_data
+ )
- # scrambler
- scrambler = InsertReset(Scrambler())
- self.submodules += scrambler
+ # scrambler
+ scrambler = InsertReset(Scrambler())
+ self.submodules += scrambler
- # Datapath
- self.comb += [
- Record.connect(sink, source),
- If(sink.stb,
- If(~change,
- counter.ce.eq(sink.ack & (counter.value !=2)),
- # insert CONT
- If(counter.value == 1,
- source.charisk.eq(0b0001),
- source.data.eq(primitives["CONT"])
- # insert scrambled data for EMI
- ).Elif(counter.value == 2,
- scrambler.ce.eq(sink.ack),
- source.charisk.eq(0b0000),
- source.data.eq(scrambler.value)
- )
- ).Else(
- counter.reset.eq(source.ack),
- If(counter.value == 2,
- # Reinsert last primitive
- If(is_data | (~is_data & was_hold),
- source.stb.eq(1),
- sink.ack.eq(0),
- source.charisk.eq(0b0001),
- source.data.eq(last_primitive)
- )
- )
- )
- )
- ]
+ # Datapath
+ self.comb += [
+ Record.connect(sink, source),
+ If(sink.stb,
+ If(~change,
+ counter.ce.eq(sink.ack & (counter.value !=2)),
+ # insert CONT
+ If(counter.value == 1,
+ source.charisk.eq(0b0001),
+ source.data.eq(primitives["CONT"])
+ # insert scrambled data for EMI
+ ).Elif(counter.value == 2,
+ scrambler.ce.eq(sink.ack),
+ source.charisk.eq(0b0000),
+ source.data.eq(scrambler.value)
+ )
+ ).Else(
+ counter.reset.eq(source.ack),
+ If(counter.value == 2,
+ # Reinsert last primitive
+ If(is_data | (~is_data & was_hold),
+ source.stb.eq(1),
+ sink.ack.eq(0),
+ source.charisk.eq(0b0001),
+ source.data.eq(last_primitive)
+ )
+ )
+ )
+ )
+ ]
class LiteSATACONTRemover(Module):
- def __init__(self, description):
- self.sink = sink = Sink(description)
- self.source = source = Source(description)
+ def __init__(self, description):
+ self.sink = sink = Sink(description)
+ self.source = source = Source(description)
- ###
+ ###
- is_data = Signal()
- is_cont = Signal()
- in_cont = Signal()
- cont_ongoing = Signal()
+ is_data = Signal()
+ is_cont = Signal()
+ in_cont = Signal()
+ cont_ongoing = Signal()
- self.comb += [
- is_data.eq(sink.charisk == 0),
- is_cont.eq(~is_data & (sink.data == primitives["CONT"]))
- ]
- self.sync += \
- If(sink.stb & sink.ack,
- If(is_cont,
- in_cont.eq(1)
- ).Elif(~is_data,
- in_cont.eq(0)
- )
- )
- self.comb += cont_ongoing.eq(is_cont | (in_cont & is_data))
+ self.comb += [
+ is_data.eq(sink.charisk == 0),
+ is_cont.eq(~is_data & (sink.data == primitives["CONT"]))
+ ]
+ self.sync += \
+ If(sink.stb & sink.ack,
+ If(is_cont,
+ in_cont.eq(1)
+ ).Elif(~is_data,
+ in_cont.eq(0)
+ )
+ )
+ self.comb += cont_ongoing.eq(is_cont | (in_cont & is_data))
- # Datapath
- last_primitive = Signal(32)
- self.sync += [
- If(sink.stb & sink.ack,
- If(~is_data & ~is_cont,
- last_primitive.eq(sink.data)
- )
- )
- ]
- self.comb += [
- Record.connect(sink, source),
- If(cont_ongoing,
- source.charisk.eq(0b0001),
- source.data.eq(last_primitive)
- )
- ]
+ # Datapath
+ last_primitive = Signal(32)
+ self.sync += [
+ If(sink.stb & sink.ack,
+ If(~is_data & ~is_cont,
+ last_primitive.eq(sink.data)
+ )
+ )
+ ]
+ self.comb += [
+ Record.connect(sink, source),
+ If(cont_ongoing,
+ source.charisk.eq(0b0001),
+ source.data.eq(last_primitive)
+ )
+ ]
from misoclib.mem.litesata.common import *
class CRCEngine(Module):
- """Cyclic Redundancy Check Engine
-
- Compute next CRC value from last CRC value and data input using
- an optimized asynchronous LFSR.
-
- Parameters
- ----------
- width : int
- Width of the data bus and CRC.
- polynom : int
- Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
-
- Attributes
- ----------
- d : in
- Data input.
- last : in
- last CRC value.
- next :
- next CRC value.
- """
- def __init__(self, width, polynom):
- self.d = Signal(width)
- self.last = Signal(width)
- self.next = Signal(width)
-
- ###
-
- def _optimize_eq(l):
- """
- Replace even numbers of XORs in the equation
- with an equivalent XOR
- """
- d = OrderedDict()
- for e in l:
- if e in d:
- d[e] += 1
- else:
- d[e] = 1
- r = []
- for key, value in d.items():
- if value%2 != 0:
- r.append(key)
- return r
-
- new = Signal(32)
- self.comb += new.eq(self.last ^ self.d)
-
- # compute and optimize CRC's LFSR
- curval = [[("new", i)] for i in range(width)]
- for i in range(width):
- feedback = curval.pop()
- for j in range(width-1):
- if (polynom & (1<<(j+1))):
- curval[j] += feedback
- curval[j] = _optimize_eq(curval[j])
- curval.insert(0, feedback)
-
- # implement logic
- for i in range(width):
- xors = []
- for t, n in curval[i]:
- if t == "new":
- xors += [new[n]]
- self.comb += self.next[i].eq(optree("^", xors))
+ """Cyclic Redundancy Check Engine
+
+ Compute next CRC value from last CRC value and data input using
+ an optimized asynchronous LFSR.
+
+ Parameters
+ ----------
+ width : int
+ Width of the data bus and CRC.
+ polynom : int
+ Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
+
+ Attributes
+ ----------
+ d : in
+ Data input.
+ last : in
+ last CRC value.
+ next :
+ next CRC value.
+ """
+ def __init__(self, width, polynom):
+ self.d = Signal(width)
+ self.last = Signal(width)
+ self.next = Signal(width)
+
+ ###
+
+ def _optimize_eq(l):
+ """
+ Replace even numbers of XORs in the equation
+ with an equivalent XOR
+ """
+ d = OrderedDict()
+ for e in l:
+ if e in d:
+ d[e] += 1
+ else:
+ d[e] = 1
+ r = []
+ for key, value in d.items():
+ if value%2 != 0:
+ r.append(key)
+ return r
+
+ new = Signal(32)
+ self.comb += new.eq(self.last ^ self.d)
+
+ # compute and optimize CRC's LFSR
+ curval = [[("new", i)] for i in range(width)]
+ for i in range(width):
+ feedback = curval.pop()
+ for j in range(width-1):
+ if (polynom & (1<<(j+1))):
+ curval[j] += feedback
+ curval[j] = _optimize_eq(curval[j])
+ curval.insert(0, feedback)
+
+ # implement logic
+ for i in range(width):
+ xors = []
+ for t, n in curval[i]:
+ if t == "new":
+ xors += [new[n]]
+ self.comb += self.next[i].eq(optree("^", xors))
@DecorateModule(InsertReset)
@DecorateModule(InsertCE)
class LiteSATACRC(Module):
- """SATA CRC
-
- Implement a SATA CRC generator/checker
-
- Attributes
- ----------
- value : out
- CRC value (used for generator).
- error : out
- CRC error (used for checker).
- """
- width = 32
- polynom = 0x04C11DB7
- init = 0x52325032
- check = 0x00000000
- def __init__(self, dw=32):
- self.d = Signal(self.width)
- self.value = Signal(self.width)
- self.error = Signal()
-
- ###
-
- engine = CRCEngine(self.width, self.polynom)
- self.submodules += engine
- reg_i = Signal(self.width, reset=self.init)
- self.sync += reg_i.eq(engine.next)
- self.comb += [
- engine.d.eq(self.d),
- engine.last.eq(reg_i),
-
- self.value.eq(reg_i),
- self.error.eq(engine.next != self.check)
- ]
+ """SATA CRC
+
+ Implement a SATA CRC generator/checker
+
+ Attributes
+ ----------
+ value : out
+ CRC value (used for generator).
+ error : out
+ CRC error (used for checker).
+ """
+ width = 32
+ polynom = 0x04C11DB7
+ init = 0x52325032
+ check = 0x00000000
+ def __init__(self, dw=32):
+ self.d = Signal(self.width)
+ self.value = Signal(self.width)
+ self.error = Signal()
+
+ ###
+
+ engine = CRCEngine(self.width, self.polynom)
+ self.submodules += engine
+ reg_i = Signal(self.width, reset=self.init)
+ self.sync += reg_i.eq(engine.next)
+ self.comb += [
+ engine.d.eq(self.d),
+ engine.last.eq(reg_i),
+
+ self.value.eq(reg_i),
+ self.error.eq(engine.next != self.check)
+ ]
class CRCInserter(Module):
- """CRC Inserter
-
- Append a CRC at the end of each packet.
-
- Parameters
- ----------
- layout : layout
- Layout of the dataflow.
-
- Attributes
- ----------
- sink : in
- Packets input without CRC.
- source : out
- Packets output with CRC.
- """
- def __init__(self, crc_class, layout):
- self.sink = sink = Sink(layout)
- self.source = source = Source(layout)
- self.busy = Signal()
-
- ###
-
- dw = flen(sink.d)
- crc = crc_class(dw)
- fsm = FSM(reset_state="IDLE")
- self.submodules += crc, fsm
-
- fsm.act("IDLE",
- crc.reset.eq(1),
- sink.ack.eq(1),
- If(sink.stb & sink.sop,
- sink.ack.eq(0),
- NextState("COPY"),
- )
- )
- fsm.act("COPY",
- crc.ce.eq(sink.stb & source.ack),
- crc.d.eq(sink.d),
- Record.connect(sink, source),
- source.eop.eq(0),
- If(sink.stb & sink.eop & source.ack,
- NextState("INSERT"),
- )
- )
- ratio = crc.width//dw
- if ratio > 1:
- cnt = Signal(max=ratio, reset=ratio-1)
- cnt_done = Signal()
- fsm.act("INSERT",
- source.stb.eq(1),
- chooser(crc.value, cnt, source.d, reverse=True),
- If(cnt_done,
- source.eop.eq(1),
- If(source.ack, NextState("IDLE"))
- )
- )
- self.comb += cnt_done.eq(cnt == 0)
- self.sync += \
- If(fsm.ongoing("IDLE"),
- cnt.eq(cnt.reset)
- ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
- cnt.eq(cnt - source.ack)
- )
- else:
- fsm.act("INSERT",
- source.stb.eq(1),
- source.eop.eq(1),
- source.d.eq(crc.value),
- If(source.ack, NextState("IDLE"))
- )
- self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
+ """CRC Inserter
+
+ Append a CRC at the end of each packet.
+
+ Parameters
+ ----------
+ layout : layout
+ Layout of the dataflow.
+
+ Attributes
+ ----------
+ sink : in
+ Packets input without CRC.
+ source : out
+ Packets output with CRC.
+ """
+ def __init__(self, crc_class, layout):
+ self.sink = sink = Sink(layout)
+ self.source = source = Source(layout)
+ self.busy = Signal()
+
+ ###
+
+ dw = flen(sink.d)
+ crc = crc_class(dw)
+ fsm = FSM(reset_state="IDLE")
+ self.submodules += crc, fsm
+
+ fsm.act("IDLE",
+ crc.reset.eq(1),
+ sink.ack.eq(1),
+ If(sink.stb & sink.sop,
+ sink.ack.eq(0),
+ NextState("COPY"),
+ )
+ )
+ fsm.act("COPY",
+ crc.ce.eq(sink.stb & source.ack),
+ crc.d.eq(sink.d),
+ Record.connect(sink, source),
+ source.eop.eq(0),
+ If(sink.stb & sink.eop & source.ack,
+ NextState("INSERT"),
+ )
+ )
+ ratio = crc.width//dw
+ if ratio > 1:
+ cnt = Signal(max=ratio, reset=ratio-1)
+ cnt_done = Signal()
+ fsm.act("INSERT",
+ source.stb.eq(1),
+ chooser(crc.value, cnt, source.d, reverse=True),
+ If(cnt_done,
+ source.eop.eq(1),
+ If(source.ack, NextState("IDLE"))
+ )
+ )
+ self.comb += cnt_done.eq(cnt == 0)
+ self.sync += \
+ If(fsm.ongoing("IDLE"),
+ cnt.eq(cnt.reset)
+ ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
+ cnt.eq(cnt - source.ack)
+ )
+ else:
+ fsm.act("INSERT",
+ source.stb.eq(1),
+ source.eop.eq(1),
+ source.d.eq(crc.value),
+ If(source.ack, NextState("IDLE"))
+ )
+ self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
class CRCChecker(Module):
- """CRC Checker
-
- Check CRC at the end of each packet.
-
- Parameters
- ----------
- layout : layout
- Layout of the dataflow.
-
- Attributes
- ----------
- sink : in
- Packets input with CRC.
- source : out
- Packets output without CRC and "error" set to 0
- on eop when CRC OK / set to 1 when CRC KO.
- """
- def __init__(self, crc_class, layout):
- self.sink = sink = Sink(layout)
- self.source = source = Source(layout)
- self.busy = Signal()
-
- ###
-
- dw = flen(sink.d)
- crc = crc_class(dw)
- self.submodules += crc
- ratio = crc.width//dw
-
- error = Signal()
- fifo = InsertReset(SyncFIFO(layout, ratio + 1))
- self.submodules += fifo
-
- fsm = FSM(reset_state="RESET")
- self.submodules += fsm
-
- fifo_in = Signal()
- fifo_out = Signal()
- fifo_full = Signal()
-
- self.comb += [
- fifo_full.eq(fifo.fifo.level == ratio),
- fifo_in.eq(sink.stb & (~fifo_full | fifo_out)),
- fifo_out.eq(source.stb & source.ack),
-
- Record.connect(sink, fifo.sink),
- fifo.sink.stb.eq(fifo_in),
- self.sink.ack.eq(fifo_in),
-
- source.stb.eq(sink.stb & fifo_full),
- source.sop.eq(fifo.source.sop),
- source.eop.eq(sink.eop),
- fifo.source.ack.eq(fifo_out),
- source.payload.eq(fifo.source.payload),
-
- source.error.eq(sink.error | crc.error),
- ]
-
- fsm.act("RESET",
- crc.reset.eq(1),
- fifo.reset.eq(1),
- NextState("IDLE"),
- )
- fsm.act("IDLE",
- crc.d.eq(sink.d),
- If(sink.stb & sink.sop & sink.ack,
- crc.ce.eq(1),
- NextState("COPY")
- )
- )
- fsm.act("COPY",
- crc.d.eq(sink.d),
- If(sink.stb & sink.ack,
- crc.ce.eq(1),
- If(sink.eop,
- NextState("RESET")
- )
- )
- )
- self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
+ """CRC Checker
+
+ Check CRC at the end of each packet.
+
+ Parameters
+ ----------
+ layout : layout
+ Layout of the dataflow.
+
+ Attributes
+ ----------
+ sink : in
+ Packets input with CRC.
+ source : out
+ Packets output without CRC and "error" set to 0
+ on eop when CRC OK / set to 1 when CRC KO.
+ """
+ def __init__(self, crc_class, layout):
+ self.sink = sink = Sink(layout)
+ self.source = source = Source(layout)
+ self.busy = Signal()
+
+ ###
+
+ dw = flen(sink.d)
+ crc = crc_class(dw)
+ self.submodules += crc
+ ratio = crc.width//dw
+
+ error = Signal()
+ fifo = InsertReset(SyncFIFO(layout, ratio + 1))
+ self.submodules += fifo
+
+ fsm = FSM(reset_state="RESET")
+ self.submodules += fsm
+
+ fifo_in = Signal()
+ fifo_out = Signal()
+ fifo_full = Signal()
+
+ self.comb += [
+ fifo_full.eq(fifo.fifo.level == ratio),
+ fifo_in.eq(sink.stb & (~fifo_full | fifo_out)),
+ fifo_out.eq(source.stb & source.ack),
+
+ Record.connect(sink, fifo.sink),
+ fifo.sink.stb.eq(fifo_in),
+ self.sink.ack.eq(fifo_in),
+
+ source.stb.eq(sink.stb & fifo_full),
+ source.sop.eq(fifo.source.sop),
+ source.eop.eq(sink.eop),
+ fifo.source.ack.eq(fifo_out),
+ source.payload.eq(fifo.source.payload),
+
+ source.error.eq(sink.error | crc.error),
+ ]
+
+ fsm.act("RESET",
+ crc.reset.eq(1),
+ fifo.reset.eq(1),
+ NextState("IDLE"),
+ )
+ fsm.act("IDLE",
+ crc.d.eq(sink.d),
+ If(sink.stb & sink.sop & sink.ack,
+ crc.ce.eq(1),
+ NextState("COPY")
+ )
+ )
+ fsm.act("COPY",
+ crc.d.eq(sink.d),
+ If(sink.stb & sink.ack,
+ crc.ce.eq(1),
+ If(sink.eop,
+ NextState("RESET")
+ )
+ )
+ )
+ self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
class LiteSATACRCInserter(CRCInserter):
- def __init__(self, description):
- CRCInserter.__init__(self, LiteSATACRC, description)
+ def __init__(self, description):
+ CRCInserter.__init__(self, LiteSATACRC, description)
class LiteSATACRCChecker(CRCChecker):
- def __init__(self, description):
- CRCChecker.__init__(self, LiteSATACRC, description)
+ def __init__(self, description):
+ CRCChecker.__init__(self, LiteSATACRC, description)
@DecorateModule(InsertCE)
class Scrambler(Module):
- """SATA Scrambler
+ """SATA Scrambler
- Implement a SATA Scrambler
+ Implement a SATA Scrambler
- Attributes
- ----------
- value : out
- Scrambled value.
- """
- def __init__(self):
- self.value = Signal(32)
+ Attributes
+ ----------
+ value : out
+ Scrambled value.
+ """
+ def __init__(self):
+ self.value = Signal(32)
- ###
+ ###
- context = Signal(16, reset=0xf0f6)
- next_value = Signal(32)
- self.sync += context.eq(next_value[16:32])
+ context = Signal(16, reset=0xf0f6)
+ next_value = Signal(32)
+ self.sync += context.eq(next_value[16:32])
- # XXX: from SATA specification, replace it with
- # a generic implementation using polynoms.
- lfsr_coefs = (
- (15, 13, 4, 0), #0
- (15, 14, 13, 5, 4, 1, 0),
- (14, 13, 6, 5, 4, 2,1, 0),
- (15, 14, 7, 6, 5, 3,2, 1),
- (13, 8, 7, 6, 3, 2, 0),
- (14, 9, 8, 7, 4, 3, 1),
- (15, 10, 9, 8, 5, 4, 2),
- (15, 13, 11, 10, 9, 6, 5, 4, 3, 0),
- (15, 14, 13, 12, 11, 10,7, 6, 5, 1, 0),
- (14, 12, 11, 8, 7, 6, 4, 2, 1, 0),
- (15, 13, 12, 9, 8, 7, 5, 3, 2, 1),
- (15, 14, 10, 9, 8, 6, 3, 2, 0),
- (13, 11, 10, 9, 7, 3, 1, 0),
- (14, 12, 11, 10, 8, 4, 2, 1),
- (15, 13, 12, 11, 9, 5, 3, 2),
- (15, 14, 12, 10, 6, 3, 0),
+ # XXX: from SATA specification, replace it with
+ # a generic implementation using polynoms.
+ lfsr_coefs = (
+ (15, 13, 4, 0), #0
+ (15, 14, 13, 5, 4, 1, 0),
+ (14, 13, 6, 5, 4, 2,1, 0),
+ (15, 14, 7, 6, 5, 3,2, 1),
+ (13, 8, 7, 6, 3, 2, 0),
+ (14, 9, 8, 7, 4, 3, 1),
+ (15, 10, 9, 8, 5, 4, 2),
+ (15, 13, 11, 10, 9, 6, 5, 4, 3, 0),
+ (15, 14, 13, 12, 11, 10,7, 6, 5, 1, 0),
+ (14, 12, 11, 8, 7, 6, 4, 2, 1, 0),
+ (15, 13, 12, 9, 8, 7, 5, 3, 2, 1),
+ (15, 14, 10, 9, 8, 6, 3, 2, 0),
+ (13, 11, 10, 9, 7, 3, 1, 0),
+ (14, 12, 11, 10, 8, 4, 2, 1),
+ (15, 13, 12, 11, 9, 5, 3, 2),
+ (15, 14, 12, 10, 6, 3, 0),
- (11, 7, 1, 0), #16
- (12, 8, 2, 1),
- (13, 9, 3, 2),
- (14, 10, 4, 3),
- (15, 11, 5, 4),
- (15, 13, 12, 6, 5, 4, 0),
- (15, 14, 7, 6, 5, 4, 1, 0),
- (13, 8, 7, 6, 5, 4, 2, 1, 0),
- (14, 9, 8,7, 6, 5, 3, 2, 1),
- (15, 10, 9, 8, 7, 6, 4, 3, 2),
- (15, 13, 11, 10, 9, 8, 7, 5, 3, 0),
- (15, 14, 13, 12, 11, 10, 9, 8, 6, 1, 0),
- (14, 12, 11, 10, 9, 7, 4, 2, 1, 0),
- (15, 13, 12, 11, 10, 8, 5, 3, 2, 1),
- (15, 14, 12, 11, 9, 6, 3, 2, 0),
- (12, 10, 7, 3, 1, 0),
- )
+ (11, 7, 1, 0), #16
+ (12, 8, 2, 1),
+ (13, 9, 3, 2),
+ (14, 10, 4, 3),
+ (15, 11, 5, 4),
+ (15, 13, 12, 6, 5, 4, 0),
+ (15, 14, 7, 6, 5, 4, 1, 0),
+ (13, 8, 7, 6, 5, 4, 2, 1, 0),
+ (14, 9, 8,7, 6, 5, 3, 2, 1),
+ (15, 10, 9, 8, 7, 6, 4, 3, 2),
+ (15, 13, 11, 10, 9, 8, 7, 5, 3, 0),
+ (15, 14, 13, 12, 11, 10, 9, 8, 6, 1, 0),
+ (14, 12, 11, 10, 9, 7, 4, 2, 1, 0),
+ (15, 13, 12, 11, 10, 8, 5, 3, 2, 1),
+ (15, 14, 12, 11, 9, 6, 3, 2, 0),
+ (12, 10, 7, 3, 1, 0),
+ )
- for n, coefs in enumerate(lfsr_coefs):
- eq = [context[i] for i in coefs]
- self.comb += next_value[n].eq(optree("^", eq))
+ for n, coefs in enumerate(lfsr_coefs):
+ eq = [context[i] for i in coefs]
+ self.comb += next_value[n].eq(optree("^", eq))
- self.comb += self.value.eq(next_value)
+ self.comb += self.value.eq(next_value)
@DecorateModule(InsertReset)
class LiteSATAScrambler(Module):
- def __init__(self, description):
- self.sink = sink = Sink(description)
- self.source = source = Source(description)
+ def __init__(self, description):
+ self.sink = sink = Sink(description)
+ self.source = source = Source(description)
- ###
+ ###
- scrambler = Scrambler()
- self.submodules += scrambler
- self.comb += [
- scrambler.ce.eq(sink.stb & sink.ack),
- Record.connect(sink, source),
- source.d.eq(sink.d ^ scrambler.value)
- ]
+ scrambler = Scrambler()
+ self.submodules += scrambler
+ self.comb += [
+ scrambler.ce.eq(sink.stb & sink.ack),
+ Record.connect(sink, source),
+ source.d.eq(sink.d ^ scrambler.value)
+ ]
from misoclib.mem.litesata.common import *
def _get_item(obj, name, width):
- if "_lsb" in name:
- item = getattr(obj, name.replace("_lsb", ""))[:width]
- elif "_msb" in name:
- item = getattr(obj, name.replace("_msb", ""))[width:2*width]
- else:
- item = getattr(obj, name)
- return item
+ if "_lsb" in name:
+ item = getattr(obj, name.replace("_lsb", ""))[:width]
+ elif "_msb" in name:
+ item = getattr(obj, name.replace("_msb", ""))[width:2*width]
+ else:
+ item = getattr(obj, name)
+ return item
def _encode_cmd(obj, description, signal):
- r = []
- for k, v in sorted(description.items()):
- start = v.dword*32 + v.offset
- end = start + v.width
- item = _get_item(obj, k, v.width)
- r.append(signal[start:end].eq(item))
- return r
+ r = []
+ for k, v in sorted(description.items()):
+ start = v.dword*32 + v.offset
+ end = start + v.width
+ item = _get_item(obj, k, v.width)
+ r.append(signal[start:end].eq(item))
+ return r
def test_type(name, signal):
- return signal == fis_types[name]
+ return signal == fis_types[name]
class LiteSATATransportTX(Module):
- def __init__(self, link):
- self.sink = sink = Sink(transport_tx_description(32))
+ def __init__(self, link):
+ self.sink = sink = Sink(transport_tx_description(32))
- ###
+ ###
- cmd_ndwords = max(fis_reg_h2d_cmd_len, fis_data_cmd_len)
- encoded_cmd = Signal(cmd_ndwords*32)
+ cmd_ndwords = max(fis_reg_h2d_cmd_len, fis_data_cmd_len)
+ encoded_cmd = Signal(cmd_ndwords*32)
- counter = Counter(max=cmd_ndwords+1)
- self.submodules += counter
+ counter = Counter(max=cmd_ndwords+1)
+ self.submodules += counter
- cmd_len = Signal(counter.width)
- cmd_with_data = Signal()
+ cmd_len = Signal(counter.width)
+ cmd_with_data = Signal()
- cmd_send = Signal()
- data_send = Signal()
- cmd_done = Signal()
+ cmd_send = Signal()
+ data_send = Signal()
+ cmd_done = Signal()
- fis_type = Signal(8)
- update_fis_type = Signal()
+ fis_type = Signal(8)
+ update_fis_type = Signal()
- def test_type_tx(name):
- return test_type(name, sink.type)
+ def test_type_tx(name):
+ return test_type(name, sink.type)
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- sink.ack.eq(0),
- counter.reset.eq(1),
- update_fis_type.eq(1),
- If(sink.stb & sink.sop,
- If(test_type_tx("REG_H2D"),
- NextState("SEND_CTRL_CMD")
- ).Elif(test_type_tx("DATA"),
- NextState("SEND_DATA_CMD")
- ).Else(
- sink.ack.eq(1)
- )
- ).Else(
- sink.ack.eq(1)
- )
- )
- self.sync += \
- If(update_fis_type, fis_type.eq(link.source.d[:8]))
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ sink.ack.eq(0),
+ counter.reset.eq(1),
+ update_fis_type.eq(1),
+ If(sink.stb & sink.sop,
+ If(test_type_tx("REG_H2D"),
+ NextState("SEND_CTRL_CMD")
+ ).Elif(test_type_tx("DATA"),
+ NextState("SEND_DATA_CMD")
+ ).Else(
+ sink.ack.eq(1)
+ )
+ ).Else(
+ sink.ack.eq(1)
+ )
+ )
+ self.sync += \
+ If(update_fis_type, fis_type.eq(link.source.d[:8]))
- fsm.act("SEND_CTRL_CMD",
- _encode_cmd(sink, fis_reg_h2d_layout, encoded_cmd),
- cmd_len.eq(fis_reg_h2d_cmd_len-1),
- cmd_send.eq(1),
- If(cmd_done,
- sink.ack.eq(1),
- NextState("IDLE")
- )
- )
- fsm.act("SEND_DATA_CMD",
- sink.ack.eq(0),
- _encode_cmd(sink, fis_data_layout, encoded_cmd),
- cmd_len.eq(fis_data_cmd_len-1),
- cmd_with_data.eq(1),
- cmd_send.eq(1),
- If(cmd_done,
- NextState("SEND_DATA")
- )
- )
- fsm.act("SEND_DATA",
- data_send.eq(1),
- sink.ack.eq(link.sink.ack),
- If(sink.stb & sink.eop & sink.ack,
- NextState("IDLE")
- )
- )
+ fsm.act("SEND_CTRL_CMD",
+ _encode_cmd(sink, fis_reg_h2d_layout, encoded_cmd),
+ cmd_len.eq(fis_reg_h2d_cmd_len-1),
+ cmd_send.eq(1),
+ If(cmd_done,
+ sink.ack.eq(1),
+ NextState("IDLE")
+ )
+ )
+ fsm.act("SEND_DATA_CMD",
+ sink.ack.eq(0),
+ _encode_cmd(sink, fis_data_layout, encoded_cmd),
+ cmd_len.eq(fis_data_cmd_len-1),
+ cmd_with_data.eq(1),
+ cmd_send.eq(1),
+ If(cmd_done,
+ NextState("SEND_DATA")
+ )
+ )
+ fsm.act("SEND_DATA",
+ data_send.eq(1),
+ sink.ack.eq(link.sink.ack),
+ If(sink.stb & sink.eop & sink.ack,
+ NextState("IDLE")
+ )
+ )
- cmd_cases = {}
- for i in range(cmd_ndwords):
- cmd_cases[i] = [link.sink.d.eq(encoded_cmd[32*i:32*(i+1)])]
+ cmd_cases = {}
+ for i in range(cmd_ndwords):
+ cmd_cases[i] = [link.sink.d.eq(encoded_cmd[32*i:32*(i+1)])]
- self.comb += [
- counter.ce.eq(sink.stb & link.sink.ack),
- cmd_done.eq((counter.value == cmd_len) & link.sink.stb & link.sink.ack),
- If(cmd_send,
- link.sink.stb.eq(sink.stb),
- link.sink.sop.eq(counter.value == 0),
- link.sink.eop.eq((counter.value == cmd_len) & ~cmd_with_data),
- Case(counter.value, cmd_cases)
- ).Elif(data_send,
- link.sink.stb.eq(sink.stb),
- link.sink.sop.eq(0),
- link.sink.eop.eq(sink.eop),
- link.sink.d.eq(sink.data)
- )
- ]
+ self.comb += [
+ counter.ce.eq(sink.stb & link.sink.ack),
+ cmd_done.eq((counter.value == cmd_len) & link.sink.stb & link.sink.ack),
+ If(cmd_send,
+ link.sink.stb.eq(sink.stb),
+ link.sink.sop.eq(counter.value == 0),
+ link.sink.eop.eq((counter.value == cmd_len) & ~cmd_with_data),
+ Case(counter.value, cmd_cases)
+ ).Elif(data_send,
+ link.sink.stb.eq(sink.stb),
+ link.sink.sop.eq(0),
+ link.sink.eop.eq(sink.eop),
+ link.sink.d.eq(sink.data)
+ )
+ ]
def _decode_cmd(signal, description, obj):
- r = []
- for k, v in sorted(description.items()):
- start = v.dword*32+v.offset
- end = start+v.width
- item = _get_item(obj, k, v.width)
- r.append(item.eq(signal[start:end]))
- return r
+ r = []
+ for k, v in sorted(description.items()):
+ start = v.dword*32+v.offset
+ end = start+v.width
+ item = _get_item(obj, k, v.width)
+ r.append(item.eq(signal[start:end]))
+ return r
class LiteSATATransportRX(Module):
- def __init__(self, link):
- self.source = source = Source(transport_rx_description(32))
+ def __init__(self, link):
+ self.source = source = Source(transport_rx_description(32))
- ###
+ ###
- cmd_ndwords = max(fis_reg_d2h_cmd_len, fis_dma_activate_d2h_cmd_len,
- fis_pio_setup_d2h_cmd_len, fis_data_cmd_len)
- encoded_cmd = Signal(cmd_ndwords*32)
+ cmd_ndwords = max(fis_reg_d2h_cmd_len, fis_dma_activate_d2h_cmd_len,
+ fis_pio_setup_d2h_cmd_len, fis_data_cmd_len)
+ encoded_cmd = Signal(cmd_ndwords*32)
- counter = Counter(max=cmd_ndwords+1)
- self.submodules += counter
+ counter = Counter(max=cmd_ndwords+1)
+ self.submodules += counter
- cmd_len = Signal(counter.width)
+ cmd_len = Signal(counter.width)
- cmd_receive = Signal()
- data_receive = Signal()
- cmd_done = Signal()
- data_done = Signal()
+ cmd_receive = Signal()
+ data_receive = Signal()
+ cmd_done = Signal()
+ data_done = Signal()
- def test_type_rx(name):
- return test_type(name, link.source.d[:8])
+ def test_type_rx(name):
+ return test_type(name, link.source.d[:8])
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
- data_sop = Signal()
- fis_type = Signal(8)
- update_fis_type = Signal()
+ data_sop = Signal()
+ fis_type = Signal(8)
+ update_fis_type = Signal()
- fsm.act("IDLE",
- link.source.ack.eq(0),
- counter.reset.eq(1),
- update_fis_type.eq(1),
- If(link.source.stb & link.source.sop,
- If(test_type_rx("REG_D2H"),
- NextState("RECEIVE_CTRL_CMD")
- ).Elif(test_type_rx("DMA_ACTIVATE_D2H"),
- NextState("RECEIVE_CTRL_CMD")
- ).Elif(test_type_rx("PIO_SETUP_D2H"),
- NextState("RECEIVE_CTRL_CMD")
- ).Elif(test_type_rx("DATA"),
- NextState("RECEIVE_DATA_CMD"),
- ).Else(
- link.source.ack.eq(1)
- )
- ).Else(
- link.source.ack.eq(1)
- )
- )
- self.sync += \
- If(update_fis_type, fis_type.eq(link.source.d[:8]))
+ fsm.act("IDLE",
+ link.source.ack.eq(0),
+ counter.reset.eq(1),
+ update_fis_type.eq(1),
+ If(link.source.stb & link.source.sop,
+ If(test_type_rx("REG_D2H"),
+ NextState("RECEIVE_CTRL_CMD")
+ ).Elif(test_type_rx("DMA_ACTIVATE_D2H"),
+ NextState("RECEIVE_CTRL_CMD")
+ ).Elif(test_type_rx("PIO_SETUP_D2H"),
+ NextState("RECEIVE_CTRL_CMD")
+ ).Elif(test_type_rx("DATA"),
+ NextState("RECEIVE_DATA_CMD"),
+ ).Else(
+ link.source.ack.eq(1)
+ )
+ ).Else(
+ link.source.ack.eq(1)
+ )
+ )
+ self.sync += \
+ If(update_fis_type, fis_type.eq(link.source.d[:8]))
- fsm.act("RECEIVE_CTRL_CMD",
- If(test_type("REG_D2H", fis_type),
- cmd_len.eq(fis_reg_d2h_cmd_len-1)
- ).Elif(test_type("DMA_ACTIVATE_D2H", fis_type),
- cmd_len.eq(fis_dma_activate_d2h_cmd_len-1)
- ).Else(
- cmd_len.eq(fis_pio_setup_d2h_cmd_len-1)
- ),
- cmd_receive.eq(1),
- link.source.ack.eq(1),
- If(cmd_done,
- NextState("PRESENT_CTRL_CMD")
- )
- )
- fsm.act("PRESENT_CTRL_CMD",
- source.stb.eq(1),
- source.sop.eq(1),
- source.eop.eq(1),
- If(test_type("REG_D2H", fis_type),
- _decode_cmd(encoded_cmd, fis_reg_d2h_layout, source),
- ).Elif(test_type("DMA_ACTIVATE_D2H", fis_type),
- _decode_cmd(encoded_cmd, fis_dma_activate_d2h_layout, source),
- ).Else(
- _decode_cmd(encoded_cmd, fis_pio_setup_d2h_layout, source),
- ),
- If(source.stb & source.ack,
- NextState("IDLE")
- )
- )
- fsm.act("RECEIVE_DATA_CMD",
- cmd_len.eq(fis_data_cmd_len-1),
- cmd_receive.eq(1),
- link.source.ack.eq(1),
- If(cmd_done,
- NextState("PRESENT_DATA")
- )
- )
- fsm.act("PRESENT_DATA",
- data_receive.eq(1),
- source.stb.eq(link.source.stb),
- _decode_cmd(encoded_cmd, fis_data_layout, source),
- source.sop.eq(data_sop),
- source.eop.eq(link.source.eop),
- source.error.eq(link.source.error),
- source.data.eq(link.source.d),
- link.source.ack.eq(source.ack),
- If(source.stb & source.eop & source.ack,
- NextState("IDLE")
- )
- )
+ fsm.act("RECEIVE_CTRL_CMD",
+ If(test_type("REG_D2H", fis_type),
+ cmd_len.eq(fis_reg_d2h_cmd_len-1)
+ ).Elif(test_type("DMA_ACTIVATE_D2H", fis_type),
+ cmd_len.eq(fis_dma_activate_d2h_cmd_len-1)
+ ).Else(
+ cmd_len.eq(fis_pio_setup_d2h_cmd_len-1)
+ ),
+ cmd_receive.eq(1),
+ link.source.ack.eq(1),
+ If(cmd_done,
+ NextState("PRESENT_CTRL_CMD")
+ )
+ )
+ fsm.act("PRESENT_CTRL_CMD",
+ source.stb.eq(1),
+ source.sop.eq(1),
+ source.eop.eq(1),
+ If(test_type("REG_D2H", fis_type),
+ _decode_cmd(encoded_cmd, fis_reg_d2h_layout, source),
+ ).Elif(test_type("DMA_ACTIVATE_D2H", fis_type),
+ _decode_cmd(encoded_cmd, fis_dma_activate_d2h_layout, source),
+ ).Else(
+ _decode_cmd(encoded_cmd, fis_pio_setup_d2h_layout, source),
+ ),
+ If(source.stb & source.ack,
+ NextState("IDLE")
+ )
+ )
+ fsm.act("RECEIVE_DATA_CMD",
+ cmd_len.eq(fis_data_cmd_len-1),
+ cmd_receive.eq(1),
+ link.source.ack.eq(1),
+ If(cmd_done,
+ NextState("PRESENT_DATA")
+ )
+ )
+ fsm.act("PRESENT_DATA",
+ data_receive.eq(1),
+ source.stb.eq(link.source.stb),
+ _decode_cmd(encoded_cmd, fis_data_layout, source),
+ source.sop.eq(data_sop),
+ source.eop.eq(link.source.eop),
+ source.error.eq(link.source.error),
+ source.data.eq(link.source.d),
+ link.source.ack.eq(source.ack),
+ If(source.stb & source.eop & source.ack,
+ NextState("IDLE")
+ )
+ )
- self.sync += \
- If(fsm.ongoing("RECEIVE_DATA_CMD"),
- data_sop.eq(1)
- ).Elif(fsm.ongoing("PRESENT_DATA"),
- If(source.stb & source.ack,
- data_sop.eq(0)
- )
- )
+ self.sync += \
+ If(fsm.ongoing("RECEIVE_DATA_CMD"),
+ data_sop.eq(1)
+ ).Elif(fsm.ongoing("PRESENT_DATA"),
+ If(source.stb & source.ack,
+ data_sop.eq(0)
+ )
+ )
- cmd_cases = {}
- for i in range(cmd_ndwords):
- cmd_cases[i] = [encoded_cmd[32*i:32*(i+1)].eq(link.source.d)]
+ cmd_cases = {}
+ for i in range(cmd_ndwords):
+ cmd_cases[i] = [encoded_cmd[32*i:32*(i+1)].eq(link.source.d)]
- self.comb += \
- If(cmd_receive & link.source.stb,
- counter.ce.eq(1)
- )
- self.sync += \
- If(cmd_receive,
- Case(counter.value, cmd_cases),
- )
- self.comb += cmd_done.eq((counter.value == cmd_len) & link.source.ack)
+ self.comb += \
+ If(cmd_receive & link.source.stb,
+ counter.ce.eq(1)
+ )
+ self.sync += \
+ If(cmd_receive,
+ Case(counter.value, cmd_cases),
+ )
+ self.comb += cmd_done.eq((counter.value == cmd_len) & link.source.ack)
class LiteSATATransport(Module):
- def __init__(self, link):
- self.submodules.tx = LiteSATATransportTX(link)
- self.submodules.rx = LiteSATATransportRX(link)
- self.sink, self.source = self.tx.sink, self.rx.source
+ def __init__(self, link):
+ self.submodules.tx = LiteSATATransportTX(link)
+ self.submodules.rx = LiteSATATransportRX(link)
+ self.sink, self.source = self.tx.sink, self.rx.source
from misoclib.mem.litesata.common import *
def _import(default, name):
- return importlib.import_module(default + "." + name)
+ return importlib.import_module(default + "." + name)
def _get_args():
- parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
- description="""\
+ parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="""\
LiteSATA - based on Migen.
This program builds and/or loads LiteSATA components.
all clean, build-csr-csv, build-bitstream, load-bitstream.
""")
- parser.add_argument("-t", "--target", default="bist", help="Core type to build")
- parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build")
- parser.add_argument("-p", "--platform", default=None, help="platform to build for")
- parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option")
- parser.add_argument("-Op", "--platform-option", default=[("programmer", "vivado")], nargs=2, action="append", help="set platform-specific option")
- parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into")
+ parser.add_argument("-t", "--target", default="bist", help="Core type to build")
+ parser.add_argument("-s", "--sub-target", default="", help="variant of the Core type to build")
+ parser.add_argument("-p", "--platform", default=None, help="platform to build for")
+ parser.add_argument("-Ot", "--target-option", default=[], nargs=2, action="append", help="set target-specific option")
+ parser.add_argument("-Op", "--platform-option", default=[("programmer", "vivado")], nargs=2, action="append", help="set platform-specific option")
+ parser.add_argument("--csr_csv", default="./test/csr.csv", help="CSV file to save the CSR map into")
- parser.add_argument("action", nargs="+", help="specify an action")
+ parser.add_argument("action", nargs="+", help="specify an action")
- return parser.parse_args()
+ return parser.parse_args()
# Note: misoclib need to be installed as a python library
if __name__ == "__main__":
- args = _get_args()
-
- # create top-level Core object
- target_module = _import("targets", args.target)
- if args.sub_target:
- top_class = getattr(target_module, args.sub_target)
- else:
- top_class = target_module.default_subtarget
-
- if args.platform is None:
- platform_name = top_class.default_platform
- else:
- platform_name = args.platform
- platform_module = _import("platforms", platform_name)
- platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option)
- platform = platform_module.Platform(**platform_kwargs)
-
- build_name = top_class.__name__.lower() + "-" + platform_name
- top_kwargs = dict((k, autotype(v)) for k, v in args.target_option)
- soc = top_class(platform, **top_kwargs)
- soc.finalize()
- try:
- memory_regions = soc.get_memory_regions()
- csr_regions = soc.get_csr_regions()
- except:
- pass
-
- # decode actions
- action_list = ["clean", "build-csr-csv", "build-core", "build-bitstream", "load-bitstream", "all"]
- actions = {k: False for k in action_list}
- for action in args.action:
- if action in actions:
- actions[action] = True
- else:
- print("Unknown action: "+action+". Valid actions are:")
- for a in action_list:
- print(" "+a)
- sys.exit(1)
-
-
- revision = soc.sata_phy.revision
- has_bist = hasattr(soc.sata, "bist")
- user_ports = len(soc.sata.crossbar.users)
-
- print("""
+ args = _get_args()
+
+ # create top-level Core object
+ target_module = _import("targets", args.target)
+ if args.sub_target:
+ top_class = getattr(target_module, args.sub_target)
+ else:
+ top_class = target_module.default_subtarget
+
+ if args.platform is None:
+ platform_name = top_class.default_platform
+ else:
+ platform_name = args.platform
+ platform_module = _import("platforms", platform_name)
+ platform_kwargs = dict((k, autotype(v)) for k, v in args.platform_option)
+ platform = platform_module.Platform(**platform_kwargs)
+
+ build_name = top_class.__name__.lower() + "-" + platform_name
+ top_kwargs = dict((k, autotype(v)) for k, v in args.target_option)
+ soc = top_class(platform, **top_kwargs)
+ soc.finalize()
+ try:
+ memory_regions = soc.get_memory_regions()
+ csr_regions = soc.get_csr_regions()
+ except:
+ pass
+
+ # decode actions
+ action_list = ["clean", "build-csr-csv", "build-core", "build-bitstream", "load-bitstream", "all"]
+ actions = {k: False for k in action_list}
+ for action in args.action:
+ if action in actions:
+ actions[action] = True
+ else:
+ print("Unknown action: "+action+". Valid actions are:")
+ for a in action_list:
+ print(" "+a)
+ sys.exit(1)
+
+
+ revision = soc.sata_phy.revision
+ has_bist = hasattr(soc.sata, "bist")
+ user_ports = len(soc.sata.crossbar.users)
+
+ print("""
__ _ __ _______ _________
/ / (_) /____ / __/ _ /_ __/ _ |
/ /__/ / __/ -_)\ \/ __ |/ / / __ |
User ports: {}
BIST: {}
===============================""".format(
- revision.replace("sata_", "SATA "), bitrates[revision],
- soc.clk_freq/1000000, frequencies[revision],
- user_ports,
- has_bist
- )
+ revision.replace("sata_", "SATA "), bitrates[revision],
+ soc.clk_freq/1000000, frequencies[revision],
+ user_ports,
+ has_bist
+ )
)
- # dependencies
- if actions["all"]:
- actions["build-csr-csv"] = True
- actions["build-bitstream"] = True
- actions["load-bitstream"] = True
-
- if actions["build-bitstream"]:
- actions["build-csr-csv"] = True
- actions["build-bitstream"] = True
- actions["load-bitstream"] = True
-
- if actions["clean"]:
- subprocess.call(["rm", "-rf", "build/*"])
-
- if actions["build-csr-csv"]:
- csr_csv = cpuif.get_csr_csv(csr_regions)
- write_to_file(args.csr_csv, csr_csv)
-
- if actions["build-core"]:
- ios = soc.get_ios()
- if not isinstance(soc, _Fragment):
- soc = soc.get_fragment()
- platform.finalize(soc)
- so = {
- NoRetiming: XilinxNoRetiming,
- MultiReg: XilinxMultiReg,
- AsyncResetSynchronizer: XilinxAsyncResetSynchronizer
- }
- v_output = verilog.convert(soc, ios, special_overrides=so)
- v_output.write("build/litesata.v")
-
- if actions["build-bitstream"]:
- vns = platform.build(soc, build_name=build_name, run=True)
- if hasattr(soc, "do_exit") and vns is not None:
- if hasattr(soc.do_exit, '__call__'):
- soc.do_exit(vns)
-
- if actions["load-bitstream"]:
- prog = platform.create_programmer()
- prog.load_bitstream("build/" + build_name + platform.bitstream_ext)
+ # dependencies
+ if actions["all"]:
+ actions["build-csr-csv"] = True
+ actions["build-bitstream"] = True
+ actions["load-bitstream"] = True
+
+ if actions["build-bitstream"]:
+ actions["build-csr-csv"] = True
+ actions["build-bitstream"] = True
+ actions["load-bitstream"] = True
+
+ if actions["clean"]:
+ subprocess.call(["rm", "-rf", "build/*"])
+
+ if actions["build-csr-csv"]:
+ csr_csv = cpuif.get_csr_csv(csr_regions)
+ write_to_file(args.csr_csv, csr_csv)
+
+ if actions["build-core"]:
+ ios = soc.get_ios()
+ if not isinstance(soc, _Fragment):
+ soc = soc.get_fragment()
+ platform.finalize(soc)
+ so = {
+ NoRetiming: XilinxNoRetiming,
+ MultiReg: XilinxMultiReg,
+ AsyncResetSynchronizer: XilinxAsyncResetSynchronizer
+ }
+ v_output = verilog.convert(soc, ios, special_overrides=so)
+ v_output.write("build/litesata.v")
+
+ if actions["build-bitstream"]:
+ vns = platform.build(soc, build_name=build_name, run=True)
+ if hasattr(soc, "do_exit") and vns is not None:
+ if hasattr(soc.do_exit, '__call__'):
+ soc.do_exit(vns)
+
+ if actions["load-bitstream"]:
+ prog = platform.create_programmer()
+ prog.load_bitstream("build/" + build_name + platform.bitstream_ext)
from mibuild.platforms import kc705
_sata_io = [
- ("sata", 0,
- Subsignal("refclk_p", Pins("HPC:GBTCLK0_M2C_P")),
- Subsignal("refclk_n", Pins("HPC:GBTCLK0_M2C_N")),
- Subsignal("txp", Pins("HPC:DP0_C2M_P")),
- Subsignal("txn", Pins("HPC:DP0_C2M_N")),
- Subsignal("rxp", Pins("HPC:DP0_M2C_P")),
- Subsignal("rxn", Pins("HPC:DP0_M2C_N")),
- )
+ ("sata", 0,
+ Subsignal("refclk_p", Pins("HPC:GBTCLK0_M2C_P")),
+ Subsignal("refclk_n", Pins("HPC:GBTCLK0_M2C_N")),
+ Subsignal("txp", Pins("HPC:DP0_C2M_P")),
+ Subsignal("txn", Pins("HPC:DP0_C2M_N")),
+ Subsignal("rxp", Pins("HPC:DP0_M2C_P")),
+ Subsignal("rxn", Pins("HPC:DP0_M2C_N")),
+ )
]
class Platform(kc705.Platform):
- def __init__(self, *args, **kwargs):
- kc705.Platform.__init__(self, *args, **kwargs)
- self.add_extension(_sata_io)
+ def __init__(self, *args, **kwargs):
+ kc705.Platform.__init__(self, *args, **kwargs)
+ self.add_extension(_sata_io)
- def do_finalize(self, fragment):
- try:
- self.add_period_constraint(self.lookup_request("clk156").p, 6.4)
- except ConstraintError:
- pass
- try:
- self.add_period_constraint(self.lookup_request("clk200").p, 5.0)
- except ConstraintError:
- pass
- self.add_platform_command("""
+ def do_finalize(self, fragment):
+ try:
+ self.add_period_constraint(self.lookup_request("clk156").p, 6.4)
+ except ConstraintError:
+ pass
+ try:
+ self.add_period_constraint(self.lookup_request("clk200").p, 5.0)
+ except ConstraintError:
+ pass
+ self.add_platform_command("""
create_clock -name sys_clk -period 6 [get_nets sys_clk]
create_clock -name sata_rx_clk -period 3.33 [get_nets sata_rx_clk]
create_clock -name sata_tx_clk -period 3.33 [get_nets sata_tx_clk]
from mibuild.xilinx.platform import XilinxPlatform
_io = [
- ("sys_clk", 0, Pins("X")),
- ("sys_rst", 1, Pins("X")),
+ ("sys_clk", 0, Pins("X")),
+ ("sys_rst", 1, Pins("X")),
- ("sata", 0,
- Subsignal("refclk_p", Pins("C8")),
- Subsignal("refclk_n", Pins("C7")),
- Subsignal("txp", Pins("D2")),
- Subsignal("txn", Pins("D1")),
- Subsignal("rxp", Pins("E4")),
- Subsignal("rxn", Pins("E3")),
- ),
+ ("sata", 0,
+ Subsignal("refclk_p", Pins("C8")),
+ Subsignal("refclk_n", Pins("C7")),
+ Subsignal("txp", Pins("D2")),
+ Subsignal("txn", Pins("D1")),
+ Subsignal("rxp", Pins("E4")),
+ Subsignal("rxn", Pins("E3")),
+ ),
]
class Platform(XilinxPlatform):
- def __init__(self, device="xc7k325t", programmer=""):
- XilinxPlatform.__init__(self, device, _io)
+ def __init__(self, device="xc7k325t", programmer=""):
+ XilinxPlatform.__init__(self, device, _io)
- def do_finalize(self, *args, **kwargs):
- pass
+ def do_finalize(self, *args, **kwargs):
+ pass
from misoclib.mem.litesata import LiteSATA
class _CRG(Module):
- def __init__(self, platform):
- self.clock_domains.cd_sys = ClockDomain()
- self.reset = Signal()
+ def __init__(self, platform):
+ self.clock_domains.cd_sys = ClockDomain()
+ self.reset = Signal()
- clk200 = platform.request("clk200")
- clk200_se = Signal()
- self.specials += Instance("IBUFDS", i_I=clk200.p, i_IB=clk200.n, o_O=clk200_se)
+ clk200 = platform.request("clk200")
+ clk200_se = Signal()
+ self.specials += Instance("IBUFDS", i_I=clk200.p, i_IB=clk200.n, o_O=clk200_se)
- pll_locked = Signal()
- pll_fb = Signal()
- pll_sys = Signal()
- self.specials += [
- Instance("PLLE2_BASE",
- p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
+ pll_locked = Signal()
+ pll_fb = Signal()
+ pll_sys = Signal()
+ self.specials += [
+ Instance("PLLE2_BASE",
+ p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
- # VCO @ 1GHz
- p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=5.0,
- p_CLKFBOUT_MULT=5, p_DIVCLK_DIVIDE=1,
- i_CLKIN1=clk200_se, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb,
+ # VCO @ 1GHz
+ p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=5.0,
+ p_CLKFBOUT_MULT=5, p_DIVCLK_DIVIDE=1,
+ i_CLKIN1=clk200_se, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb,
- # 166MHz
- p_CLKOUT0_DIVIDE=6, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys,
+ # 166MHz
+ p_CLKOUT0_DIVIDE=6, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys,
- p_CLKOUT1_DIVIDE=2, p_CLKOUT1_PHASE=0.0, #o_CLKOUT1=,
+ p_CLKOUT1_DIVIDE=2, p_CLKOUT1_PHASE=0.0, #o_CLKOUT1=,
- p_CLKOUT2_DIVIDE=2, p_CLKOUT2_PHASE=0.0, #o_CLKOUT2=,
+ p_CLKOUT2_DIVIDE=2, p_CLKOUT2_PHASE=0.0, #o_CLKOUT2=,
- p_CLKOUT3_DIVIDE=2, p_CLKOUT3_PHASE=0.0, #o_CLKOUT3=,
+ p_CLKOUT3_DIVIDE=2, p_CLKOUT3_PHASE=0.0, #o_CLKOUT3=,
- p_CLKOUT4_DIVIDE=2, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4=
- ),
- Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
- AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset") | self.reset),
- ]
+ p_CLKOUT4_DIVIDE=2, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4=
+ ),
+ Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
+ AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset") | self.reset),
+ ]
class BISTLeds(Module):
- def __init__(self, platform, sata_phy):
- # 1Hz blinking leds (sata_rx and sata_tx clocks)
- sata_rx_led = platform.request("user_led", 0)
- sata_tx_led = platform.request("user_led", 1)
-
- sata_rx_cnt = Signal(32)
- sata_tx_cnt = Signal(32)
-
- sata_freq = int(frequencies[sata_phy.revision]*1000*1000)
-
- self.sync.sata_rx += \
- If(sata_rx_cnt == 0,
- sata_rx_led.eq(~sata_rx_led),
- sata_rx_cnt.eq(sata_freq//2)
- ).Else(
- sata_rx_cnt.eq(sata_rx_cnt-1)
- )
-
- self.sync.sata_tx += \
- If(sata_tx_cnt == 0,
- sata_tx_led.eq(~sata_tx_led),
- sata_tx_cnt.eq(sata_freq//2)
- ).Else(
- sata_tx_cnt.eq(sata_tx_cnt-1)
- )
-
- # ready leds (crg and ctrl)
- self.comb += platform.request("user_led", 2).eq(sata_phy.crg.ready)
- self.comb += platform.request("user_led", 3).eq(sata_phy.ctrl.ready)
+ def __init__(self, platform, sata_phy):
+ # 1Hz blinking leds (sata_rx and sata_tx clocks)
+ sata_rx_led = platform.request("user_led", 0)
+ sata_tx_led = platform.request("user_led", 1)
+
+ sata_rx_cnt = Signal(32)
+ sata_tx_cnt = Signal(32)
+
+ sata_freq = int(frequencies[sata_phy.revision]*1000*1000)
+
+ self.sync.sata_rx += \
+ If(sata_rx_cnt == 0,
+ sata_rx_led.eq(~sata_rx_led),
+ sata_rx_cnt.eq(sata_freq//2)
+ ).Else(
+ sata_rx_cnt.eq(sata_rx_cnt-1)
+ )
+
+ self.sync.sata_tx += \
+ If(sata_tx_cnt == 0,
+ sata_tx_led.eq(~sata_tx_led),
+ sata_tx_cnt.eq(sata_freq//2)
+ ).Else(
+ sata_tx_cnt.eq(sata_tx_cnt-1)
+ )
+
+ # ready leds (crg and ctrl)
+ self.comb += platform.request("user_led", 2).eq(sata_phy.crg.ready)
+ self.comb += platform.request("user_led", 3).eq(sata_phy.ctrl.ready)
class BISTSoC(SoC, AutoCSR):
- default_platform = "kc705"
- csr_map = {
- "sata": 10,
- }
- csr_map.update(SoC.csr_map)
- def __init__(self, platform):
- clk_freq = 166*1000000
- SoC.__init__(self, platform, clk_freq,
- cpu_type="none",
- with_csr=True, csr_data_width=32,
- with_uart=False,
- with_identifier=True,
- with_timer=False
- )
- self.add_cpu_or_bridge(LiteScopeUART2WB(platform.request("serial"), clk_freq, baudrate=115200))
- self.add_wb_master(self.cpu_or_bridge.wishbone)
- self.submodules.crg = _CRG(platform)
-
- # SATA PHY/Core/Frontend
- self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata"), "sata_gen2", clk_freq)
- self.comb += self.crg.reset.eq(self.sata_phy.ctrl.need_reset) # XXX FIXME
- self.submodules.sata = LiteSATA(self.sata_phy, with_bist=True, with_bist_csr=True)
-
- # Status Leds
- self.submodules.leds = BISTLeds(platform, self.sata_phy)
+ default_platform = "kc705"
+ csr_map = {
+ "sata": 10,
+ }
+ csr_map.update(SoC.csr_map)
+ def __init__(self, platform):
+ clk_freq = 166*1000000
+ SoC.__init__(self, platform, clk_freq,
+ cpu_type="none",
+ with_csr=True, csr_data_width=32,
+ with_uart=False,
+ with_identifier=True,
+ with_timer=False
+ )
+ self.add_cpu_or_bridge(LiteScopeUART2WB(platform.request("serial"), clk_freq, baudrate=115200))
+ self.add_wb_master(self.cpu_or_bridge.wishbone)
+ self.submodules.crg = _CRG(platform)
+
+ # SATA PHY/Core/Frontend
+ self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata"), "sata_gen2", clk_freq)
+ self.comb += self.crg.reset.eq(self.sata_phy.ctrl.need_reset) # XXX FIXME
+ self.submodules.sata = LiteSATA(self.sata_phy, with_bist=True, with_bist_csr=True)
+
+ # Status Leds
+ self.submodules.leds = BISTLeds(platform, self.sata_phy)
class BISTSoCDevel(BISTSoC, AutoCSR):
- csr_map = {
- "la": 20
- }
- csr_map.update(BISTSoC.csr_map)
- def __init__(self, platform):
- BISTSoC.__init__(self, platform)
-
- self.sata_core_link_rx_fsm_state = Signal(4)
- self.sata_core_link_tx_fsm_state = Signal(4)
- self.sata_core_transport_rx_fsm_state = Signal(4)
- self.sata_core_transport_tx_fsm_state = Signal(4)
- self.sata_core_command_rx_fsm_state = Signal(4)
- self.sata_core_command_tx_fsm_state = Signal(4)
-
- debug = (
- self.sata_phy.ctrl.ready,
-
- self.sata_phy.source.stb,
- self.sata_phy.source.data,
- self.sata_phy.source.charisk,
-
- self.sata_phy.sink.stb,
- self.sata_phy.sink.data,
- self.sata_phy.sink.charisk,
-
- self.sata.core.command.sink.stb,
- self.sata.core.command.sink.sop,
- self.sata.core.command.sink.eop,
- self.sata.core.command.sink.ack,
- self.sata.core.command.sink.write,
- self.sata.core.command.sink.read,
- self.sata.core.command.sink.identify,
-
- self.sata.core.command.source.stb,
- self.sata.core.command.source.sop,
- self.sata.core.command.source.eop,
- self.sata.core.command.source.ack,
- self.sata.core.command.source.write,
- self.sata.core.command.source.read,
- self.sata.core.command.source.identify,
- self.sata.core.command.source.failed,
- self.sata.core.command.source.data,
-
- self.sata_core_link_rx_fsm_state,
- self.sata_core_link_tx_fsm_state,
- self.sata_core_transport_rx_fsm_state,
- self.sata_core_transport_tx_fsm_state,
- self.sata_core_command_rx_fsm_state,
- self.sata_core_command_tx_fsm_state,
- )
-
- self.submodules.la = LiteScopeLA(debug, 2048)
- self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
-
- def do_finalize(self):
- BISTSoC.do_finalize(self)
- self.comb += [
- self.sata_core_link_rx_fsm_state.eq(self.sata.core.link.rx.fsm.state),
- self.sata_core_link_tx_fsm_state.eq(self.sata.core.link.tx.fsm.state),
- self.sata_core_transport_rx_fsm_state.eq(self.sata.core.transport.rx.fsm.state),
- self.sata_core_transport_tx_fsm_state.eq(self.sata.core.transport.tx.fsm.state),
- self.sata_core_command_rx_fsm_state.eq(self.sata.core.command.rx.fsm.state),
- self.sata_core_command_tx_fsm_state.eq(self.sata.core.command.tx.fsm.state)
- ]
-
- def do_exit(self, vns):
- self.la.export(vns, "test/la.csv")
+ csr_map = {
+ "la": 20
+ }
+ csr_map.update(BISTSoC.csr_map)
+ def __init__(self, platform):
+ BISTSoC.__init__(self, platform)
+
+ self.sata_core_link_rx_fsm_state = Signal(4)
+ self.sata_core_link_tx_fsm_state = Signal(4)
+ self.sata_core_transport_rx_fsm_state = Signal(4)
+ self.sata_core_transport_tx_fsm_state = Signal(4)
+ self.sata_core_command_rx_fsm_state = Signal(4)
+ self.sata_core_command_tx_fsm_state = Signal(4)
+
+ debug = (
+ self.sata_phy.ctrl.ready,
+
+ self.sata_phy.source.stb,
+ self.sata_phy.source.data,
+ self.sata_phy.source.charisk,
+
+ self.sata_phy.sink.stb,
+ self.sata_phy.sink.data,
+ self.sata_phy.sink.charisk,
+
+ self.sata.core.command.sink.stb,
+ self.sata.core.command.sink.sop,
+ self.sata.core.command.sink.eop,
+ self.sata.core.command.sink.ack,
+ self.sata.core.command.sink.write,
+ self.sata.core.command.sink.read,
+ self.sata.core.command.sink.identify,
+
+ self.sata.core.command.source.stb,
+ self.sata.core.command.source.sop,
+ self.sata.core.command.source.eop,
+ self.sata.core.command.source.ack,
+ self.sata.core.command.source.write,
+ self.sata.core.command.source.read,
+ self.sata.core.command.source.identify,
+ self.sata.core.command.source.failed,
+ self.sata.core.command.source.data,
+
+ self.sata_core_link_rx_fsm_state,
+ self.sata_core_link_tx_fsm_state,
+ self.sata_core_transport_rx_fsm_state,
+ self.sata_core_transport_tx_fsm_state,
+ self.sata_core_command_rx_fsm_state,
+ self.sata_core_command_tx_fsm_state,
+ )
+
+ self.submodules.la = LiteScopeLA(debug, 2048)
+ self.la.trigger.add_port(LiteScopeTerm(self.la.dw))
+
+ def do_finalize(self):
+ BISTSoC.do_finalize(self)
+ self.comb += [
+ self.sata_core_link_rx_fsm_state.eq(self.sata.core.link.rx.fsm.state),
+ self.sata_core_link_tx_fsm_state.eq(self.sata.core.link.tx.fsm.state),
+ self.sata_core_transport_rx_fsm_state.eq(self.sata.core.transport.rx.fsm.state),
+ self.sata_core_transport_tx_fsm_state.eq(self.sata.core.transport.tx.fsm.state),
+ self.sata_core_command_rx_fsm_state.eq(self.sata.core.command.rx.fsm.state),
+ self.sata_core_command_tx_fsm_state.eq(self.sata.core.command.tx.fsm.state)
+ ]
+
+ def do_exit(self, vns):
+ self.la.export(vns, "test/la.csv")
default_subtarget = BISTSoC
from misoclib.mem.litesata import LiteSATA
class LiteSATACore(Module):
- default_platform = "verilog_backend"
- def __init__(self, platform, clk_freq=166*1000000, nports=4):
- self.clk_freq = clk_freq
+ default_platform = "verilog_backend"
+ def __init__(self, platform, clk_freq=166*1000000, nports=4):
+ self.clk_freq = clk_freq
- # SATA PHY/Core/Frontend
- self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata"), "sata_gen2", clk_freq)
- self.submodules.sata = LiteSATA(self.sata_phy, with_bist=True)
+ # SATA PHY/Core/Frontend
+ self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata"), "sata_gen2", clk_freq)
+ self.submodules.sata = LiteSATA(self.sata_phy, with_bist=True)
- # Get user ports from crossbar
- self.user_ports = self.sata.crossbar.get_ports(nports)
+ # Get user ports from crossbar
+ self.user_ports = self.sata.crossbar.get_ports(nports)
- def get_ios(self):
- ios = set()
+ def get_ios(self):
+ ios = set()
- # Transceiver
- for e in dir(self.sata_phy.pads):
- obj = getattr(self.sata_phy.pads, e)
- if isinstance(obj, Signal):
- ios = ios.union({obj})
+ # Transceiver
+ for e in dir(self.sata_phy.pads):
+ obj = getattr(self.sata_phy.pads, e)
+ if isinstance(obj, Signal):
+ ios = ios.union({obj})
- # Status
- ios = ios.union({
- self.sata_phy.crg.ready,
- self.sata_phy.ctrl.ready
- })
+ # Status
+ ios = ios.union({
+ self.sata_phy.crg.ready,
+ self.sata_phy.ctrl.ready
+ })
- # BIST
- if hasattr(self.sata, "bist"):
- for bist_unit in ["generator", "checker"]:
- for signal in ["start", "sector", "count", "random", "done", "aborted", "errors"]:
- ios = ios.union({getattr(getattr(self.sata.bist, bist_unit), signal)})
- ios = ios.union({
- self.sata.bist.identify.start,
- self.sata.bist.identify.done,
- self.sata.bist.identify.source.stb,
- self.sata.bist.identify.source.data,
- self.sata.bist.identify.source.ack
- })
+ # BIST
+ if hasattr(self.sata, "bist"):
+ for bist_unit in ["generator", "checker"]:
+ for signal in ["start", "sector", "count", "random", "done", "aborted", "errors"]:
+ ios = ios.union({getattr(getattr(self.sata.bist, bist_unit), signal)})
+ ios = ios.union({
+ self.sata.bist.identify.start,
+ self.sata.bist.identify.done,
+ self.sata.bist.identify.source.stb,
+ self.sata.bist.identify.source.data,
+ self.sata.bist.identify.source.ack
+ })
- # User ports
- def _iter_layout(layout):
- for e in layout:
- if isinstance(e[1], list):
- yield from _iter_layout(e[1])
- else:
- yield e
+ # User ports
+ def _iter_layout(layout):
+ for e in layout:
+ if isinstance(e[1], list):
+ yield from _iter_layout(e[1])
+ else:
+ yield e
- for port in self.user_ports:
- for endpoint in [port.sink, port.source]:
- for e in _iter_layout(endpoint.layout):
- obj = getattr(endpoint, e[0])
- ios = ios.union({obj})
- return ios
+ for port in self.user_ports:
+ for endpoint in [port.sink, port.source]:
+ for e in _iter_layout(endpoint.layout):
+ obj = getattr(endpoint, e[0])
+ ios = ios.union({obj})
+ return ios
default_subtarget = LiteSATACore
logical_sector_size = 512
class Timer:
- def __init__(self):
- self.value = None
+ def __init__(self):
+ self.value = None
- def start(self):
- self._start = time.time()
+ def start(self):
+ self._start = time.time()
- def stop(self):
- self._stop = time.time()
- self.value = max(self._stop - self._start, 1/1000000)
+ def stop(self):
+ self._stop = time.time()
+ self.value = max(self._stop - self._start, 1/1000000)
class LiteSATABISTUnitDriver:
- def __init__(self, regs, name):
- self.regs = regs
- self.name = name
- self.frequency = regs.identifier_frequency.read()
- self.time = 0
- for s in ["start", "sector", "count", "loops", "random", "done", "aborted", "errors", "cycles"]:
- setattr(self, s, getattr(regs, name + "_"+ s))
-
- def run(self, sector, count, loops, random, blocking=True, hw_timer=True):
- self.sector.write(sector)
- self.count.write(count)
- self.loops.write(loops)
- self.random.write(random)
- timer = Timer()
- timer.start()
- self.start.write(1)
- if blocking:
- while (self.done.read() == 0):
- pass
- timer.stop()
- aborted = self.aborted.read()
- if not aborted:
- if hw_timer:
- self.time = self.cycles.read()/self.frequency
- else:
- self.time = timer.value
- speed = (loops*count*logical_sector_size)/self.time
- errors = self.errors.read()
- else:
- speed = 0
- errors = -1
- return (aborted, errors, speed)
+ def __init__(self, regs, name):
+ self.regs = regs
+ self.name = name
+ self.frequency = regs.identifier_frequency.read()
+ self.time = 0
+ for s in ["start", "sector", "count", "loops", "random", "done", "aborted", "errors", "cycles"]:
+ setattr(self, s, getattr(regs, name + "_"+ s))
+
+ def run(self, sector, count, loops, random, blocking=True, hw_timer=True):
+ self.sector.write(sector)
+ self.count.write(count)
+ self.loops.write(loops)
+ self.random.write(random)
+ timer = Timer()
+ timer.start()
+ self.start.write(1)
+ if blocking:
+ while (self.done.read() == 0):
+ pass
+ timer.stop()
+ aborted = self.aborted.read()
+ if not aborted:
+ if hw_timer:
+ self.time = self.cycles.read()/self.frequency
+ else:
+ self.time = timer.value
+ speed = (loops*count*logical_sector_size)/self.time
+ errors = self.errors.read()
+ else:
+ speed = 0
+ errors = -1
+ return (aborted, errors, speed)
class LiteSATABISTGeneratorDriver(LiteSATABISTUnitDriver):
- def __init__(self, regs, name):
- LiteSATABISTUnitDriver.__init__(self, regs, name + "_generator")
+ def __init__(self, regs, name):
+ LiteSATABISTUnitDriver.__init__(self, regs, name + "_generator")
class LiteSATABISTCheckerDriver(LiteSATABISTUnitDriver):
- def __init__(self, regs, name):
- LiteSATABISTUnitDriver.__init__(self, regs, name + "_checker")
+ def __init__(self, regs, name):
+ LiteSATABISTUnitDriver.__init__(self, regs, name + "_checker")
class LiteSATABISTIdentifyDriver:
- def __init__(self, regs, name):
- self.regs = regs
- self.name = name
- for s in ["start", "done", "source_stb", "source_ack", "source_data"]:
- setattr(self, s, getattr(regs, name + "_identify_"+ s))
- self.data = []
-
- def read_fifo(self):
- self.data = []
- while self.source_stb.read():
- dword = self.source_data.read()
- word_lsb = dword & 0xffff
- word_msb = (dword >> 16) & 0xffff
- self.data += [word_lsb, word_msb]
- self.source_ack.write(1)
-
- def run(self, blocking=True):
- self.read_fifo() # flush the fifo before we start
- self.start.write(1)
- if blocking:
- while (self.done.read() == 0):
- pass
- self.read_fifo()
- self.decode()
-
- def decode(self):
- self.serial_number = ""
- for i, word in enumerate(self.data[10:20]):
- s = word.to_bytes(2, byteorder='big').decode("utf-8")
- self.serial_number += s
- self.firmware_revision = ""
- for i, word in enumerate(self.data[23:27]):
- s = word.to_bytes(2, byteorder='big').decode("utf-8")
- self.firmware_revision += s
- self.model_number = ""
- for i, word in enumerate(self.data[27:46]):
- s = word.to_bytes(2, byteorder='big').decode("utf-8")
- self.model_number += s
-
- self.total_sectors = self.data[100]
- self.total_sectors += (self.data[101] << 16)
- self.total_sectors += (self.data[102] << 32)
- self.total_sectors += (self.data[103] << 48)
-
- self.capabilities = OrderedDict()
- self.capabilities["SATA Gen1"] = (self.data[76] >> 1) & 0x1
- self.capabilities["SATA Gen2"] = (self.data[76] >> 2) & 0x1
- self.capabilities["SATA Gen3"] = (self.data[76] >> 3) & 0x1
- self.capabilities["48 bits LBA supported"] = (self.data[83] >> 10) & 0x1
-
- def hdd_info(self):
- info = "Serial Number: " + self.serial_number + "\n"
- info += "Firmware Revision: " + self.firmware_revision + "\n"
- info += "Model Number: " + self.model_number + "\n"
- info += "Capacity: %3.2f GB\n" %((self.total_sectors*logical_sector_size)/GB)
- for k, v in self.capabilities.items():
- info += k + ": " + str(v) + "\n"
- print(info, end="")
+ def __init__(self, regs, name):
+ self.regs = regs
+ self.name = name
+ for s in ["start", "done", "source_stb", "source_ack", "source_data"]:
+ setattr(self, s, getattr(regs, name + "_identify_"+ s))
+ self.data = []
+
+ def read_fifo(self):
+ self.data = []
+ while self.source_stb.read():
+ dword = self.source_data.read()
+ word_lsb = dword & 0xffff
+ word_msb = (dword >> 16) & 0xffff
+ self.data += [word_lsb, word_msb]
+ self.source_ack.write(1)
+
+ def run(self, blocking=True):
+ self.read_fifo() # flush the fifo before we start
+ self.start.write(1)
+ if blocking:
+ while (self.done.read() == 0):
+ pass
+ self.read_fifo()
+ self.decode()
+
+ def decode(self):
+ self.serial_number = ""
+ for i, word in enumerate(self.data[10:20]):
+ s = word.to_bytes(2, byteorder='big').decode("utf-8")
+ self.serial_number += s
+ self.firmware_revision = ""
+ for i, word in enumerate(self.data[23:27]):
+ s = word.to_bytes(2, byteorder='big').decode("utf-8")
+ self.firmware_revision += s
+ self.model_number = ""
+ for i, word in enumerate(self.data[27:46]):
+ s = word.to_bytes(2, byteorder='big').decode("utf-8")
+ self.model_number += s
+
+ self.total_sectors = self.data[100]
+ self.total_sectors += (self.data[101] << 16)
+ self.total_sectors += (self.data[102] << 32)
+ self.total_sectors += (self.data[103] << 48)
+
+ self.capabilities = OrderedDict()
+ self.capabilities["SATA Gen1"] = (self.data[76] >> 1) & 0x1
+ self.capabilities["SATA Gen2"] = (self.data[76] >> 2) & 0x1
+ self.capabilities["SATA Gen3"] = (self.data[76] >> 3) & 0x1
+ self.capabilities["48 bits LBA supported"] = (self.data[83] >> 10) & 0x1
+
+ def hdd_info(self):
+ info = "Serial Number: " + self.serial_number + "\n"
+ info += "Firmware Revision: " + self.firmware_revision + "\n"
+ info += "Model Number: " + self.model_number + "\n"
+ info += "Capacity: %3.2f GB\n" %((self.total_sectors*logical_sector_size)/GB)
+ for k, v in self.capabilities.items():
+ info += k + ": " + str(v) + "\n"
+ print(info, end="")
def _get_args():
- parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
- description="""\
+ parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="""\
SATA BIST utility.
""")
- parser.add_argument("--port", default=2, help="UART port")
- parser.add_argument("--baudrate", default=115200, help="UART baudrate")
- parser.add_argument("--busword", default=32, help="CSR busword")
- parser.add_argument("-s", "--transfer_size", default=1024, help="transfer sizes (in KB, up to 16MB)")
- parser.add_argument("-l", "--total_length", default=256, help="total transfer length (in MB, up to HDD capacity)")
- parser.add_argument("-n", "--loops", default=1, help="number of loop per transfer (allow more precision on speed calculation for small transfers)")
- parser.add_argument("-r", "--random", action="store_true", help="use random data")
- parser.add_argument("-c", "--continuous", action="store_true", help="continuous mode (Escape to exit)")
- parser.add_argument("-i", "--identify", action="store_true", help="only run identify")
- parser.add_argument("-t", "--software_timer", action="store_true", help="use software timer")
- parser.add_argument("-a", "--random_addressing", action="store_true", help="use random addressing")
- return parser.parse_args()
+ parser.add_argument("--port", default=2, help="UART port")
+ parser.add_argument("--baudrate", default=115200, help="UART baudrate")
+ parser.add_argument("--busword", default=32, help="CSR busword")
+ parser.add_argument("-s", "--transfer_size", default=1024, help="transfer sizes (in KB, up to 16MB)")
+ parser.add_argument("-l", "--total_length", default=256, help="total transfer length (in MB, up to HDD capacity)")
+ parser.add_argument("-n", "--loops", default=1, help="number of loop per transfer (allow more precision on speed calculation for small transfers)")
+ parser.add_argument("-r", "--random", action="store_true", help="use random data")
+ parser.add_argument("-c", "--continuous", action="store_true", help="continuous mode (Escape to exit)")
+ parser.add_argument("-i", "--identify", action="store_true", help="only run identify")
+ parser.add_argument("-t", "--software_timer", action="store_true", help="use software timer")
+ parser.add_argument("-a", "--random_addressing", action="store_true", help="use random addressing")
+ return parser.parse_args()
if __name__ == "__main__":
- args = _get_args()
- wb = LiteScopeUARTDriver(args.port, args.baudrate, "./csr.csv", int(args.busword), debug=False)
- wb.open()
- ###
- identify = LiteSATABISTIdentifyDriver(wb.regs, "sata_bist")
- generator = LiteSATABISTGeneratorDriver(wb.regs, "sata_bist")
- checker = LiteSATABISTCheckerDriver(wb.regs, "sata_bist")
-
- identify.run()
- identify.hdd_info()
-
- if not int(args.identify):
- sector = 0
- count = int(args.transfer_size)*KB//logical_sector_size
- loops = int(args.loops)
- length = int(args.total_length)*MB
- random = int(args.random)
- continuous = int(args.continuous)
- sw_timer = int(args.software_timer)
- random_addressing = int(args.random_addressing)
-
- run_sectors = 0
- try:
- while ((run_sectors*logical_sector_size < length) or continuous) and (sector < identify.total_sectors):
- retry = 0
- # generator (write data to HDD)
- write_done = False
- while not write_done:
- write_aborted, write_errors, write_speed = generator.run(sector, count, loops, random, True, not sw_timer)
- write_done = not write_aborted
- if not write_done:
- retry += 1
-
- # checker (read and check data from HDD)
- read_done = False
- while not read_done:
- read_aborted, read_errors, read_speed = checker.run(sector, count, loops, random, True, not sw_timer)
- read_done = not read_aborted
- if not read_done:
- retry += 1
-
- print("sector=%d(%dMB) wr_speed=%4.2fMB/s rd_speed=%4.2fMB/s errors=%d retry=%d" %(
- sector,
- run_sectors*logical_sector_size/MB,
- write_speed/MB,
- read_speed/MB,
- write_errors + read_errors,
- retry))
- if random_addressing:
- sector = rand.randint(0, identify.total_sectors//(256*2))*256
- else:
- sector += count
- run_sectors += count
-
- except KeyboardInterrupt:
- pass
- ###
- wb.close()
+ args = _get_args()
+ wb = LiteScopeUARTDriver(args.port, args.baudrate, "./csr.csv", int(args.busword), debug=False)
+ wb.open()
+ ###
+ identify = LiteSATABISTIdentifyDriver(wb.regs, "sata_bist")
+ generator = LiteSATABISTGeneratorDriver(wb.regs, "sata_bist")
+ checker = LiteSATABISTCheckerDriver(wb.regs, "sata_bist")
+
+ identify.run()
+ identify.hdd_info()
+
+ if not int(args.identify):
+ sector = 0
+ count = int(args.transfer_size)*KB//logical_sector_size
+ loops = int(args.loops)
+ length = int(args.total_length)*MB
+ random = int(args.random)
+ continuous = int(args.continuous)
+ sw_timer = int(args.software_timer)
+ random_addressing = int(args.random_addressing)
+
+ run_sectors = 0
+ try:
+ while ((run_sectors*logical_sector_size < length) or continuous) and (sector < identify.total_sectors):
+ retry = 0
+ # generator (write data to HDD)
+ write_done = False
+ while not write_done:
+ write_aborted, write_errors, write_speed = generator.run(sector, count, loops, random, True, not sw_timer)
+ write_done = not write_aborted
+ if not write_done:
+ retry += 1
+
+ # checker (read and check data from HDD)
+ read_done = False
+ while not read_done:
+ read_aborted, read_errors, read_speed = checker.run(sector, count, loops, random, True, not sw_timer)
+ read_done = not read_aborted
+ if not read_done:
+ retry += 1
+
+ print("sector=%d(%dMB) wr_speed=%4.2fMB/s rd_speed=%4.2fMB/s errors=%d retry=%d" %(
+ sector,
+ run_sectors*logical_sector_size/MB,
+ write_speed/MB,
+ read_speed/MB,
+ write_errors + read_errors,
+ retry))
+ if random_addressing:
+ sector = rand.randint(0, identify.total_sectors//(256*2))*256
+ else:
+ sector += count
+ run_sectors += count
+
+ except KeyboardInterrupt:
+ pass
+ ###
+ wb.close()
import argparse, importlib
def _get_args():
- parser = argparse.ArgumentParser()
- parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use")
- parser.add_argument("--port", default="2", help="UART port")
- parser.add_argument("--baudrate", default=115200, help="UART baudrate")
- parser.add_argument("--ip_address", default="192.168.0.42", help="Etherbone IP address")
- parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port")
- parser.add_argument("--busword", default=32, help="CSR busword")
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-b", "--bridge", default="uart", help="Bridge to use")
+ parser.add_argument("--port", default="2", help="UART port")
+ parser.add_argument("--baudrate", default=115200, help="UART baudrate")
+ parser.add_argument("--ip_address", default="192.168.0.42", help="Etherbone IP address")
+ parser.add_argument("--udp_port", default=20000, help="Etherbone UDP port")
+ parser.add_argument("--busword", default=32, help="CSR busword")
- parser.add_argument("test", nargs="+", help="specify a test")
+ parser.add_argument("test", nargs="+", help="specify a test")
- return parser.parse_args()
+ return parser.parse_args()
if __name__ == "__main__":
- args = _get_args()
- if args.bridge == "uart":
- from misoclib.tools.litescope.host.driver.uart import LiteScopeUARTDriver
- port = args.port if not args.port.isdigit() else int(args.port)
- wb = LiteScopeUARTDriver(port, args.baudrate, "./csr.csv", int(args.busword), debug=False)
- elif args.bridge == "etherbone":
- from misoclib.tools.litescope.host.driver.etherbone import LiteScopeEtherboneDriver
- wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False)
- else:
- ValueError("Invalid bridge {}".format(args.bridge))
+ args = _get_args()
+ if args.bridge == "uart":
+ from misoclib.tools.litescope.host.driver.uart import LiteScopeUARTDriver
+ port = args.port if not args.port.isdigit() else int(args.port)
+ wb = LiteScopeUARTDriver(port, args.baudrate, "./csr.csv", int(args.busword), debug=False)
+ elif args.bridge == "etherbone":
+ from misoclib.tools.litescope.host.driver.etherbone import LiteScopeEtherboneDriver
+ wb = LiteScopeEtherboneDriver(args.ip_address, int(args.udp_port), "./csr.csv", int(args.busword), debug=False)
+ else:
+ ValueError("Invalid bridge {}".format(args.bridge))
- def _import(name):
- return importlib.import_module(name)
+ def _import(name):
+ return importlib.import_module(name)
- for test in args.test:
- t = _import(test)
- t.main(wb)
+ for test in args.test:
+ t = _import(test)
+ t.main(wb)
from litescope.host.driver.la import LiteScopeLADriver
def main(wb):
- la = LiteScopeLADriver(wb.regs, "la")
- identify = LiteSATABISTIdentifyDriver(wb.regs, "sata_bist")
- generator = LiteSATABISTGeneratorDriver(wb.regs, "sata_bist")
- checker = LiteSATABISTCheckerDriver(wb.regs, "sata_bist")
- wb.open()
- regs = wb.regs
- ###
+ la = LiteScopeLADriver(wb.regs, "la")
+ identify = LiteSATABISTIdentifyDriver(wb.regs, "sata_bist")
+ generator = LiteSATABISTGeneratorDriver(wb.regs, "sata_bist")
+ checker = LiteSATABISTCheckerDriver(wb.regs, "sata_bist")
+ wb.open()
+ regs = wb.regs
+ ###
- trig = "now"
- if len(sys.argv) < 2:
- print("No trigger condition, triggering immediately!")
- else:
- trig = sys.argv[1]
+ trig = "now"
+ if len(sys.argv) < 2:
+ print("No trigger condition, triggering immediately!")
+ else:
+ trig = sys.argv[1]
- conditions = {}
- conditions["now"] = {}
- conditions["id_cmd"] = {
- "sata_command_tx_sink_stb" : 1,
- "sata_command_tx_sink_payload_identify" : 1,
- }
- conditions["id_resp"] = {
- "source_source_payload_data" : primitives["X_RDY"],
- }
- conditions["wr_cmd"] = {
- "sata_command_tx_sink_stb" : 1,
- "sata_command_tx_sink_payload_write" : 1,
- }
- conditions["wr_resp"] = {
- "sata_command_rx_source_stb" : 1,
- "sata_command_rx_source_payload_write" : 1,
- }
- conditions["rd_cmd"] = {
- "sata_command_tx_sink_stb" : 1,
- "sata_command_tx_sink_payload_read" : 1,
- }
- conditions["rd_resp"] = {
- "sata_command_rx_source_stb" : 1,
- "sata_command_rx_source_payload_read" : 1,
- }
+ conditions = {}
+ conditions["now"] = {}
+ conditions["id_cmd"] = {
+ "sata_command_tx_sink_stb" : 1,
+ "sata_command_tx_sink_payload_identify" : 1,
+ }
+ conditions["id_resp"] = {
+ "source_source_payload_data" : primitives["X_RDY"],
+ }
+ conditions["wr_cmd"] = {
+ "sata_command_tx_sink_stb" : 1,
+ "sata_command_tx_sink_payload_write" : 1,
+ }
+ conditions["wr_resp"] = {
+ "sata_command_rx_source_stb" : 1,
+ "sata_command_rx_source_payload_write" : 1,
+ }
+ conditions["rd_cmd"] = {
+ "sata_command_tx_sink_stb" : 1,
+ "sata_command_tx_sink_payload_read" : 1,
+ }
+ conditions["rd_resp"] = {
+ "sata_command_rx_source_stb" : 1,
+ "sata_command_rx_source_payload_read" : 1,
+ }
- la.configure_term(port=0, cond=conditions[trig])
- la.configure_sum("term")
+ la.configure_term(port=0, cond=conditions[trig])
+ la.configure_sum("term")
- # Run Logic Analyzer
- la.run(offset=64, length=1024)
+ # Run Logic Analyzer
+ la.run(offset=64, length=1024)
- #identify.run(blocking=False)
- generator.run(0, 2, 1, 0, blocking=False)
- #checker.run(0, 2, 1, 0, blocking=False)
+ #identify.run(blocking=False)
+ generator.run(0, 2, 1, 0, blocking=False)
+ #checker.run(0, 2, 1, 0, blocking=False)
- while not la.done():
- pass
+ while not la.done():
+ pass
- la.upload()
- la.save("dump.vcd")
- ###
- wb.close()
+ la.upload()
+ la.save("dump.vcd")
+ ###
+ wb.close()
- f = open("dump_link.txt", "w")
- data = link_trace(la,
- tx_data_name="sink_sink_payload_data",
- rx_data_name="source_source_payload_data"
- )
- f.write(data)
- f.close()
+ f = open("dump_link.txt", "w")
+ data = link_trace(la,
+ tx_data_name="sink_sink_payload_data",
+ rx_data_name="source_source_payload_data"
+ )
+ f.write(data)
+ f.close()
def main(wb):
- wb.open()
- regs = wb.regs
- ###
- print("sysid : 0x{:04x}".format(regs.identifier_sysid.read()))
- print("revision : 0x{:04x}".format(regs.identifier_revision.read()))
- print("frequency : {}MHz".format(int(regs.identifier_frequency.read()/1000000)))
- ###
- wb.close()
+ wb.open()
+ regs = wb.regs
+ ###
+ print("sysid : 0x{:04x}".format(regs.identifier_sysid.read()))
+ print("revision : 0x{:04x}".format(regs.identifier_revision.read()))
+ print("frequency : {}MHz".format(int(regs.identifier_frequency.read()/1000000)))
+ ###
+ wb.close()
from litescope.host.dump import *
primitives = {
- "ALIGN" : 0x7B4A4ABC,
- "CONT" : 0X9999AA7C,
- "SYNC" : 0xB5B5957C,
- "R_RDY" : 0x4A4A957C,
- "R_OK" : 0x3535B57C,
- "R_ERR" : 0x5656B57C,
- "R_IP" : 0X5555B57C,
- "X_RDY" : 0x5757B57C,
- "CONT" : 0x9999AA7C,
- "WTRM" : 0x5858B57C,
- "SOF" : 0x3737B57C,
- "EOF" : 0xD5D5B57C,
- "HOLD" : 0xD5D5AA7C,
- "HOLDA" : 0X9595AA7C
+ "ALIGN" : 0x7B4A4ABC,
+ "CONT" : 0X9999AA7C,
+ "SYNC" : 0xB5B5957C,
+ "R_RDY" : 0x4A4A957C,
+ "R_OK" : 0x3535B57C,
+ "R_ERR" : 0x5656B57C,
+ "R_IP" : 0X5555B57C,
+ "X_RDY" : 0x5757B57C,
+ "CONT" : 0x9999AA7C,
+ "WTRM" : 0x5858B57C,
+ "SOF" : 0x3737B57C,
+ "EOF" : 0xD5D5B57C,
+ "HOLD" : 0xD5D5AA7C,
+ "HOLDA" : 0X9595AA7C
}
def decode_primitive(dword):
- for k, v in primitives.items():
- if dword == v:
- return k
- return ""
+ for k, v in primitives.items():
+ if dword == v:
+ return k
+ return ""
def link_trace(mila, tx_data_name, rx_data_name):
- r = ""
- dump = Dump()
- dump.add_from_layout(mila.layout, mila.dat)
+ r = ""
+ dump = Dump()
+ dump.add_from_layout(mila.layout, mila.dat)
- for var in dump.vars:
- if var.name == tx_data_name:
- tx_data = var.values
- if var.name == rx_data_name:
- rx_data = var.values
+ for var in dump.vars:
+ if var.name == tx_data_name:
+ tx_data = var.values
+ if var.name == rx_data_name:
+ rx_data = var.values
- for i in range(len(tx_data)):
- tx = "%08x " %tx_data[i]
- tx += decode_primitive(tx_data[i])
- tx += " "*(16-len(tx))
+ for i in range(len(tx_data)):
+ tx = "%08x " %tx_data[i]
+ tx += decode_primitive(tx_data[i])
+ tx += " "*(16-len(tx))
- rx = "%08x " %rx_data[i]
- rx += decode_primitive(rx_data[i])
- rx += " "*(16-len(rx))
+ rx = "%08x " %rx_data[i]
+ rx += decode_primitive(rx_data[i])
+ rx += " "*(16-len(rx))
- r += tx + rx + "\n"
+ r += tx + rx + "\n"
- return r
+ return r
from migen.genlib.roundrobin import *
class LiteSATAArbiter(Module):
- def __init__(self, users, master):
- self.rr = RoundRobin(len(users))
- self.submodules += self.rr
- self.grant = self.rr.grant
- cases = {}
- for i, slave in enumerate(users):
- sink, source = slave.sink, slave.source
- start = Signal()
- done = Signal()
- ongoing = Signal()
- self.comb += [
- start.eq(sink.stb & sink.sop),
- done.eq(source.stb & source.last & source.eop & source.ack)
- ]
- self.sync += \
- If(start,
- ongoing.eq(1)
- ).Elif(done,
- ongoing.eq(0)
- )
- self.comb += self.rr.request[i].eq((start | ongoing) & ~done)
- cases[i] = [users[i].connect(master)]
- self.comb += Case(self.grant, cases)
+ def __init__(self, users, master):
+ self.rr = RoundRobin(len(users))
+ self.submodules += self.rr
+ self.grant = self.rr.grant
+ cases = {}
+ for i, slave in enumerate(users):
+ sink, source = slave.sink, slave.source
+ start = Signal()
+ done = Signal()
+ ongoing = Signal()
+ self.comb += [
+ start.eq(sink.stb & sink.sop),
+ done.eq(source.stb & source.last & source.eop & source.ack)
+ ]
+ self.sync += \
+ If(start,
+ ongoing.eq(1)
+ ).Elif(done,
+ ongoing.eq(0)
+ )
+ self.comb += self.rr.request[i].eq((start | ongoing) & ~done)
+ cases[i] = [users[i].connect(master)]
+ self.comb += Case(self.grant, cases)
from migen.bank.description import *
class LiteSATABISTGenerator(Module):
- def __init__(self, user_port):
- self.start = Signal()
- self.sector = Signal(48)
- self.count = Signal(16)
- self.random = Signal()
-
- self.done = Signal()
- self.aborted = Signal()
- self.errors = Signal(32) # Note: Not used for writes
-
- ###
-
- source, sink = user_port.sink, user_port.source
-
- counter = Counter(32)
- self.submodules += counter
-
- scrambler = scrambler = InsertReset(Scrambler())
- self.submodules += scrambler
- self.comb += [
- scrambler.reset.eq(counter.reset),
- scrambler.ce.eq(counter.ce)
- ]
-
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- self.done.eq(1),
- counter.reset.eq(1),
- If(self.start,
- NextState("SEND_CMD_AND_DATA")
- )
- )
- self.comb += [
- source.sop.eq(counter.value == 0),
- source.eop.eq(counter.value == (logical_sector_size//4*self.count)-1),
- source.write.eq(1),
- source.sector.eq(self.sector),
- source.count.eq(self.count),
- If(self.random,
- source.data.eq(scrambler.value)
- ).Else(
- source.data.eq(counter.value)
- )
- ]
- fsm.act("SEND_CMD_AND_DATA",
- source.stb.eq(1),
- If(source.stb & source.ack,
- counter.ce.eq(1),
- If(source.eop,
- NextState("WAIT_ACK")
- )
- )
- )
- fsm.act("WAIT_ACK",
- sink.ack.eq(1),
- If(sink.stb,
- NextState("IDLE")
- )
- )
- self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed))
+ def __init__(self, user_port):
+ self.start = Signal()
+ self.sector = Signal(48)
+ self.count = Signal(16)
+ self.random = Signal()
+
+ self.done = Signal()
+ self.aborted = Signal()
+ self.errors = Signal(32) # Note: Not used for writes
+
+ ###
+
+ source, sink = user_port.sink, user_port.source
+
+ counter = Counter(32)
+ self.submodules += counter
+
+ scrambler = scrambler = InsertReset(Scrambler())
+ self.submodules += scrambler
+ self.comb += [
+ scrambler.reset.eq(counter.reset),
+ scrambler.ce.eq(counter.ce)
+ ]
+
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ self.done.eq(1),
+ counter.reset.eq(1),
+ If(self.start,
+ NextState("SEND_CMD_AND_DATA")
+ )
+ )
+ self.comb += [
+ source.sop.eq(counter.value == 0),
+ source.eop.eq(counter.value == (logical_sector_size//4*self.count)-1),
+ source.write.eq(1),
+ source.sector.eq(self.sector),
+ source.count.eq(self.count),
+ If(self.random,
+ source.data.eq(scrambler.value)
+ ).Else(
+ source.data.eq(counter.value)
+ )
+ ]
+ fsm.act("SEND_CMD_AND_DATA",
+ source.stb.eq(1),
+ If(source.stb & source.ack,
+ counter.ce.eq(1),
+ If(source.eop,
+ NextState("WAIT_ACK")
+ )
+ )
+ )
+ fsm.act("WAIT_ACK",
+ sink.ack.eq(1),
+ If(sink.stb,
+ NextState("IDLE")
+ )
+ )
+ self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed))
class LiteSATABISTChecker(Module):
- def __init__(self, user_port):
- self.start = Signal()
- self.sector = Signal(48)
- self.count = Signal(16)
- self.random = Signal()
-
- self.done = Signal()
- self.aborted = Signal()
- self.errors = Signal(32)
-
- ###
-
- source, sink = user_port.sink, user_port.source
-
- counter = Counter(32)
- error_counter = Counter(32)
- self.submodules += counter, error_counter
- self.comb += self.errors.eq(error_counter.value)
-
- scrambler = InsertReset(Scrambler())
- self.submodules += scrambler
- self.comb += [
- scrambler.reset.eq(counter.reset),
- scrambler.ce.eq(counter.ce)
- ]
-
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += self.fsm
- fsm.act("IDLE",
- self.done.eq(1),
- counter.reset.eq(1),
- If(self.start,
- error_counter.reset.eq(1),
- NextState("SEND_CMD")
- )
- )
- self.comb += [
- source.sop.eq(1),
- source.eop.eq(1),
- source.read.eq(1),
- source.sector.eq(self.sector),
- source.count.eq(self.count),
- ]
- fsm.act("SEND_CMD",
- source.stb.eq(1),
- If(source.ack,
- counter.reset.eq(1),
- NextState("WAIT_ACK")
- )
- )
- fsm.act("WAIT_ACK",
- If(sink.stb & sink.read,
- NextState("RECEIVE_DATA")
- )
- )
- expected_data = Signal(32)
- self.comb += \
- If(self.random,
- expected_data.eq(scrambler.value)
- ).Else(
- expected_data.eq(counter.value)
- )
- fsm.act("RECEIVE_DATA",
- sink.ack.eq(1),
- If(sink.stb,
- counter.ce.eq(1),
- If(sink.data != expected_data,
- error_counter.ce.eq(~sink.last)
- ),
- If(sink.eop,
- If(sink.last,
- NextState("IDLE")
- ).Else(
- NextState("WAIT_ACK")
- )
- )
- )
- )
- self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed))
+ def __init__(self, user_port):
+ self.start = Signal()
+ self.sector = Signal(48)
+ self.count = Signal(16)
+ self.random = Signal()
+
+ self.done = Signal()
+ self.aborted = Signal()
+ self.errors = Signal(32)
+
+ ###
+
+ source, sink = user_port.sink, user_port.source
+
+ counter = Counter(32)
+ error_counter = Counter(32)
+ self.submodules += counter, error_counter
+ self.comb += self.errors.eq(error_counter.value)
+
+ scrambler = InsertReset(Scrambler())
+ self.submodules += scrambler
+ self.comb += [
+ scrambler.reset.eq(counter.reset),
+ scrambler.ce.eq(counter.ce)
+ ]
+
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += self.fsm
+ fsm.act("IDLE",
+ self.done.eq(1),
+ counter.reset.eq(1),
+ If(self.start,
+ error_counter.reset.eq(1),
+ NextState("SEND_CMD")
+ )
+ )
+ self.comb += [
+ source.sop.eq(1),
+ source.eop.eq(1),
+ source.read.eq(1),
+ source.sector.eq(self.sector),
+ source.count.eq(self.count),
+ ]
+ fsm.act("SEND_CMD",
+ source.stb.eq(1),
+ If(source.ack,
+ counter.reset.eq(1),
+ NextState("WAIT_ACK")
+ )
+ )
+ fsm.act("WAIT_ACK",
+ If(sink.stb & sink.read,
+ NextState("RECEIVE_DATA")
+ )
+ )
+ expected_data = Signal(32)
+ self.comb += \
+ If(self.random,
+ expected_data.eq(scrambler.value)
+ ).Else(
+ expected_data.eq(counter.value)
+ )
+ fsm.act("RECEIVE_DATA",
+ sink.ack.eq(1),
+ If(sink.stb,
+ counter.ce.eq(1),
+ If(sink.data != expected_data,
+ error_counter.ce.eq(~sink.last)
+ ),
+ If(sink.eop,
+ If(sink.last,
+ NextState("IDLE")
+ ).Else(
+ NextState("WAIT_ACK")
+ )
+ )
+ )
+ )
+ self.sync += If(sink.stb & sink.ack, self.aborted.eq(sink.failed))
class LiteSATABISTUnitCSR(Module, AutoCSR):
- def __init__(self, bist_unit):
- self._start = CSR()
- self._sector = CSRStorage(48)
- self._count = CSRStorage(16)
- self._loops = CSRStorage(8)
- self._random = CSRStorage()
-
- self._done = CSRStatus()
- self._aborted = CSRStatus()
- self._errors = CSRStatus(32)
- self._cycles = CSRStatus(32)
-
- ###
-
- self.submodules += bist_unit
-
- start = self._start.r & self._start.re
- done = self._done.status
- loops = self._loops.storage
-
- self.comb += [
- bist_unit.sector.eq(self._sector.storage),
- bist_unit.count.eq(self._count.storage),
- bist_unit.random.eq(self._random.storage),
-
- self._aborted.status.eq(bist_unit.aborted),
- self._errors.status.eq(bist_unit.errors)
- ]
-
- self.fsm = fsm = FSM(reset_state="IDLE")
- loop_counter = Counter(8)
- self.submodules += fsm, loop_counter
- fsm.act("IDLE",
- self._done.status.eq(1),
- loop_counter.reset.eq(1),
- If(start,
- NextState("CHECK")
- )
- )
- fsm.act("CHECK",
- If(loop_counter.value < loops,
- NextState("START")
- ).Else(
- NextState("IDLE")
- )
- )
- fsm.act("START",
- bist_unit.start.eq(1),
- NextState("WAIT_DONE")
- )
- fsm.act("WAIT_DONE",
- If(bist_unit.done,
- loop_counter.ce.eq(1),
- NextState("CHECK")
- )
- )
-
- cycles_counter = Counter(32)
- self.submodules += cycles_counter
- self.sync += [
- cycles_counter.reset.eq(start),
- cycles_counter.ce.eq(~fsm.ongoing("IDLE")),
- self._cycles.status.eq(cycles_counter.value)
- ]
+ def __init__(self, bist_unit):
+ self._start = CSR()
+ self._sector = CSRStorage(48)
+ self._count = CSRStorage(16)
+ self._loops = CSRStorage(8)
+ self._random = CSRStorage()
+
+ self._done = CSRStatus()
+ self._aborted = CSRStatus()
+ self._errors = CSRStatus(32)
+ self._cycles = CSRStatus(32)
+
+ ###
+
+ self.submodules += bist_unit
+
+ start = self._start.r & self._start.re
+ done = self._done.status
+ loops = self._loops.storage
+
+ self.comb += [
+ bist_unit.sector.eq(self._sector.storage),
+ bist_unit.count.eq(self._count.storage),
+ bist_unit.random.eq(self._random.storage),
+
+ self._aborted.status.eq(bist_unit.aborted),
+ self._errors.status.eq(bist_unit.errors)
+ ]
+
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ loop_counter = Counter(8)
+ self.submodules += fsm, loop_counter
+ fsm.act("IDLE",
+ self._done.status.eq(1),
+ loop_counter.reset.eq(1),
+ If(start,
+ NextState("CHECK")
+ )
+ )
+ fsm.act("CHECK",
+ If(loop_counter.value < loops,
+ NextState("START")
+ ).Else(
+ NextState("IDLE")
+ )
+ )
+ fsm.act("START",
+ bist_unit.start.eq(1),
+ NextState("WAIT_DONE")
+ )
+ fsm.act("WAIT_DONE",
+ If(bist_unit.done,
+ loop_counter.ce.eq(1),
+ NextState("CHECK")
+ )
+ )
+
+ cycles_counter = Counter(32)
+ self.submodules += cycles_counter
+ self.sync += [
+ cycles_counter.reset.eq(start),
+ cycles_counter.ce.eq(~fsm.ongoing("IDLE")),
+ self._cycles.status.eq(cycles_counter.value)
+ ]
class LiteSATABISTIdentify(Module):
- def __init__(self, user_port):
- self.start = Signal()
- self.done = Signal()
-
- fifo = SyncFIFO([("data", 32)], 512, buffered=True)
- self.submodules += fifo
- self.source = fifo.source
-
- ###
-
- source, sink = user_port.sink, user_port.source
-
- self.fsm = fsm = FSM(reset_state="IDLE")
- self.submodules += fsm
- fsm.act("IDLE",
- self.done.eq(1),
- If(self.start,
- NextState("SEND_CMD")
- )
- )
- self.comb += [
- source.sop.eq(1),
- source.eop.eq(1),
- source.identify.eq(1),
- ]
- fsm.act("SEND_CMD",
- source.stb.eq(1),
- If(source.stb & source.ack,
- NextState("WAIT_ACK")
- )
- )
- fsm.act("WAIT_ACK",
- If(sink.stb & sink.identify,
- NextState("RECEIVE_DATA")
- )
- )
- self.comb += fifo.sink.data.eq(sink.data)
- fsm.act("RECEIVE_DATA",
- sink.ack.eq(fifo.sink.ack),
- If(sink.stb,
- fifo.sink.stb.eq(1),
- If(sink.eop,
- NextState("IDLE")
- )
- )
- )
+ def __init__(self, user_port):
+ self.start = Signal()
+ self.done = Signal()
+
+ fifo = SyncFIFO([("data", 32)], 512, buffered=True)
+ self.submodules += fifo
+ self.source = fifo.source
+
+ ###
+
+ source, sink = user_port.sink, user_port.source
+
+ self.fsm = fsm = FSM(reset_state="IDLE")
+ self.submodules += fsm
+ fsm.act("IDLE",
+ self.done.eq(1),
+ If(self.start,
+ NextState("SEND_CMD")
+ )
+ )
+ self.comb += [
+ source.sop.eq(1),
+ source.eop.eq(1),
+ source.identify.eq(1),
+ ]
+ fsm.act("SEND_CMD",
+ source.stb.eq(1),
+ If(source.stb & source.ack,
+ NextState("WAIT_ACK")
+ )
+ )
+ fsm.act("WAIT_ACK",
+ If(sink.stb & sink.identify,
+ NextState("RECEIVE_DATA")
+ )
+ )
+ self.comb += fifo.sink.data.eq(sink.data)
+ fsm.act("RECEIVE_DATA",
+ sink.ack.eq(fifo.sink.ack),
+ If(sink.stb,
+ fifo.sink.stb.eq(1),
+ If(sink.eop,
+ NextState("IDLE")
+ )
+ )
+ )
class LiteSATABISTIdentifyCSR(Module, AutoCSR):
- def __init__(self, bist_identify):
- self._start = CSR()
- self._done = CSRStatus()
- self._source_stb = CSRStatus()
- self._source_ack = CSR()
- self._source_data = CSRStatus(32)
+ def __init__(self, bist_identify):
+ self._start = CSR()
+ self._done = CSRStatus()
+ self._source_stb = CSRStatus()
+ self._source_ack = CSR()
+ self._source_data = CSRStatus(32)
- ###
+ ###
- self.submodules += bist_identify
- self.comb += [
- bist_identify.start.eq(self._start.r & self._start.re),
- self._done.status.eq(bist_identify.done),
+ self.submodules += bist_identify
+ self.comb += [
+ bist_identify.start.eq(self._start.r & self._start.re),
+ self._done.status.eq(bist_identify.done),
- self._source_stb.status.eq(bist_identify.source.stb),
- self._source_data.status.eq(bist_identify.source.data),
- bist_identify.source.ack.eq(self._source_ack.r & self._source_ack.re)
- ]
+ self._source_stb.status.eq(bist_identify.source.stb),
+ self._source_data.status.eq(bist_identify.source.data),
+ bist_identify.source.ack.eq(self._source_ack.r & self._source_ack.re)
+ ]
class LiteSATABIST(Module, AutoCSR):
- def __init__(self, crossbar, with_csr=False):
- generator = LiteSATABISTGenerator(crossbar.get_port())
- checker = LiteSATABISTChecker(crossbar.get_port())
- identify = LiteSATABISTIdentify(crossbar.get_port())
- if with_csr:
- generator = LiteSATABISTUnitCSR(generator)
- checker = LiteSATABISTUnitCSR(checker)
- identify = LiteSATABISTIdentifyCSR(identify)
- self.submodules.generator = generator
- self.submodules.checker = checker
- self.submodules.identify = identify
+ def __init__(self, crossbar, with_csr=False):
+ generator = LiteSATABISTGenerator(crossbar.get_port())
+ checker = LiteSATABISTChecker(crossbar.get_port())
+ identify = LiteSATABISTIdentify(crossbar.get_port())
+ if with_csr:
+ generator = LiteSATABISTUnitCSR(generator)
+ checker = LiteSATABISTUnitCSR(checker)
+ identify = LiteSATABISTIdentifyCSR(identify)
+ self.submodules.generator = generator
+ self.submodules.checker = checker
+ self.submodules.identify = identify
from misoclib.mem.litesata.common import *
class LiteSATAMasterPort:
- def __init__(self, dw):
- self.source = Source(command_tx_description(dw))
- self.sink = Sink(command_rx_description(dw))
+ def __init__(self, dw):
+ self.source = Source(command_tx_description(dw))
+ self.sink = Sink(command_rx_description(dw))
- def connect(self, slave):
- return [
- Record.connect(self.source, slave.sink),
- Record.connect(slave.source, self.sink)
- ]
+ def connect(self, slave):
+ return [
+ Record.connect(self.source, slave.sink),
+ Record.connect(slave.source, self.sink)
+ ]
class LiteSATASlavePort:
- def __init__(self, dw):
- self.sink = Sink(command_tx_description(dw))
- self.source = Source(command_rx_description(dw))
+ def __init__(self, dw):
+ self.sink = Sink(command_tx_description(dw))
+ self.source = Source(command_rx_description(dw))
- def connect(self, master):
- return [
- Record.connect(self.sink, master.source),
- Record.connect(master.sink, self.source)
- ]
+ def connect(self, master):
+ return [
+ Record.connect(self.sink, master.source),
+ Record.connect(master.sink, self.source)
+ ]
class LiteSATAUserPort(LiteSATASlavePort):
- def __init__(self, dw):
- LiteSATASlavePort.__init__(self, dw)
+ def __init__(self, dw):
+ LiteSATASlavePort.__init__(self, dw)
from misoclib.mem.litesata.frontend.arbiter import LiteSATAArbiter
class LiteSATACrossbar(Module):
- def __init__(self, core):
- self.users = []
- self.master = LiteSATAMasterPort(32)
- self.comb += [
- self.master.source.connect(core.sink),
- core.source.connect(self.master.sink)
- ]
+ def __init__(self, core):
+ self.users = []
+ self.master = LiteSATAMasterPort(32)
+ self.comb += [
+ self.master.source.connect(core.sink),
+ core.source.connect(self.master.sink)
+ ]
- def get_port(self):
- port = LiteSATAUserPort(32)
- self.users += [port]
- return port
+ def get_port(self):
+ port = LiteSATAUserPort(32)
+ self.users += [port]
+ return port
- def get_ports(self, n):
- ports = []
- for i in range(n):
- ports.append(self.get_port())
- return ports
+ def get_ports(self, n):
+ ports = []
+ for i in range(n):
+ ports.append(self.get_port())
+ return ports
- def do_finalize(self):
- arbiter = LiteSATAArbiter(self.users, self.master)
- self.submodules += arbiter
\ No newline at end of file
+ def do_finalize(self):
+ arbiter = LiteSATAArbiter(self.users, self.master)
+ self.submodules += arbiter
\ No newline at end of file
from misoclib.mem.litesata.phy.datapath import *
class LiteSATAPHY(Module):
- def __init__(self, device, pads, revision, clk_freq):
- self.pads = pads
- self.revision = revision
- # Transceiver / Clocks
- if device[:3] == "xc7": # Kintex 7
- from misoclib.mem.litesata.phy.k7.trx import K7LiteSATAPHYTRX
- from misoclib.mem.litesata.phy.k7.crg import K7LiteSATAPHYCRG
- self.submodules.trx = K7LiteSATAPHYTRX(pads, revision)
- self.submodules.crg = K7LiteSATAPHYCRG(pads, self.trx, revision, clk_freq)
- else:
- msg = "Device" + device + "not (yet) supported."
- raise NotImplementedError(msg)
+ def __init__(self, device, pads, revision, clk_freq):
+ self.pads = pads
+ self.revision = revision
+ # Transceiver / Clocks
+ if device[:3] == "xc7": # Kintex 7
+ from misoclib.mem.litesata.phy.k7.trx import K7LiteSATAPHYTRX
+ from misoclib.mem.litesata.phy.k7.crg import K7LiteSATAPHYCRG
+ self.submodules.trx = K7LiteSATAPHYTRX(pads, revision)
+ self.submodules.crg = K7LiteSATAPHYCRG(pads, self.trx, revision, clk_freq)
+ else:
+ msg = "Device" + device + "not (yet) supported."
+ raise NotImplementedError(msg)
- # Control
- self.submodules.ctrl = LiteSATAPHYCtrl(self.trx, self.crg, clk_freq)
+ # Control
+ self.submodules.ctrl = LiteSATAPHYCtrl(self.trx, self.crg, clk_freq)
- # Datapath
- self.submodules.datapath = LiteSATAPHYDatapath(self.trx, self.ctrl)
- self.sink, self.source = self.datapath.sink, self.datapath.source
+ # Datapath
+ self.submodules.datapath = LiteSATAPHYDatapath(self.trx, self.ctrl)
+ self.sink, self.source = self.datapath.sink, self.datapath.source
from misoclib.mem.litesata.common import *
def us(t, clk_freq):
- clk_period_us = 1000000/clk_freq
- return math.ceil(t/clk_period_us)
+ clk_period_us = 1000000/clk_freq
+ return math.ceil(t/clk_period_us)
class LiteSATAPHYCtrl(Module):
- def __init__(self, trx, crg, clk_freq):
- self.ready = Signal()
- self.need_reset = Signal()
- self.sink = sink = Sink(phy_description(32))
- self.source = source = Source(phy_description(32))
+ def __init__(self, trx, crg, clk_freq):
+ self.ready = Signal()
+ self.need_reset = Signal()
+ self.sink = sink = Sink(phy_description(32))
+ self.source = source = Source(phy_description(32))
- ###
- self.comb += [
- source.stb.eq(1),
- sink.ack.eq(1)
- ]
+ ###
+ self.comb += [
+ source.stb.eq(1),
+ sink.ack.eq(1)
+ ]
- retry_timeout = Timeout(us(10000, clk_freq))
- align_timeout = Timeout(us(873, clk_freq))
- self.submodules += align_timeout, retry_timeout
+ retry_timeout = Timeout(us(10000, clk_freq))
+ align_timeout = Timeout(us(873, clk_freq))
+ self.submodules += align_timeout, retry_timeout
- align_detect = Signal()
- non_align_cnt = Signal(4)
+ align_detect = Signal()
+ non_align_cnt = Signal(4)
- self.fsm = fsm = FSM(reset_state="RESET")
- self.submodules += fsm
- fsm.act("RESET",
- trx.tx_idle.eq(1),
- retry_timeout.reset.eq(1),
- align_timeout.reset.eq(1),
- If(crg.ready,
- NextState("COMINIT")
- ),
- )
- fsm.act("COMINIT",
- trx.tx_idle.eq(1),
- trx.tx_cominit_stb.eq(1),
- If(trx.tx_cominit_ack & ~trx.rx_cominit_stb,
- NextState("AWAIT_COMINIT")
- ),
- )
- fsm.act("AWAIT_COMINIT",
- trx.tx_idle.eq(1),
- retry_timeout.ce.eq(1),
- If(trx.rx_cominit_stb,
- NextState("AWAIT_NO_COMINIT")
- ).Else(
- If(retry_timeout.reached,
- NextState("RESET")
- )
- ),
- )
- fsm.act("AWAIT_NO_COMINIT",
- trx.tx_idle.eq(1),
- retry_timeout.reset.eq(1),
- If(~trx.rx_cominit_stb,
- NextState("CALIBRATE")
- ),
- )
- fsm.act("CALIBRATE",
- trx.tx_idle.eq(1),
- NextState("COMWAKE"),
- )
- fsm.act("COMWAKE",
- trx.tx_idle.eq(1),
- trx.tx_comwake_stb.eq(1),
- If(trx.tx_comwake_ack,
- NextState("AWAIT_COMWAKE")
- ),
- )
- fsm.act("AWAIT_COMWAKE",
- trx.tx_idle.eq(1),
- retry_timeout.ce.eq(1),
- If(trx.rx_comwake_stb,
- NextState("AWAIT_NO_COMWAKE")
- ).Else(
- If(retry_timeout.reached,
- NextState("RESET")
- )
- ),
- )
- fsm.act("AWAIT_NO_COMWAKE",
- trx.tx_idle.eq(1),
- If(~trx.rx_comwake_stb,
- NextState("AWAIT_NO_RX_IDLE")
- ),
- )
- fsm.act("AWAIT_NO_RX_IDLE",
- trx.tx_idle.eq(0),
- source.data.eq(0x4A4A4A4A), #D10.2
- source.charisk.eq(0b0000),
- If(~trx.rx_idle,
- NextState("AWAIT_ALIGN"),
- crg.reset.eq(1),
- trx.pmarxreset.eq(1)
- ),
- )
- fsm.act("AWAIT_ALIGN",
- trx.tx_idle.eq(0),
- source.data.eq(0x4A4A4A4A), #D10.2
- source.charisk.eq(0b0000),
- trx.rx_align.eq(1),
- align_timeout.ce.eq(1),
- If(align_detect & ~trx.rx_idle,
- NextState("SEND_ALIGN")
- ).Elif(align_timeout.reached,
- NextState("RESET")
- ),
- )
- fsm.act("SEND_ALIGN",
- trx.tx_idle.eq(0),
- trx.rx_align.eq(1),
- source.data.eq(primitives["ALIGN"]),
- source.charisk.eq(0b0001),
- If(non_align_cnt == 3,
- NextState("READY")
- ),
- )
- fsm.act("READY",
- trx.tx_idle.eq(0),
- trx.rx_align.eq(1),
- source.data.eq(primitives["SYNC"]),
- source.charisk.eq(0b0001),
- If(trx.rx_idle,
- NextState("RESET")
- ),
- self.ready.eq(1),
- )
+ self.fsm = fsm = FSM(reset_state="RESET")
+ self.submodules += fsm
+ fsm.act("RESET",
+ trx.tx_idle.eq(1),
+ retry_timeout.reset.eq(1),
+ align_timeout.reset.eq(1),
+ If(crg.ready,
+ NextState("COMINIT")
+ ),
+ )
+ fsm.act("COMINIT",
+ trx.tx_idle.eq(1),
+ trx.tx_cominit_stb.eq(1),
+ If(trx.tx_cominit_ack & ~trx.rx_cominit_stb,
+ NextState("AWAIT_COMINIT")
+ ),
+ )
+ fsm.act("AWAIT_COMINIT",
+ trx.tx_idle.eq(1),
+ retry_timeout.ce.eq(1),
+ If(trx.rx_cominit_stb,
+ NextState("AWAIT_NO_COMINIT")
+ ).Else(
+ If(retry_timeout.reached,
+ NextState("RESET")
+ )
+ ),
+ )
+ fsm.act("AWAIT_NO_COMINIT",
+ trx.tx_idle.eq(1),
+ retry_timeout.reset.eq(1),
+ If(~trx.rx_cominit_stb,
+ NextState("CALIBRATE")
+ ),
+ )
+ fsm.act("CALIBRATE",
+ trx.tx_idle.eq(1),
+ NextState("COMWAKE"),
+ )
+ fsm.act("COMWAKE",
+ trx.tx_idle.eq(1),
+ trx.tx_comwake_stb.eq(1),
+ If(trx.tx_comwake_ack,
+ NextState("AWAIT_COMWAKE")
+ ),
+ )
+ fsm.act("AWAIT_COMWAKE",
+ trx.tx_idle.eq(1),
+ retry_timeout.ce.eq(1),
+ If(trx.rx_comwake_stb,
+ NextState("AWAIT_NO_COMWAKE")
+ ).Else(
+ If(retry_timeout.reached,
+ NextState("RESET")
+ )
+ ),
+ )
+ fsm.act("AWAIT_NO_COMWAKE",
+ trx.tx_idle.eq(1),
+ If(~trx.rx_comwake_stb,
+ NextState("AWAIT_NO_RX_IDLE")
+ ),
+ )
+ fsm.act("AWAIT_NO_RX_IDLE",
+ trx.tx_idle.eq(0),
+ source.data.eq(0x4A4A4A4A), #D10.2
+ source.charisk.eq(0b0000),
+ If(~trx.rx_idle,
+ NextState("AWAIT_ALIGN"),
+ crg.reset.eq(1),
+ trx.pmarxreset.eq(1)
+ ),
+ )
+ fsm.act("AWAIT_ALIGN",
+ trx.tx_idle.eq(0),
+ source.data.eq(0x4A4A4A4A), #D10.2
+ source.charisk.eq(0b0000),
+ trx.rx_align.eq(1),
+ align_timeout.ce.eq(1),
+ If(align_detect & ~trx.rx_idle,
+ NextState("SEND_ALIGN")
+ ).Elif(align_timeout.reached,
+ NextState("RESET")
+ ),
+ )
+ fsm.act("SEND_ALIGN",
+ trx.tx_idle.eq(0),
+ trx.rx_align.eq(1),
+ source.data.eq(primitives["ALIGN"]),
+ source.charisk.eq(0b0001),
+ If(non_align_cnt == 3,
+ NextState("READY")
+ ),
+ )
+ fsm.act("READY",
+ trx.tx_idle.eq(0),
+ trx.rx_align.eq(1),
+ source.data.eq(primitives["SYNC"]),
+ source.charisk.eq(0b0001),
+ If(trx.rx_idle,
+ NextState("RESET")
+ ),
+ self.ready.eq(1),
+ )
- reset_timeout = Timeout(clk_freq//16)
- self.submodules += reset_timeout
- self.comb += [
- reset_timeout.ce.eq(~self.ready),
- self.need_reset.eq(reset_timeout.reached)
- ]
+ reset_timeout = Timeout(clk_freq//16)
+ self.submodules += reset_timeout
+ self.comb += [
+ reset_timeout.ce.eq(~self.ready),
+ self.need_reset.eq(reset_timeout.reached)
+ ]
- self.comb += \
- align_detect.eq(self.sink.stb & (self.sink.data == primitives["ALIGN"]))
- self.sync += \
- If(fsm.ongoing("SEND_ALIGN"),
- If(sink.stb,
- If(sink.data[0:8] == 0x7C,
- non_align_cnt.eq(non_align_cnt + 1)
- ).Else(
- non_align_cnt.eq(0)
- )
- )
- )
+ self.comb += \
+ align_detect.eq(self.sink.stb & (self.sink.data == primitives["ALIGN"]))
+ self.sync += \
+ If(fsm.ongoing("SEND_ALIGN"),
+ If(sink.stb,
+ If(sink.data[0:8] == 0x7C,
+ non_align_cnt.eq(non_align_cnt + 1)
+ ).Else(
+ non_align_cnt.eq(0)
+ )
+ )
+ )
from misoclib.mem.litesata.common import *
class LiteSATAPHYDatapathRX(Module):
- def __init__(self):
- self.sink = sink = Sink(phy_description(16))
- self.source = source = Source(phy_description(32))
-
- ###
-
- # width convertion (16 to 32) and byte alignment
- byte_alignment = Signal()
- last_charisk = Signal(2)
- last_data = Signal(16)
- self.sync.sata_rx += \
- If(sink.stb & sink.ack,
- If(sink.charisk != 0,
- byte_alignment.eq(sink.charisk[1])
- ),
- last_charisk.eq(sink.charisk),
- last_data.eq(sink.data)
- )
- converter = Converter(phy_description(16), phy_description(32), reverse=False)
- converter = InsertReset(RenameClockDomains(converter, "sata_rx"))
- self.submodules += converter
- self.comb += [
- converter.sink.stb.eq(sink.stb),
- If(byte_alignment,
- converter.sink.charisk.eq(Cat(last_charisk[1], sink.charisk[0])),
- converter.sink.data.eq(Cat(last_data[8:], sink.data[:8]))
- ).Else(
- converter.sink.charisk.eq(sink.charisk),
- converter.sink.data.eq(sink.data)
- ),
- sink.ack.eq(converter.sink.ack),
- converter.reset.eq(converter.source.charisk[2:] != 0)
- ]
-
- # clock domain crossing
- # (sata_gen3) 300MHz sata_rx clk to sys_clk
- # (sata_gen2) 150MHz sata_rx clk to sys_clk
- # (sata_gen1) 75MHz sata_rx clk to sys_clk
- # requirements:
- # due to the convertion ratio of 2, sys_clk need to be > sata_rx/2
- # source destination is always able to accept data (ack always 1)
- fifo = AsyncFIFO(phy_description(32), 4)
- fifo = RenameClockDomains(fifo, {"write": "sata_rx", "read": "sys"})
- self.submodules += fifo
- self.comb += [
- Record.connect(converter.source, fifo.sink),
- Record.connect(fifo.source, source)
- ]
+ def __init__(self):
+ self.sink = sink = Sink(phy_description(16))
+ self.source = source = Source(phy_description(32))
+
+ ###
+
+ # width convertion (16 to 32) and byte alignment
+ byte_alignment = Signal()
+ last_charisk = Signal(2)
+ last_data = Signal(16)
+ self.sync.sata_rx += \
+ If(sink.stb & sink.ack,
+ If(sink.charisk != 0,
+ byte_alignment.eq(sink.charisk[1])
+ ),
+ last_charisk.eq(sink.charisk),
+ last_data.eq(sink.data)
+ )
+ converter = Converter(phy_description(16), phy_description(32), reverse=False)
+ converter = InsertReset(RenameClockDomains(converter, "sata_rx"))
+ self.submodules += converter
+ self.comb += [
+ converter.sink.stb.eq(sink.stb),
+ If(byte_alignment,
+ converter.sink.charisk.eq(Cat(last_charisk[1], sink.charisk[0])),
+ converter.sink.data.eq(Cat(last_data[8:], sink.data[:8]))
+ ).Else(
+ converter.sink.charisk.eq(sink.charisk),
+ converter.sink.data.eq(sink.data)
+ ),
+ sink.ack.eq(converter.sink.ack),
+ converter.reset.eq(converter.source.charisk[2:] != 0)
+ ]
+
+ # clock domain crossing
+ # (sata_gen3) 300MHz sata_rx clk to sys_clk
+ # (sata_gen2) 150MHz sata_rx clk to sys_clk
+ # (sata_gen1) 75MHz sata_rx clk to sys_clk
+ # requirements:
+ # due to the convertion ratio of 2, sys_clk need to be > sata_rx/2
+ # source destination is always able to accept data (ack always 1)
+ fifo = AsyncFIFO(phy_description(32), 4)
+ fifo = RenameClockDomains(fifo, {"write": "sata_rx", "read": "sys"})
+ self.submodules += fifo
+ self.comb += [
+ Record.connect(converter.source, fifo.sink),
+ Record.connect(fifo.source, source)
+ ]
class LiteSATAPHYDatapathTX(Module):
- def __init__(self):
- self.sink = sink = Sink(phy_description(32))
- self.source = source = Source(phy_description(16))
-
- ###
-
- # clock domain crossing
- # (sata_gen3) sys_clk to 300MHz sata_tx clk
- # (sata_gen2) sys_clk to 150MHz sata_tx clk
- # (sata_gen1) sys_clk to 75MHz sata_tx clk
- # requirements:
- # source destination is always able to accept data (ack always 1)
- fifo = AsyncFIFO(phy_description(32), 4)
- fifo = RenameClockDomains(fifo, {"write": "sys", "read": "sata_tx"})
- self.submodules += fifo
- self.comb += Record.connect(sink, fifo.sink)
-
- # width convertion (32 to 16)
- converter = Converter(phy_description(32), phy_description(16), reverse=False)
- converter = RenameClockDomains(converter, "sata_tx")
- self.submodules += converter
- self.comb += [
- Record.connect(fifo.source, converter.sink),
- Record.connect(converter.source, source)
- ]
+ def __init__(self):
+ self.sink = sink = Sink(phy_description(32))
+ self.source = source = Source(phy_description(16))
+
+ ###
+
+ # clock domain crossing
+ # (sata_gen3) sys_clk to 300MHz sata_tx clk
+ # (sata_gen2) sys_clk to 150MHz sata_tx clk
+ # (sata_gen1) sys_clk to 75MHz sata_tx clk
+ # requirements:
+ # source destination is always able to accept data (ack always 1)
+ fifo = AsyncFIFO(phy_description(32), 4)
+ fifo = RenameClockDomains(fifo, {"write": "sys", "read": "sata_tx"})
+ self.submodules += fifo
+ self.comb += Record.connect(sink, fifo.sink)
+
+ # width convertion (32 to 16)
+ converter = Converter(phy_description(32), phy_description(16), reverse=False)
+ converter = RenameClockDomains(converter, "sata_tx")
+ self.submodules += converter
+ self.comb += [
+ Record.connect(fifo.source, converter.sink),
+ Record.connect(converter.source, source)
+ ]
class LiteSATAPHYAlignInserter(Module):
- def __init__(self, ctrl):
- self.sink = sink = Sink(phy_description(32))
- self.source = source = Source(phy_description(32))
-
- ###
-
- # send 2 ALIGN every 256 DWORDs
- # used for clock compensation between
- # HOST and device
- cnt = Signal(8)
- send = Signal()
- self.sync += \
- If(~ctrl.ready,
- cnt.eq(0)
- ).Elif(source.stb & source.ack,
- cnt.eq(cnt+1)
- )
- self.comb += [
- send.eq(cnt < 2),
- If(send,
- source.stb.eq(1),
- source.charisk.eq(0b0001),
- source.data.eq(primitives["ALIGN"]),
- sink.ack.eq(0)
- ).Else(
- source.stb.eq(sink.stb),
- source.data.eq(sink.data),
- source.charisk.eq(sink.charisk),
- sink.ack.eq(source.ack)
- )
- ]
+ def __init__(self, ctrl):
+ self.sink = sink = Sink(phy_description(32))
+ self.source = source = Source(phy_description(32))
+
+ ###
+
+ # send 2 ALIGN every 256 DWORDs
+ # used for clock compensation between
+ # HOST and device
+ cnt = Signal(8)
+ send = Signal()
+ self.sync += \
+ If(~ctrl.ready,
+ cnt.eq(0)
+ ).Elif(source.stb & source.ack,
+ cnt.eq(cnt+1)
+ )
+ self.comb += [
+ send.eq(cnt < 2),
+ If(send,
+ source.stb.eq(1),
+ source.charisk.eq(0b0001),
+ source.data.eq(primitives["ALIGN"]),
+ sink.ack.eq(0)
+ ).Else(
+ source.stb.eq(sink.stb),
+ source.data.eq(sink.data),
+ source.charisk.eq(sink.charisk),
+ sink.ack.eq(source.ack)
+ )
+ ]
class LiteSATAPHYAlignRemover(Module):
- def __init__(self):
- self.sink = sink = Sink(phy_description(32))
- self.source = source = Source(phy_description(32))
+ def __init__(self):
+ self.sink = sink = Sink(phy_description(32))
+ self.source = source = Source(phy_description(32))
- ###
+ ###
- charisk_match = sink.charisk == 0b0001
- data_match = sink.data == primitives["ALIGN"]
+ charisk_match = sink.charisk == 0b0001
+ data_match = sink.data == primitives["ALIGN"]
- self.comb += \
- If(sink.stb & charisk_match & data_match,
- sink.ack.eq(1),
- ).Else(
- Record.connect(sink, source)
- )
+ self.comb += \
+ If(sink.stb & charisk_match & data_match,
+ sink.ack.eq(1),
+ ).Else(
+ Record.connect(sink, source)
+ )
class LiteSATAPHYDatapath(Module):
- def __init__(self, trx, ctrl):
- self.sink = sink = Sink(phy_description(32))
- self.source = source = Source(phy_description(32))
-
- ###
-
- # TX path
- align_inserter = LiteSATAPHYAlignInserter(ctrl)
- mux = Multiplexer(phy_description(32), 2)
- tx = LiteSATAPHYDatapathTX()
- self.submodules += align_inserter, mux, tx
- self.comb += [
- mux.sel.eq(ctrl.ready),
- Record.connect(sink, align_inserter.sink),
- Record.connect(ctrl.source, mux.sink0),
- Record.connect(align_inserter.source, mux.sink1),
- Record.connect(mux.source, tx.sink),
- Record.connect(tx.source, trx.sink)
- ]
-
- # RX path
- rx = LiteSATAPHYDatapathRX()
- demux = Demultiplexer(phy_description(32), 2)
- align_remover = LiteSATAPHYAlignRemover()
- self.submodules += rx, demux, align_remover
- self.comb += [
- demux.sel.eq(ctrl.ready),
- Record.connect(trx.source, rx.sink),
- Record.connect(rx.source, demux.sink),
- Record.connect(demux.source0, ctrl.sink),
- Record.connect(demux.source1, align_remover.sink),
- Record.connect(align_remover.source, source)
- ]
+ def __init__(self, trx, ctrl):
+ self.sink = sink = Sink(phy_description(32))
+ self.source = source = Source(phy_description(32))
+
+ ###
+
+ # TX path
+ align_inserter = LiteSATAPHYAlignInserter(ctrl)
+ mux = Multiplexer(phy_description(32), 2)
+ tx = LiteSATAPHYDatapathTX()
+ self.submodules += align_inserter, mux, tx
+ self.comb += [
+ mux.sel.eq(ctrl.ready),
+ Record.connect(sink, align_inserter.sink),
+ Record.connect(ctrl.source, mux.sink0),
+ Record.connect(align_inserter.source, mux.sink1),
+ Record.connect(mux.source, tx.sink),
+ Record.connect(tx.source, trx.sink)
+ ]
+
+ # RX path
+ rx = LiteSATAPHYDatapathRX()
+ demux = Demultiplexer(phy_description(32), 2)
+ align_remover = LiteSATAPHYAlignRemover()
+ self.submodules += rx, demux, align_remover
+ self.comb += [
+ demux.sel.eq(ctrl.ready),
+ Record.connect(trx.source, rx.sink),
+ Record.connect(rx.source, demux.sink),
+ Record.connect(demux.source0, ctrl.sink),
+ Record.connect(demux.source1, align_remover.sink),
+ Record.connect(align_remover.source, source)
+ ]
from misoclib.mem.litesata.common import *
class K7LiteSATAPHYCRG(Module):
- def __init__(self, pads, gtx, revision, clk_freq):
- self.reset = Signal()
- self.ready = Signal()
-
- self.clock_domains.cd_sata_tx = ClockDomain()
- self.clock_domains.cd_sata_rx = ClockDomain()
-
- # CPLL
- # (sata_gen3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps
- # (sata_gen2 & sata_gen1) VCO still @ 3 GHz, Line rate is decreased with output dividers.
- refclk = Signal()
- self.specials += Instance("IBUFDS_GTE2",
- i_CEB=0,
- i_I=pads.refclk_p,
- i_IB=pads.refclk_n,
- o_O=refclk
- )
- self.comb += gtx.gtrefclk0.eq(refclk)
-
- # TX clocking
- # (sata_gen3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits)
- # (sata_gen2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits)
- # (sata_gen1) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 75MHz (16-bits)
- mmcm_reset = Signal()
- mmcm_locked = Signal()
- mmcm_fb = Signal()
- mmcm_clk_i = Signal()
- mmcm_clk0_o = Signal()
- mmcm_div_config = {
- "sata_gen1" : 16.0,
- "sata_gen2" : 8.0,
- "sata_gen3" : 4.0
- }
- mmcm_div = mmcm_div_config[revision]
- self.specials += [
- Instance("BUFG", i_I=gtx.txoutclk, 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=0, i_DEN=0, i_DWE=0, #o_DRDY=,
- i_DADDR=0, i_DI=0, #o_DO=,
-
- # VCO
- p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=6.666,
- p_CLKFBOUT_MULT_F=8.000, p_CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=1,
- i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb,
-
- # CLK0
- p_CLKOUT0_DIVIDE_F=mmcm_div, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0_o,
- ),
- Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_tx.clk),
- ]
- self.comb += [
- gtx.txusrclk.eq(self.cd_sata_tx.clk),
- gtx.txusrclk2.eq(self.cd_sata_tx.clk)
- ]
-
- # RX clocking
- # (sata_gen3) sata_rx recovered clk @ 300MHz from GTX RXOUTCLK
- # (sata_gen2) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
- # (sata_gen1) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
- 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)
- ]
-
- # Configuration Reset
- # After configuration, GTX's resets have to stay low for at least 500ns
- # See AR43482
- reset_en = Signal()
- clk_period_ns = 1000000000/clk_freq
- reset_en_cnt_max = math.ceil(500/clk_period_ns)
- reset_en_cnt = Signal(max=reset_en_cnt_max, reset=reset_en_cnt_max-1)
- self.sync += \
- If(self.reset,
- reset_en_cnt.eq(reset_en_cnt.reset)
- ).Elif(~reset_en,
- reset_en_cnt.eq(reset_en_cnt-1)
- )
- self.comb += reset_en.eq(reset_en_cnt == 0)
-
- # TX Reset FSM
- tx_reset_fsm = InsertReset(FSM(reset_state="IDLE"))
- self.submodules += tx_reset_fsm
- self.comb += tx_reset_fsm.reset.eq(self.reset)
- tx_reset_fsm.act("IDLE",
- If(reset_en,
- NextState("RESET_GTX"),
- )
- )
- tx_reset_fsm.act("RESET_GTX",
- gtx.gttxreset.eq(1),
- If(gtx.cplllock & mmcm_locked,
- NextState("RELEASE_GTX")
- )
- )
- tx_reset_fsm.act("RELEASE_GTX",
- gtx.txuserrdy.eq(1),
- If(gtx.txresetdone,
- NextState("READY")
- )
- )
- tx_reset_fsm.act("READY",
- gtx.txuserrdy.eq(1)
- )
-
- # RX Reset FSM
- rx_reset_fsm = InsertReset(FSM(reset_state="IDLE"))
- self.submodules += rx_reset_fsm
- self.comb += rx_reset_fsm.reset.eq(self.reset)
-
- rx_reset_fsm.act("IDLE",
- If(reset_en,
- NextState("RESET_GTX"),
- )
- )
- rx_reset_fsm.act("RESET_GTX",
- gtx.gtrxreset.eq(1),
- If(gtx.cplllock & mmcm_locked,
- NextState("RELEASE_GTX")
- )
- )
- rx_reset_fsm.act("RELEASE_GTX",
- gtx.rxuserrdy.eq(1),
- If(gtx.rxresetdone,
- NextState("READY")
- )
- )
- rx_reset_fsm.act("READY",
- gtx.rxuserrdy.eq(1)
- )
-
- # Ready
- self.tx_ready = tx_reset_fsm.ongoing("READY")
- self.rx_ready = rx_reset_fsm.ongoing("READY")
- self.comb += self.ready.eq(self.tx_ready & self.rx_ready)
-
- # Reset PLL
- self.comb += gtx.cpllreset.eq(ResetSignal() | self.reset | ~reset_en)
-
- # Reset MMCM
- self.comb += mmcm_reset.eq(ResetSignal() | self.reset | ~gtx.cplllock)
-
- # Reset for SATA TX/RX clock domains
- self.specials += [
- AsyncResetSynchronizer(self.cd_sata_tx, ~self.tx_ready),
- AsyncResetSynchronizer(self.cd_sata_rx, ~self.rx_ready),
- ]
+ def __init__(self, pads, gtx, revision, clk_freq):
+ self.reset = Signal()
+ self.ready = Signal()
+
+ self.clock_domains.cd_sata_tx = ClockDomain()
+ self.clock_domains.cd_sata_rx = ClockDomain()
+
+ # CPLL
+ # (sata_gen3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps
+ # (sata_gen2 & sata_gen1) VCO still @ 3 GHz, Line rate is decreased with output dividers.
+ refclk = Signal()
+ self.specials += Instance("IBUFDS_GTE2",
+ i_CEB=0,
+ i_I=pads.refclk_p,
+ i_IB=pads.refclk_n,
+ o_O=refclk
+ )
+ self.comb += gtx.gtrefclk0.eq(refclk)
+
+ # TX clocking
+ # (sata_gen3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits)
+ # (sata_gen2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits)
+ # (sata_gen1) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 75MHz (16-bits)
+ mmcm_reset = Signal()
+ mmcm_locked = Signal()
+ mmcm_fb = Signal()
+ mmcm_clk_i = Signal()
+ mmcm_clk0_o = Signal()
+ mmcm_div_config = {
+ "sata_gen1" : 16.0,
+ "sata_gen2" : 8.0,
+ "sata_gen3" : 4.0
+ }
+ mmcm_div = mmcm_div_config[revision]
+ self.specials += [
+ Instance("BUFG", i_I=gtx.txoutclk, 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=0, i_DEN=0, i_DWE=0, #o_DRDY=,
+ i_DADDR=0, i_DI=0, #o_DO=,
+
+ # VCO
+ p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=6.666,
+ p_CLKFBOUT_MULT_F=8.000, p_CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=1,
+ i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb,
+
+ # CLK0
+ p_CLKOUT0_DIVIDE_F=mmcm_div, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0_o,
+ ),
+ Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_tx.clk),
+ ]
+ self.comb += [
+ gtx.txusrclk.eq(self.cd_sata_tx.clk),
+ gtx.txusrclk2.eq(self.cd_sata_tx.clk)
+ ]
+
+ # RX clocking
+ # (sata_gen3) sata_rx recovered clk @ 300MHz from GTX RXOUTCLK
+ # (sata_gen2) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
+ # (sata_gen1) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
+ 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)
+ ]
+
+ # Configuration Reset
+ # After configuration, GTX's resets have to stay low for at least 500ns
+ # See AR43482
+ reset_en = Signal()
+ clk_period_ns = 1000000000/clk_freq
+ reset_en_cnt_max = math.ceil(500/clk_period_ns)
+ reset_en_cnt = Signal(max=reset_en_cnt_max, reset=reset_en_cnt_max-1)
+ self.sync += \
+ If(self.reset,
+ reset_en_cnt.eq(reset_en_cnt.reset)
+ ).Elif(~reset_en,
+ reset_en_cnt.eq(reset_en_cnt-1)
+ )
+ self.comb += reset_en.eq(reset_en_cnt == 0)
+
+ # TX Reset FSM
+ tx_reset_fsm = InsertReset(FSM(reset_state="IDLE"))
+ self.submodules += tx_reset_fsm
+ self.comb += tx_reset_fsm.reset.eq(self.reset)
+ tx_reset_fsm.act("IDLE",
+ If(reset_en,
+ NextState("RESET_GTX"),
+ )
+ )
+ tx_reset_fsm.act("RESET_GTX",
+ gtx.gttxreset.eq(1),
+ If(gtx.cplllock & mmcm_locked,
+ NextState("RELEASE_GTX")
+ )
+ )
+ tx_reset_fsm.act("RELEASE_GTX",
+ gtx.txuserrdy.eq(1),
+ If(gtx.txresetdone,
+ NextState("READY")
+ )
+ )
+ tx_reset_fsm.act("READY",
+ gtx.txuserrdy.eq(1)
+ )
+
+ # RX Reset FSM
+ rx_reset_fsm = InsertReset(FSM(reset_state="IDLE"))
+ self.submodules += rx_reset_fsm
+ self.comb += rx_reset_fsm.reset.eq(self.reset)
+
+ rx_reset_fsm.act("IDLE",
+ If(reset_en,
+ NextState("RESET_GTX"),
+ )
+ )
+ rx_reset_fsm.act("RESET_GTX",
+ gtx.gtrxreset.eq(1),
+ If(gtx.cplllock & mmcm_locked,
+ NextState("RELEASE_GTX")
+ )
+ )
+ rx_reset_fsm.act("RELEASE_GTX",
+ gtx.rxuserrdy.eq(1),
+ If(gtx.rxresetdone,
+ NextState("READY")
+ )
+ )
+ rx_reset_fsm.act("READY",
+ gtx.rxuserrdy.eq(1)
+ )
+
+ # Ready
+ self.tx_ready = tx_reset_fsm.ongoing("READY")
+ self.rx_ready = rx_reset_fsm.ongoing("READY")
+ self.comb += self.ready.eq(self.tx_ready & self.rx_ready)
+
+ # Reset PLL
+ self.comb += gtx.cpllreset.eq(ResetSignal() | self.reset | ~reset_en)
+
+ # Reset MMCM
+ self.comb += mmcm_reset.eq(ResetSignal() | self.reset | ~gtx.cplllock)
+
+ # Reset for SATA TX/RX clock domains
+ self.specials += [
+ AsyncResetSynchronizer(self.cd_sata_tx, ~self.tx_ready),
+ AsyncResetSynchronizer(self.cd_sata_rx, ~self.rx_ready),
+ ]
from misoclib.mem.litesata.common import *
def ones(width):
- return 2**width-1
+ return 2**width-1
class _PulseSynchronizer(PulseSynchronizer):
- def __init__(self, i, idomain, o, odomain):
- PulseSynchronizer.__init__(self, idomain, odomain)
- self.comb += [
- self.i.eq(i),
- o.eq(self.o)
- ]
+ def __init__(self, i, idomain, o, odomain):
+ PulseSynchronizer.__init__(self, idomain, odomain)
+ self.comb += [
+ self.i.eq(i),
+ o.eq(self.o)
+ ]
class _RisingEdge(Module):
- def __init__(self, i, o):
- i_d = Signal()
- self.sync += i_d.eq(i)
- self.comb += o.eq(i & ~i_d)
+ def __init__(self, i, o):
+ i_d = Signal()
+ self.sync += i_d.eq(i)
+ self.comb += o.eq(i & ~i_d)
class K7LiteSATAPHYTRX(Module):
- def __init__(self, pads, revision):
- # Common signals
-
- # control
- self.tx_idle = Signal() #i
-
- self.tx_cominit_stb = Signal() #i
- self.tx_cominit_ack = Signal() #o
- self.tx_comwake_stb = Signal() #i
- self.tx_comwake_ack = Signal() #o
-
- self.rx_idle = Signal() #o
- self.rx_align = Signal() #i
-
- self.rx_cominit_stb = Signal() #o
- self.rx_comwake_stb = Signal() #o
-
- # datapath
- self.sink = Sink(phy_description(16))
- self.source = Source(phy_description(16))
-
- # K7 specific signals
- # Channel - Ref Clock Ports
- self.gtrefclk0 = Signal()
-
- # Channel PLL
- self.cplllock = Signal()
- self.cpllreset = Signal()
-
- # Receive Ports
- self.rxuserrdy = Signal()
- self.rxalign = Signal()
-
- # Receive Ports - 8b10b Decoder
- self.rxcharisk = Signal(2)
- self.rxdisperr = Signal(2)
-
- # Receive Ports - RX Data Path interface
- self.gtrxreset = Signal()
- self.pmarxreset = Signal()
- self.rxdata = Signal(16)
- self.rxoutclk = Signal()
- self.rxusrclk = Signal()
- self.rxusrclk2 = Signal()
-
- # Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR
- self.rxelecidle = Signal()
-
- # Receive Ports - RX PLL Ports
- self.rxresetdone = Signal()
-
- # Receive Ports - RX Ports for SATA
- self.rxcominitdet = Signal()
- self.rxcomwakedet = Signal()
-
- # Transmit Ports
- self.txuserrdy = Signal()
-
- # Transmit Ports - 8b10b Encoder Control Ports
- self.txcharisk = Signal(2)
-
- # Transmit Ports - TX Data Path interface
- self.gttxreset = Signal()
- self.txdata = Signal(16)
- self.txoutclk = Signal()
- self.txusrclk = Signal()
- self.txusrclk2 = Signal()
-
- # Transmit Ports - TX PLL Ports
- self.txresetdone = Signal()
-
- # Transmit Ports - TX Ports for PCI Express
- self.txelecidle = Signal(reset=1)
-
- # Transmit Ports - TX Ports for SATA
- self.txcomfinish = Signal()
- self.txcominit = Signal()
- self.txcomwake = Signal()
- self.txrate = Signal(3)
- self.rxcdrlock = Signal()
-
- # Config at startup
- div_config = {
- "sata_gen1" : 4,
- "sata_gen2" : 2,
- "sata_gen3" : 1
- }
- rxout_div = div_config[revision]
- txout_div = div_config[revision]
-
- cdr_config = {
- "sata_gen1" : 0x0380008BFF40100008,
- "sata_gen2" : 0x0388008BFF40200008,
- "sata_gen3" : 0X0380008BFF10200010
- }
- rxcdr_cfg = cdr_config[revision]
-
- # Specific / Generic signals encoding/decoding
- self.comb += [
- self.txelecidle.eq(self.tx_idle),
- self.tx_cominit_ack.eq(self.tx_cominit_stb & self.txcomfinish),
- self.tx_comwake_ack.eq(self.tx_comwake_stb & self.txcomfinish),
- self.rx_idle.eq(self.rxelecidle),
- self.rxalign.eq(self.rx_align),
- self.rx_cominit_stb.eq(self.rxcominitdet),
- self.rx_comwake_stb.eq(self.rxcomwakedet),
- ]
- self.submodules += [
- _RisingEdge(self.tx_cominit_stb, self.txcominit),
- _RisingEdge(self.tx_comwake_stb, self.txcomwake),
- ]
-
- self.comb += [
- self.txcharisk.eq(self.sink.charisk),
- self.txdata.eq(self.sink.data),
- self.sink.ack.eq(1),
-
- self.source.stb.eq(1),
- self.source.charisk.eq(self.rxcharisk),
- self.source.data.eq(self.rxdata)
- ]
-
- # Internals and clock domain crossing
- # sys_clk --> sata_tx clk
- txuserrdy = Signal()
- txelecidle = Signal(reset=1)
- txcominit = Signal()
- txcomwake = Signal()
- txrate = Signal(3)
-
- self.specials += [
- MultiReg(self.txuserrdy, txuserrdy, "sata_tx"),
- MultiReg(self.txelecidle, txelecidle, "sata_tx"),
- MultiReg(self.txrate, txrate, "sata_tx")
- ]
- self.submodules += [
- _PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"),
- _PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"),
- ]
-
- # sata_tx clk --> sys clk
- txresetdone = Signal()
- txcomfinish = Signal()
-
- self.specials += [
- MultiReg(txresetdone, self.txresetdone, "sys"),
- ]
-
- self.submodules += [
- _PulseSynchronizer(txcomfinish, "sata_tx", self.txcomfinish, "sys"),
- ]
-
- # sys clk --> sata_rx clk
- rxuserrdy = Signal()
-
- self.specials += [
- MultiReg(self.rxuserrdy, rxuserrdy, "sata_rx"),
- ]
-
- # sata_rx clk --> sys clk
- rxelecidle = Signal()
- rxelecidle_i = Signal()
- rxelecidle_cnt_i = Signal(9)
- rxresetdone = Signal()
- rxcominitdet = Signal()
- rxcomwakedet = Signal()
- rxratedone = Signal()
- rxcdrlock = Signal()
-
- self.specials += [
- MultiReg(rxelecidle, rxelecidle_i, "sys"),
- MultiReg(rxresetdone, self.rxresetdone, "sys"),
- MultiReg(rxcominitdet, self.rxcominitdet, "sys"),
- MultiReg(rxcomwakedet, self.rxcomwakedet, "sys"),
- MultiReg(rxcdrlock, self.rxcdrlock, "sys"),
- ]
-
- self.sync += [
- If(rxelecidle_i != self.rxelecidle,
- If(rxelecidle_cnt_i == 0,
- self.rxelecidle.eq(rxelecidle_i),
- rxelecidle_cnt_i.eq(255)
- ).Else(
- rxelecidle_cnt_i.eq(rxelecidle_cnt_i-1)
- )
- ).Else(
- rxelecidle_cnt_i.eq(255)
- )
- ]
-
- self.rxbyteisaligned = Signal()
-
- # QPLL input clock
- self.qpllclk = Signal()
- self.qpllrefclk = Signal()
-
- # Instance
- gtxe2_channel_parameters = {
- # Simulation-Only Attributes
- "p_SIM_RECEIVER_DETECT_PASS":"TRUE",
- "p_SIM_TX_EIDLE_DRIVE_LEVEL":"X",
- "p_SIM_RESET_SPEEDUP":"TRUE",
- "p_SIM_CPLLREFCLK_SEL":0b001,
- "p_SIM_VERSION":"4.0",
-
- # RX Byte and Word Alignment Attributes
- "p_ALIGN_COMMA_DOUBLE":"FALSE",
- "p_ALIGN_COMMA_ENABLE":ones(10),
- "p_ALIGN_COMMA_WORD":2,
- "p_ALIGN_MCOMMA_DET":"TRUE",
- "p_ALIGN_MCOMMA_VALUE":0b1010000011,
- "p_ALIGN_PCOMMA_DET":"TRUE",
- "p_ALIGN_PCOMMA_VALUE":0b0101111100,
- "p_SHOW_REALIGN_COMMA":"FALSE",
- "p_RXSLIDE_AUTO_WAIT":7,
- "p_RXSLIDE_MODE":"PCS",
- "p_RX_SIG_VALID_DLY":10,
-
- # RX 8B/10B Decoder Attributes
- "p_RX_DISPERR_SEQ_MATCH":"TRUE",
- "p_DEC_MCOMMA_DETECT":"TRUE",
- "p_DEC_PCOMMA_DETECT":"TRUE",
- "p_DEC_VALID_COMMA_ONLY":"FALSE",
-
- # RX Clock Correction Attributes
- "p_CBCC_DATA_SOURCE_SEL":"DECODED",
- "p_CLK_COR_SEQ_2_USE":"FALSE",
- "p_CLK_COR_KEEP_IDLE":"FALSE",
- "p_CLK_COR_MAX_LAT":9,
- "p_CLK_COR_MIN_LAT":7,
- "p_CLK_COR_PRECEDENCE":"TRUE",
- "p_CLK_COR_REPEAT_WAIT":0,
- "p_CLK_COR_SEQ_LEN":1,
- "p_CLK_COR_SEQ_1_ENABLE":ones(4),
- "p_CLK_COR_SEQ_1_1":0b0100000000,
- "p_CLK_COR_SEQ_1_2":0b0000000000,
- "p_CLK_COR_SEQ_1_3":0b0000000000,
- "p_CLK_COR_SEQ_1_4":0b0000000000,
- "p_CLK_CORRECT_USE":"FALSE",
- "p_CLK_COR_SEQ_2_ENABLE":ones(4),
- "p_CLK_COR_SEQ_2_1":0b0100000000,
- "p_CLK_COR_SEQ_2_2":0,
- "p_CLK_COR_SEQ_2_3":0,
- "p_CLK_COR_SEQ_2_4":0,
-
- # RX Channel Bonding Attributes
- "p_CHAN_BOND_KEEP_ALIGN":"FALSE",
- "p_CHAN_BOND_MAX_SKEW":1,
- "p_CHAN_BOND_SEQ_LEN":1,
- "p_CHAN_BOND_SEQ_1_1":0,
- "p_CHAN_BOND_SEQ_1_1":0,
- "p_CHAN_BOND_SEQ_1_2":0,
- "p_CHAN_BOND_SEQ_1_3":0,
- "p_CHAN_BOND_SEQ_1_4":0,
- "p_CHAN_BOND_SEQ_1_ENABLE":ones(4),
- "p_CHAN_BOND_SEQ_2_1":0,
- "p_CHAN_BOND_SEQ_2_2":0,
- "p_CHAN_BOND_SEQ_2_3":0,
- "p_CHAN_BOND_SEQ_2_4":0,
- "p_CHAN_BOND_SEQ_2_ENABLE":ones(4),
- "p_CHAN_BOND_SEQ_2_USE":"FALSE",
- "p_FTS_DESKEW_SEQ_ENABLE":ones(4),
- "p_FTS_LANE_DESKEW_CFG":ones(4),
- "p_FTS_LANE_DESKEW_EN":"FALSE",
-
- # RX Margin Analysis Attributes
- "p_ES_CONTROL":0,
- "p_ES_ERRDET_EN":"FALSE",
- "p_ES_EYE_SCAN_EN":"TRUE",
- "p_ES_HORZ_OFFSET":0,
- "p_ES_PMA_CFG":0,
- "p_ES_PRESCALE":0,
- "p_ES_QUALIFIER":0,
- "p_ES_QUAL_MASK":0,
- "p_ES_SDATA_MASK":0,
- "p_ES_VERT_OFFSET":0,
-
- # FPGA RX Interface Attributes
- "p_RX_DATA_WIDTH":20,
-
- # PMA Attributes
- "p_OUTREFCLK_SEL_INV":0b11,
- "p_PMA_RSV":0x00018480,
- "p_PMA_RSV2":0x2050,
- "p_PMA_RSV3":0,
- "p_PMA_RSV4":0,
- "p_RX_BIAS_CFG":0b100,
- "p_DMONITOR_CFG":0xA00,
- "p_RX_CM_SEL":0b11,
- "p_RX_CM_TRIM":0b010,
- "p_RX_DEBUG_CFG":0,
- "p_RX_OS_CFG":0b10000000,
- "p_TERM_RCAL_CFG":0,
- "p_TERM_RCAL_OVRD":0,
- "p_TST_RSV":0,
- "p_RX_CLK25_DIV":6,
- "p_TX_CLK25_DIV":6,
- "p_UCODEER_CLR":0,
-
- # PCI Express Attributes
- "p_PCS_PCIE_EN":"FALSE",
-
- # PCS Attributes
- "p_PCS_RSVD_ATTR":0x100,
-
- # RX Buffer Attributes
- "p_RXBUF_ADDR_MODE":"FAST",
- "p_RXBUF_EIDLE_HI_CNT":0b1000,
- "p_RXBUF_EIDLE_LO_CNT":0,
- "p_RXBUF_EN":"TRUE",
- "p_RX_BUFFER_CFG":0,
- "p_RXBUF_RESET_ON_CB_CHANGE":"TRUE",
- "p_RXBUF_RESET_ON_COMMAALIGN":"FALSE",
- "p_RXBUF_RESET_ON_EIDLE":"FALSE",
- "p_RXBUF_RESET_ON_RATE_CHANGE":"TRUE",
- "p_RXBUFRESET_TIME":1,
- "p_RXBUF_THRESH_OVFLW":61,
- "p_RXBUF_THRESH_OVRD":"FALSE",
- "p_RXBUF_THRESH_UNDFLW":4,
- "p_RXDLY_CFG":0x1f,
- "p_RXDLY_LCFG":0x30,
- "p_RXDLY_TAP_CFG":0,
- "p_RXPH_CFG":0,
- "p_RXPHDLY_CFG":0x084820,
- "p_RXPH_MONITOR_SEL":0,
- "p_RX_XCLK_SEL":"RXUSR",
- "p_RX_DDI_SEL":0,
- "p_RX_DEFER_RESET_BUF_EN":"TRUE",
-
- #CDR Attributes
- "p_RXCDR_CFG":rxcdr_cfg,
- "p_RXCDR_FR_RESET_ON_EIDLE":0,
- "p_RXCDR_HOLD_DURING_EIDLE":0,
- "p_RXCDR_PH_RESET_ON_EIDLE":0,
- "p_RXCDR_LOCK_CFG":0b010101,
-
- # RX Initialization and Reset Attributes
- "p_RXCDRFREQRESET_TIME":1,
- "p_RXCDRPHRESET_TIME":1,
- "p_RXISCANRESET_TIME":1,
- "p_RXPCSRESET_TIME":1,
- "p_RXPMARESET_TIME":3,
-
- # RX OOB Signaling Attributes
- "p_RXOOB_CFG":0b0000110,
-
- # RX Gearbox Attributes
- "p_RXGEARBOX_EN":"FALSE",
- "p_GEARBOX_MODE":0,
-
- # PRBS Detection Attribute
- "p_RXPRBS_ERR_LOOPBACK":0,
-
- # Power-Down Attributes
- "p_PD_TRANS_TIME_FROM_P2":0x03c,
- "p_PD_TRANS_TIME_NONE_P2":0x3c,
- "p_PD_TRANS_TIME_TO_P2":0x64,
-
- # RX OOB Signaling Attributes
- "p_SAS_MAX_COM":64,
- "p_SAS_MIN_COM":36,
- "p_SATA_BURST_SEQ_LEN":0b0101,
- "p_SATA_BURST_VAL":0b100,
- "p_SATA_EIDLE_VAL":0b100,
- "p_SATA_MAX_BURST":8,
- "p_SATA_MAX_INIT":21,
- "p_SATA_MAX_WAKE":7,
- "p_SATA_MIN_BURST":4,
- "p_SATA_MIN_INIT":12,
- "p_SATA_MIN_WAKE":4,
-
- # RX Fabric Clock Output Control Attributes
- "p_TRANS_TIME_RATE":0x0e,
-
- # TX Buffer Attributes
- "p_TXBUF_EN":"TRUE",
- "p_TXBUF_RESET_ON_RATE_CHANGE":"TRUE",
- "p_TXDLY_CFG":0x1f,
- "p_TXDLY_LCFG":0x030,
- "p_TXDLY_TAP_CFG":0,
- "p_TXPH_CFG":0x0780,
- "p_TXPHDLY_CFG":0x084020,
- "p_TXPH_MONITOR_SEL":0,
- "p_TX_XCLK_SEL":"TXOUT",
-
- # FPGA TX Interface Attributes
- "p_TX_DATA_WIDTH":20,
-
- # TX Configurable Driver Attributes
- "p_TX_DEEMPH0":0,
- "p_TX_DEEMPH1":0,
- "p_TX_EIDLE_ASSERT_DELAY":0b110,
- "p_TX_EIDLE_DEASSERT_DELAY":0b100,
- "p_TX_LOOPBACK_DRIVE_HIZ":"FALSE",
- "p_TX_MAINCURSOR_SEL":0,
- "p_TX_DRIVE_MODE":"DIRECT",
- "p_TX_MARGIN_FULL_0":0b1001110,
- "p_TX_MARGIN_FULL_1":0b1001001,
- "p_TX_MARGIN_FULL_2":0b1000101,
- "p_TX_MARGIN_FULL_3":0b1000010,
- "p_TX_MARGIN_FULL_4":0b1000000,
- "p_TX_MARGIN_LOW_0":0b1000110,
- "p_TX_MARGIN_LOW_1":0b1000100,
- "p_TX_MARGIN_LOW_2":0b1000010,
- "p_TX_MARGIN_LOW_3":0b1000000,
- "p_TX_MARGIN_LOW_4":0b1000000,
-
- # TX Gearbox Attributes
- "p_TXGEARBOX_EN":"FALSE",
-
- # TX Initialization and Reset Attributes
- "p_TXPCSRESET_TIME":1,
- "p_TXPMARESET_TIME":1,
-
- # TX Receiver Detection Attributes
- "p_TX_RXDETECT_CFG":0x1832,
- "p_TX_RXDETECT_REF":0b100,
-
- # CPLL Attributes
- "p_CPLL_CFG":0xBC07DC,
- "p_CPLL_FBDIV":4,
- "p_CPLL_FBDIV_45":5,
- "p_CPLL_INIT_CFG":0x00001e,
- "p_CPLL_LOCK_CFG":0x01e8,
- "p_CPLL_REFCLK_DIV":1,
- "p_RXOUT_DIV":rxout_div,
- "p_TXOUT_DIV":txout_div,
- "p_SATA_CPLL_CFG":"VCO_3000MHZ",
-
- # RX Initialization and Reset Attributes
- "p_RXDFELPMRESET_TIME":0b0001111,
-
- # RX Equalizer Attributes
- "p_RXLPM_HF_CFG":0b00000011110000,
- "p_RXLPM_LF_CFG":0b00000011110000,
- "p_RX_DFE_GAIN_CFG":0x020fea,
- "p_RX_DFE_H2_CFG":0b000000000000,
- "p_RX_DFE_H3_CFG":0b000001000000,
- "p_RX_DFE_H4_CFG":0b00011110000,
- "p_RX_DFE_H5_CFG":0b00011100000,
- "p_RX_DFE_KL_CFG":0b0000011111110,
- "p_RX_DFE_LPM_CFG":0x0954,
- "p_RX_DFE_LPM_HOLD_DURING_EIDLE":0,
- "p_RX_DFE_UT_CFG":0b10001111000000000,
- "p_RX_DFE_VP_CFG":0b00011111100000011,
-
- # Power-Down Attributes
- "p_RX_CLKMUX_PD":1,
- "p_TX_CLKMUX_PD":1,
-
- # FPGA RX Interface Attribute
- "p_RX_INT_DATAWIDTH":0,
-
- # FPGA TX Interface Attribute
- "p_TX_INT_DATAWIDTH":0,
-
- # TX Configurable Driver Attributes
- "p_TX_QPI_STATUS_EN":0,
-
- # RX Equalizer Attributes
- "p_RX_DFE_KL_CFG2":0b00110011000100000001100000001100,
- "p_RX_DFE_XYD_CFG":0b0000000000000,
-
- # TX Configurable Driver Attributes
- "p_TX_PREDRIVER_MODE":0,
- }
-
- self.specials += \
- Instance("GTXE2_CHANNEL",
- # CPLL Ports
- #o_CPLLFBCLKLOST=,
- o_CPLLLOCK=self.cplllock,
- i_CPLLLOCKDETCLK=0,
- i_CPLLLOCKEN=1,
- i_CPLLPD=0,
- #o_CPLLREFCLKLOST=0,
- i_CPLLREFCLKSEL=0b001,
- i_CPLLRESET=self.cpllreset,
- i_GTRSVD=0,
- i_PCSRSVDIN=0,
- i_PCSRSVDIN2=0,
- i_PMARSVDIN=0,
- i_PMARSVDIN2=0,
- i_TSTIN=ones(20),
- #o_TSTOUT=,
-
- # Channel
- i_CLKRSVD=0,
-
- # Channel - Clocking Ports
- i_GTGREFCLK=0,
- i_GTNORTHREFCLK0=0,
- i_GTNORTHREFCLK1=0,
- i_GTREFCLK0=self.gtrefclk0,
- i_GTREFCLK1=0,
- i_GTSOUTHREFCLK0=0,
- i_GTSOUTHREFCLK1=0,
-
- # Channel - DRP Ports
- i_DRPADDR=0,
- i_DRPCLK=0,
- i_DRPDI=0,
- #o_DRPDO=,
- i_DRPEN=0,
- #o_DRPRDY=,
- i_DRPWE=0,
-
- # Clocking Ports
- #o_GTREFCLKMONITOR=,
- i_QPLLCLK=self.qpllclk,
- i_QPLLREFCLK=self.qpllrefclk,
- i_RXSYSCLKSEL=0b00,
- i_TXSYSCLKSEL=0b00,
-
- # Digital Monitor Ports
- #o_DMONITOROUT=,
-
- # FPGA TX Interface Datapath Configuration
- i_TX8B10BEN=1,
-
- # Loopback Ports
- i_LOOPBACK=0,
-
- # PCI Express Ports
- #o_PHYSTATUS=,
- i_RXRATE=0,
- #o_RXVALID=,
-
- # Power-Down Ports
- i_RXPD=0b00,
- i_TXPD=0b00,
-
- # RX 8B/10B Decoder Ports
- i_SETERRSTATUS=0,
-
- # RX Initialization and Reset Ports
- i_EYESCANRESET=0,
- i_RXUSERRDY=rxuserrdy,
-
- # RX Margin Analysis Ports
- #o_EYESCANDATAERROR=,
- i_EYESCANMODE=0,
- i_EYESCANTRIGGER=0,
-
- # Receive Ports - CDR Ports
- i_RXCDRFREQRESET=0,
- i_RXCDRHOLD=0,
- o_RXCDRLOCK=rxcdrlock,
- i_RXCDROVRDEN=0,
- i_RXCDRRESET=0,
- i_RXCDRRESETRSV=0,
-
- # Receive Ports - Clock Correction Ports
- #o_RXCLKCORCNT=,
-
- # Receive Ports - FPGA RX Interface Datapath Configuration
- i_RX8B10BEN=1,
-
- # Receive Ports - FPGA RX Interface Ports
- i_RXUSRCLK=self.rxusrclk,
- i_RXUSRCLK2=self.rxusrclk2,
-
- # Receive Ports - FPGA RX interface Ports
- o_RXDATA=self.rxdata,
-
- # Receive Ports - Pattern Checker Ports
- #o_RXPRBSERR=,
- i_RXPRBSSEL=0,
-
- # Receive Ports - Pattern Checker ports
- i_RXPRBSCNTRESET=0,
-
- # Receive Ports - RX Equalizer Ports
- i_RXDFEXYDEN=0,
- i_RXDFEXYDHOLD=0,
- i_RXDFEXYDOVRDEN=0,
-
- # Receive Ports - RX 8B/10B Decoder Ports
- #o_RXDISPERR=,
- #o_RXNOTINTABLE=,
-
- # Receive Ports - RX AFE
- i_GTXRXP=pads.rxp,
- i_GTXRXN=pads.rxn,
-
- # Receive Ports - RX Buffer Bypass Ports
- i_RXBUFRESET=0,
- #o_RXBUFSTATUS=,
- i_RXDDIEN=0,
- i_RXDLYBYPASS=1,
- i_RXDLYEN=0,
- i_RXDLYOVRDEN=0,
- i_RXDLYSRESET=0,
- #o_RXDLYSRESETDONE=0,
- i_RXPHALIGN=0,
- #o_RXPHALIGNDONE=,
- i_RXPHALIGNEN=0,
- i_RXPHDLYPD=0,
- i_RXPHDLYRESET=0,
- #o_RXPHMONITOR=,
- i_RXPHOVRDEN=0,
- #o_RXPHSLIPMONITOR=,
- #o_RXSTATUS=,
-
- # Receive Ports - RX Byte and Word Alignment Ports
- o_RXBYTEISALIGNED=self.rxbyteisaligned,
- #o_RXBYTEREALIGN=,
- #o_RXCOMMADET=,
- i_RXCOMMADETEN=1,
- i_RXMCOMMAALIGNEN=1,
- i_RXPCOMMAALIGNEN=1,
-
- # Receive Ports - RX Channel Bonding Ports
- #o_RXCHANBONDSEQ=,
- i_RXCHBONDEN=0,
- i_RXCHBONDLEVEL=0,
- i_RXCHBONDMASTER=0,
- #o_RXCHBONDO=,
- i_RXCHBONDSLAVE=0,
-
- # Receive Ports - RX Channel Bonding Ports
- #o_RXCHANISALIGNED=,
- #o_RXCHANREALIGN=,
-
- # Receive Ports - RX Equalizer Ports
- i_RXDFEAGCHOLD=0,
- i_RXDFEAGCOVRDEN=0,
- i_RXDFECM1EN=0,
- i_RXDFELFHOLD=0,
- i_RXDFELFOVRDEN=1,
- i_RXDFELPMRESET=0,
- i_RXDFETAP2HOLD=0,
- i_RXDFETAP2OVRDEN=0,
- i_RXDFETAP3HOLD=0,
- i_RXDFETAP3OVRDEN=0,
- i_RXDFETAP4HOLD=0,
- i_RXDFETAP4OVRDEN=0,
- i_RXDFETAP5HOLD=0,
- i_RXDFETAP5OVRDEN=0,
- i_RXDFEUTHOLD=0,
- i_RXDFEUTOVRDEN=0,
- i_RXDFEVPHOLD=0,
- i_RXDFEVPOVRDEN=0,
- i_RXDFEVSEN=0,
- i_RXLPMLFKLOVRDEN=0,
- #o_RXMONITOROUT=,
- i_RXMONITORSEL=0b00,
- i_RXOSHOLD=0,
- i_RXOSOVRDEN=0,
-
- # Receive Ports - RX Equilizer Ports
- i_RXLPMHFHOLD=0,
- i_RXLPMHFOVRDEN=0,
- i_RXLPMLFHOLD=0,
-
- # Receive Ports - RX Fabric ClocK Output Control Ports
- #o_RXRATEDONE=,
-
- # Receive Ports - RX Fabric Output Control Ports
- o_RXOUTCLK=self.rxoutclk,
- #o_RXOUTCLKFABRIC=,
- #o_RXOUTCLKPCS=,
- i_RXOUTCLKSEL=0b010,
-
- # Receive Ports - RX Gearbox Ports
- #o_RXDATAVALID=,
- #o_RXHEADER=,
- #o_RXHEADERVALID=,
- #o_RXSTARTOFSEQ=,
-
- # Receive Ports - RX Gearbox Ports
- i_RXGEARBOXSLIP=0,
-
- # Receive Ports - RX Initialization and Reset Ports
- i_GTRXRESET=self.gtrxreset,
- i_RXOOBRESET=0,
- i_RXPCSRESET=0,
- i_RXPMARESET=self.pmarxreset,
-
- # Receive Ports - RX Margin Analysis ports
- i_RXLPMEN=0,
-
- # Receive Ports - RX OOB Signaling ports
- #o_RXCOMSASDET=,
- o_RXCOMWAKEDET=rxcomwakedet,
-
- # Receive Ports - RX OOB Signaling ports
- o_RXCOMINITDET=rxcominitdet,
-
- # Receive Ports - RX OOB signalling Ports
- o_RXELECIDLE=rxelecidle,
- i_RXELECIDLEMODE=0b00,
-
- # Receive Ports - RX Polarity Control Ports
- i_RXPOLARITY=0,
-
- # Receive Ports - RX gearbox ports
- i_RXSLIDE=0,
-
- # Receive Ports - RX8B/10B Decoder Ports
- #o_RXCHARISCOMMA=,
- o_RXCHARISK=self.rxcharisk,
-
- # Receive Ports - Rx Channel Bonding Ports
- i_RXCHBONDI=0,
-
- # Receive Ports -RX Initialization and Reset Ports
- o_RXRESETDONE=rxresetdone,
-
- # Rx AFE Ports
- i_RXQPIEN=0,
- #o_RXQPISENN=,
- #o_RXQPISENP=,
-
- # TX Buffer Bypass Ports
- i_TXPHDLYTSTCLK=0,
-
- # TX Configurable Driver Ports
- i_TXPOSTCURSOR=0,
- i_TXPOSTCURSORINV=0,
- i_TXPRECURSOR=0,
- i_TXPRECURSORINV=0,
- i_TXQPIBIASEN=0,
- i_TXQPISTRONGPDOWN=0,
- i_TXQPIWEAKPUP=0,
-
- # TX Initialization and Reset Ports
- i_CFGRESET=0,
- i_GTTXRESET=self.gttxreset,
- #o_PCSRSVDOUT=,
- i_TXUSERRDY=txuserrdy,
-
- # Transceiver Reset Mode Operation
- i_GTRESETSEL=0,
- i_RESETOVRD=0,
-
- # Transmit Ports - 8b10b Encoder Control Ports
- i_TXCHARDISPMODE=0,
- i_TXCHARDISPVAL=0,
-
- # Transmit Ports - FPGA TX Interface Ports
- i_TXUSRCLK=self.txusrclk,
- i_TXUSRCLK2=self.txusrclk2,
-
- # Transmit Ports - PCI Express Ports
- i_TXELECIDLE=txelecidle,
- i_TXMARGIN=0,
- i_TXRATE=txrate,
- i_TXSWING=0,
-
- # Transmit Ports - Pattern Generator Ports
- i_TXPRBSFORCEERR=0,
-
- # Transmit Ports - TX Buffer Bypass Ports
- i_TXDLYBYPASS=1,
- i_TXDLYEN=0,
- i_TXDLYHOLD=0,
- i_TXDLYOVRDEN=0,
- i_TXDLYSRESET=0,
- #o_TXDLYSRESETDONE=,
- i_TXDLYUPDOWN=0,
- i_TXPHALIGN=0,
- #o_TXPHALIGNDONE=txphaligndone,
- i_TXPHALIGNEN=0,
- i_TXPHDLYPD=0,
- i_TXPHDLYRESET=0,
- i_TXPHINIT=0,
- #o_TXPHINITDONE=,
- i_TXPHOVRDEN=0,
-
- # Transmit Ports - TX Buffer Ports
- #o_TXBUFSTATUS=,
-
- # Transmit Ports - TX Configurable Driver Ports
- i_TXBUFDIFFCTRL=0b100,
- i_TXDEEMPH=0,
- i_TXDIFFCTRL=0b1000,
- i_TXDIFFPD=0,
- i_TXINHIBIT=0,
- i_TXMAINCURSOR=0,
- i_TXPISOPD=0,
-
- # Transmit Ports - TX Data Path interface
- i_TXDATA=self.txdata,
-
- # Transmit Ports - TX Driver and OOB signaling
- o_GTXTXP=pads.txp,
- o_GTXTXN=pads.txn,
-
- # Transmit Ports - TX Fabric Clock Output Control Ports
- o_TXOUTCLK=self.txoutclk,
- #o_TXOUTCLKFABRIC=,
- #o_TXOUTCLKPCS=,
- i_TXOUTCLKSEL=0b11, #??
- #o_TXRATEDONE=,
- # Transmit Ports - TX Gearbox Ports
- i_TXCHARISK=self.txcharisk,
- #o_TXGEARBOXREADY=,
- i_TXHEADER=0,
- i_TXSEQUENCE=0,
- i_TXSTARTSEQ=0,
-
- # Transmit Ports - TX Initialization and Reset Ports
- i_TXPCSRESET=0,
- i_TXPMARESET=0,
- o_TXRESETDONE=txresetdone,
-
- # Transmit Ports - TX OOB signalling Ports
- o_TXCOMFINISH=txcomfinish,
- i_TXCOMINIT=txcominit,
- i_TXCOMSAS=0,
- i_TXCOMWAKE=txcomwake,
- i_TXPDELECIDLEMODE=0,
-
- # Transmit Ports - TX Polarity Control Ports
- i_TXPOLARITY=0,
-
- # Transmit Ports - TX Receiver Detection Ports
- i_TXDETECTRX=0,
-
- # Transmit Ports - TX8b/10b Encoder Ports
- i_TX8B10BBYPASS=0,
-
- # Transmit Ports - pattern Generator Ports
- i_TXPRBSSEL=0,
-
- # Tx Configurable Driver Ports
- #o_TXQPISENN=,
- #o_TXQPISENP=,
-
- **gtxe2_channel_parameters
- )
+ def __init__(self, pads, revision):
+ # Common signals
+
+ # control
+ self.tx_idle = Signal() #i
+
+ self.tx_cominit_stb = Signal() #i
+ self.tx_cominit_ack = Signal() #o
+ self.tx_comwake_stb = Signal() #i
+ self.tx_comwake_ack = Signal() #o
+
+ self.rx_idle = Signal() #o
+ self.rx_align = Signal() #i
+
+ self.rx_cominit_stb = Signal() #o
+ self.rx_comwake_stb = Signal() #o
+
+ # datapath
+ self.sink = Sink(phy_description(16))
+ self.source = Source(phy_description(16))
+
+ # K7 specific signals
+ # Channel - Ref Clock Ports
+ self.gtrefclk0 = Signal()
+
+ # Channel PLL
+ self.cplllock = Signal()
+ self.cpllreset = Signal()
+
+ # Receive Ports
+ self.rxuserrdy = Signal()
+ self.rxalign = Signal()
+
+ # Receive Ports - 8b10b Decoder
+ self.rxcharisk = Signal(2)
+ self.rxdisperr = Signal(2)
+
+ # Receive Ports - RX Data Path interface
+ self.gtrxreset = Signal()
+ self.pmarxreset = Signal()
+ self.rxdata = Signal(16)
+ self.rxoutclk = Signal()
+ self.rxusrclk = Signal()
+ self.rxusrclk2 = Signal()
+
+ # Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR
+ self.rxelecidle = Signal()
+
+ # Receive Ports - RX PLL Ports
+ self.rxresetdone = Signal()
+
+ # Receive Ports - RX Ports for SATA
+ self.rxcominitdet = Signal()
+ self.rxcomwakedet = Signal()
+
+ # Transmit Ports
+ self.txuserrdy = Signal()
+
+ # Transmit Ports - 8b10b Encoder Control Ports
+ self.txcharisk = Signal(2)
+
+ # Transmit Ports - TX Data Path interface
+ self.gttxreset = Signal()
+ self.txdata = Signal(16)
+ self.txoutclk = Signal()
+ self.txusrclk = Signal()
+ self.txusrclk2 = Signal()
+
+ # Transmit Ports - TX PLL Ports
+ self.txresetdone = Signal()
+
+ # Transmit Ports - TX Ports for PCI Express
+ self.txelecidle = Signal(reset=1)
+
+ # Transmit Ports - TX Ports for SATA
+ self.txcomfinish = Signal()
+ self.txcominit = Signal()
+ self.txcomwake = Signal()
+ self.txrate = Signal(3)
+ self.rxcdrlock = Signal()
+
+ # Config at startup
+ div_config = {
+ "sata_gen1" : 4,
+ "sata_gen2" : 2,
+ "sata_gen3" : 1
+ }
+ rxout_div = div_config[revision]
+ txout_div = div_config[revision]
+
+ cdr_config = {
+ "sata_gen1" : 0x0380008BFF40100008,
+ "sata_gen2" : 0x0388008BFF40200008,
+ "sata_gen3" : 0X0380008BFF10200010
+ }
+ rxcdr_cfg = cdr_config[revision]
+
+ # Specific / Generic signals encoding/decoding
+ self.comb += [
+ self.txelecidle.eq(self.tx_idle),
+ self.tx_cominit_ack.eq(self.tx_cominit_stb & self.txcomfinish),
+ self.tx_comwake_ack.eq(self.tx_comwake_stb & self.txcomfinish),
+ self.rx_idle.eq(self.rxelecidle),
+ self.rxalign.eq(self.rx_align),
+ self.rx_cominit_stb.eq(self.rxcominitdet),
+ self.rx_comwake_stb.eq(self.rxcomwakedet),
+ ]
+ self.submodules += [
+ _RisingEdge(self.tx_cominit_stb, self.txcominit),
+ _RisingEdge(self.tx_comwake_stb, self.txcomwake),
+ ]
+
+ self.comb += [
+ self.txcharisk.eq(self.sink.charisk),
+ self.txdata.eq(self.sink.data),
+ self.sink.ack.eq(1),
+
+ self.source.stb.eq(1),
+ self.source.charisk.eq(self.rxcharisk),
+ self.source.data.eq(self.rxdata)
+ ]
+
+ # Internals and clock domain crossing
+ # sys_clk --> sata_tx clk
+ txuserrdy = Signal()
+ txelecidle = Signal(reset=1)
+ txcominit = Signal()
+ txcomwake = Signal()
+ txrate = Signal(3)
+
+ self.specials += [
+ MultiReg(self.txuserrdy, txuserrdy, "sata_tx"),
+ MultiReg(self.txelecidle, txelecidle, "sata_tx"),
+ MultiReg(self.txrate, txrate, "sata_tx")
+ ]
+ self.submodules += [
+ _PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"),
+ _PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"),
+ ]
+
+ # sata_tx clk --> sys clk
+ txresetdone = Signal()
+ txcomfinish = Signal()
+
+ self.specials += [
+ MultiReg(txresetdone, self.txresetdone, "sys"),
+ ]
+
+ self.submodules += [
+ _PulseSynchronizer(txcomfinish, "sata_tx", self.txcomfinish, "sys"),
+ ]
+
+ # sys clk --> sata_rx clk
+ rxuserrdy = Signal()
+
+ self.specials += [
+ MultiReg(self.rxuserrdy, rxuserrdy, "sata_rx"),
+ ]
+
+ # sata_rx clk --> sys clk
+ rxelecidle = Signal()
+ rxelecidle_i = Signal()
+ rxelecidle_cnt_i = Signal(9)
+ rxresetdone = Signal()
+ rxcominitdet = Signal()
+ rxcomwakedet = Signal()
+ rxratedone = Signal()
+ rxcdrlock = Signal()
+
+ self.specials += [
+ MultiReg(rxelecidle, rxelecidle_i, "sys"),
+ MultiReg(rxresetdone, self.rxresetdone, "sys"),
+ MultiReg(rxcominitdet, self.rxcominitdet, "sys"),
+ MultiReg(rxcomwakedet, self.rxcomwakedet, "sys"),
+ MultiReg(rxcdrlock, self.rxcdrlock, "sys"),
+ ]
+
+ self.sync += [
+ If(rxelecidle_i != self.rxelecidle,
+ If(rxelecidle_cnt_i == 0,
+ self.rxelecidle.eq(rxelecidle_i),
+ rxelecidle_cnt_i.eq(255)
+ ).Else(
+ rxelecidle_cnt_i.eq(rxelecidle_cnt_i-1)
+ )
+ ).Else(
+ rxelecidle_cnt_i.eq(255)
+ )
+ ]
+
+ self.rxbyteisaligned = Signal()
+
+ # QPLL input clock
+ self.qpllclk = Signal()
+ self.qpllrefclk = Signal()
+
+ # Instance
+ gtxe2_channel_parameters = {
+ # Simulation-Only Attributes
+ "p_SIM_RECEIVER_DETECT_PASS":"TRUE",
+ "p_SIM_TX_EIDLE_DRIVE_LEVEL":"X",
+ "p_SIM_RESET_SPEEDUP":"TRUE",
+ "p_SIM_CPLLREFCLK_SEL":0b001,
+ "p_SIM_VERSION":"4.0",
+
+ # RX Byte and Word Alignment Attributes
+ "p_ALIGN_COMMA_DOUBLE":"FALSE",
+ "p_ALIGN_COMMA_ENABLE":ones(10),
+ "p_ALIGN_COMMA_WORD":2,
+ "p_ALIGN_MCOMMA_DET":"TRUE",
+ "p_ALIGN_MCOMMA_VALUE":0b1010000011,
+ "p_ALIGN_PCOMMA_DET":"TRUE",
+ "p_ALIGN_PCOMMA_VALUE":0b0101111100,
+ "p_SHOW_REALIGN_COMMA":"FALSE",
+ "p_RXSLIDE_AUTO_WAIT":7,
+ "p_RXSLIDE_MODE":"PCS",
+ "p_RX_SIG_VALID_DLY":10,
+
+ # RX 8B/10B Decoder Attributes
+ "p_RX_DISPERR_SEQ_MATCH":"TRUE",
+ "p_DEC_MCOMMA_DETECT":"TRUE",
+ "p_DEC_PCOMMA_DETECT":"TRUE",
+ "p_DEC_VALID_COMMA_ONLY":"FALSE",
+
+ # RX Clock Correction Attributes
+ "p_CBCC_DATA_SOURCE_SEL":"DECODED",
+ "p_CLK_COR_SEQ_2_USE":"FALSE",
+ "p_CLK_COR_KEEP_IDLE":"FALSE",
+ "p_CLK_COR_MAX_LAT":9,
+ "p_CLK_COR_MIN_LAT":7,
+ "p_CLK_COR_PRECEDENCE":"TRUE",
+ "p_CLK_COR_REPEAT_WAIT":0,
+ "p_CLK_COR_SEQ_LEN":1,
+ "p_CLK_COR_SEQ_1_ENABLE":ones(4),
+ "p_CLK_COR_SEQ_1_1":0b0100000000,
+ "p_CLK_COR_SEQ_1_2":0b0000000000,
+ "p_CLK_COR_SEQ_1_3":0b0000000000,
+ "p_CLK_COR_SEQ_1_4":0b0000000000,
+ "p_CLK_CORRECT_USE":"FALSE",
+ "p_CLK_COR_SEQ_2_ENABLE":ones(4),
+ "p_CLK_COR_SEQ_2_1":0b0100000000,
+ "p_CLK_COR_SEQ_2_2":0,
+ "p_CLK_COR_SEQ_2_3":0,
+ "p_CLK_COR_SEQ_2_4":0,
+
+ # RX Channel Bonding Attributes
+ "p_CHAN_BOND_KEEP_ALIGN":"FALSE",
+ "p_CHAN_BOND_MAX_SKEW":1,
+ "p_CHAN_BOND_SEQ_LEN":1,
+ "p_CHAN_BOND_SEQ_1_1":0,
+ "p_CHAN_BOND_SEQ_1_1":0,
+ "p_CHAN_BOND_SEQ_1_2":0,
+ "p_CHAN_BOND_SEQ_1_3":0,
+ "p_CHAN_BOND_SEQ_1_4":0,
+ "p_CHAN_BOND_SEQ_1_ENABLE":ones(4),
+ "p_CHAN_BOND_SEQ_2_1":0,
+ "p_CHAN_BOND_SEQ_2_2":0,
+ "p_CHAN_BOND_SEQ_2_3":0,
+ "p_CHAN_BOND_SEQ_2_4":0,
+ "p_CHAN_BOND_SEQ_2_ENABLE":ones(4),
+ "p_CHAN_BOND_SEQ_2_USE":"FALSE",
+ "p_FTS_DESKEW_SEQ_ENABLE":ones(4),
+ "p_FTS_LANE_DESKEW_CFG":ones(4),
+ "p_FTS_LANE_DESKEW_EN":"FALSE",
+
+ # RX Margin Analysis Attributes
+ "p_ES_CONTROL":0,
+ "p_ES_ERRDET_EN":"FALSE",
+ "p_ES_EYE_SCAN_EN":"TRUE",
+ "p_ES_HORZ_OFFSET":0,
+ "p_ES_PMA_CFG":0,
+ "p_ES_PRESCALE":0,
+ "p_ES_QUALIFIER":0,
+ "p_ES_QUAL_MASK":0,
+ "p_ES_SDATA_MASK":0,
+ "p_ES_VERT_OFFSET":0,
+
+ # FPGA RX Interface Attributes
+ "p_RX_DATA_WIDTH":20,
+
+ # PMA Attributes
+ "p_OUTREFCLK_SEL_INV":0b11,
+ "p_PMA_RSV":0x00018480,
+ "p_PMA_RSV2":0x2050,
+ "p_PMA_RSV3":0,
+ "p_PMA_RSV4":0,
+ "p_RX_BIAS_CFG":0b100,
+ "p_DMONITOR_CFG":0xA00,
+ "p_RX_CM_SEL":0b11,
+ "p_RX_CM_TRIM":0b010,
+ "p_RX_DEBUG_CFG":0,
+ "p_RX_OS_CFG":0b10000000,
+ "p_TERM_RCAL_CFG":0,
+ "p_TERM_RCAL_OVRD":0,
+ "p_TST_RSV":0,
+ "p_RX_CLK25_DIV":6,
+ "p_TX_CLK25_DIV":6,
+ "p_UCODEER_CLR":0,
+
+ # PCI Express Attributes
+ "p_PCS_PCIE_EN":"FALSE",
+
+ # PCS Attributes
+ "p_PCS_RSVD_ATTR":0x100,
+
+ # RX Buffer Attributes
+ "p_RXBUF_ADDR_MODE":"FAST",
+ "p_RXBUF_EIDLE_HI_CNT":0b1000,
+ "p_RXBUF_EIDLE_LO_CNT":0,
+ "p_RXBUF_EN":"TRUE",
+ "p_RX_BUFFER_CFG":0,
+ "p_RXBUF_RESET_ON_CB_CHANGE":"TRUE",
+ "p_RXBUF_RESET_ON_COMMAALIGN":"FALSE",
+ "p_RXBUF_RESET_ON_EIDLE":"FALSE",
+ "p_RXBUF_RESET_ON_RATE_CHANGE":"TRUE",
+ "p_RXBUFRESET_TIME":1,
+ "p_RXBUF_THRESH_OVFLW":61,
+ "p_RXBUF_THRESH_OVRD":"FALSE",
+ "p_RXBUF_THRESH_UNDFLW":4,
+ "p_RXDLY_CFG":0x1f,
+ "p_RXDLY_LCFG":0x30,
+ "p_RXDLY_TAP_CFG":0,
+ "p_RXPH_CFG":0,
+ "p_RXPHDLY_CFG":0x084820,
+ "p_RXPH_MONITOR_SEL":0,
+ "p_RX_XCLK_SEL":"RXUSR",
+ "p_RX_DDI_SEL":0,
+ "p_RX_DEFER_RESET_BUF_EN":"TRUE",
+
+ #CDR Attributes
+ "p_RXCDR_CFG":rxcdr_cfg,
+ "p_RXCDR_FR_RESET_ON_EIDLE":0,
+ "p_RXCDR_HOLD_DURING_EIDLE":0,
+ "p_RXCDR_PH_RESET_ON_EIDLE":0,
+ "p_RXCDR_LOCK_CFG":0b010101,
+
+ # RX Initialization and Reset Attributes
+ "p_RXCDRFREQRESET_TIME":1,
+ "p_RXCDRPHRESET_TIME":1,
+ "p_RXISCANRESET_TIME":1,
+ "p_RXPCSRESET_TIME":1,
+ "p_RXPMARESET_TIME":3,
+
+ # RX OOB Signaling Attributes
+ "p_RXOOB_CFG":0b0000110,
+
+ # RX Gearbox Attributes
+ "p_RXGEARBOX_EN":"FALSE",
+ "p_GEARBOX_MODE":0,
+
+ # PRBS Detection Attribute
+ "p_RXPRBS_ERR_LOOPBACK":0,
+
+ # Power-Down Attributes
+ "p_PD_TRANS_TIME_FROM_P2":0x03c,
+ "p_PD_TRANS_TIME_NONE_P2":0x3c,
+ "p_PD_TRANS_TIME_TO_P2":0x64,
+
+ # RX OOB Signaling Attributes
+ "p_SAS_MAX_COM":64,
+ "p_SAS_MIN_COM":36,
+ "p_SATA_BURST_SEQ_LEN":0b0101,
+ "p_SATA_BURST_VAL":0b100,
+ "p_SATA_EIDLE_VAL":0b100,
+ "p_SATA_MAX_BURST":8,
+ "p_SATA_MAX_INIT":21,
+ "p_SATA_MAX_WAKE":7,
+ "p_SATA_MIN_BURST":4,
+ "p_SATA_MIN_INIT":12,
+ "p_SATA_MIN_WAKE":4,
+
+ # RX Fabric Clock Output Control Attributes
+ "p_TRANS_TIME_RATE":0x0e,
+
+ # TX Buffer Attributes
+ "p_TXBUF_EN":"TRUE",
+ "p_TXBUF_RESET_ON_RATE_CHANGE":"TRUE",
+ "p_TXDLY_CFG":0x1f,
+ "p_TXDLY_LCFG":0x030,
+ "p_TXDLY_TAP_CFG":0,
+ "p_TXPH_CFG":0x0780,
+ "p_TXPHDLY_CFG":0x084020,
+ "p_TXPH_MONITOR_SEL":0,
+ "p_TX_XCLK_SEL":"TXOUT",
+
+ # FPGA TX Interface Attributes
+ "p_TX_DATA_WIDTH":20,
+
+ # TX Configurable Driver Attributes
+ "p_TX_DEEMPH0":0,
+ "p_TX_DEEMPH1":0,
+ "p_TX_EIDLE_ASSERT_DELAY":0b110,
+ "p_TX_EIDLE_DEASSERT_DELAY":0b100,
+ "p_TX_LOOPBACK_DRIVE_HIZ":"FALSE",
+ "p_TX_MAINCURSOR_SEL":0,
+ "p_TX_DRIVE_MODE":"DIRECT",
+ "p_TX_MARGIN_FULL_0":0b1001110,
+ "p_TX_MARGIN_FULL_1":0b1001001,
+ "p_TX_MARGIN_FULL_2":0b1000101,
+ "p_TX_MARGIN_FULL_3":0b1000010,
+ "p_TX_MARGIN_FULL_4":0b1000000,
+ "p_TX_MARGIN_LOW_0":0b1000110,
+ "p_TX_MARGIN_LOW_1":0b1000100,
+ "p_TX_MARGIN_LOW_2":0b1000010,
+ "p_TX_MARGIN_LOW_3":0b1000000,
+ "p_TX_MARGIN_LOW_4":0b1000000,
+
+ # TX Gearbox Attributes
+ "p_TXGEARBOX_EN":"FALSE",
+
+ # TX Initialization and Reset Attributes
+ "p_TXPCSRESET_TIME":1,
+ "p_TXPMARESET_TIME":1,
+
+ # TX Receiver Detection Attributes
+ "p_TX_RXDETECT_CFG":0x1832,
+ "p_TX_RXDETECT_REF":0b100,
+
+ # CPLL Attributes
+ "p_CPLL_CFG":0xBC07DC,
+ "p_CPLL_FBDIV":4,
+ "p_CPLL_FBDIV_45":5,
+ "p_CPLL_INIT_CFG":0x00001e,
+ "p_CPLL_LOCK_CFG":0x01e8,
+ "p_CPLL_REFCLK_DIV":1,
+ "p_RXOUT_DIV":rxout_div,
+ "p_TXOUT_DIV":txout_div,
+ "p_SATA_CPLL_CFG":"VCO_3000MHZ",
+
+ # RX Initialization and Reset Attributes
+ "p_RXDFELPMRESET_TIME":0b0001111,
+
+ # RX Equalizer Attributes
+ "p_RXLPM_HF_CFG":0b00000011110000,
+ "p_RXLPM_LF_CFG":0b00000011110000,
+ "p_RX_DFE_GAIN_CFG":0x020fea,
+ "p_RX_DFE_H2_CFG":0b000000000000,
+ "p_RX_DFE_H3_CFG":0b000001000000,
+ "p_RX_DFE_H4_CFG":0b00011110000,
+ "p_RX_DFE_H5_CFG":0b00011100000,
+ "p_RX_DFE_KL_CFG":0b0000011111110,
+ "p_RX_DFE_LPM_CFG":0x0954,
+ "p_RX_DFE_LPM_HOLD_DURING_EIDLE":0,
+ "p_RX_DFE_UT_CFG":0b10001111000000000,
+ "p_RX_DFE_VP_CFG":0b00011111100000011,
+
+ # Power-Down Attributes
+ "p_RX_CLKMUX_PD":1,
+ "p_TX_CLKMUX_PD":1,
+
+ # FPGA RX Interface Attribute
+ "p_RX_INT_DATAWIDTH":0,
+
+ # FPGA TX Interface Attribute
+ "p_TX_INT_DATAWIDTH":0,
+
+ # TX Configurable Driver Attributes
+ "p_TX_QPI_STATUS_EN":0,
+
+ # RX Equalizer Attributes
+ "p_RX_DFE_KL_CFG2":0b00110011000100000001100000001100,
+ "p_RX_DFE_XYD_CFG":0b0000000000000,
+
+ # TX Configurable Driver Attributes
+ "p_TX_PREDRIVER_MODE":0,
+ }
+
+ self.specials += \
+ Instance("GTXE2_CHANNEL",
+ # CPLL Ports
+ #o_CPLLFBCLKLOST=,
+ o_CPLLLOCK=self.cplllock,
+ i_CPLLLOCKDETCLK=0,
+ i_CPLLLOCKEN=1,
+ i_CPLLPD=0,
+ #o_CPLLREFCLKLOST=0,
+ i_CPLLREFCLKSEL=0b001,
+ i_CPLLRESET=self.cpllreset,
+ i_GTRSVD=0,
+ i_PCSRSVDIN=0,
+ i_PCSRSVDIN2=0,
+ i_PMARSVDIN=0,
+ i_PMARSVDIN2=0,
+ i_TSTIN=ones(20),
+ #o_TSTOUT=,
+
+ # Channel
+ i_CLKRSVD=0,
+
+ # Channel - Clocking Ports
+ i_GTGREFCLK=0,
+ i_GTNORTHREFCLK0=0,
+ i_GTNORTHREFCLK1=0,
+ i_GTREFCLK0=self.gtrefclk0,
+ i_GTREFCLK1=0,
+ i_GTSOUTHREFCLK0=0,
+ i_GTSOUTHREFCLK1=0,
+
+ # Channel - DRP Ports
+ i_DRPADDR=0,
+ i_DRPCLK=0,
+ i_DRPDI=0,
+ #o_DRPDO=,
+ i_DRPEN=0,
+ #o_DRPRDY=,
+ i_DRPWE=0,
+
+ # Clocking Ports
+ #o_GTREFCLKMONITOR=,
+ i_QPLLCLK=self.qpllclk,
+ i_QPLLREFCLK=self.qpllrefclk,
+ i_RXSYSCLKSEL=0b00,
+ i_TXSYSCLKSEL=0b00,
+
+ # Digital Monitor Ports
+ #o_DMONITOROUT=,
+
+ # FPGA TX Interface Datapath Configuration
+ i_TX8B10BEN=1,
+
+ # Loopback Ports
+ i_LOOPBACK=0,
+
+ # PCI Express Ports
+ #o_PHYSTATUS=,
+ i_RXRATE=0,
+ #o_RXVALID=,
+
+ # Power-Down Ports
+ i_RXPD=0b00,
+ i_TXPD=0b00,
+
+ # RX 8B/10B Decoder Ports
+ i_SETERRSTATUS=0,
+
+ # RX Initialization and Reset Ports
+ i_EYESCANRESET=0,
+ i_RXUSERRDY=rxuserrdy,
+
+ # RX Margin Analysis Ports
+ #o_EYESCANDATAERROR=,
+ i_EYESCANMODE=0,
+ i_EYESCANTRIGGER=0,
+
+ # Receive Ports - CDR Ports
+ i_RXCDRFREQRESET=0,
+ i_RXCDRHOLD=0,
+ o_RXCDRLOCK=rxcdrlock,
+ i_RXCDROVRDEN=0,
+ i_RXCDRRESET=0,
+ i_RXCDRRESETRSV=0,
+
+ # Receive Ports - Clock Correction Ports
+ #o_RXCLKCORCNT=,
+
+ # Receive Ports - FPGA RX Interface Datapath Configuration
+ i_RX8B10BEN=1,
+
+ # Receive Ports - FPGA RX Interface Ports
+ i_RXUSRCLK=self.rxusrclk,
+ i_RXUSRCLK2=self.rxusrclk2,
+
+ # Receive Ports - FPGA RX interface Ports
+ o_RXDATA=self.rxdata,
+
+ # Receive Ports - Pattern Checker Ports
+ #o_RXPRBSERR=,
+ i_RXPRBSSEL=0,
+
+ # Receive Ports - Pattern Checker ports
+ i_RXPRBSCNTRESET=0,
+
+ # Receive Ports - RX Equalizer Ports
+ i_RXDFEXYDEN=0,
+ i_RXDFEXYDHOLD=0,
+ i_RXDFEXYDOVRDEN=0,
+
+ # Receive Ports - RX 8B/10B Decoder Ports
+ #o_RXDISPERR=,
+ #o_RXNOTINTABLE=,
+
+ # Receive Ports - RX AFE
+ i_GTXRXP=pads.rxp,
+ i_GTXRXN=pads.rxn,
+
+ # Receive Ports - RX Buffer Bypass Ports
+ i_RXBUFRESET=0,
+ #o_RXBUFSTATUS=,
+ i_RXDDIEN=0,
+ i_RXDLYBYPASS=1,
+ i_RXDLYEN=0,
+ i_RXDLYOVRDEN=0,
+ i_RXDLYSRESET=0,
+ #o_RXDLYSRESETDONE=0,
+ i_RXPHALIGN=0,
+ #o_RXPHALIGNDONE=,
+ i_RXPHALIGNEN=0,
+ i_RXPHDLYPD=0,
+ i_RXPHDLYRESET=0,
+ #o_RXPHMONITOR=,
+ i_RXPHOVRDEN=0,
+ #o_RXPHSLIPMONITOR=,
+ #o_RXSTATUS=,
+
+ # Receive Ports - RX Byte and Word Alignment Ports
+ o_RXBYTEISALIGNED=self.rxbyteisaligned,
+ #o_RXBYTEREALIGN=,
+ #o_RXCOMMADET=,
+ i_RXCOMMADETEN=1,
+ i_RXMCOMMAALIGNEN=1,
+ i_RXPCOMMAALIGNEN=1,
+
+ # Receive Ports - RX Channel Bonding Ports
+ #o_RXCHANBONDSEQ=,
+ i_RXCHBONDEN=0,
+ i_RXCHBONDLEVEL=0,
+ i_RXCHBONDMASTER=0,
+ #o_RXCHBONDO=,
+ i_RXCHBONDSLAVE=0,
+
+ # Receive Ports - RX Channel Bonding Ports
+ #o_RXCHANISALIGNED=,
+ #o_RXCHANREALIGN=,
+
+ # Receive Ports - RX Equalizer Ports
+ i_RXDFEAGCHOLD=0,
+ i_RXDFEAGCOVRDEN=0,
+ i_RXDFECM1EN=0,
+ i_RXDFELFHOLD=0,
+ i_RXDFELFOVRDEN=1,
+ i_RXDFELPMRESET=0,
+ i_RXDFETAP2HOLD=0,
+ i_RXDFETAP2OVRDEN=0,
+ i_RXDFETAP3HOLD=0,
+ i_RXDFETAP3OVRDEN=0,
+ i_RXDFETAP4HOLD=0,
+ i_RXDFETAP4OVRDEN=0,
+ i_RXDFETAP5HOLD=0,
+ i_RXDFETAP5OVRDEN=0,
+ i_RXDFEUTHOLD=0,
+ i_RXDFEUTOVRDEN=0,
+ i_RXDFEVPHOLD=0,
+ i_RXDFEVPOVRDEN=0,
+ i_RXDFEVSEN=0,
+ i_RXLPMLFKLOVRDEN=0,
+ #o_RXMONITOROUT=,
+ i_RXMONITORSEL=0b00,
+ i_RXOSHOLD=0,
+ i_RXOSOVRDEN=0,
+
+ # Receive Ports - RX Equilizer Ports
+ i_RXLPMHFHOLD=0,
+ i_RXLPMHFOVRDEN=0,
+ i_RXLPMLFHOLD=0,
+
+ # Receive Ports - RX Fabric ClocK Output Control Ports
+ #o_RXRATEDONE=,
+
+ # Receive Ports - RX Fabric Output Control Ports
+ o_RXOUTCLK=self.rxoutclk,
+ #o_RXOUTCLKFABRIC=,
+ #o_RXOUTCLKPCS=,
+ i_RXOUTCLKSEL=0b010,
+
+ # Receive Ports - RX Gearbox Ports
+ #o_RXDATAVALID=,
+ #o_RXHEADER=,
+ #o_RXHEADERVALID=,
+ #o_RXSTARTOFSEQ=,
+
+ # Receive Ports - RX Gearbox Ports
+ i_RXGEARBOXSLIP=0,
+
+ # Receive Ports - RX Initialization and Reset Ports
+ i_GTRXRESET=self.gtrxreset,
+ i_RXOOBRESET=0,
+ i_RXPCSRESET=0,
+ i_RXPMARESET=self.pmarxreset,
+
+ # Receive Ports - RX Margin Analysis ports
+ i_RXLPMEN=0,
+
+ # Receive Ports - RX OOB Signaling ports
+ #o_RXCOMSASDET=,
+ o_RXCOMWAKEDET=rxcomwakedet,
+
+ # Receive Ports - RX OOB Signaling ports
+ o_RXCOMINITDET=rxcominitdet,
+
+ # Receive Ports - RX OOB signalling Ports
+ o_RXELECIDLE=rxelecidle,
+ i_RXELECIDLEMODE=0b00,
+
+ # Receive Ports - RX Polarity Control Ports
+ i_RXPOLARITY=0,
+
+ # Receive Ports - RX gearbox ports
+ i_RXSLIDE=0,
+
+ # Receive Ports - RX8B/10B Decoder Ports
+ #o_RXCHARISCOMMA=,
+ o_RXCHARISK=self.rxcharisk,
+
+ # Receive Ports - Rx Channel Bonding Ports
+ i_RXCHBONDI=0,
+
+ # Receive Ports -RX Initialization and Reset Ports
+ o_RXRESETDONE=rxresetdone,
+
+ # Rx AFE Ports
+ i_RXQPIEN=0,
+ #o_RXQPISENN=,
+ #o_RXQPISENP=,
+
+ # TX Buffer Bypass Ports
+ i_TXPHDLYTSTCLK=0,
+
+ # TX Configurable Driver Ports
+ i_TXPOSTCURSOR=0,
+ i_TXPOSTCURSORINV=0,
+ i_TXPRECURSOR=0,
+ i_TXPRECURSORINV=0,
+ i_TXQPIBIASEN=0,
+ i_TXQPISTRONGPDOWN=0,
+ i_TXQPIWEAKPUP=0,
+
+ # TX Initialization and Reset Ports
+ i_CFGRESET=0,
+ i_GTTXRESET=self.gttxreset,
+ #o_PCSRSVDOUT=,
+ i_TXUSERRDY=txuserrdy,
+
+ # Transceiver Reset Mode Operation
+ i_GTRESETSEL=0,
+ i_RESETOVRD=0,
+
+ # Transmit Ports - 8b10b Encoder Control Ports
+ i_TXCHARDISPMODE=0,
+ i_TXCHARDISPVAL=0,
+
+ # Transmit Ports - FPGA TX Interface Ports
+ i_TXUSRCLK=self.txusrclk,
+ i_TXUSRCLK2=self.txusrclk2,
+
+ # Transmit Ports - PCI Express Ports
+ i_TXELECIDLE=txelecidle,
+ i_TXMARGIN=0,
+ i_TXRATE=txrate,
+ i_TXSWING=0,
+
+ # Transmit Ports - Pattern Generator Ports
+ i_TXPRBSFORCEERR=0,
+
+ # Transmit Ports - TX Buffer Bypass Ports
+ i_TXDLYBYPASS=1,
+ i_TXDLYEN=0,
+ i_TXDLYHOLD=0,
+ i_TXDLYOVRDEN=0,
+ i_TXDLYSRESET=0,
+ #o_TXDLYSRESETDONE=,
+ i_TXDLYUPDOWN=0,
+ i_TXPHALIGN=0,
+ #o_TXPHALIGNDONE=txphaligndone,
+ i_TXPHALIGNEN=0,
+ i_TXPHDLYPD=0,
+ i_TXPHDLYRESET=0,
+ i_TXPHINIT=0,
+ #o_TXPHINITDONE=,
+ i_TXPHOVRDEN=0,
+
+ # Transmit Ports - TX Buffer Ports
+ #o_TXBUFSTATUS=,
+
+ # Transmit Ports - TX Configurable Driver Ports
+ i_TXBUFDIFFCTRL=0b100,
+ i_TXDEEMPH=0,
+ i_TXDIFFCTRL=0b1000,
+ i_TXDIFFPD=0,
+ i_TXINHIBIT=0,
+ i_TXMAINCURSOR=0,
+ i_TXPISOPD=0,
+
+ # Transmit Ports - TX Data Path interface
+ i_TXDATA=self.txdata,
+
+ # Transmit Ports - TX Driver and OOB signaling
+ o_GTXTXP=pads.txp,
+ o_GTXTXN=pads.txn,
+
+ # Transmit Ports - TX Fabric Clock Output Control Ports
+ o_TXOUTCLK=self.txoutclk,
+ #o_TXOUTCLKFABRIC=,
+ #o_TXOUTCLKPCS=,
+ i_TXOUTCLKSEL=0b11, #??
+ #o_TXRATEDONE=,
+ # Transmit Ports - TX Gearbox Ports
+ i_TXCHARISK=self.txcharisk,
+ #o_TXGEARBOXREADY=,
+ i_TXHEADER=0,
+ i_TXSEQUENCE=0,
+ i_TXSTARTSEQ=0,
+
+ # Transmit Ports - TX Initialization and Reset Ports
+ i_TXPCSRESET=0,
+ i_TXPMARESET=0,
+ o_TXRESETDONE=txresetdone,
+
+ # Transmit Ports - TX OOB signalling Ports
+ o_TXCOMFINISH=txcomfinish,
+ i_TXCOMINIT=txcominit,
+ i_TXCOMSAS=0,
+ i_TXCOMWAKE=txcomwake,
+ i_TXPDELECIDLEMODE=0,
+
+ # Transmit Ports - TX Polarity Control Ports
+ i_TXPOLARITY=0,
+
+ # Transmit Ports - TX Receiver Detection Ports
+ i_TXDETECTRX=0,
+
+ # Transmit Ports - TX8b/10b Encoder Ports
+ i_TX8B10BBYPASS=0,
+
+ # Transmit Ports - pattern Generator Ports
+ i_TXPRBSSEL=0,
+
+ # Tx Configurable Driver Ports
+ #o_TXQPISENN=,
+ #o_TXQPISENP=,
+
+ **gtxe2_channel_parameters
+ )
from misoclib.mem.litesata.test.common import *
class TB(Module):
- def __init__(self):
- self.submodules.hdd = HDD(
- link_debug=False, link_random_level=0,
- transport_debug=False, transport_loopback=False,
- hdd_debug=True)
- self.submodules.controller = LiteSATA(self.hdd.phy)
- self.submodules.generator = LiteSATABISTGenerator(self.controller.crossbar.get_port())
- self.submodules.checker = LiteSATABISTChecker(self.controller.crossbar.get_port())
+ def __init__(self):
+ self.submodules.hdd = HDD(
+ link_debug=False, link_random_level=0,
+ transport_debug=False, transport_loopback=False,
+ hdd_debug=True)
+ self.submodules.controller = LiteSATA(self.hdd.phy)
+ self.submodules.generator = LiteSATABISTGenerator(self.controller.crossbar.get_port())
+ self.submodules.checker = LiteSATABISTChecker(self.controller.crossbar.get_port())
- def gen_simulation(self, selfp):
- hdd = self.hdd
- hdd.malloc(0, 64)
- selfp.generator.sector = 0
- selfp.generator.count = 17
- selfp.checker.sector = 0
- selfp.checker.count = 17
- while True:
- selfp.generator.start = 1
- yield
- selfp.generator.start = 0
- yield
- while selfp.generator.done == 0:
- yield
- selfp.checker.start = 1
- yield
- selfp.checker.start = 0
- yield
- while selfp.checker.done == 0:
- yield
- print("errors {}".format(selfp.checker.errors))
- selfp.generator.sector += 1
- selfp.generator.count = max((selfp.generator.count + 1)%8, 1)
- selfp.checker.sector += 1
- selfp.checker.count = max((selfp.checker.count + 1)%8, 1)
+ def gen_simulation(self, selfp):
+ hdd = self.hdd
+ hdd.malloc(0, 64)
+ selfp.generator.sector = 0
+ selfp.generator.count = 17
+ selfp.checker.sector = 0
+ selfp.checker.count = 17
+ while True:
+ selfp.generator.start = 1
+ yield
+ selfp.generator.start = 0
+ yield
+ while selfp.generator.done == 0:
+ yield
+ selfp.checker.start = 1
+ yield
+ selfp.checker.start = 0
+ yield
+ while selfp.checker.done == 0:
+ yield
+ print("errors {}".format(selfp.checker.errors))
+ selfp.generator.sector += 1
+ selfp.generator.count = max((selfp.generator.count + 1)%8, 1)
+ selfp.checker.sector += 1
+ selfp.checker.count = max((selfp.checker.count + 1)%8, 1)
if __name__ == "__main__":
- run_simulation(TB(), ncycles=8192*2, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=8192*2, vcd_name="my.vcd", keep_files=True)
from misoclib.mem.litesata.test.common import *
class CommandTXPacket(list):
- def __init__(self, write=0, read=0, sector=0, count=0, data=[]):
- self.ongoing = False
- self.done = False
- self.write = write
- self.read = read
- self.sector = sector
- self.count = count
- for d in data:
- self.append(d)
+ def __init__(self, write=0, read=0, sector=0, count=0, data=[]):
+ self.ongoing = False
+ self.done = False
+ self.write = write
+ self.read = read
+ self.sector = sector
+ self.count = count
+ for d in data:
+ self.append(d)
class CommandStreamer(PacketStreamer):
- def __init__(self):
- PacketStreamer.__init__(self, command_tx_description(32), CommandTXPacket)
+ def __init__(self):
+ PacketStreamer.__init__(self, command_tx_description(32), CommandTXPacket)
- def do_simulation(self, selfp):
- PacketStreamer.do_simulation(self, selfp)
- selfp.source.write = self.packet.write
- selfp.source.read = self.packet.read
- selfp.source.sector = self.packet.sector
- selfp.source.count = self.packet.count
+ def do_simulation(self, selfp):
+ PacketStreamer.do_simulation(self, selfp)
+ selfp.source.write = self.packet.write
+ selfp.source.read = self.packet.read
+ selfp.source.sector = self.packet.sector
+ selfp.source.count = self.packet.count
class CommandRXPacket(list):
- def __init__(self):
- self.ongoing = False
- self.done = False
- self.write = 0
- self.read = 0
- self.failed = 0
+ def __init__(self):
+ self.ongoing = False
+ self.done = False
+ self.write = 0
+ self.read = 0
+ self.failed = 0
class CommandLogger(PacketLogger):
- def __init__(self):
- PacketLogger.__init__(self, command_rx_description(32), CommandRXPacket)
+ def __init__(self):
+ PacketLogger.__init__(self, command_rx_description(32), CommandRXPacket)
- def do_simulation(self, selfp):
- selfp.sink.ack = 1
- if selfp.sink.stb == 1 and selfp.sink.sop == 1:
- self.packet = CommandRXPacket()
- self.packet.write = selfp.sink.write
- self.packet.read = selfp.sink.read
- self.packet.failed = selfp.sink.failed
- self.packet.append(selfp.sink.data)
- elif selfp.sink.stb:
- self.packet.append(selfp.sink.data)
- if selfp.sink.stb == 1 and selfp.sink.eop == 1:
- self.packet.done = True
+ def do_simulation(self, selfp):
+ selfp.sink.ack = 1
+ if selfp.sink.stb == 1 and selfp.sink.sop == 1:
+ self.packet = CommandRXPacket()
+ self.packet.write = selfp.sink.write
+ self.packet.read = selfp.sink.read
+ self.packet.failed = selfp.sink.failed
+ self.packet.append(selfp.sink.data)
+ elif selfp.sink.stb:
+ self.packet.append(selfp.sink.data)
+ if selfp.sink.stb == 1 and selfp.sink.eop == 1:
+ self.packet.done = True
class TB(Module):
- def __init__(self):
- self.submodules.hdd = HDD(
- link_debug=False, link_random_level=50,
- transport_debug=False, transport_loopback=False,
- hdd_debug=True)
- self.submodules.core = LiteSATACore(self.hdd.phy, buffer_depth=512)
+ def __init__(self):
+ self.submodules.hdd = HDD(
+ link_debug=False, link_random_level=50,
+ transport_debug=False, transport_loopback=False,
+ hdd_debug=True)
+ self.submodules.core = LiteSATACore(self.hdd.phy, buffer_depth=512)
- self.submodules.streamer = CommandStreamer()
- self.submodules.streamer_randomizer = Randomizer(command_tx_description(32), level=50)
+ self.submodules.streamer = CommandStreamer()
+ self.submodules.streamer_randomizer = Randomizer(command_tx_description(32), level=50)
- self.submodules.logger = CommandLogger()
- self.submodules.logger_randomizer = Randomizer(command_rx_description(32), level=50)
+ self.submodules.logger = CommandLogger()
+ self.submodules.logger_randomizer = Randomizer(command_rx_description(32), level=50)
- self.submodules.pipeline = Pipeline(
- self.streamer,
- self.streamer_randomizer,
- self.core,
- self.logger_randomizer,
- self.logger
- )
+ self.submodules.pipeline = Pipeline(
+ self.streamer,
+ self.streamer_randomizer,
+ self.core,
+ self.logger_randomizer,
+ self.logger
+ )
- def gen_simulation(self, selfp):
- hdd = self.hdd
- hdd.malloc(0, 64)
- write_data = [i for i in range(sectors2dwords(2))]
- write_len = dwords2sectors(len(write_data))
- write_packet = CommandTXPacket(write=1, sector=2, count=write_len, data=write_data)
- yield from self.streamer.send(write_packet)
- yield from self.logger.receive()
- read_packet = CommandTXPacket(read=1, sector=2, count=write_len)
- yield from self.streamer.send(read_packet)
- yield from self.logger.receive()
- read_data = self.logger.packet
+ def gen_simulation(self, selfp):
+ hdd = self.hdd
+ hdd.malloc(0, 64)
+ write_data = [i for i in range(sectors2dwords(2))]
+ write_len = dwords2sectors(len(write_data))
+ write_packet = CommandTXPacket(write=1, sector=2, count=write_len, data=write_data)
+ yield from self.streamer.send(write_packet)
+ yield from self.logger.receive()
+ read_packet = CommandTXPacket(read=1, sector=2, count=write_len)
+ yield from self.streamer.send(read_packet)
+ yield from self.logger.receive()
+ read_data = self.logger.packet
- # check results
- s, l, e = check(write_data, read_data)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ # check results
+ s, l, e = check(write_data, read_data)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
- run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
from misoclib.mem.litesata.common import *
def seed_to_data(seed, random=True):
- if random:
- return (seed * 0x31415979 + 1) & 0xffffffff
- else:
- return seed
+ if random:
+ return (seed * 0x31415979 + 1) & 0xffffffff
+ else:
+ return seed
def check(p1, p2):
- p1 = copy.deepcopy(p1)
- p2 = copy.deepcopy(p2)
- if isinstance(p1, int):
- return 0, 1, int(p1 != p2)
- else:
- if len(p1) >= len(p2):
- ref, res = p1, p2
- else:
- ref, res = p2, p1
- shift = 0
- while((ref[0] != res[0]) and (len(res)>1)):
- res.pop(0)
- shift += 1
- length = min(len(ref), len(res))
- errors = 0
- for i in range(length):
- if ref.pop(0) != res.pop(0):
- errors += 1
- return shift, length, errors
+ p1 = copy.deepcopy(p1)
+ p2 = copy.deepcopy(p2)
+ if isinstance(p1, int):
+ return 0, 1, int(p1 != p2)
+ else:
+ if len(p1) >= len(p2):
+ ref, res = p1, p2
+ else:
+ ref, res = p2, p1
+ shift = 0
+ while((ref[0] != res[0]) and (len(res)>1)):
+ res.pop(0)
+ shift += 1
+ length = min(len(ref), len(res))
+ errors = 0
+ for i in range(length):
+ if ref.pop(0) != res.pop(0):
+ errors += 1
+ return shift, length, errors
def randn(max_n):
- return random.randint(0, max_n-1)
+ return random.randint(0, max_n-1)
class PacketStreamer(Module):
- def __init__(self, description, packet_class):
- self.source = Source(description)
- ###
- self.packets = []
- self.packet = packet_class()
- self.packet.done = 1
-
- self.source_data = 0
-
- def send(self, packet, blocking=True):
- packet = copy.deepcopy(packet)
- self.packets.append(packet)
- if blocking:
- while packet.done == 0:
- yield
-
- def do_simulation(self, selfp):
- if len(self.packets) and self.packet.done:
- self.packet = self.packets.pop(0)
- if not self.packet.ongoing and not self.packet.done:
- selfp.source.stb = 1
- if self.source.description.packetized:
- selfp.source.sop = 1
- if len(self.packet) > 0:
- self.source_data = self.packet.pop(0)
- if hasattr(selfp.source, "data"):
- selfp.source.data = self.source_data
- else:
- selfp.source.d = self.source_data
- self.packet.ongoing = True
- elif selfp.source.stb == 1 and selfp.source.ack == 1:
- if self.source.description.packetized:
- selfp.source.sop = 0
- selfp.source.eop = (len(self.packet) == 1)
- if len(self.packet) > 0:
- selfp.source.stb = 1
- self.source_data = self.packet.pop(0)
- if hasattr(selfp.source, "data"):
- selfp.source.data = self.source_data
- else:
- selfp.source.d = self.source_data
- else:
- self.packet.done = 1
- selfp.source.stb = 0
+ def __init__(self, description, packet_class):
+ self.source = Source(description)
+ ###
+ self.packets = []
+ self.packet = packet_class()
+ self.packet.done = 1
+
+ self.source_data = 0
+
+ def send(self, packet, blocking=True):
+ packet = copy.deepcopy(packet)
+ self.packets.append(packet)
+ if blocking:
+ while packet.done == 0:
+ yield
+
+ def do_simulation(self, selfp):
+ if len(self.packets) and self.packet.done:
+ self.packet = self.packets.pop(0)
+ if not self.packet.ongoing and not self.packet.done:
+ selfp.source.stb = 1
+ if self.source.description.packetized:
+ selfp.source.sop = 1
+ if len(self.packet) > 0:
+ self.source_data = self.packet.pop(0)
+ if hasattr(selfp.source, "data"):
+ selfp.source.data = self.source_data
+ else:
+ selfp.source.d = self.source_data
+ self.packet.ongoing = True
+ elif selfp.source.stb == 1 and selfp.source.ack == 1:
+ if self.source.description.packetized:
+ selfp.source.sop = 0
+ selfp.source.eop = (len(self.packet) == 1)
+ if len(self.packet) > 0:
+ selfp.source.stb = 1
+ self.source_data = self.packet.pop(0)
+ if hasattr(selfp.source, "data"):
+ selfp.source.data = self.source_data
+ else:
+ selfp.source.d = self.source_data
+ else:
+ self.packet.done = 1
+ selfp.source.stb = 0
class PacketLogger(Module):
- def __init__(self, description, packet_class):
- self.sink = Sink(description)
- ###
- self.packet_class = packet_class
- self.packet = packet_class()
-
- def receive(self, length=None):
- self.packet.done = 0
- if length is None:
- while self.packet.done == 0:
- yield
- else:
- while length > len(self.packet):
- yield
-
- def do_simulation(self, selfp):
- selfp.sink.ack = 1
- if self.sink.description.packetized:
- if selfp.sink.stb == 1 and selfp.sink.sop == 1:
- self.packet = self.packet_class()
- if selfp.sink.stb:
- if hasattr(selfp.sink, "data"):
- self.packet.append(selfp.sink.data)
- else:
- self.packet.append(selfp.sink.d)
- if self.sink.description.packetized:
- if selfp.sink.stb == 1 and selfp.sink.eop == 1:
- self.packet.done = True
+ def __init__(self, description, packet_class):
+ self.sink = Sink(description)
+ ###
+ self.packet_class = packet_class
+ self.packet = packet_class()
+
+ def receive(self, length=None):
+ self.packet.done = 0
+ if length is None:
+ while self.packet.done == 0:
+ yield
+ else:
+ while length > len(self.packet):
+ yield
+
+ def do_simulation(self, selfp):
+ selfp.sink.ack = 1
+ if self.sink.description.packetized:
+ if selfp.sink.stb == 1 and selfp.sink.sop == 1:
+ self.packet = self.packet_class()
+ if selfp.sink.stb:
+ if hasattr(selfp.sink, "data"):
+ self.packet.append(selfp.sink.data)
+ else:
+ self.packet.append(selfp.sink.d)
+ if self.sink.description.packetized:
+ if selfp.sink.stb == 1 and selfp.sink.eop == 1:
+ self.packet.done = True
class Randomizer(Module):
- def __init__(self, description, level=0):
- self.level = level
-
- self.sink = Sink(description)
- self.source = Source(description)
-
- self.run = Signal()
-
- self.comb += \
- If(self.run,
- Record.connect(self.sink, self.source)
- ).Else(
- self.source.stb.eq(0),
- self.sink.ack.eq(0),
- )
-
- def do_simulation(self, selfp):
- n = randn(100)
- if n < self.level:
- selfp.run = 0
- else:
- selfp.run = 1
+ def __init__(self, description, level=0):
+ self.level = level
+
+ self.sink = Sink(description)
+ self.source = Source(description)
+
+ self.run = Signal()
+
+ self.comb += \
+ If(self.run,
+ Record.connect(self.sink, self.source)
+ ).Else(
+ self.source.stb.eq(0),
+ self.sink.ack.eq(0),
+ )
+
+ def do_simulation(self, selfp):
+ n = randn(100)
+ if n < self.level:
+ selfp.run = 0
+ else:
+ selfp.run = 1
from misoclib.mem.litesata.test.common import *
class ContPacket(list):
- def __init__(self, data=[]):
- self.ongoing = False
- self.done = False
- for d in data:
- self.append(d)
+ def __init__(self, data=[]):
+ self.ongoing = False
+ self.done = False
+ for d in data:
+ self.append(d)
class ContStreamer(PacketStreamer):
- def __init__(self):
- PacketStreamer.__init__(self, phy_description(32), ContPacket)
+ def __init__(self):
+ PacketStreamer.__init__(self, phy_description(32), ContPacket)
- def do_simulation(self, selfp):
- PacketStreamer.do_simulation(self, selfp)
- selfp.source.charisk = 0
- # Note: for simplicity we generate charisk by detecting
- # primitives in data
- for k, v in primitives.items():
- try:
- if self.source_data == v:
- selfp.source.charisk = 0b0001
- except:
- pass
+ def do_simulation(self, selfp):
+ PacketStreamer.do_simulation(self, selfp)
+ selfp.source.charisk = 0
+ # Note: for simplicity we generate charisk by detecting
+ # primitives in data
+ for k, v in primitives.items():
+ try:
+ if self.source_data == v:
+ selfp.source.charisk = 0b0001
+ except:
+ pass
class ContLogger(PacketLogger):
- def __init__(self):
- PacketLogger.__init__(self, phy_description(32), ContPacket)
+ def __init__(self):
+ PacketLogger.__init__(self, phy_description(32), ContPacket)
class TB(Module):
- def __init__(self):
- self.submodules.streamer = ContStreamer()
- self.submodules.streamer_randomizer = Randomizer(phy_description(32), level=50)
- self.submodules.inserter = LiteSATACONTInserter(phy_description(32))
- self.submodules.remover = LiteSATACONTRemover(phy_description(32))
- self.submodules.logger_randomizer = Randomizer(phy_description(32), level=50)
- self.submodules.logger = ContLogger()
+ def __init__(self):
+ self.submodules.streamer = ContStreamer()
+ self.submodules.streamer_randomizer = Randomizer(phy_description(32), level=50)
+ self.submodules.inserter = LiteSATACONTInserter(phy_description(32))
+ self.submodules.remover = LiteSATACONTRemover(phy_description(32))
+ self.submodules.logger_randomizer = Randomizer(phy_description(32), level=50)
+ self.submodules.logger = ContLogger()
- self.submodules.pipeline = Pipeline(
- self.streamer,
- self.streamer_randomizer,
- self.inserter,
- self.remover,
- self.logger_randomizer,
- self.logger
- )
+ self.submodules.pipeline = Pipeline(
+ self.streamer,
+ self.streamer_randomizer,
+ self.inserter,
+ self.remover,
+ self.logger_randomizer,
+ self.logger
+ )
- def gen_simulation(self, selfp):
- test_packet = ContPacket([
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["ALIGN"],
- primitives["ALIGN"],
- primitives["SYNC"],
- primitives["SYNC"],
- #primitives["SYNC"],
- 0x00000000,
- 0x00000001,
- 0x00000002,
- 0x00000003,
- 0x00000004,
- 0x00000005,
- 0x00000006,
- 0x00000007,
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["ALIGN"],
- primitives["ALIGN"],
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["SYNC"],
- primitives["SYNC"]]*4
- )
- streamer_packet = ContPacket(test_packet)
- yield from self.streamer.send(streamer_packet)
- yield from self.logger.receive(len(test_packet))
- #for d in self.logger.packet:
- # print("%08x" %d)
+ def gen_simulation(self, selfp):
+ test_packet = ContPacket([
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["ALIGN"],
+ primitives["ALIGN"],
+ primitives["SYNC"],
+ primitives["SYNC"],
+ #primitives["SYNC"],
+ 0x00000000,
+ 0x00000001,
+ 0x00000002,
+ 0x00000003,
+ 0x00000004,
+ 0x00000005,
+ 0x00000006,
+ 0x00000007,
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["ALIGN"],
+ primitives["ALIGN"],
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["SYNC"],
+ primitives["SYNC"]]*4
+ )
+ streamer_packet = ContPacket(test_packet)
+ yield from self.streamer.send(streamer_packet)
+ yield from self.logger.receive(len(test_packet))
+ #for d in self.logger.packet:
+ # print("%08x" %d)
- # check results
- s, l, e = check(streamer_packet, self.logger.packet)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ # check results
+ s, l, e = check(streamer_packet, self.logger.packet)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
- run_simulation(TB(), ncycles=1024, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=1024, vcd_name="my.vcd", keep_files=True)
from misoclib.mem.litesata.test.common import *
class TB(Module):
- def __init__(self, length, random):
- self.submodules.crc = LiteSATACRC()
- self.length = length
- self.random = random
-
- def get_c_crc(self, datas):
- stdin = ""
- for data in datas:
- stdin += "0x%08x " %data
- stdin += "exit"
- with subprocess.Popen("./crc", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
- process.stdin.write(stdin.encode("ASCII"))
- out, err = process.communicate()
- return int(out.decode("ASCII"), 16)
-
- def gen_simulation(self, selfp):
- # init CRC
- selfp.crc.d = 0
- selfp.crc.ce = 1
- selfp.crc.reset = 1
- yield
- selfp.crc.reset = 0
-
- # feed CRC with datas
- datas = []
- for i in range(self.length):
- data = seed_to_data(i, self.random)
- datas.append(data)
- selfp.crc.d = data
- yield
-
- # log results
- yield
- sim_crc = selfp.crc.value
-
- # stop
- selfp.crc.ce = 0
- for i in range(32):
- yield
-
- # get C core reference
- c_crc = self.get_c_crc(datas)
-
- # check results
- s, l, e = check(c_crc, sim_crc)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ def __init__(self, length, random):
+ self.submodules.crc = LiteSATACRC()
+ self.length = length
+ self.random = random
+
+ def get_c_crc(self, datas):
+ stdin = ""
+ for data in datas:
+ stdin += "0x%08x " %data
+ stdin += "exit"
+ with subprocess.Popen("./crc", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
+ process.stdin.write(stdin.encode("ASCII"))
+ out, err = process.communicate()
+ return int(out.decode("ASCII"), 16)
+
+ def gen_simulation(self, selfp):
+ # init CRC
+ selfp.crc.d = 0
+ selfp.crc.ce = 1
+ selfp.crc.reset = 1
+ yield
+ selfp.crc.reset = 0
+
+ # feed CRC with datas
+ datas = []
+ for i in range(self.length):
+ data = seed_to_data(i, self.random)
+ datas.append(data)
+ selfp.crc.d = data
+ yield
+
+ # log results
+ yield
+ sim_crc = selfp.crc.value
+
+ # stop
+ selfp.crc.ce = 0
+ for i in range(32):
+ yield
+
+ # get C core reference
+ c_crc = self.get_c_crc(datas)
+
+ # check results
+ s, l, e = check(c_crc, sim_crc)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
- from migen.sim.generic import run_simulation
- length = 8192
- run_simulation(TB(length, True), ncycles=length+100, vcd_name="my.vcd")
+ from migen.sim.generic import run_simulation
+ length = 8192
+ run_simulation(TB(length, True), ncycles=length+100, vcd_name="my.vcd")
from misoclib.mem.litesata.test.common import *
def print_with_prefix(s, prefix=""):
- if not isinstance(s, str):
- s = s.__repr__()
- s = s.split("\n")
- for l in s:
- print(prefix + l)
+ if not isinstance(s, str):
+ s = s.__repr__()
+ s = s.split("\n")
+ for l in s:
+ print(prefix + l)
# PHY Layer model
class PHYDword:
- def __init__(self, dat=0):
- self.dat = dat
- self.start = 1
- self.done = 0
+ def __init__(self, dat=0):
+ self.dat = dat
+ self.start = 1
+ self.done = 0
class PHYSource(Module):
- def __init__(self):
- self.source = Source(phy_description(32))
- ###
- self.dword = PHYDword()
-
- def send(self, dword):
- self.dword = dword
-
- def do_simulation(self, selfp):
- selfp.source.stb = 1
- selfp.source.charisk = 0b0000
- for k, v in primitives.items():
- if v == self.dword.dat:
- selfp.source.charisk = 0b0001
- selfp.source.data = self.dword.dat
+ def __init__(self):
+ self.source = Source(phy_description(32))
+ ###
+ self.dword = PHYDword()
+
+ def send(self, dword):
+ self.dword = dword
+
+ def do_simulation(self, selfp):
+ selfp.source.stb = 1
+ selfp.source.charisk = 0b0000
+ for k, v in primitives.items():
+ if v == self.dword.dat:
+ selfp.source.charisk = 0b0001
+ selfp.source.data = self.dword.dat
class PHYSink(Module):
- def __init__(self):
- self.sink = Sink(phy_description(32))
- ###
- self.dword = PHYDword()
-
- def receive(self):
- self.dword.done = 0
- while self.dword.done == 0:
- yield
-
- def do_simulation(self, selfp):
- self.dword.done = 0
- selfp.sink.ack = 1
- if selfp.sink.stb == 1:
- self.dword.done = 1
- self.dword.dat = selfp.sink.data
+ def __init__(self):
+ self.sink = Sink(phy_description(32))
+ ###
+ self.dword = PHYDword()
+
+ def receive(self):
+ self.dword.done = 0
+ while self.dword.done == 0:
+ yield
+
+ def do_simulation(self, selfp):
+ self.dword.done = 0
+ selfp.sink.ack = 1
+ if selfp.sink.stb == 1:
+ self.dword.done = 1
+ self.dword.dat = selfp.sink.data
class PHYLayer(Module):
- def __init__(self):
+ def __init__(self):
- self.submodules.rx = PHYSink()
- self.submodules.tx = PHYSource()
+ self.submodules.rx = PHYSink()
+ self.submodules.tx = PHYSource()
- self.source = self.tx.source
- self.sink = self.rx.sink
+ self.source = self.tx.source
+ self.sink = self.rx.sink
- def send(self, dword):
- packet = PHYDword(dword)
- self.tx.send(packet)
+ def send(self, dword):
+ packet = PHYDword(dword)
+ self.tx.send(packet)
- def receive(self):
- yield from self.rx.receive()
+ def receive(self):
+ yield from self.rx.receive()
- def __repr__(self):
- receiving = "%08x " %self.rx.dword.dat
- receiving += decode_primitive(self.rx.dword.dat)
- receiving += " "*(16-len(receiving))
+ def __repr__(self):
+ receiving = "%08x " %self.rx.dword.dat
+ receiving += decode_primitive(self.rx.dword.dat)
+ receiving += " "*(16-len(receiving))
- sending = "%08x " %self.tx.dword.dat
- sending += decode_primitive(self.tx.dword.dat)
- sending += " "*(16-len(sending))
+ sending = "%08x " %self.tx.dword.dat
+ sending += decode_primitive(self.tx.dword.dat)
+ sending += " "*(16-len(sending))
- return receiving + sending
+ return receiving + sending
# Link Layer model
def print_link(s):
- print_with_prefix(s, "[LNK]: ")
+ print_with_prefix(s, "[LNK]: ")
def import_scrambler_datas():
- with subprocess.Popen(["./scrambler"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
- process.stdin.write("0x10000".encode("ASCII"))
- out, err = process.communicate()
- return [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
+ with subprocess.Popen(["./scrambler"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
+ process.stdin.write("0x10000".encode("ASCII"))
+ out, err = process.communicate()
+ return [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
class LinkPacket(list):
- def __init__(self, init=[]):
- self.ongoing = False
- self.done = False
- self.scrambled_datas = import_scrambler_datas()
- for dword in init:
- self.append(dword)
+ def __init__(self, init=[]):
+ self.ongoing = False
+ self.done = False
+ self.scrambled_datas = import_scrambler_datas()
+ for dword in init:
+ self.append(dword)
class LinkRXPacket(LinkPacket):
- def descramble(self):
- for i in range(len(self)):
- self[i] = self[i] ^ self.scrambled_datas[i]
-
- def check_crc(self):
- stdin = ""
- for v in self[:-1]:
- stdin += "0x%08x " %v
- stdin += "exit"
- with subprocess.Popen("./crc", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
- process.stdin.write(stdin.encode("ASCII"))
- out, err = process.communicate()
- crc = int(out.decode("ASCII"), 16)
- r = (self[-1] == crc)
- self.pop()
- return r
-
- def decode(self):
- self.descramble()
- return self.check_crc()
+ def descramble(self):
+ for i in range(len(self)):
+ self[i] = self[i] ^ self.scrambled_datas[i]
+
+ def check_crc(self):
+ stdin = ""
+ for v in self[:-1]:
+ stdin += "0x%08x " %v
+ stdin += "exit"
+ with subprocess.Popen("./crc", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
+ process.stdin.write(stdin.encode("ASCII"))
+ out, err = process.communicate()
+ crc = int(out.decode("ASCII"), 16)
+ r = (self[-1] == crc)
+ self.pop()
+ return r
+
+ def decode(self):
+ self.descramble()
+ return self.check_crc()
class LinkTXPacket(LinkPacket):
- def insert_crc(self):
- stdin = ""
- for v in self:
- stdin += "0x%08x " %v
- stdin += "exit"
- with subprocess.Popen("./crc", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
- process.stdin.write(stdin.encode("ASCII"))
- out, err = process.communicate()
- crc = int(out.decode("ASCII"), 16)
- self.append(crc)
-
- def scramble(self):
- for i in range(len(self)):
- self[i] = self[i] ^ self.scrambled_datas[i]
-
- def encode(self):
- self.insert_crc()
- self.scramble()
+ def insert_crc(self):
+ stdin = ""
+ for v in self:
+ stdin += "0x%08x " %v
+ stdin += "exit"
+ with subprocess.Popen("./crc", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
+ process.stdin.write(stdin.encode("ASCII"))
+ out, err = process.communicate()
+ crc = int(out.decode("ASCII"), 16)
+ self.append(crc)
+
+ def scramble(self):
+ for i in range(len(self)):
+ self[i] = self[i] ^ self.scrambled_datas[i]
+
+ def encode(self):
+ self.insert_crc()
+ self.scramble()
class LinkLayer(Module):
- def __init__(self, phy, debug=False, random_level=0):
- self.phy = phy
- self.debug = debug
- self.random_level = random_level
- self.tx_packets = []
- self.tx_packet = LinkTXPacket()
- self.rx_packet = LinkRXPacket()
-
- self.rx_cont = False
- self.rx_last = 0
- self.tx_cont = False
- self.tx_cont_nb = -1
- self.tx_lasts = [0, 0, 0]
-
- self.scrambled_datas = import_scrambler_datas()
-
- self.transport_callback = None
-
- self.send_state = ""
- self.send_states = ["RDY", "SOF", "DATA", "EOF", "WTRM"]
-
- def set_transport_callback(self, callback):
- self.transport_callback = callback
-
- def send(self, dword):
- if self.send_state == "RDY":
- self.phy.send(primitives["X_RDY"])
- if dword == primitives["R_RDY"]:
- self.send_state = "SOF"
- elif self.send_state == "SOF":
- self.phy.send(primitives["SOF"])
- self.send_state = "DATA"
- elif self.send_state == "DATA":
- if dword == primitives["HOLD"]:
- self.phy.send(primitives["HOLDA"])
- else:
- self.phy.send(self.tx_packet.pop(0))
- if len(self.tx_packet) == 0:
- self.send_state = "EOF"
- elif self.send_state == "EOF":
- self.phy.send(primitives["EOF"])
- self.send_state = "WTRM"
- elif self.send_state == "WTRM":
- self.phy.send(primitives["WTRM"])
- if dword == primitives["R_OK"]:
- self.tx_packet.done = True
- elif dword == primitives["R_ERR"]:
- self.tx_packet.done = True
- if self.tx_packet.done:
- self.phy.send(primitives["SYNC"])
-
- def insert_cont(self):
- self.tx_lasts.pop(0)
- self.tx_lasts.append(self.phy.tx.dword.dat)
- self.tx_cont = True
- for i in range(3):
- if not is_primitive(self.tx_lasts[i]):
- self.tx_cont = False
- if self.tx_lasts[i] != self.tx_lasts[0]:
- self.tx_cont = False
- if self.tx_cont:
- if self.tx_cont_nb == 0:
- self.phy.send(primitives["CONT"])
- else:
- self.phy.send(self.scrambled_datas[self.tx_cont_nb])
- self.tx_cont_nb += 1
- else:
- self.tx_cont_nb = 0
-
- def remove_cont(self, dword):
- if dword == primitives["HOLD"]:
- if self.rx_cont:
- self.tx_lasts = [0, 0, 0]
- if dword == primitives["CONT"]:
- self.rx_cont = True
- elif is_primitive(dword):
- self.rx_last = dword
- self.rx_cont = False
- if self.rx_cont:
- dword = self.rx_last
- return dword
-
- def callback(self, dword):
- if dword == primitives["X_RDY"]:
- self.phy.send(primitives["R_RDY"])
- elif dword == primitives["WTRM"]:
- self.phy.send(primitives["R_OK"])
- if self.rx_packet.ongoing:
- self.rx_packet.decode()
- if self.transport_callback is not None:
- self.transport_callback(self.rx_packet)
- self.rx_packet.ongoing = False
- elif dword == primitives["HOLD"]:
- self.phy.send(primitives["HOLDA"])
- elif dword == primitives["EOF"]:
- pass
- elif self.rx_packet.ongoing:
- if dword != primitives["HOLD"]:
- n = randn(100)
- if n < self.random_level:
- self.phy.send(primitives["HOLD"])
- else:
- self.phy.send(primitives["R_IP"])
- if not is_primitive(dword):
- self.rx_packet.append(dword)
- elif dword == primitives["SOF"]:
- self.rx_packet = LinkRXPacket()
- self.rx_packet.ongoing = True
-
- def gen_simulation(self, selfp):
- self.tx_packet.done = True
- self.phy.send(primitives["SYNC"])
- while True:
- yield from self.phy.receive()
- if self.debug:
- print_link(self.phy)
- self.phy.send(primitives["SYNC"])
- rx_dword = self.phy.rx.dword.dat
- rx_dword = self.remove_cont(rx_dword)
- if len(self.tx_packets) != 0:
- if self.tx_packet.done:
- self.tx_packet = self.tx_packets.pop(0)
- self.tx_packet.encode()
- self.send_state = "RDY"
- if not self.tx_packet.done:
- self.send(rx_dword)
- else:
- self.callback(rx_dword)
- self.insert_cont()
+ def __init__(self, phy, debug=False, random_level=0):
+ self.phy = phy
+ self.debug = debug
+ self.random_level = random_level
+ self.tx_packets = []
+ self.tx_packet = LinkTXPacket()
+ self.rx_packet = LinkRXPacket()
+
+ self.rx_cont = False
+ self.rx_last = 0
+ self.tx_cont = False
+ self.tx_cont_nb = -1
+ self.tx_lasts = [0, 0, 0]
+
+ self.scrambled_datas = import_scrambler_datas()
+
+ self.transport_callback = None
+
+ self.send_state = ""
+ self.send_states = ["RDY", "SOF", "DATA", "EOF", "WTRM"]
+
+ def set_transport_callback(self, callback):
+ self.transport_callback = callback
+
+ def send(self, dword):
+ if self.send_state == "RDY":
+ self.phy.send(primitives["X_RDY"])
+ if dword == primitives["R_RDY"]:
+ self.send_state = "SOF"
+ elif self.send_state == "SOF":
+ self.phy.send(primitives["SOF"])
+ self.send_state = "DATA"
+ elif self.send_state == "DATA":
+ if dword == primitives["HOLD"]:
+ self.phy.send(primitives["HOLDA"])
+ else:
+ self.phy.send(self.tx_packet.pop(0))
+ if len(self.tx_packet) == 0:
+ self.send_state = "EOF"
+ elif self.send_state == "EOF":
+ self.phy.send(primitives["EOF"])
+ self.send_state = "WTRM"
+ elif self.send_state == "WTRM":
+ self.phy.send(primitives["WTRM"])
+ if dword == primitives["R_OK"]:
+ self.tx_packet.done = True
+ elif dword == primitives["R_ERR"]:
+ self.tx_packet.done = True
+ if self.tx_packet.done:
+ self.phy.send(primitives["SYNC"])
+
+ def insert_cont(self):
+ self.tx_lasts.pop(0)
+ self.tx_lasts.append(self.phy.tx.dword.dat)
+ self.tx_cont = True
+ for i in range(3):
+ if not is_primitive(self.tx_lasts[i]):
+ self.tx_cont = False
+ if self.tx_lasts[i] != self.tx_lasts[0]:
+ self.tx_cont = False
+ if self.tx_cont:
+ if self.tx_cont_nb == 0:
+ self.phy.send(primitives["CONT"])
+ else:
+ self.phy.send(self.scrambled_datas[self.tx_cont_nb])
+ self.tx_cont_nb += 1
+ else:
+ self.tx_cont_nb = 0
+
+ def remove_cont(self, dword):
+ if dword == primitives["HOLD"]:
+ if self.rx_cont:
+ self.tx_lasts = [0, 0, 0]
+ if dword == primitives["CONT"]:
+ self.rx_cont = True
+ elif is_primitive(dword):
+ self.rx_last = dword
+ self.rx_cont = False
+ if self.rx_cont:
+ dword = self.rx_last
+ return dword
+
+ def callback(self, dword):
+ if dword == primitives["X_RDY"]:
+ self.phy.send(primitives["R_RDY"])
+ elif dword == primitives["WTRM"]:
+ self.phy.send(primitives["R_OK"])
+ if self.rx_packet.ongoing:
+ self.rx_packet.decode()
+ if self.transport_callback is not None:
+ self.transport_callback(self.rx_packet)
+ self.rx_packet.ongoing = False
+ elif dword == primitives["HOLD"]:
+ self.phy.send(primitives["HOLDA"])
+ elif dword == primitives["EOF"]:
+ pass
+ elif self.rx_packet.ongoing:
+ if dword != primitives["HOLD"]:
+ n = randn(100)
+ if n < self.random_level:
+ self.phy.send(primitives["HOLD"])
+ else:
+ self.phy.send(primitives["R_IP"])
+ if not is_primitive(dword):
+ self.rx_packet.append(dword)
+ elif dword == primitives["SOF"]:
+ self.rx_packet = LinkRXPacket()
+ self.rx_packet.ongoing = True
+
+ def gen_simulation(self, selfp):
+ self.tx_packet.done = True
+ self.phy.send(primitives["SYNC"])
+ while True:
+ yield from self.phy.receive()
+ if self.debug:
+ print_link(self.phy)
+ self.phy.send(primitives["SYNC"])
+ rx_dword = self.phy.rx.dword.dat
+ rx_dword = self.remove_cont(rx_dword)
+ if len(self.tx_packets) != 0:
+ if self.tx_packet.done:
+ self.tx_packet = self.tx_packets.pop(0)
+ self.tx_packet.encode()
+ self.send_state = "RDY"
+ if not self.tx_packet.done:
+ self.send(rx_dword)
+ else:
+ self.callback(rx_dword)
+ self.insert_cont()
# Transport Layer model
def print_transport(s):
- print_with_prefix(s, "[TRN]: ")
+ print_with_prefix(s, "[TRN]: ")
def get_field_data(field, packet):
- return (packet[field.dword] >> field.offset) & (2**field.width-1)
+ return (packet[field.dword] >> field.offset) & (2**field.width-1)
class FIS:
- def __init__(self, packet, description, direction="H2D"):
- self.packet = packet
- self.description = description
- self.direction = direction
- self.decode()
-
- def decode(self):
- for k, v in self.description.items():
- setattr(self, k, get_field_data(v, self.packet))
-
- def encode(self):
- for k, v in self.description.items():
- self.packet[v.dword] |= (getattr(self, k) << v.offset)
-
- def __repr__(self):
- if self.direction == "H2D":
- r = ">>>>>>>>\n"
- else:
- r = "<<<<<<<<\n"
- for k in sorted(self.description.keys()):
- r += k + " : 0x%x" %getattr(self,k) + "\n"
- return r
+ def __init__(self, packet, description, direction="H2D"):
+ self.packet = packet
+ self.description = description
+ self.direction = direction
+ self.decode()
+
+ def decode(self):
+ for k, v in self.description.items():
+ setattr(self, k, get_field_data(v, self.packet))
+
+ def encode(self):
+ for k, v in self.description.items():
+ self.packet[v.dword] |= (getattr(self, k) << v.offset)
+
+ def __repr__(self):
+ if self.direction == "H2D":
+ r = ">>>>>>>>\n"
+ else:
+ r = "<<<<<<<<\n"
+ for k in sorted(self.description.keys()):
+ r += k + " : 0x%x" %getattr(self,k) + "\n"
+ return r
class FIS_REG_H2D(FIS):
- def __init__(self, packet=[0]*fis_reg_h2d_cmd_len):
- FIS.__init__(self, packet, fis_reg_h2d_layout)
- self.type = fis_types["REG_H2D"]
- self.direction = "H2D"
+ def __init__(self, packet=[0]*fis_reg_h2d_cmd_len):
+ FIS.__init__(self, packet, fis_reg_h2d_layout)
+ self.type = fis_types["REG_H2D"]
+ self.direction = "H2D"
- def __repr__(self):
- r = "FIS_REG_H2D\n"
- r += FIS.__repr__(self)
- return r
+ def __repr__(self):
+ r = "FIS_REG_H2D\n"
+ r += FIS.__repr__(self)
+ return r
class FIS_REG_D2H(FIS):
- def __init__(self, packet=[0]*fis_reg_d2h_cmd_len):
- FIS.__init__(self, packet, fis_reg_d2h_layout)
- self.type = fis_types["REG_D2H"]
- self.direction = "D2H"
+ def __init__(self, packet=[0]*fis_reg_d2h_cmd_len):
+ FIS.__init__(self, packet, fis_reg_d2h_layout)
+ self.type = fis_types["REG_D2H"]
+ self.direction = "D2H"
- def __repr__(self):
- r = "FIS_REG_D2H\n"
- r += FIS.__repr__(self)
- return r
+ def __repr__(self):
+ r = "FIS_REG_D2H\n"
+ r += FIS.__repr__(self)
+ return r
class FIS_DMA_ACTIVATE_D2H(FIS):
- def __init__(self, packet=[0]*fis_dma_activate_d2h_cmd_len):
- FIS.__init__(self, packet, fis_dma_activate_d2h_layout)
- self.type = fis_types["DMA_ACTIVATE_D2H"]
- self.direction = "D2H"
+ def __init__(self, packet=[0]*fis_dma_activate_d2h_cmd_len):
+ FIS.__init__(self, packet, fis_dma_activate_d2h_layout)
+ self.type = fis_types["DMA_ACTIVATE_D2H"]
+ self.direction = "D2H"
- def __repr__(self):
- r = "FIS_DMA_ACTIVATE_D2H\n"
- r += FIS.__repr__(self)
- return r
+ def __repr__(self):
+ r = "FIS_DMA_ACTIVATE_D2H\n"
+ r += FIS.__repr__(self)
+ return r
class FIS_DATA(FIS):
- def __init__(self, packet=[0], direction="H2D"):
- FIS.__init__(self, packet, fis_data_layout, direction)
- self.type = fis_types["DATA"]
+ def __init__(self, packet=[0], direction="H2D"):
+ FIS.__init__(self, packet, fis_data_layout, direction)
+ self.type = fis_types["DATA"]
- def __repr__(self):
- r = "FIS_DATA\n"
- r += FIS.__repr__(self)
- for data in self.packet[1:]:
- r += "%08x\n" %data
- return r
+ def __repr__(self):
+ r = "FIS_DATA\n"
+ r += FIS.__repr__(self)
+ for data in self.packet[1:]:
+ r += "%08x\n" %data
+ return r
class FIS_UNKNOWN(FIS):
- def __init__(self, packet=[0], direction="H2D"):
- FIS.__init__(self, packet, {}, direction)
-
- def __repr__(self):
- r = "UNKNOWN\n"
- if self.direction == "H2D":
- r += ">>>>>>>>\n"
- else:
- r += "<<<<<<<<\n"
- for dword in self.packet:
- r += "%08x\n" %dword
- return r
+ def __init__(self, packet=[0], direction="H2D"):
+ FIS.__init__(self, packet, {}, direction)
+
+ def __repr__(self):
+ r = "UNKNOWN\n"
+ if self.direction == "H2D":
+ r += ">>>>>>>>\n"
+ else:
+ r += "<<<<<<<<\n"
+ for dword in self.packet:
+ r += "%08x\n" %dword
+ return r
class TransportLayer(Module):
- def __init__(self, link, debug=False, loopback=False):
- self.link = link
- self.debug = debug
- self.loopback = loopback
- self.link.set_transport_callback(self.callback)
-
- def set_command_callback(self, callback):
- self.command_callback = callback
-
- def send(self, fis):
- fis.encode()
- packet = LinkTXPacket(fis.packet)
- self.link.tx_packets.append(packet)
- if self.debug and not self.loopback:
- print_transport(fis)
-
- def callback(self, packet):
- fis_type = packet[0] & 0xff
- if fis_type == fis_types["REG_H2D"]:
- fis = FIS_REG_H2D(packet)
- elif fis_type == fis_types["REG_D2H"]:
- fis = FIS_REG_D2H(packet)
- elif fis_type == fis_types["DMA_ACTIVATE_D2H"]:
- fis = FIS_DMA_ACTIVATE_D2H(packet)
- elif fis_type == fis_types["DATA"]:
- fis = FIS_DATA(packet, direction="H2D")
- else:
- fis = FIS_UNKNOWN(packet, direction="H2D")
- if self.debug:
- print_transport(fis)
- if self.loopback:
- self.send(fis)
- else:
- self.command_callback(fis)
+ def __init__(self, link, debug=False, loopback=False):
+ self.link = link
+ self.debug = debug
+ self.loopback = loopback
+ self.link.set_transport_callback(self.callback)
+
+ def set_command_callback(self, callback):
+ self.command_callback = callback
+
+ def send(self, fis):
+ fis.encode()
+ packet = LinkTXPacket(fis.packet)
+ self.link.tx_packets.append(packet)
+ if self.debug and not self.loopback:
+ print_transport(fis)
+
+ def callback(self, packet):
+ fis_type = packet[0] & 0xff
+ if fis_type == fis_types["REG_H2D"]:
+ fis = FIS_REG_H2D(packet)
+ elif fis_type == fis_types["REG_D2H"]:
+ fis = FIS_REG_D2H(packet)
+ elif fis_type == fis_types["DMA_ACTIVATE_D2H"]:
+ fis = FIS_DMA_ACTIVATE_D2H(packet)
+ elif fis_type == fis_types["DATA"]:
+ fis = FIS_DATA(packet, direction="H2D")
+ else:
+ fis = FIS_UNKNOWN(packet, direction="H2D")
+ if self.debug:
+ print_transport(fis)
+ if self.loopback:
+ self.send(fis)
+ else:
+ self.command_callback(fis)
# Command Layer model
class CommandLayer(Module):
- def __init__(self, transport):
- self.transport = transport
- self.transport.set_command_callback(self.callback)
+ def __init__(self, transport):
+ self.transport = transport
+ self.transport.set_command_callback(self.callback)
- self.hdd = None
+ self.hdd = None
- def set_hdd(self, hdd):
- self.hdd = hdd
+ def set_hdd(self, hdd):
+ self.hdd = hdd
- def callback(self, fis):
- resp = None
- if isinstance(fis, FIS_REG_H2D):
- if fis.command == regs["WRITE_DMA_EXT"]:
- resp = self.hdd.write_dma_callback(fis)
- elif fis.command == regs["READ_DMA_EXT"]:
- resp = self.hdd.read_dma_callback(fis)
- elif isinstance(fis, FIS_DATA):
- resp = self.hdd.data_callback(fis)
+ def callback(self, fis):
+ resp = None
+ if isinstance(fis, FIS_REG_H2D):
+ if fis.command == regs["WRITE_DMA_EXT"]:
+ resp = self.hdd.write_dma_callback(fis)
+ elif fis.command == regs["READ_DMA_EXT"]:
+ resp = self.hdd.read_dma_callback(fis)
+ elif isinstance(fis, FIS_DATA):
+ resp = self.hdd.data_callback(fis)
- if resp is not None:
- for packet in resp:
- self.transport.send(packet)
+ if resp is not None:
+ for packet in resp:
+ self.transport.send(packet)
# HDD model
def print_hdd(s):
- print_with_prefix(s, "[HDD]: ")
+ print_with_prefix(s, "[HDD]: ")
class HDDMemRegion:
- def __init__(self, base, count, sector_size):
- self.base = base
- self.count = count
- self.data = [0]*(count*sector_size//4)
+ def __init__(self, base, count, sector_size):
+ self.base = base
+ self.count = count
+ self.data = [0]*(count*sector_size//4)
class HDD(Module):
- def __init__(self,
- link_debug=False, link_random_level=0,
- transport_debug=False, transport_loopback=False,
- hdd_debug=False,
- ):
- ###
- self.submodules.phy = PHYLayer()
- self.submodules.link = LinkLayer(self.phy, link_debug, link_random_level)
- self.submodules.transport = TransportLayer(self.link, transport_debug, transport_loopback)
- self.submodules.command = CommandLayer(self.transport)
-
- self.command.set_hdd(self)
-
- self.debug = hdd_debug
- self.mem = None
- self.wr_sector = 0
- self.wr_end_sector = 0
- self.rd_sector = 0
- self.rx_end_sector = 0
-
- def malloc(self, sector, count):
- if self.debug:
- s = "Allocating {n} sectors: {s} to {e}".format(n=count, s=sector, e=sector+count)
- s += " ({} KB)".format(count*logical_sector_size//1024)
- print_hdd(s)
- self.mem = HDDMemRegion(sector, count, logical_sector_size)
-
- def write(self, sector, data):
- n = math.ceil(dwords2sectors(len(data)))
- if self.debug:
- if n == 1:
- s = "{}".format(sector)
- else:
- s = "{s} to {e}".format(s=sector, e=sector+n-1)
- print_hdd("Writing sector " + s)
- for i in range(len(data)):
- offset = sectors2dwords(sector)
- self.mem.data[offset+i] = data[i]
-
- def read(self, sector, count):
- if self.debug:
- if count == 1:
- s = "{}".format(sector)
- else:
- s = "{s} to {e}".format(s=sector, e=sector+count-1)
- print_hdd("Reading sector " + s)
- data = []
- for i in range(sectors2dwords(count)):
- data.append(self.mem.data[sectors2dwords(sector)+i])
- return data
-
- def write_dma_callback(self, fis):
- self.wr_sector = fis.lba_lsb + (fis.lba_msb << 32)
- self.wr_end_sector = self.wr_sector + fis.count
- return [FIS_DMA_ACTIVATE_D2H()]
-
- def read_dma_callback(self, fis):
- self.rd_sector = fis.lba_lsb + (fis.lba_msb << 32)
- self.rd_end_sector = self.rd_sector + fis.count
- packets = []
- while self.rd_sector != self.rd_end_sector:
- count = min(self.rd_end_sector-self.rd_sector, (fis_max_dwords*4)//logical_sector_size)
- packet = self.read(self.rd_sector, count)
- packet.insert(0, 0)
- packets.append(FIS_DATA(packet, direction="D2H"))
- self.rd_sector += count
- packets.append(FIS_REG_D2H())
- return packets
-
- def data_callback(self, fis):
- self.write(self.wr_sector, fis.packet[1:])
- self.wr_sector += dwords2sectors(len(fis.packet[1:]))
- if self.wr_sector == self.wr_end_sector:
- return [FIS_REG_D2H()]
- else:
- return [FIS_DMA_ACTIVATE_D2H()]
+ def __init__(self,
+ link_debug=False, link_random_level=0,
+ transport_debug=False, transport_loopback=False,
+ hdd_debug=False,
+ ):
+ ###
+ self.submodules.phy = PHYLayer()
+ self.submodules.link = LinkLayer(self.phy, link_debug, link_random_level)
+ self.submodules.transport = TransportLayer(self.link, transport_debug, transport_loopback)
+ self.submodules.command = CommandLayer(self.transport)
+
+ self.command.set_hdd(self)
+
+ self.debug = hdd_debug
+ self.mem = None
+ self.wr_sector = 0
+ self.wr_end_sector = 0
+ self.rd_sector = 0
+ self.rx_end_sector = 0
+
+ def malloc(self, sector, count):
+ if self.debug:
+ s = "Allocating {n} sectors: {s} to {e}".format(n=count, s=sector, e=sector+count)
+ s += " ({} KB)".format(count*logical_sector_size//1024)
+ print_hdd(s)
+ self.mem = HDDMemRegion(sector, count, logical_sector_size)
+
+ def write(self, sector, data):
+ n = math.ceil(dwords2sectors(len(data)))
+ if self.debug:
+ if n == 1:
+ s = "{}".format(sector)
+ else:
+ s = "{s} to {e}".format(s=sector, e=sector+n-1)
+ print_hdd("Writing sector " + s)
+ for i in range(len(data)):
+ offset = sectors2dwords(sector)
+ self.mem.data[offset+i] = data[i]
+
+ def read(self, sector, count):
+ if self.debug:
+ if count == 1:
+ s = "{}".format(sector)
+ else:
+ s = "{s} to {e}".format(s=sector, e=sector+count-1)
+ print_hdd("Reading sector " + s)
+ data = []
+ for i in range(sectors2dwords(count)):
+ data.append(self.mem.data[sectors2dwords(sector)+i])
+ return data
+
+ def write_dma_callback(self, fis):
+ self.wr_sector = fis.lba_lsb + (fis.lba_msb << 32)
+ self.wr_end_sector = self.wr_sector + fis.count
+ return [FIS_DMA_ACTIVATE_D2H()]
+
+ def read_dma_callback(self, fis):
+ self.rd_sector = fis.lba_lsb + (fis.lba_msb << 32)
+ self.rd_end_sector = self.rd_sector + fis.count
+ packets = []
+ while self.rd_sector != self.rd_end_sector:
+ count = min(self.rd_end_sector-self.rd_sector, (fis_max_dwords*4)//logical_sector_size)
+ packet = self.read(self.rd_sector, count)
+ packet.insert(0, 0)
+ packets.append(FIS_DATA(packet, direction="D2H"))
+ self.rd_sector += count
+ packets.append(FIS_REG_D2H())
+ return packets
+
+ def data_callback(self, fis):
+ self.write(self.wr_sector, fis.packet[1:])
+ self.wr_sector += dwords2sectors(len(fis.packet[1:]))
+ if self.wr_sector == self.wr_end_sector:
+ return [FIS_REG_D2H()]
+ else:
+ return [FIS_DMA_ACTIVATE_D2H()]
from misoclib.mem.litesata.test.hdd import *
class LinkStreamer(PacketStreamer):
- def __init__(self):
- PacketStreamer.__init__(self, link_description(32), LinkTXPacket)
+ def __init__(self):
+ PacketStreamer.__init__(self, link_description(32), LinkTXPacket)
class LinkLogger(PacketLogger):
- def __init__(self):
- PacketLogger.__init__(self, link_description(32), LinkRXPacket)
+ def __init__(self):
+ PacketLogger.__init__(self, link_description(32), LinkRXPacket)
class TB(Module):
- def __init__(self):
- self.submodules.hdd = HDD(
- link_debug=False, link_random_level=50,
- transport_debug=False, transport_loopback=True)
- self.submodules.link = InsertReset(LiteSATALink(self.hdd.phy, buffer_depth=512))
+ def __init__(self):
+ self.submodules.hdd = HDD(
+ link_debug=False, link_random_level=50,
+ transport_debug=False, transport_loopback=True)
+ self.submodules.link = InsertReset(LiteSATALink(self.hdd.phy, buffer_depth=512))
- self.submodules.streamer = LinkStreamer()
- self.submodules.streamer_randomizer = Randomizer(link_description(32), level=50)
+ self.submodules.streamer = LinkStreamer()
+ self.submodules.streamer_randomizer = Randomizer(link_description(32), level=50)
- self.submodules.logger_randomizer = Randomizer(link_description(32), level=50)
- self.submodules.logger = LinkLogger()
+ self.submodules.logger_randomizer = Randomizer(link_description(32), level=50)
+ self.submodules.logger = LinkLogger()
- self.submodules.pipeline = Pipeline(
- self.streamer,
- self.streamer_randomizer,
- self.link,
- self.logger_randomizer,
- self.logger
- )
+ self.submodules.pipeline = Pipeline(
+ self.streamer,
+ self.streamer_randomizer,
+ self.link,
+ self.logger_randomizer,
+ self.logger
+ )
- def gen_simulation(self, selfp):
- for i in range(8):
- streamer_packet = LinkTXPacket([i for i in range(64)])
- yield from self.streamer.send(streamer_packet)
- yield from self.logger.receive()
+ def gen_simulation(self, selfp):
+ for i in range(8):
+ streamer_packet = LinkTXPacket([i for i in range(64)])
+ yield from self.streamer.send(streamer_packet)
+ yield from self.logger.receive()
- # check results
- s, l, e = check(streamer_packet, self.logger.packet)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ # check results
+ s, l, e = check(streamer_packet, self.logger.packet)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
- run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)
from misoclib.mem.litesata.test.common import *
class DataPacket(list):
- def __init__(self, data=[]):
- self.ongoing = False
- self.done = False
- for d in data:
- self.append(d)
+ def __init__(self, data=[]):
+ self.ongoing = False
+ self.done = False
+ for d in data:
+ self.append(d)
class DataStreamer(PacketStreamer):
- def __init__(self):
- PacketStreamer.__init__(self, phy_description(32), DataPacket)
+ def __init__(self):
+ PacketStreamer.__init__(self, phy_description(32), DataPacket)
- def do_simulation(self, selfp):
- PacketStreamer.do_simulation(self, selfp)
- selfp.source.charisk = 0
- # Note: for simplicity we generate charisk by detecting
- # primitives in data
- for k, v in primitives.items():
- try:
- if self.source_data == v:
- selfp.source.charisk = 0b0001
- except:
- pass
+ def do_simulation(self, selfp):
+ PacketStreamer.do_simulation(self, selfp)
+ selfp.source.charisk = 0
+ # Note: for simplicity we generate charisk by detecting
+ # primitives in data
+ for k, v in primitives.items():
+ try:
+ if self.source_data == v:
+ selfp.source.charisk = 0b0001
+ except:
+ pass
class DataLogger(PacketLogger):
- def __init__(self):
- PacketLogger.__init__(self, phy_description(32), DataPacket)
+ def __init__(self):
+ PacketLogger.__init__(self, phy_description(32), DataPacket)
class TRX(Module):
- def __init__(self):
- self.sink = Sink(phy_description(32))
- self.source = Source(phy_description(32))
- self.comb += Record.connect(self.sink, self.source)
+ def __init__(self):
+ self.sink = Sink(phy_description(32))
+ self.source = Source(phy_description(32))
+ self.comb += Record.connect(self.sink, self.source)
class CTRL(Module):
- def __init__(self):
- self.sink = Sink(phy_description(32))
- self.source = Source(phy_description(32))
- self.ready = Signal(reset=1)
+ def __init__(self):
+ self.sink = Sink(phy_description(32))
+ self.source = Source(phy_description(32))
+ self.ready = Signal(reset=1)
class TB(Module):
- def __init__(self):
- # use sys_clk for each clock_domain
- self.clock_domains.cd_sata_rx = ClockDomain()
- self.clock_domains.cd_sata_tx = ClockDomain()
- self.comb += [
- self.cd_sata_rx.clk.eq(ClockSignal()),
- self.cd_sata_rx.rst.eq(ResetSignal()),
- self.cd_sata_tx.clk.eq(ClockSignal()),
- self.cd_sata_tx.rst.eq(ResetSignal()),
- ]
+ def __init__(self):
+ # use sys_clk for each clock_domain
+ self.clock_domains.cd_sata_rx = ClockDomain()
+ self.clock_domains.cd_sata_tx = ClockDomain()
+ self.comb += [
+ self.cd_sata_rx.clk.eq(ClockSignal()),
+ self.cd_sata_rx.rst.eq(ResetSignal()),
+ self.cd_sata_tx.clk.eq(ClockSignal()),
+ self.cd_sata_tx.rst.eq(ResetSignal()),
+ ]
- self.submodules.streamer = DataStreamer()
- self.submodules.streamer_randomizer = Randomizer(phy_description(32), level=10)
- self.submodules.trx = TRX()
- self.submodules.ctrl = CTRL()
- self.submodules.datapath = LiteSATAPHYDatapath(self.trx, self.ctrl)
- self.submodules.logger_randomizer = Randomizer(phy_description(32), level=10)
- self.submodules.logger = DataLogger()
+ self.submodules.streamer = DataStreamer()
+ self.submodules.streamer_randomizer = Randomizer(phy_description(32), level=10)
+ self.submodules.trx = TRX()
+ self.submodules.ctrl = CTRL()
+ self.submodules.datapath = LiteSATAPHYDatapath(self.trx, self.ctrl)
+ self.submodules.logger_randomizer = Randomizer(phy_description(32), level=10)
+ self.submodules.logger = DataLogger()
- self.submodules.pipeline = Pipeline(
- self.streamer,
- self.streamer_randomizer,
- self.datapath,
- self.logger_randomizer,
- self.logger
- )
+ self.submodules.pipeline = Pipeline(
+ self.streamer,
+ self.streamer_randomizer,
+ self.datapath,
+ self.logger_randomizer,
+ self.logger
+ )
- def gen_simulation(self, selfp):
- streamer_packet = DataPacket([seed_to_data(i, False) for i in range(512)])
- yield from self.streamer.send(streamer_packet)
- yield from self.logger.receive(512)
- for d in self.logger.packet:
- r = "%08x " %d
- r +=decode_primitive(d)
- print(r)
+ def gen_simulation(self, selfp):
+ streamer_packet = DataPacket([seed_to_data(i, False) for i in range(512)])
+ yield from self.streamer.send(streamer_packet)
+ yield from self.logger.receive(512)
+ for d in self.logger.packet:
+ r = "%08x " %d
+ r +=decode_primitive(d)
+ print(r)
- # check results
- #s, l, e = check(streamer_packet, self.logger.packet)
- #print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ # check results
+ #s, l, e = check(streamer_packet, self.logger.packet)
+ #print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
- run_simulation(TB(), ncycles=4096, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(), ncycles=4096, vcd_name="my.vcd", keep_files=True)
from misoclib.mem.litesata.test.common import *
class TB(Module):
- def __init__(self, length):
- self.submodules.scrambler = InsertReset(Scrambler())
- self.length = length
-
- def get_c_values(self, length):
- stdin = "0x%08x" %length
- with subprocess.Popen("./scrambler", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
- process.stdin.write(stdin.encode("ASCII"))
- out, err = process.communicate()
- return [int(e, 16) for e in out.decode("ASCII").split("\n")[:-1]]
-
- def gen_simulation(self, selfp):
- # init CRC
- selfp.scrambler.ce = 1
- selfp.scrambler.reset = 1
- yield
- selfp.scrambler.reset = 0
-
- # log results
- yield
- sim_values = []
- for i in range(self.length):
- sim_values.append(selfp.scrambler.value)
- yield
-
- # stop
- selfp.scrambler.ce = 0
- for i in range(32):
- yield
-
- # get C code reference
- c_values = self.get_c_values(self.length)
-
- # check results
- s, l, e = check(c_values, sim_values)
- print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
+ def __init__(self, length):
+ self.submodules.scrambler = InsertReset(Scrambler())
+ self.length = length
+
+ def get_c_values(self, length):
+ stdin = "0x%08x" %length
+ with subprocess.Popen("./scrambler", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
+ process.stdin.write(stdin.encode("ASCII"))
+ out, err = process.communicate()
+ return [int(e, 16) for e in out.decode("ASCII").split("\n")[:-1]]
+
+ def gen_simulation(self, selfp):
+ # init CRC
+ selfp.scrambler.ce = 1
+ selfp.scrambler.reset = 1
+ yield
+ selfp.scrambler.reset = 0
+
+ # log results
+ yield
+ sim_values = []
+ for i in range(self.length):
+ sim_values.append(selfp.scrambler.value)
+ yield
+
+ # stop
+ selfp.scrambler.ce = 0
+ for i in range(32):
+ yield
+
+ # get C code reference
+ c_values = self.get_c_values(self.length)
+
+ # check results
+ s, l, e = check(c_values, sim_values)
+ print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
- from migen.sim.generic import run_simulation
- length = 8192
- run_simulation(TB(length), ncycles=length+100, vcd_name="my.vcd")
+ from migen.sim.generic import run_simulation
+ length = 8192
+ run_simulation(TB(length), ncycles=length+100, vcd_name="my.vcd")