clean up mac_tx, working in simulation

This commit is contained in:
Fischer Moseley 2023-04-24 19:12:28 -04:00
parent 64a582c786
commit 0bb3f9c74a
10 changed files with 221 additions and 17885 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,257 +0,0 @@
`define CP 20
`define HCP (`CP / 2)
/* checking helper for testing tasks */
`define CHECK(COND, TESTOK, MSG) do begin \
if (!(COND) && TESTOK) begin \
$display("FAIL: %s", MSG); \
TESTOK = 0; \
end \
end while (0)
`default_nettype none
`timescale 1ns / 1ps
`define PREAM_BAD 2'b10
`define PREAM_FIRST 2'b00
`define CRSDV_HOLD 10
`define MAC_BITS 48
`define ETYPE_BITS 16
`define MAX_MSG_BITS 128
`define AGGREGATE_SIZE 32
`define TIMEOUT 200
`define PREAMBLE 64'h5555_5555_5555_5557 /* pre-flipped for us */
`define MAC_BCAST 48'hFF_FF_FF_FF_FF_FF
`define MAC_SRC 48'h69_69_69_69_69_69 /* don't care if flipped */
`define ETYPE 16'h6969 /* don't care if flipped */
`define MSG(BITS, SIZE) (BITS << (`MAX_MSG_BITS - SIZE))
`define TTINY `MSG(2'b10, 2)
`define T32 `MSG(32'h4353_f92c, 32)
`define T64 `MSG(64'h1234_5678_0000_0000, 64)
`define T128 `MSG({(64){2'b10}}, 128)
`define T64_EXPECT 32'h84_1C_95_2D
`define T128_EXPECT 32'hAA_AA_AA_AA
module integrationsim;
logic clk, rst;
logic[1:0] rxd;
logic crsdv;
/* ether -> bitorder */
logic[1:0] ether_axiod;
logic ether_axiov;
/* bitorder -> firewall */
logic[1:0] bitorder_axiod;
logic bitorder_axiov;
/* firewall -> aggregate */
logic[1:0] firewall_axiod;
logic firewall_axiov;
/* aggregate output */
logic[31:0] axiod;
logic axiov;
/* constants */
logic[0:63] preamble;
logic[0:`MAC_BITS-1] dst, src;
logic[0:`ETYPE_BITS-1] etype;
assign preamble = `PREAMBLE;
assign dst = `MAC_BCAST;
assign src = `MAC_SRC;
assign etype = `ETYPE;
ether e(.clk(clk),
.rst(rst),
.rxd(rxd),
.crsdv(crsdv),
.axiov(ether_axiov),
.axiod(ether_axiod));
bitorder b(.clk(clk),
.rst(rst),
.axiiv(ether_axiov),
.axiid(ether_axiod),
.axiov(bitorder_axiov),
.axiod(bitorder_axiod));
firewall f(.clk(clk),
.rst(rst),
.axiiv(bitorder_axiov),
.axiid(bitorder_axiod),
.axiov(firewall_axiov),
.axiod(firewall_axiod));
aggregate a(.clk(clk),
.rst(rst),
.axiiv(firewall_axiov),
.axiid(firewall_axiod),
.axiov(axiov),
.axiod(axiod));
integer ok;
task test;
input[0:`MAX_MSG_BITS-1] msg;
input[63:0] msgsize;
input[31:0] exp;
input showexp;
input dorst;
begin
integer i, rcv;
rxd = 2'b00;
crsdv = 1'b0;
rcv = 0;
ok = 1;
if (dorst) begin
rst = 1'b1;
#`CP;
end
rst = 1'b0;
#`CP;
`CHECK(axiov === 0, ok, "axiov != 0 @ start");
for (i = 0; i < `CRSDV_HOLD; i = i + 1) begin
crsdv = 1'b1;
rxd = `PREAM_FIRST;
#`CP;
`CHECK(axiov === 0, ok, "crs: axiov != 0");
end
for (i = 0; i < 64; i = i + 2) begin
crsdv = 1'b1;
rxd = {preamble[i], preamble[i+1]};
#`CP;
`CHECK(axiov === 0, ok, "preamble: bad axiov");
end
for (i = 0; i < `MAC_BITS; i = i + 2) begin
crsdv = 1'b1;
rxd = {dst[i], dst[i+1]};
`CHECK(axiov === 0, ok, "axiov>0 in dst");
#`CP;
end
for (i = 0; i < `MAC_BITS; i = i + 2) begin
crsdv = 1'b1;
rxd = {src[i], src[i+1]};
`CHECK(axiov === 0, ok, "axiov>0 in src");
#`CP;
end
for (i = 0; i < `ETYPE_BITS; i = i + 2) begin
crsdv = 1'b1;
rxd = {etype[i], etype[i+1]};
`CHECK(axiov === 0, ok, "axiov>0 before data");
#`CP;
end
for (i = 0; i < msgsize; i = i + 2) begin
crsdv = 1'b1;
rxd = {msg[i], msg[i+1]};
if (axiov) begin
`CHECK(showexp, ok, "unexpected out");
`CHECK(rcv == 0,
ok,
"aggregate valid for >1 cycle");
`CHECK(axiod === exp,
ok,
"axiod != expected output");
rcv = 1;
end
#`CP;
end
rxd = 2'b00;
crsdv = 1'b0;
while (i < `TIMEOUT) begin
if (axiov) begin
`CHECK(showexp, ok, "unexpected out");
`CHECK(rcv == 0,
ok,
"aggregate valid for >1 cycle");
`CHECK(axiod === exp,
ok,
"axiod != expected output");
rcv = 1;
end
#`CP;
i = i + 2;
end
if (showexp) `CHECK(rcv, ok, "timeout");
end
endtask
initial begin: CLK
clk = 1;
forever #`HCP clk = ~clk;
end
initial begin: MAIN
`ifdef MKWAVEFORM
$dumpfile("obj/integration.vcd");
$dumpvars(0, integrationsim);
`endif /* MKWAVEFORM */
rxd = 2'b00;
crsdv = 1'b0;
rst = 1'b0;
#`CP;
$display("=== test 1: tiny 1-bit message ===");
test(`TTINY, 1, 0, 0, 1);
if (ok) $display("OK");
else $finish();
$display("=== test 2: 32-bit message (no FCS) ===");
test(`T32, 32, 0, 0, 0);
if (ok) $display("OK");
else $finish();
$display("=== test 3: 32-bit message (with FCS) ===");
test(`T64, 64, `T64_EXPECT, 1, 0);
if (ok) $display("OK");
else $finish();
$display("=== test 4: 96-bit message (with FCS) ===");
test(`T128, 128, `T128_EXPECT, 1, 0);
if (ok) $display("OK");
else $finish();
$display("=== test 5: one more 32 bit message (+ FCS) ===");
test(`T64, 64, `T64_EXPECT, 1, 0);
if (ok) $display("OK");
else $finish();
$display("=== all tests passed ===");
$finish();
end
endmodule

View File

@ -14,9 +14,6 @@ module mac_tx_tb();
logic eth_crsdv;
logic[1:0] eth_rxd;
logic eth_refclk;
logic eth_rstn;
/* ether -> { cksum, bitorder } */
logic[1:0] ether_axiod;
logic ether_axiov;
@ -38,35 +35,25 @@ module mac_tx_tb();
/* and here's the pipeline... */
logic enable;
logic eth_crsdv_ref;
logic [1:0] eth_rxd_ref;
ether_la_playback #(.MEM_FILE("capture.mem")) ether_la_playback_inst (
.clk(ethclk),
.enable(enable),
.done(),
logic eth_crsdv_mtx;
logic [1:0] eth_rxd_mtx;
.eth_crsdv(eth_crsdv_ref),
.eth_rxd(eth_rxd_ref),
.eth_txen(),
.eth_txd());
logic start;
logic mtx_start;
mac_tx mtx (
.clk(ethclk),
.data(16'h5678),
.data(16'h5679),
.start(start),
.start(mtx_start),
.txen(eth_crsdv),
.txd(eth_rxd));
.txen(eth_crsdv_mtx),
.txd(eth_rxd_mtx));
ether e(
.clk(ethclk),
.rst(rst),
.rxd(eth_rxd),
.crsdv(eth_crsdv_ref),
.rxd(eth_rxd_mtx),
.crsdv(eth_crsdv_mtx),
.axiov(ether_axiov),
.axiod(ether_axiod));
@ -107,19 +94,15 @@ module mac_tx_tb();
$dumpfile("mac_tx_tb.vcd");
$dumpvars(0, mac_tx_tb);
rst = 0;
start = 0;
mtx_start = 0;
#10;
rst = 1;
#10;
rst = 0;
#10;
enable = 1;
#500;
start = 1;
#10;
start = 0;
mtx_start = 1;
#5000;
#10000;
$finish();
end

View File

@ -1,133 +0,0 @@
`default_nettype none
`timescale 1ns/1ps
module packet_blaster_9k_tb();
logic ethclk;
logic rst;
always begin
#5;
ethclk = !ethclk;
end
/* batteries... */
logic eth_crsdv;
logic[1:0] eth_rxd;
logic eth_refclk;
logic eth_rstn;
/* ether -> { cksum, bitorder } */
logic[1:0] ether_axiod;
logic ether_axiov;
/* cksum -> top_level */
logic cksum_done, cksum_kill;
/* bitorder -> firewall */
logic[1:0] bitorder_axiod;
logic bitorder_axiov;
/* firewall -> aggregate */
logic[1:0] firewall_axiod;
logic firewall_axiov;
/* aggregate output */
logic[31:0] aggregate_axiod;
logic aggregate_axiov;
/* and here's the pipeline... */
logic enable;
logic eth_crsdv_ref;
logic [1:0] eth_rxd_ref;
ether_la_playback #(.MEM_FILE("capture.mem")) ether_la_playback_inst (
.clk(ethclk),
.enable(enable),
.done(),
.eth_crsdv(eth_crsdv_ref),
.eth_rxd(eth_rxd_ref),
.eth_txen(),
.eth_txd());
logic start;
packet_blaster_9k pb9k (
.clk(ethclk),
.rst(rst),
//.src_mac(48'h69_2C_08_30_75_FD),
.src_mac(48'h00_00_00_00_00_00),
.dst_mac(48'hFF_FF_FF_FF_FF_FF),
.data(16'h5678),
.start(start),
.txen(eth_crsdv),
.txd(eth_rxd));
ether e(
.clk(ethclk),
.rst(rst),
.rxd(eth_rxd),
.crsdv(eth_crsdv),
.axiov(ether_axiov),
.axiod(ether_axiod));
bitorder b(
.clk(ethclk),
.rst(rst),
.axiiv(ether_axiov),
.axiid(ether_axiod),
.axiov(bitorder_axiov),
.axiod(bitorder_axiod));
firewall f(
.clk(ethclk),
.rst(rst),
.axiiv(bitorder_axiov),
.axiid(bitorder_axiod),
.axiov(firewall_axiov),
.axiod(firewall_axiod));
aggregate a(
.clk(ethclk),
.rst(rst),
.axiiv(firewall_axiov),
.axiid(firewall_axiod),
.axiov(aggregate_axiov),
.axiod(aggregate_axiod));
cksum c(
.clk(ethclk),
.rst(rst),
.axiiv(ether_axiov),
.axiid(ether_axiod),
.done(cksum_done),
.kill(cksum_kill));
initial begin
ethclk = 0;
$dumpfile("packet_blaster_9k_tb.vcd");
$dumpvars(0, packet_blaster_9k_tb);
rst = 0;
start = 0;
#10;
rst = 1;
#10;
rst = 0;
#10;
enable = 1;
#430;
start = 1;
#10;
start = 0;
#5000;
$finish();
end
endmodule
`default_nettype wire

View File

@ -1,56 +0,0 @@
/*
This playback module was generated with Manta v0.0.0 on 19 Apr 2023 at 12:01:24 by fischerm
If this breaks or if you've got dank formal verification memes, contact fischerm [at] mit.edu
Provided under a GNU GPLv3 license. Go wild.
Here's an example instantiation of the Manta module you configured, feel free to copy-paste
this into your source!
ether_la_playback #(.MEM_FILE("capture.mem")) ether_la_playback_inst (
.clk(clk),
.enable(1'b1),
.eth_crsdv(eth_crsdv),
.eth_rxd(eth_rxd),
.eth_txen(eth_txen),
.eth_txd(eth_txd));
*/
module ether_la_playback (
input wire clk,
input wire enable,
output reg done,
output reg eth_crsdv,
output reg [1:0] eth_rxd,
output reg eth_txen,
output reg [1:0] eth_txd);
parameter MEM_FILE = "";
localparam SAMPLE_DEPTH = 17000;
localparam TOTAL_PROBE_WIDTH = 6;
reg [TOTAL_PROBE_WIDTH-1:0] capture [SAMPLE_DEPTH-1:0];
reg [$clog2(SAMPLE_DEPTH)-1:0] addr;
reg [TOTAL_PROBE_WIDTH-1:0] sample;
assign done = (addr >= SAMPLE_DEPTH);
initial begin
$readmemb("capture.mem", capture, 0, SAMPLE_DEPTH-1);
addr = 0;
end
always @(posedge clk) begin
if (enable && !done) begin
addr = addr + 1;
sample = capture[addr];
{eth_txd, eth_txen, eth_rxd, eth_crsdv} = sample;
end
end
endmodule

View File

@ -1,173 +0,0 @@
`default_nettype none
`timescale 1ns/1ps
module turbo_bullshit_tb();
logic ethclk;
logic rst;
always begin
#5;
ethclk = !ethclk;
end
/* batteries... */
logic eth_crsdv;
logic[1:0] eth_rxd;
logic eth_refclk;
logic eth_rstn;
/* ether -> { cksum, bitorder } */
logic[1:0] ether_axiod;
logic ether_axiov;
/* cksum -> top_level */
logic cksum_done, cksum_kill;
/* bitorder -> firewall */
logic[1:0] bitorder_axiod;
logic bitorder_axiov;
/* firewall -> aggregate */
logic[1:0] firewall_axiod;
logic firewall_axiov;
/* aggregate output */
logic[31:0] aggregate_axiod;
logic aggregate_axiov;
/* and here's the pipeline... */
logic enable;
logic eth_crsdv_playback;
logic [1:0] eth_rxd_playback;
logic eth_crsdv_pb9k;
logic [1:0] eth_rxd_pb9k;
logic eth_crsdv_mtx;
logic [1:0] eth_rxd_mtx;
logic eth_crsdv_debug;
logic [1:0] eth_rxd_debug;
// assign eth_crsdv_debug = eth_crsdv_playback;
// assign eth_rxd_debug = eth_rxd_playback;
assign eth_crsdv_debug = eth_crsdv_pb9k;
assign eth_rxd_debug = eth_rxd_pb9k;
// assign eth_crsdv_debug = eth_crsdv_mtx;
// assign eth_rxd_debug = eth_rxd_mtx;
reg serenity_now;
assign serenity_now = (eth_rxd_mtx != eth_rxd_pb9k);
ether_la_playback #(.MEM_FILE("capture.mem")) ether_la_playback_inst (
.clk(ethclk),
.enable(enable),
.done(),
.eth_crsdv(eth_crsdv_playback),
.eth_rxd(eth_rxd_playback),
.eth_txen(),
.eth_txd());
logic pb9k_start;
packet_blaster_9k pb9k (
.clk(ethclk),
.rst(rst),
//.src_mac(48'h69_2C_08_30_75_FD),
.src_mac(48'h00_00_00_00_00_00),
.dst_mac(48'hFF_FF_FF_FF_FF_FF),
.data(16'h5678),
.start(pb9k_start),
.txen(eth_crsdv_pb9k),
.txd(eth_rxd_pb9k));
logic mtx_start;
mac_tx mtx (
.clk(ethclk),
.data(16'h5678),
.start(mtx_start),
.txen(eth_crsdv_mtx),
.txd(eth_rxd_mtx));
ether e(
.clk(ethclk),
.rst(rst),
.rxd(eth_rxd_debug),
.crsdv(eth_crsdv_debug),
.axiov(ether_axiov),
.axiod(ether_axiod));
bitorder b(
.clk(ethclk),
.rst(rst),
.axiiv(ether_axiov),
.axiid(ether_axiod),
.axiov(bitorder_axiov),
.axiod(bitorder_axiod));
firewall f(
.clk(ethclk),
.rst(rst),
.axiiv(bitorder_axiov),
.axiid(bitorder_axiod),
.axiov(firewall_axiov),
.axiod(firewall_axiod));
aggregate a(
.clk(ethclk),
.rst(rst),
.axiiv(firewall_axiov),
.axiid(firewall_axiod),
.axiov(aggregate_axiov),
.axiod(aggregate_axiod));
cksum c(
.clk(ethclk),
.rst(rst),
.axiiv(ether_axiov),
.axiid(ether_axiod),
.done(cksum_done),
.kill(cksum_kill));
initial begin
ethclk = 0;
$dumpfile("turbo_bullshit_tb.vcd");
$dumpvars(0, turbo_bullshit_tb);
rst = 0;
pb9k_start = 0;
mtx_start = 0;
#10;
rst = 1;
#10;
rst = 0;
#10;
enable = 1;
#430;
pb9k_start = 1;
#10;
pb9k_start = 0;
#60;
mtx_start = 1 ;
#10;
mtx_start = 0;
#5000;
$finish();
end
endmodule
`default_nettype wire

View File

@ -1,192 +1,248 @@
`default_nettype none
`timescale 1ns/1ps
module mac_tx(
module mac_tx (
input wire clk,
// TODO: make this variable width
input wire [15:0] data,
input wire start,
output reg txen,
output reg [1:0] txd
);
/*
ok so how's this going to work:
what goes on the line is either the fcs, or everything else after being routed through bitorder
we keep the counter, once it gets to some value then we'll flip the switch and talk to the FCS
so then we mux between:
- the fixed portion ahead of the payload (prepayload)
- the payload, which is some register
- the zero padding, which is of some length that's parameterized
- the FCS, which DOES NOT GO THROUGH BITORDER
*/
output reg [1:0] txd);
// packet magic numbers
localparam PREAMBLE = {7{8'b01010101}};
localparam SFD = 8'b11010101;
parameter SRC_MAC = 48'h69_69_69_69_69_69;
parameter DST_MAC = 48'hFF_FF_FF_FF_FF_FF;
parameter LENGTH = 16'h1234;
localparam FCS_DATA = 32'b01001110_00010000_01011001_10011010;
localparam PREPAYLOAD_DATA = {PREAMBLE, SFD, DST_MAC, SRC_MAC, LENGTH};
parameter ETHERTYPE = 16'h1234;
// all lengths are in units of dibits, hence all the mulitplies by four
localparam PREPAYLOAD_LEN = (7 + 1 + 6 + 6 + 2) * 4; // in dibits
// localparam PAYLOAD_LEN = LENGTH * 4;
localparam PREAMBLE_LEN = 7 * 4;
localparam SFD_LEN = 1 * 4;
localparam SRC_MAC_LEN = 6 * 4;
localparam DST_MAC_LEN = 6 * 4;
localparam ETHERTYPE_LEN = 2 * 4;
localparam PAYLOAD_LEN = 2 * 4;
// localparam ZERO_PAD_LEN = (46 * 4) - PAYLOAD_LEN ; // minimum payload size is 46 bytes
localparam ZERO_PAD_LEN = (46 * 4) - PAYLOAD_LEN + 6; // minimum payload size is 46 bytes
localparam FCS_LEN = 4*4;
localparam IPG_LEN = 96/2;
// state machine
reg [8:0] counter = 0;
reg [2:0] state = 0;
localparam IDLE = 0;
localparam PREPAYLOAD = 1;
localparam PAYLOAD = 2;
localparam ZERO_PAD = 3;
localparam FCS = 4;
localparam IPG = 5;
reg prev_start;
always @(posedge clk) prev_start <= start;
localparam ZERO_PAD_LEN = (46 * 4) - PAYLOAD_LEN + 4; // minimum payload size is 46 bytes
localparam FCS_LEN = 4 * 4;
localparam IPG_LEN = 96 / 2;
// TODO: make crc and bitorder modules not need reset
reg rst = 1;
always @(posedge clk) rst <= 0;
reg bitorder_axiiv;
reg [1:0] bitorder_axiid;
reg bitorder_axiov;
reg [1:0] bitorder_axiod;
reg bitorder_axiiv;
reg bitorder_axiov;
bitorder b(
bitorder bitorder (
.clk(clk),
.rst(rst),
.axiiv(bitorder_axiiv),
.axiid(bitorder_axiid),
.axiov(bitorder_axiov),
.axiod(bitorder_axiod));
reg crc_rst = 1;
reg crc_axiiv = 0;
reg crc_axiov;
reg [31:0] crc_axiod;
reg [31:0] fcs = 0;
crc32 crc(
crc32 crc (
.clk(clk),
.rst(rst),
.rst(crc_rst),
.axiiv(crc_axiiv),
.axiid(txd),
.axiid(bitorder_axiod),
.axiov(crc_axiov),
// TODO: remove axiov from crc32 module, it's always valid
.axiov(),
.axiod(crc_axiod));
always @(*) begin
if (state == FCS && counter == 0) begin
txen <= 1;
txd <= {crc_axiod[30], crc_axiod[31]};
end
// state machine
reg [8:0] counter = 0;
reg [3:0] state = 0;
else if (state == FCS && counter != 0) begin
txen <= 1;
txd <= {fcs[2*(FCS_LEN-counter)-2], fcs[2*(FCS_LEN-counter)-1]};
end
else if (state == IPG) begin
txen <= 0;
txd <= 0;
end
else begin
txen = bitorder_axiov;
txd = bitorder_axiod;
end
localparam IDLE_STATE = 0;
localparam PREAMBLE_STATE = 1;
localparam SFD_STATE = 2;
localparam DST_MAC_STATE = 3;
localparam SRC_MAC_STATE = 4;
localparam ETHERTYPE_STATE = 5;
localparam PAYLOAD_STATE = 6;
localparam ZERO_PAD_STATE = 7;
localparam FCS_STATE = 8;
localparam IPG_STATE = 9;
end
// sequential logic manages the state machine
always @(posedge clk) begin
counter <= counter + 1;
crc_rst <= 0;
// idle state
if (state == IDLE) begin
bitorder_axiiv <= 0;
bitorder_axiid <= 0;
if(start && ~prev_start) state <= PREPAYLOAD;
if(state == IDLE_STATE) begin
counter <= 0;
crc_axiiv <= 0;
if(start) state <= PREAMBLE_STATE;
end
// everything before the payload (preamble, sfd, dst mac, src mac, length)
else if (state == PREPAYLOAD) begin
bitorder_axiiv <= 1;
bitorder_axiid <= PREPAYLOAD_DATA[2*(PREPAYLOAD_LEN-counter)-1-:2];
if(counter == 36) crc_axiiv <= 1;
counter <= counter + 1;
if(counter == PREPAYLOAD_LEN - 1) begin
else if(state == PREAMBLE_STATE) begin
if(counter == PREAMBLE_LEN - 1) begin
counter <= 0;
state <= PAYLOAD;
state <= SFD_STATE;
end
end
// the payload itself
else if (state == PAYLOAD) begin
$display(2*(PAYLOAD_LEN-counter)-2);
bitorder_axiid <= data[2*(PAYLOAD_LEN-counter)-1-:2];
else if(state == SFD_STATE) begin
if(counter == SFD_LEN - 1) begin
counter <= 0;
state <= DST_MAC_STATE;
end
end
counter <= counter + 1;
else if(state == DST_MAC_STATE) begin
// this is because the crc module lags behind the FSM,
// as it has to go through bitorder first
if(counter == 3) crc_axiiv <= 1;
if(counter == DST_MAC_LEN - 1) begin
counter <= 0;
state <= SRC_MAC_STATE;
end
end
else if(state == SRC_MAC_STATE) begin
if(counter == SRC_MAC_LEN - 1) begin
counter <= 0;
state <= ETHERTYPE_STATE;
end
end
else if(state == ETHERTYPE_STATE) begin
if(counter == ETHERTYPE_LEN - 1) begin
counter <= 0;
state <= PAYLOAD_STATE;
end
end
else if(state == PAYLOAD_STATE) begin
if(counter == PAYLOAD_LEN - 1) begin
counter <= 0;
state <= ZERO_PAD;
state <= ZERO_PAD_STATE;
end
end
// zero padding
else if (state == ZERO_PAD) begin
bitorder_axiid <= 2'b00;
counter <= counter + 1;
if(counter == ZERO_PAD_LEN - 2) begin
else if(state == ZERO_PAD_STATE) begin
if(counter == ZERO_PAD_LEN - 1) begin
crc_axiiv <= 0;
counter <= 0;
state <= FCS;
state <= FCS_STATE;
end
end
// readout fcs from the checksum module
else if (state == FCS) begin
if(counter == 0) fcs <= crc_axiod;
counter <= counter + 1;
else if(state == FCS_STATE) begin
if(counter == FCS_LEN - 1) begin
counter <= 0;
state <= IPG;
state <= IPG_STATE;
end
end
// interpacket gap
else if (state == IPG) begin
bitorder_axiiv <= 0;
bitorder_axiid <= 2'b00;
counter <= counter + 1;
if (counter == IPG_LEN - 1) begin
else if(state == IPG_STATE) begin
if(counter == IPG_LEN - 1) begin
crc_rst <= 1;
counter <= 0;
state <= IDLE;
state <= IDLE_STATE;
end
end
end
// combinational logic handles the pipeline
always @(*) begin
case (state)
IDLE_STATE: begin
bitorder_axiiv = 0;
bitorder_axiid = 0;
txen = 0;
txd = 0;
end
PREAMBLE_STATE: begin
bitorder_axiiv = 1;
bitorder_axiid = PREAMBLE[2*(PREAMBLE_LEN-counter)-1-:2];
txen = bitorder_axiov;
txd = bitorder_axiod;
end
SFD_STATE: begin
bitorder_axiiv = 1;
bitorder_axiid = SFD[2*(SFD_LEN-counter)-1-:2];
txen = bitorder_axiov;
txd = bitorder_axiod;
end
DST_MAC_STATE: begin
bitorder_axiiv = 1;
bitorder_axiid = DST_MAC[2*(DST_MAC_LEN-counter)-1-:2];
txen = bitorder_axiov;
txd = bitorder_axiod;
end
SRC_MAC_STATE: begin
bitorder_axiiv = 1;
bitorder_axiid = SRC_MAC[2*(SRC_MAC_LEN-counter)-1-:2];
txen = bitorder_axiov;
txd = bitorder_axiod;
end
ETHERTYPE_STATE: begin
bitorder_axiiv = 1;
bitorder_axiid = ETHERTYPE[2*(ETHERTYPE_LEN-counter)-1-:2];
txen = bitorder_axiov;
txd = bitorder_axiod;
end
PAYLOAD_STATE: begin
bitorder_axiiv = 1;
bitorder_axiid = data[2*(PAYLOAD_LEN-counter)-1-:2];
txen = bitorder_axiov;
txd = bitorder_axiod;
end
ZERO_PAD_STATE: begin
bitorder_axiiv = 1;
bitorder_axiid = 0;
txen = bitorder_axiov;
txd = bitorder_axiod;
end
FCS_STATE: begin
bitorder_axiiv = 0;
bitorder_axiid = 0;
txen = 1;
txd = {crc_axiod[2*(FCS_LEN-counter)-2], crc_axiod[2*(FCS_LEN-counter)-1]};
end
IPG_STATE: begin
bitorder_axiiv = 0;
bitorder_axiid = 0;
txen = 0;
txd = 0;
end
default: begin
bitorder_axiiv = 0;
bitorder_axiid = 0;
txen = 0;
txd = 0;
end
endcase
end
endmodule
`default_nettype wire

View File

@ -1,97 +0,0 @@
`default_nettype none
`timescale 1ns/1ps
module packet_blaster_9k(
input wire clk,
input wire rst,
input wire [47:0] src_mac,
input wire [47:0] dst_mac,
input wire [15:0] data,
input wire start,
output reg txen,
output reg [1:0] txd
);
/*
PREAMBLE: 7 bytes
SFD: 1 bytes
DEST MAC: 6 bytes
SOURCE MAC: 6 bytes
LENGTH: 2 bytes
DATA: 46 to 1k bytes
FCS:4 bytes
*/
// how long should our bus transactions be?
/*
coming in:
2 bytes for address
2 bytes for data (if writing)
2 bytes for data (if reading)
yeah for now let's do two and then just mask it off - only other option is trying to have some kind of buffered thing?
but then we have to be able to handle buffering the entire ethernet MTU - which is possible, but annoying. and now we're back
to buffering bus transactions, which was an explicit design anti-goal
maybe for now we just do the stupid thing?
ok so then this module should take output 2 bytes of data at the top of the packet, and then 44 bytes worth of zeros
length is then set to 46?
ok so plan for tomorrow is:
- to see if we can generate the packet we want to see on scapy. verify this in wireshark
- fire that over to the fpga, and save what it looks like with manta.
- make sure that if we replay that back to the host through txen/txd that we get what we think we should
- if not, then we have one FPGA transmit that packet to the other, which is recording with manta
- if so, then just massage packet blaster 9k to produce the right output.
*/
// all of our packets are going to be 72 bytes on wire, which is 288 dibits
reg [8:0] counter = 0;
reg [591:0] buffer = 0;
reg run = 0;
reg prev_start;
localparam PREAMBLE = {7{8'b01010101}};
localparam SFD = 8'b11010101;
localparam FCS = 32'b01001110_00010000_01011001_10011010;
bitorder b(
.clk(clk),
.rst(rst),
.axiiv(run),
.axiid(buffer[591:590]),
.axiov(txen),
.axiod(txd));
always @(posedge clk) begin
prev_start <= start;
if (run) begin
if (counter != 298) begin
counter <= counter + 1;
buffer <= {buffer[589:0], 2'b0};
end
else begin
run <= 0;
end
end
else begin
if (start && ~prev_start) begin
counter <= 0;
run <= 1;
buffer <= {16'b0, PREAMBLE, SFD, dst_mac, src_mac, 16'h1234, data, 352'b0, FCS};
end
end
end
endmodule
`default_nettype wire

View File

@ -6,6 +6,8 @@ module top_level (
input wire btnc,
input wire btnd,
input wire [15:0] sw,
output reg eth_refclk,
output reg eth_rstn,
@ -36,15 +38,26 @@ module top_level (
.eth_txen(eth_txen),
.eth_txd(eth_txd));
packet_blaster_9k pb9k (
// packet_blaster_9k pb9k (
// .clk(clk_50mhz),
// .rst(btnc),
// //.src_mac(48'h69_2C_08_30_75_FD),
// .src_mac(48'b00_00_00_00_00_00),
// .dst_mac(48'hFF_FF_FF_FF_FF_FF),
// .data(16'h5678),
// .start(btnd),
// .txen(eth_txen),
// .txd(eth_txd));
mac_tx mtx (
.clk(clk_50mhz),
.rst(btnc),
//.src_mac(48'h69_2C_08_30_75_FD),
.src_mac(48'b00_00_00_00_00_00),
.dst_mac(48'hFF_FF_FF_FF_FF_FF),
.data(16'h5678),
.data(sw),
.start(btnd),

View File

@ -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