mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
transport: code SATATransportLayerTX (untested)
This commit is contained in:
parent
e4c0b4a11f
commit
1aab9a449e
3 changed files with 163 additions and 17 deletions
|
@ -48,13 +48,48 @@ def link_layout(dw):
|
|||
]
|
||||
return EndpointDescription(layout, packetized=True)
|
||||
|
||||
def transport_tx_layout(dw):
|
||||
def transport_cmd_tx_layout():
|
||||
layout = [
|
||||
("d", dw)
|
||||
("type", 8),
|
||||
("pm_port", 4),
|
||||
("a", 1),
|
||||
("c", 1),
|
||||
("d", 1),
|
||||
("i", 1),
|
||||
("command", 8),
|
||||
("features", 16),
|
||||
("lba", 48),
|
||||
("device", 8),
|
||||
("count", 16),
|
||||
("icc", 8),
|
||||
("control", 8),
|
||||
("dma_buffer_id", 64),
|
||||
("dma_buffer_offset", 32),
|
||||
("dma_transfer_count", 32),
|
||||
]
|
||||
return EndpointDescription(layout, packetized=True)
|
||||
|
||||
def transport_rx_layout(dw):
|
||||
def transport_cmd_rx_layout():
|
||||
layout = [
|
||||
("type", 8),
|
||||
("pm_port", 4),
|
||||
("a", 1),
|
||||
("d", 1),
|
||||
("i", 1),
|
||||
("status", 8),
|
||||
("error", 8),
|
||||
("lba", 48),
|
||||
("device", 8),
|
||||
("count", 16),
|
||||
("e_status", 8),
|
||||
("transfer_count", 16),
|
||||
("dma_buffer_id", 64),
|
||||
("dma_buffer_offset", 32),
|
||||
("dma_transfer_count", 32)
|
||||
]
|
||||
return EndpointDescription(layout, packetized=True)
|
||||
|
||||
def transport_data_layout(dw):
|
||||
layout = [
|
||||
("d", dw)
|
||||
]
|
||||
|
|
|
@ -1,15 +1,125 @@
|
|||
from lib.sata.std import *
|
||||
from lib.sata.transport.std import *
|
||||
|
||||
def _encode_cmd(obj, layout, signal):
|
||||
r = []
|
||||
for k, v in sorted(layout.items()):
|
||||
start = v.word*32 + v.offset
|
||||
end = start + v.width
|
||||
r.append(signal[start:end].eq(getattr(obj, k)))
|
||||
return r
|
||||
|
||||
class SATATransportLayerTX(Module):
|
||||
def __init__(self):
|
||||
self.sink = Sink(transport_layout(32))
|
||||
def __init__(self, link):
|
||||
self.cmd = cmd = Sink(transport_cmd_tx_layout())
|
||||
self.data = data = Sink(transport_data_layout(32))
|
||||
|
||||
###
|
||||
|
||||
cmd_ndwords = max(fis_reg_h2d_cmd_len, fis_dma_setup_cmd_len, fis_data_cmd_len)
|
||||
encoded_cmd = Signal(cmd_ndwords*32)
|
||||
|
||||
cnt = Signal(max=cmd_ndwords+1)
|
||||
clr_cnt = Signal()
|
||||
inc_cnt = Signal()
|
||||
|
||||
cmd_len = Signal(flen(cnt))
|
||||
cmd_with_data = Signal()
|
||||
|
||||
cmd_send = Signal()
|
||||
data_send = Signal()
|
||||
cmd_done = Signal()
|
||||
data_done = Signal()
|
||||
|
||||
fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += fsm
|
||||
|
||||
# FSM
|
||||
fsm.act("IDLE",
|
||||
clr_cnt.eq(1),
|
||||
If(cmd.stb,
|
||||
If(cmd.type == fis_types["REG_H2D"],
|
||||
NextState("SEND_REG_H2D_CMD")
|
||||
).Elif(cmd.type == "DMA_SETUP_CMD",
|
||||
NextState("SEND_DMA_SETUP")
|
||||
).Elif(cmd.type == "DATA_CMD"),
|
||||
NextState("SEND_DATA")
|
||||
).Else(
|
||||
# XXX: Generate error to command layer?
|
||||
cmd.ack.eq(1)
|
||||
)
|
||||
)
|
||||
)
|
||||
fsm.act("SEND_REG_H2D_CMD",
|
||||
_encode_cmd(self.cmd, fis_reg_h2d_layout, encoded_cmd),
|
||||
cmd_len.eq(fis_reg_h2d_cmd_len),
|
||||
cmd_send.eq(1)
|
||||
If(ack_cmd,
|
||||
NextState.eq("ACK")
|
||||
)
|
||||
)
|
||||
fsm.act("SEND_DMA_SETUP_CMD",
|
||||
_encode_cmd(self.cmd, fis_dma_setup_layout, encoded_cmd),
|
||||
cmd_len.eq(fis_dma_setup_cmd_len),
|
||||
cmd_send.eq(1),
|
||||
If(ack_cmd,
|
||||
NextState.eq("ACK")
|
||||
)
|
||||
)
|
||||
fsm.act("SEND_DATA_CMD",
|
||||
_encode_cmd(self.cmd, fis_data_layout, encoded_cmd),
|
||||
cmd_len.eq(fis_send_data_cmd_len),
|
||||
cmd_width_data.eq(1),
|
||||
cmd_send.eq(1),
|
||||
If(cmd_done,
|
||||
NextState.eq("SEND_DATA")
|
||||
)
|
||||
)
|
||||
fsm.act("SEND_DATA",
|
||||
data_send.eq(1),
|
||||
If(data_done,
|
||||
NextState.eq("ACK")
|
||||
)
|
||||
)
|
||||
fsm.act("ACK",
|
||||
cmd.ack.eq(1),
|
||||
NextState.eq("IDLE")
|
||||
)
|
||||
|
||||
cmd_cases = {}
|
||||
for i in range(cmd_ndwords):
|
||||
cmd_cases[i] = [link.sink.d.eq(encoded_cmd[32*i:32*(i+1)])]
|
||||
|
||||
self.comb += \
|
||||
If(cmd_send,
|
||||
link.sink.stb.eq(1),
|
||||
link.sink.sop.eq(cnt==0),
|
||||
link.sink.eop.eq((cnt==cmd_len) & ~cmd_with_data),
|
||||
Case(cnt, cmd_cases),
|
||||
inc_cnt.eq(link.sink.ack),
|
||||
cmd_done.eq(cnt==cmd_len)
|
||||
).Elif(data_send,
|
||||
link.sink.stb.eq(data.stb),
|
||||
link.sink.sop.eq(0),
|
||||
link.sink.eop.eq(data.eop),
|
||||
link.sink.d.eq(data.d),
|
||||
data.ack.eq(link.sink.ack),
|
||||
data_done.eq(data.eop & data.ack)
|
||||
)
|
||||
|
||||
self.sync += \
|
||||
If(clr_cnt,
|
||||
cnt.eq(0)
|
||||
).Elif(inc_cnt,
|
||||
cnt.eq(cnt+1)
|
||||
)
|
||||
|
||||
class SATATransportLayerRX(Module):
|
||||
def __init__(self):
|
||||
self.sink = Sink(transport_layout(32))
|
||||
def __init__(self, link):
|
||||
self.cmd = Source(transport_cmd_rx_layout())
|
||||
self.data = Source(transport_data_layout(32))
|
||||
|
||||
class SATATransportLayer(Module):
|
||||
def __init__(self):
|
||||
self.submodules.tx = SATATransportLayerTX()
|
||||
self.submodules.rx = SATATransportLayerRX()
|
||||
def __init__(self, link):
|
||||
self.submodules.tx = SATATransportLayerTX(link)
|
||||
self.submodules.rx = SATATransportLayerRX(link)
|
||||
|
|
|
@ -13,7 +13,7 @@ class FISField():
|
|||
self.offset = offset
|
||||
self.width = width
|
||||
|
||||
fis_reg_h2d_len = 5
|
||||
fis_reg_h2d_cmd_len = 5
|
||||
fis_reg_h2d_layout = {
|
||||
"type": FISField(0, 0, 8),
|
||||
"pm_port": FISField(0, 8, 4),
|
||||
|
@ -22,7 +22,7 @@ fis_reg_h2d_layout = {
|
|||
"features_lsb": FISField(0, 24, 8),
|
||||
|
||||
"lba_lsb": FISField(1, 0, 24),
|
||||
"device": FISField(1, 24, 0),
|
||||
"device": FISField(1, 24, 8),
|
||||
|
||||
"lba_msb": FISField(2, 0, 24),
|
||||
"features_msb": FISField(2, 24, 8),
|
||||
|
@ -32,7 +32,7 @@ fis_reg_h2d_layout = {
|
|||
"control": FISField(3, 24, 8)
|
||||
}
|
||||
|
||||
fis_reg_d2h_len = 5
|
||||
fis_reg_d2h_cmd_len = 5
|
||||
fis_reg_d2h_layout = {
|
||||
"type": FISField(0, 0, 8),
|
||||
"pm_port": FISField(0, 8, 4),
|
||||
|
@ -41,20 +41,20 @@ fis_reg_d2h_layout = {
|
|||
"error": FISField(0, 24, 8),
|
||||
|
||||
"lba_lsb": FISField(1, 0, 24),
|
||||
"device": FISField(1, 24, 0),
|
||||
"device": FISField(1, 24, 8),
|
||||
|
||||
"lba_msb": FISField(2, 0, 24),
|
||||
|
||||
"count": FISField(3, 0, 16)
|
||||
}
|
||||
|
||||
fis_dma_activate_d2h_len = 1
|
||||
fis_dma_activate_d2h_cmd_len = 1
|
||||
fis_dma_activate_d2h_layout = {
|
||||
"type": FISField(0, 0, 8),
|
||||
"pm_port": FISField(0, 8, 4)
|
||||
}
|
||||
|
||||
fis_dma_setup_len = 7
|
||||
fis_dma_setup_cmd_len = 7
|
||||
fis_dma_setup_layout = {
|
||||
"type": FISField(0, 0, 8),
|
||||
"pm_port": FISField(0, 8, 4),
|
||||
|
@ -71,6 +71,7 @@ fis_dma_setup_layout = {
|
|||
"dma_transfer_count": FISField(4, 0, 32)
|
||||
}
|
||||
|
||||
fis_data_cmd_len = 1
|
||||
fis_data_layout = {
|
||||
"type": FISField(0, 0, 8)
|
||||
}
|
||||
|
@ -85,7 +86,7 @@ fis_pio_setup_d2h_layout = {
|
|||
"error": FISField(0, 24, 8),
|
||||
|
||||
"lba_lsb": FISField(1, 0, 24),
|
||||
"device": FISField(1, 24, 0),
|
||||
"device": FISField(1, 24, 8),
|
||||
|
||||
"lba_msb": FISField(2, 0, 24),
|
||||
|
||||
|
|
Loading…
Reference in a new issue