Files
max2771-raw-ethernet-recorder/tb/common/tb_ethernet_tx_mac.sv
T

101 lines
4.2 KiB
Systemverilog

`timescale 1ns/1ps
`default_nettype none
module tb_ethernet_tx_mac;
logic clk=0, rst=1;
logic frame_start=0;
logic [10:0] payload_length=11'd4;
logic [7:0] payload_data;
logic payload_valid, payload_ready;
logic [7:0] gmii_txd;
logic gmii_tx_en, gmii_tx_er, busy, frame_done;
logic [63:0] frames, payload_bytes;
byte payload [0:3];
byte captured [0:255];
byte body [0:59];
integer payload_pos=0, cap_count=0, i;
logic [31:0] reference_crc;
always #4 clk=~clk;
assign payload_data = payload[payload_pos];
assign payload_valid = (payload_pos < 4);
ethernet_tx_mac dut (
.clk(clk), .rst(rst), .frame_start(frame_start), .payload_length(payload_length),
.payload_data(payload_data), .payload_valid(payload_valid), .payload_ready(payload_ready),
.gmii_txd(gmii_txd), .gmii_tx_en(gmii_tx_en), .gmii_tx_er(gmii_tx_er),
.busy(busy), .frame_done(frame_done), .frames_transmitted(frames),
.payload_bytes_transmitted(payload_bytes)
);
always @(posedge clk) begin
if (!rst && gmii_tx_en) begin
captured[cap_count] = gmii_txd;
cap_count = cap_count + 1;
if (gmii_tx_er) $fatal(1, "unexpected GMII TX error");
end
if (!rst && payload_ready && payload_valid)
payload_pos <= payload_pos + 1;
end
function automatic [31:0] crc_byte(input [31:0] cin, input [7:0] din);
reg [31:0] c;
integer b;
begin
c=cin;
for (b=0;b<8;b=b+1)
c=(c[0]^din[b]) ? ((c>>1)^32'hedb88320) : (c>>1);
crc_byte=c;
end
endfunction
initial begin
payload[0]=8'hde; payload[1]=8'had; payload[2]=8'hbe; payload[3]=8'hef;
repeat(4) @(posedge clk); rst=0;
@(posedge clk); frame_start=1;
@(posedge clk); frame_start=0;
wait(frame_done);
@(posedge clk);
if (cap_count != 72) $fatal(1, "frame byte count %0d expected 72", cap_count);
for (i=0;i<7;i=i+1) if(captured[i]!==8'h55) $fatal(1,"bad preamble byte %0d",i);
if(captured[7]!==8'hd5) $fatal(1,"bad SFD");
for (i=0;i<6;i=i+1) body[i]=8'hff;
body[6]=8'h02; body[7]=8'h27; body[8]=8'h71; body[9]=8'h00; body[10]=8'h00; body[11]=8'h01;
body[12]=8'h88; body[13]=8'hb5;
body[14]=8'hde; body[15]=8'had; body[16]=8'hbe; body[17]=8'hef;
for(i=18;i<60;i=i+1) body[i]=8'h00;
for(i=0;i<60;i=i+1) if(captured[8+i]!==body[i])
$fatal(1,"body mismatch byte %0d got %02x expected %02x",i,captured[8+i],body[i]);
reference_crc=32'hffffffff;
for(i=0;i<60;i=i+1) reference_crc=crc_byte(reference_crc,body[i]);
reference_crc=~reference_crc;
if(captured[68]!==reference_crc[7:0] || captured[69]!==reference_crc[15:8] ||
captured[70]!==reference_crc[23:16] || captured[71]!==reference_crc[31:24])
$fatal(1,"FCS mismatch got %02x%02x%02x%02x expected %08x",
captured[71],captured[70],captured[69],captured[68],reference_crc);
if(frames!==64'd1 || payload_bytes!==64'd4) $fatal(1,"MAC counters incorrect");
// Reset while idle, then send another complete frame. No TX_EN fragment
// may appear during reset or before the new preamble.
rst=1; payload_pos=0; cap_count=0;
repeat(3) begin @(posedge clk); if(gmii_tx_en) $fatal(1,"TX_EN asserted during idle reset"); end
rst=0;
repeat(2) @(posedge clk);
frame_start=1; @(posedge clk); frame_start=0;
wait(frame_done); @(posedge clk);
if(cap_count!=72) $fatal(1,"post-reset frame malformed: %0d bytes",cap_count);
for(i=0;i<7;i=i+1) if(captured[i]!==8'h55) $fatal(1,"post-reset preamble byte %0d",i);
reference_crc=32'hffffffff;
for(i=0;i<60;i=i+1) reference_crc=crc_byte(reference_crc,body[i]);
reference_crc=~reference_crc;
if({captured[71],captured[70],captured[69],captured[68]}!==reference_crc)
$fatal(1,"post-reset FCS mismatch");
$display("PASS tb_ethernet_tx_mac: frame/padding/FCS/IFG and reset-between-frames verified");
$finish;
end
initial begin #10000; $fatal(1,"MAC test timeout"); end
endmodule
`default_nettype wire