add ethernet_tx_tb

This commit is contained in:
Fischer Moseley 2023-04-27 23:13:51 -04:00
parent 2c461ed08d
commit 15aa5f469f
8 changed files with 250 additions and 74 deletions

View File

@ -11,6 +11,9 @@ lint:
serve_docs:
mkdocs serve
src_loc:
find src -type f \( -iname \*.sv -o -iname \*.v -o -iname \*.py -o -iname \*.yaml -o -iname \*.md \) | sed 's/.*/"&"/' | xargs wc -l
total_loc:
find . -type f \( -iname \*.sv -o -iname \*.v -o -iname \*.py -o -iname \*.yaml -o -iname \*.yml -o -iname \*.md \) | sed 's/.*/"&"/' | xargs wc -l
@ -31,6 +34,11 @@ auto_gen:
# Functional Simulation
functional_sim: io_core_tb logic_analyzer_tb bit_fifo_tb bridge_rx_tb bridge_tx_tb lut_mem_tb
ethernet_tx_tb:
iverilog -g2012 -o sim.out -y src/manta/ether_iface test/functional_sim/ethernet_tx_tb.sv
vvp sim.out
rm sim.out
ethernet_rx_tb:
iverilog -g2012 -o sim.out -y src/manta/ether_iface test/functional_sim/ethernet_rx_tb.sv
vvp sim.out

View File

@ -5,4 +5,4 @@ cores:
size: 64
ethernet:
interface: "en3"
interface: "en8"

View File

@ -1,17 +1,7 @@
from manta import Manta
from random import randint
m = Manta('manta.yaml')
from manta import Manta
from time import sleep
m = Manta("manta.yaml")
print(m.my_lut_mem.read(0))
m.my_lut_mem.write(0, 5)
print(m.my_lut_mem.read(0))
# for addr in range(m.my_lut_mem.size):
# write_data = randint(0, (2**16)-1)
@ -19,4 +9,41 @@ print(m.my_lut_mem.read(0))
# read_data = m.my_lut_mem.read(addr)
# print(f"test addr: {addr} with data: {write_data}")
# print(f" -> correct data received on readback?: {write_data == read_data}")
# print(f" -> correct data received on readback?: {write_data == read_data}")
# addrs = list(range(m.my_lut_mem.size))
# datas = addrs
# print(m.my_lut_mem.interface.read_batch(addrs))
# internal rage intensifies
# try writing a single register at a time which is known good,
# and then read them back all at once
# m.my_lut_mem.write(39, 42069)
# m.my_lut_mem.write(40, 42070)
# print(m.my_lut_mem.read(39))
# print(m.my_lut_mem.read(40))
# print(m.my_lut_mem.interface.read_batch([39,40]))
# exit()
# ok so i think i kind of understand the issue
# so basically what's happening here is that whatever is in the
# 16's place of the write data at the last write persists in all the reads, meaning
#addrs = list(range(48))
addrs = list(range(m.my_lut_mem.size))
print(addrs)
print('\n')
from time import sleep
for addr in addrs:
m.my_lut_mem.write(addr, addr)
sleep(0.1)
print([m.my_lut_mem.read(addr) for addr in addrs])
print('\n')

View File

