mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
transport: add transport_tb skeleton and fix compilation
This commit is contained in:
parent
ed9d9e1375
commit
7ea46ed7a6
5 changed files with 86 additions and 38 deletions
|
@ -17,6 +17,9 @@ scrambler_tb:
|
||||||
link_tb:
|
link_tb:
|
||||||
$(CMD) link_tb.py
|
$(CMD) link_tb.py
|
||||||
|
|
||||||
|
transport_tb:
|
||||||
|
$(CMD) transport_tb.py
|
||||||
|
|
||||||
all: crc_tb scrambler_tb
|
all: crc_tb scrambler_tb
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -285,7 +285,7 @@ class FIS:
|
||||||
return r
|
return r
|
||||||
|
|
||||||
class FIS_REG_H2D(FIS):
|
class FIS_REG_H2D(FIS):
|
||||||
def __init__(self, packet=[0]*fis_reg_h2d_len):
|
def __init__(self, packet=[0]*fis_reg_h2d_cmd_len):
|
||||||
FIS.__init__(self, packet,fis_reg_h2d_layout)
|
FIS.__init__(self, packet,fis_reg_h2d_layout)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -294,7 +294,7 @@ class FIS_REG_H2D(FIS):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
class FIS_REG_D2H(FIS):
|
class FIS_REG_D2H(FIS):
|
||||||
def __init__(self, packet=[0]*fis_reg_d2h_len):
|
def __init__(self, packet=[0]*fis_reg_d2h_cmd_len):
|
||||||
FIS.__init__(self, packet,fis_reg_d2h_layout)
|
FIS.__init__(self, packet,fis_reg_d2h_layout)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -303,7 +303,7 @@ class FIS_REG_D2H(FIS):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
class FIS_DMA_ACTIVATE_D2H(FIS):
|
class FIS_DMA_ACTIVATE_D2H(FIS):
|
||||||
def __init__(self, packet=[0]*fis_dma_activate_d2h_len):
|
def __init__(self, packet=[0]*fis_dma_activate_d2h_cmd_len):
|
||||||
FIS.__init__(self, packet,fis_dma_activate_d2h_layout)
|
FIS.__init__(self, packet,fis_dma_activate_d2h_layout)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -312,7 +312,7 @@ class FIS_DMA_ACTIVATE_D2H(FIS):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
class FIS_DMA_SETUP(FIS):
|
class FIS_DMA_SETUP(FIS):
|
||||||
def __init__(self, packet=[0]*fis_dma_setup_len):
|
def __init__(self, packet=[0]*fis_dma_setup_cmd_len):
|
||||||
FIS.__init__(self, packet,fis_dma_setup_layout)
|
FIS.__init__(self, packet,fis_dma_setup_layout)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -330,7 +330,7 @@ class FIS_DATA(FIS):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
class FIS_PIO_SETUP_D2H(FIS):
|
class FIS_PIO_SETUP_D2H(FIS):
|
||||||
def __init__(self, packet=[0]*fis_pio_setup_d2h_len):
|
def __init__(self, packet=[0]*fis_pio_setup_d2h_cmd_len):
|
||||||
FIS.__init__(self, packet,fis_pio_setup_d2h_layout)
|
FIS.__init__(self, packet,fis_pio_setup_d2h_layout)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
28
lib/sata/test/transport_tb.py
Normal file
28
lib/sata/test/transport_tb.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.genlib.record import *
|
||||||
|
from migen.sim.generic import run_simulation
|
||||||
|
|
||||||
|
from lib.sata.std import *
|
||||||
|
from lib.sata.link import SATALinkLayer
|
||||||
|
from lib.sata.transport import SATATransportLayer
|
||||||
|
|
||||||
|
from lib.sata.test.bfm import *
|
||||||
|
from lib.sata.test.common import *
|
||||||
|
|
||||||
|
class TB(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.submodules.bfm = BFM(phy_debug=False,
|
||||||
|
link_random_level=50, transport_debug=True, transport_loopback=True)
|
||||||
|
self.submodules.link = SATALinkLayer(self.bfm.phy)
|
||||||
|
self.submodules.transport = SATATransportLayer(self.link)
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
self.transport.tx.cmd.stb.eq(1),
|
||||||
|
self.transport.tx.cmd.type.eq(fis_types["REG_H2D"]),
|
||||||
|
self.transport.tx.cmd.lba.eq(0x12345678)
|
||||||
|
]
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_simulation(TB(), ncycles=256, vcd_name="my.vcd", keep_files=True)
|
|
@ -1,12 +1,21 @@
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.genlib.fsm import FSM, NextState
|
||||||
|
|
||||||
from lib.sata.std import *
|
from lib.sata.std import *
|
||||||
from lib.sata.transport.std import *
|
from lib.sata.transport.std import *
|
||||||
|
|
||||||
def _encode_cmd(obj, layout, signal):
|
def _encode_cmd(obj, layout, signal):
|
||||||
r = []
|
r = []
|
||||||
for k, v in sorted(layout.items()):
|
for k, v in sorted(layout.items()):
|
||||||
start = v.word*32 + v.offset
|
start = v.dword*32 + v.offset
|
||||||
end = start + v.width
|
end = start + v.width
|
||||||
r.append(signal[start:end].eq(getattr(obj, k)))
|
if "_lsb" in k:
|
||||||
|
item = getattr(obj, k.replace("_lsb", ""))[:v.width]
|
||||||
|
elif "_msb" in k:
|
||||||
|
item = getattr(obj, k.replace("_msb", ""))[v.width:2*v.width]
|
||||||
|
else:
|
||||||
|
item = getattr(obj, k)
|
||||||
|
r.append(signal[start:end].eq(item))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
class SATATransportLayerTX(Module):
|
class SATATransportLayerTX(Module):
|
||||||
|
@ -31,19 +40,21 @@ class SATATransportLayerTX(Module):
|
||||||
cmd_done = Signal()
|
cmd_done = Signal()
|
||||||
data_done = Signal()
|
data_done = Signal()
|
||||||
|
|
||||||
|
def test_type(name):
|
||||||
|
return cmd.type == fis_types[name]
|
||||||
|
|
||||||
fsm = FSM(reset_state="IDLE")
|
fsm = FSM(reset_state="IDLE")
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
|
|
||||||
# FSM
|
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
clr_cnt.eq(1),
|
clr_cnt.eq(1),
|
||||||
If(cmd.stb,
|
If(cmd.stb,
|
||||||
If(cmd.type == fis_types["REG_H2D"],
|
If(test_type("REG_H2D"),
|
||||||
NextState("SEND_REG_H2D_CMD")
|
NextState("SEND_REG_H2D_CMD")
|
||||||
).Elif(cmd.type == "DMA_SETUP_CMD",
|
).Elif(test_type("DMA_SETUP"),
|
||||||
NextState("SEND_DMA_SETUP")
|
NextState("SEND_DMA_SETUP_CMD")
|
||||||
).Elif(cmd.type == "DATA_CMD"),
|
).Elif(test_type("DATA"),
|
||||||
NextState("SEND_DATA")
|
NextState("SEND_DATA_CMD")
|
||||||
).Else(
|
).Else(
|
||||||
# XXX: Generate error to command layer?
|
# XXX: Generate error to command layer?
|
||||||
cmd.ack.eq(1)
|
cmd.ack.eq(1)
|
||||||
|
@ -53,37 +64,37 @@ class SATATransportLayerTX(Module):
|
||||||
fsm.act("SEND_REG_H2D_CMD",
|
fsm.act("SEND_REG_H2D_CMD",
|
||||||
_encode_cmd(self.cmd, fis_reg_h2d_layout, encoded_cmd),
|
_encode_cmd(self.cmd, fis_reg_h2d_layout, encoded_cmd),
|
||||||
cmd_len.eq(fis_reg_h2d_cmd_len),
|
cmd_len.eq(fis_reg_h2d_cmd_len),
|
||||||
cmd_send.eq(1)
|
cmd_send.eq(1),
|
||||||
If(ack_cmd,
|
If(cmd_done,
|
||||||
NextState.eq("ACK")
|
NextState("ACK")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("SEND_DMA_SETUP_CMD",
|
fsm.act("SEND_DMA_SETUP_CMD",
|
||||||
_encode_cmd(self.cmd, fis_dma_setup_layout, encoded_cmd),
|
_encode_cmd(self.cmd, fis_dma_setup_layout, encoded_cmd),
|
||||||
cmd_len.eq(fis_dma_setup_cmd_len),
|
cmd_len.eq(fis_dma_setup_cmd_len),
|
||||||
cmd_send.eq(1),
|
cmd_send.eq(1),
|
||||||
If(ack_cmd,
|
If(cmd_done,
|
||||||
NextState.eq("ACK")
|
NextState("ACK")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("SEND_DATA_CMD",
|
fsm.act("SEND_DATA_CMD",
|
||||||
_encode_cmd(self.cmd, fis_data_layout, encoded_cmd),
|
_encode_cmd(self.cmd, fis_data_layout, encoded_cmd),
|
||||||
cmd_len.eq(fis_send_data_cmd_len),
|
cmd_len.eq(fis_data_cmd_len),
|
||||||
cmd_width_data.eq(1),
|
cmd_with_data.eq(1),
|
||||||
cmd_send.eq(1),
|
cmd_send.eq(1),
|
||||||
If(cmd_done,
|
If(cmd_done,
|
||||||
NextState.eq("SEND_DATA")
|
NextState("SEND_DATA")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("SEND_DATA",
|
fsm.act("SEND_DATA",
|
||||||
data_send.eq(1),
|
data_send.eq(1),
|
||||||
If(data_done,
|
If(data_done,
|
||||||
NextState.eq("ACK")
|
NextState("ACK")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("ACK",
|
fsm.act("ACK",
|
||||||
cmd.ack.eq(1),
|
cmd.ack.eq(1),
|
||||||
NextState.eq("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
|
|
||||||
cmd_cases = {}
|
cmd_cases = {}
|
||||||
|
@ -117,20 +128,26 @@ class SATATransportLayerTX(Module):
|
||||||
def _decode_cmd(signal, layout, obj):
|
def _decode_cmd(signal, layout, obj):
|
||||||
r = []
|
r = []
|
||||||
for k, v in sorted(layout.items()):
|
for k, v in sorted(layout.items()):
|
||||||
start = v.word*32+v.offset
|
start = v.dword*32+v.offset
|
||||||
end = start+v.width
|
end = start+v.width
|
||||||
r.append(getattr(obj, k).eq(signal[start:end]))
|
if "_lsb" in k:
|
||||||
|
item = getattr(obj, k.replace("_lsb", ""))[:v.width]
|
||||||
|
elif "_msb" in k:
|
||||||
|
item = getattr(obj, k.replace("_msb", ""))[v.width:2*v.width]
|
||||||
|
else:
|
||||||
|
item = getattr(obj, k)
|
||||||
|
r.append(item.eq(signal[start:end]))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
class SATATransportLayerRX(Module):
|
class SATATransportLayerRX(Module):
|
||||||
def __init__(self, link):
|
def __init__(self, link):
|
||||||
self.cmd = Source(transport_cmd_rx_layout())
|
self.cmd = cmd = Source(transport_cmd_rx_layout())
|
||||||
self.data = Source(transport_data_layout(32))
|
self.data = data = Source(transport_data_layout(32))
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
cmd_ndwords = max(fis_reg_d2h_cmd_len, fis_dma_activate_d2h_cmd_len, fis_dma_setup_cmd_len,
|
cmd_ndwords = max(fis_reg_d2h_cmd_len, fis_dma_activate_d2h_cmd_len, fis_dma_setup_cmd_len,
|
||||||
fis_data_cmd_len, fis_pio_setup_d2h_len)
|
fis_data_cmd_len, fis_pio_setup_d2h_cmd_len)
|
||||||
encoded_cmd = Signal(cmd_ndwords*32)
|
encoded_cmd = Signal(cmd_ndwords*32)
|
||||||
|
|
||||||
cnt = Signal(max=cmd_ndwords+1)
|
cnt = Signal(max=cmd_ndwords+1)
|
||||||
|
@ -144,15 +161,15 @@ class SATATransportLayerRX(Module):
|
||||||
cmd_done = Signal()
|
cmd_done = Signal()
|
||||||
data_done = Signal()
|
data_done = Signal()
|
||||||
|
|
||||||
fsm = FSM(reset_state="IDLE")
|
|
||||||
self.submodules += fsm
|
|
||||||
|
|
||||||
def test_type(name):
|
def test_type(name):
|
||||||
return link.source.d[:8] == fis_types[name]
|
return link.source.d[:8] == fis_types[name]
|
||||||
|
|
||||||
|
fsm = FSM(reset_state="IDLE")
|
||||||
|
self.submodules += fsm
|
||||||
|
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
If(link.source.stb & link.source.sop,
|
If(link.source.stb & link.source.sop,
|
||||||
If(test_type("REG_D2H"]),
|
If(test_type("REG_D2H"),
|
||||||
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")
|
||||||
|
@ -225,7 +242,7 @@ class SATATransportLayerRX(Module):
|
||||||
NextState("PRESENT_DATA_CMD")
|
NextState("PRESENT_DATA_CMD")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("DECODE_DATA",
|
fsm.act("PRESENT_DATA_CMD",
|
||||||
cmd.stb.eq(1),
|
cmd.stb.eq(1),
|
||||||
_decode_cmd(encoded_cmd, fis_data_layout ,cmd),
|
_decode_cmd(encoded_cmd, fis_data_layout ,cmd),
|
||||||
If(cmd.ack,
|
If(cmd.ack,
|
||||||
|
@ -233,7 +250,7 @@ class SATATransportLayerRX(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("RECEIVE_PIO_SETUP_D2H_CMD",
|
fsm.act("RECEIVE_PIO_SETUP_D2H_CMD",
|
||||||
cmd_len.eq(fis_pio_setup_d2h_len),
|
cmd_len.eq(fis_pio_setup_d2h_cmd_len),
|
||||||
cmd_receive.eq(1),
|
cmd_receive.eq(1),
|
||||||
If(cmd_done,
|
If(cmd_done,
|
||||||
NextState("PRESENT_PIO_SETUP_D2H_CMD")
|
NextState("PRESENT_PIO_SETUP_D2H_CMD")
|
||||||
|
@ -249,7 +266,7 @@ class SATATransportLayerRX(Module):
|
||||||
|
|
||||||
cmd_cases = {}
|
cmd_cases = {}
|
||||||
for i in range(cmd_ndwords):
|
for i in range(cmd_ndwords):
|
||||||
cmd_cases[i] = [encoded_cmd[32*i:32*(i+1)]).eq(link.source.d)]
|
cmd_cases[i] = [encoded_cmd[32*i:32*(i+1)].eq(link.source.d)]
|
||||||
|
|
||||||
self.sync += \
|
self.sync += \
|
||||||
If(cmd_receive,
|
If(cmd_receive,
|
||||||
|
|
|
@ -62,9 +62,9 @@ fis_dma_setup_layout = {
|
||||||
"i": FISField(0, 14, 1),
|
"i": FISField(0, 14, 1),
|
||||||
"a": FISField(0, 15, 1),
|
"a": FISField(0, 15, 1),
|
||||||
|
|
||||||
"dma_buffer_id_low": FISField(1, 0, 32),
|
"dma_buffer_id_lsb": FISField(1, 0, 32),
|
||||||
|
|
||||||
"dma_buffer_id_high": FISField(2, 0, 32),
|
"dma_buffer_id_msb": FISField(2, 0, 32),
|
||||||
|
|
||||||
"dma_buffer_offset": FISField(4, 0, 32),
|
"dma_buffer_offset": FISField(4, 0, 32),
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ fis_data_layout = {
|
||||||
"type": FISField(0, 0, 8)
|
"type": FISField(0, 0, 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fis_pio_setup_d2h_len = 5
|
fis_pio_setup_d2h_cmd_len = 5
|
||||||
fis_pio_setup_d2h_layout = {
|
fis_pio_setup_d2h_layout = {
|
||||||
"type": FISField(0, 0, 8),
|
"type": FISField(0, 0, 8),
|
||||||
"pm_port": FISField(0, 8, 4),
|
"pm_port": FISField(0, 8, 4),
|
||||||
|
|
Loading…
Reference in a new issue