diff --git a/.gitignore b/.gitignore
index f468ce5560c82da84e6f2c7a6ecb673368876221..cb22a9668faa741e140536647af31339a3ce8ca2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,9 +17,22 @@
 *.gtkw
 *debug_profile*
 
+# Drawio temp files.
+*.bkp
+*.dtmp
 
 *.mem
 sim_top
 
 # Allow sources.list specifically
 !*sources.list
+
+# Cocotb
+sim_build
+*.fst
+__pycache__
+*.vcd
+*.fst.*
+results.xml
+html
+*.pcapng
\ No newline at end of file
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index abf3ef9b9f9c615cded3327c2e444748aec539b1..db995ee86b813b132ced545509819c170db2a75b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -7,15 +7,20 @@ stages:
 
 build:
   stage: build
+  when: manual
   tags:
     - efinity
     - linux
   script:
-    - source init_env.sh
+    # - source init_env.sh
+    - module load efinity/2024.1
     - make
+  after_script:
+    - cat hw/super6502_fpga/outflow/super6502_fpga.err.log
 
 sim:
   stage: sim
+  needs: []
   tags:
     - linux
     - efinity
@@ -23,3 +28,18 @@ sim:
     - source init_env.sh
     - 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
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
index ef62624bf37b9d3f70a4ad72a30ae1f98b35207a..8b5ab54e5fd8af45688ce3fa7835333cbfd08f8f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -13,3 +13,15 @@
 [submodule "hw/super6502_fpga/src/sub/sdspi"]
 	path = hw/super6502_fpga/src/sub/sd_controller_wrapper/sdspi
 	url = ../sdspi.git
+[submodule "hw/super6502_fpga/src/sub/verilog-ethernet"]
+	path = hw/super6502_fpga/src/sub/verilog-ethernet
+	url = ../verilog-ethernet.git
+[submodule "hw/super6502_fpga/src/sub/stream_dmas"]
+	path = hw/super6502_fpga/src/sub/stream_dmas
+	url = ../stream_dmas.git
+[submodule "hw/super6502_fpga/src/sub/interfaces"]
+	path = hw/super6502_fpga/src/sub/interfaces
+	url = ../interfaces.git
+[submodule "hw/super6502_fpga/src/sub/my-fifos"]
+	path = hw/super6502_fpga/src/sub/my-fifos
+	url = ../my-fifos.git
diff --git a/Makefile b/Makefile
index aab0a02085fb45edc9b51c88719d9882e440eeb5..ef47ba51517f1cd21ea2276e61b9f8a8ca6ead4a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-ROM_TARGET=test_code/sd_controller_test
+ROM_TARGET=test_code/loop_test
 
 INIT_HEX=hw/super6502_fpga/init_hex.mem
 HEX=sw/$(ROM_TARGET)/$(notdir $(ROM_TARGET)).bin
@@ -26,7 +26,7 @@ $(CC65):
 	$(MAKE) -C sw/toolchain/cc65 -j $(shell nproc)
 
 $(INIT_HEX): $(CC65) script/generate_rom_image.py $(HEX)
-	python script/generate_rom_image.py -i $(HEX) -o $@
+	python3 script/generate_rom_image.py -i $(HEX) -o $@
 
 # This should get dependencies of rom, not be phony
 .PHONY: $(HEX)
diff --git a/hw/super6502_fpga/.gitignore b/hw/super6502_fpga/.gitignore
index 0af698cd684c75180634443918786ddab0852d24..7ec48121f7f57918dfad295514333431b566bae8 100644
--- a/hw/super6502_fpga/.gitignore
+++ b/hw/super6502_fpga/.gitignore
@@ -1,3 +1,4 @@
 outflow
 work_*
 .lock
+obj_dir
\ No newline at end of file
diff --git a/hw/super6502_fpga/constraints/constraints.sdc b/hw/super6502_fpga/constraints/constraints.sdc
index f294bb259279ed8699f9a8a7ab961b4ba7304011..c0f1c11a08d921b2f391979446a5ed643ad8e82e 100644
--- a/hw/super6502_fpga/constraints/constraints.sdc
+++ b/hw/super6502_fpga/constraints/constraints.sdc
@@ -2,4 +2,9 @@ create_clock -period 5.00 i_sdrclk
 create_clock -period 5.00 i_tACclk
 create_clock -period 10.00 i_sysclk
 
+create_clock -period 40.00 mii_rx_clk
+create_clock -period 40.00 mii_tx_clk
+
+set_clock_groups -exclusive -group {i_sysclk i_sdrclk i_tACclk} -group {mii_tx_clk} -group {mii_rx_clk}
+
 create_generated_clock -source i_sysclk -divide_by 50 clk_cpu
diff --git a/hw/super6502_fpga/sources.list b/hw/super6502_fpga/sources.list
index 4e453fe03e0a75702e6a4ad1c68bb4ee41cf0950..ae7fd14ecf9a28644126658288632e12b2f70986 100644
--- a/hw/super6502_fpga/sources.list
+++ b/hw/super6502_fpga/sources.list
@@ -1,35 +1,11 @@
+src/sub/interfaces/sources.list
 src/rtl/super_6502_fpga.sv
-src/sub/cpu_wrapper/cpu_wrapper.sv
-src/sub/rtl-common/src/rtl/async_fifo.sv
-src/sub/rtl-common/src/rtl/axi4_lite_ram.sv
-src/sub/rtl-common/src/rtl/axi4_lite_rom.sv
-src/sub/rtl-common/src/rtl/ff_cdc.sv
-src/sub/rtl-common/src/rtl/shallow_async_fifo.sv
-src/sub/rtl-common/src/rtl/sync_fifo.sv
-src/sub/rtl-common/src/rtl/axi4_lite_to_apb4.sv
 ip/sdram_controller/sdram_controller.v
-src/sub/wb2axip/rtl/axilxbar.v
-src/sub/wb2axip/rtl/addrdecode.v
-src/sub/wb2axip/rtl/skidbuffer.v
-src/sub/sd_controller_wrapper/sd_controller_wrapper.sv
-src/sub/sd_controller_wrapper/shadow_regs.sv
-src/sub/sd_controller_wrapper/sdspi/rtl/sdckgen.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sddma_rxgears.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sddma.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdrxframe.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdtxframe.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sddma_s2mm.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sddma_s2mm_axi.v
-src/sub/sd_controller_wrapper/sdspi/rtl/afifo.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sddma_txgears.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdskid.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdfrontend.v
-src/sub/sd_controller_wrapper/sdspi/rtl/spicmd.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdaxil.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sddma_mm2s.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sddma_mm2s_axi.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdio_top.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdwb.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdio.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdcmd.v
-src/sub/sd_controller_wrapper/sdspi/rtl/sdfifo.v
\ No newline at end of file
+src/sub/cpu_wrapper/sources.list
+src/sub/network_processor/sources.list
+src/sub/rtl-common/sources.list
+src/sub/sd_controller_wrapper/sources.list
+src/sub/wb2axip/sources.list
+src/sub/verilog-ethernet/sources.list
+src/sub/stream_dmas/sources.list
+src/sub/my-fifos/sources.list
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/rtl/super_6502_fpga.sv b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv
index 2e877f0f7a17e85c704f19ffc83d55f131640a07..908bd4ef48f8cd2dda0c6cc17834b731b9433b3d 100644
--- a/hw/super6502_fpga/src/rtl/super_6502_fpga.sv
+++ b/hw/super6502_fpga/src/rtl/super_6502_fpga.sv
@@ -43,8 +43,26 @@ module super6502_fpga(
     input                       i_sd_dat,
     output                      o_sd_dat,
     output                      o_sd_dat_oe,
-    output                      o_sd_clk
-    // input                       i_sd_cd
+    output                      o_sd_clk,
+    // input                       i_sd_cd,
+
+    //MII Interface
+    input   wire                    mii_rx_clk,
+    input   wire    [3:0]           mii_rxd,
+    input   wire                    mii_rx_dv,
+    input   wire                    mii_rx_er,
+    input   wire                    mii_tx_clk,
+    output  wire    [3:0]           mii_txd,
+    output  wire                    mii_tx_en,
+    output  wire                    mii_tx_er,
+
+    // MDIO Interface
+    input                           i_Mdi,
+    output                          o_Mdo,
+    output                          o_MdoEn,
+    output                          o_Mdc,
+
+    output                          phy_rstn
 );
 
 
@@ -73,7 +91,9 @@ assign pre_resetn = button_resetn & vio0_resetn;
 
 assign sdram_ready = |w_sdr_state;
 
-assign master_resetn = pre_resetn & sdram_ready;
+always_ff @(posedge i_sysclk) begin
+    master_resetn <= pre_resetn & sdram_ready;
+end
 
 assign o_sd_cs = '1;
 
@@ -193,11 +213,17 @@ logic                       sd_controller_dma_RREADY;
 logic  [DATA_WIDTH-1:0]     sd_controller_dma_RDATA;
 logic  [1:0]                sd_controller_dma_RRESP;
 
