Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb360d3c6d |
@@ -0,0 +1,270 @@
|
||||
from http import server
|
||||
from scapy.layers.inet import Ether, IP, TCP
|
||||
from scapy.layers.l2 import ARP
|
||||
from scapy.data import IP_PROTOS
|
||||
|
||||
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()
|
||||
|
||||
con.close()
|
||||
serversocket.close()
|
||||
|
||||
while True:
|
||||
pkt = t.recv()
|
||||
if (pkt.proto == IP_PROTOS.tcp):
|
||||
break
|
||||
print(pkt)
|
||||
|
||||
tcp_fin = Ether(dst=dut_mac, src=tb_mac) / pkt
|
||||
|
||||
await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_fin.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)
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
# 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()
|
||||
@@ -0,0 +1,139 @@
|
||||
module tcp_dest_decap (
|
||||
input i_clk,
|
||||
input i_rst,
|
||||
|
||||
ip_intf.SLAVE s_ip,
|
||||
ip_intf.MASTER m_ip,
|
||||
|
||||
output wire [15:0] o_tcp_dest,
|
||||
output wire o_tcp_dest_valid
|
||||
);
|
||||
|
||||
|
||||
logic [15:0] tcp_dest, tcp_dest_next;
|
||||
logic [31:0] pipe, pipe_next;
|
||||
logic [3:0] pipe_valid, pipe_valid_next;
|
||||
logic [3:0] pipe_last, pipe_last_next;
|
||||
|
||||
logic valid;
|
||||
|
||||
|
||||
enum logic [1:0] {PORTS, PASSTHROUGH} state, state_next;
|
||||
logic [1:0] counter, counter_next;
|
||||
|
||||
|
||||
// We don't need the mac addresses or the ethertype.
|
||||
assign m_ip.eth_src_mac = '0;
|
||||
assign m_ip.eth_dest_mac = '0;
|
||||
assign m_ip.eth_type = '0;
|
||||
|
||||
assign o_tcp_dest_valid = valid;
|
||||
assign o_tcp_dest = tcp_dest;
|
||||
|
||||
skidbuffer #(
|
||||
.DW(160)
|
||||
) u_tcp_ip_hdr_skidbuffer (
|
||||
.i_clk (i_clk),
|
||||
.i_reset (i_rst),
|
||||
|
||||
.i_valid (s_ip.ip_hdr_valid),
|
||||
.o_ready (s_ip.ip_hdr_ready),
|
||||
.i_data ({
|
||||
s_ip.ip_version,
|
||||
s_ip.ip_ihl,
|
||||
s_ip.ip_dscp,
|
||||
s_ip.ip_ecn,
|
||||
s_ip.ip_length,
|
||||
s_ip.ip_identification,
|
||||
s_ip.ip_flags,
|
||||
s_ip.ip_fragment_offset,
|
||||
s_ip.ip_ttl,
|
||||
s_ip.ip_protocol,
|
||||
s_ip.ip_header_checksum,
|
||||
s_ip.ip_source_ip,
|
||||
s_ip.ip_dest_ip
|
||||
}),
|
||||
.o_valid (m_ip.ip_hdr_valid),
|
||||
.i_ready (m_ip.ip_hdr_ready),
|
||||
.o_data ({
|
||||
m_ip.ip_version,
|
||||
m_ip.ip_ihl,
|
||||
m_ip.ip_dscp,
|
||||
m_ip.ip_ecn,
|
||||
m_ip.ip_length,
|
||||
m_ip.ip_identification,
|
||||
m_ip.ip_flags,
|
||||
m_ip.ip_fragment_offset,
|
||||
m_ip.ip_ttl,
|
||||
m_ip.ip_protocol,
|
||||
m_ip.ip_header_checksum,
|
||||
m_ip.ip_source_ip,
|
||||
m_ip.ip_dest_ip
|
||||
})
|
||||
);
|
||||
|
||||
always_ff @(posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
tcp_dest <= '0;
|
||||
pipe <= '0;
|
||||
pipe_valid <= '0;
|
||||
pipe_last <= '0;
|
||||
state <= PORTS;
|
||||
counter <= '0;
|
||||
end else begin
|
||||
tcp_dest <= tcp_dest_next;
|
||||
pipe <= pipe_next;
|
||||
pipe_valid <= pipe_valid_next;
|
||||
pipe_last <= pipe_last_next;
|
||||
state <= state_next;
|
||||
counter <= counter_next;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
tcp_dest_next = tcp_dest;
|
||||
state_next = state;
|
||||
pipe_next = pipe;
|
||||
pipe_valid_next = pipe_valid;
|
||||
pipe_last_next = pipe_last;
|
||||
counter_next = pipe;
|
||||
|
||||
s_ip.ip_payload_axis_tready = '0;
|
||||
|
||||
case (state)
|
||||
PORTS: begin
|
||||
s_ip.ip_payload_axis_tready = 1;
|
||||
valid = '0;
|
||||
|
||||
if (s_ip.ip_payload_axis_tvalid) begin
|
||||
counter_next = counter + 1;
|
||||
pipe_valid_next = {pipe_valid[2:0], 1'b1};
|
||||
pipe_next = {pipe_next[23:0], s_ip.ip_payload_axis_tdata};
|
||||
if (counter == 2'h3) begin
|
||||
state_next = PASSTHROUGH;
|
||||
tcp_dest_next = pipe_next[15:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
PASSTHROUGH: begin
|
||||
// match ready except if we have seen last, then just finish it out.
|
||||
pipe_valid_next = {pipe_valid[2:0], s_ip.ip_payload_axis_tvalid};
|
||||
pipe_last_next = {pipe_last[2:0], s_ip.ip_payload_axis_tlast};
|
||||
pipe_next = {pipe_next[23:0], s_ip.ip_payload_axis_tdata};
|
||||
|
||||
s_ip.ip_payload_axis_tready = m_ip.ip_payload_axis_tready;
|
||||
m_ip.ip_payload_axis_tvalid = pipe_valid[3];
|
||||
m_ip.ip_payload_axis_tlast = pipe_last[3];
|
||||
m_ip.ip_payload_axis_tdata = pipe[31:24];
|
||||
|
||||
valid = '1;
|
||||
|
||||
if (pipe_last[3] && pipe_valid[3]) begin
|
||||
state_next = PORTS;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,49 @@
|
||||
import tcp_pkg::*;
|
||||
|
||||
module tcp_rx_ctrl (
|
||||
input logic i_clk,
|
||||
input logic i_rst,
|
||||
|
||||
output tcp_pkg::rx_msg_t o_rx_msg,
|
||||
output logic o_rx_msg_valid,
|
||||
input logic i_rx_msg_ack,
|
||||
|
||||
input logic [31:0] i_seq_number,
|
||||
input logic [31:0] i_ack_number,
|
||||
input logic [15:0] i_source_port,
|
||||
input logic [15:0] i_dest_port,
|
||||
input logic [7:0] i_flags,
|
||||
input logic [15:0] i_window_size,
|
||||
input logic i_hdr_valid,
|
||||
|
||||
output logic [31:0] o_ack_number
|
||||
);
|
||||
|
||||
logic [31:0] ack_num, ack_num_next;
|
||||
assign o_ack_number = ack_num;
|
||||
|
||||
always_ff @(posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
ack_num <= '0;
|
||||
end else begin
|
||||
ack_num <= ack_num_next;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
if (i_hdr_valid) begin
|
||||
if (i_flags == 8'h12) begin
|
||||
o_rx_msg = RX_MSG_RECV_SYNACK;
|
||||
o_rx_msg_valid = '1;
|
||||
|
||||
ack_num_next = i_seq_number + 1;
|
||||
end
|
||||
|
||||
if (i_flags == 8'h11) begin
|
||||
o_rx_msg = RX_MSG_RECV_FIN;
|
||||
o_rx_msg_valid = '1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,100 @@
|
||||
import tcp_pkg::*;
|
||||
|
||||
module tcp_state_manager(
|
||||
input wire i_clk,
|
||||
input wire i_rst,
|
||||
|
||||
input wire i_enable,
|
||||
|
||||
input wire i_open,
|
||||
output logic o_open_clr,
|
||||
input wire i_close,
|
||||
output logic o_close_clr,
|
||||
|
||||
output tcp_pkg::tx_ctrl_t o_tx_ctrl,
|
||||
output logic o_tx_ctrl_valid,
|
||||
input logic i_tx_ctrl_ack,
|
||||
|
||||
input tcp_pkg::rx_msg_t i_rx_msg,
|
||||
input wire i_rx_msg_valid,
|
||||
output logic o_rx_msg_ack
|
||||
);
|
||||
|
||||
enum logic [3:0] {
|
||||
IDLE,
|
||||
SYN_RCVD, // In this design, this state should not be reached!
|
||||
SYN_SENT_1,
|
||||
SYN_SENT_2,
|
||||
ESTABLISHED,
|
||||
WAIT_CLOSE,
|
||||
LAST_ACK,
|
||||
TIME_WAIT,
|
||||
FIN_WAIT_1,
|
||||
FIN_WAIT_2
|
||||
} tcp_state, tcp_state_next;
|
||||
|
||||
|
||||
always_ff @(posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
tcp_state <= IDLE;
|
||||
end else begin
|
||||
if (~i_enable) begin
|
||||
tcp_state <= IDLE;
|
||||
end else begin
|
||||
tcp_state <= tcp_state_next;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
tcp_state_next = tcp_state;
|
||||
|
||||
o_tx_ctrl_valid = '0;
|
||||
|
||||
o_tx_ctrl = TX_CTRL_NOP;
|
||||
o_tx_ctrl_valid = '0;
|
||||
|
||||
o_rx_msg_ack = '0;
|
||||
|
||||
case (tcp_state)
|
||||
IDLE: begin
|
||||
if (i_open) begin
|
||||
o_tx_ctrl = TX_CTRL_SEND_SYN;
|
||||
o_tx_ctrl_valid = '1;
|
||||
|
||||
if (i_tx_ctrl_ack) begin
|
||||
tcp_state_next = SYN_SENT_1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SYN_SENT_1: begin
|
||||
if (i_rx_msg_valid && i_rx_msg== RX_MSG_RECV_SYNACK) begin
|
||||
tcp_state_next = SYN_SENT_2;
|
||||
end
|
||||
end
|
||||
|
||||
SYN_SENT_2: begin
|
||||
o_tx_ctrl = TX_CTRL_SEND_ACK;
|
||||
o_tx_ctrl_valid = '1;
|
||||
|
||||
if (i_tx_ctrl_ack) begin
|
||||
tcp_state_next = ESTABLISHED;
|
||||
end
|
||||
end
|
||||
|
||||
ESTABLISHED: begin
|
||||
if (i_rx_msg_valid && i_rx_msg == RX_MSG_RECV_FIN) begin
|
||||
o_tx_ctrl = TX_CTRL_SEND_FIN;
|
||||
o_tx_ctrl_valid = '1;
|
||||
tcp_state_next = LAST_ACK;
|
||||
end
|
||||
end
|
||||
|
||||
LAST_ACK: begin
|
||||
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
131
hw/super6502_fpga/src/sub/network_processor/src/tcp_tx_ctrl.sv
Normal file
131
hw/super6502_fpga/src/sub/network_processor/src/tcp_tx_ctrl.sv
Normal file
@@ -0,0 +1,131 @@
|
||||
import tcp_pkg::*;
|
||||
|
||||
module tcp_tx_ctrl(
|
||||
input i_clk,
|
||||
input i_rst,
|
||||
|
||||
input tcp_pkg::tx_ctrl_t i_tx_ctrl,
|
||||
input logic i_tx_ctrl_valid,
|
||||
output logic o_tx_ctrl_ack,
|
||||
|
||||
output logic [15:0] o_ip_len,
|
||||
output logic [31:0] o_seq_number,
|
||||
output logic [31:0] o_ack_number,
|
||||
output logic [7:0] o_flags,
|
||||
output logic [15:0] o_window_size,
|
||||
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
|
||||
);
|
||||
|
||||
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_SYN = (1 << 1);
|
||||
localparam FLAG_RST = (1 << 2);
|
||||
localparam FLAG_PSH = (1 << 3);
|
||||
localparam FLAG_ACK = (1 << 4);
|
||||
localparam FLAG_URG = (1 << 5);
|
||||
localparam FLAG_ECE = (1 << 6);
|
||||
localparam FLAG_CWR = (1 << 7);
|
||||
|
||||
logic [31:0] seq_num, seq_num_next;
|
||||
assign o_seq_number = seq_num;
|
||||
|
||||
enum logic [2:0] {IDLE, SEND_SYN, SEND_ACK, SEND_FIN, SEND_DATA} state, state_next;
|
||||
|
||||
always_ff @(posedge i_clk) begin
|
||||
if (i_rst) begin
|
||||
state <= IDLE;
|
||||
seq_num <= '0;
|
||||
end else begin
|
||||
state <= state_next;
|
||||
seq_num <= seq_num_next;
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
state_next = state;
|
||||
|
||||
o_ack_number = '0;
|
||||
o_flags = '0;
|
||||
o_window_size = 16'b1;
|
||||
o_hdr_valid = '0;
|
||||
|
||||
seq_num_next = seq_num;
|
||||
|
||||
o_ip_len = 16'd40; // default length of IP packet
|
||||
|
||||
case (state)
|
||||
IDLE: begin
|
||||
if (i_tx_ctrl_valid) begin
|
||||
o_tx_ctrl_ack = '1;
|
||||
|
||||
case (i_tx_ctrl)
|
||||
TX_CTRL_SEND_SYN: state_next = SEND_SYN;
|
||||
TX_CTRL_SEND_ACK: state_next = SEND_ACK;
|
||||
TX_CTRL_SEND_FIN: state_next = SEND_FIN;
|
||||
endcase
|
||||
end
|
||||
|
||||
if (s_axis.tvalid) begin
|
||||
state_next = SEND_DATA;
|
||||
end
|
||||
end
|
||||
|
||||
SEND_SYN: begin
|
||||
o_flags = FLAG_SYN;
|
||||
o_hdr_valid = '1;
|
||||
|
||||
if (i_packet_done) begin
|
||||
state_next = IDLE;
|
||||
seq_num_next = seq_num + 1;
|
||||
end
|
||||
end
|
||||
|
||||
SEND_ACK: begin
|
||||
o_flags = FLAG_ACK;
|
||||
o_hdr_valid = '1;
|
||||
|
||||
if (i_packet_done) begin
|
||||
state_next = IDLE;
|
||||
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
|
||||
|
||||
SEND_FIN: begin
|
||||
o_flags = FLAG_ACK | FLAG_FIN;
|
||||
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
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
||||
13
init_env.sh
13
init_env.sh
@@ -8,12 +8,11 @@ export KICAD7_SYMBOL_DIR=$REPO_TOP/hw/kicad_library/symbols
|
||||
export KICAD7_3DMODEL_DIR=$REPO_TOP/hw/kicad_library/3dmodels
|
||||
export KICAD7_FOOTPRINT_DIR=$REPO_TOP/hw/kicad_library/footprints
|
||||
|
||||
|
||||
python3.11 -m venv .user_venv
|
||||
. .user_venv/bin/activate
|
||||
|
||||
module load efinity/2023.1
|
||||
module load iverilog/12.0
|
||||
#module load efinity/2023.1
|
||||
module load verilator
|
||||
module load gtkwave/3.3_gtk3
|
||||
|
||||
# pip install -r requirements.txt
|
||||
python3.12 -m venv .user_venv
|
||||
. .user_venv/bin/activate
|
||||
|
||||
pip install -r requirements.txt
|
||||
|
||||
Reference in New Issue
Block a user