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