+axil_intf ntw_reg();
+axil_intf ntw_dma();
+
+logic cpu_wrapper_reset;
+always_ff @(posedge i_sysclk) cpu_wrapper_reset <= ~master_resetn;
+
 
 cpu_wrapper u_cpu_wrapper_0(
     .i_clk_cpu  (clk_cpu),
     .i_clk_100  (i_sysclk),
-    .i_rst      (~master_resetn),
+    .i_rst      (cpu_wrapper_reset),
 
     .o_cpu_rst  (o_cpu0_reset),
     .o_cpu_rdy  (o_cpu0_rdy),
@@ -237,64 +263,70 @@ cpu_wrapper u_cpu_wrapper_0(
     .i_nmi('0)
 );
 
+logic crossbar_resetn;
+always_ff @(posedge i_sysclk) crossbar_resetn <= master_resetn;
 
 axilxbar #(
-    .NM(2),
-    .NS(4),
+    .NM(3),
+    .NS(5),
     .SLAVE_ADDR({
         {32'h000001ff, 32'h00000000},
         {32'h0000ffff, 32'h0000f000},
         {32'h0000dfff, 32'h00000200},
-        {32'h0000e03f, 32'h0000e000}
+        {32'h0000e03f, 32'h0000e000},
+        {32'h0000e3ff, 32'h0000e200}
     })
 ) u_crossbar (
     .S_AXI_ACLK         (i_sysclk),
-    .S_AXI_ARESETN      (master_resetn),
-
-    .S_AXI_ARADDR       ({cpu0_ARADDR,  sd_controller_dma_ARADDR        }),
-    .S_AXI_ARVALID      ({cpu0_ARVALID, sd_controller_dma_ARVALID       }),
-    .S_AXI_ARREADY      ({cpu0_ARREADY, sd_controller_dma_ARREADY       }),
-    .S_AXI_RDATA        ({cpu0_RDATA,   sd_controller_dma_RDATA         }),
-    .S_AXI_RRESP        ({cpu0_RRESP,   sd_controller_dma_RRESP         }),
-    .S_AXI_RVALID       ({cpu0_RVALID,  sd_controller_dma_RVALID        }),
-    .S_AXI_RREADY       ({cpu0_RREADY,  sd_controller_dma_RREADY        }),
-    .S_AXI_AWADDR       ({cpu0_AWADDR,  sd_controller_dma_AWADDR        }),
-    .S_AXI_AWREADY      ({cpu0_AWREADY, sd_controller_dma_AWREADY       }),
-    .S_AXI_AWVALID      ({cpu0_AWVALID, sd_controller_dma_AWVALID       }),
-    .S_AXI_WVALID       ({cpu0_WVALID,  sd_controller_dma_WVALID        }),
-    .S_AXI_WREADY       ({cpu0_WREADY,  sd_controller_dma_WREADY        }),
-    .S_AXI_WDATA        ({cpu0_WDATA,   sd_controller_dma_WDATA         }),
-    .S_AXI_WSTRB        ({cpu0_WSTRB,   sd_controller_dma_WSTRB         }),
-    .S_AXI_BRESP        ({cpu0_BRESP,   sd_controller_dma_BRESP         }),
-    .S_AXI_BVALID       ({cpu0_BVALID,  sd_controller_dma_BVALID        }),
-    .S_AXI_BREADY       ({cpu0_BREADY,  sd_controller_dma_BREADY        }),
-    .M_AXI_ARADDR       ({ram_araddr,   rom_araddr,     sdram_ARADDR,   sd_controller_ctrl_ARADDR    }),
-    .M_AXI_ARVALID      ({ram_arvalid,  rom_arvalid,    sdram_ARVALID,  sd_controller_ctrl_ARVALID   }),
-    .M_AXI_ARREADY      ({ram_arready,  rom_arready,    sdram_ARREADY,  sd_controller_ctrl_ARREADY   }),
-    .M_AXI_RDATA        ({ram_rdata,    rom_rdata,      sdram_RDATA,    sd_controller_ctrl_RDATA     }),
-    .M_AXI_RRESP        ({ram_rresp,    rom_rresp,      sdram_RRESP,    sd_controller_ctrl_RRESP     }),
-    .M_AXI_RVALID       ({ram_rvalid,   rom_rvalid,     sdram_RVALID,   sd_controller_ctrl_RVALID    }),
-    .M_AXI_RREADY       ({ram_rready,   rom_rready,     sdram_RREADY,   sd_controller_ctrl_RREADY    }),
-    .M_AXI_AWADDR       ({ram_awaddr,   rom_awaddr,     sdram_AWADDR,   sd_controller_ctrl_AWADDR    }),
-    .M_AXI_AWVALID      ({ram_awvalid,  rom_awvalid,    sdram_AWVALID,  sd_controller_ctrl_AWVALID   }),
-    .M_AXI_AWREADY      ({ram_awready,  rom_awready,    sdram_AWREADY,  sd_controller_ctrl_AWREADY   }),
-    .M_AXI_WDATA        ({ram_wdata,    rom_wdata,      sdram_WDATA,    sd_controller_ctrl_WDATA     }),
-    .M_AXI_WVALID       ({ram_wvalid,   rom_wvalid,     sdram_WVALID,   sd_controller_ctrl_WVALID    }),
-    .M_AXI_WREADY       ({ram_wready,   rom_wready,     sdram_WREADY,   sd_controller_ctrl_WREADY    }),
-    .M_AXI_WSTRB        ({ram_wstrb,    rom_wstrb,      sdram_WSTRB,    sd_controller_ctrl_WSTRB     }),
-    .M_AXI_BRESP        ({ram_bresp,    rom_bresp,      sdram_BRESP,    sd_controller_ctrl_BRESP     }),
-    .M_AXI_BVALID       ({ram_bvalid,   rom_bvalid,     sdram_BVALID,   sd_controller_ctrl_BVALID    }),
-    .M_AXI_BREADY       ({ram_bready,   rom_bready,     sdram_BREADY,   sd_controller_ctrl_BREADY    })
+    .S_AXI_ARESETN      (crossbar_resetn),
+
+    .S_AXI_ARADDR       ({cpu0_ARADDR,  sd_controller_dma_ARADDR,       ntw_dma.araddr  }),
+    .S_AXI_ARVALID      ({cpu0_ARVALID, sd_controller_dma_ARVALID,      ntw_dma.arvalid }),
+    .S_AXI_ARREADY      ({cpu0_ARREADY, sd_controller_dma_ARREADY,      ntw_dma.arready }),
+    .S_AXI_RDATA        ({cpu0_RDATA,   sd_controller_dma_RDATA,        ntw_dma.rdata   }),
+    .S_AXI_RRESP        ({cpu0_RRESP,   sd_controller_dma_RRESP,        ntw_dma.rresp   }),
+    .S_AXI_RVALID       ({cpu0_RVALID,  sd_controller_dma_RVALID,       ntw_dma.rvalid  }),
+    .S_AXI_RREADY       ({cpu0_RREADY,  sd_controller_dma_RREADY,       ntw_dma.rready  }),
+    .S_AXI_AWADDR       ({cpu0_AWADDR,  sd_controller_dma_AWADDR,       ntw_dma.awaddr  }),
+    .S_AXI_AWVALID      ({cpu0_AWVALID, sd_controller_dma_AWVALID,      ntw_dma.awvalid }),
+    .S_AXI_AWREADY      ({cpu0_AWREADY, sd_controller_dma_AWREADY,      ntw_dma.awready }),
+    .S_AXI_WVALID       ({cpu0_WVALID,  sd_controller_dma_WVALID,       ntw_dma.wvalid  }),
+    .S_AXI_WDATA        ({cpu0_WDATA,   sd_controller_dma_WDATA,        ntw_dma.wdata   }),
+    .S_AXI_WREADY       ({cpu0_WREADY,  sd_controller_dma_WREADY,       ntw_dma.wready  }),
+    .S_AXI_WSTRB        ({cpu0_WSTRB,   sd_controller_dma_WSTRB,        ntw_dma.wstrb   }),
+    .S_AXI_BRESP        ({cpu0_BRESP,   sd_controller_dma_BRESP,        ntw_dma.bresp   }),
+    .S_AXI_BVALID       ({cpu0_BVALID,  sd_controller_dma_BVALID,       ntw_dma.bvalid  }),
+    .S_AXI_BREADY       ({cpu0_BREADY,  sd_controller_dma_BREADY,       ntw_dma.bready  }),
+    .M_AXI_ARADDR       ({ram_araddr,   rom_araddr,     sdram_ARADDR,   sd_controller_ctrl_ARADDR,  ntw_reg.araddr  }),
+    .M_AXI_ARVALID      ({ram_arvalid,  rom_arvalid,    sdram_ARVALID,  sd_controller_ctrl_ARVALID, ntw_reg.arvalid }),
+    .M_AXI_ARREADY      ({ram_arready,  rom_arready,    sdram_ARREADY,  sd_controller_ctrl_ARREADY, ntw_reg.arready }),
+    .M_AXI_RDATA        ({ram_rdata,    rom_rdata,      sdram_RDATA,    sd_controller_ctrl_RDATA,   ntw_reg.rdata   }),
+    .M_AXI_RRESP        ({ram_rresp,    rom_rresp,      sdram_RRESP,    sd_controller_ctrl_RRESP,   ntw_reg.rresp   }),
+    .M_AXI_RVALID       ({ram_rvalid,   rom_rvalid,     sdram_RVALID,   sd_controller_ctrl_RVALID,  ntw_reg.rvalid  }),
+    .M_AXI_RREADY       ({ram_rready,   rom_rready,     sdram_RREADY,   sd_controller_ctrl_RREADY,  ntw_reg.rready  }),
+    .M_AXI_AWADDR       ({ram_awaddr,   rom_awaddr,     sdram_AWADDR,   sd_controller_ctrl_AWADDR,  ntw_reg.awaddr  }),
+    .M_AXI_AWVALID      ({ram_awvalid,  rom_awvalid,    sdram_AWVALID,  sd_controller_ctrl_AWVALID, ntw_reg.awvalid }),
+    .M_AXI_AWREADY      ({ram_awready,  rom_awready,    sdram_AWREADY,  sd_controller_ctrl_AWREADY, ntw_reg.awready }),
+    .M_AXI_WDATA        ({ram_wdata,    rom_wdata,      sdram_WDATA,    sd_controller_ctrl_WDATA,   ntw_reg.wdata   }),
+    .M_AXI_WVALID       ({ram_wvalid,   rom_wvalid,     sdram_WVALID,   sd_controller_ctrl_WVALID,  ntw_reg.wvalid  }),
+    .M_AXI_WREADY       ({ram_wready,   rom_wready,     sdram_WREADY,   sd_controller_ctrl_WREADY,  ntw_reg.wready  }),
+    .M_AXI_WSTRB        ({ram_wstrb,    rom_wstrb,      sdram_WSTRB,    sd_controller_ctrl_WSTRB,   ntw_reg.wstrb   }),
+    .M_AXI_BRESP        ({ram_bresp,    rom_bresp,      sdram_BRESP,    sd_controller_ctrl_BRESP,   ntw_reg.bresp   }),
+    .M_AXI_BVALID       ({ram_bvalid,   rom_bvalid,     sdram_BVALID,   sd_controller_ctrl_BVALID,  ntw_reg.bvalid  }),
+    .M_AXI_BREADY       ({ram_bready,   rom_bready,     sdram_BREADY,   sd_controller_ctrl_BREADY,  ntw_reg.bready  })
 
 );
 
+logic rom_reset;
+always_ff @(posedge i_sysclk) rom_reset <= ~master_resetn;
+
 axi4_lite_rom #(
     .ROM_SIZE(12),
     .BASE_ADDRESS(32'h0000f000),
     .ROM_INIT_FILE("init_hex.mem")
 ) u_rom (
     .i_clk(i_sysclk),
-    .i_rst(~master_resetn),
+    .i_rst(rom_reset),
 
     .o_AWREADY(rom_awready),
     .o_WREADY(rom_wready),
@@ -322,12 +354,15 @@ axi4_lite_rom #(
     .i_WSTRB(rom_wstrb)
 );
 
+logic ram_reset;
+always_ff @(posedge i_sysclk) ram_reset <= ~master_resetn;
+
 axi4_lite_ram #(
     .RAM_SIZE(9),
     .ZERO_INIT(1)
 ) u_ram(
     .i_clk(i_sysclk),
-    .i_rst(~master_resetn),
+    .i_rst(ram_reset),
 
     .o_AWREADY(ram_awready),
     .o_WREADY(ram_wready),
@@ -430,12 +465,15 @@ sdram_controller u_sdram_controller(
 
 logic sd_irq;
 
+logic sd_controller_wrapper_reset;
+always_ff @(posedge i_sysclk) sd_controller_wrapper_reset <= ~master_resetn;
+
 sd_controller_wrapper #(
     .NUMIO              (1),   // board as it stands is in 1 bit mode
     .BASE_ADDRESS       (32'h0000E000)
 ) u_sdio_top (
     .i_clk              (i_sysclk),
-    .i_reset            (~master_resetn),
+    .i_reset            (sd_controller_wrapper_reset),
 
     .S_AXIL_AWVALID     (sd_controller_ctrl_AWVALID),
     .S_AXIL_AWREADY     (sd_controller_ctrl_AWREADY),
@@ -484,4 +522,33 @@ sd_controller_wrapper #(
     .o_int              (sd_irq)
 );
 
-endmodule
\ No newline at end of file
+logic network_processor_reset;
+always_ff @(posedge i_sysclk) network_processor_reset <= ~master_resetn;
+
+network_processor #(
+    .NUM_TCP(2)
+) u_network_processor (
+    .i_clk              (i_sysclk),
+    .i_rst              (network_processor_reset),
+
+    .s_reg_axil         (ntw_reg),
+    .m_dma_axil         (ntw_dma),
+
+    .mii_rx_clk         (mii_rx_clk),
+    .mii_rxd            (mii_rxd),
+    .mii_rx_dv          (mii_rx_dv),
+    .mii_rx_er          (mii_rx_er),
+    .mii_tx_clk         (mii_tx_clk),
+    .mii_txd            (mii_txd),
+    .mii_tx_en          (mii_tx_en),
+    .mii_tx_er          (mii_tx_er),
+
+    .i_Mdi              (i_Mdi),
+    .o_Mdo              (o_Mdo),
+    .o_MdoEn            (o_MdoEn),
+    .o_Mdc              (o_Mdc),
+
+    .phy_rstn           (phy_rstn)
+);
+
+endmodule
diff --git a/hw/super6502_fpga/src/sim/Makefile b/hw/super6502_fpga/src/sim/Makefile
index e1930d4b806a272aee489529bfc3c7b1124a7fcf..413056d29f99b3d6b11dd4c2f83f30f39efbd1e7 100644
--- a/hw/super6502_fpga/src/sim/Makefile
+++ b/hw/super6502_fpga/src/sim/Makefile
@@ -1,25 +1,34 @@
 FPGA_SRCS_LIST=../../sources.list
 SIM_SRCS_LIST=sources.list
+BAD_SOURCES_LIST=stubs.list
 
-SUPER6502_FPGA_SOURCES=$(foreach file, $(shell cat $(FPGA_SRCS_LIST)), ../../$(file))
+SUPER6502_FPGA_SOURCES=$(shell rtl-manifest $(FPGA_SRCS_LIST))
+BAD_SOURCES=$(shell rtl-manifest $(BAD_SOURCES_LIST))
+GOOD_FPGA_SOURCES=$(filter-out $(BAD_SOURCES), $(SUPER6502_FPGA_SOURCES))
 SIM_SOURCES=$(shell cat $(SIM_SRCS_LIST))
 
 INCLUDE=include/sdram_controller_define.vh
 
-TB_NAME=sim_top
+TB_NAME=./obj_dir/Vsim_top
 
 COPY_FILES=addr_map.mem init_hex.mem
 SD_IMAGE=sd_image.bin
 
 FLAGS=-DSIM -DRTL_SIM -DVERILATOR -DSDIO_AXI
 
+# IVERILOG=$(REPO_TOP)/../iverilog/local/bin/iverilog -v
+IVERILOG=iverilog
+
 all: waves
 
 waves: $(TB_NAME)
-	./$(TB_NAME) -fst
+#	./$(TB_NAME) -fst
+	./obj_dir/Vsim_top
 
 $(TB_NAME): $(SUPER6502_FPGA_SOURCES) $(SIM_SOURCES) $(COPY_FILES) $(SD_IMAGE)
-	iverilog -g2005-sv $(FLAGS) -s $@ -o $@ $(INCLUDE) $(SUPER6502_FPGA_SOURCES) $(SIM_SOURCES) -I ../../
+# $(IVERILOG) -g2005-sv $(FLAGS) -s $@ -o $@ $(INCLUDE) $(SUPER6502_FPGA_SOURCES) $(SIM_SOURCES) -I ../../
+	verilator --binary $(FLAGS) $(INCLUDE) $(GOOD_FPGA_SOURCES) $(SIM_SOURCES) +incdir+../../ -Wno-BLKANDNBLK -Wno-fatal -j 16 --top sim_top --trace-fst -Wno-ASSIGNDLY
+
 
 $(SD_IMAGE):
 	dd if=/dev/urandom bs=1 count=65536 of=$(SD_IMAGE)
@@ -34,3 +43,4 @@ clean:
 	rm -rf $(COPY_FILES)
 	rm -rf $(TB_NAME)
 	rm -rf sim_top.vcd
+	rm -rf obj_dir
diff --git a/hw/super6502_fpga/src/sim/hvl/sdram_sram.sv b/hw/super6502_fpga/src/sim/hvl/sdram_sram.sv
new file mode 100644
index 0000000000000000000000000000000000000000..2ae4845f9bbe35e954c7201abf774af771a0d158
--- /dev/null
+++ b/hw/super6502_fpga/src/sim/hvl/sdram_sram.sv
@@ -0,0 +1,105 @@
+module sdram_controller (
+    input i_aresetn,
+    input i_sysclk,
+    input i_sdrclk,
+    input i_tACclk,
+
+    output o_pll_reset,
+    input i_pll_locked,
+
+    output o_sdr_state,
+
+    input i_AXI4_AWVALID,
+    output o_AXI4_AWREADY,
+    input [23:0] i_AXI4_AWADDR,
+    input i_AXI4_WVALID,
+    output o_AXI4_WREADY,
+    input [31:0] i_AXI4_WDATA,
+    input [3:0] i_AXI4_WSTRB,
+    output o_AXI4_BVALID,
+    input i_AXI4_BREADY,
+    input i_AXI4_ARVALID,
+    output o_AXI4_ARREADY,
+    input [23:0] i_AXI4_ARADDR,
+    output o_AXI4_RVALID,
+    input i_AXI4_RREADY,
+    output [31:0] o_AXI4_RDATA,
+
+    input i_AXI4_WLAST,
+    output o_AXI4_RLAST,
+    input [3:0] i_AXI4_AWID,
+    input [2:0] i_AXI4_AWSIZE,
+    input [3:0] i_AXI4_ARID,
+    input [7:0] i_AXI4_ARLEN,
+    input [2:0] i_AXI4_ARSIZE,
+    input [1:0] i_AXI4_ARBURST,
+    input [7:0] i_AXI4_AWLEN,
+    output [3:0] o_AXI4_RID,
+    output [3:0] o_AXI4_BID,
+
+    output [1:0] o_sdr_CKE,
+    output [1:0] o_sdr_n_CS,
+    output [1:0] o_sdr_n_RAS,
+    output [1:0] o_sdr_n_CAS,
+    output [1:0] o_sdr_n_WE,
+    output [3:0] o_sdr_BA,
+    output [25:0] o_sdr_ADDR,
+    output [31:0] o_sdr_DATA,
+    output [31:0] o_sdr_DATA_oe,
+    input [31:0] i_sdr_DATA,
+    output [3:0] o_sdr_DQM
+);
+
+assign o_sdr_state	= '1;
+
+assign o_AXI4_RLAST 	= '0;
+assign o_AXI4_RID 	= '0;
+assign o_AXI4_BID 	= '0;
+
+assign o_sdr_CKE 	= '0;
+assign o_sdr_n_CS 	= '0;
+assign o_sdr_n_RAS 	= '0;
+assign o_sdr_n_CAS 	= '0;
+assign o_sdr_n_WE 	= '0;
+assign o_sdr_BA 	= '0;
+assign o_sdr_ADDR 	= '0;
+assign o_sdr_DATA 	= '0;
+assign o_sdr_DATA_oe 	= '0;
+assign o_sdr_DQM 	= '0;
+
+
+axi4_lite_ram #(
+    .RAM_SIZE(25),
+    .ZERO_INIT(1)
+) u_sdram_emu (
+    .i_clk(i_sysclk),
+    .i_rst(~i_aresetn),
+
+    .o_AWREADY(o_AXI4_AWREADY),
+    .o_WREADY(o_AXI4_WREADY),
+
+    .o_BVALID(o_AXI4_BVALID),
+    .i_BREADY(i_AXI4_BREADY),
+    .o_BRESP(o_BRESP),
+
+    .i_ARVALID(i_AXI4_ARVALID),
+    .o_ARREADY(o_AXI4_ARREADY),
+    .i_ARADDR(i_AXI4_ARADDR),
+    .i_ARPROT('0),
+    
+    .o_RVALID(o_AXI4_RVALID),
+    .i_RREADY(i_AXI4_RREADY),
+    .o_RDATA(o_AXI4_RDATA),
+    .o_RRESP(o_AXI4_RRESP),
+
+    .i_AWVALID(i_AXI4_AWVALID),
+    .i_AWADDR(i_AXI4_AWADDR),
+    .i_AWPROT('0),
+
+    .i_WVALID(i_AXI4_WVALID),
+    .i_WDATA(i_AXI4_WDATA),
+    .i_WSTRB(i_AXI4_WSTRB)
+);
+
+
+endmodule
diff --git a/hw/super6502_fpga/src/sim/hvl/sim_top.sv b/hw/super6502_fpga/src/sim/hvl/sim_top.sv
index 35db4bba68ca66ba313115eb277cd039c1ada4fe..f774e93e3470462c13f329991a3435a0e6fde8e1 100644
--- a/hw/super6502_fpga/src/sim/hvl/sim_top.sv
+++ b/hw/super6502_fpga/src/sim/hvl/sim_top.sv
@@ -87,6 +87,7 @@ logic   [DQ_GROUP				-1:0]   w_sdr_DQM;
 wire    [DQ_GROUP	*DQ_WIDTH	-1:0]   w_sdr_DQ;
 // ^ Has to be wire because of tristate/inout stuff
 
+/*
 genvar i, j;
 generate
     for (i=0; i<DQ_GROUP*DQ_WIDTH; i=i+1)
@@ -111,7 +112,7 @@ generate
         );
     end
 endgenerate
-
+*/
 
 // potential sd card sim here?
 
@@ -179,13 +180,15 @@ IOBUF dat_buf (
     .IO(w_sd_dat)
 );
 
+wire [2:0] w_sd_dat_unused;
+
 mdl_sdio #(
     .LGMEMSZ(16),
     .MEMFILE("sd_image.bin")
 ) u_sd_card_emu (
     .sd_clk(o_sd_clk),
     .sd_cmd(w_sd_cmd),
-    .sd_dat(w_sd_dat)
+    .sd_dat({w_sd_dat_unused, w_sd_dat})
 );
 
 initial begin
@@ -198,4 +201,4 @@ initial begin
     $finish();
 end
 
-endmodule
\ No newline at end of file
+endmodule
diff --git a/hw/super6502_fpga/src/sim/sources.list b/hw/super6502_fpga/src/sim/sources.list
index 6ea37838ec35a44c6558d07ba17f7892b51988ad..2fb4de4957b63c5d2801c1f86a2c9f75c464d658 100644
--- a/hw/super6502_fpga/src/sim/sources.list
+++ b/hw/super6502_fpga/src/sim/sources.list
@@ -1,9 +1,9 @@
 hvl/sim_top.sv
 sub/verilog-6502/ALU.v
 sub/verilog-6502/cpu_65c02.v
-sub/sim_sdram/generic_sdr.v
+hvl/sdram_sram.sv
 ../sub/sd_controller_wrapper/sdspi/bench/verilog/mdl_sdio.v
 ../sub/sd_controller_wrapper/sdspi/bench/verilog/mdl_sdcmd.v
 ../sub/sd_controller_wrapper/sdspi/bench/verilog/mdl_sdrx.v
 ../sub/sd_controller_wrapper/sdspi/bench/verilog/mdl_sdtx.v
-../sub/sd_controller_wrapper/sdspi/bench/verilog/IOBUF.v
\ No newline at end of file
+../sub/sd_controller_wrapper/sdspi/bench/verilog/IOBUF.v
diff --git a/hw/super6502_fpga/src/sim/stubs.list b/hw/super6502_fpga/src/sim/stubs.list
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/hw/super6502_fpga/src/sim/sub/sim_sdram/generic_sdr.v b/hw/super6502_fpga/src/sim/sub/sim_sdram/generic_sdr.v
index aaa53f799e8ba6aca4832249e312098dc1f9b7b6..de74693a1dd6c95f4b79c0423ea50cb81d5da8c2 100644
--- a/hw/super6502_fpga/src/sim/sub/sim_sdram/generic_sdr.v
+++ b/hw/super6502_fpga/src/sim/sub/sim_sdram/generic_sdr.v
@@ -1127,19 +1127,19 @@ parameter mem_sizes        = 2**(ROW_BITS+COL_BITS) - 1;
             tCMS =  1.5,                                        // CS#, RAS#, CAS#, WE#, DQM# Setup Time
             tDH  =  0.8,                                        // Data-in Hold Time
             tDS  =  1.5;                                        // Data-in Setup Time
-        $width    (posedge Clk,           tCH);
-        $width    (negedge Clk,           tCL);
-        $period   (negedge Clk,           tCK3);
-        $period   (posedge Clk,           tCK3);
-        $setuphold(posedge Clk,    Cke,   tCKS, tCKH);
-        $setuphold(posedge Clk,    Cs_n,  tCMS, tCMH);
-        $setuphold(posedge Clk,    Cas_n, tCMS, tCMH);
-        $setuphold(posedge Clk,    Ras_n, tCMS, tCMH);
-        $setuphold(posedge Clk,    We_n,  tCMS, tCMH);
-        $setuphold(posedge Clk,    Addr,  tAS,  tAH);
-        $setuphold(posedge Clk,    Ba,    tAS,  tAH);
-        $setuphold(posedge Clk,    Dqm,   tCMS, tCMH);
-        $setuphold(posedge Dq_chk, Dq,    tDS,  tDH);
+        // $width    (posedge Clk,           tCH);
+        // $width    (negedge Clk,           tCL);
+        // $period   (negedge Clk,           tCK3);
+        // $period   (posedge Clk,           tCK3);
+        // $setuphold(posedge Clk,    Cke,   tCKS, tCKH);
+        // $setuphold(posedge Clk,    Cs_n,  tCMS, tCMH);
+        // $setuphold(posedge Clk,    Cas_n, tCMS, tCMH);
+        // $setuphold(posedge Clk,    Ras_n, tCMS, tCMH);
+        // $setuphold(posedge Clk,    We_n,  tCMS, tCMH);
+        // $setuphold(posedge Clk,    Addr,  tAS,  tAH);
+        // $setuphold(posedge Clk,    Ba,    tAS,  tAH);
+        // $setuphold(posedge Clk,    Dqm,   tCMS, tCMH);
+        // $setuphold(posedge Dq_chk, Dq,    tDS,  tDH);
     endspecify
 
 endmodule
diff --git a/hw/super6502_fpga/src/sim/sub/sim_sdram/generic_sdr_stub.v b/hw/super6502_fpga/src/sim/sub/sim_sdram/generic_sdr_stub.v
new file mode 100644
index 0000000000000000000000000000000000000000..be406253830c2897250180710404ad6881002ab1
--- /dev/null
+++ b/hw/super6502_fpga/src/sim/sub/sim_sdram/generic_sdr_stub.v
@@ -0,0 +1,106 @@
+/**************************************************************************
+*
+*    File Name:  sdr.v  
+*      Version:  2.2
+*         Date:  October 12th, 2010
+*        Model:  BUS Functional
+*    Simulator:  Model Technology
+*
+* Dependencies:  None
+*
+*        Email:  modelsupport@micron.com
+*      Company:  Micron Technology, Inc.
+*
+*  Description:  Micron SDRAM Verilog model
+*
+*   Limitation:  - Doesn't check for refresh timing
+*
+*         Note:  - Set simulator resolution to "ps" accuracy
+*                - Set Debug = 0 to disable $display messages
+*
+*   Disclaimer:  THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY 
+*                WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY 
+*                IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
+*                A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
+*
+*                Copyright � 2001 Micron Semiconductor Products, Inc.
+*                All rights researved
+*
+* Rev  Author          Date        Changes
+* ---  --------------------------  ---------------------------------------
+* 2.3  SH              05/12/2016  - Update tAC, tHZ timing
+*      Micron Technology Inc.
+*
+* 2.2  SH              10/12/2010  - Combine all parts into sdr_parameters.vh
+*      Micron Technology Inc.
+*
+* 2.1  SH              06/06/2002  - Typo in bank multiplex
+*      Micron Technology Inc.
+*
+* 2.0  SH              04/30/2002  - Second release
+*      Micron Technology Inc.
+*
+**************************************************************************/
+
+`timescale 1ns / 1ps
+`define x8
+`define CLK_200
+`define SYS_CLK_100
+
+module generic_sdr (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
+	
+`include "include/sdram_controller_define.vh"
+
+parameter tCK              =     1000/fCK_MHz; // tCK    ns    Nominal Clock Cycle Time
+`ifdef CLK_200
+    parameter real tAC3             =     4.5; // tAC3   ns    Access time from CLK (pos edge) CL = 3
+    parameter real tAC2             =     4.5; // tAC2   ns    Access time from CLK (pos edge) CL = 2
+    parameter real tAC1             =     4.5; // tAC1   ns    Parameter definition for compilation - CL = 1 illegal for sg75
+`elsif CLK_166
+    parameter real tAC3             =     5.4; // tAC3   ns    Access time from CLK (pos edge) CL = 3
+    parameter real tAC2             =     5.4; // tAC2   ns    Access time from CLK (pos edge) CL = 2
+    parameter real tAC1             =     5.4; // tAC1   ns    Parameter definition for compilation - CL = 1 illegal for sg75
+`elsif CLK_133
+    parameter real tAC3             =     6.0; // tAC3   ns    Access time from CLK (pos edge) CL = 3
+    parameter real tAC2             =     6.0; // tAC2   ns    Access time from CLK (pos edge) CL = 2
+    parameter real tAC1             =     6.0; // tAC1   ns    Parameter definition for compilation - CL = 1 illegal for sg75
+`endif    
+    
+`ifdef CLK_200
+    parameter real tHZ3             =     4.5; // tHZ3   ns    Data Out High Z time - CL = 3
+    parameter real tHZ2             =     4.5; // tHZ2   ns    Data Out High Z time - CL = 2
+    parameter real tHZ1             =     4.5; // tHZ1   ns    Parameter definition for compilation - CL = 1 illegal for sg75
+`elsif CLK_166
+    parameter real tHZ3             =     5.4; // tHZ3   ns    Data Out High Z time - CL = 3
+    parameter real tHZ2             =     5.4; // tHZ2   ns    Data Out High Z time - CL = 2
+    parameter real tHZ1             =     5.4; // tHZ1   ns    Parameter definition for compilation - CL = 1 illegal for sg75
+`elsif CLK_133
+    parameter real tHZ3             =     6.0; // tHZ3   ns    Data Out High Z time - CL = 3
+    parameter real tHZ2             =     6.0; // tHZ2   ns    Data Out High Z time - CL = 2
+    parameter real tHZ1             =     6.0; // tHZ1   ns    Parameter definition for compilation - CL = 1 illegal for sg75
+`endif
+
+parameter tOH              =     2.7; // tOH    ns    Data Out Hold time
+parameter tRRD             =     2.0; // tRRD   tCK   Active bank a to Active bank b command time (2 * tCK)
+parameter tWRa             =     tCK; // tWR    ns    Write recovery time (auto-precharge mode - must add 1 CLK)
+parameter tWRm             =   2*tCK; // tWR    ns    Write recovery time	
+parameter ADDR_BITS        = ROW_WIDTH; // Set this parameter to control how many Address bits are used
+parameter ROW_BITS         = ROW_WIDTH; // Set this parameter to control how many Row bits are used
+parameter COL_BITS         = COL_WIDTH; // Set this parameter to control how many Column bits are used
+parameter DQ_BITS          = DQ_WIDTH; // Set this parameter to control how many Data bits are used
+parameter DM_BITS          = 1; // Set this parameter to control how many DM bits are used
+parameter BA_BITS          = BA_WIDTH; // Bank bits
+parameter mem_sizes        = 2**(ROW_BITS+COL_BITS) - 1;
+
+    input                         Clk;
+    input                         Cke;
+    input                         Cs_n;
+    input                         Ras_n;
+    input                         Cas_n;
+    input                         We_n;
+    input     [ADDR_BITS - 1 : 0] Addr;
+    input       [BA_BITS - 1 : 0] Ba;
+    inout       [DQ_BITS - 1 : 0] Dq;
+    input       [DM_BITS - 1 : 0] Dqm;
+
+endmodule
diff --git a/hw/super6502_fpga/src/sub/cpu_wrapper/sources.list b/hw/super6502_fpga/src/sub/cpu_wrapper/sources.list
new file mode 100644
index 0000000000000000000000000000000000000000..2de578c18b86558a4563e72b3cb8e0f3c9df0db5
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/cpu_wrapper/sources.list
@@ -0,0 +1 @@
+cpu_wrapper.sv
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/interfaces b/hw/super6502_fpga/src/sub/interfaces
new file mode 160000
index 0000000000000000000000000000000000000000..e3c55d1bb224762384ca97ada087d3f606ac8990
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/interfaces
@@ -0,0 +1 @@
+Subproject commit e3c55d1bb224762384ca97ada087d3f606ac8990
diff --git a/hw/super6502_fpga/src/sub/my-fifos b/hw/super6502_fpga/src/sub/my-fifos
new file mode 160000
index 0000000000000000000000000000000000000000..8d960ab4bfa1a49a00594d7ee89c4d874ccd55cc
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/my-fifos
@@ -0,0 +1 @@
+Subproject commit 8d960ab4bfa1a49a00594d7ee89c4d874ccd55cc
diff --git a/hw/super6502_fpga/src/sub/network_processor/doc/network_processor.drawio b/hw/super6502_fpga/src/sub/network_processor/doc/network_processor.drawio
new file mode 100644
index 0000000000000000000000000000000000000000..c9ab32c2ddd26a96bcc6ea2a3e6aa21e8866d90f
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/doc/network_processor.drawio
@@ -0,0 +1,164 @@
+<mxfile host="Electron" modified="2024-08-20T05:13:27.279Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.2.8 Chrome/112.0.5615.165 Electron/24.2.0 Safari/537.36" etag="ixB1A9XLpoNPfgontKOY" version="21.2.8" type="device">
+  <diagram name="Page-1" id="6PukHK6WJVPqU_tSf8UC">
+    <mxGraphModel dx="708" dy="486" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
+      <root>
+        <mxCell id="0" />
+        <mxCell id="1" parent="0" />
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-2" target="xWUiTusR7ZZWym1XTSiP-20">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-2" value="TCP" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="560" y="360" width="160" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#d80073;strokeColor=#A50040;startArrow=classic;startFill=1;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-3" target="xWUiTusR7ZZWym1XTSiP-4">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#d80073;strokeColor=#A50040;startArrow=classic;startFill=1;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-3" target="xWUiTusR7ZZWym1XTSiP-2">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#d80073;strokeColor=#A50040;startArrow=classic;startFill=1;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-3" target="xWUiTusR7ZZWym1XTSiP-5">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-3" value="axi4 xbar" style="shape=trapezoid;perimeter=trapezoidPerimeter;whiteSpace=wrap;html=1;fixedSize=1;rotation=-90;" vertex="1" parent="1">
+          <mxGeometry x="360" y="500" width="120" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-4" target="xWUiTusR7ZZWym1XTSiP-20">
+          <mxGeometry relative="1" as="geometry">
+            <Array as="points">
+              <mxPoint x="750" y="500" />
+              <mxPoint x="750" y="410" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-4" value="UDP" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="560" y="480" width="160" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-33" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-5" target="xWUiTusR7ZZWym1XTSiP-20">
+          <mxGeometry relative="1" as="geometry">
+            <Array as="points">
+              <mxPoint x="760" y="620" />
+              <mxPoint x="760" y="440" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-5" value="Other IP Type" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="560" y="600" width="160" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fillColor=#e3c800;strokeColor=#B09500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-10" target="xWUiTusR7ZZWym1XTSiP-54">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-10" value="MAC" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
+          <mxGeometry x="1160" y="480" width="80" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-15" target="xWUiTusR7ZZWym1XTSiP-21">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-15" value="IP" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="920" y="480" width="80" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-20" target="xWUiTusR7ZZWym1XTSiP-15">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-20" value="ip arb" style="shape=trapezoid;perimeter=trapezoidPerimeter;whiteSpace=wrap;html=1;fixedSize=1;rotation=90;" vertex="1" parent="1">
+          <mxGeometry x="800" y="390" width="120" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-21" target="xWUiTusR7ZZWym1XTSiP-5">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-21" target="xWUiTusR7ZZWym1XTSiP-2">
+          <mxGeometry relative="1" as="geometry">
+            <Array as="points">
+              <mxPoint x="810" y="600" />
+              <mxPoint x="810" y="420" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-31" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.75;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;fillColor=#fa6800;strokeColor=#C73500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-21" target="xWUiTusR7ZZWym1XTSiP-4">
+          <mxGeometry relative="1" as="geometry">
+            <Array as="points">
+              <mxPoint x="800" y="630" />
+              <mxPoint x="800" y="540" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-21" value="ip demux" style="shape=trapezoid;perimeter=trapezoidPerimeter;whiteSpace=wrap;html=1;fixedSize=1;rotation=90;" vertex="1" parent="1">
+          <mxGeometry x="800" y="610" width="120" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-58" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#008a00;strokeColor=#005700;exitX=1;exitY=0.25;exitDx=0;exitDy=0;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-15" target="xWUiTusR7ZZWym1XTSiP-53">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="1120" y="500" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-43" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#d80073;strokeColor=#A50040;" edge="1" parent="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="560" y="760" as="sourcePoint" />
+            <mxPoint x="640.03" y="760" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-44" value="axi4-lite" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xWUiTusR7ZZWym1XTSiP-43">
+          <mxGeometry x="0.2037" y="2" relative="1" as="geometry">
+            <mxPoint x="-8" y="-8" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-45" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;" edge="1" parent="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="680" y="760" as="sourcePoint" />
+            <mxPoint x="760.03" y="760" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-46" value="axi4-stream" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xWUiTusR7ZZWym1XTSiP-45">
+          <mxGeometry x="0.2037" y="2" relative="1" as="geometry">
+            <mxPoint x="-8" y="-8" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-47" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="800.03" y="760" as="sourcePoint" />
+            <mxPoint x="880.03" y="760" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-48" value="arp" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xWUiTusR7ZZWym1XTSiP-47">
+          <mxGeometry x="0.2037" y="2" relative="1" as="geometry">
+            <mxPoint x="-8" y="-8" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-49" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#fa6800;strokeColor=#C73500;" edge="1" parent="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="920.03" y="760" as="sourcePoint" />
+            <mxPoint x="1000.03" y="760" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-50" value="ip-stream" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xWUiTusR7ZZWym1XTSiP-49">
+          <mxGeometry x="0.2037" y="2" relative="1" as="geometry">
+            <mxPoint x="-8" y="-8" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-51" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#008a00;strokeColor=#005700;" edge="1" parent="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="1040" y="760" as="sourcePoint" />
+            <mxPoint x="1120" y="760" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-52" value="eth-stream" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="xWUiTusR7ZZWym1XTSiP-51">
+          <mxGeometry x="0.2037" y="2" relative="1" as="geometry">
+            <mxPoint x="-8" y="-8" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-60" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;fillColor=#e3c800;strokeColor=#B09500;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-53" target="xWUiTusR7ZZWym1XTSiP-10">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-53" value="eth_axis_tx" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="1040" y="480" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-59" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.75;entryDx=0;entryDy=0;fillColor=#008a00;strokeColor=#005700;" edge="1" parent="1" source="xWUiTusR7ZZWym1XTSiP-54" target="xWUiTusR7ZZWym1XTSiP-15">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="1120" y="540" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="xWUiTusR7ZZWym1XTSiP-54" value="eth_axis_rx" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
+          <mxGeometry x="1040" y="520" width="80" height="40" as="geometry" />
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+</mxfile>
diff --git a/hw/super6502_fpga/src/sub/network_processor/doc/network_processor.drawio.png b/hw/super6502_fpga/src/sub/network_processor/doc/network_processor.drawio.png
new file mode 100644
index 0000000000000000000000000000000000000000..83fc4013f6d2c39a6a3713c2e7bda1dfe29f04ba
Binary files /dev/null and b/hw/super6502_fpga/src/sub/network_processor/doc/network_processor.drawio.png differ
diff --git a/hw/super6502_fpga/src/sub/network_processor/doc/network_processor.md b/hw/super6502_fpga/src/sub/network_processor/doc/network_processor.md
new file mode 100644
index 0000000000000000000000000000000000000000..8ecbbfd6a894d99f9c93bd6cad2f4c8a8b0cb865
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/doc/network_processor.md
@@ -0,0 +1,55 @@
+# Network Processor
+
+The network processor terminates TCP connections.
+
+## Theory of Operation
+
+Configuration is loaded statically into one of the available TCP
+
+## Components
+
+### TCP State Manager
+
+The TCP State manager is responsible for maintaining the TCP State. It facilitates
+communication between the RX control and TX control. The most important thing that
+the TCP State manager does is request the socket structures from memory, and load
+these values into the RX and TX control, and vice-versa.
+
+When the TCP State Manager sees i_tx_ctx_ptr_valid, it will read i_tx_ctx_ptr and then
+DMA that struct into it's local memory. It will then look up the port in the CAM. If
+the port is not present, it will write it. If the CAM is full, then we set a flag in
+the context saying that the socket was not opened successfully.
+
+#### Clock and Reset
+
+
+| Clock Name | Clock Frequency |
+|---------------|---------------|
+| System Clock | 100MHz |
+
+| Reset Name | Purpose |
+|-----------|------------|
+| rst_n   | General Reset |
+
+#### Regfile Inputs
+
+All of the registers go through the tcp state manager.
+
+
+#### Other Signals
+| Signal Name | Direction | Description |
+| ----------- | --------- | ----------- |
+| o_send_type | O | Type of packet to create |
+| o_send_valid | O | Send a packet |
+| o_seq_num | O | Current sequence number |
+| i_seq_num | I | Next sequence number |
+| i_seq_num_we | I | Write new sequence number |
+| o_ack_num | O | Current ack number |
+| i_ack_num | I | Next ack number |
+| i_ack_num_we | I | Write new ack number |
+| i_recvd_type | I | Received packet type from RX control. Bitmask from packet. |
+| i_recvd_valid | I | Recieved type valid |
+| o_tx_port | O | TX port output to TX Packet Gen |
+| o_tx_ip | O | TX IP Address |
+| o_rx_port | O | RX port output to RX Parser |
+| o_rx_ip | O | RX IP. Local IP of device |
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/doc/tcp.drawio b/hw/super6502_fpga/src/sub/network_processor/doc/tcp.drawio
new file mode 100644
index 0000000000000000000000000000000000000000..9cc1648e7eeb1a97e492abd5f808a74d94f769f0
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/doc/tcp.drawio
@@ -0,0 +1,574 @@
+<mxfile host="Electron" modified="2024-08-30T01:36:46.743Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.2.8 Chrome/112.0.5615.165 Electron/24.2.0 Safari/537.36" etag="v0ewGMV_NAF0fF2QkYBg" version="21.2.8" type="device">
+  <diagram name="Page-1" id="8lX2gjxiGhIz8fm0OWgg">
+    <mxGraphModel dx="1794" dy="648" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
+      <root>
+        <mxCell id="0" />
+        <mxCell id="1" parent="0" />
+        <mxCell id="hUmURhrymKCytomf8O3q-317" value="" style="group;fillColor=default;" parent="1" vertex="1" connectable="0">
+          <mxGeometry x="130" y="200" width="610" height="400" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-318" value="" style="group;strokeColor=default;fillColor=none;container=0;" parent="hUmURhrymKCytomf8O3q-317" vertex="1" connectable="0">
+          <mxGeometry width="610" height="400" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-321" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;" parent="hUmURhrymKCytomf8O3q-317" target="hUmURhrymKCytomf8O3q-340" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint y="120" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-322" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-339" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint y="340" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-323" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-324" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="610" y="120" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-324" value="Packet Generator" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-317" vertex="1">
+          <mxGeometry x="430" y="80.07" width="120" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-325" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-326" target="hUmURhrymKCytomf8O3q-324" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-326" value="TX Control" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-317" vertex="1">
+          <mxGeometry x="310" y="100.07" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-327" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-340" target="hUmURhrymKCytomf8O3q-326" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="270.0000000000002" y="120.06999999999994" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-328" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-330" target="hUmURhrymKCytomf8O3q-326" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-329" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-330" target="hUmURhrymKCytomf8O3q-324" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-330" value="TCP State Manager" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-317" vertex="1">
+          <mxGeometry x="310" y="200.07" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-331" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-332" target="hUmURhrymKCytomf8O3q-330" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-332" value="Parser" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-317" vertex="1">
+          <mxGeometry x="430" y="320.07000000000005" width="120" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-333" value="" style="endArrow=classic;html=1;rounded=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-317" target="hUmURhrymKCytomf8O3q-332" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="610" y="340" as="sourcePoint" />
+            <mxPoint x="530" y="180.07" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-334" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-335" target="hUmURhrymKCytomf8O3q-330" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-335" value="RX Control" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-317" vertex="1">
+          <mxGeometry x="310" y="320.07000000000005" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-336" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-332" target="hUmURhrymKCytomf8O3q-335" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-337" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="hUmURhrymKCytomf8O3q-317" source="hUmURhrymKCytomf8O3q-335" target="hUmURhrymKCytomf8O3q-339" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="270.0000000000002" y="340.07000000000016" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-338" value="REGS" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-317" vertex="1">
+          <mxGeometry x="290" y="20.069999999999993" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-339" value="Ring Buffer Manager" style="rounded=0;whiteSpace=wrap;html=1;container=0;" parent="hUmURhrymKCytomf8O3q-317" vertex="1">
+          <mxGeometry x="80" y="310" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-340" value="Ring Buffer Manager" style="rounded=0;whiteSpace=wrap;html=1;container=0;" parent="hUmURhrymKCytomf8O3q-317" vertex="1">
+          <mxGeometry x="80" y="90.07" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-348" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.625;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endArrow=none;endFill=0;fillColor=#6a00ff;strokeColor=#3700CC;" parent="1" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="620.03" y="160" as="targetPoint" />
+            <mxPoint x="620.03" y="250" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-293" value="" style="group;fillColor=default;" parent="1" vertex="1" connectable="0">
+          <mxGeometry x="140" y="210" width="610" height="400" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-294" value="" style="group;strokeColor=default;fillColor=none;container=0;" parent="hUmURhrymKCytomf8O3q-293" vertex="1" connectable="0">
+          <mxGeometry width="610" height="400" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-297" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;" parent="hUmURhrymKCytomf8O3q-293" target="hUmURhrymKCytomf8O3q-316" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint y="120" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-298" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-315" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint y="340" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-299" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-300" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="610" y="120" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-300" value="Packet Generator" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-293" vertex="1">
+          <mxGeometry x="430" y="80.07" width="120" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-301" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-302" target="hUmURhrymKCytomf8O3q-300" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-302" value="TX Control" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-293" vertex="1">
+          <mxGeometry x="310" y="100.07" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-303" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-316" target="hUmURhrymKCytomf8O3q-302" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="270.0000000000002" y="120.06999999999994" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-304" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-306" target="hUmURhrymKCytomf8O3q-302" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-305" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-306" target="hUmURhrymKCytomf8O3q-300" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-306" value="TCP State Manager" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-293" vertex="1">
+          <mxGeometry x="310" y="200.07" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-307" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-308" target="hUmURhrymKCytomf8O3q-306" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-308" value="Parser" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-293" vertex="1">
+          <mxGeometry x="430" y="320.07000000000005" width="120" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-309" value="" style="endArrow=classic;html=1;rounded=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-293" target="hUmURhrymKCytomf8O3q-308" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="610" y="340" as="sourcePoint" />
+            <mxPoint x="530" y="180.07" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-310" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-311" target="hUmURhrymKCytomf8O3q-306" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-311" value="RX Control" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-293" vertex="1">
+          <mxGeometry x="310" y="320.07000000000005" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-312" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-308" target="hUmURhrymKCytomf8O3q-311" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-313" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="hUmURhrymKCytomf8O3q-293" source="hUmURhrymKCytomf8O3q-311" target="hUmURhrymKCytomf8O3q-315" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="270.0000000000002" y="340.07000000000016" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-314" value="REGS" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-293" vertex="1">
+          <mxGeometry x="290" y="20.069999999999993" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-315" value="Ring Buffer Manager" style="rounded=0;whiteSpace=wrap;html=1;container=0;" parent="hUmURhrymKCytomf8O3q-293" vertex="1">
+          <mxGeometry x="80" y="310" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-316" value="Ring Buffer Manager" style="rounded=0;whiteSpace=wrap;html=1;container=0;" parent="hUmURhrymKCytomf8O3q-293" vertex="1">
+          <mxGeometry x="80" y="90.07" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-347" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.625;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endArrow=none;endFill=0;fillColor=#6a00ff;strokeColor=#3700CC;" parent="1" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="629.95" y="160" as="targetPoint" />
+            <mxPoint x="629.95" y="250" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-269" value="" style="group;fillColor=default;" parent="1" vertex="1" connectable="0">
+          <mxGeometry x="150" y="220" width="610" height="400" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-270" value="" style="group;strokeColor=default;fillColor=none;container=0;" parent="hUmURhrymKCytomf8O3q-269" vertex="1" connectable="0">
+          <mxGeometry width="610" height="400" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-273" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;" parent="hUmURhrymKCytomf8O3q-269" target="hUmURhrymKCytomf8O3q-292" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint y="120" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-274" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-291" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint y="340" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-275" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-276" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="610" y="120" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-276" value="Packet Generator" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-269" vertex="1">
+          <mxGeometry x="430" y="80.07" width="120" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-277" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-278" target="hUmURhrymKCytomf8O3q-276" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-278" value="TX Control" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-269" vertex="1">
+          <mxGeometry x="310" y="100.07" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-279" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-292" target="hUmURhrymKCytomf8O3q-278" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="270.0000000000002" y="120.06999999999994" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-280" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-282" target="hUmURhrymKCytomf8O3q-278" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-281" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-282" target="hUmURhrymKCytomf8O3q-276" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-282" value="TCP State Manager" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-269" vertex="1">
+          <mxGeometry x="310" y="200.07" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-283" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-284" target="hUmURhrymKCytomf8O3q-282" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-284" value="Parser" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-269" vertex="1">
+          <mxGeometry x="430" y="320.07000000000005" width="120" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-285" value="" style="endArrow=classic;html=1;rounded=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-269" target="hUmURhrymKCytomf8O3q-284" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="610" y="340" as="sourcePoint" />
+            <mxPoint x="530" y="180.07" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-286" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-287" target="hUmURhrymKCytomf8O3q-282" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-287" value="RX Control" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-269" vertex="1">
+          <mxGeometry x="310" y="320.07000000000005" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-288" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-284" target="hUmURhrymKCytomf8O3q-287" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-289" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="hUmURhrymKCytomf8O3q-269" source="hUmURhrymKCytomf8O3q-287" target="hUmURhrymKCytomf8O3q-291" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="270.0000000000002" y="340.07000000000016" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-290" value="REGS" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-269" vertex="1">
+          <mxGeometry x="290" y="20.069999999999993" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-291" value="Ring Buffer Manager" style="rounded=0;whiteSpace=wrap;html=1;container=0;" parent="hUmURhrymKCytomf8O3q-269" vertex="1">
+          <mxGeometry x="80" y="310" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-292" value="Ring Buffer Manager" style="rounded=0;whiteSpace=wrap;html=1;container=0;" parent="hUmURhrymKCytomf8O3q-269" vertex="1">
+          <mxGeometry x="80" y="90.07" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-142" value="" style="endArrow=none;html=1;rounded=0;entryX=0.667;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endFill=0;fillColor=#fa6800;strokeColor=#C73500;exitX=0.333;exitY=0.999;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="740.0000000000005" y="540.027868852459" as="sourcePoint" />
+            <mxPoint x="840.0000000000005" y="539.9978688524591" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-143" value="" style="endArrow=none;html=1;rounded=0;entryX=0.584;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endFill=0;fillColor=#fa6800;strokeColor=#C73500;exitX=0.416;exitY=0.999;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="750.0000000000005" y="550.027868852459" as="sourcePoint" />
+            <mxPoint x="840.0000000000005" y="549.9978688524591" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-144" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;startArrow=classic;startFill=1;endFill=0;fillColor=#fa6800;strokeColor=#C73500;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="760" y="560" as="sourcePoint" />
+            <mxPoint x="840" y="560" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-360" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d80073;strokeColor=#A50040;" parent="1" target="wy1xcPKCa-p-PBI3JPLa-122" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="630" y="80" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-122" value="APB Decoder" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
+          <mxGeometry x="550" y="120" width="160" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-129" value="" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.annotation_2;align=left;labelPosition=right;pointerEvents=1;rotation=135;" parent="1" vertex="1">
+          <mxGeometry x="750" y="170" width="30" height="70" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-130" value="N" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
+          <mxGeometry x="750" y="170" width="60" height="30" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-170" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#fa6800;strokeColor=#C73500;" parent="1" source="wy1xcPKCa-p-PBI3JPLa-132" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="1040" y="340" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-132" value="ip arb" style="shape=trapezoid;perimeter=trapezoidPerimeter;whiteSpace=wrap;html=1;fixedSize=1;rotation=-90;flipH=1;flipV=1;" parent="1" vertex="1">
+          <mxGeometry x="800" y="320.03" width="120" height="40.07" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-133" value="ip demux" style="shape=trapezoid;perimeter=trapezoidPerimeter;whiteSpace=wrap;html=1;fixedSize=1;rotation=-90;flipH=1;flipV=1;" parent="1" vertex="1">
+          <mxGeometry x="800" y="540" width="120" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-134" value="" style="endArrow=none;html=1;rounded=0;entryX=0.667;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endFill=0;fillColor=#fa6800;strokeColor=#C73500;exitX=0.333;exitY=0.999;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="wy1xcPKCa-p-PBI3JPLa-132" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="810" y="320.03" as="sourcePoint" />
+            <mxPoint x="770" y="320.03" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-135" value="" style="endArrow=none;html=1;rounded=0;entryX=0.584;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endFill=0;fillColor=#fa6800;strokeColor=#C73500;exitX=0.416;exitY=0.999;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="wy1xcPKCa-p-PBI3JPLa-132" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="820" y="330.03" as="sourcePoint" />
+            <mxPoint x="770" y="330.03" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-136" value="" style="endArrow=none;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;startArrow=classic;startFill=1;endFill=0;fillColor=#fa6800;strokeColor=#C73500;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="840" y="340" as="sourcePoint" />
+            <mxPoint x="770" y="340.03" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-137" value="" style="endArrow=none;html=1;rounded=0;entryX=0.417;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endFill=0;fillColor=#fa6800;strokeColor=#C73500;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="840" y="350.03" as="sourcePoint" />
+            <mxPoint x="770" y="350.03" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-145" value="" style="endArrow=none;html=1;rounded=0;entryX=0.417;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endFill=0;fillColor=#fa6800;strokeColor=#C73500;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="770.0000000000005" y="570.0578688524588" as="sourcePoint" />
+            <mxPoint x="840.0000000000005" y="570.0578688524588" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-357" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d80073;strokeColor=#A50040;" parent="1" target="hUmURhrymKCytomf8O3q-23" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="-120.00000000000023" y="340.06999999999994" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-23" value="M2S DMA" style="whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
+          <mxGeometry x="-80" y="300.07" width="80" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-346" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.625;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;startArrow=classic;startFill=1;endArrow=none;endFill=0;fillColor=#6a00ff;strokeColor=#3700CC;" parent="1" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="640.03" y="160" as="targetPoint" />
+            <mxPoint x="640.03" y="250" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-358" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d80073;strokeColor=#A50040;" parent="1" source="hUmURhrymKCytomf8O3q-24" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="-120.00000000000023" y="560" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-24" value="S2M DMA" style="whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
+          <mxGeometry x="-80" y="520" width="80" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-268" value="" style="group;fillColor=default;" parent="1" vertex="1" connectable="0">
+          <mxGeometry x="159.97" y="230" width="610" height="400" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-99" value="" style="group;strokeColor=default;fillColor=none;container=0;" parent="hUmURhrymKCytomf8O3q-268" vertex="1" connectable="0">
+          <mxGeometry width="610" height="400" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;" parent="hUmURhrymKCytomf8O3q-268" target="hUmURhrymKCytomf8O3q-13" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint y="120" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;" parent="hUmURhrymKCytomf8O3q-268" source="hUmURhrymKCytomf8O3q-16" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint y="340" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-84" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-268" source="wy1xcPKCa-p-PBI3JPLa-85" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="610" y="120" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-85" value="Packet Generator" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-268" vertex="1">
+          <mxGeometry x="430" y="80.07" width="120" height="80" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-87" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-268" source="wy1xcPKCa-p-PBI3JPLa-88" target="wy1xcPKCa-p-PBI3JPLa-85" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-88" value="TX Control" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-268" vertex="1">
+          <mxGeometry x="310" y="100.07" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-89" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="hUmURhrymKCytomf8O3q-268" source="hUmURhrymKCytomf8O3q-13" target="wy1xcPKCa-p-PBI3JPLa-88" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="270.0000000000002" y="120.06999999999994" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-90" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-268" source="wy1xcPKCa-p-PBI3JPLa-92" target="wy1xcPKCa-p-PBI3JPLa-88" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-91" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-268" source="wy1xcPKCa-p-PBI3JPLa-92" target="wy1xcPKCa-p-PBI3JPLa-85" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-92" value="TCP State Manager" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-268" vertex="1">
+          <mxGeometry x="310" y="200.07" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-93" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-268" source="wy1xcPKCa-p-PBI3JPLa-94" target="wy1xcPKCa-p-PBI3JPLa-92" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-94" value="Parser" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-268" vertex="1">
+          <mxGeometry x="430" y="320.07000000000005" width="120" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-95" value="" style="endArrow=classic;html=1;rounded=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-268" target="wy1xcPKCa-p-PBI3JPLa-94" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="610" y="340" as="sourcePoint" />
+            <mxPoint x="530" y="180.07" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-96" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-268" source="wy1xcPKCa-p-PBI3JPLa-97" target="wy1xcPKCa-p-PBI3JPLa-92" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-97" value="RX Control" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-268" vertex="1">
+          <mxGeometry x="310" y="320.07000000000005" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-98" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#fa6800;strokeColor=#C73500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;" parent="hUmURhrymKCytomf8O3q-268" source="wy1xcPKCa-p-PBI3JPLa-94" target="wy1xcPKCa-p-PBI3JPLa-97" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-101" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#e3c800;strokeColor=#B09500;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="hUmURhrymKCytomf8O3q-268" source="wy1xcPKCa-p-PBI3JPLa-97" target="hUmURhrymKCytomf8O3q-16" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="270.0000000000002" y="340.07000000000016" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="wy1xcPKCa-p-PBI3JPLa-102" value="REGS" style="rounded=0;whiteSpace=wrap;html=1;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;locked=0;connectable=1;container=0;" parent="hUmURhrymKCytomf8O3q-268" vertex="1">
+          <mxGeometry x="430" y="9.999999999999993" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-16" value="4k/128 SAF" style="rounded=0;whiteSpace=wrap;html=1;container=0;" parent="hUmURhrymKCytomf8O3q-268" vertex="1">
+          <mxGeometry x="80" y="310" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-13" value="4k/128 SAF" style="rounded=0;whiteSpace=wrap;html=1;container=0;" parent="hUmURhrymKCytomf8O3q-268" vertex="1">
+          <mxGeometry x="80" y="90.07" width="120" height="60" as="geometry" />
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-345" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;endArrow=none;endFill=0;fillColor=#6a00ff;strokeColor=#3700CC;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.625;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="wy1xcPKCa-p-PBI3JPLa-102" target="wy1xcPKCa-p-PBI3JPLa-122" edge="1">
+          <mxGeometry relative="1" as="geometry">
+            <mxPoint x="650" y="170" as="targetPoint" />
+            <Array as="points" />
+            <mxPoint x="730.0000000000002" y="270" as="sourcePoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-349" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;exitX=1;exitY=0.25;exitDx=0;exitDy=0;" parent="1" edge="1" source="hUmURhrymKCytomf8O3q-23">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="80" y="320.03" as="sourcePoint" />
+            <mxPoint x="130" y="320.03" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-350" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;exitX=1;exitY=0.374;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" edge="1" source="hUmURhrymKCytomf8O3q-23">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="80" y="330" as="sourcePoint" />
+            <mxPoint x="140" y="330" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-351" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" edge="1" source="hUmURhrymKCytomf8O3q-23">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="80" y="340" as="sourcePoint" />
+            <mxPoint x="150" y="340" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-352" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;exitX=1;exitY=0.624;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" edge="1" source="hUmURhrymKCytomf8O3q-23">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="80" y="350" as="sourcePoint" />
+            <mxPoint x="160" y="350" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-353" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;entryX=1;entryY=0.25;entryDx=0;entryDy=0;" parent="1" edge="1" target="hUmURhrymKCytomf8O3q-24">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="129.97" y="540" as="sourcePoint" />
+            <mxPoint x="79.97" y="540" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-354" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;entryX=1;entryY=0.375;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1" target="hUmURhrymKCytomf8O3q-24">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="139.97" y="549.97" as="sourcePoint" />
+            <mxPoint x="79.97" y="549.97" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-355" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" edge="1" target="hUmURhrymKCytomf8O3q-24">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="149.97" y="559.97" as="sourcePoint" />
+            <mxPoint x="10" y="560" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="hUmURhrymKCytomf8O3q-356" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;entryX=1;entryY=0.625;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" edge="1" target="hUmURhrymKCytomf8O3q-24">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="159.97" y="569.97" as="sourcePoint" />
+            <mxPoint x="79.97" y="569.97" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="1vVpc469gqlHnz9TW-pm-9" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#d80073;strokeColor=#A50040;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="159.97" y="720" as="sourcePoint" />
+            <mxPoint x="240" y="720" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="1vVpc469gqlHnz9TW-pm-11" value="axi4-lite" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="1vVpc469gqlHnz9TW-pm-9" vertex="1" connectable="0">
+          <mxGeometry x="0.2037" y="2" relative="1" as="geometry">
+            <mxPoint x="-8" y="-8" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="1vVpc469gqlHnz9TW-pm-12" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#e3c800;strokeColor=#B09500;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="279.97" y="720" as="sourcePoint" />
+            <mxPoint x="360" y="720" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="1vVpc469gqlHnz9TW-pm-13" value="axi4-stream" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="1vVpc469gqlHnz9TW-pm-12" vertex="1" connectable="0">
+          <mxGeometry x="0.2037" y="2" relative="1" as="geometry">
+            <mxPoint x="-8" y="-8" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="1vVpc469gqlHnz9TW-pm-14" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#0050ef;strokeColor=#001DBC;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="400" y="720" as="sourcePoint" />
+            <mxPoint x="480" y="720" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="1vVpc469gqlHnz9TW-pm-15" value="cpuif" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="1vVpc469gqlHnz9TW-pm-14" vertex="1" connectable="0">
+          <mxGeometry x="0.2037" y="2" relative="1" as="geometry">
+            <mxPoint x="-8" y="-8" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="1vVpc469gqlHnz9TW-pm-16" value="" style="endArrow=classic;html=1;rounded=0;fillColor=#fa6800;strokeColor=#C73500;" parent="1" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="520" y="720" as="sourcePoint" />
+            <mxPoint x="600" y="720" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="1vVpc469gqlHnz9TW-pm-17" value="ip-stream" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="1vVpc469gqlHnz9TW-pm-16" vertex="1" connectable="0">
+          <mxGeometry x="0.2037" y="2" relative="1" as="geometry">
+            <mxPoint x="-8" y="-8" as="offset" />
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="DDA_X_hQHvZcJVnLFhaM-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;" parent="1" source="DDA_X_hQHvZcJVnLFhaM-3" target="wy1xcPKCa-p-PBI3JPLa-133" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="DDA_X_hQHvZcJVnLFhaM-3" value="port mapper" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
+          <mxGeometry x="920" y="540" width="80" height="40" as="geometry" />
+        </mxCell>
+        <mxCell id="DDA_X_hQHvZcJVnLFhaM-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.375;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="wy1xcPKCa-p-PBI3JPLa-92" target="DDA_X_hQHvZcJVnLFhaM-3" edge="1">
+          <mxGeometry relative="1" as="geometry" />
+        </mxCell>
+        <mxCell id="DDA_X_hQHvZcJVnLFhaM-5" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" target="DDA_X_hQHvZcJVnLFhaM-3" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="770" y="440" as="sourcePoint" />
+            <mxPoint x="780" y="410" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="960" y="440" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="DDA_X_hQHvZcJVnLFhaM-6" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.625;entryY=0;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" target="DDA_X_hQHvZcJVnLFhaM-3" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="770" y="430" as="sourcePoint" />
+            <mxPoint x="970" y="550" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="970" y="430" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="DDA_X_hQHvZcJVnLFhaM-7" value="" style="endArrow=classic;html=1;rounded=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" parent="1" target="DDA_X_hQHvZcJVnLFhaM-3" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="770" y="420" as="sourcePoint" />
+            <mxPoint x="980" y="560" as="targetPoint" />
+            <Array as="points">
+              <mxPoint x="980" y="420" />
+            </Array>
+          </mxGeometry>
+        </mxCell>
+        <mxCell id="DDA_X_hQHvZcJVnLFhaM-9" value="" style="endArrow=classic;html=1;rounded=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;fillColor=#fa6800;strokeColor=#C73500;" parent="1" target="DDA_X_hQHvZcJVnLFhaM-3" edge="1">
+          <mxGeometry width="50" height="50" relative="1" as="geometry">
+            <mxPoint x="1040" y="560" as="sourcePoint" />
+            <mxPoint x="1020" y="520" as="targetPoint" />
+          </mxGeometry>
+        </mxCell>
+      </root>
+    </mxGraphModel>
+  </diagram>
+</mxfile>
diff --git a/hw/super6502_fpga/src/sub/network_processor/doc/tcp.drawio.png b/hw/super6502_fpga/src/sub/network_processor/doc/tcp.drawio.png
new file mode 100644
index 0000000000000000000000000000000000000000..346a396ca1b57a8e44119014a203635ca71c56ef
Binary files /dev/null and b/hw/super6502_fpga/src/sub/network_processor/doc/tcp.drawio.png differ
diff --git a/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/Makefile b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..88ec829e1b93560fcd9e9249fbbf3fd4ff4ef49c
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/Makefile
@@ -0,0 +1,24 @@
+RTL_SRCS_LIST=$(REPO_TOP)/hw/super6502_fpga/sources.list
+SIM_SRCS_LIST=tb/sources.list
+
+RTL_SOURCES=$(shell rtl-manifest $(RTL_SRCS_LIST))
+SIM_SOURCES=$(shell rtl-manifest $(SIM_SRCS_LIST))
+
+VERILOG_SOURCES= $(INTF_SOURCES) $(RTL_SOURCES) $(SIM_SOURCES)
+
+TOPLEVEL_LANG ?= verilog
+
+SIM ?= verilator
+
+EXTRA_ARGS += --trace --trace-fst --trace-structs -Wno-fatal -Wno-PINMISSING
+
+
+TOPLEVEL = tb_top
+
+GPI_IMPL := vpi
+
+export PYTHONPATH := $(PWD)/tests:$(PYTHONPATH)
+export TOPLEVEL_LANG
+MODULE=scapy_irl_test
+
+include $(shell cocotb-config --makefiles)/Makefile.sim
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tb/sources.list b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tb/sources.list
new file mode 100644
index 0000000000000000000000000000000000000000..bd036c2c4fc38fe1fa1f7510153c405fb15f9e08
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tb/sources.list
@@ -0,0 +1 @@
+tb_top.sv
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tb/tb_top.sv b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tb/tb_top.sv
new file mode 100644
index 0000000000000000000000000000000000000000..ab18621dbb5b6e493fc46035738c592b9a4c5cc1
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tb/tb_top.sv
@@ -0,0 +1,120 @@
+module tb_top(
+    input   wire            clk,
+    input   wire            rst,
+
+    output  wire            s_regs_axil_awready,
+    input   wire            s_regs_axil_awvalid,
+    input   wire [31:0]     s_regs_axil_awaddr,
+    input   wire [2:0]      s_regs_axil_awprot,
+    output  wire            s_regs_axil_wready,
+    input   wire            s_regs_axil_wvalid,
+    input   wire [31:0]     s_regs_axil_wdata,
+    input   wire [3:0]      s_regs_axil_wstrb,
+    input   wire            s_regs_axil_bready,
+    output  wire            s_regs_axil_bvalid,
+    output  wire [1:0]      s_regs_axil_bresp,
+    output  wire            s_regs_axil_arready,
+    input   wire            s_regs_axil_arvalid,
+    input   wire [31:0]     s_regs_axil_araddr,
+    input   wire [2:0]      s_regs_axil_arprot,
+    input   wire            s_regs_axil_rready,
+    output  wire            s_regs_axil_rvalid,
+    output  wire [31:0]     s_regs_axil_rdata,
+    output  wire [1:0]      s_regs_axil_rresp,
+
+    input   wire            m_dma_axil_awready,
+    output  wire            m_dma_axil_awvalid,
+    output  wire [31:0]     m_dma_axil_awaddr,
+    output  wire [2:0]      m_dma_axil_awprot,
+    input   wire            m_dma_axil_wready,
+    output  wire            m_dma_axil_wvalid,
+    output  wire [31:0]     m_dma_axil_wdata,
+    output  wire [3:0]      m_dma_axil_wstrb,
+    output  wire            m_dma_axil_bready,
+    input   wire            m_dma_axil_bvalid,
+    input   wire [1:0]      m_dma_axil_bresp,
+    input   wire            m_dma_axil_arready,
+    output  wire            m_dma_axil_arvalid,
+    output  wire [31:0]     m_dma_axil_araddr,
+    output  wire [2:0]      m_dma_axil_arprot,
+    output  wire            m_dma_axil_rready,
+    input   wire            m_dma_axil_rvalid,
+    input   wire [31:0]     m_dma_axil_rdata,
+    input   wire [1:0]      m_dma_axil_rresp,
+
+    //MII Interface
+    input   wire            mii_rx_clk,
+    input   wire    [3:0]   mii_rxd,
+    input   wire            mii_rx_dv,
+    input   wire            mii_rx_er,
+    input   wire            mii_tx_clk,
+    output  wire    [3:0]   mii_txd,
+    output  wire            mii_tx_en,
+    output  wire            mii_tx_er
+);
+
+axil_intf regs_axil();
+axil_intf dma_axil();
+
+assign dma_axil.awready     = m_dma_axil_awready;
+assign m_dma_axil_awvalid   = dma_axil.awvalid;
+assign m_dma_axil_awaddr    = dma_axil.awaddr;
+assign m_dma_axil_awprot    = dma_axil.awprot;
+assign dma_axil.wready      = m_dma_axil_wready;
+assign m_dma_axil_wvalid    = dma_axil.wvalid;
+assign m_dma_axil_wdata     = dma_axil.wdata;
+assign m_dma_axil_wstrb     = dma_axil.wstrb;
+assign m_dma_axil_bready    = dma_axil.bready;
+assign dma_axil.bvalid      = m_dma_axil_bvalid;
+assign dma_axil.bresp       = m_dma_axil_bresp;
+assign dma_axil.arready     = m_dma_axil_arready;
+assign m_dma_axil_arvalid   = dma_axil.arvalid;
+assign m_dma_axil_araddr    = dma_axil.araddr;
+assign m_dma_axil_arprot    = dma_axil.arprot;
+assign m_dma_axil_rready    = dma_axil.rready;
+assign dma_axil.rvalid      = m_dma_axil_rvalid;
+assign dma_axil.rdata       = m_dma_axil_rdata;
+assign dma_axil.rresp       = m_dma_axil_rresp;
+
+assign s_regs_axil_awready  = regs_axil.awready;
+assign regs_axil.awvalid    = s_regs_axil_awvalid;
+assign regs_axil.awaddr     = s_regs_axil_awaddr;
+assign regs_axil.awprot     = s_regs_axil_awprot;
+assign s_regs_axil_wready   = regs_axil.wready;
+assign regs_axil.wvalid     = s_regs_axil_wvalid;
+assign regs_axil.wdata      = s_regs_axil_wdata;
+assign regs_axil.wstrb      = s_regs_axil_wstrb;
+assign regs_axil.bready     = s_regs_axil_bready;
+assign s_regs_axil_bvalid   = regs_axil.bvalid;
+assign s_regs_axil_bresp    = regs_axil.bresp;
+assign s_regs_axil_arready  = regs_axil.arready;
+assign regs_axil.arvalid    = s_regs_axil_arvalid;
+assign regs_axil.araddr     = s_regs_axil_araddr;
+assign regs_axil.arprot     = s_regs_axil_arprot;
+assign regs_axil.rready     = s_regs_axil_rready;
+assign s_regs_axil_rvalid   = regs_axil.rvalid;
+assign s_regs_axil_rdata    = regs_axil.rdata;
+assign s_regs_axil_rresp    = regs_axil.rresp;
+
+
+
+network_processor #(
+    .NUM_TCP(4)
+) u_network_processor (
+    .i_clk                  (clk),
+    .i_rst                  (rst),
+
+    .s_reg_axil             (regs_axil),
+    .m_dma_axil             (dma_axil),
+
+    .mii_rx_clk             (mii_rx_clk),
+    .mii_rxd                (mii_rxd),
+    .mii_rx_dv              (mii_rx_dv),
+    .mii_rx_er              (mii_rx_er),
+    .mii_tx_clk             (mii_tx_clk),
+    .mii_txd                (mii_txd),
+    .mii_tx_en              (mii_tx_en),
+    .mii_tx_er              (mii_tx_er)
+);
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tests/scapy_irl_test.py b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tests/scapy_irl_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..48f75dcb2f4fcac04dd5ae1d0b6d4192786a0498
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tests/scapy_irl_test.py
@@ -0,0 +1,466 @@
+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 IP, TCP
+from scapy.layers.l2 import ARP, Ether
+from scapy.packet import Packet
+from scapy.utils import PcapWriter
+
+from scapy.layers.tuntap import TunTapInterface
+import logging
+
+from decimal import Decimal
+
+import random
+
+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 group netdev
+# 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)
+
+    async def read_tcp_from_dut():
+        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}")
+
+        return ip_packet
+
+    #############################
+    # Reset 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"
+
+    dut_port = random.randint(1024, 65535)
+    tb_port = random.randint(1024, 65535)
+
+    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    serversocket.bind((tb_ip, tb_port))
+    serversocket.listen(1)
+    t = TunTapInterface('tun0')
+
+
+    ###############################
+    # Configure DUT Network block #
+    ###############################
+
+    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"
+
+    # hardcode the ARP response for now
+    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))
+
+
+    ###############################
+    # Start TCP handshake         #
+    ###############################
+
+    ip_packet = await read_tcp_from_dut()
+
+    t.send(ip_packet)
+
+    while True:
+        pkt = t.recv()
+        assert isinstance(pkt, Packet)
+        if (pkt.proto == IP_PROTOS.tcp):
+            break
+    print(pkt)
+
+    tcp_synack = Ether(dst=dut_mac, src=tb_mac)  / pkt
+
+    await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_synack.build()))
+
+    ip_packet = await read_tcp_from_dut()
+
+    t.send(ip_packet)
+
+    con, addr = serversocket.accept()
+
+    ###############################
+    # Send data from DUT to host  #
+    ###############################
+
+    # 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)
+    tb.log.info("Received 64 packets")
+
+    ###############################
+    # Close connection from host  #
+    ###############################
+
+    con.close()
+    serversocket.close()
+
+    while True:
+        pkt = t.recv()
+        assert isinstance(pkt, Packet)
+        if (pkt.proto == IP_PROTOS.tcp):
+            break
+    print(pkt)
+
+    tcp_ack = Ether(dst=dut_mac, src=tb_mac) / pkt
+
+    await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_ack.build()))
+
+    tb.log.info("Expecting to send an F here")
+
+    while True:
+        pkt = t.recv()
+        assert isinstance(pkt, Packet)
+        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()))
+
+    tb.log.info("Expecting to get ACK from DUT")
+
+    ip_packet = await read_tcp_from_dut()
+
+    t.send(ip_packet)
+
+    tb.log.info("Expecting to get FINACK from DUT")
+
+    ip_packet = await read_tcp_from_dut()
+
+    t.send(ip_packet)
+
+    tb.log.info("Expecting to get ACK from host")
+
+    while True:
+        pkt = t.recv()
+        assert isinstance(pkt, Packet)
+        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()))
+
+    await Timer(Decimal(CLK_PERIOD_NS * 1000), units='ns')
+
+
+@cocotb.test()
+async def test_close(dut):
+    tb = TB(dut)
+
+    async def read_tcp_from_dut():
+        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}")
+
+        return ip_packet
+
+    def get_pkt_from_host():
+        while True:
+            pkt = t.recv()
+            assert isinstance(pkt, Packet)
+            if (pkt.proto == IP_PROTOS.tcp):
+                break
+        print(pkt)
+        return pkt
+
+    #############################
+    # Reset 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"
+
+    dut_port = random.randint(1024, 65535)
+    tb_port = random.randint(1024, 65535)
+
+    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    serversocket.bind((tb_ip, tb_port))
+    serversocket.listen(1)
+    t = TunTapInterface('tun0')
+
+
+    ###############################
+    # Configure DUT Network block #
+    ###############################
+
+    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"
+
+    # hardcode the ARP response for now
+    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))
+
+
+    ###############################
+    # Start TCP handshake         #
+    ###############################
+
+    ip_packet = await read_tcp_from_dut()
+
+    t.send(ip_packet)
+
+
+    pkt = get_pkt_from_host()
+    tcp_synack = Ether(dst=dut_mac, src=tb_mac)  / pkt
+
+    await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_synack.build()))
+
+    ip_packet = await read_tcp_from_dut()
+
+    t.send(ip_packet)
+
+    con, addr = serversocket.accept()
+
+    tb.log.info(f"con_timeout: {con.timeout}")
+
+    ###############################
+    # Close connection from DUT   #
+    ###############################
+
+    tb.log.info("Closing connection from the DUT side")
+    await tb.axil_master.write_dword(0x210, 5)
+
+    ip_packet = await read_tcp_from_dut()
+
+    tb.log.info("Sending packet to host")
+    t.send(ip_packet)
+
+    pkt = get_pkt_from_host()
+    tcp_synack = Ether(dst=dut_mac, src=tb_mac)  / pkt
+
+    tb.log.info("Sending reply to DUT, this should be an ACK?")
+    await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_synack.build()))
+
+    tb.log.info(tcp_synack.flags)
+
+    # Host will send an ack first, then a finack?
+
+    tb.log.info("Closing server socket")
+    con.close()
+    serversocket.close()
+
+    pkt = get_pkt_from_host()
+    tcp_synack = Ether(dst=dut_mac, src=tb_mac)  / pkt
+
+    tb.log.info("Sending packet to DUT, this should be a FINACK?")
+    await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_synack.build()))
+
+    pkt = get_pkt_from_host()
+    tcp_synack = Ether(dst=dut_mac, src=tb_mac)  / pkt
+
+    ip_packet = await read_tcp_from_dut()
+
+    tb.log.info("Sending packet to host")
+    t.send(ip_packet)
+
+    await Timer(Decimal(CLK_PERIOD_NS * 20000), units='ns')
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tests/tcp_test.py b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tests/tcp_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..c350673457b4c01a36acc3c6b7f96db07474de34
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/sim/cocotb/tests/tcp_test.py
@@ -0,0 +1,215 @@
+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
+
+import logging
+
+from decimal import Decimal
+
+CLK_PERIOD_NS = 10
+
+MII_CLK_PERIOD_NS = 40
+
+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_simple(dut):
+    pktdump = PcapWriter("tcp.pcapng", append=False, sync=True)
+
+
+    tb = TB(dut)
+
+    await tb.cycle_reset()
+
+    dut_ip = "172.0.0.2"
+    tb_ip = "172.0.0.1"
+
+    dut_port = 0x1234
+    tb_port = 0x5678
+
+    tb_mac = "02:00:00:11:22:33"
+
+    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())
+    pktdump.write(packet)
+
+    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()
+
+    pktdump.write(arp_response)
+
+    await tb.mii_phy.rx.send(GmiiFrame.from_payload(arp_response))
+
+    # 1. DUT sends syn with seq number
+
+    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}")
+
+    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}")
+
+
+    dut_seq = tcp_packet.seq
+    tb_seq = 11111111
+
+    # 2. Send SYNACK with seq as our sequence number, and ACK as their sequence number plus 1
+
+    tcp_synack = Ether(dst=dut_mac, src=tb_mac)
+    tcp_synack /= IP(src=tb_ip, dst=dut_ip)
+    tcp_synack /= TCP(sport=tb_port, dport=dut_port, seq=tb_seq, ack=dut_seq+1, flags="SA")
+    tcp_synack = tcp_synack.build()
+    pktdump.write(tcp_synack)
+
+    await tb.mii_phy.rx.send(GmiiFrame.from_payload(tcp_synack))
+
+    # 3. Receieve ACK with our sequence number plus 1
+
+    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}")
+
+
+    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}")
+
+    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()
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/sources.list b/hw/super6502_fpga/src/sub/network_processor/sources.list
new file mode 100644
index 0000000000000000000000000000000000000000..d6286bd045dc78d6815a5bfe209b4d4457e253f3
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/sources.list
@@ -0,0 +1,24 @@
+src/regs/tcp_stream_regs_pkg.sv
+src/regs/tcp_stream_regs.sv
+src/regs/tcp_top_regfile_pkg.sv
+src/regs/tcp_top_regfile.sv
+src/regs/mac_regs_pkg.sv
+src/regs/mac_regs.sv
+src/regs/ntw_top_regfile_pkg.sv
+src/regs/ntw_top_regfile.sv
+src/network_processor.sv
+src/tcp_pkg.sv
+src/tcp_tx_ctrl.sv
+src/tcp_rx_ctrl.sv
+src/tcp_packet_generator.sv
+src/tcp_state_manager.sv
+src/tcp_stream.sv
+src/tcp.sv
+src/eth_wrapper.sv
+src/ip_arb_mux_wrapper.sv
+src/ip_demux_wrapper.sv
+src/tcp_dest_decap.sv
+src/tcp_parser.sv
+src/checksum_calc.sv
+src/ip_pipeline_register_wrapper.sv
+src/axil_reg_slice.sv
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/axil_reg_slice.sv b/hw/super6502_fpga/src/sub/network_processor/src/axil_reg_slice.sv
new file mode 100644
index 0000000000000000000000000000000000000000..6dec744a23a496c914412d8d896571d93937bb0d
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/axil_reg_slice.sv
@@ -0,0 +1,76 @@
+module axil_reg_slice(
+    input clk,
+    input rst,
+
+    axil_intf.SLAVE s_axil,
+    axil_intf.MASTER m_axil
+);
+
+skidbuffer #(
+    .DW(s_axil.AXIL_ADDR_WIDTH)
+) awskid(
+    .i_clk(clk),
+    .i_reset(rst),
+
+    .i_valid(s_axil.awvalid),
+    .o_ready(s_axil.awready),
+    .i_data(s_axil.awaddr),
+    .o_valid(m_axil.awvalid),
+    .i_ready(m_axil.awready),
+    .o_data(m_axil.awaddr)
+);
+
+skidbuffer #(
+    .DW(s_axil.AXIL_DATA_WIDTH + s_axil.AXIL_STRB_WIDTH)
+) wskid(
+    .i_clk(clk),
+    .i_reset(rst),
+
+    .i_valid(s_axil.wvalid),
+    .o_ready(s_axil.wready),
+    .i_data({s_axil.wdata, s_axil.wstrb}),
+    .o_valid(m_axil.wvalid),
+    .i_ready(m_axil.wready),
+    .o_data({m_axil.wdata, m_axil.wstrb})
+);
+
+skidbuffer #(
+    .DW(s_axil.AXIL_ADDR_WIDTH)
+) arskid(
+    .i_clk(clk),
+    .i_reset(rst),
+
+    .i_valid(s_axil.arvalid),
+    .o_ready(s_axil.arready),
+    .i_data(s_axil.araddr),
+    .o_valid(m_axil.arvalid),
+    .i_ready(m_axil.arready),
+    .o_data(m_axil.araddr)
+);
+
+skidbuffer #(
+    .DW(s_axil.AXIL_DATA_WIDTH + 2)
+) rskid(
+    .i_clk(clk),
+    .i_reset(rst),
+
+    .i_valid(m_axil.rvalid),
+    .o_ready(m_axil.rready),
+    .i_data({m_axil.rdata, m_axil.rresp}),
+    .o_valid(s_axil.rvalid),
+    .i_ready(s_axil.rready),
+    .o_data({s_axil.rdata, s_axil.rresp})
+);
+skidbuffer #(.DW(2)) bskid(
+    .i_clk(clk),
+    .i_reset(rst),
+
+    .i_valid(m_axil.bvalid),
+    .o_ready(m_axil.bready),
+    .i_data(m_axil.bresp),
+    .o_valid(s_axil.bvalid),
+    .i_ready(s_axil.bready),
+    .o_data(s_axil.bresp)
+);
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/checksum_calc.sv b/hw/super6502_fpga/src/sub/network_processor/src/checksum_calc.sv
new file mode 100644
index 0000000000000000000000000000000000000000..d8c752c78c678bd273e0736325582e29ebec6f12
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/checksum_calc.sv
@@ -0,0 +1,36 @@
+module checksum_calc (
+    input i_rst,
+    input i_clk,
+
+    input i_clear,
+    input i_enable,
+
+    input [31:0] i_data,
+
+    output [15:0] o_checksum
+);
+
+logic [31:0] sum;
+logic [31:0] pre_sum;
+logic [31:0] sum_next;
+logic [15:0] sum_wrapped;
+
+assign sum_wrapped = sum[15:0] + sum [31:16];
+assign o_checksum = ~sum_wrapped;
+
+always @(posedge i_clk) begin
+    if (i_rst || i_clear) begin
+        sum <= '0;
+    end else begin
+        if (i_enable) begin
+            sum <= sum_next;
+        end
+    end
+end
+
+always_comb begin
+    pre_sum = i_data[31:16] + i_data[15:0];
+    sum_next = sum + pre_sum;
+end
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/eth_wrapper.sv b/hw/super6502_fpga/src/sub/network_processor/src/eth_wrapper.sv
new file mode 100644
index 0000000000000000000000000000000000000000..1e8551c4416325964640285663d6e89c66aa32a1
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/eth_wrapper.sv
@@ -0,0 +1,133 @@
+module eth_wrapper #(
+    parameter MAC_DATA_WIDTH=8,
+    parameter MAC_KEEP_WIDTH = ((MAC_DATA_WIDTH+7)/8)
+)(
+    input  wire                       rst,
+    input  wire                       clk_sys,
+
+    axis_intf.SLAVE                   tx_axis,
+    axis_intf.MASTER                  rx_axis,
+
+    /*
+     * MII interface
+     */
+    input  wire                       mii_rx_clk,
+    input  wire [3:0]                 mii_rxd,
+    input  wire                       mii_rx_dv,
+    input  wire                       mii_rx_er,
+    input  wire                       mii_tx_clk,
+    output wire [3:0]                 mii_txd,
+    output wire                       mii_tx_en,
+    output wire                       mii_tx_er,
+
+
+    /*
+     * CPUIF interface
+     */
+    input  wire                       s_cpuif_req,
+    input  wire                       s_cpuif_req_is_wr,
+    input  wire [4:0]                 s_cpuif_addr,
+    input  wire [31:0]                s_cpuif_wr_data,
+    input  wire [31:0]                s_cpuif_wr_biten,
+    output wire                       s_cpuif_req_stall_wr,
+    output wire                       s_cpuif_req_stall_rd,
+    output wire                       s_cpuif_rd_ack,
+    output wire                       s_cpuif_rd_err,
+    output wire [31:0]                s_cpuif_rd_data,
+    output wire                       s_cpuif_wr_ack,
+    output wire                       s_cpuif_wr_err,
+
+    // MDIO Interface
+    input  wire                       Mdi,
+    output wire                       Mdo,
+    output wire                       MdoEn,
+    output wire                       Mdc,
+
+
+    output wire                       phy_rstn
+);
+
+assign Mdo = '0;
+assign MdoEn = '0;
+assign Mdc = '0;
+
+mac_regs_pkg::mac_regs__in_t hwif_in;
+mac_regs_pkg::mac_regs__out_t hwif_out;
+
+mac_regs u_mac_regs(
+    .clk(clk_sys),
+    .rst(rst),
+
+    .s_cpuif_req            (s_cpuif_req),
+    .s_cpuif_req_is_wr      (s_cpuif_req_is_wr),
+    .s_cpuif_addr           (s_cpuif_addr),
+    .s_cpuif_wr_data        (s_cpuif_wr_data),
+    .s_cpuif_wr_biten       (s_cpuif_wr_biten),
+    .s_cpuif_req_stall_wr   (s_cpuif_req_stall_wr),
+    .s_cpuif_req_stall_rd   (s_cpuif_req_stall_rd),
+    .s_cpuif_rd_ack         (s_cpuif_rd_ack),
+    .s_cpuif_rd_err         (s_cpuif_rd_err),
+    .s_cpuif_rd_data        (s_cpuif_rd_data),
+    .s_cpuif_wr_ack         (s_cpuif_wr_ack),
+    .s_cpuif_wr_err         (s_cpuif_wr_err),
+
+    .hwif_in                (hwif_in),
+    .hwif_out               (hwif_out)
+);
+
+assign phy_rstn = hwif_out.ctrl.phy_rstn.value;
+
+eth_mac_mii_fifo #(
+    .TARGET("GENERIC"),
+    .AXIS_DATA_WIDTH(MAC_DATA_WIDTH),
+    .MIN_FRAME_LENGTH(64),
+    .TX_FIFO_DEPTH(4096),
+    .TX_FIFO_RAM_PIPELINE(1),
+    .TX_FRAME_FIFO(1),
+    .RX_FIFO_DEPTH(4096),
+    .RX_FIFO_RAM_PIPELINE(1),
+    .RX_FRAME_FIFO(1)
+) u_mac (
+    .rst                (rst),
+    .logic_clk          (clk_sys),
+    .logic_rst          (rst),
+
+    .tx_axis_tdata      (tx_axis.tdata),
+    .tx_axis_tkeep      (tx_axis.tkeep),
+    .tx_axis_tvalid     (tx_axis.tvalid),
+    .tx_axis_tready     (tx_axis.tready),
+    .tx_axis_tlast      (tx_axis.tlast),
+    .tx_axis_tuser      ('0),
+
+    .rx_axis_tdata      (rx_axis.tdata),
+    .rx_axis_tkeep      (rx_axis.tkeep),
+    .rx_axis_tvalid     (rx_axis.tvalid),
+    .rx_axis_tready     (rx_axis.tready),
+    .rx_axis_tlast      (rx_axis.tlast),
+    .rx_axis_tuser      (rx_axis.tuser),
+
+    .mii_rx_clk         (mii_rx_clk),
+    .mii_rxd            (mii_rxd),
+    .mii_rx_dv          (mii_rx_dv),
+    .mii_rx_er          (mii_rx_er),
+    .mii_tx_clk         (mii_tx_clk),
+    .mii_txd            (mii_txd),
+    .mii_tx_en          (mii_tx_en),
+    .mii_tx_er          (mii_tx_er),
+
+    .tx_error_underflow (hwif_in.stats.tx_error_underflow.hwset),
+    .tx_fifo_overflow   (hwif_in.stats.tx_fifo_overflow.hwset),
+    .tx_fifo_bad_frame  (hwif_in.stats.tx_fifo_bad_frame.hwset),
+    .tx_fifo_good_frame (hwif_in.stats.tx_fifo_good_frame.hwset),
+    .rx_error_bad_frame (hwif_in.stats.rx_error_bad_frame.hwset),
+    .rx_error_bad_fcs   (hwif_in.stats.rx_error_bad_fcs.hwset),
+    .rx_fifo_overflow   (hwif_in.stats.rx_fifo_overflow.hwset),
+    .rx_fifo_bad_frame  (hwif_in.stats.rx_fifo_bad_frame.hwset),
+    .rx_fifo_good_frame (hwif_in.stats.rx_fifo_good_frame.hwset),
+
+    .cfg_ifg            (hwif_out.ctrl.ifg.value),
+    .cfg_tx_enable      (hwif_out.ctrl.tx_en.value),   // this should be configurable w/ regfile
+    .cfg_rx_enable      (hwif_out.ctrl.rx_en.value)
+);
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/ip_arb_mux_wrapper.sv b/hw/super6502_fpga/src/sub/network_processor/src/ip_arb_mux_wrapper.sv
new file mode 100644
index 0000000000000000000000000000000000000000..dd6d197acdb4ec81786513ae4bfa71e59cd2b7dd
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/ip_arb_mux_wrapper.sv
@@ -0,0 +1,154 @@
+module ip_arb_mux_wrapper #(
+    parameter S_COUNT = 4,
+    parameter DATA_WIDTH = 8,
+    parameter KEEP_ENABLE = (DATA_WIDTH>8),
+    parameter KEEP_WIDTH = (DATA_WIDTH/8),
+    parameter ID_ENABLE = 0,
+    parameter ID_WIDTH = 8,
+    parameter DEST_ENABLE = 0,
+    parameter DEST_WIDTH = 8,
+    parameter USER_ENABLE = 1,
+    parameter USER_WIDTH = 1,
+    // select round robin arbitration
+    parameter ARB_TYPE_ROUND_ROBIN = 0,
+    // LSB priority selection
+    parameter ARB_LSB_HIGH_PRIORITY = 1
+) (
+    input i_clk,
+    input i_rst,
+
+    ip_intf.SLAVE s_ip  [S_COUNT],
+    ip_intf.MASTER m_ip
+);
+
+logic [S_COUNT-1:0]             s_ip_hdr_valid;
+logic [S_COUNT-1:0]             s_ip_hdr_ready;
+logic [S_COUNT*48-1:0]          s_eth_dest_mac;
+logic [S_COUNT*48-1:0]          s_eth_src_mac;
+logic [S_COUNT*16-1:0]          s_eth_type;
+logic [S_COUNT*4-1:0]           s_ip_version;
+logic [S_COUNT*4-1:0]           s_ip_ihl;
+logic [S_COUNT*6-1:0]           s_ip_dscp;
+logic [S_COUNT*2-1:0]           s_ip_ecn;
+logic [S_COUNT*16-1:0]          s_ip_length;
+logic [S_COUNT*16-1:0]          s_ip_identification;
+logic [S_COUNT*3-1:0]           s_ip_flags;
+logic [S_COUNT*13-1:0]          s_ip_fragment_offset;
+logic [S_COUNT*8-1:0]           s_ip_ttl;
+logic [S_COUNT*8-1:0]           s_ip_protocol;
+logic [S_COUNT*16-1:0]          s_ip_header_checksum;
+logic [S_COUNT*32-1:0]          s_ip_source_ip;
+logic [S_COUNT*32-1:0]          s_ip_dest_ip;
+logic [S_COUNT*DATA_WIDTH-1:0]  s_ip_payload_axis_tdata;
+logic [S_COUNT*KEEP_WIDTH-1:0]  s_ip_payload_axis_tkeep;
+logic [S_COUNT-1:0]             s_ip_payload_axis_tvalid;
+logic [S_COUNT-1:0]             s_ip_payload_axis_tready;
+logic [S_COUNT-1:0]             s_ip_payload_axis_tlast;
+logic [S_COUNT*ID_WIDTH-1:0]    s_ip_payload_axis_tid;
+logic [S_COUNT*DEST_WIDTH-1:0]  s_ip_payload_axis_tdest;
+logic [S_COUNT*USER_WIDTH-1:0]  s_ip_payload_axis_tuser;
+
+generate
+    for (genvar i = 0; i < S_COUNT; i++) begin
+        assign s_ip_hdr_valid[i]                                    = s_ip[i].ip_hdr_valid;
+        assign s_ip[i].ip_hdr_ready                                 = s_ip_hdr_ready[i];
+        assign s_eth_dest_mac[i*48+:48]                             = s_ip[i].eth_dest_mac;
+        assign s_eth_src_mac[i*48+:48]                              = s_ip[i].eth_src_mac;
+        assign s_eth_type[i*16+:16]                                 = s_ip[i].eth_type;
+        assign s_ip_version[i*4+:4]                                 = s_ip[i].ip_version;
+        assign s_ip_ihl[i*4+:4]                                     = s_ip[i].ip_ihl;
+        assign s_ip_dscp[i*6+:6]                                    = s_ip[i].ip_dscp;
+        assign s_ip_ecn[i*2+:2]                                     = s_ip[i].ip_ecn;
+        assign s_ip_length[i*16+:16]                                = s_ip[i].ip_length;
+        assign s_ip_identification[i*16+:16]                        = s_ip[i].ip_identification;
+        assign s_ip_flags[i*3+:3]                                   = s_ip[i].ip_flags;
+        assign s_ip_fragment_offset[i*13+:13]                       = s_ip[i].ip_fragment_offset;
+        assign s_ip_ttl[i*8+:8]                                     = s_ip[i].ip_ttl;
+        assign s_ip_protocol[i*8+:8]                                = s_ip[i].ip_protocol;
+        assign s_ip_header_checksum[i*16+:16]                       = s_ip[i].ip_header_checksum;
+        assign s_ip_source_ip[i*32+:32]                             = s_ip[i].ip_source_ip;
+        assign s_ip_dest_ip[i*32+:32]                               = s_ip[i].ip_dest_ip;
+        assign s_ip_payload_axis_tdata[i*DATA_WIDTH+:DATA_WIDTH]    = s_ip[i].ip_payload_axis_tdata;
+        assign s_ip_payload_axis_tkeep[i*KEEP_WIDTH+:KEEP_WIDTH]    = s_ip[i].ip_payload_axis_tkeep;
+        assign s_ip_payload_axis_tvalid[i*KEEP_WIDTH+:KEEP_WIDTH]   = s_ip[i].ip_payload_axis_tvalid;
+        assign s_ip[i].ip_payload_axis_tready                       = s_ip_payload_axis_tready[i];
+        assign s_ip_payload_axis_tlast[i]                           = s_ip[i].ip_payload_axis_tlast;
+        assign s_ip_payload_axis_tid[i*ID_WIDTH+:ID_WIDTH]          = s_ip[i].ip_payload_axis_tid;
+        assign s_ip_payload_axis_tdest[i*DEST_WIDTH+:DEST_WIDTH]    = s_ip[i].ip_payload_axis_tdest;
+        assign s_ip_payload_axis_tuser[i*USER_WIDTH+:USER_WIDTH]    = s_ip[i].ip_payload_axis_tuser;
+    end
+endgenerate
+
+ip_arb_mux #(
+    .S_COUNT(S_COUNT),
+    .DATA_WIDTH(DATA_WIDTH),
+    .KEEP_ENABLE(KEEP_ENABLE),
+    .KEEP_WIDTH(KEEP_WIDTH),
+    .ID_ENABLE(ID_ENABLE),
+    .ID_WIDTH(ID_WIDTH),
+    .DEST_ENABLE(DEST_ENABLE),
+    .DEST_WIDTH(DEST_WIDTH),
+    .USER_ENABLE(USER_ENABLE),
+    .USER_WIDTH(USER_WIDTH),
+    .ARB_TYPE_ROUND_ROBIN(ARB_TYPE_ROUND_ROBIN),
+    .ARB_LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY)
+) u_arb_mux (
+    .clk                                (i_clk),
+    .rst                                (i_rst),
+
+    .s_ip_hdr_valid                     (s_ip_hdr_valid                 ),
+    .s_ip_hdr_ready                     (s_ip_hdr_ready                 ),
+    .s_eth_dest_mac                     (s_eth_dest_mac                 ),
+    .s_eth_src_mac                      (s_eth_src_mac                  ),
+    .s_eth_type                         (s_eth_type                     ),
+    .s_ip_version                       (s_ip_version                   ),
+    .s_ip_ihl                           (s_ip_ihl                       ),
+    .s_ip_dscp                          (s_ip_dscp                      ),
+    .s_ip_ecn                           (s_ip_ecn                       ),
+    .s_ip_length                        (s_ip_length                    ),
+    .s_ip_identification                (s_ip_identification            ),
+    .s_ip_flags                         (s_ip_flags                     ),
+    .s_ip_fragment_offset               (s_ip_fragment_offset           ),
+    .s_ip_ttl                           (s_ip_ttl                       ),
+    .s_ip_protocol                      (s_ip_protocol                  ),
+    .s_ip_header_checksum               (s_ip_header_checksum           ),
+    .s_ip_source_ip                     (s_ip_source_ip                 ),
+    .s_ip_dest_ip                       (s_ip_dest_ip                   ),
+    .s_ip_payload_axis_tdata            (s_ip_payload_axis_tdata        ),
+    .s_ip_payload_axis_tkeep            (s_ip_payload_axis_tkeep        ),
+    .s_ip_payload_axis_tvalid           (s_ip_payload_axis_tvalid       ),
+    .s_ip_payload_axis_tready           (s_ip_payload_axis_tready       ),
+    .s_ip_payload_axis_tlast            (s_ip_payload_axis_tlast        ),
+    .s_ip_payload_axis_tid              (s_ip_payload_axis_tid          ),
+    .s_ip_payload_axis_tdest            (s_ip_payload_axis_tdest        ),
+    .s_ip_payload_axis_tuser            (s_ip_payload_axis_tuser        ),
+
+    .m_ip_hdr_valid                     (m_ip.ip_hdr_valid              ),
+    .m_ip_hdr_ready                     (m_ip.ip_hdr_ready              ),
+    .m_eth_dest_mac                     (m_ip.eth_dest_mac              ),
+    .m_eth_src_mac                      (m_ip.eth_src_mac               ),
+    .m_eth_type                         (m_ip.eth_type                  ),
+    .m_ip_version                       (m_ip.ip_version                ),
+    .m_ip_ihl                           (m_ip.ip_ihl                    ),
+    .m_ip_dscp                          (m_ip.ip_dscp                   ),
+    .m_ip_ecn                           (m_ip.ip_ecn                    ),
+    .m_ip_length                        (m_ip.ip_length                 ),
+    .m_ip_identification                (m_ip.ip_identification         ),
+    .m_ip_flags                         (m_ip.ip_flags                  ),
+    .m_ip_fragment_offset               (m_ip.ip_fragment_offset        ),
+    .m_ip_ttl                           (m_ip.ip_ttl                    ),
+    .m_ip_protocol                      (m_ip.ip_protocol               ),
+    .m_ip_header_checksum               (m_ip.ip_header_checksum        ),
+    .m_ip_source_ip                     (m_ip.ip_source_ip              ),
+    .m_ip_dest_ip                       (m_ip.ip_dest_ip                ),
+    .m_ip_payload_axis_tdata            (m_ip.ip_payload_axis_tdata     ),
+    .m_ip_payload_axis_tkeep            (m_ip.ip_payload_axis_tkeep     ),
+    .m_ip_payload_axis_tvalid           (m_ip.ip_payload_axis_tvalid    ),
+    .m_ip_payload_axis_tready           (m_ip.ip_payload_axis_tready    ),
+    .m_ip_payload_axis_tlast            (m_ip.ip_payload_axis_tlast     ),
+    .m_ip_payload_axis_tid              (m_ip.ip_payload_axis_tid       ),
+    .m_ip_payload_axis_tdest            (m_ip.ip_payload_axis_tdest     ),
+    .m_ip_payload_axis_tuser            (m_ip.ip_payload_axis_tuser     )
+);
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/ip_demux_wrapper.sv b/hw/super6502_fpga/src/sub/network_processor/src/ip_demux_wrapper.sv
new file mode 100644
index 0000000000000000000000000000000000000000..7d87a01e8d33948457839c61e2498beb395ca6aa
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/ip_demux_wrapper.sv
@@ -0,0 +1,158 @@
+module ip_demux_wrapper #(
+    parameter M_COUNT = 4,
+    parameter DATA_WIDTH = 8,
+    parameter KEEP_ENABLE = (DATA_WIDTH>8),
+    parameter KEEP_WIDTH = (DATA_WIDTH/8),
+    parameter ID_ENABLE = 0,
+    parameter ID_WIDTH = 8,
+    parameter DEST_ENABLE = 0,
+    parameter DEST_WIDTH = 8,
+    parameter USER_ENABLE = 1,
+    parameter USER_WIDTH = 1
+)
+(
+    input  wire                          clk,
+    input  wire                          rst,
+
+    ip_intf.SLAVE s_ip,
+    ip_intf.MASTER m_ip [M_COUNT],
+
+    input  wire                          enable,
+    input  wire                          drop,
+    input  wire [$clog2(M_COUNT)-1:0]    select
+);
+
+logic [M_COUNT-1:0]            m_ip_hdr_valid;
+logic [M_COUNT-1:0]            m_ip_hdr_ready;
+logic [M_COUNT*48-1:0]         m_eth_dest_mac;
+logic [M_COUNT*48-1:0]         m_eth_src_mac;
+logic [M_COUNT*16-1:0]         m_eth_type;
+logic [M_COUNT*4-1:0]          m_ip_version;
+logic [M_COUNT*4-1:0]          m_ip_ihl;
+logic [M_COUNT*6-1:0]          m_ip_dscp;
+logic [M_COUNT*2-1:0]          m_ip_ecn;
+logic [M_COUNT*16-1:0]         m_ip_length;
+logic [M_COUNT*16-1:0]         m_ip_identification;
+logic [M_COUNT*3-1:0]          m_ip_flags;
+logic [M_COUNT*13-1:0]         m_ip_fragment_offset;
+logic [M_COUNT*8-1:0]          m_ip_ttl;
+logic [M_COUNT*8-1:0]          m_ip_protocol;
+logic [M_COUNT*16-1:0]         m_ip_header_checksum;
+logic [M_COUNT*32-1:0]         m_ip_source_ip;
+logic [M_COUNT*32-1:0]         m_ip_dest_ip;
+logic [M_COUNT*DATA_WIDTH-1:0] m_ip_payload_axis_tdata;
+logic [M_COUNT*KEEP_WIDTH-1:0] m_ip_payload_axis_tkeep;
+logic [M_COUNT-1:0]            m_ip_payload_axis_tvalid;
+logic [M_COUNT-1:0]            m_ip_payload_axis_tready;
+logic [M_COUNT-1:0]            m_ip_payload_axis_tlast;
+logic [M_COUNT*ID_WIDTH-1:0]   m_ip_payload_axis_tid;
+logic [M_COUNT*DEST_WIDTH-1:0] m_ip_payload_axis_tdest;
+logic [M_COUNT*USER_WIDTH-1:0] m_ip_payload_axis_tuser;
+
+
+generate
+    for (genvar i = 0; i < M_COUNT; i++) begin
+        assign m_ip[i].ip_hdr_valid             = m_ip_hdr_valid[i];
+        assign m_ip_hdr_ready[i]                = m_ip[i].ip_hdr_ready;
+        assign m_ip[i].eth_dest_mac             = m_eth_dest_mac[i*48+:48];
+        assign m_ip[i].eth_src_mac              = m_eth_src_mac[i*48+:48];
+        assign m_ip[i].eth_type                 = m_eth_type[i*16+:16];
+        assign m_ip[i].ip_version               = m_ip_version[i*4+:4];
+        assign m_ip[i].ip_ihl                   = m_ip_ihl[i*4+:4];
+        assign m_ip[i].ip_dscp                  = m_ip_dscp[i*6+:6];
+        assign m_ip[i].ip_ecn                   = m_ip_ecn[i*2+:2];
+        assign m_ip[i].ip_length                = m_ip_length[i*16+:16];
+        assign m_ip[i].ip_identification        = m_ip_identification[i*16+:16];
+        assign m_ip[i].ip_flags                 = m_ip_flags[i*3+:3];
+        assign m_ip[i].ip_fragment_offset       = m_ip_fragment_offset[i*13+:13];
+        assign m_ip[i].ip_ttl                   = m_ip_ttl[i*8+:8];
+        assign m_ip[i].ip_protocol              = m_ip_protocol[i*8+:8];
+        assign m_ip[i].ip_header_checksum       = m_ip_header_checksum[i*16+:16];
+        assign m_ip[i].ip_source_ip             = m_ip_source_ip[i*32+:32];
+        assign m_ip[i].ip_dest_ip               = m_ip_dest_ip[i*32+:32];
+        assign m_ip[i].ip_payload_axis_tdata    = m_ip_payload_axis_tdata[i*DATA_WIDTH+:DATA_WIDTH];
+        assign m_ip[i].ip_payload_axis_tkeep    = m_ip_payload_axis_tkeep[i*KEEP_WIDTH+:KEEP_WIDTH];
+        assign m_ip[i].ip_payload_axis_tvalid   = m_ip_payload_axis_tvalid[i*KEEP_WIDTH+:KEEP_WIDTH];
+        assign m_ip_payload_axis_tready[i]      = m_ip[i].ip_payload_axis_tready;
+        assign m_ip[i].ip_payload_axis_tlast    = m_ip_payload_axis_tlast[i];
+        assign m_ip[i].ip_payload_axis_tid      = m_ip_payload_axis_tid[i*ID_WIDTH+:ID_WIDTH];
+        assign m_ip[i].ip_payload_axis_tdest    = m_ip_payload_axis_tdest[i*DEST_WIDTH+:DEST_WIDTH];
+        assign m_ip[i].ip_payload_axis_tuser    = m_ip_payload_axis_tuser[i*USER_WIDTH+:USER_WIDTH];
+    end
+endgenerate
+
+ip_demux #(
+    .M_COUNT(M_COUNT),
+    .DATA_WIDTH(DATA_WIDTH),
+    .KEEP_ENABLE(KEEP_ENABLE),
+    .KEEP_WIDTH(KEEP_WIDTH),
+    .ID_ENABLE(ID_ENABLE),
+    .ID_WIDTH(ID_WIDTH),
+    .DEST_ENABLE(DEST_ENABLE),
+    .DEST_WIDTH(DEST_WIDTH),
+    .USER_ENABLE(USER_ENABLE),
+    .USER_WIDTH(USER_WIDTH)
+) u_ip_demux (
+    .clk                                (clk),
+    .rst                                (rst),
+
+    .s_ip_hdr_valid                     (s_ip.ip_hdr_valid              ),
+    .s_ip_hdr_ready                     (s_ip.ip_hdr_ready              ),
+    .s_eth_dest_mac                     (s_ip.eth_dest_mac              ),
+    .s_eth_src_mac                      (s_ip.eth_src_mac               ),
+    .s_eth_type                         (s_ip.eth_type                  ),
+    .s_ip_version                       (s_ip.ip_version                ),
+    .s_ip_ihl                           (s_ip.ip_ihl                    ),
+    .s_ip_dscp                          (s_ip.ip_dscp                   ),
+    .s_ip_ecn                           (s_ip.ip_ecn                    ),
+    .s_ip_length                        (s_ip.ip_length                 ),
+    .s_ip_identification                (s_ip.ip_identification         ),
+    .s_ip_flags                         (s_ip.ip_flags                  ),
+    .s_ip_fragment_offset               (s_ip.ip_fragment_offset        ),
+    .s_ip_ttl                           (s_ip.ip_ttl                    ),
+    .s_ip_protocol                      (s_ip.ip_protocol               ),
+    .s_ip_header_checksum               (s_ip.ip_header_checksum        ),
+    .s_ip_source_ip                     (s_ip.ip_source_ip              ),
+    .s_ip_dest_ip                       (s_ip.ip_dest_ip                ),
+    .s_ip_payload_axis_tdata            (s_ip.ip_payload_axis_tdata     ),
+    .s_ip_payload_axis_tkeep            (s_ip.ip_payload_axis_tkeep     ),
+    .s_ip_payload_axis_tvalid           (s_ip.ip_payload_axis_tvalid    ),
+    .s_ip_payload_axis_tready           (s_ip.ip_payload_axis_tready    ),
+    .s_ip_payload_axis_tlast            (s_ip.ip_payload_axis_tlast     ),
+    .s_ip_payload_axis_tid              (s_ip.ip_payload_axis_tid       ),
+    .s_ip_payload_axis_tdest            (s_ip.ip_payload_axis_tdest     ),
+    .s_ip_payload_axis_tuser            (s_ip.ip_payload_axis_tuser     ),
+
+    .m_ip_hdr_valid                     (m_ip_hdr_valid                 ),
+    .m_ip_hdr_ready                     (m_ip_hdr_ready                 ),
+    .m_eth_dest_mac                     (m_eth_dest_mac                 ),
+    .m_eth_src_mac                      (m_eth_src_mac                  ),
+    .m_eth_type                         (m_eth_type                     ),
+    .m_ip_version                       (m_ip_version                   ),
+    .m_ip_ihl                           (m_ip_ihl                       ),
+    .m_ip_dscp                          (m_ip_dscp                      ),
+    .m_ip_ecn                           (m_ip_ecn                       ),
+    .m_ip_length                        (m_ip_length                    ),
+    .m_ip_identification                (m_ip_identification            ),
+    .m_ip_flags                         (m_ip_flags                     ),
+    .m_ip_fragment_offset               (m_ip_fragment_offset           ),
+    .m_ip_ttl                           (m_ip_ttl                       ),
+    .m_ip_protocol                      (m_ip_protocol                  ),
+    .m_ip_header_checksum               (m_ip_header_checksum           ),
+    .m_ip_source_ip                     (m_ip_source_ip                 ),
+    .m_ip_dest_ip                       (m_ip_dest_ip                   ),
+    .m_ip_payload_axis_tdata            (m_ip_payload_axis_tdata        ),
+    .m_ip_payload_axis_tkeep            (m_ip_payload_axis_tkeep        ),
+    .m_ip_payload_axis_tvalid           (m_ip_payload_axis_tvalid       ),
+    .m_ip_payload_axis_tready           (m_ip_payload_axis_tready       ),
+    .m_ip_payload_axis_tlast            (m_ip_payload_axis_tlast        ),
+    .m_ip_payload_axis_tid              (m_ip_payload_axis_tid          ),
+    .m_ip_payload_axis_tdest            (m_ip_payload_axis_tdest        ),
+    .m_ip_payload_axis_tuser            (m_ip_payload_axis_tuser        ),
+
+    .enable                             (enable),
+    .drop                               (drop),
+    .select                             (select)
+);
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/ip_pipeline_register_wrapper.sv b/hw/super6502_fpga/src/sub/network_processor/src/ip_pipeline_register_wrapper.sv
new file mode 100644
index 0000000000000000000000000000000000000000..8349ea114163130bb14e1453b42ac2fc9e087300
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/ip_pipeline_register_wrapper.sv
@@ -0,0 +1,59 @@
+module ip_pipeline_register_wrapper(
+    input logic clk,
+    input logic rst,
+
+    ip_intf.SLAVE s_ip,
+    ip_intf.MASTER m_ip
+);
+
+assign m_ip.ip_hdr_valid        = s_ip.ip_hdr_valid;
+assign s_ip.ip_hdr_ready        = m_ip.ip_hdr_ready;
+assign m_ip.eth_dest_mac        = s_ip.eth_dest_mac;
+assign m_ip.eth_src_mac         = s_ip.eth_src_mac;
+assign m_ip.eth_type            = s_ip.eth_type;
+assign m_ip.ip_version          = s_ip.ip_version;
+assign m_ip.ip_ihl              = s_ip.ip_ihl;
+assign m_ip.ip_dscp             = s_ip.ip_dscp;
+assign m_ip.ip_ecn              = s_ip.ip_ecn;
+assign m_ip.ip_length           = s_ip.ip_length;
+assign m_ip.ip_identification   = s_ip.ip_identification;
+assign m_ip.ip_flags            = s_ip.ip_flags;
+assign m_ip.ip_fragment_offset  = s_ip.ip_fragment_offset;
+assign m_ip.ip_ttl              = s_ip.ip_ttl;
+assign m_ip.ip_protocol         = s_ip.ip_protocol;
+assign m_ip.ip_header_checksum  = s_ip.ip_header_checksum;
+assign m_ip.ip_source_ip        = s_ip.ip_source_ip;
+assign m_ip.ip_dest_ip          = s_ip.ip_dest_ip;
+
+axis_pipeline_register #(
+    .DATA_WIDTH(s_ip.DATA_WIDTH),
+    .KEEP_WIDTH(s_ip.KEEP_WIDTH),
+    .ID_ENABLE(1),
+    .ID_WIDTH(s_ip.ID_WIDTH),
+    .DEST_ENABLE(1),
+    .DEST_WIDTH(s_ip.DEST_WIDTH),
+    .USER_WIDTH(s_ip.USER_WIDTH)
+) u_reg (
+    .clk(clk),
+    .rst(rst),
+
+    .s_axis_tdata   (s_ip.ip_payload_axis_tdata),
+    .s_axis_tkeep   (s_ip.ip_payload_axis_tkeep),
+    .s_axis_tvalid  (s_ip.ip_payload_axis_tvalid),
+    .s_axis_tready  (s_ip.ip_payload_axis_tready),
+    .s_axis_tlast   (s_ip.ip_payload_axis_tlast),
+    .s_axis_tid     (s_ip.ip_payload_axis_tid),
+    .s_axis_tdest   (s_ip.ip_payload_axis_tdest),
+    .s_axis_tuser   (s_ip.ip_payload_axis_tuser),
+
+    .m_axis_tdata   (m_ip.ip_payload_axis_tdata),
+    .m_axis_tkeep   (m_ip.ip_payload_axis_tkeep),
+    .m_axis_tvalid  (m_ip.ip_payload_axis_tvalid),
+    .m_axis_tready  (m_ip.ip_payload_axis_tready),
+    .m_axis_tlast   (m_ip.ip_payload_axis_tlast),
+    .m_axis_tid     (m_ip.ip_payload_axis_tid),
+    .m_axis_tdest   (m_ip.ip_payload_axis_tdest),
+    .m_axis_tuser   (m_ip.ip_payload_axis_tuser)
+);
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/network_processor.sv b/hw/super6502_fpga/src/sub/network_processor/src/network_processor.sv
new file mode 100644
index 0000000000000000000000000000000000000000..9f4867c54cc49dac5304dad341bf67b8b7575860
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/network_processor.sv
@@ -0,0 +1,343 @@
+module network_processor #(
+    parameter NUM_TCP=8
+)(
+    input i_clk,
+    input i_rst,
+
+    axil_intf.SLAVE                     s_reg_axil,
+    axil_intf.MASTER                    m_dma_axil,
+
+    //MII Interface
+    input   wire                        mii_rx_clk,
+    input   wire    [3:0]               mii_rxd,
+    input   wire                        mii_rx_dv,
+    input   wire                        mii_rx_er,
+    input   wire                        mii_tx_clk,
+    output  wire    [3:0]               mii_txd,
+    output  wire                        mii_tx_en,
+    output  wire                        mii_tx_er,
+
+    // MDIO Interface
+    input                               i_Mdi,
+    output                              o_Mdo,
+    output                              o_MdoEn,
+    output                              o_Mdc,
+
+    output                              phy_rstn
+
+);
+
+`define PROTO_ICMP 8'h1
+`define PROTO_TCP 8'h6
+`define PROTO_UDP 8'h11
+
+localparam ICMP_IDX = 2;
+localparam UDP_IDX = 1;
+localparam TCP_IDX = 0;
+
+localparam MAC_DATA_WIDTH = 8;
+localparam AXIS_DATA_WIDTH = 8;
+localparam AXIS_KEEP_WIDTH = ((AXIS_DATA_WIDTH+7)/8);
+
+axil_intf reg_axil_post_reg();
+
+axis_intf #(.DATA_WIDTH(MAC_DATA_WIDTH)) mac_tx_axis();
+axis_intf #(.DATA_WIDTH(MAC_DATA_WIDTH)) mac_rx_axis();
+
+eth_intf #(.DATA_WIDTH(MAC_DATA_WIDTH)) mac_tx_eth();
+eth_intf #(.DATA_WIDTH(MAC_DATA_WIDTH)) mac_rx_eth();
+
+ip_intf #(.DATA_WIDTH(MAC_DATA_WIDTH)) ntw_tx_ip();
+ip_intf #(.DATA_WIDTH(MAC_DATA_WIDTH)) ntw_rx_ip();
+
+ip_intf #(.DATA_WIDTH(MAC_DATA_WIDTH)) proto_rx_ip[3]();
+ip_intf #(.DATA_WIDTH(MAC_DATA_WIDTH)) proto_tx_ip[3]();
+
+ntw_top_regfile_pkg::ntw_top_regfile__in_t hwif_in;
+ntw_top_regfile_pkg::ntw_top_regfile__out_t hwif_out;
+
+axil_reg_slice u_reg_axil_reg_slice(
+    .clk(i_clk),
+    .rst(i_rst),
+
+    .s_axil(s_reg_axil),
+    .m_axil(reg_axil_post_reg)
+);
+
+ntw_top_regfile u_ntw_top_regfile (
+    .clk                                (i_clk),
+    .rst                                (i_rst),
+
+    .s_axil_awready                     (reg_axil_post_reg.awready),
+    .s_axil_awvalid                     (reg_axil_post_reg.awvalid),
+    .s_axil_awaddr                      (reg_axil_post_reg.awaddr),
+    .s_axil_awprot                      (reg_axil_post_reg.awprot),
+    .s_axil_wready                      (reg_axil_post_reg.wready),
+    .s_axil_wvalid                      (reg_axil_post_reg.wvalid),
+    .s_axil_wdata                       (reg_axil_post_reg.wdata),
+    .s_axil_wstrb                       (reg_axil_post_reg.wstrb),
+    .s_axil_bready                      (reg_axil_post_reg.bready),
+    .s_axil_bvalid                      (reg_axil_post_reg.bvalid),
+    .s_axil_bresp                       (reg_axil_post_reg.bresp),
+    .s_axil_arready                     (reg_axil_post_reg.arready),
+    .s_axil_arvalid                     (reg_axil_post_reg.arvalid),
+    .s_axil_araddr                      (reg_axil_post_reg.araddr),
+    .s_axil_arprot                      (reg_axil_post_reg.arprot),
+    .s_axil_rready                      (reg_axil_post_reg.rready),
+    .s_axil_rvalid                      (reg_axil_post_reg.rvalid),
+    .s_axil_rdata                       (reg_axil_post_reg.rdata),
+    .s_axil_rresp                       (reg_axil_post_reg.rresp),
+
+    .hwif_in                            (hwif_in),
+    .hwif_out                           (hwif_out)
+);
+
+// eth wrapper
+eth_wrapper #(
+    .MAC_DATA_WIDTH(MAC_DATA_WIDTH)
+) u_eth_wrapper (
+    .rst                                (i_rst),
+    .clk_sys                            (i_clk),
+
+    .s_cpuif_req                        (hwif_out.mac.req),
+    .s_cpuif_req_is_wr                  (hwif_out.mac.req_is_wr),
+    .s_cpuif_addr                       (hwif_out.mac.addr),
+    .s_cpuif_wr_data                    (hwif_out.mac.wr_data),
+    .s_cpuif_wr_biten                   (hwif_out.mac.wr_biten),
+    .s_cpuif_req_stall_wr               (),
+    .s_cpuif_req_stall_rd               (),
+    .s_cpuif_rd_ack                     (hwif_in.mac.rd_ack),
+    .s_cpuif_rd_err                     (),
+    .s_cpuif_rd_data                    (hwif_in.mac.rd_data),
+    .s_cpuif_wr_ack                     (hwif_in.mac.wr_ack),
+    .s_cpuif_wr_err                     (),
+
+    // MII
+    .mii_rx_clk                         (mii_rx_clk),
+    .mii_rxd                            (mii_rxd),
+    .mii_rx_dv                          (mii_rx_dv),
+    .mii_rx_er                          (mii_rx_er),
+    .mii_tx_clk                         (mii_tx_clk),
+    .mii_txd                            (mii_txd),
+    .mii_tx_en                          (mii_tx_en),
+    .mii_tx_er                          (mii_tx_er),
+
+    .tx_axis                            (mac_tx_axis),
+    .rx_axis                            (mac_rx_axis),
+
+    .Mdi                                (i_Mdi),
+    .Mdo                                (o_Mdo),
+    .MdoEn                              (o_MdoEn),
+    .Mdc                                (o_Mdc)
+);
+
+eth_axis_rx #(
+    .DATA_WIDTH(MAC_DATA_WIDTH)
+) u_mac_eth_axis_rx (
+    .clk                                (i_clk),
+    .rst                                (i_rst),
+
+    .s_axis_tdata                       (mac_rx_axis.tdata),
+    .s_axis_tvalid                      (mac_rx_axis.tvalid),
+    .s_axis_tready                      (mac_rx_axis.tready),
+    .s_axis_tlast                       (mac_rx_axis.tlast),
+    .s_axis_tuser                       (mac_rx_axis.tuser),
+    .s_axis_tkeep                       (mac_rx_axis.tkeep),
+
+    .m_eth_hdr_valid                    (mac_rx_eth.eth_hdr_valid),
+    .m_eth_hdr_ready                    (mac_rx_eth.eth_hdr_ready),
+    .m_eth_dest_mac                     (mac_rx_eth.eth_dest_mac),
+    .m_eth_src_mac                      (mac_rx_eth.eth_src_mac),
+    .m_eth_type                         (mac_rx_eth.eth_type),
+    .m_eth_payload_axis_tdata           (mac_rx_eth.eth_payload_axis_tdata),
+    .m_eth_payload_axis_tkeep           (mac_rx_eth.eth_payload_axis_tkeep),
+    .m_eth_payload_axis_tvalid          (mac_rx_eth.eth_payload_axis_tvalid),
+    .m_eth_payload_axis_tready          (mac_rx_eth.eth_payload_axis_tready),
+    .m_eth_payload_axis_tlast           (mac_rx_eth.eth_payload_axis_tlast),
+    .m_eth_payload_axis_tuser           (mac_rx_eth.eth_payload_axis_tuser),
+
+    .busy                               (),
+    .error_header_early_termination     () // We can add this to a register
+);
+
+eth_axis_tx #(
+    .DATA_WIDTH(MAC_DATA_WIDTH)
+) u_mac_eth_axis_tx (
+    .clk                                (i_clk),
+    .rst                                (i_rst),
+
+    .s_eth_hdr_valid                    (mac_tx_eth.eth_hdr_valid),
+    .s_eth_hdr_ready                    (mac_tx_eth.eth_hdr_ready),
+    .s_eth_dest_mac                     (mac_tx_eth.eth_dest_mac),
+    .s_eth_src_mac                      (mac_tx_eth.eth_src_mac),
+    .s_eth_type                         (mac_tx_eth.eth_type),
+    .s_eth_payload_axis_tdata           (mac_tx_eth.eth_payload_axis_tdata),
+    .s_eth_payload_axis_tkeep           (mac_tx_eth.eth_payload_axis_tkeep),
+    .s_eth_payload_axis_tvalid          (mac_tx_eth.eth_payload_axis_tvalid),
+    .s_eth_payload_axis_tready          (mac_tx_eth.eth_payload_axis_tready),
+    .s_eth_payload_axis_tlast           (mac_tx_eth.eth_payload_axis_tlast),
+    .s_eth_payload_axis_tuser           (mac_tx_eth.eth_payload_axis_tuser),
+
+    .m_axis_tdata                       (mac_tx_axis.tdata),
+    .m_axis_tvalid                      (mac_tx_axis.tvalid),
+    .m_axis_tready                      (mac_tx_axis.tready),
+    .m_axis_tlast                       (mac_tx_axis.tlast),
+    .m_axis_tuser                       (mac_tx_axis.tuser),
+    .m_axis_tkeep                       (mac_tx_axis.tkeep),
+
+    .busy                               ()
+);
+
+
+// this is 8 bit only, we should assert that data width is 8 at this point.
+
+ip_complete #(
+    .ARP_CACHE_ADDR_WIDTH(7),    // memory usage is 81 bits per entry
+    .ARP_REQUEST_RETRY_COUNT(4),
+    .ARP_REQUEST_RETRY_INTERVAL(125000000*2),   // these are defaults
+    .ARP_REQUEST_TIMEOUT(125000000*30)
+) u_ip_complete (
+    .clk                                (i_clk),
+    .rst                                (i_rst),
+
+    .s_eth_hdr_valid                    (mac_rx_eth.eth_hdr_valid),
+    .s_eth_hdr_ready                    (mac_rx_eth.eth_hdr_ready),
+    .s_eth_dest_mac                     (mac_rx_eth.eth_dest_mac),
+    .s_eth_src_mac                      (mac_rx_eth.eth_src_mac),
+    .s_eth_type                         (mac_rx_eth.eth_type),
+    .s_eth_payload_axis_tdata           (mac_rx_eth.eth_payload_axis_tdata),
+    .s_eth_payload_axis_tvalid          (mac_rx_eth.eth_payload_axis_tvalid),
+    .s_eth_payload_axis_tready          (mac_rx_eth.eth_payload_axis_tready),
+    .s_eth_payload_axis_tlast           (mac_rx_eth.eth_payload_axis_tlast),
+    .s_eth_payload_axis_tuser           (mac_rx_eth.eth_payload_axis_tuser),
+
+    .m_eth_hdr_valid                    (mac_tx_eth.eth_hdr_valid),
+    .m_eth_hdr_ready                    (mac_tx_eth.eth_hdr_ready),
+    .m_eth_dest_mac                     (mac_tx_eth.eth_dest_mac),
+    .m_eth_src_mac                      (mac_tx_eth.eth_src_mac),
+    .m_eth_type                         (mac_tx_eth.eth_type),
+    .m_eth_payload_axis_tdata           (mac_tx_eth.eth_payload_axis_tdata),
+    .m_eth_payload_axis_tvalid          (mac_tx_eth.eth_payload_axis_tvalid),
+    .m_eth_payload_axis_tready          (mac_tx_eth.eth_payload_axis_tready),
+    .m_eth_payload_axis_tlast           (mac_tx_eth.eth_payload_axis_tlast),
+    .m_eth_payload_axis_tuser           (mac_tx_eth.eth_payload_axis_tuser),
+
+    .s_ip_hdr_valid                     (ntw_tx_ip.ip_hdr_valid),
+    .s_ip_hdr_ready                     (ntw_tx_ip.ip_hdr_ready),
+    .s_ip_dscp                          (ntw_tx_ip.ip_dscp),
+    .s_ip_ecn                           (ntw_tx_ip.ip_ecn),
+    .s_ip_length                        (ntw_tx_ip.ip_length),
+    .s_ip_ttl                           (ntw_tx_ip.ip_ttl),
+    .s_ip_protocol                      (ntw_tx_ip.ip_protocol),
+    .s_ip_source_ip                     (ntw_tx_ip.ip_source_ip),
+    .s_ip_dest_ip                       (ntw_tx_ip.ip_dest_ip),
+    .s_ip_payload_axis_tdata            (ntw_tx_ip.ip_payload_axis_tdata),
+    .s_ip_payload_axis_tvalid           (ntw_tx_ip.ip_payload_axis_tvalid),
+    .s_ip_payload_axis_tready           (ntw_tx_ip.ip_payload_axis_tready),
+    .s_ip_payload_axis_tlast            (ntw_tx_ip.ip_payload_axis_tlast),
+    .s_ip_payload_axis_tuser            (ntw_tx_ip.ip_payload_axis_tuser),
+
+    .m_ip_hdr_valid                     (ntw_rx_ip.ip_hdr_valid),
+    .m_ip_hdr_ready                     (ntw_rx_ip.ip_hdr_ready),
+    .m_ip_eth_dest_mac                  (ntw_rx_ip.eth_dest_mac),
+    .m_ip_eth_src_mac                   (ntw_rx_ip.eth_src_mac),
+    .m_ip_eth_type                      (ntw_rx_ip.eth_type),
+    .m_ip_version                       (ntw_rx_ip.ip_version),
+    .m_ip_ihl                           (ntw_rx_ip.ip_ihl),
+    .m_ip_dscp                          (ntw_rx_ip.ip_dscp),
+    .m_ip_ecn                           (ntw_rx_ip.ip_ecn),
+    .m_ip_length                        (ntw_rx_ip.ip_length),
+    .m_ip_identification                (ntw_rx_ip.ip_identification),
+    .m_ip_flags                         (ntw_rx_ip.ip_flags),
+    .m_ip_fragment_offset               (ntw_rx_ip.ip_fragment_offset),
+    .m_ip_ttl                           (ntw_rx_ip.ip_ttl),
+    .m_ip_protocol                      (ntw_rx_ip.ip_protocol),
+    .m_ip_header_checksum               (ntw_rx_ip.ip_header_checksum),
+    .m_ip_source_ip                     (ntw_rx_ip.ip_source_ip),
+    .m_ip_dest_ip                       (ntw_rx_ip.ip_dest_ip),
+    .m_ip_payload_axis_tdata            (ntw_rx_ip.ip_payload_axis_tdata),
+    .m_ip_payload_axis_tvalid           (ntw_rx_ip.ip_payload_axis_tvalid),
+    .m_ip_payload_axis_tready           (ntw_rx_ip.ip_payload_axis_tready),
+    .m_ip_payload_axis_tlast            (ntw_rx_ip.ip_payload_axis_tlast),
+    .m_ip_payload_axis_tuser            (ntw_rx_ip.ip_payload_axis_tuser),
+
+    .rx_busy                            (), // should go to stats register
+    .tx_busy                            (), // should go to stats register
+    .rx_error_header_early_termination  (), // should go to stats register
+    .rx_error_payload_early_termination (), // should go to stats register
+    .rx_error_invalid_header            (), // should go to stats register
+    .rx_error_invalid_checksum          (), // should go to stats register
+    .tx_error_payload_early_termination (), // should go to stats register
+    .tx_error_arp_failed                (), // should go to stats register
+
+    .local_mac                          (48'h020000aabbcc), // should be a register
+    .local_ip                           (32'hAC000002),     // should be a register
+    .gateway_ip                         (32'hAC000001),     // should be a register
+    .subnet_mask                        (32'hffffff00),     // should be a register
+    .clear_arp_cache                    ('0)                // should come from sw
+);
+
+
+logic ip_demux_drop;
+assign ip_demux_drop = !((ntw_rx_ip.ip_protocol == `PROTO_ICMP) || (ntw_rx_ip.ip_protocol == `PROTO_UDP) || (ntw_rx_ip.ip_protocol == `PROTO_TCP));
+
+logic [1:0] ip_demux_sel;
+assign ip_demux_sel = (ntw_rx_ip.ip_protocol == `PROTO_ICMP) ? 2'h2 : (ntw_rx_ip.ip_protocol == `PROTO_UDP) ? 2'h1 : 2'h0;
+
+
+ip_demux_wrapper #(
+    .M_COUNT(3),
+    .DATA_WIDTH(MAC_DATA_WIDTH)
+) u_ip_demux (
+    .clk                                (i_clk),
+    .rst                                (i_rst),
+
+    .s_ip                               (ntw_rx_ip),
+    .m_ip                               (proto_rx_ip),
+
+    .enable                             ('1),
+    .drop                               (ip_demux_drop),
+    .select                             (ip_demux_sel)
+);
+
+assign proto_rx_ip[ICMP_IDX].ip_hdr_ready = '1;
+assign proto_rx_ip[ICMP_IDX].ip_payload_axis_tready = '1;
+assign proto_rx_ip[UDP_IDX].ip_hdr_ready = '1;
+assign proto_rx_ip[UDP_IDX].ip_payload_axis_tready = '1;
+
+ip_arb_mux_wrapper #(
+    .S_COUNT(3),
+    .DATA_WIDTH(MAC_DATA_WIDTH)
+)  u_ip_arb_mux (
+    .i_clk                              (i_clk),
+    .i_rst                              (i_rst),
+
+    .s_ip                               (proto_tx_ip),
+    .m_ip                               (ntw_tx_ip)
+);
+
+tcp #(
+    .NUM_TCP(NUM_TCP)
+) tcp (
+    .i_clk                              (i_clk),
+    .i_rst                              (i_rst),
+
+    .s_cpuif_req                        (hwif_out.tcp_top.req),
+    .s_cpuif_req_is_wr                  (hwif_out.tcp_top.req_is_wr),
+    .s_cpuif_addr                       (hwif_out.tcp_top.addr),
+    .s_cpuif_wr_data                    (hwif_out.tcp_top.wr_data),
+    .s_cpuif_wr_biten                   (hwif_out.tcp_top.wr_biten),
+    .s_cpuif_req_stall_wr               (),
+    .s_cpuif_req_stall_rd               (),
+    .s_cpuif_rd_ack                     (hwif_in.tcp_top.rd_ack),
+    .s_cpuif_rd_err                     (),
+    .s_cpuif_rd_data                    (hwif_in.tcp_top.rd_data),
+    .s_cpuif_wr_ack                     (hwif_in.tcp_top.wr_ack),
+    .s_cpuif_wr_err                     (),
+
+    .s_ip                               (proto_rx_ip[TCP_IDX]),
+    .m_ip                               (proto_tx_ip[TCP_IDX]),
+
+    .m_dma_axil                         (m_dma_axil)
+);
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/mac_regs.rdl b/hw/super6502_fpga/src/sub/network_processor/src/regs/mac_regs.rdl
new file mode 100644
index 0000000000000000000000000000000000000000..e3d2a38f38132fc8cb4b9f497381f3e6c4253235
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/mac_regs.rdl
@@ -0,0 +1,121 @@
+addrmap mac_regs {
+    reg {
+        name = "Control";
+        desc = "Control bits for the MAC";
+
+        field {
+            name = "TX Enable";
+            desc = "Enable TX";
+            hw   = r;
+            sw   = rw;
+        } tx_en[0:0] = 0x0;
+
+        field {
+            name = "RX Enable";
+            desc = "Enable RX";
+            hw   = r;
+            sw   = rw;
+        } rx_en[1:1] = 0x0;
+
+        field {
+            name = "PHY Reset";
+            desc = "phy_rstn";
+            hw   = r;
+            sw   = rw;
+        } phy_rstn[2:2] = 0x1;
+
+        field {
+            name = "Interframe Gap";
+            desc = "Interframe gap in mii clock cycles";
+            hw   = r;
+            sw   = rw;
+        } ifg[15:8] = 0x0;
+
+    } ctrl @ 0x0;
+
+    reg {
+        name = "Error";
+        desc = "Latched Error from the MAC";
+
+        field {
+            name = "tx_error_underflow";
+            desc = "";
+            hw   = r;
+            sw   = r;
+            rclr;
+            hwset;
+        } tx_error_underflow[0:0] = 0x0;
+
+        field {
+            name = "tx_fifo_overflow";
+            desc = "";
+            hw   = r;
+            sw   = r;
+            rclr;
+            hwset;
+        } tx_fifo_overflow[1:1] = 0x0;
+
+        field {
+            name = "tx_fifo_bad_frame";
+            desc = "";
+            hw   = r;
+            sw   = r;
+            rclr;
+            hwset;
+        } tx_fifo_bad_frame[2:2] = 0x0;
+
+        field {
+            name = "tx_fifo_good_frame";
+            desc = "";
+            hw   = r;
+            sw   = r;
+            rclr;
+            hwset;
+        } tx_fifo_good_frame[3:3] = 0x0;
+
+        field {
+            name = "rx_error_bad_frame";
+            desc = "";
+            hw   = r;
+            sw   = r;
+            rclr;
+            hwset;
+        } rx_error_bad_frame[4:4] = 0x0;
+
+        field {
+            name = "rx_error_bad_fcs";
+            desc = "";
+            hw   = r;
+            sw   = r;
+            rclr;
+            hwset;
+        } rx_error_bad_fcs[5:5] = 0x0;
+
+        field {
+            name = "rx_fifo_overflow";
+            desc = "";
+            hw   = r;
+            sw   = r;
+            rclr;
+            hwset;
+        } rx_fifo_overflow[6:6] = 0x0;
+
+        field {
+            name = "rx_fifo_bad_frame";
+            desc = "";
+            hw   = r;
+            sw   = r;
+            rclr;
+            hwset;
+        } rx_fifo_bad_frame[7:7] = 0x0;
+
+        field {
+            name = "rx_fifo_good_frame";
+            desc = "";
+            hw   = r;
+            sw   = r;
+            rclr;
+            hwset;
+        } rx_fifo_good_frame[8:8] = 0x0;
+    } stats @ 0x4;
+};
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/mac_regs.sv b/hw/super6502_fpga/src/sub/network_processor/src/regs/mac_regs.sv
new file mode 100644
index 0000000000000000000000000000000000000000..e82bf2d7fe9402c85af4480f856e34d8edfb4a0a
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/mac_regs.sv
@@ -0,0 +1,547 @@
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+//  https://github.com/SystemRDL/PeakRDL-regblock
+
+module mac_regs (
+        input wire clk,
+        input wire rst,
+
+        input wire s_cpuif_req,
+        input wire s_cpuif_req_is_wr,
+        input wire [2:0] s_cpuif_addr,
+        input wire [31:0] s_cpuif_wr_data,
+        input wire [31:0] s_cpuif_wr_biten,
+        output wire s_cpuif_req_stall_wr,
+        output wire s_cpuif_req_stall_rd,
+        output wire s_cpuif_rd_ack,
+        output wire s_cpuif_rd_err,
+        output wire [31:0] s_cpuif_rd_data,
+        output wire s_cpuif_wr_ack,
+        output wire s_cpuif_wr_err,
+
+        input mac_regs_pkg::mac_regs__in_t hwif_in,
+        output mac_regs_pkg::mac_regs__out_t hwif_out
+    );
+
+    //--------------------------------------------------------------------------
+    // CPU Bus interface logic
+    //--------------------------------------------------------------------------
+    logic cpuif_req;
+    logic cpuif_req_is_wr;
+    logic [2:0] cpuif_addr;
+    logic [31:0] cpuif_wr_data;
+    logic [31:0] cpuif_wr_biten;
+    logic cpuif_req_stall_wr;
+    logic cpuif_req_stall_rd;
+
+    logic cpuif_rd_ack;
+    logic cpuif_rd_err;
+    logic [31:0] cpuif_rd_data;
+
+    logic cpuif_wr_ack;
+    logic cpuif_wr_err;
+
+    assign cpuif_req = s_cpuif_req;
+    assign cpuif_req_is_wr = s_cpuif_req_is_wr;
+    assign cpuif_addr = s_cpuif_addr;
+    assign cpuif_wr_data = s_cpuif_wr_data;
+    assign cpuif_wr_biten = s_cpuif_wr_biten;
+    assign s_cpuif_req_stall_wr = cpuif_req_stall_wr;
+    assign s_cpuif_req_stall_rd = cpuif_req_stall_rd;
+    assign s_cpuif_rd_ack = cpuif_rd_ack;
+    assign s_cpuif_rd_err = cpuif_rd_err;
+    assign s_cpuif_rd_data = cpuif_rd_data;
+    assign s_cpuif_wr_ack = cpuif_wr_ack;
+    assign s_cpuif_wr_err = cpuif_wr_err;
+
+    logic cpuif_req_masked;
+
+    // Read & write latencies are balanced. Stalls not required
+    assign cpuif_req_stall_rd = '0;
+    assign cpuif_req_stall_wr = '0;
+    assign cpuif_req_masked = cpuif_req
+                            & !(!cpuif_req_is_wr & cpuif_req_stall_rd)
+                            & !(cpuif_req_is_wr & cpuif_req_stall_wr);
+
+    //--------------------------------------------------------------------------
+    // Address Decode
+    //--------------------------------------------------------------------------
+    typedef struct {
+        logic ctrl;
+        logic stats;
+    } decoded_reg_strb_t;
+    decoded_reg_strb_t decoded_reg_strb;
+    logic decoded_req;
+    logic decoded_req_is_wr;
+    logic [31:0] decoded_wr_data;
+    logic [31:0] decoded_wr_biten;
+
+    always_comb begin
+        decoded_reg_strb.ctrl = cpuif_req_masked & (cpuif_addr == 3'h0);
+        decoded_reg_strb.stats = cpuif_req_masked & (cpuif_addr == 3'h4);
+    end
+
+    // Pass down signals to next stage
+    assign decoded_req = cpuif_req_masked;
+    assign decoded_req_is_wr = cpuif_req_is_wr;
+    assign decoded_wr_data = cpuif_wr_data;
+    assign decoded_wr_biten = cpuif_wr_biten;
+
+    //--------------------------------------------------------------------------
+    // Field logic
+    //--------------------------------------------------------------------------
+    typedef struct {
+        struct {
+            struct {
+                logic next;
+                logic load_next;
+            } tx_en;
+            struct {
+                logic next;
+                logic load_next;
+            } rx_en;
+            struct {
+                logic next;
+                logic load_next;
+            } phy_rstn;
+            struct {
+                logic [7:0] next;
+                logic load_next;
+            } ifg;
+        } ctrl;
+        struct {
+            struct {
+                logic next;
+                logic load_next;
+            } tx_error_underflow;
+            struct {
+                logic next;
+                logic load_next;
+            } tx_fifo_overflow;
+            struct {
+                logic next;
+                logic load_next;
+            } tx_fifo_bad_frame;
+            struct {
+                logic next;
+                logic load_next;
+            } tx_fifo_good_frame;
+            struct {
+                logic next;
+                logic load_next;
+            } rx_error_bad_frame;
+            struct {
+                logic next;
+                logic load_next;
+            } rx_error_bad_fcs;
+            struct {
+                logic next;
+                logic load_next;
+            } rx_fifo_overflow;
+            struct {
+                logic next;
+                logic load_next;
+            } rx_fifo_bad_frame;
+            struct {
+                logic next;
+                logic load_next;
+            } rx_fifo_good_frame;
+        } stats;
+    } field_combo_t;
+    field_combo_t field_combo;
+
+    typedef struct {
+        struct {
+            struct {
+                logic value;
+            } tx_en;
+            struct {
+                logic value;
+            } rx_en;
+            struct {
+                logic value;
+            } phy_rstn;
+            struct {
+                logic [7:0] value;
+            } ifg;
+        } ctrl;
+        struct {
+            struct {
+                logic value;
+            } tx_error_underflow;
+            struct {
+                logic value;
+            } tx_fifo_overflow;
+            struct {
+                logic value;
+            } tx_fifo_bad_frame;
+            struct {
+                logic value;
+            } tx_fifo_good_frame;
+            struct {
+                logic value;
+            } rx_error_bad_frame;
+            struct {
+                logic value;
+            } rx_error_bad_fcs;
+            struct {
+                logic value;
+            } rx_fifo_overflow;
+            struct {
+                logic value;
+            } rx_fifo_bad_frame;
+            struct {
+                logic value;
+            } rx_fifo_good_frame;
+        } stats;
+    } field_storage_t;
+    field_storage_t field_storage;
+
+    // Field: mac_regs.ctrl.tx_en
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.ctrl.tx_en.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.ctrl && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.ctrl.tx_en.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]);
+            load_next_c = '1;
+        end
+        field_combo.ctrl.tx_en.next = next_c;
+        field_combo.ctrl.tx_en.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.ctrl.tx_en.value <= 1'h0;
+        end else if(field_combo.ctrl.tx_en.load_next) begin
+            field_storage.ctrl.tx_en.value <= field_combo.ctrl.tx_en.next;
+        end
+    end
+    assign hwif_out.ctrl.tx_en.value = field_storage.ctrl.tx_en.value;
+    // Field: mac_regs.ctrl.rx_en
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.ctrl.rx_en.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.ctrl && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.ctrl.rx_en.value & ~decoded_wr_biten[1:1]) | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]);
+            load_next_c = '1;
+        end
+        field_combo.ctrl.rx_en.next = next_c;
+        field_combo.ctrl.rx_en.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.ctrl.rx_en.value <= 1'h0;
+        end else if(field_combo.ctrl.rx_en.load_next) begin
+            field_storage.ctrl.rx_en.value <= field_combo.ctrl.rx_en.next;
+        end
+    end
+    assign hwif_out.ctrl.rx_en.value = field_storage.ctrl.rx_en.value;
+    // Field: mac_regs.ctrl.phy_rstn
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.ctrl.phy_rstn.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.ctrl && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.ctrl.phy_rstn.value & ~decoded_wr_biten[2:2]) | (decoded_wr_data[2:2] & decoded_wr_biten[2:2]);
+            load_next_c = '1;
+        end
+        field_combo.ctrl.phy_rstn.next = next_c;
+        field_combo.ctrl.phy_rstn.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.ctrl.phy_rstn.value <= 1'h1;
+        end else if(field_combo.ctrl.phy_rstn.load_next) begin
+            field_storage.ctrl.phy_rstn.value <= field_combo.ctrl.phy_rstn.next;
+        end
+    end
+    assign hwif_out.ctrl.phy_rstn.value = field_storage.ctrl.phy_rstn.value;
+    // Field: mac_regs.ctrl.ifg
+    always_comb begin
+        automatic logic [7:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.ctrl.ifg.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.ctrl && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.ctrl.ifg.value & ~decoded_wr_biten[15:8]) | (decoded_wr_data[15:8] & decoded_wr_biten[15:8]);
+            load_next_c = '1;
+        end
+        field_combo.ctrl.ifg.next = next_c;
+        field_combo.ctrl.ifg.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.ctrl.ifg.value <= 8'h0;
+        end else if(field_combo.ctrl.ifg.load_next) begin
+            field_storage.ctrl.ifg.value <= field_combo.ctrl.ifg.next;
+        end
+    end
+    assign hwif_out.ctrl.ifg.value = field_storage.ctrl.ifg.value;
+    // Field: mac_regs.stats.tx_error_underflow
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.stats.tx_error_underflow.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.stats && !decoded_req_is_wr) begin // SW clear on read
+            next_c = '0;
+            load_next_c = '1;
+        end else if(hwif_in.stats.tx_error_underflow.hwset) begin // HW Set
+            next_c = '1;
+            load_next_c = '1;
+        end
+        field_combo.stats.tx_error_underflow.next = next_c;
+        field_combo.stats.tx_error_underflow.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.stats.tx_error_underflow.value <= 1'h0;
+        end else if(field_combo.stats.tx_error_underflow.load_next) begin
+            field_storage.stats.tx_error_underflow.value <= field_combo.stats.tx_error_underflow.next;
+        end
+    end
+    assign hwif_out.stats.tx_error_underflow.value = field_storage.stats.tx_error_underflow.value;
+    // Field: mac_regs.stats.tx_fifo_overflow
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.stats.tx_fifo_overflow.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.stats && !decoded_req_is_wr) begin // SW clear on read
+            next_c = '0;
+            load_next_c = '1;
+        end else if(hwif_in.stats.tx_fifo_overflow.hwset) begin // HW Set
+            next_c = '1;
+            load_next_c = '1;
+        end
+        field_combo.stats.tx_fifo_overflow.next = next_c;
+        field_combo.stats.tx_fifo_overflow.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.stats.tx_fifo_overflow.value <= 1'h0;
+        end else if(field_combo.stats.tx_fifo_overflow.load_next) begin
+            field_storage.stats.tx_fifo_overflow.value <= field_combo.stats.tx_fifo_overflow.next;
+        end
+    end
+    assign hwif_out.stats.tx_fifo_overflow.value = field_storage.stats.tx_fifo_overflow.value;
+    // Field: mac_regs.stats.tx_fifo_bad_frame
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.stats.tx_fifo_bad_frame.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.stats && !decoded_req_is_wr) begin // SW clear on read
+            next_c = '0;
+            load_next_c = '1;
+        end else if(hwif_in.stats.tx_fifo_bad_frame.hwset) begin // HW Set
+            next_c = '1;
+            load_next_c = '1;
+        end
+        field_combo.stats.tx_fifo_bad_frame.next = next_c;
+        field_combo.stats.tx_fifo_bad_frame.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.stats.tx_fifo_bad_frame.value <= 1'h0;
+        end else if(field_combo.stats.tx_fifo_bad_frame.load_next) begin
+            field_storage.stats.tx_fifo_bad_frame.value <= field_combo.stats.tx_fifo_bad_frame.next;
+        end
+    end
+    assign hwif_out.stats.tx_fifo_bad_frame.value = field_storage.stats.tx_fifo_bad_frame.value;
+    // Field: mac_regs.stats.tx_fifo_good_frame
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.stats.tx_fifo_good_frame.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.stats && !decoded_req_is_wr) begin // SW clear on read
+            next_c = '0;
+            load_next_c = '1;
+        end else if(hwif_in.stats.tx_fifo_good_frame.hwset) begin // HW Set
+            next_c = '1;
+            load_next_c = '1;
+        end
+        field_combo.stats.tx_fifo_good_frame.next = next_c;
+        field_combo.stats.tx_fifo_good_frame.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.stats.tx_fifo_good_frame.value <= 1'h0;
+        end else if(field_combo.stats.tx_fifo_good_frame.load_next) begin
+            field_storage.stats.tx_fifo_good_frame.value <= field_combo.stats.tx_fifo_good_frame.next;
+        end
+    end
+    assign hwif_out.stats.tx_fifo_good_frame.value = field_storage.stats.tx_fifo_good_frame.value;
+    // Field: mac_regs.stats.rx_error_bad_frame
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.stats.rx_error_bad_frame.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.stats && !decoded_req_is_wr) begin // SW clear on read
+            next_c = '0;
+            load_next_c = '1;
+        end else if(hwif_in.stats.rx_error_bad_frame.hwset) begin // HW Set
+            next_c = '1;
+            load_next_c = '1;
+        end
+        field_combo.stats.rx_error_bad_frame.next = next_c;
+        field_combo.stats.rx_error_bad_frame.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.stats.rx_error_bad_frame.value <= 1'h0;
+        end else if(field_combo.stats.rx_error_bad_frame.load_next) begin
+            field_storage.stats.rx_error_bad_frame.value <= field_combo.stats.rx_error_bad_frame.next;
+        end
+    end
+    assign hwif_out.stats.rx_error_bad_frame.value = field_storage.stats.rx_error_bad_frame.value;
+    // Field: mac_regs.stats.rx_error_bad_fcs
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.stats.rx_error_bad_fcs.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.stats && !decoded_req_is_wr) begin // SW clear on read
+            next_c = '0;
+            load_next_c = '1;
+        end else if(hwif_in.stats.rx_error_bad_fcs.hwset) begin // HW Set
+            next_c = '1;
+            load_next_c = '1;
+        end
+        field_combo.stats.rx_error_bad_fcs.next = next_c;
+        field_combo.stats.rx_error_bad_fcs.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.stats.rx_error_bad_fcs.value <= 1'h0;
+        end else if(field_combo.stats.rx_error_bad_fcs.load_next) begin
+            field_storage.stats.rx_error_bad_fcs.value <= field_combo.stats.rx_error_bad_fcs.next;
+        end
+    end
+    assign hwif_out.stats.rx_error_bad_fcs.value = field_storage.stats.rx_error_bad_fcs.value;
+    // Field: mac_regs.stats.rx_fifo_overflow
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.stats.rx_fifo_overflow.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.stats && !decoded_req_is_wr) begin // SW clear on read
+            next_c = '0;
+            load_next_c = '1;
+        end else if(hwif_in.stats.rx_fifo_overflow.hwset) begin // HW Set
+            next_c = '1;
+            load_next_c = '1;
+        end
+        field_combo.stats.rx_fifo_overflow.next = next_c;
+        field_combo.stats.rx_fifo_overflow.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.stats.rx_fifo_overflow.value <= 1'h0;
+        end else if(field_combo.stats.rx_fifo_overflow.load_next) begin
+            field_storage.stats.rx_fifo_overflow.value <= field_combo.stats.rx_fifo_overflow.next;
+        end
+    end
+    assign hwif_out.stats.rx_fifo_overflow.value = field_storage.stats.rx_fifo_overflow.value;
+    // Field: mac_regs.stats.rx_fifo_bad_frame
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.stats.rx_fifo_bad_frame.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.stats && !decoded_req_is_wr) begin // SW clear on read
+            next_c = '0;
+            load_next_c = '1;
+        end else if(hwif_in.stats.rx_fifo_bad_frame.hwset) begin // HW Set
+            next_c = '1;
+            load_next_c = '1;
+        end
+        field_combo.stats.rx_fifo_bad_frame.next = next_c;
+        field_combo.stats.rx_fifo_bad_frame.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.stats.rx_fifo_bad_frame.value <= 1'h0;
+        end else if(field_combo.stats.rx_fifo_bad_frame.load_next) begin
+            field_storage.stats.rx_fifo_bad_frame.value <= field_combo.stats.rx_fifo_bad_frame.next;
+        end
+    end
+    assign hwif_out.stats.rx_fifo_bad_frame.value = field_storage.stats.rx_fifo_bad_frame.value;
+    // Field: mac_regs.stats.rx_fifo_good_frame
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.stats.rx_fifo_good_frame.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.stats && !decoded_req_is_wr) begin // SW clear on read
+            next_c = '0;
+            load_next_c = '1;
+        end else if(hwif_in.stats.rx_fifo_good_frame.hwset) begin // HW Set
+            next_c = '1;
+            load_next_c = '1;
+        end
+        field_combo.stats.rx_fifo_good_frame.next = next_c;
+        field_combo.stats.rx_fifo_good_frame.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.stats.rx_fifo_good_frame.value <= 1'h0;
+        end else if(field_combo.stats.rx_fifo_good_frame.load_next) begin
+            field_storage.stats.rx_fifo_good_frame.value <= field_combo.stats.rx_fifo_good_frame.next;
+        end
+    end
+    assign hwif_out.stats.rx_fifo_good_frame.value = field_storage.stats.rx_fifo_good_frame.value;
+
+    //--------------------------------------------------------------------------
+    // Write response
+    //--------------------------------------------------------------------------
+    assign cpuif_wr_ack = decoded_req & decoded_req_is_wr;
+    // Writes are always granted with no error response
+    assign cpuif_wr_err = '0;
+
+    //--------------------------------------------------------------------------
+    // Readback
+    //--------------------------------------------------------------------------
+
+    logic readback_err;
+    logic readback_done;
+    logic [31:0] readback_data;
+
+    // Assign readback values to a flattened array
+    logic [31:0] readback_array[2];
+    assign readback_array[0][0:0] = (decoded_reg_strb.ctrl && !decoded_req_is_wr) ? field_storage.ctrl.tx_en.value : '0;
+    assign readback_array[0][1:1] = (decoded_reg_strb.ctrl && !decoded_req_is_wr) ? field_storage.ctrl.rx_en.value : '0;
+    assign readback_array[0][2:2] = (decoded_reg_strb.ctrl && !decoded_req_is_wr) ? field_storage.ctrl.phy_rstn.value : '0;
+    assign readback_array[0][7:3] = '0;
+    assign readback_array[0][15:8] = (decoded_reg_strb.ctrl && !decoded_req_is_wr) ? field_storage.ctrl.ifg.value : '0;
+    assign readback_array[0][31:16] = '0;
+    assign readback_array[1][0:0] = (decoded_reg_strb.stats && !decoded_req_is_wr) ? field_storage.stats.tx_error_underflow.value : '0;
+    assign readback_array[1][1:1] = (decoded_reg_strb.stats && !decoded_req_is_wr) ? field_storage.stats.tx_fifo_overflow.value : '0;
+    assign readback_array[1][2:2] = (decoded_reg_strb.stats && !decoded_req_is_wr) ? field_storage.stats.tx_fifo_bad_frame.value : '0;
+    assign readback_array[1][3:3] = (decoded_reg_strb.stats && !decoded_req_is_wr) ? field_storage.stats.tx_fifo_good_frame.value : '0;
+    assign readback_array[1][4:4] = (decoded_reg_strb.stats && !decoded_req_is_wr) ? field_storage.stats.rx_error_bad_frame.value : '0;
+    assign readback_array[1][5:5] = (decoded_reg_strb.stats && !decoded_req_is_wr) ? field_storage.stats.rx_error_bad_fcs.value : '0;
+    assign readback_array[1][6:6] = (decoded_reg_strb.stats && !decoded_req_is_wr) ? field_storage.stats.rx_fifo_overflow.value : '0;
+    assign readback_array[1][7:7] = (decoded_reg_strb.stats && !decoded_req_is_wr) ? field_storage.stats.rx_fifo_bad_frame.value : '0;
+    assign readback_array[1][8:8] = (decoded_reg_strb.stats && !decoded_req_is_wr) ? field_storage.stats.rx_fifo_good_frame.value : '0;
+    assign readback_array[1][31:9] = '0;
+
+    // Reduce the array
+    always_comb begin
+        automatic logic [31:0] readback_data_var;
+        readback_done = decoded_req & ~decoded_req_is_wr;
+        readback_err = '0;
+        readback_data_var = '0;
+        for(int i=0; i<2; i++) readback_data_var |= readback_array[i];
+        readback_data = readback_data_var;
+    end
+
+    assign cpuif_rd_ack = readback_done;
+    assign cpuif_rd_data = readback_data;
+    assign cpuif_rd_err = readback_err;
+endmodule
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/mac_regs_pkg.sv b/hw/super6502_fpga/src/sub/network_processor/src/regs/mac_regs_pkg.sv
new file mode 100644
index 0000000000000000000000000000000000000000..30f6de4ffcd2403a5e5cae6bff80113b6451f531
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/mac_regs_pkg.sv
@@ -0,0 +1,136 @@
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+//  https://github.com/SystemRDL/PeakRDL-regblock
+
+package mac_regs_pkg;
+
+    localparam MAC_REGS_DATA_WIDTH = 32;
+    localparam MAC_REGS_MIN_ADDR_WIDTH = 3;
+
+    typedef struct {
+        logic hwset;
+    } mac_regs__stats__tx_error_underflow__in_t;
+
+    typedef struct {
+        logic hwset;
+    } mac_regs__stats__tx_fifo_overflow__in_t;
+
+    typedef struct {
+        logic hwset;
+    } mac_regs__stats__tx_fifo_bad_frame__in_t;
+
+    typedef struct {
+        logic hwset;
+    } mac_regs__stats__tx_fifo_good_frame__in_t;
+
+    typedef struct {
+        logic hwset;
+    } mac_regs__stats__rx_error_bad_frame__in_t;
+
+    typedef struct {
+        logic hwset;
+    } mac_regs__stats__rx_error_bad_fcs__in_t;
+
+    typedef struct {
+        logic hwset;
+    } mac_regs__stats__rx_fifo_overflow__in_t;
+
+    typedef struct {
+        logic hwset;
+    } mac_regs__stats__rx_fifo_bad_frame__in_t;
+
+    typedef struct {
+        logic hwset;
+    } mac_regs__stats__rx_fifo_good_frame__in_t;
+
+    typedef struct {
+        mac_regs__stats__tx_error_underflow__in_t tx_error_underflow;
+        mac_regs__stats__tx_fifo_overflow__in_t tx_fifo_overflow;
+        mac_regs__stats__tx_fifo_bad_frame__in_t tx_fifo_bad_frame;
+        mac_regs__stats__tx_fifo_good_frame__in_t tx_fifo_good_frame;
+        mac_regs__stats__rx_error_bad_frame__in_t rx_error_bad_frame;
+        mac_regs__stats__rx_error_bad_fcs__in_t rx_error_bad_fcs;
+        mac_regs__stats__rx_fifo_overflow__in_t rx_fifo_overflow;
+        mac_regs__stats__rx_fifo_bad_frame__in_t rx_fifo_bad_frame;
+        mac_regs__stats__rx_fifo_good_frame__in_t rx_fifo_good_frame;
+    } mac_regs__stats__in_t;
+
+    typedef struct {
+        mac_regs__stats__in_t stats;
+    } mac_regs__in_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__ctrl__tx_en__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__ctrl__rx_en__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__ctrl__phy_rstn__out_t;
+
+    typedef struct {
+        logic [7:0] value;
+    } mac_regs__ctrl__ifg__out_t;
+
+    typedef struct {
+        mac_regs__ctrl__tx_en__out_t tx_en;
+        mac_regs__ctrl__rx_en__out_t rx_en;
+        mac_regs__ctrl__phy_rstn__out_t phy_rstn;
+        mac_regs__ctrl__ifg__out_t ifg;
+    } mac_regs__ctrl__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__stats__tx_error_underflow__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__stats__tx_fifo_overflow__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__stats__tx_fifo_bad_frame__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__stats__tx_fifo_good_frame__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__stats__rx_error_bad_frame__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__stats__rx_error_bad_fcs__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__stats__rx_fifo_overflow__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__stats__rx_fifo_bad_frame__out_t;
+
+    typedef struct {
+        logic value;
+    } mac_regs__stats__rx_fifo_good_frame__out_t;
+
+    typedef struct {
+        mac_regs__stats__tx_error_underflow__out_t tx_error_underflow;
+        mac_regs__stats__tx_fifo_overflow__out_t tx_fifo_overflow;
+        mac_regs__stats__tx_fifo_bad_frame__out_t tx_fifo_bad_frame;
+        mac_regs__stats__tx_fifo_good_frame__out_t tx_fifo_good_frame;
+        mac_regs__stats__rx_error_bad_frame__out_t rx_error_bad_frame;
+        mac_regs__stats__rx_error_bad_fcs__out_t rx_error_bad_fcs;
+        mac_regs__stats__rx_fifo_overflow__out_t rx_fifo_overflow;
+        mac_regs__stats__rx_fifo_bad_frame__out_t rx_fifo_bad_frame;
+        mac_regs__stats__rx_fifo_good_frame__out_t rx_fifo_good_frame;
+    } mac_regs__stats__out_t;
+
+    typedef struct {
+        mac_regs__ctrl__out_t ctrl;
+        mac_regs__stats__out_t stats;
+    } mac_regs__out_t;
+endpackage
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/ntw_top_regfile.sv b/hw/super6502_fpga/src/sub/network_processor/src/regs/ntw_top_regfile.sv
new file mode 100644
index 0000000000000000000000000000000000000000..6dc267e89bdbcd7794089f1453489fc879dbb3e1
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/ntw_top_regfile.sv
@@ -0,0 +1,350 @@
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+//  https://github.com/SystemRDL/PeakRDL-regblock
+
+module ntw_top_regfile (
+        input wire clk,
+        input wire rst,
+
+        output logic s_axil_awready,
+        input wire s_axil_awvalid,
+        input wire [9:0] s_axil_awaddr,
+        input wire [2:0] s_axil_awprot,
+        output logic s_axil_wready,
+        input wire s_axil_wvalid,
+        input wire [31:0] s_axil_wdata,
+        input wire [3:0]s_axil_wstrb,
+        input wire s_axil_bready,
+        output logic s_axil_bvalid,
+        output logic [1:0] s_axil_bresp,
+        output logic s_axil_arready,
+        input wire s_axil_arvalid,
+        input wire [9:0] s_axil_araddr,
+        input wire [2:0] s_axil_arprot,
+        input wire s_axil_rready,
+        output logic s_axil_rvalid,
+        output logic [31:0] s_axil_rdata,
+        output logic [1:0] s_axil_rresp,
+
+        input ntw_top_regfile_pkg::ntw_top_regfile__in_t hwif_in,
+        output ntw_top_regfile_pkg::ntw_top_regfile__out_t hwif_out
+    );
+
+    //--------------------------------------------------------------------------
+    // CPU Bus interface logic
+    //--------------------------------------------------------------------------
+    logic cpuif_req;
+    logic cpuif_req_is_wr;
+    logic [9:0] cpuif_addr;
+    logic [31:0] cpuif_wr_data;
+    logic [31:0] cpuif_wr_biten;
+    logic cpuif_req_stall_wr;
+    logic cpuif_req_stall_rd;
+
+    logic cpuif_rd_ack;
+    logic cpuif_rd_err;
+    logic [31:0] cpuif_rd_data;
+
+    logic cpuif_wr_ack;
+    logic cpuif_wr_err;
+
+    // Max Outstanding Transactions: 2
+    logic [1:0] axil_n_in_flight;
+    logic axil_prev_was_rd;
+    logic axil_arvalid;
+    logic [9:0] axil_araddr;
+    logic axil_ar_accept;
+    logic axil_awvalid;
+    logic [9:0] axil_awaddr;
+    logic axil_wvalid;
+    logic [31:0] axil_wdata;
+    logic [3:0] axil_wstrb;
+    logic axil_aw_accept;
+    logic axil_resp_acked;
+
+    // Transaction request acceptance
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            axil_prev_was_rd <= '0;
+            axil_arvalid <= '0;
+            axil_araddr <= '0;
+            axil_awvalid <= '0;
+            axil_awaddr <= '0;
+            axil_wvalid <= '0;
+            axil_wdata <= '0;
+            axil_wstrb <= '0;
+            axil_n_in_flight <= '0;
+        end else begin
+            // AR* acceptance register
+            if(axil_ar_accept) begin
+                axil_prev_was_rd <= '1;
+                axil_arvalid <= '0;
+            end
+            if(s_axil_arvalid && s_axil_arready) begin
+                axil_arvalid <= '1;
+                axil_araddr <= s_axil_araddr;
+            end
+
+            // AW* & W* acceptance registers
+            if(axil_aw_accept) begin
+                axil_prev_was_rd <= '0;
+                axil_awvalid <= '0;
+                axil_wvalid <= '0;
+            end
+            if(s_axil_awvalid && s_axil_awready) begin
+                axil_awvalid <= '1;
+                axil_awaddr <= s_axil_awaddr;
+            end
+            if(s_axil_wvalid && s_axil_wready) begin
+                axil_wvalid <= '1;
+                axil_wdata <= s_axil_wdata;
+                axil_wstrb <= s_axil_wstrb;
+            end
+
+            // Keep track of in-flight transactions
+            if((axil_ar_accept || axil_aw_accept) && !axil_resp_acked) begin
+                axil_n_in_flight <= axil_n_in_flight + 1'b1;
+            end else if(!(axil_ar_accept || axil_aw_accept) && axil_resp_acked) begin
+                axil_n_in_flight <= axil_n_in_flight - 1'b1;
+            end
+        end
+    end
+
+    always_comb begin
+        s_axil_arready = (!axil_arvalid || axil_ar_accept);
+        s_axil_awready = (!axil_awvalid || axil_aw_accept);
+        s_axil_wready = (!axil_wvalid || axil_aw_accept);
+    end
+
+    // Request dispatch
+    always_comb begin
+        cpuif_wr_data = axil_wdata;
+        for(int i=0; i<4; i++) begin
+            cpuif_wr_biten[i*8 +: 8] = {8{axil_wstrb[i]}};
+        end
+        cpuif_req = '0;
+        cpuif_req_is_wr = '0;
+        cpuif_addr = '0;
+        axil_ar_accept = '0;
+        axil_aw_accept = '0;
+
+        if(axil_n_in_flight < 2'd2) begin
+            // Can safely issue more transactions without overwhelming response buffer
+            if(axil_arvalid && !axil_prev_was_rd) begin
+                cpuif_req = '1;
+                cpuif_req_is_wr = '0;
+                cpuif_addr = {axil_araddr[9:2], 2'b0};
+                if(!cpuif_req_stall_rd) axil_ar_accept = '1;
+            end else if(axil_awvalid && axil_wvalid) begin
+                cpuif_req = '1;
+                cpuif_req_is_wr = '1;
+                cpuif_addr = {axil_awaddr[9:2], 2'b0};
+                if(!cpuif_req_stall_wr) axil_aw_accept = '1;
+            end else if(axil_arvalid) begin
+                cpuif_req = '1;
+                cpuif_req_is_wr = '0;
+                cpuif_addr = {axil_araddr[9:2], 2'b0};
+                if(!cpuif_req_stall_rd) axil_ar_accept = '1;
+            end
+        end
+    end
+
+
+    // AXI4-Lite Response Logic
+    struct {
+        logic is_wr;
+        logic err;
+        logic [31:0] rdata;
+    } axil_resp_buffer[2];
+
+    logic [1:0] axil_resp_wptr;
+    logic [1:0] axil_resp_rptr;
+
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            for(int i=0; i<2; i++) begin
+                axil_resp_buffer[i].is_wr <= '0;
+                axil_resp_buffer[i].err <= '0;
+                axil_resp_buffer[i].rdata <= '0;
+            end
+            axil_resp_wptr <= '0;
+            axil_resp_rptr <= '0;
+        end else begin
+            // Store responses in buffer until AXI response channel accepts them
+            if(cpuif_rd_ack || cpuif_wr_ack) begin
+                if(cpuif_rd_ack) begin
+                    axil_resp_buffer[axil_resp_wptr[0:0]].is_wr <= '0;
+                    axil_resp_buffer[axil_resp_wptr[0:0]].err <= cpuif_rd_err;
+                    axil_resp_buffer[axil_resp_wptr[0:0]].rdata <= cpuif_rd_data;
+
+                end else if(cpuif_wr_ack) begin
+                    axil_resp_buffer[axil_resp_wptr[0:0]].is_wr <= '1;
+                    axil_resp_buffer[axil_resp_wptr[0:0]].err <= cpuif_wr_err;
+                end
+                axil_resp_wptr <= axil_resp_wptr + 1'b1;
+            end
+
+            // Advance read pointer when acknowledged
+            if(axil_resp_acked) begin
+                axil_resp_rptr <= axil_resp_rptr + 1'b1;
+            end
+        end
+    end
+
+    always_comb begin
+        axil_resp_acked = '0;
+        s_axil_bvalid = '0;
+        s_axil_rvalid = '0;
+        if(axil_resp_rptr != axil_resp_wptr) begin
+            if(axil_resp_buffer[axil_resp_rptr[0:0]].is_wr) begin
+                s_axil_bvalid = '1;
+                if(s_axil_bready) axil_resp_acked = '1;
+            end else begin
+                s_axil_rvalid = '1;
+                if(s_axil_rready) axil_resp_acked = '1;
+            end
+        end
+
+        s_axil_rdata = axil_resp_buffer[axil_resp_rptr[0:0]].rdata;
+        if(axil_resp_buffer[axil_resp_rptr[0:0]].err) begin
+            s_axil_bresp = 2'b10;
+            s_axil_rresp = 2'b10;
+        end else begin
+            s_axil_bresp = 2'b00;
+            s_axil_rresp = 2'b00;
+        end
+    end
+
+    logic cpuif_req_masked;
+    logic external_req;
+    logic external_pending;
+    logic external_wr_ack;
+    logic external_rd_ack;
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            external_pending <= '0;
+        end else begin
+            if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1;
+            else if(external_wr_ack | external_rd_ack) external_pending <= '0;
+            assert(!external_wr_ack || (external_pending | external_req))
+                else $error("An external wr_ack strobe was asserted when no external request was active");
+            assert(!external_rd_ack || (external_pending | external_req))
+                else $error("An external rd_ack strobe was asserted when no external request was active");
+        end
+    end
+
+    // Read & write latencies are balanced. Stalls not required
+    // except if external
+    assign cpuif_req_stall_rd = external_pending;
+    assign cpuif_req_stall_wr = external_pending;
+    assign cpuif_req_masked = cpuif_req
+                            & !(!cpuif_req_is_wr & cpuif_req_stall_rd)
+                            & !(cpuif_req_is_wr & cpuif_req_stall_wr);
+
+    //--------------------------------------------------------------------------
+    // Address Decode
+    //--------------------------------------------------------------------------
+    typedef struct {
+        logic mac;
+        logic tcp_top;
+    } decoded_reg_strb_t;
+    decoded_reg_strb_t decoded_reg_strb;
+    logic decoded_strb_is_external;
+
+    logic [9:0] decoded_addr;
+
+    logic decoded_req;
+    logic decoded_req_is_wr;
+    logic [31:0] decoded_wr_data;
+    logic [31:0] decoded_wr_biten;
+
+    always_comb begin
+        automatic logic is_external;
+        is_external = '0;
+        decoded_reg_strb.mac = cpuif_req_masked & (cpuif_addr >= 10'h0) & (cpuif_addr <= 10'h0 + 10'h7);
+        is_external |= cpuif_req_masked & (cpuif_addr >= 10'h0) & (cpuif_addr <= 10'h0 + 10'h7);
+        decoded_reg_strb.tcp_top = cpuif_req_masked & (cpuif_addr >= 10'h200) & (cpuif_addr <= 10'h200 + 10'hff);
+        is_external |= cpuif_req_masked & (cpuif_addr >= 10'h200) & (cpuif_addr <= 10'h200 + 10'hff);
+        decoded_strb_is_external = is_external;
+        external_req = is_external;
+    end
+
+    // Pass down signals to next stage
+    assign decoded_addr = cpuif_addr;
+
+    assign decoded_req = cpuif_req_masked;
+    assign decoded_req_is_wr = cpuif_req_is_wr;
+    assign decoded_wr_data = cpuif_wr_data;
+    assign decoded_wr_biten = cpuif_wr_biten;
+
+    //--------------------------------------------------------------------------
+    // Field logic
+    //--------------------------------------------------------------------------
+    
+
+    
+
+    assign hwif_out.mac.req = decoded_reg_strb.mac;
+    assign hwif_out.mac.addr = decoded_addr[3:0];
+    assign hwif_out.mac.req_is_wr = decoded_req_is_wr;
+    assign hwif_out.mac.wr_data = decoded_wr_data;
+    assign hwif_out.mac.wr_biten = decoded_wr_biten;
+    assign hwif_out.tcp_top.req = decoded_reg_strb.tcp_top;
+    assign hwif_out.tcp_top.addr = decoded_addr[8:0];
+    assign hwif_out.tcp_top.req_is_wr = decoded_req_is_wr;
+    assign hwif_out.tcp_top.wr_data = decoded_wr_data;
+    assign hwif_out.tcp_top.wr_biten = decoded_wr_biten;
+
+    //--------------------------------------------------------------------------
+    // Write response
+    //--------------------------------------------------------------------------
+    always_comb begin
+        automatic logic wr_ack;
+        wr_ack = '0;
+        wr_ack |= hwif_in.mac.wr_ack;
+        wr_ack |= hwif_in.tcp_top.wr_ack;
+        external_wr_ack = wr_ack;
+    end
+    assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external);
+    // Writes are always granted with no error response
+    assign cpuif_wr_err = '0;
+
+    //--------------------------------------------------------------------------
+    // Readback
+    //--------------------------------------------------------------------------
+    logic readback_external_rd_ack_c;
+    always_comb begin
+        automatic logic rd_ack;
+        rd_ack = '0;
+        rd_ack |= hwif_in.mac.rd_ack;
+        rd_ack |= hwif_in.tcp_top.rd_ack;
+        readback_external_rd_ack_c = rd_ack;
+    end
+
+    logic readback_external_rd_ack;
+
+    assign readback_external_rd_ack = readback_external_rd_ack_c;
+
+    logic readback_err;
+    logic readback_done;
+    logic [31:0] readback_data;
+
+    // Assign readback values to a flattened array
+    logic [31:0] readback_array[2];
+    assign readback_array[0] = hwif_in.mac.rd_ack ? hwif_in.mac.rd_data : '0;
+    assign readback_array[1] = hwif_in.tcp_top.rd_ack ? hwif_in.tcp_top.rd_data : '0;
+
+    // Reduce the array
+    always_comb begin
+        automatic logic [31:0] readback_data_var;
+        readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external;
+        readback_err = '0;
+        readback_data_var = '0;
+        for(int i=0; i<2; i++) readback_data_var |= readback_array[i];
+        readback_data = readback_data_var;
+    end
+
+    assign external_rd_ack = readback_external_rd_ack;
+    assign cpuif_rd_ack = readback_done | readback_external_rd_ack;
+    assign cpuif_rd_data = readback_data;
+    assign cpuif_rd_err = readback_err;
+endmodule
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/ntw_top_regfile_pkg.sv b/hw/super6502_fpga/src/sub/network_processor/src/regs/ntw_top_regfile_pkg.sv
new file mode 100644
index 0000000000000000000000000000000000000000..f8939d2cee962643b5eb8987693d26a6d97a75bc
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/ntw_top_regfile_pkg.sv
@@ -0,0 +1,46 @@
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+//  https://github.com/SystemRDL/PeakRDL-regblock
+
+package ntw_top_regfile_pkg;
+
+    localparam NTW_TOP_REGFILE_DATA_WIDTH = 32;
+    localparam NTW_TOP_REGFILE_MIN_ADDR_WIDTH = 10;
+
+    typedef struct {
+        logic rd_ack;
+        logic [31:0] rd_data;
+        logic wr_ack;
+    } mac_regs__external__in_t;
+
+    typedef struct {
+        logic rd_ack;
+        logic [31:0] rd_data;
+        logic wr_ack;
+    } tcp_top_regfile__external__in_t;
+
+    typedef struct {
+        mac_regs__external__in_t mac;
+        tcp_top_regfile__external__in_t tcp_top;
+    } ntw_top_regfile__in_t;
+
+    typedef struct {
+        logic req;
+        logic [2:0] addr;
+        logic req_is_wr;
+        logic [31:0] wr_data;
+        logic [31:0] wr_biten;
+    } mac_regs__external__out_t;
+
+    typedef struct {
+        logic req;
+        logic [7:0] addr;
+        logic req_is_wr;
+        logic [31:0] wr_data;
+        logic [31:0] wr_biten;
+    } tcp_top_regfile__external__out_t;
+
+    typedef struct {
+        mac_regs__external__out_t mac;
+        tcp_top_regfile__external__out_t tcp_top;
+    } ntw_top_regfile__out_t;
+endpackage
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/ntw_top_regs.rdl b/hw/super6502_fpga/src/sub/network_processor/src/regs/ntw_top_regs.rdl
new file mode 100644
index 0000000000000000000000000000000000000000..a68d66f7f8f87cd5016d667ea615bcd985f89aec
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/ntw_top_regs.rdl
@@ -0,0 +1,4 @@
+addrmap ntw_top_regfile {
+    external mac_regs mac @ 0x0;
+    external tcp_top_regfile tcp_top @ 0x200;
+};
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/run_precompile.sh b/hw/super6502_fpga/src/sub/network_processor/src/regs/run_precompile.sh
new file mode 100644
index 0000000000000000000000000000000000000000..60f2e8819669d1110b42f9884106ea822f31d26b
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/run_precompile.sh
@@ -0,0 +1,5 @@
+peakrdl regblock -t tcp_top_regfile ../../../stream_dmas/src/regs/m2s_dma_regs.rdl tcp_stream_regs.rdl tcp_top_regs.rdl -o . --cpuif passthrough
+peakrdl regblock -t tcp_stream_regs ../../../stream_dmas/src/regs/m2s_dma_regs.rdl tcp_stream_regs.rdl -o . --cpuif passthrough
+peakrdl regblock -t mac_regs mac_regs.rdl -o . --cpuif passthrough
+peakrdl regblock -t ntw_top_regfile mac_regs.rdl ../../../stream_dmas/src/regs/m2s_dma_regs.rdl tcp_stream_regs.rdl tcp_top_regs.rdl ntw_top_regs.rdl -o . --cpuif axi4-lite-flat
+peakrdl html -t ntw_top_regfile mac_regs.rdl ../../../stream_dmas/src/regs/m2s_dma_regs.rdl tcp_stream_regs.rdl tcp_top_regs.rdl ntw_top_regs.rdl -o html
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_stream_regs.rdl b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_stream_regs.rdl
new file mode 100644
index 0000000000000000000000000000000000000000..df22881d54ae9fa2561c478c092218b9af7556a3
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_stream_regs.rdl
@@ -0,0 +1,137 @@
+addrmap tcp_stream_regs {
+    name = "TCP Stream Regs";
+    desc = "";
+
+    reg {
+        name = "SourcePort";
+        desc = "";
+
+        field {
+            name = "d";
+            desc = "";
+            hw   = r;
+            sw   = rw;
+        } d[31:0] = 0x0;
+    } source_port @ 0x0;
+
+    reg {
+        name = "SourceIP";
+        desc = "";
+
+        field {
+            name = "d";
+            desc = "";
+            hw   = r;
+            sw   = rw;
+        } d[31:0] = 0x0;
+    } source_ip @ 0x4;
+
+    reg {
+        name = "DestPort";
+        desc = "";
+
+        field {
+            name = "d";
+            desc = "";
+            hw   = r;
+            sw   = rw;
+        } d[31:0] = 0x0;
+    } dest_port @ 0x8;
+
+    reg {
+        name = "DestIP";
+        desc = "";
+
+        field {
+            name = "d";
+            desc = "";
+            hw   = r;
+            sw   = rw;
+        } d[31:0] = 0x0;
+    } dest_ip @ 0xc;
+
+    reg {
+        name = "Control";
+        desc = "";
+
+        field {
+            name = "Enable";
+            desc = "Enable the stream";
+            hw   = r;
+            sw   = rw;
+        } enable[0:0] = 0x0;
+
+        field {
+            name = "Open";
+            desc = "Open a new connection with the given parameters.
+                    When written with 1, initiate a TCP handshake.";
+            hw   = r;
+            sw   = rw;
+            hwclr;
+        } open[1:1] = 0x0;
+
+        field {
+            name = "Close";
+            desc = "Closes the exisitng connection when written with 1";
+            hw   = r;
+            sw   = rw;
+            hwclr;
+        } close[2:2] = 0x0;
+
+        field {
+            name = "State";
+            desc = "Current state of the TCP connection";
+            hw   = w;
+            sw   = r;
+        } state[5:3] = 0x0;
+
+    } control @ 0x10;
+
+    // is addrmap right for this? How do we specify the address of it though?
+    // Maybe we have to do this separately and include it?
+    regfile stats {
+        name = "Statistics";
+        desc = "";
+
+        reg {
+            name = "TXValidPackets";
+            desc = "Number of packets transmitted";
+
+            field {
+                name = "d";
+                desc = "";
+                hw   = r;
+                sw   = w;
+            } d[31:0] = 0x0;
+
+        } tx_valid_packets @ 0x14;
+
+        reg {
+            name = "RXValidPackets";
+            desc = "Number of valid received packets";
+
+            field {
+                name = "d";
+                desc = "";
+                hw   = r;
+                sw   = w;
+            } d[31:0] = 0x0;
+
+        } rx_valid_packets @ 0x4;
+
+        reg {
+            name = "RXBadCRC";
+            desc = "RX packets with bad CRC";
+
+            field {
+                name = "d";
+                desc = "";
+                hw   = r;
+                sw   = w;
+            } d[31:0] = 0x0;
+
+        } rx_bad_crc @ 0x8;
+    };
+
+    external m2s_dma_regs m2s_dma_regs @ 0x20;
+};
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_stream_regs.sv b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_stream_regs.sv
new file mode 100644
index 0000000000000000000000000000000000000000..4c8238a51f9e4c9684be8405181f5747209f353c
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_stream_regs.sv
@@ -0,0 +1,423 @@
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+//  https://github.com/SystemRDL/PeakRDL-regblock
+
+module tcp_stream_regs (
+        input wire clk,
+        input wire rst,
+
+        input wire s_cpuif_req,
+        input wire s_cpuif_req_is_wr,
+        input wire [5:0] s_cpuif_addr,
+        input wire [31:0] s_cpuif_wr_data,
+        input wire [31:0] s_cpuif_wr_biten,
+        output wire s_cpuif_req_stall_wr,
+        output wire s_cpuif_req_stall_rd,
+        output wire s_cpuif_rd_ack,
+        output wire s_cpuif_rd_err,
+        output wire [31:0] s_cpuif_rd_data,
+        output wire s_cpuif_wr_ack,
+        output wire s_cpuif_wr_err,
+
+        input tcp_stream_regs_pkg::tcp_stream_regs__in_t hwif_in,
+        output tcp_stream_regs_pkg::tcp_stream_regs__out_t hwif_out
+    );
+
+    //--------------------------------------------------------------------------
+    // CPU Bus interface logic
+    //--------------------------------------------------------------------------
+    logic cpuif_req;
+    logic cpuif_req_is_wr;
+    logic [5:0] cpuif_addr;
+    logic [31:0] cpuif_wr_data;
+    logic [31:0] cpuif_wr_biten;
+    logic cpuif_req_stall_wr;
+    logic cpuif_req_stall_rd;
+
+    logic cpuif_rd_ack;
+    logic cpuif_rd_err;
+    logic [31:0] cpuif_rd_data;
+
+    logic cpuif_wr_ack;
+    logic cpuif_wr_err;
+
+    assign cpuif_req = s_cpuif_req;
+    assign cpuif_req_is_wr = s_cpuif_req_is_wr;
+    assign cpuif_addr = s_cpuif_addr;
+    assign cpuif_wr_data = s_cpuif_wr_data;
+    assign cpuif_wr_biten = s_cpuif_wr_biten;
+    assign s_cpuif_req_stall_wr = cpuif_req_stall_wr;
+    assign s_cpuif_req_stall_rd = cpuif_req_stall_rd;
+    assign s_cpuif_rd_ack = cpuif_rd_ack;
+    assign s_cpuif_rd_err = cpuif_rd_err;
+    assign s_cpuif_rd_data = cpuif_rd_data;
+    assign s_cpuif_wr_ack = cpuif_wr_ack;
+    assign s_cpuif_wr_err = cpuif_wr_err;
+
+    logic cpuif_req_masked;
+    logic external_req;
+    logic external_pending;
+    logic external_wr_ack;
+    logic external_rd_ack;
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            external_pending <= '0;
+        end else begin
+            if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1;
+            else if(external_wr_ack | external_rd_ack) external_pending <= '0;
+            assert(!external_wr_ack || (external_pending | external_req))
+                else $error("An external wr_ack strobe was asserted when no external request was active");
+            assert(!external_rd_ack || (external_pending | external_req))
+                else $error("An external rd_ack strobe was asserted when no external request was active");
+        end
+    end
+
+    // Read & write latencies are balanced. Stalls not required
+    // except if external
+    assign cpuif_req_stall_rd = external_pending;
+    assign cpuif_req_stall_wr = external_pending;
+    assign cpuif_req_masked = cpuif_req
+                            & !(!cpuif_req_is_wr & cpuif_req_stall_rd)
+                            & !(cpuif_req_is_wr & cpuif_req_stall_wr);
+
+    //--------------------------------------------------------------------------
+    // Address Decode
+    //--------------------------------------------------------------------------
+    typedef struct {
+        logic source_port;
+        logic source_ip;
+        logic dest_port;
+        logic dest_ip;
+        logic control;
+        logic m2s_dma_regs;
+    } decoded_reg_strb_t;
+    decoded_reg_strb_t decoded_reg_strb;
+    logic decoded_strb_is_external;
+
+    logic [5:0] decoded_addr;
+
+    logic decoded_req;
+    logic decoded_req_is_wr;
+    logic [31:0] decoded_wr_data;
+    logic [31:0] decoded_wr_biten;
+
+    always_comb begin
+        automatic logic is_external;
+        is_external = '0;
+        decoded_reg_strb.source_port = cpuif_req_masked & (cpuif_addr == 6'h0);
+        decoded_reg_strb.source_ip = cpuif_req_masked & (cpuif_addr == 6'h4);
+        decoded_reg_strb.dest_port = cpuif_req_masked & (cpuif_addr == 6'h8);
+        decoded_reg_strb.dest_ip = cpuif_req_masked & (cpuif_addr == 6'hc);
+        decoded_reg_strb.control = cpuif_req_masked & (cpuif_addr == 6'h10);
+        decoded_reg_strb.m2s_dma_regs = cpuif_req_masked & (cpuif_addr >= 6'h20) & (cpuif_addr <= 6'h20 + 6'hf);
+        is_external |= cpuif_req_masked & (cpuif_addr >= 6'h20) & (cpuif_addr <= 6'h20 + 6'hf);
+        decoded_strb_is_external = is_external;
+        external_req = is_external;
+    end
+
+    // Pass down signals to next stage
+    assign decoded_addr = cpuif_addr;
+
+    assign decoded_req = cpuif_req_masked;
+    assign decoded_req_is_wr = cpuif_req_is_wr;
+    assign decoded_wr_data = cpuif_wr_data;
+    assign decoded_wr_biten = cpuif_wr_biten;
+
+    //--------------------------------------------------------------------------
+    // Field logic
+    //--------------------------------------------------------------------------
+    typedef struct {
+        struct {
+            struct {
+                logic [31:0] next;
+                logic load_next;
+            } d;
+        } source_port;
+        struct {
+            struct {
+                logic [31:0] next;
+                logic load_next;
+            } d;
+        } source_ip;
+        struct {
+            struct {
+                logic [31:0] next;
+                logic load_next;
+            } d;
+        } dest_port;
+        struct {
+            struct {
+                logic [31:0] next;
+                logic load_next;
+            } d;
+        } dest_ip;
+        struct {
+            struct {
+                logic next;
+                logic load_next;
+            } enable;
+            struct {
+                logic next;
+                logic load_next;
+            } open;
+            struct {
+                logic next;
+                logic load_next;
+            } close;
+        } control;
+    } field_combo_t;
+    field_combo_t field_combo;
+
+    typedef struct {
+        struct {
+            struct {
+                logic [31:0] value;
+            } d;
+        } source_port;
+        struct {
+            struct {
+                logic [31:0] value;
+            } d;
+        } source_ip;
+        struct {
+            struct {
+                logic [31:0] value;
+            } d;
+        } dest_port;
+        struct {
+            struct {
+                logic [31:0] value;
+            } d;
+        } dest_ip;
+        struct {
+            struct {
+                logic value;
+            } enable;
+            struct {
+                logic value;
+            } open;
+            struct {
+                logic value;
+            } close;
+        } control;
+    } field_storage_t;
+    field_storage_t field_storage;
+
+    // Field: tcp_stream_regs.source_port.d
+    always_comb begin
+        automatic logic [31:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.source_port.d.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.source_port && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.source_port.d.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
+            load_next_c = '1;
+        end
+        field_combo.source_port.d.next = next_c;
+        field_combo.source_port.d.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.source_port.d.value <= 32'h0;
+        end else if(field_combo.source_port.d.load_next) begin
+            field_storage.source_port.d.value <= field_combo.source_port.d.next;
+        end
+    end
+    assign hwif_out.source_port.d.value = field_storage.source_port.d.value;
+    // Field: tcp_stream_regs.source_ip.d
+    always_comb begin
+        automatic logic [31:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.source_ip.d.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.source_ip && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.source_ip.d.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
+            load_next_c = '1;
+        end
+        field_combo.source_ip.d.next = next_c;
+        field_combo.source_ip.d.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.source_ip.d.value <= 32'h0;
+        end else if(field_combo.source_ip.d.load_next) begin
+            field_storage.source_ip.d.value <= field_combo.source_ip.d.next;
+        end
+    end
+    assign hwif_out.source_ip.d.value = field_storage.source_ip.d.value;
+    // Field: tcp_stream_regs.dest_port.d
+    always_comb begin
+        automatic logic [31:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.dest_port.d.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.dest_port && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.dest_port.d.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
+            load_next_c = '1;
+        end
+        field_combo.dest_port.d.next = next_c;
+        field_combo.dest_port.d.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.dest_port.d.value <= 32'h0;
+        end else if(field_combo.dest_port.d.load_next) begin
+            field_storage.dest_port.d.value <= field_combo.dest_port.d.next;
+        end
+    end
+    assign hwif_out.dest_port.d.value = field_storage.dest_port.d.value;
+    // Field: tcp_stream_regs.dest_ip.d
+    always_comb begin
+        automatic logic [31:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.dest_ip.d.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.dest_ip && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.dest_ip.d.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]);
+            load_next_c = '1;
+        end
+        field_combo.dest_ip.d.next = next_c;
+        field_combo.dest_ip.d.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.dest_ip.d.value <= 32'h0;
+        end else if(field_combo.dest_ip.d.load_next) begin
+            field_storage.dest_ip.d.value <= field_combo.dest_ip.d.next;
+        end
+    end
+    assign hwif_out.dest_ip.d.value = field_storage.dest_ip.d.value;
+    // Field: tcp_stream_regs.control.enable
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.control.enable.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.control && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.control.enable.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]);
+            load_next_c = '1;
+        end
+        field_combo.control.enable.next = next_c;
+        field_combo.control.enable.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.control.enable.value <= 1'h0;
+        end else if(field_combo.control.enable.load_next) begin
+            field_storage.control.enable.value <= field_combo.control.enable.next;
+        end
+    end
+    assign hwif_out.control.enable.value = field_storage.control.enable.value;
+    // Field: tcp_stream_regs.control.open
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.control.open.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.control && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.control.open.value & ~decoded_wr_biten[1:1]) | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]);
+            load_next_c = '1;
+        end else if(hwif_in.control.open.hwclr) begin // HW Clear
+            next_c = '0;
+            load_next_c = '1;
+        end
+        field_combo.control.open.next = next_c;
+        field_combo.control.open.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.control.open.value <= 1'h0;
+        end else if(field_combo.control.open.load_next) begin
+            field_storage.control.open.value <= field_combo.control.open.next;
+        end
+    end
+    assign hwif_out.control.open.value = field_storage.control.open.value;
+    // Field: tcp_stream_regs.control.close
+    always_comb begin
+        automatic logic [0:0] next_c;
+        automatic logic load_next_c;
+        next_c = field_storage.control.close.value;
+        load_next_c = '0;
+        if(decoded_reg_strb.control && decoded_req_is_wr) begin // SW write
+            next_c = (field_storage.control.close.value & ~decoded_wr_biten[2:2]) | (decoded_wr_data[2:2] & decoded_wr_biten[2:2]);
+            load_next_c = '1;
+        end else if(hwif_in.control.close.hwclr) begin // HW Clear
+            next_c = '0;
+            load_next_c = '1;
+        end
+        field_combo.control.close.next = next_c;
+        field_combo.control.close.load_next = load_next_c;
+    end
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            field_storage.control.close.value <= 1'h0;
+        end else if(field_combo.control.close.load_next) begin
+            field_storage.control.close.value <= field_combo.control.close.next;
+        end
+    end
+    assign hwif_out.control.close.value = field_storage.control.close.value;
+    assign hwif_out.m2s_dma_regs.req = decoded_reg_strb.m2s_dma_regs;
+    assign hwif_out.m2s_dma_regs.addr = decoded_addr[4:0];
+    assign hwif_out.m2s_dma_regs.req_is_wr = decoded_req_is_wr;
+    assign hwif_out.m2s_dma_regs.wr_data = decoded_wr_data;
+    assign hwif_out.m2s_dma_regs.wr_biten = decoded_wr_biten;
+
+    //--------------------------------------------------------------------------
+    // Write response
+    //--------------------------------------------------------------------------
+    always_comb begin
+        automatic logic wr_ack;
+        wr_ack = '0;
+        wr_ack |= hwif_in.m2s_dma_regs.wr_ack;
+        external_wr_ack = wr_ack;
+    end
+    assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external);
+    // Writes are always granted with no error response
+    assign cpuif_wr_err = '0;
+
+    //--------------------------------------------------------------------------
+    // Readback
+    //--------------------------------------------------------------------------
+    logic readback_external_rd_ack_c;
+    always_comb begin
+        automatic logic rd_ack;
+        rd_ack = '0;
+        rd_ack |= hwif_in.m2s_dma_regs.rd_ack;
+        readback_external_rd_ack_c = rd_ack;
+    end
+
+    logic readback_external_rd_ack;
+
+    assign readback_external_rd_ack = readback_external_rd_ack_c;
+
+    logic readback_err;
+    logic readback_done;
+    logic [31:0] readback_data;
+
+    // Assign readback values to a flattened array
+    logic [31:0] readback_array[6];
+    assign readback_array[0][31:0] = (decoded_reg_strb.source_port && !decoded_req_is_wr) ? field_storage.source_port.d.value : '0;
+    assign readback_array[1][31:0] = (decoded_reg_strb.source_ip && !decoded_req_is_wr) ? field_storage.source_ip.d.value : '0;
+    assign readback_array[2][31:0] = (decoded_reg_strb.dest_port && !decoded_req_is_wr) ? field_storage.dest_port.d.value : '0;
+    assign readback_array[3][31:0] = (decoded_reg_strb.dest_ip && !decoded_req_is_wr) ? field_storage.dest_ip.d.value : '0;
+    assign readback_array[4][0:0] = (decoded_reg_strb.control && !decoded_req_is_wr) ? field_storage.control.enable.value : '0;
+    assign readback_array[4][1:1] = (decoded_reg_strb.control && !decoded_req_is_wr) ? field_storage.control.open.value : '0;
+    assign readback_array[4][2:2] = (decoded_reg_strb.control && !decoded_req_is_wr) ? field_storage.control.close.value : '0;
+    assign readback_array[4][5:3] = (decoded_reg_strb.control && !decoded_req_is_wr) ? hwif_in.control.state.next : '0;
+    assign readback_array[4][31:6] = '0;
+    assign readback_array[5] = hwif_in.m2s_dma_regs.rd_ack ? hwif_in.m2s_dma_regs.rd_data : '0;
+
+    // Reduce the array
+    always_comb begin
+        automatic logic [31:0] readback_data_var;
+        readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external;
+        readback_err = '0;
+        readback_data_var = '0;
+        for(int i=0; i<6; i++) readback_data_var |= readback_array[i];
+        readback_data = readback_data_var;
+    end
+
+    assign external_rd_ack = readback_external_rd_ack;
+    assign cpuif_rd_ack = readback_done | readback_external_rd_ack;
+    assign cpuif_rd_data = readback_data;
+    assign cpuif_rd_err = readback_err;
+endmodule
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_stream_regs_pkg.sv b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_stream_regs_pkg.sv
new file mode 100644
index 0000000000000000000000000000000000000000..f385fc40ab9a1b435074fb6c1d72d5030ca8b3a0
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_stream_regs_pkg.sv
@@ -0,0 +1,104 @@
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+//  https://github.com/SystemRDL/PeakRDL-regblock
+
+package tcp_stream_regs_pkg;
+
+    localparam TCP_STREAM_REGS_DATA_WIDTH = 32;
+    localparam TCP_STREAM_REGS_MIN_ADDR_WIDTH = 6;
+
+    typedef struct {
+        logic hwclr;
+    } tcp_stream_regs__control__open__in_t;
+
+    typedef struct {
+        logic hwclr;
+    } tcp_stream_regs__control__close__in_t;
+
+    typedef struct {
+        logic [2:0] next;
+    } tcp_stream_regs__control__state__in_t;
+
+    typedef struct {
+        tcp_stream_regs__control__open__in_t open;
+        tcp_stream_regs__control__close__in_t close;
+        tcp_stream_regs__control__state__in_t state;
+    } tcp_stream_regs__control__in_t;
+
+    typedef struct {
+        logic rd_ack;
+        logic [31:0] rd_data;
+        logic wr_ack;
+    } m2s_dma_regs__external__in_t;
+
+    typedef struct {
+        tcp_stream_regs__control__in_t control;
+        m2s_dma_regs__external__in_t m2s_dma_regs;
+    } tcp_stream_regs__in_t;
+
+    typedef struct {
+        logic [31:0] value;
+    } tcp_stream_regs__source_port__d__out_t;
+
+    typedef struct {
+        tcp_stream_regs__source_port__d__out_t d;
+    } tcp_stream_regs__source_port__out_t;
+
+    typedef struct {
+        logic [31:0] value;
+    } tcp_stream_regs__source_ip__d__out_t;
+
+    typedef struct {
+        tcp_stream_regs__source_ip__d__out_t d;
+    } tcp_stream_regs__source_ip__out_t;
+
+    typedef struct {
+        logic [31:0] value;
+    } tcp_stream_regs__dest_port__d__out_t;
+
+    typedef struct {
+        tcp_stream_regs__dest_port__d__out_t d;
+    } tcp_stream_regs__dest_port__out_t;
+
+    typedef struct {
+        logic [31:0] value;
+    } tcp_stream_regs__dest_ip__d__out_t;
+
+    typedef struct {
+        tcp_stream_regs__dest_ip__d__out_t d;
+    } tcp_stream_regs__dest_ip__out_t;
+
+    typedef struct {
+        logic value;
+    } tcp_stream_regs__control__enable__out_t;
+
+    typedef struct {
+        logic value;
+    } tcp_stream_regs__control__open__out_t;
+
+    typedef struct {
+        logic value;
+    } tcp_stream_regs__control__close__out_t;
+
+    typedef struct {
+        tcp_stream_regs__control__enable__out_t enable;
+        tcp_stream_regs__control__open__out_t open;
+        tcp_stream_regs__control__close__out_t close;
+    } tcp_stream_regs__control__out_t;
+
+    typedef struct {
+        logic req;
+        logic [3:0] addr;
+        logic req_is_wr;
+        logic [31:0] wr_data;
+        logic [31:0] wr_biten;
+    } m2s_dma_regs__external__out_t;
+
+    typedef struct {
+        tcp_stream_regs__source_port__out_t source_port;
+        tcp_stream_regs__source_ip__out_t source_ip;
+        tcp_stream_regs__dest_port__out_t dest_port;
+        tcp_stream_regs__dest_ip__out_t dest_ip;
+        tcp_stream_regs__control__out_t control;
+        m2s_dma_regs__external__out_t m2s_dma_regs;
+    } tcp_stream_regs__out_t;
+endpackage
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_top_regfile.sv b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_top_regfile.sv
new file mode 100644
index 0000000000000000000000000000000000000000..4427758081d4f2717d52d3a47d2435db794433db
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_top_regfile.sv
@@ -0,0 +1,188 @@
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+//  https://github.com/SystemRDL/PeakRDL-regblock
+
+module tcp_top_regfile (
+        input wire clk,
+        input wire rst,
+
+        input wire s_cpuif_req,
+        input wire s_cpuif_req_is_wr,
+        input wire [7:0] s_cpuif_addr,
+        input wire [31:0] s_cpuif_wr_data,
+        input wire [31:0] s_cpuif_wr_biten,
+        output wire s_cpuif_req_stall_wr,
+        output wire s_cpuif_req_stall_rd,
+        output wire s_cpuif_rd_ack,
+        output wire s_cpuif_rd_err,
+        output wire [31:0] s_cpuif_rd_data,
+        output wire s_cpuif_wr_ack,
+        output wire s_cpuif_wr_err,
+
+        input tcp_top_regfile_pkg::tcp_top_regfile__in_t hwif_in,
+        output tcp_top_regfile_pkg::tcp_top_regfile__out_t hwif_out
+    );
+
+    //--------------------------------------------------------------------------
+    // CPU Bus interface logic
+    //--------------------------------------------------------------------------
+    logic cpuif_req;
+    logic cpuif_req_is_wr;
+    logic [7:0] cpuif_addr;
+    logic [31:0] cpuif_wr_data;
+    logic [31:0] cpuif_wr_biten;
+    logic cpuif_req_stall_wr;
+    logic cpuif_req_stall_rd;
+
+    logic cpuif_rd_ack;
+    logic cpuif_rd_err;
+    logic [31:0] cpuif_rd_data;
+
+    logic cpuif_wr_ack;
+    logic cpuif_wr_err;
+
+    assign cpuif_req = s_cpuif_req;
+    assign cpuif_req_is_wr = s_cpuif_req_is_wr;
+    assign cpuif_addr = s_cpuif_addr;
+    assign cpuif_wr_data = s_cpuif_wr_data;
+    assign cpuif_wr_biten = s_cpuif_wr_biten;
+    assign s_cpuif_req_stall_wr = cpuif_req_stall_wr;
+    assign s_cpuif_req_stall_rd = cpuif_req_stall_rd;
+    assign s_cpuif_rd_ack = cpuif_rd_ack;
+    assign s_cpuif_rd_err = cpuif_rd_err;
+    assign s_cpuif_rd_data = cpuif_rd_data;
+    assign s_cpuif_wr_ack = cpuif_wr_ack;
+    assign s_cpuif_wr_err = cpuif_wr_err;
+
+    logic cpuif_req_masked;
+    logic external_req;
+    logic external_pending;
+    logic external_wr_ack;
+    logic external_rd_ack;
+    always_ff @(posedge clk) begin
+        if(rst) begin
+            external_pending <= '0;
+        end else begin
+            if(external_req & ~external_wr_ack & ~external_rd_ack) external_pending <= '1;
+            else if(external_wr_ack | external_rd_ack) external_pending <= '0;
+            assert(!external_wr_ack || (external_pending | external_req))
+                else $error("An external wr_ack strobe was asserted when no external request was active");
+            assert(!external_rd_ack || (external_pending | external_req))
+                else $error("An external rd_ack strobe was asserted when no external request was active");
+        end
+    end
+
+    // Read & write latencies are balanced. Stalls not required
+    // except if external
+    assign cpuif_req_stall_rd = external_pending;
+    assign cpuif_req_stall_wr = external_pending;
+    assign cpuif_req_masked = cpuif_req
+                            & !(!cpuif_req_is_wr & cpuif_req_stall_rd)
+                            & !(cpuif_req_is_wr & cpuif_req_stall_wr);
+
+    //--------------------------------------------------------------------------
+    // Address Decode
+    //--------------------------------------------------------------------------
+    typedef struct {
+        logic tcp_streams[4];
+    } decoded_reg_strb_t;
+    decoded_reg_strb_t decoded_reg_strb;
+    logic decoded_strb_is_external;
+
+    logic [7:0] decoded_addr;
+
+    logic decoded_req;
+    logic decoded_req_is_wr;
+    logic [31:0] decoded_wr_data;
+    logic [31:0] decoded_wr_biten;
+
+    always_comb begin
+        automatic logic is_external;
+        is_external = '0;
+        for(int i0=0; i0<4; i0++) begin
+            decoded_reg_strb.tcp_streams[i0] = cpuif_req_masked & (cpuif_addr >= 8'h0 + i0*8'h40) & (cpuif_addr <= 8'h0 + i0*8'h40 + 8'h2f);
+            is_external |= cpuif_req_masked & (cpuif_addr >= 8'h0 + i0*8'h40) & (cpuif_addr <= 8'h0 + i0*8'h40 + 8'h2f);
+        end
+        decoded_strb_is_external = is_external;
+        external_req = is_external;
+    end
+
+    // Pass down signals to next stage
+    assign decoded_addr = cpuif_addr;
+
+    assign decoded_req = cpuif_req_masked;
+    assign decoded_req_is_wr = cpuif_req_is_wr;
+    assign decoded_wr_data = cpuif_wr_data;
+    assign decoded_wr_biten = cpuif_wr_biten;
+
+    //--------------------------------------------------------------------------
+    // Field logic
+    //--------------------------------------------------------------------------
+    
+
+    
+
+    for(genvar i0=0; i0<4; i0++) begin
+        assign hwif_out.tcp_streams[i0].req = decoded_reg_strb.tcp_streams[i0];
+        assign hwif_out.tcp_streams[i0].addr = decoded_addr[5:0];
+        assign hwif_out.tcp_streams[i0].req_is_wr = decoded_req_is_wr;
+        assign hwif_out.tcp_streams[i0].wr_data = decoded_wr_data;
+        assign hwif_out.tcp_streams[i0].wr_biten = decoded_wr_biten;
+    end
+
+    //--------------------------------------------------------------------------
+    // Write response
+    //--------------------------------------------------------------------------
+    always_comb begin
+        automatic logic wr_ack;
+        wr_ack = '0;
+        for(int i0=0; i0<4; i0++) begin
+            wr_ack |= hwif_in.tcp_streams[i0].wr_ack;
+        end
+        external_wr_ack = wr_ack;
+    end
+    assign cpuif_wr_ack = external_wr_ack | (decoded_req & decoded_req_is_wr & ~decoded_strb_is_external);
+    // Writes are always granted with no error response
+    assign cpuif_wr_err = '0;
+
+    //--------------------------------------------------------------------------
+    // Readback
+    //--------------------------------------------------------------------------
+    logic readback_external_rd_ack_c;
+    always_comb begin
+        automatic logic rd_ack;
+        rd_ack = '0;
+        for(int i0=0; i0<4; i0++) begin
+            rd_ack |= hwif_in.tcp_streams[i0].rd_ack;
+        end
+        readback_external_rd_ack_c = rd_ack;
+    end
+
+    logic readback_external_rd_ack;
+
+    assign readback_external_rd_ack = readback_external_rd_ack_c;
+
+    logic readback_err;
+    logic readback_done;
+    logic [31:0] readback_data;
+
+    // Assign readback values to a flattened array
+    logic [31:0] readback_array[4];
+    for(genvar i0=0; i0<4; i0++) begin
+        assign readback_array[i0*1 + 0] = hwif_in.tcp_streams[i0].rd_ack ? hwif_in.tcp_streams[i0].rd_data : '0;
+    end
+
+    // Reduce the array
+    always_comb begin
+        automatic logic [31:0] readback_data_var;
+        readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external;
+        readback_err = '0;
+        readback_data_var = '0;
+        for(int i=0; i<4; i++) readback_data_var |= readback_array[i];
+        readback_data = readback_data_var;
+    end
+
+    assign external_rd_ack = readback_external_rd_ack;
+    assign cpuif_rd_ack = readback_done | readback_external_rd_ack;
+    assign cpuif_rd_data = readback_data;
+    assign cpuif_rd_err = readback_err;
+endmodule
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_top_regfile_pkg.sv b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_top_regfile_pkg.sv
new file mode 100644
index 0000000000000000000000000000000000000000..5c036212c7aa1d99c5567a8856294a4f8935692d
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_top_regfile_pkg.sv
@@ -0,0 +1,30 @@
+// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator
+//  https://github.com/SystemRDL/PeakRDL-regblock
+
+package tcp_top_regfile_pkg;
+
+    localparam TCP_TOP_REGFILE_DATA_WIDTH = 32;
+    localparam TCP_TOP_REGFILE_MIN_ADDR_WIDTH = 8;
+
+    typedef struct {
+        logic rd_ack;
+        logic [31:0] rd_data;
+        logic wr_ack;
+    } tcp_stream_regs__external__in_t;
+
+    typedef struct {
+        tcp_stream_regs__external__in_t tcp_streams[4];
+    } tcp_top_regfile__in_t;
+
+    typedef struct {
+        logic req;
+        logic [5:0] addr;
+        logic req_is_wr;
+        logic [31:0] wr_data;
+        logic [31:0] wr_biten;
+    } tcp_stream_regs__external__out_t;
+
+    typedef struct {
+        tcp_stream_regs__external__out_t tcp_streams[4];
+    } tcp_top_regfile__out_t;
+endpackage
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_top_regs.rdl b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_top_regs.rdl
new file mode 100644
index 0000000000000000000000000000000000000000..e32e8f4ad002bad06259e8e8727b8040d6974711
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/regs/tcp_top_regs.rdl
@@ -0,0 +1,3 @@
+addrmap tcp_top_regfile{
+    external tcp_stream_regs tcp_streams[4] += 0x40;
+};
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/s2m_dma.sv b/hw/super6502_fpga/src/sub/network_processor/src/s2m_dma.sv
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/tcp.sv b/hw/super6502_fpga/src/sub/network_processor/src/tcp.sv
new file mode 100644
index 0000000000000000000000000000000000000000..1745cb9cd71a517d5309afdc91dd55e83bb332d3
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/tcp.sv
@@ -0,0 +1,276 @@
+module tcp #(
+    parameter NUM_TCP=8,
+    parameter DATA_WIDTH=8
+)(
+    input i_clk,
+    input i_rst,
+
+    input  wire                         s_cpuif_req,
+    input  wire                         s_cpuif_req_is_wr,
+    input  wire [8:0]                   s_cpuif_addr,
+    input  wire [31:0]                  s_cpuif_wr_data,
+    input  wire [31:0]                  s_cpuif_wr_biten,
+    output wire                         s_cpuif_req_stall_wr,
+    output wire                         s_cpuif_req_stall_rd,
+    output wire                         s_cpuif_rd_ack,
+    output wire                         s_cpuif_rd_err,
+    output wire [31:0]                  s_cpuif_rd_data,
+    output wire                         s_cpuif_wr_ack,
+    output wire                         s_cpuif_wr_err,
+
+    /*
+     * IP input
+     */
+    ip_intf.SLAVE                       s_ip,
+
+    /*
+    * IP output
+    */
+    ip_intf.MASTER                      m_ip,
+
+    /*
+    * AXI DMA Interface
+    */
+    axil_intf.MASTER                    m_dma_axil
+);
+
+tcp_top_regfile_pkg::tcp_top_regfile__in_t tcp_hwif_in;
+tcp_top_regfile_pkg::tcp_top_regfile__out_t tcp_hwif_out;
+
+
+tcp_top_regfile u_tcp_top_regfile (
+    .clk            (i_clk),
+    .rst            (i_rst),
+
+    .s_cpuif_req            (s_cpuif_req),
+    .s_cpuif_req_is_wr      (s_cpuif_req_is_wr),
+    .s_cpuif_addr           (s_cpuif_addr),
+    .s_cpuif_wr_data        (s_cpuif_wr_data),
+    .s_cpuif_wr_biten       (s_cpuif_wr_biten),
+    .s_cpuif_req_stall_wr   (),
+    .s_cpuif_req_stall_rd   (),
+    .s_cpuif_rd_ack         (s_cpuif_rd_ack),
+    .s_cpuif_rd_err         (),
+    .s_cpuif_rd_data        (s_cpuif_rd_data),
+    .s_cpuif_wr_ack         (s_cpuif_wr_ack),
+    .s_cpuif_wr_err         (),
+
+    .hwif_in        (tcp_hwif_in),
+    .hwif_out       (tcp_hwif_out)
+);
+
+localparam KEEP_WIDTH = ((DATA_WIDTH+7)/8);
+localparam USER_WIDTH = 1;
+localparam DEST_WIDTH = 8;
+localparam ID_WIDTH = 8;
+
+ip_intf #(.DATA_WIDTH(8)) tcp_stream_tx_ip [NUM_TCP]();
+ip_intf #(.DATA_WIDTH(8)) tcp_delayed_rx_ip();
+ip_intf #(.DATA_WIDTH(8)) tcp_stream_rx_ip [NUM_TCP]();
+
+axil_intf m2s_stream_axil[NUM_TCP]();
+axil_intf s2m_stream_axil[NUM_TCP]();
+
+
+//m2s dma
+
+wire    [NUM_TCP-1:0]       xbar_s_m2s_axi_arvalid;
+wire    [NUM_TCP-1:0]       xbar_s_m2s_axi_arready;
+wire    [NUM_TCP*32-1:0]    xbar_s_m2s_axi_araddr;
+wire    [NUM_TCP*3-1:0]     xbar_s_m2s_axi_arprot;
+wire    [NUM_TCP-1:0]       xbar_s_m2s_axi_rvalid;
+wire    [NUM_TCP-1:0]       xbar_s_m2s_axi_rready;
+wire    [NUM_TCP*32-1:0]    xbar_s_m2s_axi_rdata;
+wire    [NUM_TCP*2-1:0]     xbar_s_m2s_axi_rresp;
+
+wire    [NUM_TCP-1:0]       xbar_s_s2m_axi_arvalid;
+wire    [NUM_TCP-1:0]       xbar_s_s2m_axi_arready;
+wire    [NUM_TCP*32-1:0]    xbar_s_s2m_axi_araddr;
+wire    [NUM_TCP*3-1:0]     xbar_s_s2m_axi_arprot;
+wire    [NUM_TCP-1:0]       xbar_s_s2m_axi_rvalid;
+wire    [NUM_TCP-1:0]       xbar_s_s2m_axi_rready;
+wire    [NUM_TCP*32-1:0]    xbar_s_s2m_axi_rdata;
+wire    [NUM_TCP*2-1:0]     xbar_s_s2m_axi_rresp;
+
+axilxbar #(
+    .NM(NUM_TCP*2),
+    .NS(1),
+    .SLAVE_ADDR(
+        {32'h0, 32'hffffffff}   // full address space
+    )
+) u_m2s_xbar (
+    .S_AXI_ACLK         (i_clk),
+    .S_AXI_ARESETN      (~i_rst),
+
+    // No write channel
+    .S_AXI_AWVALID      ('0),
+    .S_AXI_AWREADY      (),
+    .S_AXI_AWADDR       ('0),
+    .S_AXI_AWPROT       ('0),
+    .S_AXI_WVALID       ('0),
+    .S_AXI_WREADY       (),
+    .S_AXI_WDATA        ('0),
+    .S_AXI_WSTRB        ('0),
+    .S_AXI_BVALID       (),
+    .S_AXI_BREADY       ('0),
+    .S_AXI_BRESP        (),
+
+    .S_AXI_ARVALID      ({xbar_s_m2s_axi_arvalid,   xbar_s_s2m_axi_arvalid  }),
+    .S_AXI_ARREADY      ({xbar_s_m2s_axi_arready,   xbar_s_s2m_axi_arready  }),
+    .S_AXI_ARADDR       ({xbar_s_m2s_axi_araddr,    xbar_s_s2m_axi_araddr   }),
+    .S_AXI_ARPROT       ({xbar_s_m2s_axi_arprot,    xbar_s_s2m_axi_arprot   }),
+    .S_AXI_RVALID       ({xbar_s_m2s_axi_rvalid,    xbar_s_s2m_axi_rvalid   }),
+    .S_AXI_RREADY       ({xbar_s_m2s_axi_rready,    xbar_s_s2m_axi_rready   }),
+    .S_AXI_RDATA        ({xbar_s_m2s_axi_rdata,     xbar_s_s2m_axi_rdata    }),
+    .S_AXI_RRESP        ({xbar_s_m2s_axi_rresp,     xbar_s_s2m_axi_rresp    }),
+
+    .M_AXI_AWADDR       (m_dma_axil.awaddr),
+    .M_AXI_AWPROT       (m_dma_axil.awprot),
+    .M_AXI_AWVALID      (m_dma_axil.awvalid),
+    .M_AXI_AWREADY      (m_dma_axil.awready),
+    .M_AXI_WDATA        (m_dma_axil.wdata),
+    .M_AXI_WSTRB        (m_dma_axil.wstrb),
+    .M_AXI_WVALID       (m_dma_axil.wvalid),
+    .M_AXI_WREADY       (m_dma_axil.wready),
+    .M_AXI_BRESP        (m_dma_axil.bresp),
+    .M_AXI_BVALID       (m_dma_axil.bvalid),
+    .M_AXI_BREADY       (m_dma_axil.bready),
+
+    .M_AXI_ARADDR       (m_dma_axil.araddr),
+    .M_AXI_ARPROT       (m_dma_axil.arprot),
+    .M_AXI_ARVALID      (m_dma_axil.arvalid),
+    .M_AXI_ARREADY      (m_dma_axil.arready),
+    .M_AXI_RDATA        (m_dma_axil.rdata),
+    .M_AXI_RRESP        (m_dma_axil.rresp),
+    .M_AXI_RVALID       (m_dma_axil.rvalid),
+    .M_AXI_RREADY       (m_dma_axil.rready)
+);
+
+generate
+    for (genvar i = 0; i < NUM_TCP; i++) begin
+        assign xbar_s_m2s_axi_arvalid[i] = m2s_stream_axil[i].arvalid;
+        assign m2s_stream_axil[i].arready = xbar_s_m2s_axi_arready[i];
+        assign xbar_s_m2s_axi_araddr[32*i+:32] = m2s_stream_axil[i].araddr;
+        assign xbar_s_m2s_axi_arprot[3*i+:3] = m2s_stream_axil[i].arprot;
+        assign m2s_stream_axil[i].rvalid = xbar_s_m2s_axi_rvalid[i];
+        assign xbar_s_m2s_axi_rready[i] = m2s_stream_axil[i].rready;
+        assign m2s_stream_axil[i].rdata = xbar_s_m2s_axi_rdata[32*i+:32];
+        assign m2s_stream_axil[i].rresp = xbar_s_m2s_axi_rresp[2*i+:2];
+
+        assign xbar_s_s2m_axi_arvalid[i] = s2m_stream_axil[i].arvalid;
+        assign s2m_stream_axil[i].arready = xbar_s_s2m_axi_arready[i];
+        assign xbar_s_s2m_axi_araddr[32*i+:32] = s2m_stream_axil[i].araddr;
+        assign xbar_s_s2m_axi_arprot[3*i+:3] = s2m_stream_axil[i].arprot;
+        assign s2m_stream_axil[i].rvalid = xbar_s_s2m_axi_rvalid[i];
+        assign xbar_s_s2m_axi_rready[i] = s2m_stream_axil[i].rready;
+        assign s2m_stream_axil[i].rdata = xbar_s_s2m_axi_rdata[32*i+:32];
+        assign s2m_stream_axil[i].rresp = xbar_s_s2m_axi_rresp[2*i+:2];
+    end
+endgenerate
+
+
+//s2m dma
+
+
+// tx_stream arb mux (ip)
+ip_arb_mux_wrapper #(
+    .S_COUNT(NUM_TCP),
+    .DATA_WIDTH(DATA_WIDTH)
+) u_tx_stream_arb_mux (
+    .i_clk    (i_clk),
+    .i_rst    (i_rst),
+
+    .s_ip   (tcp_stream_tx_ip),
+    .m_ip   (m_ip)
+);
+
+// dest decap
+logic [15:0] tcp_dest;
+logic tcp_dest_valid;
+
+tcp_dest_decap u_tcp_dest_decap(
+    .i_clk      (i_clk),
+    .i_rst      (i_rst),
+
+    .s_ip       (s_ip),
+    .m_ip       (tcp_delayed_rx_ip),
+
+    .o_tcp_dest (tcp_dest),
+    .o_tcp_dest_valid(tcp_dest_valid)
+);
+
+// rx_stream demux (ip)
+
+logic [$clog2(NUM_TCP)-1:0] tcp_demux_sel;
+logic [15:0] tcp_dests [NUM_TCP];
+
+always_comb begin : TCP_DEST_SEL
+    tcp_demux_sel = '0;
+
+    for (int i = 0; i < NUM_TCP; i++) begin
+        if (tcp_dest == tcp_dests[i]) begin
+            tcp_demux_sel = i;
+        end
+    end
+end
+
+ip_demux_wrapper #(
+    .M_COUNT(NUM_TCP)
+) u_ip_demux (
+    .clk        (i_clk),
+    .rst        (i_rst),
+
+    .s_ip       (tcp_delayed_rx_ip),
+    .m_ip       (tcp_stream_rx_ip),
+
+    .enable     (tcp_dest_valid),
+    .drop       ('0),
+    .select     (tcp_demux_sel)
+);
+
+
+generate
+
+    for (genvar i = 0; i < NUM_TCP; i++) begin : TCP_STREAMS
+        logic req;
+        logic req_is_wr;
+        logic [5:0] addr;
+        logic [31:0] wr_data;
+        logic [31:0] wr_biten;
+
+        assign req = tcp_hwif_out.tcp_streams[i].req;
+        assign req_is_wr = tcp_hwif_out.tcp_streams[i].req_is_wr;
+        assign addr = tcp_hwif_out.tcp_streams[i].addr;
+        assign wr_data = tcp_hwif_out.tcp_streams[i].wr_data;
+        assign wr_biten = tcp_hwif_out.tcp_streams[i].wr_biten;
+
+        tcp_stream u_tcp_stream (
+            .clk                        (i_clk),
+            .rst                        (i_rst),
+
+            // This is the hacky decoder alex was telling me about
+            .s_cpuif_req                (req),
+            .s_cpuif_req_is_wr          (req_is_wr),
+            .s_cpuif_addr               (addr),
+            .s_cpuif_wr_data            (wr_data),
+            .s_cpuif_wr_biten           (wr_biten),
+            .s_cpuif_req_stall_wr       (),
+            .s_cpuif_req_stall_rd       (),
+            .s_cpuif_rd_ack             (tcp_hwif_in.tcp_streams[i].rd_ack),
+            .s_cpuif_rd_err             (),
+            .s_cpuif_rd_data            (tcp_hwif_in.tcp_streams[i].rd_data),
+            .s_cpuif_wr_ack             (tcp_hwif_in.tcp_streams[i].wr_ack),
+            .s_cpuif_wr_err             (),
+
+            .o_tcp_port                 (tcp_dests[i]),
+
+            .s_ip_rx                    (tcp_stream_rx_ip[i]),
+            .m_ip_tx                    (tcp_stream_tx_ip[i]),
+
+            .m_m2s_axil                 (m2s_stream_axil[i]),
+            .m_s2m_axil                 (s2m_stream_axil[i])
+        );
+    end
+endgenerate
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/tcp_dest_decap.sv b/hw/super6502_fpga/src/sub/network_processor/src/tcp_dest_decap.sv
new file mode 100644
index 0000000000000000000000000000000000000000..d6f6147082bec4806258a9e43d7289e25da37238
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/tcp_dest_decap.sv
@@ -0,0 +1,148 @@
+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;
+
+    valid = '0;
+
+    m_ip.ip_payload_axis_tdata = '0;
+    m_ip.ip_payload_axis_tvalid = '0;
+    m_ip.ip_payload_axis_tlast = '0;
+    m_ip.ip_payload_axis_tuser = '0;
+    m_ip.ip_payload_axis_tid = '0;
+    m_ip.ip_payload_axis_tdest = '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
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/tcp_packet_generator.sv b/hw/super6502_fpga/src/sub/network_processor/src/tcp_packet_generator.sv
new file mode 100644
index 0000000000000000000000000000000000000000..4f798374c5904b5c2fa499c2d8fbfa503151a441
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/tcp_packet_generator.sv
@@ -0,0 +1,262 @@
+module tcp_packet_generator (
+    input  wire             i_clk,
+    input  wire             i_rst,
+
+    axis_intf.SLAVE         s_axis_data,
+
+    input  wire             i_no_data,
+
+    input  wire [15:0]      i_ip_len,
+    input  wire [31:0]      i_seq_number,
+    input  wire [31:0]      i_ack_number,
+    input  wire [15:0]      i_source_port,
+    input  wire [15:0]      i_dest_port,
+    input  wire [7:0]       i_flags,
+    input  wire [15:0]      i_window_size,
+    input  wire             i_hdr_valid,
+
+    input  wire [31:0]      i_src_ip,
+    input  wire [31:0]      i_dst_ip,
+
+    output logic            o_packet_done,
+
+    ip_intf.MASTER          m_ip
+);
+
+axis_intf #(.DATA_WIDTH(8)) pre_checksum_data();
+axis_intf #(.DATA_WIDTH(8)) post_checksum_data();
+
+logic saf_ready;
+
+assign pre_checksum_data.tdata = s_axis_data.tdata;
+assign pre_checksum_data.tkeep = s_axis_data.tkeep;
+assign pre_checksum_data.tvalid = s_axis_data.tvalid & saf_ready;
+assign s_axis_data.tready = pre_checksum_data.tready & saf_ready;
+assign pre_checksum_data.tlast = s_axis_data.tlast;
+assign pre_checksum_data.tuser = s_axis_data.tuser;
+
+axis_saf_fifo #(
+    .DATA_DEPTH_L2(11),
+    .CTRL_DEPTH_L2(2)
+) u_checksum_fifo (
+    .sclk(i_clk),
+    .srst(i_rst),
+    .s_axis(pre_checksum_data),
+
+    .mclk(i_clk),
+    .mrst(i_rst),
+    .m_axis(post_checksum_data)
+);
+
+logic [31:0] counter, counter_next;
+enum logic [1:0] {IDLE, DATA_CHECKSUM, HEADER, DATA} state, state_next;
+
+
+logic [31:0] checksum_counter, checksum_counter_next;
+logic [15:0] data_checksum;
+assign data_checksum = '0;
+
+logic checksum_enable;
+logic checksum_clear;
+logic [31:0] checksum_data;
+logic [15:0] checksum_final;
+
+logic [31:0] data_expand, data_expand_next;
+logic data_checksum_enable;
+logic data_checksum_clear;
+logic [31:0] data_checksum_data;
+logic [15:0] data_checksum_final;
+
+logic [31:0] src_ip, dst_ip_next;
+logic [31:0] dst_ip, src_ip_next;
+
+checksum_calc u_header_checksum_calc(
+    .i_rst      (i_rst),
+    .i_clk      (i_clk),
+    .i_clear    (checksum_clear),
+    .i_enable   (checksum_enable),
+
+    .i_data     (checksum_data),
+    .o_checksum (checksum_final)
+);
+
+always_ff @(posedge i_clk) begin
+    if (i_rst) begin
+        counter <= '0;
+        checksum_counter <= '0;
+        state <= IDLE;
+        data_expand <= '0;
+        src_ip <= '0;
+        dst_ip <= '0;
+    end else begin
+        counter <= counter_next;
+        checksum_counter <= checksum_counter_next;
+        state <= state_next;
+        data_expand <= data_expand_next;
+        src_ip <= src_ip_next;
+        dst_ip <= dst_ip_next;
+    end
+end
+
+always_comb begin
+    state_next = state;
+
+    m_ip.ip_hdr_valid = '0;
+    m_ip.ip_dscp        = '0;
+    m_ip.ip_ecn         = '0;
+    m_ip.ip_length      = '0;
+    m_ip.ip_ttl         = '0;
+    m_ip.ip_protocol    = '0;
+    m_ip.ip_source_ip   = '0;
+    m_ip.ip_dest_ip     = '0;
+
+    m_ip.ip_payload_axis_tdata  = '0;
+    m_ip.ip_payload_axis_tvalid = '0;
+    m_ip.ip_payload_axis_tlast  = '0;
+    m_ip.ip_payload_axis_tuser  = '0;
+    m_ip.ip_payload_axis_tid    = '0;
+    m_ip.ip_payload_axis_tdest  = '0;
+
+    post_checksum_data.tready = '0;
+
+    checksum_counter_next = checksum_counter;
+    checksum_data = '0;
+
+    counter_next = counter;
+
+    o_packet_done = '0;
+    checksum_clear = '0;
+    checksum_enable = '0;
+
+    saf_ready = '0;
+
+    data_expand_next = data_expand;
+
+    src_ip_next = src_ip;
+    dst_ip_next = dst_ip;
+    case (state)
+
+        IDLE: begin
+            counter_next = '0;
+            checksum_counter_next = '0;
+            checksum_clear = '1;
+
+            if (i_hdr_valid) begin
+                m_ip.ip_hdr_valid   = '1;
+                m_ip.ip_dscp        = '0;
+                m_ip.ip_ecn         = '0;
+                m_ip.ip_length      = i_ip_len;
+                m_ip.ip_ttl         = '1;
+                m_ip.ip_protocol    = 8'h6;
+                m_ip.ip_source_ip   = i_src_ip;
+                m_ip.ip_dest_ip     = i_dst_ip;
+
+                src_ip_next = i_src_ip;
+                dst_ip_next = i_dst_ip;
+
+                if (m_ip.ip_hdr_ready) begin
+                    if (i_no_data) begin
+                        state_next = HEADER;
+                    end else begin
+                        state_next = DATA_CHECKSUM;
+                    end
+                end
+            end
+        end
+
+        DATA_CHECKSUM: begin
+            saf_ready = '1;
+
+            data_expand_next = {data_expand[23:0], pre_checksum_data.tdata};
+            // data_expand_next = {pre_checksum_data.tdata, data_expand[31:8]};
+
+            if (checksum_counter[1:0] == '1) begin
+                checksum_enable = '1;
+                checksum_data = data_expand_next;
+            end
+
+
+            if (s_axis_data.tready & s_axis_data.tvalid) begin
+                checksum_counter_next = checksum_counter + 1;
+                if (s_axis_data.tlast) begin
+                    state_next = HEADER;
+                    checksum_counter_next = '0;
+                end
+            end
+        end
+
+        HEADER: begin
+            m_ip.ip_payload_axis_tvalid = '1;
+            if (checksum_counter < 8) begin
+                checksum_counter_next = checksum_counter + 1;
+                checksum_enable = '1;
+            end
+
+            case (checksum_counter)
+                0: checksum_data = src_ip;
+                1: checksum_data = dst_ip;
+                2: checksum_data = {8'b0, 8'h6, (i_ip_len - 16'd20)}; // tcp length, not IP length
+                3: checksum_data = {i_source_port, i_dest_port};
+                4: checksum_data = i_seq_number;
+                5: checksum_data = i_ack_number;
+                6: checksum_data = {4'h5, 4'h0, i_flags, i_window_size};
+                7: checksum_data = '0;  // checksum and urgent pointer
+            endcase
+
+            case (counter)
+                0:  m_ip.ip_payload_axis_tdata = i_source_port[15:8];
+                1:  m_ip.ip_payload_axis_tdata = i_source_port[7:0];
+                2:  m_ip.ip_payload_axis_tdata = i_dest_port[15:8];
+                3:  m_ip.ip_payload_axis_tdata = i_dest_port[7:0];
+                4:  m_ip.ip_payload_axis_tdata = i_seq_number[31:24];
+                5:  m_ip.ip_payload_axis_tdata = i_seq_number[23:16];
+                6:  m_ip.ip_payload_axis_tdata = i_seq_number[15:8];
+                7:  m_ip.ip_payload_axis_tdata = i_seq_number[7:0];
+                8:  m_ip.ip_payload_axis_tdata = i_ack_number[31:24];
+                9:  m_ip.ip_payload_axis_tdata = i_ack_number[23:16];
+                10: m_ip.ip_payload_axis_tdata = i_ack_number[15:8];
+                11: m_ip.ip_payload_axis_tdata = i_ack_number[7:0];
+                12: m_ip.ip_payload_axis_tdata = {4'h5, 4'h0};
+                13: m_ip.ip_payload_axis_tdata = i_flags;
+                14: m_ip.ip_payload_axis_tdata = i_window_size[15:8];
+                15: m_ip.ip_payload_axis_tdata = i_window_size[7:0];
+                16: m_ip.ip_payload_axis_tdata = checksum_final[15:8];
+                17: m_ip.ip_payload_axis_tdata = checksum_final[7:0];
+                18: m_ip.ip_payload_axis_tdata = '0;
+                19: begin
+                    m_ip.ip_payload_axis_tdata = '0;
+                    m_ip.ip_payload_axis_tlast = i_no_data;    // kinda hacky
+                end
+            endcase
+
+            if (m_ip.ip_payload_axis_tready) begin
+                counter_next = counter + 1;
+
+                if (counter == 19) begin
+                    state_next = DATA;
+                end
+
+                if (m_ip.ip_payload_axis_tlast) begin
+                    state_next = IDLE;
+                    o_packet_done = '1;
+                end
+            end
+        end
+
+        DATA: begin
+            state_next = DATA;
+            post_checksum_data.tready = m_ip.ip_payload_axis_tready;
+            m_ip.ip_payload_axis_tvalid = post_checksum_data.tvalid;
+            m_ip.ip_payload_axis_tdata = post_checksum_data.tdata;
+            m_ip.ip_payload_axis_tlast = post_checksum_data.tlast;
+
+            if (post_checksum_data.tlast && post_checksum_data.tvalid && post_checksum_data.tready) begin
+                state_next = IDLE;
+                o_packet_done = '1;
+            end
+        end
+    endcase
+
+end
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/tcp_parser.sv b/hw/super6502_fpga/src/sub/network_processor/src/tcp_parser.sv
new file mode 100644
index 0000000000000000000000000000000000000000..73a26ee03ae614cdf6072a4737fa253eb5920ae2
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/tcp_parser.sv
@@ -0,0 +1,123 @@
+module tcp_parser(
+    input wire          i_clk,
+    input wire          i_rst,
+
+    ip_intf.SLAVE       s_ip,
+
+    axis_intf.MASTER    m_axis,
+
+    output  wire [31:0]      o_seq_number,
+    output  wire [31:0]      o_ack_number,
+    output  wire [7:0]       o_flags,
+    output  wire [15:0]      o_window_size,
+    output  wire             o_hdr_valid
+);
+
+enum logic {HEADER, PAYLOAD} state, state_next;
+
+logic [4:0] counter, counter_next;
+
+logic hdr_valid;
+
+logic [31:0] sequence_num, sequence_num_next;
+logic [31:0] ack_num, ack_num_next;
+logic [3:0] data_offs, data_offs_next;
+logic [7:0]  flags, flags_next;
+logic [15:0] window_size, window_size_next;
+logic [15:0] checksum, checksum_next;
+
+
+assign o_seq_number = sequence_num;
+assign o_ack_number = ack_num;
+assign o_flags = flags;
+assign o_window_size = window_size;
+assign o_hdr_valid = hdr_valid;
+
+always_ff @(posedge i_clk) begin
+    if (i_rst) begin
+        state <= HEADER;
+        counter <= '0;
+
+        sequence_num <= '0;
+        ack_num <= '0;
+        data_offs <= '0;
+        flags <= '0;
+        window_size <= '0;
+        checksum <= '0;
+    end else begin
+        state <= state_next;
+        counter <= counter_next;
+
+        sequence_num <= sequence_num_next;
+        ack_num <= ack_num_next;
+        data_offs <= data_offs_next;
+        flags <= flags_next;
+        window_size <= window_size_next;
+        checksum <= checksum_next;
+    end
+end
+
+always_comb begin
+    sequence_num_next = sequence_num;
+    ack_num_next = ack_num;
+    data_offs_next = data_offs;
+    flags_next = flags;
+    window_size_next = window_size;
+    checksum_next = checksum;
+    hdr_valid = '0;
+
+    counter_next = counter;
+
+    state_next = state;
+
+    s_ip.ip_hdr_ready = '0;
+    s_ip.ip_payload_axis_tready = '0;
+
+    case (state)
+        HEADER: begin
+            s_ip.ip_hdr_ready = '1;
+            s_ip.ip_payload_axis_tready = '1;
+
+            if (s_ip.ip_payload_axis_tvalid) begin
+                counter_next = counter + 1;
+
+                case (counter)
+                    4:  sequence_num_next   = {s_ip.ip_payload_axis_tdata, sequence_num[23:0]};
+                    5:  sequence_num_next   = {sequence_num[31:24], s_ip.ip_payload_axis_tdata, sequence_num[15:0]};
+                    6:  sequence_num_next   = {sequence_num[31:16], s_ip.ip_payload_axis_tdata, sequence_num[7:0]};
+                    7:  sequence_num_next   = {sequence_num[31:8],  s_ip.ip_payload_axis_tdata};
+                    4:  ack_num_next        = {s_ip.ip_payload_axis_tdata, ack_num[23:0]};
+                    5:  ack_num_next        = {ack_num[31:24], s_ip.ip_payload_axis_tdata, ack_num[15:0]};
+                    6:  ack_num_next        = {ack_num[31:16], s_ip.ip_payload_axis_tdata, ack_num[8:0]};
+                    7:  ack_num_next        = {ack_num[31:8],  s_ip.ip_payload_axis_tdata};
+                    12: data_offs_next      = s_ip.ip_payload_axis_tdata[7:4];
+                    13: flags_next          = s_ip.ip_payload_axis_tdata;
+                    14: window_size_next    = {s_ip.ip_payload_axis_tdata, window_size[7:0]};
+                    15: window_size_next    = {window_size[15:8], s_ip.ip_payload_axis_tdata};
+                    16: checksum_next       = {s_ip.ip_payload_axis_tdata, checksum[7:0]};
+                    17: checksum_next       = {checksum[15:8], s_ip.ip_payload_axis_tdata};
+                    19: begin
+                        state_next = PAYLOAD;
+                        hdr_valid = '1;
+                    end
+                endcase
+
+                if (s_ip.ip_payload_axis_tlast) begin
+                    counter_next = '0;
+                    state_next = HEADER;    // if we see last then we are done, its possible to have no data
+                end
+            end
+        end
+
+        PAYLOAD: begin
+            s_ip.ip_payload_axis_tready = '1;
+            if (s_ip.ip_payload_axis_tlast) begin
+                counter_next = '0;
+                state_next = HEADER;
+            end
+        end
+    endcase
+end
+
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/tcp_pkg.sv b/hw/super6502_fpga/src/sub/network_processor/src/tcp_pkg.sv
new file mode 100644
index 0000000000000000000000000000000000000000..8c43af013aa5226ef02be1bb09100a50757fd045
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/tcp_pkg.sv
@@ -0,0 +1,18 @@
+package tcp_pkg;
+
+    typedef enum logic [2:0] {
+        TX_CTRL_NOP,
+        TX_CTRL_SEND_SYN,
+        TX_CTRL_SEND_ACK,
+        TX_CTRL_SEND_SYNACK,
+        TX_CTRL_SEND_FIN
+    } tx_ctrl_t;
+
+    typedef enum logic [2:0] {
+        RX_MSG_NOP,
+        RX_MSG_RECV_SYN,
+        RX_MSG_RECV_ACK,
+        RX_MSG_RECV_FIN,
+        RX_MSG_RECV_SYNACK
+    } rx_msg_t;
+endpackage
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/tcp_rx_ctrl.sv b/hw/super6502_fpga/src/sub/network_processor/src/tcp_rx_ctrl.sv
new file mode 100644
index 0000000000000000000000000000000000000000..60b15e675d7f719f9d0debc5f3c7b2a1730969db
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/tcp_rx_ctrl.sv
@@ -0,0 +1,68 @@
+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
+);
+
+tcp_pkg::rx_msg_t rx_msg_next;
+logic rx_msg_valid_next;
+
+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;
+        o_rx_msg <= RX_MSG_NOP;
+        o_rx_msg_valid <= '0;
+    end else begin
+        ack_num <= ack_num_next;
+        o_rx_msg <= rx_msg_next;
+        o_rx_msg_valid <= rx_msg_valid_next;
+    end
+end
+
+always_comb begin
+    rx_msg_next = RX_MSG_NOP;
+    rx_msg_valid_next = '0;
+
+    ack_num_next = ack_num;
+
+    if (i_hdr_valid) begin
+        if (i_flags == 8'h12) begin
+            rx_msg_next = RX_MSG_RECV_SYNACK;
+            rx_msg_valid_next = '1;
+
+            ack_num_next = i_seq_number + 1;
+        end
+
+        if (i_flags == 8'h11) begin
+            rx_msg_next = RX_MSG_RECV_FIN;
+            rx_msg_valid_next = '1;
+            ack_num_next = i_seq_number + 1;
+        end
+
+        if (i_flags == 8'h10) begin
+            rx_msg_next = RX_MSG_RECV_ACK;
+            rx_msg_valid_next = '1;
+        end
+
+    end
+end
+
+endmodule
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/tcp_state_manager.sv b/hw/super6502_fpga/src/sub/network_processor/src/tcp_state_manager.sv
new file mode 100644
index 0000000000000000000000000000000000000000..9f192984998335f59732cf6b66cbfac2e8064298
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/tcp_state_manager.sv
@@ -0,0 +1,142 @@
+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_open_clr = '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;
+                o_open_clr = '1;
+            end
+        end
+
+        ESTABLISHED: begin
+            if (i_rx_msg_valid && i_rx_msg == RX_MSG_RECV_FIN) begin
+                o_tx_ctrl = TX_CTRL_SEND_ACK;
+                o_tx_ctrl_valid = '1;
+                tcp_state_next = WAIT_CLOSE;
+            end
+
+            if (i_close) begin
+                o_tx_ctrl = TX_CTRL_SEND_FIN;
+                o_tx_ctrl_valid = '1;
+                tcp_state_next = FIN_WAIT_1;
+            end
+        end
+
+        FIN_WAIT_1: begin
+            if (i_rx_msg_valid) begin
+                if (i_rx_msg == RX_MSG_RECV_ACK) begin
+                    tcp_state_next = FIN_WAIT_2;
+                end else if (i_rx_msg == RX_MSG_RECV_FIN) begin
+                    tcp_state_next = TIME_WAIT;
+                    o_tx_ctrl_valid = '1;
+                    o_tx_ctrl = TX_CTRL_SEND_ACK;
+                end
+            end
+        end
+
+        FIN_WAIT_2: begin
+            if (i_rx_msg == RX_MSG_RECV_FIN) begin
+                tcp_state_next = TIME_WAIT;
+                o_tx_ctrl = TX_CTRL_SEND_ACK;
+                o_tx_ctrl_valid = '1;
+            end
+        end
+
+        TIME_WAIT: begin
+            tcp_state_next = IDLE;
+        end
+
+        WAIT_CLOSE: begin
+            o_tx_ctrl = TX_CTRL_SEND_FIN;
+            o_tx_ctrl_valid = '1;
+            if (i_tx_ctrl_ack) begin        // we should be doing this other places too...
+                tcp_state_next = LAST_ACK;
+            end
+        end
+
+        LAST_ACK: begin
+            if (i_rx_msg_valid && i_rx_msg == RX_MSG_RECV_ACK) begin
+                tcp_state_next = IDLE;
+            end
+        end
+    endcase
+end
+
+endmodule
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/tcp_stream.sv b/hw/super6502_fpga/src/sub/network_processor/src/tcp_stream.sv
new file mode 100644
index 0000000000000000000000000000000000000000..f1da8e21e6dcd082804e0321c57b678c6c7a9869
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/tcp_stream.sv
@@ -0,0 +1,264 @@
+module tcp_stream #(
+    parameter DATA_WIDTH = 8,
+    parameter KEEP_WIDTH = ((DATA_WIDTH+7)/8),
+    parameter DEST_WIDTH = 8,
+    parameter USER_WIDTH = 1
+)(
+    input wire clk,
+    input wire rst,
+
+    input wire s_cpuif_req,
+    input wire s_cpuif_req_is_wr,
+    input wire [5:0] s_cpuif_addr,
+    input wire [31:0] s_cpuif_wr_data,
+    input wire [31:0] s_cpuif_wr_biten,
+    output wire s_cpuif_req_stall_wr,
+    output wire s_cpuif_req_stall_rd,
+    output wire s_cpuif_rd_ack,
+    output wire s_cpuif_rd_err,
+    output wire [31:0] s_cpuif_rd_data,
+    output wire s_cpuif_wr_ack,
+    output wire s_cpuif_wr_err,
+
+    output logic [15:0] o_tcp_port,
+
+    ip_intf.SLAVE s_ip_rx,
+    ip_intf.MASTER m_ip_tx,
+
+    axil_intf.MASTER m_m2s_axil,
+    axil_intf.MASTER m_s2m_axil
+);
+
+axis_intf m2s_axis();
+axis_intf m2s_axis_pre_reg();
+axis_intf s2m_axis();
+
+ip_intf m_ip_tx_pre_reg();
+
+axis_intf m2s_post_saf_axis();
+axis_intf s2m_pre_saf_axis();
+
+axis_intf m_tx_ctrl_axis_data();
+
+// regs
+tcp_stream_regs_pkg::tcp_stream_regs__in_t hwif_in;
+tcp_stream_regs_pkg::tcp_stream_regs__out_t hwif_out;
+
+tcp_pkg::tx_ctrl_t tx_ctrl;
+logic tx_ctrl_valid;
+logic tx_ctrl_ack;
+
+tcp_pkg::rx_msg_t rx_msg;
+logic rx_msg_valid;
+logic rx_msg_ack;
+
+logic w_no_data;
+
+logic [15:0]         w_saf_pkt_len;
+logic [15:0]         w_tx_ip_len;
+logic [31:0]         w_tx_seq_number;
+logic [31:0]         w_tx_ack_number;
+logic [7:0]          w_tx_flags;
+logic [15:0]         w_tx_window_size;
+logic                w_tx_hdr_valid;
+logic                w_tx_packet_done;
+
+logic [31:0]         w_rx_seq_number;
+logic [31:0]         w_rx_ack_number;
+logic [7:0]          w_rx_flags;
+logic [15:0]         w_rx_window_size;
+logic                w_rx_hdr_valid;
+
+
+assign o_tcp_port = hwif_out.source_port.d.value;
+
+
+tcp_stream_regs u_tcp_stream_regs (
+    .clk                    (clk),
+    .rst                    (rst),
+
+    .s_cpuif_req            (s_cpuif_req),
+    .s_cpuif_req_is_wr      (s_cpuif_req_is_wr),
+    .s_cpuif_addr           (s_cpuif_addr),
+    .s_cpuif_wr_data        (s_cpuif_wr_data),
+    .s_cpuif_wr_biten       (s_cpuif_wr_biten),
+    .s_cpuif_req_stall_wr   (s_cpuif_req_stall_wr),
+    .s_cpuif_req_stall_rd   (s_cpuif_req_stall_rd),
+    .s_cpuif_rd_ack         (s_cpuif_rd_ack),
+    .s_cpuif_rd_err         (s_cpuif_rd_err),
+    .s_cpuif_rd_data        (s_cpuif_rd_data),
+    .s_cpuif_wr_ack         (s_cpuif_wr_ack),
+    .s_cpuif_wr_err         (s_cpuif_wr_err),
+
+    .hwif_in                (hwif_in),
+    .hwif_out               (hwif_out)
+);
+
+m2s_dma #(
+    .AXIS_DATA_WIDTH(DATA_WIDTH)
+) u_m2s_dma (
+    .i_clk                      (clk),
+    .i_rst                      (rst),
+
+    .s_cpuif_req                (hwif_out.m2s_dma_regs.req),
+    .s_cpuif_req_is_wr          (hwif_out.m2s_dma_regs.req_is_wr),
+    .s_cpuif_addr               (hwif_out.m2s_dma_regs.addr),
+    .s_cpuif_wr_data            (hwif_out.m2s_dma_regs.wr_data),
+    .s_cpuif_wr_biten           (hwif_out.m2s_dma_regs.wr_biten),
+    .s_cpuif_req_stall_wr       (),
+    .s_cpuif_req_stall_rd       (),
+    .s_cpuif_rd_ack             (hwif_in.m2s_dma_regs.rd_ack),
+    .s_cpuif_rd_err             (),
+    .s_cpuif_rd_data            (hwif_in.m2s_dma_regs.rd_data),
+    .s_cpuif_wr_ack             (hwif_in.m2s_dma_regs.wr_ack),
+    .s_cpuif_wr_err             (),
+
+    .m_axil                     (m_m2s_axil),
+    .m_axis                     (m2s_axis_pre_reg)
+);
+
+axis_pipeline_register_wrapper u_m2s_reg (
+    .clk(clk),
+    .rst(rst),
+
+    .s_axis(m2s_axis_pre_reg),
+    .m_axis(m2s_axis)
+);
+
+
+// tcp state manager
+tcp_state_manager u_tcp_state_manager (
+    .i_clk                      (clk),
+    .i_rst                      (rst),
+
+    .i_enable                   (hwif_out.control.enable.value),
+
+    .i_open                     (hwif_out.control.open.value),
+    .o_open_clr                 (hwif_in.control.open.hwclr),
+    .i_close                    (hwif_out.control.close.value),
+    .o_close_clr                (hwif_in.control.close.hwclr),
+
+    .o_tx_ctrl                  (tx_ctrl),
+    .o_tx_ctrl_valid            (tx_ctrl_valid),
+    .i_tx_ctrl_ack              (tx_ctrl_ack),
+
+    .i_rx_msg                   (rx_msg),
+    .i_rx_msg_valid             (rx_msg_valid),
+    .o_rx_msg_ack               (rx_msg_ack)
+);
+
+
+// tx buffer
+axis_saf_fifo #(
+    .DATA_DEPTH_L2(12),
+    .CTRL_DEPTH_L2(7),
+    .DATA_MEM("distributed"),
+    .CTRL_MEM("distributed")
+) m2s_saf_fifo (
+    .sclk       (clk),
+    .srst       (rst),
+    .s_axis     (m2s_axis),
+
+    .mclk       (clk),
+    .mrst       (rst),
+    .m_axis     (m2s_post_saf_axis),
+
+    .o_len      (w_saf_pkt_len),
+    .o_rx_pkt   (),
+    .o_tx_pkt   (),
+    .o_drop     ()
+);
+
+
+// tx control
+tcp_tx_ctrl u_tcp_tx_ctrl (
+    .i_clk                      (clk),
+    .i_rst                      (rst),
+
+    .i_tx_ctrl                  (tx_ctrl),
+    .i_tx_ctrl_valid            (tx_ctrl_valid),
+    .o_tx_ctrl_ack              (tx_ctrl_ack),
+
+    .o_no_data                  (w_no_data),
+    .o_ip_len                   (w_tx_ip_len),
+    .o_seq_number               (w_tx_seq_number),
+    // .o_ack_number               (w_tx_ack_number),
+    .o_flags                    (w_tx_flags),
+    .o_window_size              (w_tx_window_size),
+    .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)
+);
+
+// packet generator
+tcp_packet_generator u_tcp_packet_generator (
+    .i_clk                      (clk),
+    .i_rst                      (rst),
+
+    .s_axis_data                (m_tx_ctrl_axis_data),
+
+    .i_no_data                  (w_no_data),
+    .i_ip_len                   (w_tx_ip_len),
+    .i_seq_number               (w_tx_seq_number),
+    .i_ack_number               (w_tx_ack_number),
+    .i_source_port              (hwif_out.source_port.d.value),
+    .i_dest_port                (hwif_out.dest_port.d.value),
+    .i_flags                    (w_tx_flags),
+    .i_window_size              (w_tx_window_size),
+    .i_hdr_valid                (w_tx_hdr_valid),
+    .i_src_ip                   (hwif_out.source_ip.d.value),
+    .i_dst_ip                   (hwif_out.dest_ip.d.value),
+
+    .o_packet_done              (w_tx_packet_done),
+
+    .m_ip                       (m_ip_tx_pre_reg)
+);
+
+ip_pipeline_register_wrapper u_tx_ip_reg (
+    .clk(clk),
+    .rst(rst),
+
+    .s_ip(m_ip_tx_pre_reg),
+    .m_ip(m_ip_tx)
+);
+
+// parser
+tcp_parser u_tcp_parser (
+    .i_clk                      (clk),
+    .i_rst                      (rst),
+
+    .s_ip                       (s_ip_rx),
+    .m_axis                     (s2m_pre_saf_axis),
+
+    .o_seq_number               (w_rx_seq_number),
+    .o_ack_number               (w_rx_ack_number),
+    .o_flags                    (w_rx_flags),
+    .o_window_size              (w_rx_window_size),
+    .o_hdr_valid                (w_rx_hdr_valid)
+);
+
+// rx control
+tcp_rx_ctrl u_tcp_rx_ctrl (
+    .i_clk                      (clk),
+    .i_rst                      (rst),
+
+    .o_rx_msg                   (rx_msg),
+    .o_rx_msg_valid             (rx_msg_valid),
+    .i_rx_msg_ack               (rx_msg_ack),
+
+    .i_seq_number               (w_rx_seq_number),
+    .i_ack_number               (w_rx_ack_number),
+    .i_flags                    (w_rx_flags),
+    .i_window_size              (w_rx_window_size),
+    .i_hdr_valid                (w_rx_hdr_valid),
+
+    .o_ack_number               (w_tx_ack_number)
+);
+
+// rx buffer
+
+endmodule
diff --git a/hw/super6502_fpga/src/sub/network_processor/src/tcp_tx_ctrl.sv b/hw/super6502_fpga/src/sub/network_processor/src/tcp_tx_ctrl.sv
new file mode 100644
index 0000000000000000000000000000000000000000..f6cc1595001da80d7489d4ccb824c7487083d318
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/network_processor/src/tcp_tx_ctrl.sv
@@ -0,0 +1,139 @@
+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                o_no_data,
+
+    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
+);
+
+axis_pipeline_register_wrapper u_m2s_reg (
+    .clk(i_clk),
+    .rst(i_rst),
+
+    .s_axis(s_axis),
+    .m_axis(m_axis)
+);
+
+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_no_data = '0;
+
+    o_tx_ctrl_ack = '0;
+
+    o_ack_number    = '0;
+    o_flags         = '0;
+    o_window_size   = 16'h100;
+    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_no_data = '1;
+            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_no_data = '1;
+            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_no_data = '0;
+            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_no_data = '1;
+            o_ip_len = 16'd40;   // default length of IP packet
+            o_hdr_valid = '1;
+
+            if (i_packet_done) begin
+                state_next = IDLE;
+                seq_num_next = seq_num + 1;
+            end
+        end
+    endcase
+end
+
+endmodule
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/rtl-common b/hw/super6502_fpga/src/sub/rtl-common
index 6bb56be03a32ea76c7477e2403b396ede5818c31..1f071c11d920882c4a82c25e84a3f34f169f28ad 160000
--- a/hw/super6502_fpga/src/sub/rtl-common
+++ b/hw/super6502_fpga/src/sub/rtl-common
@@ -1 +1 @@
-Subproject commit 6bb56be03a32ea76c7477e2403b396ede5818c31
+Subproject commit 1f071c11d920882c4a82c25e84a3f34f169f28ad
diff --git a/hw/super6502_fpga/src/sub/sd_controller_wrapper/sdspi b/hw/super6502_fpga/src/sub/sd_controller_wrapper/sdspi
index 4738e699cadfdc7eedc5a9406563dd15a1c1950b..eb8e8ba552ab1e336ac1478ed9d4e7962eab44c2 160000
--- a/hw/super6502_fpga/src/sub/sd_controller_wrapper/sdspi
+++ b/hw/super6502_fpga/src/sub/sd_controller_wrapper/sdspi
@@ -1 +1 @@
-Subproject commit 4738e699cadfdc7eedc5a9406563dd15a1c1950b
+Subproject commit eb8e8ba552ab1e336ac1478ed9d4e7962eab44c2
diff --git a/hw/super6502_fpga/src/sub/sd_controller_wrapper/sources.list b/hw/super6502_fpga/src/sub/sd_controller_wrapper/sources.list
new file mode 100644
index 0000000000000000000000000000000000000000..1fcbeef6bd9f6d1cf5b427747630faf58bed99f0
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/sd_controller_wrapper/sources.list
@@ -0,0 +1,22 @@
+sd_controller_wrapper.sv
+shadow_regs.sv
+sdspi/rtl/sdckgen.v
+sdspi/rtl/sddma_rxgears.v
+sdspi/rtl/sddma.v
+sdspi/rtl/sdrxframe.v
+sdspi/rtl/sdtxframe.v
+sdspi/rtl/sddma_s2mm.v
+sdspi/rtl/sddma_s2mm_axi.v
+# sdspi/rtl/afifo.v
+sdspi/rtl/sddma_txgears.v
+sdspi/rtl/sdskid.v
+sdspi/rtl/sdfrontend.v
+sdspi/rtl/spicmd.v
+sdspi/rtl/sdaxil.v
+sdspi/rtl/sddma_mm2s.v
+sdspi/rtl/sddma_mm2s_axi.v
+sdspi/rtl/sdio_top.v
+sdspi/rtl/sdwb.v
+sdspi/rtl/sdio.v
+sdspi/rtl/sdcmd.v
+sdspi/rtl/sdfifo.v
\ No newline at end of file
diff --git a/hw/super6502_fpga/src/sub/stream_dmas b/hw/super6502_fpga/src/sub/stream_dmas
new file mode 160000
index 0000000000000000000000000000000000000000..cbd06e5af4f80b6dadf12395f521d83ca85b4aae
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/stream_dmas
@@ -0,0 +1 @@
+Subproject commit cbd06e5af4f80b6dadf12395f521d83ca85b4aae
diff --git a/hw/super6502_fpga/src/sub/verilog-ethernet b/hw/super6502_fpga/src/sub/verilog-ethernet
new file mode 160000
index 0000000000000000000000000000000000000000..e00d2466b0f2ce4e10653e7a40fdc814bf422d21
--- /dev/null
+++ b/hw/super6502_fpga/src/sub/verilog-ethernet
@@ -0,0 +1 @@
+Subproject commit e00d2466b0f2ce4e10653e7a40fdc814bf422d21
diff --git a/hw/super6502_fpga/src/sub/wb2axip b/hw/super6502_fpga/src/sub/wb2axip
index bf09db69cbeba4f8b52edeb6bd6dfe824bb741da..29e1e3755f04becaaee878a8437b80444bb96df2 160000
--- a/hw/super6502_fpga/src/sub/wb2axip
+++ b/hw/super6502_fpga/src/sub/wb2axip
@@ -1 +1 @@
-Subproject commit bf09db69cbeba4f8b52edeb6bd6dfe824bb741da
+Subproject commit 29e1e3755f04becaaee878a8437b80444bb96df2
diff --git a/hw/super6502_fpga/super6502_fpga.xml b/hw/super6502_fpga/super6502_fpga.xml
index e6ebffc064c8029752422521b2e5932f7c60cbce..4d2ba84c981bdb3994ebc95cd7fc2319c801d07c 100644
--- a/hw/super6502_fpga/super6502_fpga.xml
+++ b/hw/super6502_fpga/super6502_fpga.xml
@@ -1,118 +1,298 @@
-<efx:project xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="super6502_fpga" description="" last_change_date="Wed Jul 31 2024 10:01:03 PM" location="/home/byron/Projects/super6502/hw/super6502_fpga" sw_version="2023.1.150" last_run_state="pass" last_run_tool="efx_pgm" last_run_flow="bitstream" config_result_in_sync="sync" design_ood="sync" place_ood="sync" route_ood="sync" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
+<?xml version="1.0" encoding="UTF-8"?>
+<efx:project name="super6502_fpga" description="" last_change="1728874681" sw_version="2024.1.163" last_run_state="pass" last_run_flow="bitstream" config_result_in_sync="sync" design_ood="sync" place_ood="sync" route_ood="sync" xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
     <efx:device_info>
-        <efx:family name="Trion" />
-        <efx:device name="T20F256" />
-        <efx:timing_model name="I4" />
+        <efx:family name="Trion"/>
+        <efx:device name="T20F256"/>
+        <efx:timing_model name="I4"/>
     </efx:device_info>
     <efx:design_info def_veri_version="sv_09" def_vhdl_version="vhdl_2008">
-        <efx:top_module name="super6502_fpga" />
-        <efx:design_file name="src/rtl/super_6502_fpga.sv" version="default" library="default" />
-        <efx:design_file name="src/sub/cpu_wrapper/cpu_wrapper.sv" version="default" library="default" />
-        <efx:design_file name="src/sub/rtl-common/src/rtl/axi4_lite_rom.sv" version="default" library="default" />
-        <efx:design_file name="src/sub/rtl-common/src/rtl/axi4_lite_ram.sv" version="default" library="default" />
-        <efx:design_file name="src/sub/rtl-common/src/rtl/ff_cdc.sv" version="default" library="default" />
-        <efx:design_file name="src/sub/rtl-common/src/rtl/axi4_lite_to_apb4.sv" version="default" library="default" />
-        <efx:design_file name="src/sub/rtl-common/src/rtl/async_fifo.sv" version="default" library="default" />
-        <efx:design_file name="src/sub/wb2axip/rtl/axilxbar.v" version="default" library="default" />
-        <efx:design_file name="src/sub/wb2axip/rtl/addrdecode.v" version="default" library="default" />
-        <efx:design_file name="src/sub/wb2axip/rtl/skidbuffer.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sd_controller_wrapper.sv" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/shadow_regs.sv" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdckgen.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_rxgears.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdrxframe.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdtxframe.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_s2mm.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_s2mm_axi.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/afifo.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_txgears.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdskid.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdfrontend.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/spicmd.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdaxil.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_mm2s.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_mm2s_axi.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdio_top.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdwb.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdio.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdcmd.v" version="default" library="default" />
-        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdfifo.v" version="default" library="default" />
-        <efx:top_vhdl_arch name="" />
+        <efx:top_module name="super6502_fpga"/>
+        <efx:design_file name="src/rtl/super_6502_fpga.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/cpu_wrapper/cpu_wrapper.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/rtl-common/src/rtl/axi4_lite_rom.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/rtl-common/src/rtl/axi4_lite_ram.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/rtl-common/src/rtl/ff_cdc.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/rtl-common/src/rtl/axi4_lite_to_apb4.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/rtl-common/src/rtl/async_fifo.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/wb2axip/rtl/axilxbar.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/wb2axip/rtl/addrdecode.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/wb2axip/rtl/skidbuffer.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sd_controller_wrapper.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/shadow_regs.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdckgen.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_rxgears.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdrxframe.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdtxframe.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_s2mm.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_s2mm_axi.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/afifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_txgears.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdskid.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdfrontend.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/spicmd.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdaxil.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_mm2s.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sddma_mm2s_axi.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdio_top.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdwb.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdio.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdcmd.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/sd_controller_wrapper/sdspi/rtl/sdfifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/tcp_stream.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/tcp_state_manager.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/network_processor.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/regs/tcp_stream_regs_pkg.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/regs/tcp_top_regfile.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/regs/tcp_stream_regs.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/regs/tcp_top_regfile_pkg.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/eth_wrapper.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/tcp.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/regs/mac_regs_pkg.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/regs/ntw_top_regfile.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/regs/mac_regs.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/regs/ntw_top_regfile_pkg.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/rgmii_phy_if.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_ip_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_duplicator.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ptp_clock_cdc.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_phy_10g.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/mac_ctrl_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_phy_10g_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_arb_mux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ptp_tag_insert.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_1g_rgmii.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_gmii_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_axis_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_10g_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_checksum_gen.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ssio_sdr_out.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_complete.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_baser_rx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ptp_td_phc.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_phy_10g_rx_if.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_baser_tx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_demux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_arb_mux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/filter.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_1g.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_eth_tx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/icmp_ip_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/modifier.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/mac_pause_ctrl_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/lfsr.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/arp_eth_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_1g_rgmii_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_1g_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_xgmii_tx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_1g_gmii.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_demux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_phy_10g.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_checksum_gen_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/mac_ctrl_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_mii_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/icmp_ip_rx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ssio_sdr_in_diff.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_eth_fcs_check.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_xgmii_rx_32.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_10g.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/xgmii_baser_enc_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_complete_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_complete_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_phy_10g_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/arp_eth_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_phy_10g_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/icmp_ip_tx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_eth_fcs.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ptp_clock.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_arb_mux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_eth_fcs_insert_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ptp_td_leaf.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ssio_ddr_in_diff.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_phy_10g_rx_ber_mon.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_phy_10g_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_phy_10g_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_eth_fcs_check_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/mii_phy_if.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_mux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ptp_td_rel2tod.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/xgmii_interleave.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_gmii_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/mac_pause_ctrl_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ptp_perout.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_ip_rx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_eth_fcs_insert.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/oddr.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ssio_sdr_in.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ssio_ddr_out_diff.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/arp.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_complete.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_xgmii_rx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_eth_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ssio_sdr_out_diff.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_eth_rx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_axis_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip_eth_rx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_phy_10g_rx_watchdog.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_mii.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/xgmii_deinterleave.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_ip_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/xgmii_baser_dec_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ptp_ts_extract.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_ip_tx_64.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/axis_xgmii_tx_32.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ip.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/gmii_phy_if.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/icmp_ip_tx.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/iddr.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_mac_1g_gmii_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_demux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ssio_ddr_in.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/ssio_ddr_out.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_phy_10g_rx_frame_sync.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/arp_cache.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/eth_phy_10g_tx_if.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/rtl/udp_mux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_rate_limit.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_crosspoint.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_frame_length_adjust_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_frame_join.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_srl_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_ll_bridge.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_pipeline_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_switch.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_demux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_async_fifo_adapter.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_tap.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_fifo_adapter.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_arb_mux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/ll_axis_bridge.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_stat_counter.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_ram_switch.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_srl_register.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_adapter.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/arbiter.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_broadcast.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_async_fifo.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_register.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_cobs_decode.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_pipeline_register.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_mux.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_cobs_encode.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_frame_length_adjust.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_frame_len.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/sync_reset.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/priority_encoder.v" version="default" library="default"/>
+        <efx:design_file name="src/sub/stream_dmas/src/m2s_dma.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/stream_dmas/src/regs/m2s_dma_regs.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/stream_dmas/src/regs/m2s_dma_regs_pkg.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/tcp_pkg.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/tcp_parser.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/ip_demux_wrapper.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/tcp_rx_ctrl.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/ip_arb_mux_wrapper.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/s2m_dma.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/tcp_dest_decap.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/tcp_packet_generator.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/tcp_tx_ctrl.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/checksum_calc.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/interfaces/axil_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/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:design_file name="src/sub/network_processor/src/ip_pipeline_register_wrapper.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/verilog-ethernet/lib/axis/rtl/axis_pipeline_register_wrapper.sv" version="default" library="default"/>
+        <efx:design_file name="src/sub/network_processor/src/axil_reg_slice.sv" version="default" library="default"/>
+        <efx:top_vhdl_arch name=""/>
     </efx:design_info>
     <efx:constraint_info>
-        <efx:sdc_file name="constraints/constraints.sdc" />
-        <efx:inter_file name="" />
+        <efx:sdc_file name="constraints/constraints.sdc"/>
+        <efx:inter_file name=""/>
     </efx:constraint_info>
-    <efx:sim_info />
-    <efx:misc_info />
+    <efx:sim_info/>
+    <efx:misc_info/>
     <efx:ip_info>
         <efx:ip instance_name="sdram_controller" path="ip/sdram_controller/settings.json">
-            <efx:ip_src_file name="sdram_controller.v" />
+            <efx:ip_src_file name="sdram_controller.v"/>
         </efx:ip>
     </efx:ip_info>
     <efx:synthesis tool_name="efx_map">
-        <efx:param name="work_dir" value="work_syn" value_type="e_string" />
-        <efx:param name="write_efx_verilog" value="on" value_type="e_bool" />
-        <efx:param name="allow-const-ram-index" value="0" value_type="e_option" />
-        <efx:param name="blackbox-error" value="1" value_type="e_option" />
-        <efx:param name="blast_const_operand_adders" value="1" value_type="e_option" />
-        <efx:param name="bram_output_regs_packing" value="1" value_type="e_option" />
-        <efx:param name="create-onehot-fsms" value="0" value_type="e_option" />
-        <efx:param name="fanout-limit" value="0" value_type="e_integer" />
-        <efx:param name="hdl-compile-unit" value="1" value_type="e_option" />
-        <efx:param name="infer-clk-enable" value="3" value_type="e_option" />
-        <efx:param name="infer-sync-set-reset" value="1" value_type="e_option" />
-        <efx:param name="max_ram" value="-1" value_type="e_integer" />
-        <efx:param name="max_mult" value="-1" value_type="e_integer" />
-        <efx:param name="min-sr-fanout" value="0" value_type="e_integer" />
-        <efx:param name="min-ce-fanout" value="0" value_type="e_integer" />
-        <efx:param name="mult-decomp-retime" value="0" value_type="e_option" />
-        <efx:param name="mode" value="speed" value_type="e_option" />
-        <efx:param name="operator-sharing" value="0" value_type="e_option" />
-        <efx:param name="optimize-adder-tree" value="0" value_type="e_option" />
-        <efx:param name="optimize-zero-init-rom" value="1" value_type="e_option" />
-        <efx:param name="retiming" value="1" value_type="e_option" />
-        <efx:param name="seq_opt" value="1" value_type="e_option" />
-        <efx:param name="seq-opt-sync-only" value="0" value_type="e_option" />
-        <efx:param name="mult_input_regs_packing" value="1" value_type="e_option" />
-        <efx:param name="mult_output_regs_packing" value="1" value_type="e_option" />
-        <efx:param name="include" value="ip/sdram_controller" value_type="e_string" />
-        <efx:defmacro name="SDIO_AXI" value="1" />
-        <efx:defmacro name="EFINIX" value="1" />
+        <efx:param name="work_dir" value="work_syn" value_type="e_string"/>
+        <efx:param name="write_efx_verilog" value="on" value_type="e_bool"/>
+        <efx:param name="allow-const-ram-index" value="0" value_type="e_option"/>
+        <efx:param name="blackbox-error" value="1" value_type="e_option"/>
+        <efx:param name="blast_const_operand_adders" value="1" value_type="e_option"/>
+        <efx:param name="bram_output_regs_packing" value="1" value_type="e_option"/>
+        <efx:param name="create-onehot-fsms" value="0" value_type="e_option"/>
+        <efx:param name="fanout-limit" value="0" value_type="e_integer"/>
+        <efx:param name="hdl-compile-unit" value="1" value_type="e_option"/>
+        <efx:param name="infer-clk-enable" value="3" value_type="e_option"/>
+        <efx:param name="infer-sync-set-reset" value="1" value_type="e_option"/>
+        <efx:param name="max_ram" value="-1" value_type="e_integer"/>
+        <efx:param name="max_mult" value="-1" value_type="e_integer"/>
+        <efx:param name="min-sr-fanout" value="0" value_type="e_integer"/>
+        <efx:param name="min-ce-fanout" value="0" value_type="e_integer"/>
+        <efx:param name="mult-decomp-retime" value="0" value_type="e_option"/>
+        <efx:param name="mode" value="speed" value_type="e_option"/>
+        <efx:param name="operator-sharing" value="0" value_type="e_option"/>
+        <efx:param name="optimize-adder-tree" value="0" value_type="e_option"/>
+        <efx:param name="optimize-zero-init-rom" value="1" value_type="e_option"/>
+        <efx:param name="retiming" value="1" value_type="e_option"/>
+        <efx:param name="seq_opt" value="1" value_type="e_option"/>
+        <efx:param name="seq-opt-sync-only" value="0" value_type="e_option"/>
+        <efx:param name="mult_input_regs_packing" value="1" value_type="e_option"/>
+        <efx:param name="mult_output_regs_packing" value="1" value_type="e_option"/>
+        <efx:param name="include" value="ip/sdram_controller" value_type="e_string"/>
+        <efx:param name="bram-push-tco-outreg" value="0" value_type="e_option"/>
+        <efx:param name="mult-auto-pipeline" value="0" value_type="e_integer"/>
+        <efx:param name="use-logic-for-small-mem" value="64" value_type="e_integer"/>
+        <efx:param name="use-logic-for-small-rom" value="64" value_type="e_integer"/>
+        <efx:defmacro name="SDIO_AXI" value="1"/>
+        <efx:defmacro name="EFINIX" value="1"/>
     </efx:synthesis>
     <efx:place_and_route tool_name="efx_pnr">
-        <efx:param name="work_dir" value="work_pnr" value_type="e_string" />
-        <efx:param name="verbose" value="off" value_type="e_bool" />
-        <efx:param name="load_delaym" value="on" value_type="e_bool" />
-        <efx:param name="optimization_level" value="TIMING_3" value_type="e_option" />
-        <efx:param name="seed" value="1" value_type="e_integer" />
-        <efx:param name="placer_effort_level" value="5" value_type="e_option" />
-        <efx:param name="max_threads" value="-1" value_type="e_integer" />
+        <efx:param name="work_dir" value="work_pnr" value_type="e_string"/>
+        <efx:param name="verbose" value="off" value_type="e_bool"/>
+        <efx:param name="load_delaym" value="on" value_type="e_bool"/>
+        <efx:param name="optimization_level" value="TIMING_3" value_type="e_option"/>
+        <efx:param name="seed" value="1" value_type="e_integer"/>
+        <efx:param name="placer_effort_level" value="5" value_type="e_option"/>
+        <efx:param name="max_threads" value="-1" value_type="e_integer"/>
+        <efx:param name="print_critical_path" value="10" value_type="e_integer"/>
     </efx:place_and_route>
     <efx:bitstream_generation tool_name="efx_pgm">
-        <efx:param name="mode" value="active" value_type="e_option" />
-        <efx:param name="width" value="1" value_type="e_option" />
-        <efx:param name="enable_roms" value="smart" value_type="e_option" />
-        <efx:param name="spi_low_power_mode" value="on" value_type="e_bool" />
-        <efx:param name="io_weak_pullup" value="on" value_type="e_bool" />
-        <efx:param name="oscillator_clock_divider" value="DIV8" value_type="e_option" />
-        <efx:param name="bitstream_compression" value="off" value_type="e_bool" />
-        <efx:param name="enable_external_master_clock" value="off" value_type="e_bool" />
-        <efx:param name="active_capture_clk_edge" value="posedge" value_type="e_option" />
-        <efx:param name="jtag_usercode" value="0xFFFFFFFF" value_type="e_string" />
-        <efx:param name="release_tri_then_reset" value="on" value_type="e_bool" />
-        <efx:param name="four_byte_addressing" value="off" value_type="e_bool" />
-        <efx:param name="generate_bit" value="on" value_type="e_bool" />
-        <efx:param name="generate_bitbin" value="off" value_type="e_bool" />
-        <efx:param name="generate_hex" value="on" value_type="e_bool" />
-        <efx:param name="generate_hexbin" value="off" value_type="e_bool" />
-        <efx:param name="cold_boot" value="off" value_type="e_bool" />
-        <efx:param name="cascade" value="off" value_type="e_option" />
+        <efx:param name="mode" value="active" value_type="e_option"/>
+        <efx:param name="width" value="1" value_type="e_option"/>
+        <efx:param name="enable_roms" value="smart" value_type="e_option"/>
+        <efx:param name="spi_low_power_mode" value="on" value_type="e_bool"/>
+        <efx:param name="io_weak_pullup" value="on" value_type="e_bool"/>
+        <efx:param name="oscillator_clock_divider" value="DIV8" value_type="e_option"/>
+        <efx:param name="bitstream_compression" value="off" value_type="e_bool"/>
+        <efx:param name="enable_external_master_clock" value="off" value_type="e_bool"/>
+        <efx:param name="active_capture_clk_edge" value="posedge" value_type="e_option"/>
+        <efx:param name="jtag_usercode" value="0xFFFFFFFF" value_type="e_string"/>
+        <efx:param name="release_tri_then_reset" value="on" value_type="e_bool"/>
+        <efx:param name="four_byte_addressing" value="off" value_type="e_bool"/>
+        <efx:param name="generate_bit" value="on" value_type="e_bool"/>
+        <efx:param name="generate_bitbin" value="off" value_type="e_bool"/>
+        <efx:param name="generate_hex" value="on" value_type="e_bool"/>
+        <efx:param name="generate_hexbin" value="off" value_type="e_bool"/>
+        <efx:param name="cold_boot" value="off" value_type="e_bool"/>
+        <efx:param name="cascade" value="off" value_type="e_option"/>
     </efx:bitstream_generation>
     <efx:debugger>
-        <efx:param name="work_dir" value="work_dbg" value_type="e_string" />
-        <efx:param name="auto_instantiation" value="off" value_type="e_bool" />
-        <efx:param name="profile" value="debug_profile.wizard.json" value_type="e_string" />
+        <efx:param name="work_dir" value="work_dbg" value_type="e_string"/>
+        <efx:param name="auto_instantiation" value="off" value_type="e_bool"/>
+        <efx:param name="profile" value="debug_profile.wizard.json" value_type="e_string"/>
     </efx:debugger>
-</efx:project>
\ No newline at end of file
+</efx:project>
diff --git a/init_env.sh b/init_env.sh
index 730203969a233a0065b1bb9d9c8a454b73c9eced..8e51a6a241ad4e5a253c2baa39ccffc065e70080 100644
--- a/init_env.sh
+++ b/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
 
+#module load efinity/2023.1
+module load verilator
+module load gtkwave/3.3_gtk3
 
-python3.11 -m venv .user_venv
+python3.12 -m venv .user_venv
 . .user_venv/bin/activate
 
-module load efinity/2023.1
-module load iverilog/12.0
-module load gtkwave/3.3_gtk3
-
-# pip install -r requirements.txt
+pip install -r requirements.txt
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fb552bca19322c8ffc8a88c0365a42c529c1878a
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,7 @@
+-i https://git.byronlathi.com/api/v4/projects/95/packages/pypi/simple
+peakrdl==1.1.0
+rtl-manifest>=0.2.0
+cocotb
+cocotbext-axi
+cocotbext-eth
+scapy
\ No newline at end of file
diff --git a/sw/test_code/loop_test/link.ld b/sw/test_code/loop_test/link.ld
index 44fc44597775ce13668e600c1ba37a082629f379..bc63183626d67b30fc54078ca87f5d0870a51e9b 100644
--- a/sw/test_code/loop_test/link.ld
+++ b/sw/test_code/loop_test/link.ld
@@ -1,7 +1,7 @@
 MEMORY
 {
     RAM: start = $0000, size = $200;
-    ROM: start = $FF00, size = $100, file = %O;
+    ROM: start = $F000, size = $1000, file = %O;
 }
 
 SEGMENTS {
diff --git a/sw/test_code/ntw_test/Makefile b/sw/test_code/ntw_test/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..dfda409cb9b1fdcc04d35fe09915ad516e8594fc
--- /dev/null
+++ b/sw/test_code/ntw_test/Makefile
@@ -0,0 +1,39 @@
+CC=../../toolchain/cc65/bin/cl65
+LD=../../toolchain/cc65/bin/cl65
+CFLAGS=-T -t none -I. --cpu "65C02"
+LDFLAGS=-C link.ld -m $(NAME).map
+
+NAME=ntw_test
+
+BIN=$(NAME).bin
+HEX=$(NAME).hex
+
+LISTS=lists
+
+SRCS=$(wildcard *.s) $(wildcard *.c)
+SRCS+=$(wildcard **/*.s) $(wildcard **/*.c)
+OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
+OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
+
+# Make sure the kernel linked to correct address, no relocation!
+all: $(HEX)
+
+$(HEX): $(BIN)
+	objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX)
+
+$(BIN): $(OBJS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
+
+%.o: %.c $(LISTS)
+	$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
+
+%.o: %.s $(LISTS)
+	$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
+
+$(LISTS):
+	mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
+
+.PHONY: clean
+clean:
+	rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map
+
diff --git a/sw/test_code/ntw_test/link.ld b/sw/test_code/ntw_test/link.ld
new file mode 100644
index 0000000000000000000000000000000000000000..bc63183626d67b30fc54078ca87f5d0870a51e9b
--- /dev/null
+++ b/sw/test_code/ntw_test/link.ld
@@ -0,0 +1,30 @@
+MEMORY
+{
+    RAM: start = $0000, size = $200;
+    ROM: start = $F000, size = $1000, file = %O;
+}
+
+SEGMENTS {
+    ZEROPAGE: load = RAM, type = zp,  define   = yes;
+    DATA:     load = ROM, type = rw,  define   = yes;
+    CODE:     load = ROM, type = ro;
+    RODATA:   load = ROM, type = ro;
+    VECTORS:  load = ROM, type = ro,  start    = $FFFA;
+}
+
+FEATURES {
+    CONDES:    segment = STARTUP,
+               type    = constructor,
+               label   = __CONSTRUCTOR_TABLE__,
+               count   = __CONSTRUCTOR_COUNT__;
+    CONDES:    segment = STARTUP,
+               type    = destructor,
+               label   = __DESTRUCTOR_TABLE__,
+               count   = __DESTRUCTOR_COUNT__;
+}
+
+SYMBOLS {
+    # Define the stack size for the application
+    __STACKSIZE__:  value = $0200, type = weak;
+    __STACKSTART__: type = weak, value = $0800; # 2k stack
+}
diff --git a/sw/test_code/ntw_test/main.s b/sw/test_code/ntw_test/main.s
new file mode 100644
index 0000000000000000000000000000000000000000..086625d259951186cadc29155fd2ccc0ff83d1b7
--- /dev/null
+++ b/sw/test_code/ntw_test/main.s
@@ -0,0 +1,20 @@
+.export _init, _nmi_int, _irq_int
+
+.segment  "VECTORS"
+
+.addr      _nmi_int    ; NMI vector
+.addr      _init       ; Reset vector
+.addr      _irq_int    ; IRQ/BRK vector
+
+SDRAM= $200
+
+.code
+
+_nmi_int:
+_irq_int:
+
+_init:
+        lda #$aa
+        sta $e200
+
+@end:   bra @end
\ No newline at end of file