@ -26,15 +26,7 @@ module top_level (
assign eth_refclk = clk_50mhz;
divider d (.clk(clk), .ethclk(clk_50mhz));
assign led = manta_inst.brx_my_lut_mem_addr;
assign led16_r = manta_inst.brx_my_lut_mem_rw;
assign led17_r = manta_inst.brx_my_lut_mem_valid;
ssd ssd (
.clk(clk_50mhz),
.val( {manta_inst.my_lut_mem_btx_rdata, manta_inst.brx_my_lut_mem_wdata} ),
.cat({cg,cf,ce,cd,cc,cb,ca}),
.an(an));
manta manta_inst (
.clk(clk_50mhz),
@ -44,6 +36,25 @@ module top_level (
.txen(eth_txen),
.txd(eth_txd));
// debugging!
initial led17_r = 0;
reg [31:0] val = 0;
always @(posedge clk_50mhz) begin
if(manta_inst.my_lut_mem.valid_o) begin
led <= manta_inst.my_lut_mem.addr_o;
led16_r <= manta_inst.my_lut_mem.rw_o;
led17_r <= !led17_r;
val <= {manta_inst.my_lut_mem.rdata_o, manta_inst.my_lut_mem.wdata_o};
end
end
ssd ssd (
.clk(clk_50mhz),
.val(val),
.cat({cg,cf,ce,cd,cc,cb,ca}),
.an(an));
endmodule

View File

@ -1,15 +1,16 @@
from ..hdl_utils import *
# Lazy and selective imports for quick builds!
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
from scapy.all import *
class EthernetInterface:
def __init__(self, config):
# Lazy and selective imports for quick builds!
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
# Warn if unrecognized options have been given
for option in config:
if option not in ["interface", "host_mac", "fpga_mac", "ethertype", "tcpreplay", "verbose"]:
@ -81,7 +82,7 @@ class EthernetInterface:
assert len(results) == 1, "Received more packets than expected!"
raw_response_bytes = bytes(results[0].payload)[0:2]
raw_response_bytes = bytes(results[0].payload)[3:5]
return int.from_bytes(raw_response_bytes, 'big')
def write_register(self, addr, data):
@ -99,61 +100,69 @@ class EthernetInterface:
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
def read_batch(self, addrs):
# Prepare packets to read from addresses
pkts = []
for addr in addrs:
pkt = Ether()
pkt.src = self.host_mac
pkt.dst = self.fpga_mac
pkt.type = self.ethertype
# # two bytes of address, and 44 of padding
# # makes the 46 byte minimum length
# msg = addr.to_bytes(2, 'big') + 44*b'\x00'
# 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
# pkts.append(pkt)
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)
# Start sniffer in another thread, send packets, grab responses
sniffer = AsyncSniffer(iface = self.iface, count = len(addrs), filter=f"ether src {self.fpga_mac}")
sniffer.start()
sleep(0.1)
sendp(pkts, iface=self.iface, verbose = 0, inter = 0.05)
sniffer.join()
results = sniffer.results
# sendp(pkts, iface=iface, verbose = 0)
# sniffer.join()
# results = sniffer.results
assert len(results) == len(addrs), "Received more packets than expected!"
# assert len(results) == len(addrs), "Received more packets than expected!"
# #print(raw(results[1]))
# for packet in results:
# hexdump(packet)
# print( [i for i in bytes(packet.payload)] )
# print( [i for i in raw(packet)] )
# print("\n")
# datas = []
# for packet in results:
# raw_response_bytes = bytes(packet.payload)[0:2]
# data = int.from_bytes(raw_response_bytes, 'big')
# datas.append(data)
# Parse packets
datas = []
for packet in results:
raw_response_bytes = bytes(packet.payload)[3:5]
data = int.from_bytes(raw_response_bytes, 'big')
datas.append(data)
# return datas
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
def write_batch(self, addrs, datas):
assert len(addrs) == len(datas), \
"Number of addresses provided is unequal to number of data provided!"
# addr = addrs[i]
# data = datas[i]
pkts = []
for addr, data in zip(addrs, datas):
pkt = Ether()
pkt.src = self.host_mac
pkt.dst = self.fpga_mac
pkt.type = self.ethertype
# # 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'
# one byte of rw, two bytes of address, two bytes of data, and 41
# bytes of paddding make the 46 byte limit.
msg = b'\x01' + addr.to_bytes(2, 'big') + data.to_bytes(2, 'big') + 41*b'\x00'
# pkt = pkt / msg
# pkt.load = msg
pkt = pkt / msg
pkt.load = msg
pkts.append(pkt)
# sendp(pkts, iface=iface, verbose = 0)
self.send_packet(pkts, iface=self.iface, verbose = 0)
def hdl_top_level_ports(self):
return ["input wire crsdv", \

View File

@ -34,7 +34,7 @@ module ethernet_rx (
assign rw_o = (payload[39:32] == 8'd1);
assign addr_o = payload[31:16];
assign wdata_o = payload[15:0];
assign valid_o = valid && ( payload[39:32] == 8'd0 || payload[39:32] == 8'd1);
assign valid_o = valid && ( payload[39:32] == 8'd0 || payload[39:32] == 8'd1) && (payload[55:40] == 16'h88B5);
endmodule

View File

@ -29,7 +29,7 @@ module ethernet_tx (
) mtx (
.clk(clk),
.payload(rdata_buf),
.payload({24'd0, rdata_buf}),
.start(~rw_i && valid_i),
.txen(txen),

View File

@ -0,0 +1,121 @@
`default_nettype none
//`timescale 1ns/1ps
`define FPGA_MAC 48'h69_69_5A_06_54_91
`define HOST_MAC 48'h00_E0_4C_68_1E_0C
`define ETHERTYPE 16'h88_B5
task send_on_etx_receive_on_mrx (
input [15:0] data
);
ethernet_tx_tb.etx_rdata = data;
ethernet_tx_tb.etx_rw = 0;
ethernet_tx_tb.etx_valid = 0;
#10;
ethernet_tx_tb.etx_valid = 1;
#10;
ethernet_tx_tb.etx_valid = 0;
while(!ethernet_tx_tb.mrx_valid) #10;
$display(ethernet_tx_tb.mrx_payload);
endtask
module ethernet_tx_tb();
// https://www.youtube.com/watch?v=K35qOTQLNpA
logic clk;
always begin
#5;
clk = !clk;
end
logic txen;
logic [1:0] txd;
// ethernet tx
reg [15:0] etx_rdata;
reg etx_rw;
reg etx_valid;
ethernet_tx #(
.FPGA_MAC(`FPGA_MAC),
.HOST_MAC(`HOST_MAC),
.ETHERTYPE(`ETHERTYPE)
) etx (
.clk(clk),
.rdata_i(etx_rdata),
.rw_i(etx_rw),
.valid_i(etx_valid),
.txen(txen),
.txd(txd));
// mac_rx, for decoding
logic crsdv;
logic [1:0] rxd;
reg [55:0] mrx_payload;
reg mrx_valid;
mac_rx #(
// this is the host mac since we're using mac_rx to impersonate
// the host computer, to which packets are currently addressed.
.FPGA_MAC(`HOST_MAC),
.ETHERTYPE(`ETHERTYPE)
) mrx (
.clk(clk),
.crsdv(crsdv),
.rxd(rxd),
.payload(mrx_payload),
.valid(mrx_valid));
logic [15:0] where_ethertype_should_be;
logic [7:0] where_rw_should_be;
logic [15:0] where_addr_should_be;
logic [15:0] where_data_should_be;
assign {where_ethertype_should_be, where_rw_should_be, where_addr_should_be, where_data_should_be} = mrx_payload;
assign rxd = txd;
assign crsdv = txen;
initial begin
$dumpfile("ethernet_tx_tb.vcd");
$dumpvars(0, ethernet_tx_tb);
clk = 0;
etx_rdata = 16'h6970;
etx_rw = 0;
etx_valid = 0;
#50;
send_on_etx_receive_on_mrx(16'h6970);
#10000;
// for (int i=0; i<32; i=i+1) begin
// mtx_payload = i;
// mtx_start = 0;
// #10;
// mtx_start = 1;
// #10;
// mtx_start = 0;
// while(!mrx_valid) #10;
// #1000;
// assert(mrx_payload == i) else $error("data mismatch!");
// end
$finish();
end
endmodule
`default_nettype wire