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

126 lines
6.2 KiB
Systemverilog

`timescale 1ns/1ps
`default_nettype none
module tb_recorder_stream;
localparam int FIFO_DEPTH=8192;
localparam int FRAME_BYTES=1526;
logic w_clk=0, clk=0, w_rst=1, rst=1;
logic w_en=0, w_full, r_en, r_valid, r_empty;
logic [68:0] w_data=0, r_data;
logic [$clog2(FIFO_DEPTH):0] w_level, r_level;
logic [63:0] ovf, udf;
logic frame_start, payload_valid, payload_ready, mac_busy, frame_done;
logic [10:0] payload_length;
logic [7:0] payload_data, gmii_txd;
logic gmii_tx_en, gmii_tx_er;
logic [31:0] packet_sequence;
logic activity;
logic [63:0] frames, payload_bytes;
byte captured [0:4095];
integer cap_count=0;
integer produced=0;
integer i, f, base, data_base;
logic [31:0] crc_ref, fcs_seen;
logic [31:0] seq_seen;
logic [63:0] index_seen;
logic [15:0] count_seen;
always #5 w_clk=~w_clk; // 100 MHz producer, unrelated to reader
always #4 clk=~clk; // 125 MHz Ethernet
async_fifo_gray #(.DATA_WIDTH(69),.DEPTH(FIFO_DEPTH)) fifo (
.w_clk(w_clk),.w_rst(w_rst),.w_en(w_en),.w_data(w_data),.w_full(w_full),
.w_level(w_level),.overflow_attempt_count(ovf),.r_clk(clk),.r_rst(rst),
.r_en(r_en),.r_data(r_data),.r_valid(r_valid),.r_empty(r_empty),
.r_level(r_level),.underflow_attempt_count(udf)
);
ethernet_packetizer #(.FIFO_DEPTH(FIFO_DEPTH),.FULL_SAMPLES(2936)) packetizer (
.clk(clk),.rst(rst),.link_ready(1'b1),.dropped_samples_low(32'd5),
.fifo_empty(r_empty),.fifo_level(r_level),.fifo_rd_en(r_en),
.fifo_rd_data(r_data),.fifo_rd_valid(r_valid),.mac_frame_start(frame_start),
.mac_payload_length(payload_length),.mac_payload_data(payload_data),
.mac_payload_valid(payload_valid),.mac_payload_ready(payload_ready),
.mac_busy(mac_busy),.mac_frame_done(frame_done),
.packet_sequence(packet_sequence),.frame_activity_pulse(activity)
);
ethernet_tx_mac mac (
.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(mac_busy),.frame_done(frame_done),.frames_transmitted(frames),
.payload_bytes_transmitted(payload_bytes)
);
always @(posedge clk) if (!rst && gmii_tx_en) begin
captured[cap_count]=gmii_txd;
cap_count=cap_count+1;
if(gmii_tx_er) $fatal(1,"GMII underflow/error in stream test");
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
repeat(5) @(posedge w_clk); w_rst=0;
repeat(5) @(posedge clk); rst=0;
// Supply exactly two contiguous normal frames plus CDC slack.
for(produced=0;produced<5872;produced=produced+1) begin
@(negedge w_clk);
while(w_full) @(negedge w_clk);
w_en=1;
w_data={1'b0,64'(produced),4'(produced & 15)};
end
@(negedge w_clk); w_en=0;
wait(packet_sequence==32'd2);
repeat(4) @(posedge clk);
if(cap_count!=2*FRAME_BYTES) $fatal(1,"captured %0d bytes expected %0d",cap_count,2*FRAME_BYTES);
for(f=0;f<2;f=f+1) begin
base=f*FRAME_BYTES;
for(i=0;i<7;i=i+1) if(captured[base+i]!==8'h55) $fatal(1,"frame %0d preamble",f);
if(captured[base+7]!==8'hd5 || captured[base+20]!==8'h88 || captured[base+21]!==8'hb5)
$fatal(1,"frame %0d L2 header",f);
if(captured[base+22]!=="M" || captured[base+23]!=="X" ||
captured[base+24]!=="2" || captured[base+25]!=="7") $fatal(1,"frame %0d magic",f);
if(captured[base+26]!==8'd1 || captured[base+28]!==8'd0 || captured[base+29]!==8'd32)
$fatal(1,"frame %0d protocol constants",f);
seq_seen={captured[base+30],captured[base+31],captured[base+32],captured[base+33]};
index_seen={captured[base+34],captured[base+35],captured[base+36],captured[base+37],
captured[base+38],captured[base+39],captured[base+40],captured[base+41]};
count_seen={captured[base+42],captured[base+43]};
if(seq_seen!==f || index_seen!==64'(f*2936) || count_seen!==16'd2936)
$fatal(1,"frame %0d metadata seq=%0d index=%0d count=%0d",f,seq_seen,index_seen,count_seen);
if(captured[base+44]!==8'd4 || captured[base+45]!==8'd1)
$fatal(1,"frame %0d packing metadata",f);
// First frame carries reset+link flags; second carries none.
if((f==0 && captured[base+27]!==8'h07) || (f==1 && captured[base+27]!==8'h00))
$fatal(1,"frame %0d flags %02x",f,captured[base+27]);
if ({captured[base+46],captured[base+47],captured[base+48],captured[base+49]} !== 32'd5)
$fatal(1,"frame %0d dropped-count header",f);
data_base=base+54;
for(i=0;i<2936;i=i+1) begin
if((i&1)==0) begin
if(captured[data_base+(i>>1)][7:4]!==((f*2936+i)&15))
$fatal(1,"frame %0d sample %0d high nibble",f,i);
end else if(captured[data_base+(i>>1)][3:0]!==((f*2936+i)&15))
$fatal(1,"frame %0d sample %0d low nibble",f,i);
end
crc_ref=32'hffffffff;
for(i=8;i<1522;i=i+1) crc_ref=crc_byte(crc_ref,captured[base+i]);
crc_ref=~crc_ref;
fcs_seen={captured[base+1525],captured[base+1524],captured[base+1523],captured[base+1522]};
if(fcs_seen!==crc_ref) $fatal(1,"frame %0d FCS got %08x expected %08x",f,fcs_seen,crc_ref);
end
if(frames!==64'd2 || payload_bytes!==64'd3000 || udf!==64'd0)
$fatal(1,"counter failure frames=%0d payload=%0d underflow=%0d",frames,payload_bytes,udf);
$display("PASS tb_recorder_stream: two full frames, 5872 samples, headers/index/sequence/FCS verified");
$finish;
end
initial begin #1000000; $fatal(1,"stream test timeout"); end
endmodule
`default_nettype wire