mirror of
https://github.com/corundum/corundum.git
synced 2025-02-06 08:38:23 +08:00
Add RX checksum module and testbench
This commit is contained in:
parent
755c7959be
commit
6100e3ad78
198
fpga/common/rtl/rx_checksum.v
Normal file
198
fpga/common/rtl/rx_checksum.v
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019, The Regents of the University of California.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS
|
||||||
|
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
The views and conclusions contained in the software and documentation are those
|
||||||
|
of the authors and should not be interpreted as representing official policies,
|
||||||
|
either expressed or implied, of The Regents of the University of California.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Language: Verilog 2001
|
||||||
|
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receive checksum offload module
|
||||||
|
*/
|
||||||
|
module rx_checksum #
|
||||||
|
(
|
||||||
|
parameter DATA_WIDTH = 256,
|
||||||
|
parameter KEEP_WIDTH = (DATA_WIDTH/8)
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input wire clk,
|
||||||
|
input wire rst,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AXI input
|
||||||
|
*/
|
||||||
|
input wire [DATA_WIDTH-1:0] s_axis_tdata,
|
||||||
|
input wire [KEEP_WIDTH-1:0] s_axis_tkeep,
|
||||||
|
input wire s_axis_tvalid,
|
||||||
|
input wire s_axis_tlast,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checksum output
|
||||||
|
*/
|
||||||
|
output wire [15:0] m_axis_csum,
|
||||||
|
output wire m_axis_csum_valid
|
||||||
|
);
|
||||||
|
|
||||||
|
// bus width assertions
|
||||||
|
initial begin
|
||||||
|
if (DATA_WIDTH != 256) begin
|
||||||
|
$error("Error: AXI stream interface width must be 256");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (KEEP_WIDTH * 8 != DATA_WIDTH) begin
|
||||||
|
$error("Error: AXI stream interface requires byte (8-bit) granularity");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
reg [KEEP_WIDTH-1:0] mask_reg = 32'hffffc000;
|
||||||
|
reg [DATA_WIDTH-1:0] s_axis_tdata_masked;
|
||||||
|
|
||||||
|
reg [16:0] sum_1_1_reg = 0;
|
||||||
|
reg [16:0] sum_1_2_reg = 0;
|
||||||
|
reg [16:0] sum_1_3_reg = 0;
|
||||||
|
reg [16:0] sum_1_4_reg = 0;
|
||||||
|
reg [16:0] sum_1_5_reg = 0;
|
||||||
|
reg [16:0] sum_1_6_reg = 0;
|
||||||
|
reg [16:0] sum_1_7_reg = 0;
|
||||||
|
reg [16:0] sum_1_8_reg = 0;
|
||||||
|
reg sum_1_valid_reg = 1'b0;
|
||||||
|
reg sum_1_last_reg = 1'b0;
|
||||||
|
|
||||||
|
reg [17:0] sum_2_1_reg = 0;
|
||||||
|
reg [17:0] sum_2_2_reg = 0;
|
||||||
|
reg [17:0] sum_2_3_reg = 0;
|
||||||
|
reg [17:0] sum_2_4_reg = 0;
|
||||||
|
reg sum_2_valid_reg = 1'b0;
|
||||||
|
reg sum_2_last_reg = 1'b0;
|
||||||
|
|
||||||
|
reg [18:0] sum_3_1_reg = 0;
|
||||||
|
reg [18:0] sum_3_2_reg = 0;
|
||||||
|
reg sum_3_valid_reg = 1'b0;
|
||||||
|
reg sum_3_last_reg = 1'b0;
|
||||||
|
|
||||||
|
reg [19:0] sum_4_reg = 0;
|
||||||
|
reg sum_4_valid_reg = 1'b0;
|
||||||
|
reg sum_4_last_reg = 1'b0;
|
||||||
|
|
||||||
|
reg [20:0] sum_5_temp = 0;
|
||||||
|
reg [15:0] sum_5_reg = 0;
|
||||||
|
|
||||||
|
reg [15:0] m_axis_csum_reg = 0;
|
||||||
|
reg m_axis_csum_valid_reg = 1'b0;
|
||||||
|
|
||||||
|
assign m_axis_csum = m_axis_csum_reg;
|
||||||
|
assign m_axis_csum_valid = m_axis_csum_valid_reg;
|
||||||
|
|
||||||
|
// Mask input data
|
||||||
|
integer j;
|
||||||
|
|
||||||
|
always @* begin
|
||||||
|
for (j = 0; j < KEEP_WIDTH; j = j + 1) begin
|
||||||
|
s_axis_tdata_masked[j*8 +: 8] = (s_axis_tkeep[j] && mask_reg[j]) ? s_axis_tdata[j*8 +: 8] : 8'd0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
sum_1_valid_reg <= 1'b0;
|
||||||
|
sum_2_valid_reg <= 1'b0;
|
||||||
|
sum_3_valid_reg <= 1'b0;
|
||||||
|
sum_4_valid_reg <= 1'b0;
|
||||||
|
m_axis_csum_valid_reg <= 1'b0;
|
||||||
|
|
||||||
|
if (s_axis_tvalid) begin
|
||||||
|
sum_1_1_reg <= {s_axis_tdata_masked[ 0*8 +: 8], s_axis_tdata_masked[ 1*8 +: 8]} + {s_axis_tdata_masked[ 2*8 +: 8], s_axis_tdata_masked[ 3*8 +: 8]};
|
||||||
|
sum_1_2_reg <= {s_axis_tdata_masked[ 4*8 +: 8], s_axis_tdata_masked[ 5*8 +: 8]} + {s_axis_tdata_masked[ 6*8 +: 8], s_axis_tdata_masked[ 7*8 +: 8]};
|
||||||
|
sum_1_3_reg <= {s_axis_tdata_masked[ 8*8 +: 8], s_axis_tdata_masked[ 9*8 +: 8]} + {s_axis_tdata_masked[10*8 +: 8], s_axis_tdata_masked[11*8 +: 8]};
|
||||||
|
sum_1_4_reg <= {s_axis_tdata_masked[12*8 +: 8], s_axis_tdata_masked[13*8 +: 8]} + {s_axis_tdata_masked[14*8 +: 8], s_axis_tdata_masked[15*8 +: 8]};
|
||||||
|
sum_1_5_reg <= {s_axis_tdata_masked[16*8 +: 8], s_axis_tdata_masked[17*8 +: 8]} + {s_axis_tdata_masked[18*8 +: 8], s_axis_tdata_masked[19*8 +: 8]};
|
||||||
|
sum_1_6_reg <= {s_axis_tdata_masked[20*8 +: 8], s_axis_tdata_masked[21*8 +: 8]} + {s_axis_tdata_masked[22*8 +: 8], s_axis_tdata_masked[23*8 +: 8]};
|
||||||
|
sum_1_7_reg <= {s_axis_tdata_masked[24*8 +: 8], s_axis_tdata_masked[25*8 +: 8]} + {s_axis_tdata_masked[26*8 +: 8], s_axis_tdata_masked[27*8 +: 8]};
|
||||||
|
sum_1_8_reg <= {s_axis_tdata_masked[28*8 +: 8], s_axis_tdata_masked[29*8 +: 8]} + {s_axis_tdata_masked[30*8 +: 8], s_axis_tdata_masked[31*8 +: 8]};
|
||||||
|
sum_1_valid_reg <= 1'b1;
|
||||||
|
sum_1_last_reg <= s_axis_tlast;
|
||||||
|
|
||||||
|
if (s_axis_tlast) begin
|
||||||
|
mask_reg <= 32'hffffc000;
|
||||||
|
end else begin
|
||||||
|
mask_reg <= {KEEP_WIDTH{1'b1}};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (sum_1_valid_reg) begin
|
||||||
|
sum_2_1_reg <= sum_1_1_reg + sum_1_2_reg;
|
||||||
|
sum_2_2_reg <= sum_1_3_reg + sum_1_4_reg;
|
||||||
|
sum_2_3_reg <= sum_1_5_reg + sum_1_6_reg;
|
||||||
|
sum_2_4_reg <= sum_1_7_reg + sum_1_8_reg;
|
||||||
|
sum_2_valid_reg <= 1'b1;
|
||||||
|
sum_2_last_reg <= sum_1_last_reg;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (sum_2_valid_reg) begin
|
||||||
|
sum_3_1_reg <= sum_2_1_reg + sum_2_2_reg;
|
||||||
|
sum_3_2_reg <= sum_2_3_reg + sum_2_4_reg;
|
||||||
|
sum_3_valid_reg <= 1'b1;
|
||||||
|
sum_3_last_reg <= sum_2_last_reg;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (sum_3_valid_reg) begin
|
||||||
|
sum_4_reg <= sum_3_1_reg + sum_3_2_reg;
|
||||||
|
sum_4_valid_reg <= 1'b1;
|
||||||
|
sum_4_last_reg <= sum_3_last_reg;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (sum_4_valid_reg) begin
|
||||||
|
sum_5_temp = sum_4_reg + sum_5_reg;
|
||||||
|
sum_5_temp = sum_5_temp[15:0] + sum_5_temp[20:16];
|
||||||
|
sum_5_temp = sum_5_temp[15:0] + sum_5_temp[16];
|
||||||
|
|
||||||
|
if (sum_4_last_reg) begin
|
||||||
|
m_axis_csum_reg <= sum_5_temp;
|
||||||
|
m_axis_csum_valid_reg <= 1'b1;
|
||||||
|
sum_5_reg <= 0;
|
||||||
|
end else begin
|
||||||
|
sum_5_reg <= sum_5_temp;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (rst) begin
|
||||||
|
mask_reg <= 32'hffffc000;
|
||||||
|
sum_1_valid_reg <= 1'b0;
|
||||||
|
sum_2_valid_reg <= 1'b0;
|
||||||
|
sum_3_valid_reg <= 1'b0;
|
||||||
|
sum_4_valid_reg <= 1'b0;
|
||||||
|
m_axis_csum_valid_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
322
fpga/common/tb/test_rx_checksum.py
Executable file
322
fpga/common/tb/test_rx_checksum.py
Executable file
@ -0,0 +1,322 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""
|
||||||
|
|
||||||
|
Copyright 2019, The Regents of the University of California.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS
|
||||||
|
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
The views and conclusions contained in the software and documentation are those
|
||||||
|
of the authors and should not be interpreted as representing official policies,
|
||||||
|
either expressed or implied, of The Regents of the University of California.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from myhdl import *
|
||||||
|
import os
|
||||||
|
|
||||||
|
import axis_ep
|
||||||
|
import eth_ep
|
||||||
|
|
||||||
|
module = 'rx_checksum'
|
||||||
|
testbench = 'test_%s' % module
|
||||||
|
|
||||||
|
srcs = []
|
||||||
|
|
||||||
|
srcs.append("../rtl/%s.v" % module)
|
||||||
|
srcs.append("%s.v" % testbench)
|
||||||
|
|
||||||
|
src = ' '.join(srcs)
|
||||||
|
|
||||||
|
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||||
|
|
||||||
|
def frame_checksum(frame):
|
||||||
|
data = bytearray()
|
||||||
|
if isinstance(frame, eth_ep.EthFrame):
|
||||||
|
data = frame.payload.data
|
||||||
|
elif isinstance(frame, axis_ep.AXIStreamFrame):
|
||||||
|
data = frame.data[14:]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
csum = 0
|
||||||
|
odd = False
|
||||||
|
|
||||||
|
for b in data:
|
||||||
|
if odd:
|
||||||
|
csum += b
|
||||||
|
else:
|
||||||
|
csum += b << 8
|
||||||
|
odd = not odd
|
||||||
|
|
||||||
|
csum = (csum & 0xffff) + (csum >> 16)
|
||||||
|
csum = (csum & 0xffff) + (csum >> 16)
|
||||||
|
|
||||||
|
return csum
|
||||||
|
|
||||||
|
def bench():
|
||||||
|
|
||||||
|
# Parameters
|
||||||
|
DATA_WIDTH = 256
|
||||||
|
KEEP_WIDTH = (DATA_WIDTH/8)
|
||||||
|
|
||||||
|
# Inputs
|
||||||
|
clk = Signal(bool(0))
|
||||||
|
rst = Signal(bool(0))
|
||||||
|
current_test = Signal(intbv(0)[8:])
|
||||||
|
|
||||||
|
s_axis_tdata = Signal(intbv(0)[DATA_WIDTH:])
|
||||||
|
s_axis_tkeep = Signal(intbv(0)[KEEP_WIDTH:])
|
||||||
|
s_axis_tvalid = Signal(bool(0))
|
||||||
|
s_axis_tlast = Signal(bool(0))
|
||||||
|
|
||||||
|
# Outputs
|
||||||
|
m_axis_csum = Signal(intbv(0)[16:])
|
||||||
|
m_axis_csum_valid = Signal(bool(0))
|
||||||
|
|
||||||
|
# sources and sinks
|
||||||
|
source_pause = Signal(bool(0))
|
||||||
|
|
||||||
|
source = axis_ep.AXIStreamSource()
|
||||||
|
|
||||||
|
source_logic = source.create_logic(
|
||||||
|
clk,
|
||||||
|
rst,
|
||||||
|
tdata=s_axis_tdata,
|
||||||
|
tkeep=s_axis_tkeep,
|
||||||
|
tvalid=s_axis_tvalid,
|
||||||
|
tlast=s_axis_tlast,
|
||||||
|
pause=source_pause,
|
||||||
|
name='source'
|
||||||
|
)
|
||||||
|
|
||||||
|
sink = axis_ep.AXIStreamSink()
|
||||||
|
|
||||||
|
sink_logic = sink.create_logic(
|
||||||
|
clk,
|
||||||
|
rst,
|
||||||
|
tdata=(m_axis_csum,),
|
||||||
|
tvalid=m_axis_csum_valid,
|
||||||
|
name='sink'
|
||||||
|
)
|
||||||
|
|
||||||
|
# DUT
|
||||||
|
if os.system(build_cmd):
|
||||||
|
raise Exception("Error running build command")
|
||||||
|
|
||||||
|
dut = Cosimulation(
|
||||||
|
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||||
|
clk=clk,
|
||||||
|
rst=rst,
|
||||||
|
current_test=current_test,
|
||||||
|
s_axis_tdata=s_axis_tdata,
|
||||||
|
s_axis_tkeep=s_axis_tkeep,
|
||||||
|
s_axis_tvalid=s_axis_tvalid,
|
||||||
|
s_axis_tlast=s_axis_tlast,
|
||||||
|
m_axis_csum=m_axis_csum,
|
||||||
|
m_axis_csum_valid=m_axis_csum_valid
|
||||||
|
)
|
||||||
|
|
||||||
|
@always(delay(4))
|
||||||
|
def clkgen():
|
||||||
|
clk.next = not clk
|
||||||
|
|
||||||
|
def wait_normal():
|
||||||
|
while s_axis_tvalid:
|
||||||
|
yield clk.posedge
|
||||||
|
|
||||||
|
def wait_pause_source():
|
||||||
|
while s_axis_tvalid:
|
||||||
|
yield clk.posedge
|
||||||
|
yield clk.posedge
|
||||||
|
source_pause.next = False
|
||||||
|
yield clk.posedge
|
||||||
|
source_pause.next = True
|
||||||
|
yield clk.posedge
|
||||||
|
|
||||||
|
source_pause.next = False
|
||||||
|
|
||||||
|
@instance
|
||||||
|
def check():
|
||||||
|
yield delay(100)
|
||||||
|
yield clk.posedge
|
||||||
|
rst.next = 1
|
||||||
|
yield clk.posedge
|
||||||
|
rst.next = 0
|
||||||
|
yield clk.posedge
|
||||||
|
yield delay(100)
|
||||||
|
yield clk.posedge
|
||||||
|
|
||||||
|
# testbench stimulus
|
||||||
|
|
||||||
|
for payload_len in list(range(1, 128)) + list([1024, 1500, 9000, 9214]):
|
||||||
|
yield clk.posedge
|
||||||
|
print("test 1: test packet, length %d" % payload_len)
|
||||||
|
current_test.next = 1
|
||||||
|
|
||||||
|
test_frame = eth_ep.EthFrame()
|
||||||
|
test_frame.eth_dest_mac = 0xDAD1D2D3D4D5
|
||||||
|
test_frame.eth_src_mac = 0x5A5152535455
|
||||||
|
test_frame.eth_type = 0x8000
|
||||||
|
test_frame.payload = bytearray((x%256 for x in range(payload_len)))
|
||||||
|
|
||||||
|
axis_frame = test_frame.build_axis()
|
||||||
|
|
||||||
|
for wait in wait_normal, wait_pause_source:
|
||||||
|
source.send(axis_frame)
|
||||||
|
yield clk.posedge
|
||||||
|
yield clk.posedge
|
||||||
|
|
||||||
|
yield wait()
|
||||||
|
|
||||||
|
yield sink.wait()
|
||||||
|
rx_csum = sink.recv().data[0][0]
|
||||||
|
print(hex(rx_csum))
|
||||||
|
|
||||||
|
csum = frame_checksum(test_frame)
|
||||||
|
print(hex(csum))
|
||||||
|
|
||||||
|
assert rx_csum == csum
|
||||||
|
|
||||||
|
assert sink.empty()
|
||||||
|
|
||||||
|
yield delay(100)
|
||||||
|
|
||||||
|
yield clk.posedge
|
||||||
|
print("test 2: back-to-back packets, length %d" % payload_len)
|
||||||
|
current_test.next = 2
|
||||||
|
|
||||||
|
test_frame1 = eth_ep.EthFrame()
|
||||||
|
test_frame1.eth_dest_mac = 0xDAD1D2D3D4D5
|
||||||
|
test_frame1.eth_src_mac = 0x5A5152535455
|
||||||
|
test_frame1.eth_type = 0x8000
|
||||||
|
test_frame1.payload = bytearray((x%256 for x in range(payload_len)))
|
||||||
|
test_frame2 = eth_ep.EthFrame()
|
||||||
|
test_frame2.eth_dest_mac = 0xDAD1D2D3D4D5
|
||||||
|
test_frame2.eth_src_mac = 0x5A5152535455
|
||||||
|
test_frame2.eth_type = 0x8000
|
||||||
|
test_frame2.payload = bytearray((~x%256 for x in range(payload_len)))
|
||||||
|
|
||||||
|
axis_frame1 = test_frame1.build_axis()
|
||||||
|
axis_frame2 = test_frame2.build_axis()
|
||||||
|
|
||||||
|
for wait in wait_normal, wait_pause_source:
|
||||||
|
source.send(axis_frame1)
|
||||||
|
source.send(axis_frame2)
|
||||||
|
yield clk.posedge
|
||||||
|
yield clk.posedge
|
||||||
|
|
||||||
|
yield wait()
|
||||||
|
|
||||||
|
yield sink.wait()
|
||||||
|
rx_csum = sink.recv().data[0][0]
|
||||||
|
print(hex(rx_csum))
|
||||||
|
|
||||||
|
csum = frame_checksum(test_frame1)
|
||||||
|
print(hex(csum))
|
||||||
|
|
||||||
|
assert rx_csum == csum
|
||||||
|
|
||||||
|
yield sink.wait()
|
||||||
|
rx_csum = sink.recv().data[0][0]
|
||||||
|
print(hex(rx_csum))
|
||||||
|
|
||||||
|
csum = frame_checksum(test_frame2)
|
||||||
|
print(hex(csum))
|
||||||
|
|
||||||
|
assert rx_csum == csum
|
||||||
|
|
||||||
|
assert sink.empty()
|
||||||
|
|
||||||
|
yield delay(100)
|
||||||
|
|
||||||
|
yield clk.posedge
|
||||||
|
print("test 3: overflow test")
|
||||||
|
current_test.next = 3
|
||||||
|
|
||||||
|
axis_frame = axis_ep.AXIStreamFrame(bytearray([0xff]*10240))
|
||||||
|
|
||||||
|
for wait in wait_normal, wait_pause_source:
|
||||||
|
source.send(axis_frame)
|
||||||
|
yield clk.posedge
|
||||||
|
yield clk.posedge
|
||||||
|
|
||||||
|
yield wait()
|
||||||
|
|
||||||
|
yield sink.wait()
|
||||||
|
rx_csum = sink.recv().data[0][0]
|
||||||
|
print(hex(rx_csum))
|
||||||
|
|
||||||
|
csum = frame_checksum(axis_frame)
|
||||||
|
print(hex(csum))
|
||||||
|
|
||||||
|
assert rx_csum == csum
|
||||||
|
|
||||||
|
assert sink.empty()
|
||||||
|
|
||||||
|
yield delay(100)
|
||||||
|
|
||||||
|
yield clk.posedge
|
||||||
|
print("test 4: checksum test")
|
||||||
|
current_test.next = 4
|
||||||
|
|
||||||
|
test_frame = eth_ep.EthFrame()
|
||||||
|
test_frame.eth_dest_mac = 0xDA0203040506
|
||||||
|
test_frame.eth_src_mac = 0xCA0203040506
|
||||||
|
test_frame.eth_type = 0x005a
|
||||||
|
test_frame.payload = b'\xab\xcd'+bytearray(range(20, 108))
|
||||||
|
|
||||||
|
axis_frame = test_frame.build_axis()
|
||||||
|
|
||||||
|
for wait in wait_normal, wait_pause_source:
|
||||||
|
source.send(axis_frame)
|
||||||
|
yield clk.posedge
|
||||||
|
yield clk.posedge
|
||||||
|
|
||||||
|
yield wait()
|
||||||
|
|
||||||
|
yield sink.wait()
|
||||||
|
rx_csum = sink.recv().data[0][0]
|
||||||
|
print(hex(rx_csum))
|
||||||
|
|
||||||
|
csum = frame_checksum(test_frame)
|
||||||
|
print(hex(csum))
|
||||||
|
|
||||||
|
assert csum == 0x8ad8
|
||||||
|
assert rx_csum == csum
|
||||||
|
|
||||||
|
assert sink.empty()
|
||||||
|
|
||||||
|
yield delay(100)
|
||||||
|
|
||||||
|
raise StopSimulation
|
||||||
|
|
||||||
|
return instances()
|
||||||
|
|
||||||
|
def test_bench():
|
||||||
|
sim = Simulation(bench())
|
||||||
|
sim.run()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("Running test...")
|
||||||
|
test_bench()
|
97
fpga/common/tb/test_rx_checksum.v
Normal file
97
fpga/common/tb/test_rx_checksum.v
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019, The Regents of the University of California.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS
|
||||||
|
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||||
|
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
|
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
The views and conclusions contained in the software and documentation are those
|
||||||
|
of the authors and should not be interpreted as representing official policies,
|
||||||
|
either expressed or implied, of The Regents of the University of California.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Language: Verilog 2001
|
||||||
|
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Testbench for rx_checksum
|
||||||
|
*/
|
||||||
|
module test_rx_checksum;
|
||||||
|
|
||||||
|
// Parameters
|
||||||
|
parameter DATA_WIDTH = 256;
|
||||||
|
parameter KEEP_WIDTH = (DATA_WIDTH/8);
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
reg clk = 0;
|
||||||
|
reg rst = 0;
|
||||||
|
reg [7:0] current_test = 0;
|
||||||
|
|
||||||
|
reg [DATA_WIDTH-1:0] s_axis_tdata = 0;
|
||||||
|
reg [KEEP_WIDTH-1:0] s_axis_tkeep = 0;
|
||||||
|
reg s_axis_tvalid = 0;
|
||||||
|
reg s_axis_tlast = 0;
|
||||||
|
|
||||||
|
// Outputs
|
||||||
|
wire [15:0] m_axis_csum;
|
||||||
|
wire m_axis_csum_valid;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
// myhdl integration
|
||||||
|
$from_myhdl(
|
||||||
|
clk,
|
||||||
|
rst,
|
||||||
|
current_test,
|
||||||
|
s_axis_tdata,
|
||||||
|
s_axis_tkeep,
|
||||||
|
s_axis_tvalid,
|
||||||
|
s_axis_tlast
|
||||||
|
);
|
||||||
|
$to_myhdl(
|
||||||
|
m_axis_csum,
|
||||||
|
m_axis_csum_valid
|
||||||
|
);
|
||||||
|
|
||||||
|
// dump file
|
||||||
|
$dumpfile("test_rx_checksum.lxt");
|
||||||
|
$dumpvars(0, test_rx_checksum);
|
||||||
|
end
|
||||||
|
|
||||||
|
rx_checksum #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.KEEP_WIDTH(KEEP_WIDTH)
|
||||||
|
)
|
||||||
|
UUT (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.s_axis_tdata(s_axis_tdata),
|
||||||
|
.s_axis_tkeep(s_axis_tkeep),
|
||||||
|
.s_axis_tvalid(s_axis_tvalid),
|
||||||
|
.s_axis_tlast(s_axis_tlast),
|
||||||
|
.m_axis_csum(m_axis_csum),
|
||||||
|
.m_axis_csum_valid(m_axis_csum_valid)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
Loading…
x
Reference in New Issue
Block a user