Merge branch '96-send-tcp-data-over-m2s' into '93-network-processor'
Resolve "Send TCP data over M2S" See merge request bslathi19/super6502!76
This commit is contained in:
@@ -7,6 +7,7 @@ stages:
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
|
when: manual
|
||||||
tags:
|
tags:
|
||||||
- efinity
|
- efinity
|
||||||
- linux
|
- linux
|
||||||
@@ -18,6 +19,7 @@ build:
|
|||||||
|
|
||||||
sim:
|
sim:
|
||||||
stage: sim
|
stage: sim
|
||||||
|
needs: []
|
||||||
tags:
|
tags:
|
||||||
- linux
|
- linux
|
||||||
- efinity
|
- efinity
|
||||||
@@ -25,3 +27,18 @@ sim:
|
|||||||
- source init_env.sh
|
- source init_env.sh
|
||||||
- make sim
|
- make sim
|
||||||
|
|
||||||
|
ntw_sim:
|
||||||
|
stage: sim
|
||||||
|
needs: []
|
||||||
|
tags:
|
||||||
|
- linux
|
||||||
|
script:
|
||||||
|
- source init_env.sh
|
||||||
|
- cd hw/super6502_fpga/src/sub/network_processor/sim/cocotb
|
||||||
|
- make -j `nproc`
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- hw/super6502_fpga/src/sub/network_processor/sim/cocotb/results.xml
|
||||||
|
reports:
|
||||||
|
junit: hw/super6502_fpga/src/sub/network_processor/sim/cocotb/results.xml
|
||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -22,3 +22,6 @@
|
|||||||
[submodule "hw/super6502_fpga/src/sub/interfaces"]
|
[submodule "hw/super6502_fpga/src/sub/interfaces"]
|
||||||
path = hw/super6502_fpga/src/sub/interfaces
|
path = hw/super6502_fpga/src/sub/interfaces
|
||||||
url = ../interfaces.git
|
url = ../interfaces.git
|
||||||
|
[submodule "hw/super6502_fpga/src/sub/my-fifos"]
|
||||||
|
path = hw/super6502_fpga/src/sub/my-fifos
|
||||||
|
url = ../my-fifos.git
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ src/sub/sd_controller_wrapper/sources.list
|
|||||||
src/sub/wb2axip/sources.list
|
src/sub/wb2axip/sources.list
|
||||||
src/sub/verilog-ethernet/sources.list
|
src/sub/verilog-ethernet/sources.list
|
||||||
src/sub/stream_dmas/sources.list
|
src/sub/stream_dmas/sources.list
|
||||||
|
src/sub/my-fifos/sources.list
|
||||||
1
hw/super6502_fpga/src/sub/my-fifos
Submodule
1
hw/super6502_fpga/src/sub/my-fifos
Submodule
Submodule hw/super6502_fpga/src/sub/my-fifos added at a19156c9cd
@@ -19,6 +19,6 @@ GPI_IMPL := vpi
|
|||||||
|
|
||||||
export PYTHONPATH := $(PWD)/tests:$(PYTHONPATH)
|
export PYTHONPATH := $(PWD)/tests:$(PYTHONPATH)
|
||||||
export TOPLEVEL_LANG
|
export TOPLEVEL_LANG
|
||||||
MODULE=tcp_test
|
MODULE=scapy_irl_test
|
||||||
|
|
||||||
include $(shell cocotb-config --makefiles)/Makefile.sim
|
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||||
@@ -0,0 +1,231 @@
|
|||||||
|
from http import server
|
||||||
|
from scapy.layers.inet import Ether, IP, TCP
|
||||||
|
from scapy.layers.l2 import ARP
|
||||||
|
|
||||||
|
from scapy import sendrecv
|
||||||
|
|
||||||
|
from scapy.config import conf
|
||||||
|
|
||||||
|
from scapy.supersocket import L3RawSocket
|
||||||
|
|
||||||
|
import cocotb
|
||||||
|
from cocotb.clock import Clock
|
||||||
|
from cocotb.triggers import Timer
|
||||||
|
from cocotb.triggers import RisingEdge
|
||||||
|
from cocotbext.axi import AxiLiteBus, AxiLiteMaster, AxiLiteRam
|
||||||
|
from cocotbext.eth import MiiPhy, GmiiFrame
|
||||||
|
import struct
|
||||||
|
|
||||||
|
from scapy.layers.inet import Ether, IP, TCP
|
||||||
|
from scapy.layers.l2 import ARP
|
||||||
|
from scapy.utils import PcapWriter
|
||||||
|
|
||||||
|
from scapy.layers.tuntap import TunTapInterface
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
CLK_PERIOD_NS = 10
|
||||||
|
|
||||||
|
MII_CLK_PERIOD_NS = 40
|
||||||
|
|
||||||
|
|
||||||
|
import socket
|
||||||
|
|
||||||
|
# In order for this to work, you need to run these commands:
|
||||||
|
# sudo ip tuntap add name tun0 mode tun user $USER
|
||||||
|
# sudo ip a add 172.0.0.1 peer 172.0.0.2 dev tun0
|
||||||
|
# sudo ip link set tun0 up
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
serversocket.bind(("172.0.0.1", 5678))
|
||||||
|
serversocket.listen(5)
|
||||||
|
|
||||||
|
t = TunTapInterface('tun0')
|
||||||
|
|
||||||
|
tcp_syn = IP(src="172.0.0.2", dst="172.0.0.1")/TCP(sport=1234, dport=5678, seq=0, ack=0, flags="S")
|
||||||
|
t.send(tcp_syn)
|
||||||
|
|
||||||
|
pkt = t.recv()
|
||||||
|
print(pkt)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TB:
|
||||||
|
def __init__(self, dut):
|
||||||
|
self.dut = dut
|
||||||
|
|
||||||
|
self.log = logging.getLogger("cocotb.tb")
|
||||||
|
self.log.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
cocotb.start_soon(Clock(dut.clk, CLK_PERIOD_NS, units="ns").start())
|
||||||
|
cocotb.start_soon(Clock(dut.mii_rx_clk, MII_CLK_PERIOD_NS, units="ns").start())
|
||||||
|
cocotb.start_soon(Clock(dut.mii_tx_clk, MII_CLK_PERIOD_NS, units="ns").start())
|
||||||
|
|
||||||
|
|
||||||
|
self.axil_master = AxiLiteMaster(AxiLiteBus.from_prefix(dut, "s_regs_axil"), dut.clk, dut.rst)
|
||||||
|
self.axil_ram = AxiLiteRam(AxiLiteBus.from_prefix(dut, "m_dma_axil"), dut.clk, dut.rst, size=2**16)
|
||||||
|
|
||||||
|
self.mii_phy = MiiPhy(dut.mii_txd, dut.mii_tx_er, dut.mii_tx_en, dut.mii_tx_clk,
|
||||||
|
dut.mii_rxd, dut.mii_rx_er, dut.mii_rx_dv, dut.mii_rx_clk, None, speed=100e6)
|
||||||
|
|
||||||
|
async def cycle_reset(self):
|
||||||
|
self.dut.rst.setimmediatevalue(0)
|
||||||
|
await RisingEdge(self.dut.clk) # type: ignore
|
||||||
|
await RisingEdge(self.dut.clk) # type: ignore
|
||||||
|
self.dut.rst.value = 1
|
||||||
|
await RisingEdge(self.dut.clk) # type: ignore
|
||||||
|
await RisingEdge(self.dut.clk) # type: ignore
|
||||||
|
self.dut.rst.value = 0
|
||||||
|
await RisingEdge(self.dut.clk) # type: ignore
|
||||||
|
await RisingEdge(self.dut.clk) # type: ignore
|
||||||
|
|
||||||
|
def ip_to_hex(ip: str) -> int:
|
||||||
|
octets = [int(i) for i in ip.split(".")]
|
||||||
|
|
||||||
|
result = int.from_bytes(struct.pack("BBBB", octets[0], octets[1], octets[2], octets[3]))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@cocotb.test()
|
||||||
|
async def test_irl(dut):
|
||||||
|
tb = TB(dut)
|
||||||
|
|
||||||
|
await tb.cycle_reset()
|
||||||
|
|
||||||
|
dut_ip = "172.0.0.2"
|
||||||
|
tb_ip = "172.0.0.1"
|
||||||
|
|
||||||
|
tb_mac = "02:00:00:11:22:33"
|
||||||
|
|
||||||
|
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
serversocket.bind((tb_ip, 5678))
|
||||||
|
serversocket.listen(5)
|
||||||
|
t = TunTapInterface('tun0')
|
||||||
|
|
||||||
|
|
||||||
|
dut_port = 1234
|
||||||
|
tb_port = 5678
|
||||||
|
|
||||||
|
await tb.axil_master.write_dword(0x0, 0x1807)
|
||||||
|
|
||||||
|
await tb.axil_master.write_dword(0x200, dut_port)
|
||||||
|
await tb.axil_master.write_dword(0x204, ip_to_hex(dut_ip))
|
||||||
|
await tb.axil_master.write_dword(0x208, tb_port)
|
||||||
|
await tb.axil_master.write_dword(0x20c, ip_to_hex(tb_ip))
|
||||||
|
await tb.axil_master.write_dword(0x210, 0x3)
|
||||||
|
|
||||||
|
resp = await tb.mii_phy.tx.recv() # type: GmiiFrame
|
||||||
|
|
||||||
|
packet = Ether(resp.get_payload())
|
||||||
|
|
||||||
|
tb.log.info(f"Packet Type: {packet.type:x}")
|
||||||
|
|
||||||
|
assert packet.type == 0x806, "Packet type is not ARP!"
|
||||||
|
|
||||||
|
|
||||||
|
arp_request = packet.payload
|
||||||
|
assert isinstance(arp_request, ARP)
|
||||||
|
|
||||||
|
tb.log.info(f"Arp OP: {arp_request.op}")
|
||||||
|
tb.log.info(f"Arp hwsrc: {arp_request.hwsrc}")
|
||||||
|
tb.log.info(f"Arp hwdst: {arp_request.hwdst}")
|
||||||
|
tb.log.info(f"Arp psrc: {arp_request.psrc}")
|
||||||
|
tb.log.info(f"Arp pdst: {arp_request.pdst}")
|
||||||
|
|
||||||
|
dut_mac = arp_request.hwsrc
|
||||||
|
dut_ip = arp_request.psrc
|
||||||
|
|
||||||
|
assert arp_request.op == 1, "ARP type is not request!"
|
||||||
|
assert arp_request.hwsrc == "02:00:00:aa:bb:cc", "ARP hwsrc does not match expected"
|
||||||
|
assert arp_request.hwdst == "00:00:00:00:00:00", "ARP hwdst does not match expected"
|
||||||
|
assert arp_request.psrc == dut_ip, "ARP psrc does not match expected"
|
||||||
|
assert arp_request.pdst == tb_ip, "ARP pdst does not match expected"
|
||||||
|
|
||||||
|
arp_response = Ether(dst=dut_mac, src=tb_mac)
|
||||||
|
arp_response /= ARP(op="is-at", hwsrc=tb_mac, hwdst=dut_mac, psrc=tb_ip, pdst=dut_ip)
|
||||||
|
arp_response = arp_response.build()
|
||||||
|
|
||||||
|
await tb.mii_phy.rx.send(GmiiFrame.from_payload(arp_response))
|
||||||
|
|
||||||
|
resp = await tb.mii_phy.tx.recv() # type: GmiiFrame
|
||||||
|
packet = Ether(resp.get_payload())
|
||||||
|
tb.log.info(f"Packet Type: {packet.type:x}")
|
||||||
|
|
||||||
|
ip_packet = packet.payload
|
||||||
|
assert isinstance(ip_packet, IP)
|
||||||
|
|
||||||
|
tcp_packet = ip_packet.payload
|
||||||
|
assert isinstance(tcp_packet, TCP)
|
||||||
|
|
||||||
|
tb.log.info(f"Source Port: {tcp_packet.sport}")
|
||||||
|
tb.log.info(f"Dest Port: {tcp_packet.dport}")
|
||||||
|
tb.log.info(f"Seq: {tcp_packet.seq}")
|
||||||
|
tb.log.info(f"Ack: {tcp_packet.ack}")
|
||||||
|
tb.log.info(f"Data Offs: {tcp_packet.dataofs}")
|
||||||
|
tb.log.info(f"flags: {tcp_packet.flags}")
|
||||||
|
tb.log.info(f"window: {tcp_packet.window}")
|
||||||
|
tb.log.info(f"Checksum: {tcp_packet.chksum}")
|
||||||
|
|
||||||
|
t.send(ip_packet)
|
||||||
|
|
||||||
|
pkt = t.recv()
|
||||||
|
print(pkt)
|
||||||
|
|
||||||
|
tcp_synack = Ether(dst=dut_mac, src=tb_mac) / pkt
|
||||||
|
|
||||||
|
await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_synack.build()))
|
||||||
|
|
||||||
|
resp = await tb.mii_phy.tx.recv() # type: GmiiFrame
|
||||||
|
packet = Ether(resp.get_payload())
|
||||||
|
tb.log.info(f"Packet Type: {packet.type:x}")
|
||||||
|
|
||||||
|
ip_packet = packet.payload
|
||||||
|
assert isinstance(ip_packet, IP)
|
||||||
|
|
||||||
|
tcp_packet = ip_packet.payload
|
||||||
|
assert isinstance(tcp_packet, TCP)
|
||||||
|
|
||||||
|
tb.log.info(f"Source Port: {tcp_packet.sport}")
|
||||||
|
tb.log.info(f"Dest Port: {tcp_packet.dport}")
|
||||||
|
tb.log.info(f"Seq: {tcp_packet.seq}")
|
||||||
|
tb.log.info(f"Ack: {tcp_packet.ack}")
|
||||||
|
tb.log.info(f"Data Offs: {tcp_packet.dataofs}")
|
||||||
|
tb.log.info(f"flags: {tcp_packet.flags}")
|
||||||
|
tb.log.info(f"window: {tcp_packet.window}")
|
||||||
|
tb.log.info(f"Checksum: {tcp_packet.chksum}")
|
||||||
|
|
||||||
|
t.send(ip_packet)
|
||||||
|
|
||||||
|
con, addr = serversocket.accept()
|
||||||
|
|
||||||
|
# Construct a descriptor in memry
|
||||||
|
tb.axil_ram.write_dword(0x00000000, 0x00001000)
|
||||||
|
tb.axil_ram.write_dword(0x00000004, 64)
|
||||||
|
tb.axil_ram.write_dword(0x00000008, 0)
|
||||||
|
tb.axil_ram.write_dword(0x0000000c, 0)
|
||||||
|
|
||||||
|
test_data = bytearray([x % 256 for x in range(256)])
|
||||||
|
|
||||||
|
tb.axil_ram.write(0x1000, test_data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
await tb.axil_master.write_dword(0x22c, 0)
|
||||||
|
await tb.axil_master.write_dword(0x220, 0x00000000)
|
||||||
|
await tb.axil_master.write_dword(0x224, 0x00000000)
|
||||||
|
|
||||||
|
resp = await tb.mii_phy.tx.recv() # type: GmiiFrame
|
||||||
|
packet = Ether(resp.get_payload())
|
||||||
|
|
||||||
|
t.send(packet.payload)
|
||||||
|
|
||||||
|
# con.recv(64)
|
||||||
|
|
||||||
|
serversocket.close()
|
||||||
@@ -176,3 +176,40 @@ async def test_simple(dut):
|
|||||||
tb.log.info(f"Checksum: {tcp_packet.chksum}")
|
tb.log.info(f"Checksum: {tcp_packet.chksum}")
|
||||||
|
|
||||||
assert tcp_packet.ack == tb_seq + 1
|
assert tcp_packet.ack == tb_seq + 1
|
||||||
|
|
||||||
|
# Try to send a packet from M2S
|
||||||
|
|
||||||
|
# Construct a descriptor in memry
|
||||||
|
tb.axil_ram.write_dword(0x00000000, 0x00001000)
|
||||||
|
tb.axil_ram.write_dword(0x00000004, 64)
|
||||||
|
tb.axil_ram.write_dword(0x00000008, 0)
|
||||||
|
tb.axil_ram.write_dword(0x0000000c, 0)
|
||||||
|
|
||||||
|
test_data = bytearray([x % 256 for x in range(256)])
|
||||||
|
|
||||||
|
tb.axil_ram.write(0x1000, test_data)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
await tb.axil_master.write_dword(0x22c, 0)
|
||||||
|
await tb.axil_master.write_dword(0x220, 0x00000000)
|
||||||
|
await tb.axil_master.write_dword(0x224, 0x00000000)
|
||||||
|
|
||||||
|
resp = await tb.mii_phy.tx.recv() # type: GmiiFrame
|
||||||
|
packet = Ether(resp.get_payload())
|
||||||
|
pktdump.write(packet)
|
||||||
|
tb.log.info(f"Packet Type: {packet.type:x}")
|
||||||
|
|
||||||
|
tcp_packet = ip_packet.payload
|
||||||
|
assert isinstance(tcp_packet, TCP)
|
||||||
|
|
||||||
|
tb.log.info(f"Source Port: {tcp_packet.sport}")
|
||||||
|
tb.log.info(f"Dest Port: {tcp_packet.dport}")
|
||||||
|
tb.log.info(f"Seq: {tcp_packet.seq}")
|
||||||
|
tb.log.info(f"Ack: {tcp_packet.ack}")
|
||||||
|
tb.log.info(f"Data Offs: {tcp_packet.dataofs}")
|
||||||
|
tb.log.info(f"flags: {tcp_packet.flags}")
|
||||||
|
tb.log.info(f"window: {tcp_packet.window}")
|
||||||
|
tb.log.info(f"Checksum: {tcp_packet.chksum}")
|
||||||
|
|
||||||
|
pktdump.close()
|
||||||
@@ -261,8 +261,8 @@ ip_complete #(
|
|||||||
.tx_error_arp_failed (), // should go to stats register
|
.tx_error_arp_failed (), // should go to stats register
|
||||||
|
|
||||||
.local_mac (48'h020000aabbcc), // should be a register
|
.local_mac (48'h020000aabbcc), // should be a register
|
||||||
.local_ip (32'hac000002), // should be a register
|
.local_ip (32'hAC000002), // should be a register
|
||||||
.gateway_ip (32'hac000001), // should be a register
|
.gateway_ip (32'hAC000001), // should be a register
|
||||||
.subnet_mask (32'hffffff00), // should be a register
|
.subnet_mask (32'hffffff00), // should be a register
|
||||||
.clear_arp_cache ('0) // should come from sw
|
.clear_arp_cache ('0) // should come from sw
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -127,19 +127,36 @@ always_comb begin
|
|||||||
18: m_ip.ip_payload_axis_tdata = '0;
|
18: m_ip.ip_payload_axis_tdata = '0;
|
||||||
19: begin
|
19: begin
|
||||||
m_ip.ip_payload_axis_tdata = '0;
|
m_ip.ip_payload_axis_tdata = '0;
|
||||||
m_ip.ip_payload_axis_tlast = '1;
|
m_ip.ip_payload_axis_tlast = ~s_axis_data.tvalid; // kinda hacky
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
if (m_ip.ip_payload_axis_tready) begin
|
if (m_ip.ip_payload_axis_tready) begin
|
||||||
counter_next = counter + 1;
|
counter_next = counter + 1;
|
||||||
|
|
||||||
|
if (counter == 19) begin
|
||||||
|
state_next = DATA;
|
||||||
|
end
|
||||||
|
|
||||||
if (m_ip.ip_payload_axis_tlast) begin
|
if (m_ip.ip_payload_axis_tlast) begin
|
||||||
state_next = IDLE;
|
state_next = IDLE;
|
||||||
o_packet_done = '1;
|
o_packet_done = '1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
DATA: begin
|
||||||
|
state_next = DATA;
|
||||||
|
s_axis_data.tready = m_ip.ip_payload_axis_tready;
|
||||||
|
m_ip.ip_payload_axis_tvalid = s_axis_data.tvalid;
|
||||||
|
m_ip.ip_payload_axis_tdata = s_axis_data.tdata;
|
||||||
|
m_ip.ip_payload_axis_tlast = s_axis_data.tlast;
|
||||||
|
|
||||||
|
if (s_axis_data.tlast && s_axis_data.tvalid && s_axis_data.tready) begin
|
||||||
|
state_next = IDLE;
|
||||||
|
o_packet_done = '1;
|
||||||
|
end
|
||||||
|
end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ axis_intf s2m_axis();
|
|||||||
axis_intf m2s_post_saf_axis();
|
axis_intf m2s_post_saf_axis();
|
||||||
axis_intf s2m_pre_saf_axis();
|
axis_intf s2m_pre_saf_axis();
|
||||||
|
|
||||||
|
axis_intf m_tx_ctrl_axis_data();
|
||||||
|
|
||||||
// regs
|
// regs
|
||||||
tcp_stream_regs_pkg::tcp_stream_regs__in_t hwif_in;
|
tcp_stream_regs_pkg::tcp_stream_regs__in_t hwif_in;
|
||||||
tcp_stream_regs_pkg::tcp_stream_regs__out_t hwif_out;
|
tcp_stream_regs_pkg::tcp_stream_regs__out_t hwif_out;
|
||||||
@@ -47,6 +49,7 @@ tcp_pkg::rx_msg_t rx_msg;
|
|||||||
logic rx_msg_valid;
|
logic rx_msg_valid;
|
||||||
logic rx_msg_ack;
|
logic rx_msg_ack;
|
||||||
|
|
||||||
|
logic [15:0] w_saf_pkt_len;
|
||||||
logic [15:0] w_tx_ip_len;
|
logic [15:0] w_tx_ip_len;
|
||||||
logic [31:0] w_tx_seq_number;
|
logic [31:0] w_tx_seq_number;
|
||||||
logic [31:0] w_tx_ack_number;
|
logic [31:0] w_tx_ack_number;
|
||||||
@@ -133,42 +136,27 @@ tcp_state_manager u_tcp_state_manager (
|
|||||||
|
|
||||||
|
|
||||||
// tx buffer
|
// tx buffer
|
||||||
axis_fifo #(
|
axis_saf_fifo #(
|
||||||
.DEPTH(4096),
|
.DATA_DEPTH_L2(12),
|
||||||
.DATA_WIDTH(DATA_WIDTH),
|
.CTRL_DEPTH_L2(7),
|
||||||
.FRAME_FIFO(1)
|
.DATA_MEM("distributed"),
|
||||||
|
.CTRL_MEM("distributed")
|
||||||
) m2s_saf_fifo (
|
) m2s_saf_fifo (
|
||||||
.clk (clk),
|
.sclk (clk),
|
||||||
.rst (rst),
|
.srst (rst),
|
||||||
|
.s_axis (m2s_axis),
|
||||||
|
|
||||||
.s_axis_tdata (m2s_axis.tdata),
|
.mclk (clk),
|
||||||
.s_axis_tkeep (m2s_axis.tkeep),
|
.mrst (rst),
|
||||||
.s_axis_tvalid (m2s_axis.tvalid),
|
.m_axis (m2s_post_saf_axis),
|
||||||
.s_axis_tready (m2s_axis.tready),
|
|
||||||
.s_axis_tlast (m2s_axis.tlast),
|
|
||||||
.s_axis_tid (m2s_axis.tid),
|
|
||||||
.s_axis_tdest (m2s_axis.tdest),
|
|
||||||
.s_axis_tuser (m2s_axis.tuser),
|
|
||||||
|
|
||||||
.m_axis_tdata (m2s_post_saf_axis.tdata),
|
.o_len (w_saf_pkt_len),
|
||||||
.m_axis_tkeep (m2s_post_saf_axis.tkeep),
|
.o_rx_pkt (),
|
||||||
.m_axis_tvalid (m2s_post_saf_axis.tvalid),
|
.o_tx_pkt (),
|
||||||
.m_axis_tready (m2s_post_saf_axis.tready),
|
.o_drop ()
|
||||||
.m_axis_tlast (m2s_post_saf_axis.tlast),
|
|
||||||
.m_axis_tid (m2s_post_saf_axis.tid),
|
|
||||||
.m_axis_tdest (m2s_post_saf_axis.tdest),
|
|
||||||
.m_axis_tuser (m2s_post_saf_axis.tuser),
|
|
||||||
|
|
||||||
.pause_req ('0),
|
|
||||||
.pause_ack (),
|
|
||||||
|
|
||||||
.status_depth (),
|
|
||||||
.status_depth_commit (),
|
|
||||||
.status_overflow (),
|
|
||||||
.status_bad_frame (),
|
|
||||||
.status_good_frame ()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// tx control
|
// tx control
|
||||||
tcp_tx_ctrl u_tcp_tx_ctrl (
|
tcp_tx_ctrl u_tcp_tx_ctrl (
|
||||||
.i_clk (clk),
|
.i_clk (clk),
|
||||||
@@ -185,6 +173,10 @@ tcp_tx_ctrl u_tcp_tx_ctrl (
|
|||||||
.o_window_size (w_tx_window_size),
|
.o_window_size (w_tx_window_size),
|
||||||
.o_hdr_valid (w_tx_hdr_valid),
|
.o_hdr_valid (w_tx_hdr_valid),
|
||||||
|
|
||||||
|
.s_axis_len (w_saf_pkt_len),
|
||||||
|
.s_axis (m2s_post_saf_axis),
|
||||||
|
.m_axis (m_tx_ctrl_axis_data),
|
||||||
|
|
||||||
.i_packet_done (w_tx_packet_done)
|
.i_packet_done (w_tx_packet_done)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -193,7 +185,7 @@ tcp_packet_generator u_tcp_packet_generator (
|
|||||||
.i_clk (clk),
|
.i_clk (clk),
|
||||||
.i_rst (rst),
|
.i_rst (rst),
|
||||||
|
|
||||||
.s_axis_data (m2s_post_saf_axis),
|
.s_axis_data (m_tx_ctrl_axis_data),
|
||||||
|
|
||||||
.i_ip_len (w_tx_ip_len),
|
.i_ip_len (w_tx_ip_len),
|
||||||
.i_seq_number (w_tx_seq_number),
|
.i_seq_number (w_tx_seq_number),
|
||||||
|
|||||||
@@ -15,9 +15,22 @@ module tcp_tx_ctrl(
|
|||||||
output logic [15:0] o_window_size,
|
output logic [15:0] o_window_size,
|
||||||
output logic o_hdr_valid,
|
output logic o_hdr_valid,
|
||||||
|
|
||||||
|
axis_intf.SLAVE s_axis,
|
||||||
|
input logic [15:0] s_axis_len,
|
||||||
|
axis_intf.MASTER m_axis,
|
||||||
|
|
||||||
input wire i_packet_done
|
input wire i_packet_done
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assign m_axis.tdata = s_axis.tdata;
|
||||||
|
assign m_axis.tkeep = s_axis.tkeep;
|
||||||
|
assign m_axis.tvalid = s_axis.tvalid;
|
||||||
|
assign s_axis.tready = m_axis.tready;
|
||||||
|
assign m_axis.tlast = s_axis.tlast;
|
||||||
|
assign m_axis.tid = s_axis.tid;
|
||||||
|
assign m_axis.tdest = s_axis.tdest;
|
||||||
|
assign m_axis.tuser = s_axis.tuser;
|
||||||
|
|
||||||
localparam FLAG_FIN = (1 << 0);
|
localparam FLAG_FIN = (1 << 0);
|
||||||
localparam FLAG_SYN = (1 << 1);
|
localparam FLAG_SYN = (1 << 1);
|
||||||
localparam FLAG_RST = (1 << 2);
|
localparam FLAG_RST = (1 << 2);
|
||||||
@@ -30,7 +43,7 @@ localparam FLAG_CWR = (1 << 7);
|
|||||||
logic [31:0] seq_num, seq_num_next;
|
logic [31:0] seq_num, seq_num_next;
|
||||||
assign o_seq_number = seq_num;
|
assign o_seq_number = seq_num;
|
||||||
|
|
||||||
enum logic [2:0] {IDLE, SEND_SYN, SEND_ACK} state, state_next;
|
enum logic [2:0] {IDLE, SEND_SYN, SEND_ACK, SEND_DATA} state, state_next;
|
||||||
|
|
||||||
always_ff @(posedge i_clk) begin
|
always_ff @(posedge i_clk) begin
|
||||||
if (i_rst) begin
|
if (i_rst) begin
|
||||||
@@ -43,6 +56,8 @@ always_ff @(posedge i_clk) begin
|
|||||||
end
|
end
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
|
state_next = state;
|
||||||
|
|
||||||
o_ack_number = '0;
|
o_ack_number = '0;
|
||||||
o_flags = '0;
|
o_flags = '0;
|
||||||
o_window_size = 16'b1;
|
o_window_size = 16'b1;
|
||||||
@@ -62,6 +77,10 @@ always_comb begin
|
|||||||
TX_CTRL_SEND_ACK: state_next = SEND_ACK;
|
TX_CTRL_SEND_ACK: state_next = SEND_ACK;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (s_axis.tvalid) begin
|
||||||
|
state_next = SEND_DATA;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
SEND_SYN: begin
|
SEND_SYN: begin
|
||||||
@@ -80,7 +99,18 @@ always_comb begin
|
|||||||
|
|
||||||
if (i_packet_done) begin
|
if (i_packet_done) begin
|
||||||
state_next = IDLE;
|
state_next = IDLE;
|
||||||
seq_num_next = seq_num + 1;
|
seq_num_next = seq_num;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
SEND_DATA: begin
|
||||||
|
o_flags = FLAG_ACK | FLAG_PSH;
|
||||||
|
o_ip_len = 16'd40 + s_axis_len; // default length of IP packet
|
||||||
|
o_hdr_valid = '1;
|
||||||
|
|
||||||
|
if (i_packet_done) begin
|
||||||
|
state_next = IDLE;
|
||||||
|
seq_num_next = seq_num + s_axis_len;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
|||||||
@@ -204,6 +204,11 @@
|
|||||||
<efx:design_file name="src/sub/interfaces/axis_intf.sv" version="default" library="default" />
|
<efx:design_file name="src/sub/interfaces/axis_intf.sv" version="default" library="default" />
|
||||||
<efx:design_file name="src/sub/interfaces/ip_intf.sv" version="default" library="default" />
|
<efx:design_file name="src/sub/interfaces/ip_intf.sv" version="default" library="default" />
|
||||||
<efx:design_file name="src/sub/interfaces/eth_intf.sv" version="default" library="default" />
|
<efx:design_file name="src/sub/interfaces/eth_intf.sv" version="default" library="default" />
|
||||||
|
<efx:design_file name="src/sub/my-fifos/src/axis_saf.sv" version="default" library="default"/>
|
||||||
|
<efx:design_file name="src/sub/my-fifos/src/dpram.sv" version="default" library="default"/>
|
||||||
|
<efx:design_file name="src/sub/my-fifos/src/fifo_fwft.sv" version="default" library="default"/>
|
||||||
|
<efx:design_file name="src/sub/my-fifos/src/fifo.sv" version="default" library="default"/>
|
||||||
|
<efx:design_file name="src/sub/my-fifos/src/fwft_adapter.sv" version="default" library="default"/>
|
||||||
<efx:top_vhdl_arch name="" />
|
<efx:top_vhdl_arch name="" />
|
||||||
</efx:design_info>
|
</efx:design_info>
|
||||||
<efx:constraint_info>
|
<efx:constraint_info>
|
||||||
|
|||||||
Reference in New Issue
Block a user