From 54b97fd120a344bb8491b2bc45ad934ab1c2e552 Mon Sep 17 00:00:00 2001 From: Fischer Moseley <42497969+fischermoseley@users.noreply.github.com> Date: Wed, 26 Apr 2023 22:30:02 -0400 Subject: [PATCH] add working ethernet verilog autogeneration woot woot :) --- examples/nexys_a7/lut_ram_ether/manta.yaml | 6 +- .../nexys_a7/lut_ram_ether/read_write_test.py | 22 +- .../nexys_a7/lut_ram_ether/send_packet.py | 124 ----------- examples/nexys_a7/lut_ram_ether/top_level.sv | 12 +- examples/nexys_a7/lut_ram_ether/top_level.xdc | 44 ++-- src/manta/__init__.py | 4 + src/manta/ethernet.py | 203 ++++++++++++++++++ src/manta/ethernet/ethernet_rx.v | 11 +- src/manta/ethernet/ethernet_rx_inst_tmpl.v | 13 ++ src/manta/ethernet/ethernet_tx.v | 2 +- src/manta/ethernet/ethernet_tx_inst_tmpl.v | 13 ++ src/manta/manta_def_tmpl.v | 2 +- src/manta/uart/uart_rx_bridge_rx_inst_templ.v | 4 +- 13 files changed, 284 insertions(+), 176 deletions(-) delete mode 100644 examples/nexys_a7/lut_ram_ether/send_packet.py create mode 100644 src/manta/ethernet/ethernet_rx_inst_tmpl.v create mode 100644 src/manta/ethernet/ethernet_tx_inst_tmpl.v diff --git a/examples/nexys_a7/lut_ram_ether/manta.yaml b/examples/nexys_a7/lut_ram_ether/manta.yaml index 45bdb31..ef8963e 100644 --- a/examples/nexys_a7/lut_ram_ether/manta.yaml +++ b/examples/nexys_a7/lut_ram_ether/manta.yaml @@ -4,7 +4,5 @@ cores: type: lut_ram size: 64 -uart: - port: "auto" - baudrate: 115200 - clock_freq: 100000000 \ No newline at end of file +ethernet: + interface: "en8" \ No newline at end of file diff --git a/examples/nexys_a7/lut_ram_ether/read_write_test.py b/examples/nexys_a7/lut_ram_ether/read_write_test.py index 2615797..a8dc7d2 100644 --- a/examples/nexys_a7/lut_ram_ether/read_write_test.py +++ b/examples/nexys_a7/lut_ram_ether/read_write_test.py @@ -3,10 +3,20 @@ from random import randint m = Manta('manta.yaml') -for addr in range(m.my_lut_ram.size): - write_data = randint(0, (2**16)-1) - m.my_lut_ram.write(addr, write_data) +from manta import Manta +from time import sleep - read_data = m.my_lut_ram.read(addr) - print(f"test addr: {addr} with data: {write_data}") - print(f" -> correct data received on readback?: {write_data == read_data}") \ No newline at end of file +m = Manta("manta.yaml") +print(m.my_lut_ram.read(0)) + +m.my_lut_ram.write(0, 5) + +print(m.my_lut_ram.read(0)) + +# for addr in range(m.my_lut_ram.size): +# write_data = randint(0, (2**16)-1) +# m.my_lut_ram.write(addr, write_data) + +# read_data = m.my_lut_ram.read(addr) +# print(f"test addr: {addr} with data: {write_data}") +# print(f" -> correct data received on readback?: {write_data == read_data}") \ No newline at end of file diff --git a/examples/nexys_a7/lut_ram_ether/send_packet.py b/examples/nexys_a7/lut_ram_ether/send_packet.py deleted file mode 100644 index 39bb472..0000000 --- a/examples/nexys_a7/lut_ram_ether/send_packet.py +++ /dev/null @@ -1,124 +0,0 @@ -from scapy.all import * - -src_mac = "00:E0:4C:68:1E:0C" # for manta.mit.edu's ethernet adapter -dst_mac = "69:69:5A:06:54:91" -ifc = "enx00e04c681e0c" - -def read_register(addr): - pkt = Ether() - pkt.src = src_mac - pkt.dst = dst_mac - pkt.type = 0x0002 - - # two bytes of address, and 44 of padding - # makes the 46 byte minimum length - msg = addr.to_bytes(2, 'big') + 44*b'\x00' - - pkt = pkt / msg - pkt.load = msg - - sniffer = AsyncSniffer(iface = ifc, filter="ether src 69:69:5a:06:54:91") - sniffer.start() - from time import sleep - time.sleep(0.1) - sendp(pkt, iface=ifc, verbose = 0) - results = sniffer.stop() - - assert len(results) == 1, "Received more packets than expected!" - - for packet in results: - raw_response_bytes = bytes(packet.payload)[0:2] - data = int.from_bytes(raw_response_bytes, 'big') - return data - -def write_register(addr, data): - pkt = Ether() - pkt.src = src_mac - pkt.dst = dst_mac - pkt.type = 0x0004 - - # two bytes of address, two bytes of - # data, and 42 of padding makes the 46 byte - # minimum length - msg = addr.to_bytes(2, 'big') + data.to_bytes(2, 'big') + 42*b'\x00' - - pkt = pkt / msg - pkt.load = msg - sendp(pkt, iface=ifc, verbose = 0) - -def read_batch(addrs): - pkts = [] - for addr in addrs: - pkt = Ether() - pkt.src = src_mac - pkt.dst = dst_mac - pkt.type = 0x0002 - - # two bytes of address, and 44 of padding - # makes the 46 byte minimum length - msg = addr.to_bytes(2, 'big') + 44*b'\x00' - - pkt = pkt / msg - pkt.load = msg - pkts.append(pkt) - - sniffer = AsyncSniffer(iface = ifc, count = len(addrs), filter="ether src 69:69:5a:06:54:91") - sniffer.start() - from time import sleep - time.sleep(0.1) - - sendp(pkts, iface=ifc, verbose = 0) - sniffer.join() - results = sniffer.results - - assert len(results) == len(addrs), "Received more packets than expected!" - - datas = [] - for packet in results: - raw_response_bytes = bytes(packet.payload)[0:2] - data = int.from_bytes(raw_response_bytes, 'big') - datas.append(data) - - return datas - -def write_batch(addrs, data): - pkts = [] - for i in range(len(addrs)): - pkt = Ether() - pkt.src = src_mac - pkt.dst = dst_mac - pkt.type = 0x0002 - - addr = addrs[i] - data = datas[i] - - # two bytes of address, two bytes of - # data, and 42 of padding makes the 46 byte - # minimum length - msg = addr.to_bytes(2, 'big') + data.to_bytes(2, 'big') + 42*b'\x00' - - pkt = pkt / msg - pkt.load = msg - - sendp(pkts, iface=ifc, verbose = 0) - - -from time import sleep -if __name__ == "__main__": - for addr in range(64): - data = addr - write_register(addr, data) - retval = read_register(addr) - if retval != addr: - print(f"ERROR: sent {data} got {retval}") - - else: - print(f"SUCCESS: sent {data} got {retval}") - - # addrs = [i for i in range(64)] - # datas = addrs - # write_batch(addrs, datas) - # print("done") - # retvals = read_batch(addrs) - # print(retvals) - diff --git a/examples/nexys_a7/lut_ram_ether/top_level.sv b/examples/nexys_a7/lut_ram_ether/top_level.sv index e4394d4..0cdb9d3 100644 --- a/examples/nexys_a7/lut_ram_ether/top_level.sv +++ b/examples/nexys_a7/lut_ram_ether/top_level.sv @@ -3,10 +3,6 @@ module top_level ( input wire clk, - input wire btnc, - input wire btnd, - - input wire [15:0] sw, output logic [15:0] led, output logic ca, cb, cc, cd, ce, cf, cg, @@ -22,13 +18,9 @@ module top_level ( input wire [1:0] eth_rxd, output reg eth_txen, - output reg [1:0] eth_txd, + output reg [1:0] eth_txd); - input wire uart_txd_in, - output logic uart_rxd_out - ); - - assign eth_rstn = ~btnc; + assign eth_rstn = 1; logic clk_50mhz; assign eth_refclk = clk_50mhz; diff --git a/examples/nexys_a7/lut_ram_ether/top_level.xdc b/examples/nexys_a7/lut_ram_ether/top_level.xdc index 350e0f6..ee0e978 100644 --- a/examples/nexys_a7/lut_ram_ether/top_level.xdc +++ b/examples/nexys_a7/lut_ram_ether/top_level.xdc @@ -17,22 +17,22 @@ create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {cl ##Switches -set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0] -set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1] -set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2] -set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3] -set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { sw[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4] -set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { sw[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5] -set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { sw[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6] -set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { sw[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7] -set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { sw[8] }]; #IO_L24N_T3_34 Sch=sw[8] -set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { sw[9] }]; #IO_25_34 Sch=sw[9] -set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { sw[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10] -set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { sw[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11] -set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { sw[12] }]; #IO_L24P_T3_35 Sch=sw[12] -set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { sw[13] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13] -set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { sw[14] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14] -set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { sw[15] }]; #IO_L21P_T3_DQS_14 Sch=sw[15] +# set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0] +# set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1] +# set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2] +# set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3] +# set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { sw[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4] +# set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { sw[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5] +# set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { sw[6] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6] +# set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { sw[7] }]; #IO_L5N_T0_D07_14 Sch=sw[7] +# set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { sw[8] }]; #IO_L24N_T3_34 Sch=sw[8] +# set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { sw[9] }]; #IO_25_34 Sch=sw[9] +# set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { sw[10] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10] +# set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { sw[11] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11] +# set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { sw[12] }]; #IO_L24P_T3_35 Sch=sw[12] +# set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { sw[13] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13] +# set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { sw[14] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14] +# set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { sw[15] }]; #IO_L21P_T3_DQS_14 Sch=sw[15] ## LEDs @@ -88,11 +88,11 @@ set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { an[7] # set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { cpu_resetn }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn -set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { btnc }]; #IO_L9P_T1_DQS_14 Sch=btnc +# set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { btnc }]; #IO_L9P_T1_DQS_14 Sch=btnc # set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { btnu }]; #IO_L4N_T0_D05_14 Sch=btnu # set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { btnl }]; #IO_L12P_T1_MRCC_14 Sch=btnl # set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { btnr }]; #IO_L10N_T1_D15_14 Sch=btnr -set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { btnd }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd +# set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { btnd }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd ##Pmod Headers @@ -222,10 +222,10 @@ set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { btnd } ##USB-RS232 Interface -set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in -set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out -#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { uart_cts }]; #IO_L12N_T1_MRCC_35 Sch=uart_cts -#set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { uart_rts }]; #IO_L5N_T0_AD13N_35 Sch=uart_rts +# set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in +# set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out +# set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { uart_cts }]; #IO_L12N_T1_MRCC_35 Sch=uart_cts +# set_property -dict { PACKAGE_PIN E5 IOSTANDARD LVCMOS33 } [get_ports { uart_rts }]; #IO_L5N_T0_AD13N_35 Sch=uart_rts ##USB HID (PS/2) diff --git a/src/manta/__init__.py b/src/manta/__init__.py index 6e9e8a5..c93c5ad 100644 --- a/src/manta/__init__.py +++ b/src/manta/__init__.py @@ -20,6 +20,10 @@ class Manta: # set interface if "uart" in config: self.interface = UARTInterface(config["uart"]) + + elif "ethernet" in config: + self.interface = EthernetInterface(config["ethernet"]) + else: raise ValueError("Unrecognized interface specified.") diff --git a/src/manta/ethernet.py b/src/manta/ethernet.py index e69de29..7f18ad5 100644 --- a/src/manta/ethernet.py +++ b/src/manta/ethernet.py @@ -0,0 +1,203 @@ +from .verilog_manipulator import * + +from scapy.interfaces import get_if_list +from scapy.arch import get_if_hwaddr +from scapy.layers.l2 import Ether +from scapy.sendrecv import AsyncSniffer, sendp, sendpfast +from time import sleep + +class EthernetInterface: + def __init__(self, config): + # Warn if unrecognized options have been given + for option in config: + if option not in ["interface", "host mac", "fpga mac", "ethertype", "tcpreplay", "verbose"]: + print(f"Warning: Ignoring unrecognized option '{option}' in Ethernet interface.") + + # Obtain interface. + assert "interface" in config, "No interface provided for Ethernet core." + if config["interface"] not in get_if_list(): + print(f"Warning: Interface specified is not detected by the host.") + self.iface = config["interface"] + + # Obtain Host MAC address + if self.iface in get_if_list(): + self.host_mac = get_if_hwaddr(self.iface) + else: + assert "host mac" in config, \ + "Can't automatically detect host mac address from interface, host mac must be manually provided" + self.host_mac = config["host mac"] + + # Obtain FPGA MAC address + # - the default address is a locally administered unicast address, + # which is an important distinction. please refer to: + # https://en.wikipedia.org/wiki/MAC_address#Ranges_of_group_and_locally_administered_addresses + self.fpga_mac = "12:34:56:78:9A:BC" + if "fpga mac" in config: + self.fpga_mac = config["fpga mac"] + + # Obtain Ethertype + # - the default ethertype being used is reserved for local + # experimentation by the IEEE - and might not make it beyond + # your NIC as a result. + self.ethertype = 0x88B5 + if "ethertype" in config: + self.ethertype = int(config["ethertype"], 16) + + # Set whether we use tcpreplay for faster packet blasting + self.send_packet = sendp + if "tcpreplay" in config: + assert isinstance(config["tcpreplay"], bool), \ + "tcpreplay configuration option must be boolean!" + self.send_packet = sendpfast if config["tcpreplay"] else sendp + + self.verbose = False + if "verbose" in config: + assert isinstance(config["verbose"], bool), \ + "verbose configuration option must be boolean!" + self.verbose = config["verbose"] + + def read_register(self, addr): + pkt = Ether() + pkt.src = self.host_mac + pkt.dst = self.fpga_mac + pkt.type = self.ethertype + + # one byte of rw, two bytes of address, and 44 of padding + # makes the 46 byte minimum length + msg = b'\x00' + addr.to_bytes(2, 'big') + 43*b'\x00' + + pkt = pkt / msg + pkt.load = msg + + sniffer = AsyncSniffer(iface = self.iface, filter=f"ether src {self.fpga_mac}") + sniffer.start() + sleep(0.1) + + self.send_packet(pkt, iface=self.iface, verbose = 0) + + results = sniffer.stop() + + assert len(results) == 1, "Received more packets than expected!" + + raw_response_bytes = bytes(results[0].payload)[0:2] + return int.from_bytes(raw_response_bytes, 'big') + + def write_register(self, addr, data): + pkt = Ether() + pkt.src = self.host_mac + pkt.dst = self.fpga_mac + pkt.type = self.ethertype + + # one byte of rw, two bytes of address, two bytes of + # data, and 42 of padding makes the 46 byte + # minimum length + msg = b'\x01' + addr.to_bytes(2, 'big') + data.to_bytes(2, 'big') + 41*b'\x00' + + pkt = pkt / msg + pkt.load = msg + self.send_packet(pkt, iface=self.iface, verbose = self.verbose) + + # def read_batch(addrs): + # pkts = [] + # for addr in addrs: + # pkt = Ether() + # pkt.src = src_mac + # pkt.dst = dst_mac + # pkt.type = 0x0002 + + # # two bytes of address, and 44 of padding + # # makes the 46 byte minimum length + # msg = addr.to_bytes(2, 'big') + 44*b'\x00' + + # pkt = pkt / msg + # pkt.load = msg + # pkts.append(pkt) + + # sniffer = AsyncSniffer(iface = iface, count = len(addrs), filter="ether src 69:69:5a:06:54:91") + # sniffer.start() + # from time import sleep + # time.sleep(0.1) + + # sendp(pkts, iface=iface, verbose = 0) + # sniffer.join() + # results = sniffer.results + + # assert len(results) == len(addrs), "Received more packets than expected!" + + # datas = [] + # for packet in results: + # raw_response_bytes = bytes(packet.payload)[0:2] + # data = int.from_bytes(raw_response_bytes, 'big') + # datas.append(data) + + # return datas + + # def write_batch(addrs, data): + # pkts = [] + # for i in range(len(addrs)): + # pkt = Ether() + # pkt.src = src_mac + # pkt.dst = dst_mac + # pkt.type = 0x0002 + + # addr = addrs[i] + # data = datas[i] + + # # two bytes of address, two bytes of + # # data, and 42 of padding makes the 46 byte + # # minimum length + # msg = addr.to_bytes(2, 'big') + data.to_bytes(2, 'big') + 42*b'\x00' + + # pkt = pkt / msg + # pkt.load = msg + + # sendp(pkts, iface=iface, verbose = 0) + + def hdl_top_level_ports(self): + return ["input wire crsdv", \ + "input wire [1:0] rxd", \ + "output reg txen", \ + "output reg [1:0] txd"] + + def rx_hdl_def(self): + tx = VerilogManipulator("ethernet/ethernet_rx.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/mac_rx.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/ether.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/bitorder.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/firewall.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/aggregate.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/crc32.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/cksum.v").get_hdl() + "\n" + return tx + + def tx_hdl_def(self): + tx = VerilogManipulator("ethernet/ethernet_tx.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/mac_tx.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/bitorder.v").get_hdl() + "\n" + tx += VerilogManipulator("ethernet/crc32.v").get_hdl() + "\n" + return tx + + def rx_hdl_inst(self): + rx = VerilogManipulator("ethernet/ethernet_rx_inst_tmpl.v") + + fpga_mac_verilog_literal = "48'h" + self.fpga_mac.replace(":", "_").upper() + rx.sub(fpga_mac_verilog_literal, "/* FPGA_MAC */") + + ethertype_verilog_literal = f"16'h{self.ethertype:02X}" + rx.sub(ethertype_verilog_literal, "/* ETHERTYPE */") + + return rx.get_hdl() + + def tx_hdl_inst(self): + tx = VerilogManipulator("ethernet/ethernet_tx_inst_tmpl.v") + + fpga_mac_verilog_literal = "48'h" + self.fpga_mac.replace(":", "_").upper() + tx.sub(fpga_mac_verilog_literal, "/* FPGA_MAC */") + + host_mac_verilog_literal = "48'h" + self.host_mac.replace(":", "_").upper() + tx.sub(host_mac_verilog_literal, "/* HOST_MAC */") + + ethertype_verilog_literal = f"16'h{self.ethertype:02X}" + tx.sub(ethertype_verilog_literal, "/* ETHERTYPE */") + + return tx.get_hdl() \ No newline at end of file diff --git a/src/manta/ethernet/ethernet_rx.v b/src/manta/ethernet/ethernet_rx.v index 7cd1f71..94995fb 100644 --- a/src/manta/ethernet/ethernet_rx.v +++ b/src/manta/ethernet/ethernet_rx.v @@ -16,12 +16,12 @@ module ethernet_rx ( parameter FPGA_MAC = 0; parameter ETHERTYPE = 0; - reg [31:0] data; + reg [39:0] payload; reg valid; mac_rx #( - .DST_MAC(48'h69_69_5A_06_54_91), - .ETHERTYPE(16'h88_B5) + .FPGA_MAC(FPGA_MAC), + .ETHERTYPE(ETHERTYPE) ) mrx ( .clk(clk), @@ -29,13 +29,12 @@ module ethernet_rx ( .rxd(rxd), .payload(payload), - .length(length) .valid(valid)); + assign rw_o = (payload[39:32] == 8'd1); assign addr_o = payload[31:16]; assign wdata_o = payload[15:0]; - assign rw_o = (length == 4); - assign valid_o = valid && ((length == 4) || (length == 2)); + assign valid_o = valid && ( payload[39:32] == 8'd0 || payload[39:32] == 8'd1); endmodule diff --git a/src/manta/ethernet/ethernet_rx_inst_tmpl.v b/src/manta/ethernet/ethernet_rx_inst_tmpl.v new file mode 100644 index 0000000..937ce52 --- /dev/null +++ b/src/manta/ethernet/ethernet_rx_inst_tmpl.v @@ -0,0 +1,13 @@ +ethernet_rx #( + .FPGA_MAC(/* FPGA_MAC */), + .ETHERTYPE(/* ETHERTYPE */) +) erx ( + .clk(clk), + + .crsdv(crsdv), + .rxd(rxd), + + .addr_o(), + .wdata_o(), + .rw_o(), + .valid_o()); \ No newline at end of file diff --git a/src/manta/ethernet/ethernet_tx.v b/src/manta/ethernet/ethernet_tx.v index e0e0982..08e82c7 100644 --- a/src/manta/ethernet/ethernet_tx.v +++ b/src/manta/ethernet/ethernet_tx.v @@ -25,7 +25,7 @@ module ethernet_tx ( .SRC_MAC(FPGA_MAC), .DST_MAC(HOST_MAC), .ETHERTYPE(ETHERTYPE), - .PAYLOAD_LENGTH_BYTES(2) + .PAYLOAD_LENGTH_BYTES(5) ) mtx ( .clk(clk), diff --git a/src/manta/ethernet/ethernet_tx_inst_tmpl.v b/src/manta/ethernet/ethernet_tx_inst_tmpl.v new file mode 100644 index 0000000..d618593 --- /dev/null +++ b/src/manta/ethernet/ethernet_tx_inst_tmpl.v @@ -0,0 +1,13 @@ +ethernet_tx #( + .FPGA_MAC(/* FPGA_MAC */), + .HOST_MAC(/* HOST_MAC */), + .ETHERTYPE(/* ETHERTYPE */) +) etx ( + .clk(clk), + + .rdata_i(), + .rw_i(), + .valid_i(), + + .txen(txen), + .txd(txd)); \ No newline at end of file diff --git a/src/manta/manta_def_tmpl.v b/src/manta/manta_def_tmpl.v index 8d3ec90..0081ef4 100644 --- a/src/manta/manta_def_tmpl.v +++ b/src/manta/manta_def_tmpl.v @@ -15,7 +15,7 @@ manta manta_inst ( */ -module manta( +module manta ( input wire clk, /* TOP_LEVEL_PORTS */); diff --git a/src/manta/uart/uart_rx_bridge_rx_inst_templ.v b/src/manta/uart/uart_rx_bridge_rx_inst_templ.v index 52d3f04..fcc2f85 100644 --- a/src/manta/uart/uart_rx_bridge_rx_inst_templ.v +++ b/src/manta/uart/uart_rx_bridge_rx_inst_templ.v @@ -4,8 +4,8 @@ rx_uart #(.CLOCKS_PER_BAUD(/* CLOCKS_PER_BAUD */)) urx ( .o_wr(urx_brx_axiv), .o_data(urx_brx_axid)); -logic [7:0] urx_brx_axid; -logic urx_brx_axiv; +reg [7:0] urx_brx_axid; +reg urx_brx_axiv; bridge_rx brx ( .clk(clk),