From: Florent Kermarrec Date: Mon, 13 Apr 2015 12:55:26 +0000 (+0200) Subject: litesata: pep8 (replace tabs with spaces) X-Git-Tag: 24jan2021_ls180~2340 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=808e1fe8666715eda87df0fac3ef7ee3caba220a;p=litex.git litesata: pep8 (replace tabs with spaces) --- diff --git a/misoclib/mem/litesata/__init__.py b/misoclib/mem/litesata/__init__.py index dd93affd..2a9d88fb 100644 --- a/misoclib/mem/litesata/__init__.py +++ b/misoclib/mem/litesata/__init__.py @@ -6,16 +6,16 @@ from misoclib.mem.litesata.frontend import * 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) diff --git a/misoclib/mem/litesata/common.py b/misoclib/mem/litesata/common.py index 0ccb8880..82c752d9 100644 --- a/misoclib/mem/litesata/common.py +++ b/misoclib/mem/litesata/common.py @@ -14,348 +14,348 @@ from migen.actorlib.fifo import * 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) diff --git a/misoclib/mem/litesata/core/__init__.py b/misoclib/mem/litesata/core/__init__.py index 9ca40190..de31ee3c 100644 --- a/misoclib/mem/litesata/core/__init__.py +++ b/misoclib/mem/litesata/core/__init__.py @@ -4,8 +4,8 @@ from misoclib.mem.litesata.core.transport import LiteSATATransport 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 diff --git a/misoclib/mem/litesata/core/command/__init__.py b/misoclib/mem/litesata/core/command/__init__.py index d3c5d0da..180d0391 100644 --- a/misoclib/mem/litesata/core/command/__init__.py +++ b/misoclib/mem/litesata/core/command/__init__.py @@ -1,279 +1,279 @@ 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 diff --git a/misoclib/mem/litesata/core/link/__init__.py b/misoclib/mem/litesata/core/link/__init__.py index 4c96398d..b240f2ac 100644 --- a/misoclib/mem/litesata/core/link/__init__.py +++ b/misoclib/mem/litesata/core/link/__init__.py @@ -4,251 +4,251 @@ from misoclib.mem.litesata.core.link.scrambler import LiteSATAScrambler 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 diff --git a/misoclib/mem/litesata/core/link/cont.py b/misoclib/mem/litesata/core/link/cont.py index f72affce..9158cd34 100644 --- a/misoclib/mem/litesata/core/link/cont.py +++ b/misoclib/mem/litesata/core/link/cont.py @@ -2,115 +2,115 @@ from misoclib.mem.litesata.common import * 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) + ) + ] diff --git a/misoclib/mem/litesata/core/link/crc.py b/misoclib/mem/litesata/core/link/crc.py index c33e715a..27e73fac 100644 --- a/misoclib/mem/litesata/core/link/crc.py +++ b/misoclib/mem/litesata/core/link/crc.py @@ -2,270 +2,270 @@ from collections import OrderedDict 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) diff --git a/misoclib/mem/litesata/core/link/scrambler.py b/misoclib/mem/litesata/core/link/scrambler.py index e0f9e4a0..31890763 100644 --- a/misoclib/mem/litesata/core/link/scrambler.py +++ b/misoclib/mem/litesata/core/link/scrambler.py @@ -2,80 +2,80 @@ from misoclib.mem.litesata.common import * @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) + ] diff --git a/misoclib/mem/litesata/core/transport/__init__.py b/misoclib/mem/litesata/core/transport/__init__.py index b8015b81..986a627b 100644 --- a/misoclib/mem/litesata/core/transport/__init__.py +++ b/misoclib/mem/litesata/core/transport/__init__.py @@ -1,257 +1,257 @@ 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 diff --git a/misoclib/mem/litesata/example_designs/make.py b/misoclib/mem/litesata/example_designs/make.py index f4f17715..26ba660e 100755 --- a/misoclib/mem/litesata/example_designs/make.py +++ b/misoclib/mem/litesata/example_designs/make.py @@ -14,11 +14,11 @@ from misoclib.soc import cpuif 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. @@ -34,65 +34,65 @@ load-bitstream load bitstream into volatile storage. 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(""" __ _ __ _______ _________ / / (_) /____ / __/ _ /_ __/ _ | / /__/ / __/ -_)\ \/ __ |/ / / __ | @@ -107,50 +107,50 @@ System Clk: {} MHz (min: {} MHz) 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) diff --git a/misoclib/mem/litesata/example_designs/platforms/kc705.py b/misoclib/mem/litesata/example_designs/platforms/kc705.py index d287d954..cf37d0b1 100644 --- a/misoclib/mem/litesata/example_designs/platforms/kc705.py +++ b/misoclib/mem/litesata/example_designs/platforms/kc705.py @@ -2,31 +2,31 @@ from mibuild.generic_platform import * 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] diff --git a/misoclib/mem/litesata/example_designs/platforms/verilog_backend.py b/misoclib/mem/litesata/example_designs/platforms/verilog_backend.py index 8880947b..30afdd7b 100644 --- a/misoclib/mem/litesata/example_designs/platforms/verilog_backend.py +++ b/misoclib/mem/litesata/example_designs/platforms/verilog_backend.py @@ -2,22 +2,22 @@ from mibuild.generic_platform import * 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 diff --git a/misoclib/mem/litesata/example_designs/targets/bist.py b/misoclib/mem/litesata/example_designs/targets/bist.py index 038f8532..e25e34bf 100644 --- a/misoclib/mem/litesata/example_designs/targets/bist.py +++ b/misoclib/mem/litesata/example_designs/targets/bist.py @@ -15,166 +15,166 @@ from misoclib.mem.litesata.phy import LiteSATAPHY 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 diff --git a/misoclib/mem/litesata/example_designs/targets/core.py b/misoclib/mem/litesata/example_designs/targets/core.py index e92aa330..1df688d8 100644 --- a/misoclib/mem/litesata/example_designs/targets/core.py +++ b/misoclib/mem/litesata/example_designs/targets/core.py @@ -7,59 +7,59 @@ from misoclib.mem.litesata.phy import LiteSATAPHY 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 diff --git a/misoclib/mem/litesata/example_designs/test/bist.py b/misoclib/mem/litesata/example_designs/test/bist.py index 7a0a99da..8385e2d0 100644 --- a/misoclib/mem/litesata/example_designs/test/bist.py +++ b/misoclib/mem/litesata/example_designs/test/bist.py @@ -11,192 +11,192 @@ GB = 1024*MB 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() diff --git a/misoclib/mem/litesata/example_designs/test/make.py b/misoclib/mem/litesata/example_designs/test/make.py index e0c78b28..1d3f2d9d 100644 --- a/misoclib/mem/litesata/example_designs/test/make.py +++ b/misoclib/mem/litesata/example_designs/test/make.py @@ -2,33 +2,33 @@ 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) diff --git a/misoclib/mem/litesata/example_designs/test/test_la.py b/misoclib/mem/litesata/example_designs/test/test_la.py index 0fb17a76..129d1fb8 100644 --- a/misoclib/mem/litesata/example_designs/test/test_la.py +++ b/misoclib/mem/litesata/example_designs/test/test_la.py @@ -4,68 +4,68 @@ from test_bist import * 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() diff --git a/misoclib/mem/litesata/example_designs/test/test_regs.py b/misoclib/mem/litesata/example_designs/test/test_regs.py index 07ee4915..1f29e49b 100644 --- a/misoclib/mem/litesata/example_designs/test/test_regs.py +++ b/misoclib/mem/litesata/example_designs/test/test_regs.py @@ -1,9 +1,9 @@ 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() diff --git a/misoclib/mem/litesata/example_designs/test/tools.py b/misoclib/mem/litesata/example_designs/test/tools.py index 55eabc4a..1dc666f5 100644 --- a/misoclib/mem/litesata/example_designs/test/tools.py +++ b/misoclib/mem/litesata/example_designs/test/tools.py @@ -1,48 +1,48 @@ 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 diff --git a/misoclib/mem/litesata/frontend/arbiter.py b/misoclib/mem/litesata/frontend/arbiter.py index ded478b3..80806db9 100644 --- a/misoclib/mem/litesata/frontend/arbiter.py +++ b/misoclib/mem/litesata/frontend/arbiter.py @@ -4,26 +4,26 @@ from misoclib.mem.litesata.frontend.common import * 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) diff --git a/misoclib/mem/litesata/frontend/bist.py b/misoclib/mem/litesata/frontend/bist.py index 096dab73..a6315754 100644 --- a/misoclib/mem/litesata/frontend/bist.py +++ b/misoclib/mem/litesata/frontend/bist.py @@ -4,292 +4,292 @@ from misoclib.mem.litesata.core.link.scrambler import Scrambler 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 diff --git a/misoclib/mem/litesata/frontend/common.py b/misoclib/mem/litesata/frontend/common.py index de33ee0e..8d85e401 100644 --- a/misoclib/mem/litesata/frontend/common.py +++ b/misoclib/mem/litesata/frontend/common.py @@ -1,27 +1,27 @@ 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) diff --git a/misoclib/mem/litesata/frontend/crossbar.py b/misoclib/mem/litesata/frontend/crossbar.py index 2300af2c..1d2eba0f 100644 --- a/misoclib/mem/litesata/frontend/crossbar.py +++ b/misoclib/mem/litesata/frontend/crossbar.py @@ -3,25 +3,25 @@ from misoclib.mem.litesata.frontend.common import * 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 diff --git a/misoclib/mem/litesata/phy/__init__.py b/misoclib/mem/litesata/phy/__init__.py index f17a3696..1473859f 100644 --- a/misoclib/mem/litesata/phy/__init__.py +++ b/misoclib/mem/litesata/phy/__init__.py @@ -3,22 +3,22 @@ from misoclib.mem.litesata.phy.ctrl import * 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 diff --git a/misoclib/mem/litesata/phy/ctrl.py b/misoclib/mem/litesata/phy/ctrl.py index d09253f6..32c71a45 100644 --- a/misoclib/mem/litesata/phy/ctrl.py +++ b/misoclib/mem/litesata/phy/ctrl.py @@ -1,150 +1,150 @@ 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) + ) + ) + ) diff --git a/misoclib/mem/litesata/phy/datapath.py b/misoclib/mem/litesata/phy/datapath.py index 71bc4f94..b6bac849 100644 --- a/misoclib/mem/litesata/phy/datapath.py +++ b/misoclib/mem/litesata/phy/datapath.py @@ -1,163 +1,163 @@ 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) + ] diff --git a/misoclib/mem/litesata/phy/k7/crg.py b/misoclib/mem/litesata/phy/k7/crg.py index 73bbf8ab..ee08d22d 100644 --- a/misoclib/mem/litesata/phy/k7/crg.py +++ b/misoclib/mem/litesata/phy/k7/crg.py @@ -1,155 +1,155 @@ 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), + ] diff --git a/misoclib/mem/litesata/phy/k7/trx.py b/misoclib/mem/litesata/phy/k7/trx.py index fccaa20d..f1624c50 100644 --- a/misoclib/mem/litesata/phy/k7/trx.py +++ b/misoclib/mem/litesata/phy/k7/trx.py @@ -1,852 +1,852 @@ 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 + ) diff --git a/misoclib/mem/litesata/test/bist_tb.py b/misoclib/mem/litesata/test/bist_tb.py index c007bb38..6b494aee 100644 --- a/misoclib/mem/litesata/test/bist_tb.py +++ b/misoclib/mem/litesata/test/bist_tb.py @@ -6,40 +6,40 @@ from misoclib.mem.litesata.test.hdd import * 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) diff --git a/misoclib/mem/litesata/test/command_tb.py b/misoclib/mem/litesata/test/command_tb.py index 29f7d2bd..cd340cb7 100644 --- a/misoclib/mem/litesata/test/command_tb.py +++ b/misoclib/mem/litesata/test/command_tb.py @@ -5,90 +5,90 @@ from misoclib.mem.litesata.test.hdd import * 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) diff --git a/misoclib/mem/litesata/test/common.py b/misoclib/mem/litesata/test/common.py index 8a91209e..2a0a0c0b 100644 --- a/misoclib/mem/litesata/test/common.py +++ b/misoclib/mem/litesata/test/common.py @@ -5,131 +5,131 @@ from migen.sim.generic import run_simulation 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 diff --git a/misoclib/mem/litesata/test/cont_tb.py b/misoclib/mem/litesata/test/cont_tb.py index 5a71ed53..1c2f5301 100644 --- a/misoclib/mem/litesata/test/cont_tb.py +++ b/misoclib/mem/litesata/test/cont_tb.py @@ -4,92 +4,92 @@ from misoclib.mem.litesata.core.link.cont import LiteSATACONTInserter, LiteSATAC 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) diff --git a/misoclib/mem/litesata/test/crc_tb.py b/misoclib/mem/litesata/test/crc_tb.py index 2d93b0b8..7ecb66f3 100644 --- a/misoclib/mem/litesata/test/crc_tb.py +++ b/misoclib/mem/litesata/test/crc_tb.py @@ -6,54 +6,54 @@ from misoclib.mem.litesata.core.link.crc import * 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") diff --git a/misoclib/mem/litesata/test/hdd.py b/misoclib/mem/litesata/test/hdd.py index fa1eed9d..671257c7 100644 --- a/misoclib/mem/litesata/test/hdd.py +++ b/misoclib/mem/litesata/test/hdd.py @@ -5,507 +5,507 @@ from misoclib.mem.litesata.common import * 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()] diff --git a/misoclib/mem/litesata/test/link_tb.py b/misoclib/mem/litesata/test/link_tb.py index 142e14ed..e75749a5 100644 --- a/misoclib/mem/litesata/test/link_tb.py +++ b/misoclib/mem/litesata/test/link_tb.py @@ -5,44 +5,44 @@ from misoclib.mem.litesata.test.common import * 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) diff --git a/misoclib/mem/litesata/test/phy_datapath_tb.py b/misoclib/mem/litesata/test/phy_datapath_tb.py index a78cc2fd..43163bf6 100644 --- a/misoclib/mem/litesata/test/phy_datapath_tb.py +++ b/misoclib/mem/litesata/test/phy_datapath_tb.py @@ -4,85 +4,85 @@ from misoclib.mem.litesata.phy.datapath import LiteSATAPHYDatapath 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) diff --git a/misoclib/mem/litesata/test/scrambler_tb.py b/misoclib/mem/litesata/test/scrambler_tb.py index 20c4045c..298e5e3e 100644 --- a/misoclib/mem/litesata/test/scrambler_tb.py +++ b/misoclib/mem/litesata/test/scrambler_tb.py @@ -6,44 +6,44 @@ from misoclib.mem.litesata.core.link.scrambler import * 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")