add working mac testbench - also found a problem in VCD logging

This commit is contained in:
Fischer Moseley 2023-04-21 00:10:25 -04:00
parent cfddb67652
commit dab6e3f272
3 changed files with 459 additions and 0 deletions

View File

@ -0,0 +1,170 @@
`default_nettype none
`timescale 1ns/1ps
module comparison_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;
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("comparison_tb.vcd");
$dumpvars(0, comparison_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

@ -0,0 +1,128 @@
`default_nettype none
`timescale 1ns/1ps
module mac_tx_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;
mac_tx mtx (
.clk(ethclk),
.data(16'h5678),
.start(start),
.txen(eth_crsdv),
.txd(eth_rxd));
ether e(
.clk(ethclk),
.rst(rst),
.rxd(eth_rxd),
.crsdv(eth_crsdv_ref),
.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("mac_tx_tb.vcd");
$dumpvars(0, mac_tx_tb);
rst = 0;
start = 0;
#10;
rst = 1;
#10;
rst = 0;
#10;
enable = 1;
#500;
start = 1;
#10;
start = 0;
#5000;
$finish();
end
endmodule
`default_nettype wire

View File

@ -0,0 +1,161 @@
`default_nettype none
`timescale 1ns/1ps
module mac_tx(
input wire clk,
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
*/
localparam PREAMBLE = {7{8'b01010101}};
localparam SFD = 8'b11010101;
parameter SRC_MAC = 48'h00_00_00_00_00_00;
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};
// 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 PAYLOAD_LEN = 2 * 4;
localparam ZERO_PAD_LEN = (46 * 4) - PAYLOAD_LEN ; // 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;
reg rst = 1;
always @(posedge clk) rst <= 0;
reg bitorder_axiiv;
reg [1:0] bitorder_axiid;
bitorder b(
.clk(clk),
.rst(rst),
.axiiv(bitorder_axiiv),
.axiid(bitorder_axiid),
.axiov(txen),
.axiod(txd));
reg crc_axiiv = 0;
reg crc_axiov;
reg [31:0] crc_axiod;
crc32 crc(
.clk(clk),
.rst(rst),
.axiiv(crc_axiiv),
.axiid(txd),
.axiov(crc_axiov),
.axiod(crc_axiod));
always @(posedge clk) begin
// idle state
if (state == IDLE) begin
bitorder_axiiv <= 0;
bitorder_axiid <= 0;
if(start && ~prev_start) state <= PREPAYLOAD;
counter <= 0;
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
counter <= 0;
state <= PAYLOAD;
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];
counter <= counter + 1;
if(counter == PAYLOAD_LEN - 1) begin
counter <= 0;
state <= ZERO_PAD;
end
end
// zero padding
else if (state == ZERO_PAD) begin
bitorder_axiid <= 2'b00;
counter <= counter + 1;
if(counter == ZERO_PAD_LEN - 1) begin
counter <= 0;
state <= FCS;
end
end
// readout fcs from the checksum module
else if (state == FCS) begin
bitorder_axiiv <= 1;
bitorder_axiid <= FCS_DATA[2*(FCS_LEN-counter)-1-:2];
counter <= counter + 1;
if(counter == FCS_LEN - 1) begin
counter <= 0;
state <= IPG;
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
counter <= 0;
state <= IDLE;
end
end
end
endmodule
`default_nettype wire