324 lines
7.5 KiB
Verilog
324 lines
7.5 KiB
Verilog
//
|
|
// Copyright 2012 Ettus Research LLC
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
`timescale 1 ps / 1 ps
|
|
|
|
module eth_dispatch_tb();
|
|
|
|
|
|
// Clocking and reset interface
|
|
reg clk;
|
|
reg reset;
|
|
reg clear;
|
|
// Setting register interface
|
|
reg set_stb;
|
|
reg [15:0] set_addr;
|
|
reg [31:0] set_data;
|
|
// Input 68bit AXI-Stream interface (from MAC)
|
|
wire [63:0] in_tdata;
|
|
wire [3:0] in_tuser;
|
|
wire in_tlast;
|
|
wire in_tvalid;
|
|
wire in_tready;
|
|
// Output AXI-Stream interface to VITA Radio Core
|
|
wire [63:0] vita_tdata;
|
|
wire [3:0] vita_tuser;
|
|
wire vita_tlast;
|
|
wire vita_tvalid;
|
|
wire vita_tready;
|
|
// Output AXI-Stream interface to ZPU
|
|
wire [63:0] zpu_tdata;
|
|
wire [3:0] zpu_tuser;
|
|
wire zpu_tlast;
|
|
wire zpu_tvalid;
|
|
wire zpu_tready;
|
|
// Output AXI-Stream interface to cross-over MAC
|
|
wire [63:0] xo_tdata;
|
|
wire [3:0] xo_tuser;
|
|
wire xo_tlast;
|
|
wire xo_tvalid;
|
|
wire xo_tready;
|
|
|
|
reg [63:0] data_in;
|
|
reg [3:0] user_in;
|
|
reg valid_in;
|
|
wire ready_in;
|
|
reg last_in;
|
|
|
|
eth_dispatch
|
|
#(.BASE(0))
|
|
eth_dispatch_i
|
|
(
|
|
// Clocking and reset interface
|
|
.clk(clk),
|
|
.reset(reset),
|
|
.clear(clear),
|
|
// Setting register interface
|
|
.set_stb(set_stb),
|
|
.set_addr(set_addr),
|
|
.set_data(set_data),
|
|
// Input 68bit AXI-Stream interface (from MAC)
|
|
.in_tdata(in_tdata),
|
|
.in_tuser(in_tuser),
|
|
.in_tlast(in_tlast),
|
|
.in_tvalid(in_tvalid),
|
|
.in_tready(in_tready),
|
|
// Output AXI-STream interface to VITA Radio Core
|
|
.vita_tdata(vita_tdata),
|
|
.vita_tuser(vita_tuser),
|
|
.vita_tlast(vita_tlast),
|
|
.vita_tvalid(vita_tvalid),
|
|
.vita_tready(vita_tready),
|
|
// Output AXI-Stream interface to ZPU
|
|
.zpu_tdata(zpu_tdata),
|
|
.zpu_tuser(zpu_tuser),
|
|
.zpu_tlast(zpu_tlast),
|
|
.zpu_tvalid(zpu_tvalid),
|
|
.zpu_tready(zpu_tready),
|
|
// Output AXI-Stream interface to cross-over MAC
|
|
.xo_tdata(xo_tdata),
|
|
.xo_tuser(xo_tuser),
|
|
.xo_tlast(xo_tlast),
|
|
.xo_tvalid(xo_tvalid),
|
|
.xo_tready(xo_tready)
|
|
);
|
|
|
|
//
|
|
// Define Clocks
|
|
//
|
|
initial begin
|
|
clk = 1'b1;
|
|
end
|
|
|
|
// 125MHz clock
|
|
always #4000 clk = ~clk;
|
|
|
|
//
|
|
// Good starting state
|
|
//
|
|
initial begin
|
|
reset <= 0;
|
|
clear <= 0;
|
|
set_stb <= 0;
|
|
set_addr <= 0;
|
|
set_data <= 0;
|
|
data_in <= 0;
|
|
user_in <= 0;
|
|
valid_in <= 0;
|
|
last_in <= 0;
|
|
|
|
end
|
|
|
|
|
|
|
|
//
|
|
// Task Libaray
|
|
//
|
|
task write_setting_bus;
|
|
input [15:0] address;
|
|
input [31:0] data;
|
|
|
|
begin
|
|
|
|
@(negedge clk);
|
|
set_stb = 1'b0;
|
|
set_addr = 16'h0;
|
|
set_data = 32'h0;
|
|
@(negedge clk);
|
|
set_stb = 1'b1;
|
|
set_addr = address;
|
|
set_data = data;
|
|
@(negedge clk);
|
|
set_stb = 1'b0;
|
|
set_addr = 16'h0;
|
|
set_data = 32'h0;
|
|
|
|
end
|
|
endtask // write_setting_bus
|
|
|
|
|
|
task enqueue_line;
|
|
input last;
|
|
input [2:0] keep;
|
|
input [63:0] data;
|
|
begin
|
|
data_in <= {keep, data};
|
|
last_in <= last;
|
|
valid_in <= 1;
|
|
while (~ready_in) begin
|
|
@(negedge clk);
|
|
end
|
|
@(negedge clk);
|
|
data_in <= 0;
|
|
last_in <= 0;
|
|
valid_in <= 0;
|
|
end
|
|
endtask // enqueue_line
|
|
|
|
task enqueue_arp_req;
|
|
input [47:0] src_mac;
|
|
input [31:0] src_ip;
|
|
input [47:0] dst_mac;
|
|
input [31:0] dst_ip;
|
|
|
|
begin
|
|
@(negedge clk);
|
|
// Line 0
|
|
enqueue_line( 0, 3'b0, {48'h0,16'hffff});
|
|
// Line 1 - Eth
|
|
enqueue_line( 0, 3'b0, {32'hffffffff,src_mac[47:16]});
|
|
// Line 2 - Eth+ARP (HTYPE = 1, PTYPE = 0x0800)
|
|
enqueue_line( 0, 3'b0, {src_mac[15:0],16'h0806,16'h0001,16'h0800});
|
|
// Line 3 - HLEN=6, PLEN=4 OPER=1
|
|
enqueue_line( 0, 3'b0, {8'h06,8'h04,16'h0001,src_mac[47:16]});
|
|
// Line 4 - ARP
|
|
enqueue_line( 0, 3'b0, {src_mac[15:0],src_ip[31:0],dst_mac[47:32]});
|
|
// Line 5 - ARP
|
|
enqueue_line( 1, 3'b0, {dst_mac[31:0],dst_ip[31:0]});
|
|
end
|
|
endtask // enqueue_arp_req
|
|
|
|
|
|
|
|
reg [11:0] frame_count =12'h0;
|
|
|
|
task enqueue_vita_pkt;
|
|
// We assume that we always have SID and TSF fields.
|
|
input [47:0] mac;
|
|
input [31:0] ip;
|
|
input [15:0] udp;
|
|
input [15:0] vita_size;
|
|
input [63:0] vita_tsf;
|
|
input [31:0] vita_sid;
|
|
|
|
|
|
integer i;
|
|
reg [15:0] j;
|
|
reg [19:0] vrl_size;
|
|
reg [15:0] udp_size;
|
|
reg [15:0] ip_size;
|
|
|
|
|
|
begin
|
|
vrl_size = vita_size + 3;
|
|
udp_size = vrl_size*4 + 8;
|
|
ip_size = udp_size + 20;
|
|
@(negedge clk);
|
|
// Line 0
|
|
enqueue_line( 0, 3'b0, {48'h0,mac[47:32]});
|
|
// Line 1 - Eth
|
|
enqueue_line( 0, 3'b0, {mac[31:0],32'h11223344});
|
|
// Line 2 - Eth+IP
|
|
enqueue_line( 0, 3'b0, {16'h5566,16'h0800,16'h0000,ip_size});
|
|
// Line 3 - IP
|
|
enqueue_line( 0, 3'b0, 'h11<<16);
|
|
// Line 4 - IP
|
|
enqueue_line( 0, 3'b0, {32'h09080706, ip});
|
|
// Line 5 - UDP
|
|
enqueue_line( 0, 3'b0, {16'h1234, udp, udp_size, 16'h0});
|
|
// Line 6 - VRL
|
|
enqueue_line( 0, 3'b0, {"VRLP",frame_count,vrl_size});
|
|
// Line 7 - VRT
|
|
enqueue_line( 0, 3'b0, {16'b0001000000010000, vita_size,vita_sid}); //vita hdr + SID
|
|
enqueue_line( 0, 3'b0, vita_tsf);
|
|
j = 0;
|
|
|
|
for (i = 6; i < vita_size; i = i + 2) begin
|
|
enqueue_line( 0 , 3'b0, {j,j+16'h1,j+16'h2,j+16'h3});
|
|
j = j + 4;
|
|
end
|
|
|
|
if (i-vita_size==0) // 2x32words to finish VITA packet.
|
|
enqueue_line( 1, 3'b0, {j,j+16'h1,j+16'h2,j+16'h3});
|
|
else // 1x32bit word to finish VITA packet
|
|
enqueue_line( 1, 3'h4, {j,j+16'h1,j+16'h2,j+16'h3});
|
|
end
|
|
|
|
endtask // enqueue_packet
|
|
|
|
|
|
//
|
|
// Simulation specific testbench is included here
|
|
//
|
|
`include "simulation_script.v"
|
|
|
|
|
|
//
|
|
// Input FIFO
|
|
//
|
|
axi_fifo_short
|
|
#(.WIDTH(69)) axi_fifo_short_in
|
|
(
|
|
.clk(clk),
|
|
.reset(reset),
|
|
.clear(clear),
|
|
.o_tdata({in_tlast,in_tuser,in_tdata}),
|
|
.o_tvalid(in_tvalid),
|
|
.o_tready(in_tready),
|
|
.i_tdata({last_in,user_in,data_in}),
|
|
.i_tvalid(valid_in),
|
|
.i_tready(ready_in),
|
|
.space(),
|
|
.occupied()
|
|
);
|
|
|
|
//
|
|
// Output Sinks
|
|
//
|
|
axi_probe_tb
|
|
#(.FILENAME("zpu.txt"),.VITA_PORT0(60000),.VITA_PORT1(60001)) axi_probe_tb_zpu
|
|
(
|
|
.clk(clk),
|
|
.reset(reset),
|
|
.clear(clear),
|
|
.tdata(zpu_tdata),
|
|
.tvalid(zpu_tvalid),
|
|
.tready(zpu_tready),
|
|
.tlast(zpu_tlast)
|
|
);
|
|
|
|
assign zpu_tready = 1'b1;
|
|
|
|
axi_probe_tb
|
|
#(.FILENAME("xo.txt"),.VITA_PORT0(60000),.VITA_PORT1(60001)) axi_probe_tb_xo
|
|
(
|
|
.clk(clk),
|
|
.reset(reset),
|
|
.clear(clear),
|
|
.tdata(xo_tdata),
|
|
.tvalid(xo_tvalid),
|
|
.tready(xo_tready),
|
|
.tlast(xo_tlast)
|
|
);
|
|
|
|
assign xo_tready = 1'b1;
|
|
|
|
axi_probe_tb
|
|
#(.FILENAME("vita.txt"),.VITA_PORT0(60000),.VITA_PORT1(60001),.START_AT_VRL(1)) axi_probe_tb_vita
|
|
(
|
|
.clk(clk),
|
|
.reset(reset),
|
|
.clear(clear),
|
|
.tdata(vita_tdata),
|
|
.tvalid(vita_tvalid),
|
|
.tready(vita_tready),
|
|
.tlast(vita_tlast)
|
|
);
|
|
|
|
assign vita_tready = 1'b1;
|
|
|
|
endmodule // eth_dispatch_tb
|