add support of identify device command
This commit is contained in:
parent
c227576f3d
commit
6f2c7a236c
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
||||||
MSCDIR = ../misoc
|
MSCDIR = ../misoc
|
||||||
CURDIR = ../sata-controller
|
CURDIR = ../lite-sata
|
||||||
PYTHON = python3
|
PYTHON = python3
|
||||||
TOOLCHAIN = vivado
|
TOOLCHAIN = vivado
|
||||||
PLATFORM = kc705
|
PLATFORM = kc705
|
||||||
|
|
9
README
9
README
|
@ -1,4 +1,3 @@
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
__ _ __ _______ _________
|
__ _ __ _______ _________
|
||||||
/ / (_) /____ / __/ _ /_ __/ _ |
|
/ / (_) /____ / __/ _ /_ __/ _ |
|
||||||
/ /__/ / __/ -_)\ \/ __ |/ / / __ |
|
/ /__/ / __/ -_)\ \/ __ |/ / / __ |
|
||||||
|
@ -7,8 +6,7 @@
|
||||||
Copyright 2014-2015 / Florent Kermarrec / florent@enjoy-digital.fr
|
Copyright 2014-2015 / Florent Kermarrec / florent@enjoy-digital.fr
|
||||||
|
|
||||||
A lite open-source SATA1/2/3 controller
|
A lite open-source SATA1/2/3 controller
|
||||||
developed in partnership with M-Labs Ltd / HKU
|
developed in partnership with M-Labs Ltd & HKU
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[> Getting started
|
[> Getting started
|
||||||
------------------
|
------------------
|
||||||
|
@ -46,12 +44,15 @@
|
||||||
- link_tb
|
- link_tb
|
||||||
- command_tb
|
- command_tb
|
||||||
- bist_tb
|
- bist_tb
|
||||||
hdd.py is a HDD model with implementing all SATA layers.
|
hdd.py is a HDD model implementing all SATA layers.
|
||||||
To run a simulation, move to the simulation directory and run:
|
To run a simulation, move to the simulation directory and run:
|
||||||
make simulation_name
|
make simulation_name
|
||||||
|
|
||||||
[> Tests :
|
[> Tests :
|
||||||
A synthetisable BIST is provided. It can be controled with ./test/bist.py
|
A synthetisable BIST is provided. It can be controled with ./test/bist.py
|
||||||
|
Using Miscope and the provided example ./test/test_link.py you are able to
|
||||||
|
visualize every event of the design and even inject your data in the HDD
|
||||||
|
model!
|
||||||
|
|
||||||
[> Contact
|
[> Contact
|
||||||
E-mail: florent@enjoy-digital.fr
|
E-mail: florent@enjoy-digital.fr
|
||||||
|
|
|
@ -137,7 +137,7 @@ class SATABISTChecker(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
class SATABISTControl(Module, AutoCSR):
|
class SATABISTUnitControl(Module, AutoCSR):
|
||||||
def __init__(self, bist_unit):
|
def __init__(self, bist_unit):
|
||||||
self._start = CSR()
|
self._start = CSR()
|
||||||
self._sector = CSRStorage(48)
|
self._sector = CSRStorage(48)
|
||||||
|
@ -164,13 +164,82 @@ class SATABISTControl(Module, AutoCSR):
|
||||||
self.cycles_counter.reset.eq(bist_unit.start),
|
self.cycles_counter.reset.eq(bist_unit.start),
|
||||||
self.cycles_counter.ce.eq(~bist_unit.done)
|
self.cycles_counter.ce.eq(~bist_unit.done)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class SATABISTIdentify(Module):
|
||||||
|
def __init__(self, sata_master_port):
|
||||||
|
self.start = Signal()
|
||||||
|
self.done = Signal()
|
||||||
|
|
||||||
|
self.fifo = fifo = SyncFIFO([("data", 32)], 512, buffered=True)
|
||||||
|
self.source = self.fifo.source
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
source, sink = sata_master_port.source, sata_master_port.sink
|
||||||
|
|
||||||
|
self.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
|
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 SATABISTIdentifyControl(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)
|
||||||
|
|
||||||
|
###
|
||||||
|
self.bist_identify = 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)
|
||||||
|
]
|
||||||
|
|
||||||
class SATABIST(Module, AutoCSR):
|
class SATABIST(Module, AutoCSR):
|
||||||
def __init__(self, sata_master_ports, with_control=False):
|
def __init__(self, sata_master_ports, with_control=False):
|
||||||
generator = SATABISTGenerator(sata_master_ports[0])
|
generator = SATABISTGenerator(sata_master_ports[0])
|
||||||
checker = SATABISTChecker(sata_master_ports[1])
|
checker = SATABISTChecker(sata_master_ports[1])
|
||||||
|
identify = SATABISTIdentify(sata_master_ports[2])
|
||||||
if with_control:
|
if with_control:
|
||||||
self.generator = SATABISTControl(generator)
|
self.generator = SATABISTUnitControl(generator)
|
||||||
self.checker = SATABISTControl(checker)
|
self.checker = SATABISTUnitControl(checker)
|
||||||
|
self.identify = SATABISTIdentifyControl(identify)
|
||||||
else:
|
else:
|
||||||
self.generator = generator
|
self.generator = generator
|
||||||
self.checker = checker
|
self.checker = checker
|
||||||
|
self.identify = identify
|
||||||
|
|
|
@ -3,6 +3,7 @@ from lib.sata.common import *
|
||||||
tx_to_rx = [
|
tx_to_rx = [
|
||||||
("write", 1),
|
("write", 1),
|
||||||
("read", 1),
|
("read", 1),
|
||||||
|
("identify", 1),
|
||||||
("count", 16)
|
("count", 16)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -39,6 +40,8 @@ class SATACommandTX(Module):
|
||||||
NextState("SEND_WRITE_DMA_CMD")
|
NextState("SEND_WRITE_DMA_CMD")
|
||||||
).Elif(sink.read,
|
).Elif(sink.read,
|
||||||
NextState("SEND_READ_DMA_CMD")
|
NextState("SEND_READ_DMA_CMD")
|
||||||
|
).Elif(sink.identify,
|
||||||
|
NextState("SEND_IDENTIFY_CMD")
|
||||||
).Else(
|
).Else(
|
||||||
sink.ack.eq(1)
|
sink.ack.eq(1)
|
||||||
)
|
)
|
||||||
|
@ -92,11 +95,24 @@ class SATACommandTX(Module):
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
fsm.act("SEND_IDENTIFY_CMD",
|
||||||
|
transport.sink.stb.eq(sink.stb),
|
||||||
|
transport.sink.sop.eq(1),
|
||||||
|
transport.sink.eop.eq(1),
|
||||||
|
transport.sink.type.eq(fis_types["REG_H2D"]),
|
||||||
|
transport.sink.c.eq(1),
|
||||||
|
transport.sink.command.eq(regs["IDENTIFY_DEVICE"]),
|
||||||
|
sink.ack.eq(transport.sink.ack),
|
||||||
|
If(sink.stb & sink.ack,
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
If(sink.stb,
|
If(sink.stb,
|
||||||
to_rx.write.eq(sink.write),
|
to_rx.write.eq(sink.write),
|
||||||
to_rx.read.eq(sink.read),
|
to_rx.read.eq(sink.read),
|
||||||
|
to_rx.identify.eq(sink.identify),
|
||||||
to_rx.count.eq(sink.count)
|
to_rx.count.eq(sink.count)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
@ -117,6 +133,7 @@ class SATACommandRX(Module):
|
||||||
def test_type(name):
|
def test_type(name):
|
||||||
return transport.source.type == fis_types[name]
|
return transport.source.type == fis_types[name]
|
||||||
|
|
||||||
|
identify = Signal()
|
||||||
dma_activate = Signal()
|
dma_activate = Signal()
|
||||||
read_ndwords = Signal(max=sectors2dwords(2**16))
|
read_ndwords = Signal(max=sectors2dwords(2**16))
|
||||||
self.dwords_counter = dwords_counter = Counter(max=sectors2dwords(2**16))
|
self.dwords_counter = dwords_counter = Counter(max=sectors2dwords(2**16))
|
||||||
|
@ -135,9 +152,15 @@ class SATACommandRX(Module):
|
||||||
If(from_tx.write,
|
If(from_tx.write,
|
||||||
NextState("WAIT_WRITE_ACTIVATE_OR_REG_D2H")
|
NextState("WAIT_WRITE_ACTIVATE_OR_REG_D2H")
|
||||||
).Elif(from_tx.read,
|
).Elif(from_tx.read,
|
||||||
NextState("WAIT_READ_DATA_OR_REG_D2H")
|
NextState("WAIT_READ_DATA_OR_REG_D2H"),
|
||||||
|
).Elif(from_tx.identify,
|
||||||
|
NextState("WAIT_PIO_SETUP_D2H"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
self.sync += \
|
||||||
|
If(fsm.ongoing("IDLE"),
|
||||||
|
identify.eq(from_tx.identify)
|
||||||
|
)
|
||||||
fsm.act("WAIT_WRITE_ACTIVATE_OR_REG_D2H",
|
fsm.act("WAIT_WRITE_ACTIVATE_OR_REG_D2H",
|
||||||
transport.source.ack.eq(1),
|
transport.source.ack.eq(1),
|
||||||
If(transport.source.stb,
|
If(transport.source.stb,
|
||||||
|
@ -171,6 +194,23 @@ class SATACommandRX(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
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),
|
||||||
|
# XXX : Check error/ status
|
||||||
|
If(transport.source.stb & transport.source.eop,
|
||||||
|
NextState("WAIT_READ_DATA_OR_REG_D2H")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
data_buffer.sink.sop.eq(transport.source.sop),
|
data_buffer.sink.sop.eq(transport.source.sop),
|
||||||
data_buffer.sink.eop.eq(transport.source.eop),
|
data_buffer.sink.eop.eq(transport.source.eop),
|
||||||
|
@ -182,7 +222,7 @@ class SATACommandRX(Module):
|
||||||
If(data_buffer.sink.stb & data_buffer.sink.ack,
|
If(data_buffer.sink.stb & data_buffer.sink.ack,
|
||||||
self.dwords_counter.ce.eq(~read_done),
|
self.dwords_counter.ce.eq(~read_done),
|
||||||
If(data_buffer.sink.eop,
|
If(data_buffer.sink.eop,
|
||||||
If(read_done,
|
If(read_done & ~identify,
|
||||||
NextState("WAIT_READ_DATA_OR_REG_D2H")
|
NextState("WAIT_READ_DATA_OR_REG_D2H")
|
||||||
).Else(
|
).Else(
|
||||||
NextState("PRESENT_READ_RESPONSE")
|
NextState("PRESENT_READ_RESPONSE")
|
||||||
|
@ -199,15 +239,16 @@ class SATACommandRX(Module):
|
||||||
)
|
)
|
||||||
fsm.act("PRESENT_READ_RESPONSE",
|
fsm.act("PRESENT_READ_RESPONSE",
|
||||||
cmd_buffer.sink.stb.eq(1),
|
cmd_buffer.sink.stb.eq(1),
|
||||||
cmd_buffer.sink.read.eq(1),
|
cmd_buffer.sink.read.eq(~identify),
|
||||||
cmd_buffer.sink.last.eq(read_done),
|
cmd_buffer.sink.identify.eq(identify),
|
||||||
|
cmd_buffer.sink.last.eq(read_done | identify),
|
||||||
cmd_buffer.sink.success.eq(~read_error),
|
cmd_buffer.sink.success.eq(~read_error),
|
||||||
cmd_buffer.sink.failed.eq(read_error),
|
cmd_buffer.sink.failed.eq(read_error),
|
||||||
If(cmd_buffer.sink.stb & cmd_buffer.sink.ack,
|
If(cmd_buffer.sink.stb & cmd_buffer.sink.ack,
|
||||||
If(cmd_buffer.sink.failed,
|
If(cmd_buffer.sink.failed,
|
||||||
data_buffer.reset.eq(1)
|
data_buffer.reset.eq(1)
|
||||||
),
|
),
|
||||||
If(read_done,
|
If(read_done | identify,
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
).Else(
|
).Else(
|
||||||
NextState("WAIT_READ_DATA_OR_REG_D2H")
|
NextState("WAIT_READ_DATA_OR_REG_D2H")
|
||||||
|
@ -218,7 +259,7 @@ class SATACommandRX(Module):
|
||||||
self.out_fsm = out_fsm = FSM(reset_state="IDLE")
|
self.out_fsm = out_fsm = FSM(reset_state="IDLE")
|
||||||
out_fsm.act("IDLE",
|
out_fsm.act("IDLE",
|
||||||
If(cmd_buffer.source.stb,
|
If(cmd_buffer.source.stb,
|
||||||
If(cmd_buffer.source.read & cmd_buffer.source.success,
|
If((cmd_buffer.source.read | cmd_buffer.source.identify) & cmd_buffer.source.success,
|
||||||
NextState("PRESENT_RESPONSE_WITH_DATA"),
|
NextState("PRESENT_RESPONSE_WITH_DATA"),
|
||||||
).Else(
|
).Else(
|
||||||
NextState("PRESENT_RESPONSE_WITHOUT_DATA"),
|
NextState("PRESENT_RESPONSE_WITHOUT_DATA"),
|
||||||
|
@ -229,9 +270,10 @@ class SATACommandRX(Module):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
source.write.eq(cmd_buffer.source.write),
|
source.write.eq(cmd_buffer.source.write),
|
||||||
source.read.eq(cmd_buffer.source.read),
|
source.read.eq(cmd_buffer.source.read),
|
||||||
|
source.identify.eq(cmd_buffer.source.identify),
|
||||||
source.last.eq(cmd_buffer.source.last),
|
source.last.eq(cmd_buffer.source.last),
|
||||||
source.success.eq(cmd_buffer.source.success),
|
source.success.eq(cmd_buffer.source.success),
|
||||||
source.failed.eq(cmd_buffer.source.success),
|
source.failed.eq(cmd_buffer.source.failed),
|
||||||
source.data.eq(data_buffer.source.data)
|
source.data.eq(data_buffer.source.data)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ fis_types = {
|
||||||
"REG_H2D": 0x27,
|
"REG_H2D": 0x27,
|
||||||
"REG_D2H": 0x34,
|
"REG_D2H": 0x34,
|
||||||
"DMA_ACTIVATE_D2H": 0x39,
|
"DMA_ACTIVATE_D2H": 0x39,
|
||||||
|
"PIO_SETUP_D2H": 0x5F,
|
||||||
"DATA": 0x46
|
"DATA": 0x46
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +111,24 @@ fis_dma_activate_d2h_layout = {
|
||||||
"pm_port": FISField(0, 8, 4)
|
"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),
|
||||||
|
|
||||||
|
"lba_lsb": FISField(1, 0, 24),
|
||||||
|
|
||||||
|
"lba_msb": FISField(2, 0, 24),
|
||||||
|
|
||||||
|
"count": FISField(3, 0, 16),
|
||||||
|
|
||||||
|
"transfer_count": FISField(4, 0, 16),
|
||||||
|
}
|
||||||
|
|
||||||
fis_data_cmd_len = 1
|
fis_data_cmd_len = 1
|
||||||
fis_data_layout = {
|
fis_data_layout = {
|
||||||
"type": FISField(0, 0, 8)
|
"type": FISField(0, 0, 8)
|
||||||
|
@ -135,12 +154,15 @@ def transport_rx_description(dw):
|
||||||
layout = [
|
layout = [
|
||||||
("type", 8),
|
("type", 8),
|
||||||
("pm_port", 4),
|
("pm_port", 4),
|
||||||
|
("r", 1),
|
||||||
|
("d", 1),
|
||||||
("i", 1),
|
("i", 1),
|
||||||
("status", 8),
|
("status", 8),
|
||||||
("error", 8),
|
("error", 8),
|
||||||
("lba", 48),
|
("lba", 48),
|
||||||
("device", 8),
|
("device", 8),
|
||||||
("count", 16),
|
("count", 16),
|
||||||
|
("transfer_count", 16),
|
||||||
("data", dw),
|
("data", dw),
|
||||||
("error", 1)
|
("error", 1)
|
||||||
]
|
]
|
||||||
|
@ -149,13 +171,15 @@ def transport_rx_description(dw):
|
||||||
# Command Layer
|
# Command Layer
|
||||||
regs = {
|
regs = {
|
||||||
"WRITE_DMA_EXT" : 0x35,
|
"WRITE_DMA_EXT" : 0x35,
|
||||||
"READ_DMA_EXT" : 0x25
|
"READ_DMA_EXT" : 0x25,
|
||||||
|
"IDENTIFY_DEVICE" : 0xEC
|
||||||
}
|
}
|
||||||
|
|
||||||
def command_tx_description(dw):
|
def command_tx_description(dw):
|
||||||
layout = [
|
layout = [
|
||||||
("write", 1),
|
("write", 1),
|
||||||
("read", 1),
|
("read", 1),
|
||||||
|
("identify", 1),
|
||||||
("sector", 48),
|
("sector", 48),
|
||||||
("count", 16),
|
("count", 16),
|
||||||
("data", dw)
|
("data", dw)
|
||||||
|
@ -166,6 +190,7 @@ def command_rx_description(dw):
|
||||||
layout = [
|
layout = [
|
||||||
("write", 1),
|
("write", 1),
|
||||||
("read", 1),
|
("read", 1),
|
||||||
|
("identify", 1),
|
||||||
("last", 1),
|
("last", 1),
|
||||||
("success", 1),
|
("success", 1),
|
||||||
("failed", 1),
|
("failed", 1),
|
||||||
|
@ -177,9 +202,10 @@ def command_rx_cmd_description(dw):
|
||||||
layout = [
|
layout = [
|
||||||
("write", 1),
|
("write", 1),
|
||||||
("read", 1),
|
("read", 1),
|
||||||
|
("identify", 1),
|
||||||
("last", 1),
|
("last", 1),
|
||||||
("success", 1),
|
("success", 1),
|
||||||
("failed", 1),
|
("failed", 1)
|
||||||
]
|
]
|
||||||
return EndpointDescription(layout, packetized=False)
|
return EndpointDescription(layout, packetized=False)
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,8 @@ class SATATransportRX(Module):
|
||||||
NextState("RECEIVE_REG_D2H_CMD")
|
NextState("RECEIVE_REG_D2H_CMD")
|
||||||
).Elif(test_type("DMA_ACTIVATE_D2H"),
|
).Elif(test_type("DMA_ACTIVATE_D2H"),
|
||||||
NextState("RECEIVE_DMA_ACTIVATE_D2H_CMD")
|
NextState("RECEIVE_DMA_ACTIVATE_D2H_CMD")
|
||||||
|
).Elif(test_type("PIO_SETUP_D2H"),
|
||||||
|
NextState("RECEIVE_PIO_SETUP_D2H_CMD")
|
||||||
).Elif(test_type("DATA"),
|
).Elif(test_type("DATA"),
|
||||||
NextState("RECEIVE_DATA_CMD"),
|
NextState("RECEIVE_DATA_CMD"),
|
||||||
).Else(
|
).Else(
|
||||||
|
@ -186,6 +188,23 @@ class SATATransportRX(Module):
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
fsm.act("RECEIVE_PIO_SETUP_D2H_CMD",
|
||||||
|
cmd_len.eq(fis_pio_setup_d2h_cmd_len-1),
|
||||||
|
cmd_receive.eq(1),
|
||||||
|
link.source.ack.eq(1),
|
||||||
|
If(cmd_done,
|
||||||
|
NextState("PRESENT_PIO_SETUP_D2H_CMD")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("PRESENT_PIO_SETUP_D2H_CMD",
|
||||||
|
source.stb.eq(1),
|
||||||
|
source.sop.eq(1),
|
||||||
|
source.eop.eq(1),
|
||||||
|
_decode_cmd(encoded_cmd, fis_pio_setup_d2h_layout, source),
|
||||||
|
If(source.stb & source.ack,
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
fsm.act("RECEIVE_DATA_CMD",
|
fsm.act("RECEIVE_DATA_CMD",
|
||||||
cmd_len.eq(fis_data_cmd_len-1),
|
cmd_len.eq(fis_data_cmd_len-1),
|
||||||
cmd_receive.eq(1),
|
cmd_receive.eq(1),
|
||||||
|
|
|
@ -14,7 +14,7 @@ from misoclib import identifier
|
||||||
from lib.sata.common import *
|
from lib.sata.common import *
|
||||||
from lib.sata.phy import SATAPHY
|
from lib.sata.phy import SATAPHY
|
||||||
from lib.sata import SATACON
|
from lib.sata import SATACON
|
||||||
from lib.sata.bist import SATABIST, SATABISTControl
|
from lib.sata.bist import SATABIST
|
||||||
|
|
||||||
class _CRG(Module):
|
class _CRG(Module):
|
||||||
def __init__(self, platform):
|
def __init__(self, platform):
|
||||||
|
@ -149,7 +149,7 @@ class BISTSoC(GenSoC, AutoCSR):
|
||||||
self.sata_con = SATACON(self.sata_phy)
|
self.sata_con = SATACON(self.sata_phy)
|
||||||
|
|
||||||
# SATA BIST generator and checker
|
# SATA BIST generator and checker
|
||||||
self.sata_bist = SATABIST(self.sata_con.crossbar.get_ports(2), with_control=True)
|
self.sata_bist = SATABIST(self.sata_con.crossbar.get_ports(3), with_control=True)
|
||||||
|
|
||||||
# Status Leds
|
# Status Leds
|
||||||
self.leds = BISTLeds(platform, self.sata_phy)
|
self.leds = BISTLeds(platform, self.sata_phy)
|
||||||
|
@ -162,6 +162,13 @@ class BISTSoCDevel(BISTSoC, AutoCSR):
|
||||||
def __init__(self, platform, export_mila=False):
|
def __init__(self, platform, export_mila=False):
|
||||||
BISTSoC.__init__(self, platform, export_mila)
|
BISTSoC.__init__(self, platform, export_mila)
|
||||||
|
|
||||||
|
self.sata_con_link_rx_fsm_state = Signal(4)
|
||||||
|
self.sata_con_link_tx_fsm_state = Signal(4)
|
||||||
|
self.sata_con_transport_rx_fsm_state = Signal(4)
|
||||||
|
self.sata_con_transport_tx_fsm_state = Signal(4)
|
||||||
|
self.sata_con_command_rx_fsm_state = Signal(4)
|
||||||
|
self.sata_con_command_tx_fsm_state = Signal(4)
|
||||||
|
|
||||||
debug = (
|
debug = (
|
||||||
self.sata_phy.ctrl.ready,
|
self.sata_phy.ctrl.ready,
|
||||||
|
|
||||||
|
@ -179,6 +186,7 @@ class BISTSoCDevel(BISTSoC, AutoCSR):
|
||||||
self.sata_con.command.sink.ack,
|
self.sata_con.command.sink.ack,
|
||||||
self.sata_con.command.sink.write,
|
self.sata_con.command.sink.write,
|
||||||
self.sata_con.command.sink.read,
|
self.sata_con.command.sink.read,
|
||||||
|
self.sata_con.command.sink.identify,
|
||||||
|
|
||||||
self.sata_con.command.source.stb,
|
self.sata_con.command.source.stb,
|
||||||
self.sata_con.command.source.sop,
|
self.sata_con.command.source.sop,
|
||||||
|
@ -186,9 +194,17 @@ class BISTSoCDevel(BISTSoC, AutoCSR):
|
||||||
self.sata_con.command.source.ack,
|
self.sata_con.command.source.ack,
|
||||||
self.sata_con.command.source.write,
|
self.sata_con.command.source.write,
|
||||||
self.sata_con.command.source.read,
|
self.sata_con.command.source.read,
|
||||||
|
self.sata_con.command.source.identify,
|
||||||
self.sata_con.command.source.success,
|
self.sata_con.command.source.success,
|
||||||
self.sata_con.command.source.failed,
|
self.sata_con.command.source.failed,
|
||||||
self.sata_con.command.source.data
|
self.sata_con.command.source.data,
|
||||||
|
|
||||||
|
self.sata_con_link_rx_fsm_state,
|
||||||
|
self.sata_con_link_tx_fsm_state,
|
||||||
|
self.sata_con_transport_rx_fsm_state,
|
||||||
|
self.sata_con_transport_tx_fsm_state,
|
||||||
|
self.sata_con_command_rx_fsm_state,
|
||||||
|
self.sata_con_command_tx_fsm_state,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.mila = MiLa(depth=2048, dat=Cat(*debug))
|
self.mila = MiLa(depth=2048, dat=Cat(*debug))
|
||||||
|
@ -196,6 +212,16 @@ class BISTSoCDevel(BISTSoC, AutoCSR):
|
||||||
if export_mila:
|
if export_mila:
|
||||||
mila_filename = os.path.join(platform.soc_ext_path, "test", "mila.csv")
|
mila_filename = os.path.join(platform.soc_ext_path, "test", "mila.csv")
|
||||||
self.mila.export(self, debug, mila_filename)
|
self.mila.export(self, debug, mila_filename)
|
||||||
|
def do_finalize(self):
|
||||||
|
BISTSoC.do_finalize(self)
|
||||||
|
self.comb += [
|
||||||
|
self.sata_con_link_rx_fsm_state.eq(self.sata_con.link.rx.fsm.state),
|
||||||
|
self.sata_con_link_tx_fsm_state.eq(self.sata_con.link.tx.fsm.state),
|
||||||
|
self.sata_con_transport_rx_fsm_state.eq(self.sata_con.transport.rx.fsm.state),
|
||||||
|
self.sata_con_transport_tx_fsm_state.eq(self.sata_con.transport.tx.fsm.state),
|
||||||
|
self.sata_con_command_rx_fsm_state.eq(self.sata_con.command.rx.fsm.state),
|
||||||
|
self.sata_con_command_tx_fsm_state.eq(self.sata_con.command.tx.fsm.state)
|
||||||
|
]
|
||||||
|
|
||||||
#default_subtarget = BISTSoC
|
default_subtarget = BISTSoC
|
||||||
default_subtarget = BISTSoCDevel
|
#default_subtarget = BISTSoCDevel
|
||||||
|
|
47
test/bist.py
47
test/bist.py
|
@ -4,7 +4,7 @@ from config import *
|
||||||
|
|
||||||
logical_sector_size = 512
|
logical_sector_size = 512
|
||||||
|
|
||||||
class SATABISTDriver:
|
class SATABISTUnitDriver:
|
||||||
def __init__(self, regs, name):
|
def __init__(self, regs, name):
|
||||||
self.regs = regs
|
self.regs = regs
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -25,13 +25,46 @@ class SATABISTDriver:
|
||||||
errors = self.errors.read()
|
errors = self.errors.read()
|
||||||
return (speed, errors)
|
return (speed, errors)
|
||||||
|
|
||||||
class SATABISTGeneratorDriver(SATABISTDriver):
|
class SATABISTGeneratorDriver(SATABISTUnitDriver):
|
||||||
def __init__(self, regs, name):
|
def __init__(self, regs, name):
|
||||||
SATABISTDriver.__init__(self, regs, name + "_generator")
|
SATABISTUnitDriver.__init__(self, regs, name + "_generator")
|
||||||
|
|
||||||
class SATABISTCheckerDriver(SATABISTDriver):
|
class SATABISTCheckerDriver(SATABISTUnitDriver):
|
||||||
def __init__(self, regs, name):
|
def __init__(self, regs, name):
|
||||||
SATABISTDriver.__init__(self, regs, name + "_checker")
|
SATABISTUnitDriver.__init__(self, regs, name + "_checker")
|
||||||
|
|
||||||
|
class SATABISTIdentifyDriver:
|
||||||
|
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():
|
||||||
|
self.data.append(self.source_data.read())
|
||||||
|
self.source_ack.write(1)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.read_fifo() # flush the fifo before we start
|
||||||
|
self.start.write(1)
|
||||||
|
while (self.done.read() == 0):
|
||||||
|
pass
|
||||||
|
self.read_fifo()
|
||||||
|
self.decode()
|
||||||
|
|
||||||
|
def decode(self):
|
||||||
|
self.serial_number = ""
|
||||||
|
for i, dword in enumerate(self.data[10:20]):
|
||||||
|
s = dword.to_bytes(4, byteorder='big').decode("utf-8")
|
||||||
|
self.serial_number += s[2:] + s[:2]
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
r = "Serial Number: " + self.serial_number
|
||||||
|
# XXX: enhance decode function
|
||||||
|
return r
|
||||||
|
|
||||||
KB = 1024
|
KB = 1024
|
||||||
MB = 1024*KB
|
MB = 1024*KB
|
||||||
|
@ -55,9 +88,13 @@ if __name__ == "__main__":
|
||||||
args = _get_args()
|
args = _get_args()
|
||||||
wb.open()
|
wb.open()
|
||||||
###
|
###
|
||||||
|
identify = SATABISTIdentifyDriver(wb.regs, "sata_bist")
|
||||||
generator = SATABISTGeneratorDriver(wb.regs, "sata_bist")
|
generator = SATABISTGeneratorDriver(wb.regs, "sata_bist")
|
||||||
checker = SATABISTCheckerDriver(wb.regs, "sata_bist")
|
checker = SATABISTCheckerDriver(wb.regs, "sata_bist")
|
||||||
|
|
||||||
|
identify.run()
|
||||||
|
print(identify)
|
||||||
|
|
||||||
sector = 0
|
sector = 0
|
||||||
count = int(args.transfer_size)*MB//logical_sector_size
|
count = int(args.transfer_size)*MB//logical_sector_size
|
||||||
length = int(args.total_length)*MB
|
length = int(args.total_length)*MB
|
||||||
|
|
|
@ -5,6 +5,7 @@ from bist import *
|
||||||
from miscope.host.drivers import MiLaDriver
|
from miscope.host.drivers import MiLaDriver
|
||||||
|
|
||||||
mila = MiLaDriver(wb.regs, "mila")
|
mila = MiLaDriver(wb.regs, "mila")
|
||||||
|
identify = SATABISTIdentifyDriver(wb.regs, "sata_bist")
|
||||||
generator = SATABISTGeneratorDriver(wb.regs, "sata_bist")
|
generator = SATABISTGeneratorDriver(wb.regs, "sata_bist")
|
||||||
checker = SATABISTCheckerDriver(wb.regs, "sata_bist")
|
checker = SATABISTCheckerDriver(wb.regs, "sata_bist")
|
||||||
wb.open()
|
wb.open()
|
||||||
|
@ -32,6 +33,13 @@ conditions["rd_data"] = {
|
||||||
"bistsocdevel_sata_con_command_source_source_stb" : 1,
|
"bistsocdevel_sata_con_command_source_source_stb" : 1,
|
||||||
"bistsocdevel_sata_con_command_source_source_payload_read" : 1,
|
"bistsocdevel_sata_con_command_source_source_payload_read" : 1,
|
||||||
}
|
}
|
||||||
|
conditions["id_cmd"] = {
|
||||||
|
"bistsocdevel_sata_con_command_sink_stb" : 1,
|
||||||
|
"bistsocdevel_sata_con_command_sink_payload_identify" : 1,
|
||||||
|
}
|
||||||
|
conditions["id_pio_setup"] = {
|
||||||
|
"bistsocdevel_sata_phy_source_source_payload_data" : primitives["X_RDY"],
|
||||||
|
}
|
||||||
|
|
||||||
mila.prog_term(port=0, cond=conditions[sys.argv[1]])
|
mila.prog_term(port=0, cond=conditions[sys.argv[1]])
|
||||||
mila.prog_sum("term")
|
mila.prog_sum("term")
|
||||||
|
@ -39,6 +47,7 @@ mila.prog_sum("term")
|
||||||
# Trigger / wait / receive
|
# Trigger / wait / receive
|
||||||
mila.trigger(offset=512, length=2000)
|
mila.trigger(offset=512, length=2000)
|
||||||
|
|
||||||
|
identify.run()
|
||||||
generator.run(0, 2, 0)
|
generator.run(0, 2, 0)
|
||||||
checker.run(0, 2, 0)
|
checker.run(0, 2, 0)
|
||||||
mila.wait_done()
|
mila.wait_done()
|
||||||
|
|
Loading…
Reference in New Issue