self.comb += [
transport.source.ack.eq(1),
+ # XXX for test
If(transport.source.stb & (transport.source.type == fis_types["DMA_ACTIVATE_D2H"]),
self.to_tx.dma_activate.eq(1)
+ ),
+ If(transport.source.stb & (transport.source.type == fis_types["DATA"]),
+ source.stb.eq(1),
+ source.sop.eq(transport.source.sop),
+ source.eop.eq(transport.source.eop),
+ source.data.eq(transport.source.data),
)
]
self.debug = debug
self.transport.set_command_callback(self.callback)
+ self.dma_enable = 0
+ self.dma_address = 0
+
+ def allocate_dma(self, base, length):
+ self.dma_base = base
+ self.dma_buffer = [0]*(length//4)
+
+ def enable_dma(self):
+ self.dma_enable = 1
+
+ def disable_dma(self):
+ self.dma_enable = 0
+
+ def dma_write(self, adr, data):
+ current_adr = (adr-self.dma_base)//4
+ for i in range(len(data)):
+ self.dma_buffer[current_adr+i] = data[i]
+
+ def dma_read(self, adr, length=1):
+ current_adr = (adr-self.dma_base)//4
+ data = []
+ for i in range(length//4):
+ data.append(self.dma_buffer[current_adr+i])
+ return data
+
def callback(self, fis):
+ # XXX maximum of 2048 DWORDS per DMA
if isinstance(fis, FIS_REG_H2D):
if fis.command == regs["WRITE_DMA_EXT"]:
- # XXX add checks
+ self.dma_address = fis.lba_lsb
dma_activate = FIS_DMA_ACTIVATE_D2H()
- # XXX fill dma_activate
self.transport.send(dma_activate)
+ elif fis.command == regs["READ_DMA_EXT"]:
+ self.dma_address = fis.lba_lsb
+ data = FIS_DATA(self.dma_read(fis.lba_lsb, fis.count*4))
+ self.transport.send(data)
+ elif fis.command == regs["IDENTIFY_DEVICE_DMA"]:
+ self.dma_address = fis.lba_lsb
+ data = FIS_DATA(self.dma_read(fis.lba_lsb, fis.count*4))
+ self.transport.send(data)
+ elif isinstance(fis, FIS_DATA):
+ if self.dma_enable:
+ self.dma_write(self.dma_address, fis.packet[1:])
+ self.dma_address += len(fis.packet[1:])
class BFM(Module):
def __init__(self,
self.submodules.command = SATACommand(self.transport)
def gen_simulation(self, selfp):
+ self.bfm.command.allocate_dma(0x00000000, 64*1024*1024)
+ self.bfm.command.enable_dma()
for i in range(100):
yield
for i in range(32):
selfp.command.sink.sop = (i==0)
selfp.command.sink.eop = (i==31)
selfp.command.sink.write = 1
- selfp.command.sink.address = 0x1234
+ selfp.command.sink.address = 1024
selfp.command.sink.length = 32
selfp.command.sink.data = i
yield
while selfp.command.sink.ack == 0:
yield
- selfp.command.sink.ack = 0
+ selfp.command.sink.stb = 0
+ for i in range(32):
+ yield
+ selfp.command.sink.stb = 1
+ selfp.command.sink.sop = 1
+ selfp.command.sink.eop = 1
+ selfp.command.sink.write = 0
+ selfp.command.sink.read = 1
+ selfp.command.sink.address = 1024
+ selfp.command.sink.length = 32
+ yield
+ while selfp.command.sink.ack == 0:
+ yield
+ selfp.command.sink.stb = 0
+ while True:
+ if selfp.command.source.stb:
+ print("%08x" %selfp.command.source.data)
+ yield
+ #dma_dump = self.bfm.command.dma_read(1024, 32*4)
+ #for d in dma_dump:
+ # print("%08x" %d)
if __name__ == "__main__":
run_simulation(TB(), ncycles=512, vcd_name="my.vcd", keep_files=True)
)
fsm.act("SEND_REG_H2D_CMD",
_encode_cmd(sink, fis_reg_h2d_layout, encoded_cmd),
- cmd_len.eq(fis_reg_h2d_cmd_len),
+ cmd_len.eq(fis_reg_h2d_cmd_len-1),
cmd_send.eq(1),
If(cmd_done,
sink.ack.eq(1),
)
fsm.act("SEND_DATA_CMD",
_encode_cmd(sink, fis_data_layout, encoded_cmd),
- cmd_len.eq(fis_data_cmd_len),
+ cmd_len.eq(fis_data_cmd_len-1),
cmd_with_data.eq(1),
cmd_send.eq(1),
If(cmd_done,
)
)
-
cmd_cases = {}
for i in range(cmd_ndwords):
cmd_cases[i] = [link.sink.d.eq(encoded_cmd[32*i:32*(i+1)])]
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)
+ cmd_done.eq((cnt==cmd_len) & link.sink.ack)
).Elif(data_send,
link.sink.stb.eq(sink.stb),
link.sink.sop.eq(0),
self.submodules += fsm
fsm.act("IDLE",
+ clr_cnt.eq(1),
If(link.source.stb & link.source.sop,
If(test_type("REG_D2H"),
NextState("RECEIVE_REG_D2H_CMD")
)
)
fsm.act("RECEIVE_REG_D2H_CMD",
- cmd_len.eq(fis_reg_d2h_cmd_len),
+ cmd_len.eq(fis_reg_d2h_cmd_len-1),
cmd_receive.eq(1),
If(cmd_done,
NextState("PRESENT_REG_D2H_CMD")
)
)
fsm.act("RECEIVE_DMA_ACTIVATE_D2H_CMD",
- cmd_len.eq(fis_dma_activate_d2h_cmd_len),
+ cmd_len.eq(fis_dma_activate_d2h_cmd_len-1),
cmd_receive.eq(1),
If(cmd_done,
NextState("PRESENT_DMA_ACTIVATE_D2H_CMD")
)
)
fsm.act("RECEIVE_DATA_CMD",
- cmd_len.eq(fis_data_cmd_len),
+ cmd_len.eq(fis_data_cmd_len-1),
cmd_receive.eq(1),
If(cmd_done,
NextState("PRESENT_DATA")
).Elif(inc_cnt,
cnt.eq(cnt+1)
)
- self.comb += cmd_done.eq(cnt==cmd_len)
+ self.comb += cmd_done.eq((cnt==cmd_len) & link.source.ack)
self.comb += link.source.ack.eq(cmd_receive | (data_receive & source.ack))
class SATATransport(Module):