Commit ffa5d3a8 authored by Maciej Lipinski's avatar Maciej Lipinski

[rtu]: added SystemVerilog testbench for RTU

parent a728a030
target = "xilinx" # "altera" #
action = "simulation"
#fetchto = "../../ip_cores"
files = [
"../../modules/wrsw_shared_types_pkg.vhd",
"if_rtu_port.svh",
"xwrsw_rtu_wrapper.svh",
"xwrsw_rtu_wrapper.vhd",
"main.sv",
]
vlog_opt="+incdir+./+incdir+../../ip_cores/wr-cores/sim +incdir+../../ip_cores/wr-cores/sim/fabric_emu +incdir+../../sim "
modules = {"local":
[
"../../ip_cores/wr-cores",
"../../ip_cores/wr-cores/ip_cores/general-cores/modules/genrams/",
"../../modules/wrsw_rtu/",
],
}
//
// Title : RTU port interface for testebch
//
// File : if_rtu.sv
// Author : Maciej Lipinski
// Created : 2012-05-23
// Standard : SystemVerilog
//
interface IRTU
(
input clk_i,
input rst_n_i
);
parameter g_mac_addr_width = 48;
parameter g_vid_width = 3;
parameter g_prio_width = 3;
parameter g_rtu_num_ports = 20;
logic rtu_idle;
logic rq_strobe_p;
logic [g_mac_addr_width-1:0 ] rq_smac;
logic [g_mac_addr_width-1:0 ] rq_dmac;
logic [g_vid_width -1:0 ] rq_vid;
logic rq_has_vid;
logic [g_prio_width -1:0 ] rq_prio;
logic rq_has_prio;
logic rsp_valid;
logic [g_rtu_num_ports -1:0 ] rsp_dst_port_mask;
logic rsp_drop;
logic [g_prio_width -1:0 ] rsp_prio;
logic rsp_ack;
logic port_almost_full;
logic port_full;
int cnt;
int port_nr;
task automatic init_port(input int portNum);
port_nr = portNum;
rq_smac <= 0;
rq_dmac <= 0;
rq_vid <= 0;
rq_has_vid <= 0;
rq_prio <= 0;
rq_has_prio <= 0;
rq_strobe_p <= 0;
rq_strobe_p <= 1'b0;
rsp_ack <= 1'b0;
@(posedge clk_i);
endtask
task automatic send_req
(
input bit[7:0] dmac[],
input bit[7:0] smac[],
input bit[7:0] vid,
input bit has_vid,
input bit[7:0] prio,
input bit has_prio,
input bit drop
);
rq_strobe_p <= 1'b0;
@(posedge clk_i);
rq_smac[47:40] <= smac[0];
rq_smac[39:32] <= smac[1];
rq_smac[31:24] <= smac[2];
rq_smac[23:16] <= smac[3];
rq_smac[15: 8] <= smac[4];
rq_smac[ 7: 0] <= smac[5];
rq_dmac[47:40] <= dmac[0];
rq_dmac[39:32] <= dmac[1];
rq_dmac[31:24] <= dmac[2];
rq_dmac[23:16] <= dmac[3];
rq_dmac[15: 8] <= dmac[4];
rq_dmac[ 7: 0] <= dmac[5];
rq_vid <= vid[g_vid_width -1:0 ];
rq_has_vid <= has_vid;
rq_prio <= prio[g_prio_width-1:0 ];
rq_has_prio <= has_prio;
rq_strobe_p <= 1'b1;
@(posedge clk_i);
rq_strobe_p <= 1'b0;
endtask
always@(posedge clk_i)
begin
//$display("rsp_valid = %d",rsp_valid);
if(rsp_valid == 1'b1)
begin
$display("RTU.port[%2d] rsp: dmac=0x%x, drop=%d, prio=%d [time=%4d cycles, %4d ns]",
port_nr, rsp_dst_port_mask,rsp_drop,rsp_prio, cnt, cnt*16);
rsp_ack <= 1'b1;
@(posedge clk_i);
rsp_ack <= 1'b0;
end
end
initial forever
begin
@(posedge clk_i);
//count how long a request is handled
if(rq_strobe_p == 1) cnt = 0;
else if(rtu_idle == 0) cnt++;
end
endinterface // IRTU
/*-------------------------------------------------------------------------------
-- Title : RTU Testbench
-- Project : White Rabbit switch
-------------------------------------------------------------------------------
-- File : main.sv
-- Author : Maciej Lipinski
-- Company : CERN BE-Co-HT
-- Created : 2012-05-24
-- Last update: 2012-05-24
-- Platform : SystemVerilog
-- Standard :
-------------------------------------------------------------------------------
-- Description:
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
--
-------------------------------------------------------------------------------
--
-- Copyright (c) 2012 Maciej Lipinski / CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source 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 Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2012-05-24 1.0 mlipinsk Created
------------------------------------------------------------------------------*/
// `include "xwrsw_rtu_wrapper.svh"
// `include "if_rtu_port.svh"
`include "xwrsw_rtu_wrapper.svh"
`include "if_rtu_port.svh"
`include "if_wb_master.svh"
`include "if_wb_slave.svh"
`include "simdrv_rtu.sv"
`define c_mac_addr_width 48
`define c_vid_num_width 12
`define c_prio_num_width 3
`define c_prio_num 8
`define c_num_ports 8
`define c_port_mask_bits (`c_num_ports + 1)
module main;
/* parameter g_mac_addr_width = 48;
parameter g_vid_width = 3;
parameter g_prio_width = 3;
parameter g_port_mask_bits = 15;
parameter g_prio_num = 8;
parameter g_num_ports = 16; */
reg clk_i=0;
reg rst_n=0;
always #8ns clk_i <= ~clk_i;
CRTUSimDriver rtu;
IRTU #(`c_mac_addr_width,
`c_vid_num_width,
`c_prio_num_width,
`c_port_mask_bits) port[`c_num_ports] (clk_i,rst_n_i);
swc_core_wrapper_generic
#(
.g_prio_num (`c_prio_num),
.g_prio_num_width (`c_prio_num_width),
.g_vid_num_width (`c_vid_num_width),
.g_mac_addr_width (`c_mac_addr_width),
.g_num_ports (`c_num_ports),
.g_port_mask_bits (`c_port_mask_bits)
)
DUT (
.clk_i(clk_i),
.rst_n_i(rst_n)
/* .port(port),
.rtu_wb(rtu_wb) */
);
initial begin
repeat(3) @(posedge clk_i);
rst_n <= 1;
end
initial begin
rtu_vlan_entry_t def_vlan;
CWishboneAccessor rtu_acc = DUT.rtu_wb.get_accessor();
bit[7:0] dmac[];
bit[7:0] smac[];
repeat(200) @(posedge clk_i);
rtu = new;
rtu_acc.set_mode(PIPELINED);
DUT.rtu_wb.settings.addr_gran = WORD;
rtu.set_bus(rtu_acc, 'h00000);
for (int dd=0;dd<`c_num_ports;dd++)
begin
rtu.set_port_config(dd, 1, 1, 1);
// DUT.port[dd].init_port();
end
def_vlan.port_mask = 32'hffffffff;
def_vlan.fid = 0;
def_vlan.drop = 0;
def_vlan.has_prio = 0;
def_vlan.prio_override = 0;
rtu.add_vlan_entry(0, def_vlan);
rtu.add_static_rule('{5, 'h50, 'hca, 'hfe, 'hba, 'hbe}, (1<<2 ));
rtu.add_static_rule('{6, 'h50, 'hca, 'hfe, 'hba, 'hbe}, (1<<1 ));
rtu.enable();
DUT.port[0].init_port(0);
DUT.port[1].init_port(1);
DUT.port[2].init_port(2);
DUT.port[3].init_port(3);
DUT.port[4].init_port(4);
DUT.port[5].init_port(5);
DUT.port[6].init_port(6);
DUT.port[7].init_port(7);
repeat(200) @(posedge clk_i);
smac = '{5, 'h50, 'hca, 'hfe, 'hba, 'hbe};
dmac = '{6, 'h50, 'hca, 'hfe, 'hba, 'hbe};
/*
DUT.port[0].send_req('{5, 'h50, 'hca, 'hfe, 'hba, 'hbe};, //dmac
'{6, 'h50, 'hca, 'hfe, 'hba, 'hbe}, //smac
0, //vid
0, //has_vid
0, //prio
0, //has_prio
0); //drop
*/
DUT.port[0].send_req(dmac, smac, 0,0,0,0,0);
dmac[0]=0;
DUT.port[0].send_req(dmac, smac, 0,0,0,0,0);
dmac[0]=1;
DUT.port[1].send_req(dmac, smac, 0,0,0,0,0);
dmac[0]=2;
DUT.port[2].send_req(dmac, smac, 0,0,0,0,0);
dmac[0]=3;
DUT.port[3].send_req(dmac, smac, 0,0,0,0,0);
end
endmodule //main
\ No newline at end of file
make -f Makefile
vsim -L secureip -L unisim -t 10fs work.main -voptargs="+acc" +nowarn8684 +nowarn8683
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
do wave.do
#do wave_allports.do
radix -hexadecimal
run 4000us
wave zoomfull
radix -hexadecimal
\ No newline at end of file
`include "if_rtu_port.svh"
`include "if_wb_master.svh"
`include "if_wb_slave.svh"
// `define `c_mac_addr_width 48
// `define `c_vid_width 3
// `define `c_prio_width 3
// `define `c_port_mask_bits 15
// `define `c_prio_num 8
// `define `c_num_ports 16
`define array_assign(a, ah, al, b, bl) \
for (k=al; k<=ah; k=k+1) begin assign a[k] = b[bl+k-al]; end
module swc_core_wrapper_generic
(
clk_i,
rst_n_i
// port,
// rtu_wb
);
parameter g_prio_num = 8;
parameter g_prio_num_width = 3;
parameter g_vid_num_width = 3;
parameter g_mac_addr_width = 48;
parameter g_num_ports = 16;
parameter g_port_mask_bits = 15;
input clk_i;
input rst_n_i;
IWishboneMaster #(32,32) rtu_wb (clk_i,rst_n_i);
IRTU #(g_mac_addr_width,
g_vid_num_width,
g_prio_num_width,
g_port_mask_bits) port[g_num_ports] (clk_i,rst_n_i);
wire [g_num_ports -1 :0] rtu_idle;
wire [g_num_ports -1 :0] rq_strobe_p;
wire [g_num_ports*g_mac_addr_width -1 :0] rq_smac;
wire [g_num_ports*g_mac_addr_width -1 :0] rq_dmac;
wire [g_num_ports*g_vid_num_width -1 :0] rq_vid;
wire [g_num_ports -1 :0] rq_has_vid;
wire [g_num_ports*g_prio_num_width -1 :0] rq_prio;
wire [g_num_ports -1 :0] rq_has_prio;
wire [g_num_ports -1 :0] rsp_valid;
wire [g_num_ports*g_port_mask_bits -1 :0] rsp_dst_port_mask;
wire [g_num_ports -1 :0] rsp_drop;
wire [g_num_ports*g_prio_num_width -1 :0] rsp_prio;
wire [g_num_ports -1 :0] rsp_ack;
wire [g_num_ports -1 :0] port_almost_full;
wire [g_num_ports -1 :0] port_full;
xwrsw_rtu_wrapper
#(
.g_prio_num (g_prio_num),
.g_prio_num_width (g_prio_num_width),
.g_vid_num_width (g_vid_num_width),
.g_mac_addr_width (g_mac_addr_width),
.g_num_ports (g_num_ports),
.g_port_mask_bits (g_port_mask_bits)
)DUT_RTU(
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.rtu_idle_o (rtu_idle),
.rq_strobe_p_i (rq_strobe_p),
.rq_smac_i (rq_smac),
.rq_dmac_i (rq_dmac),
.rq_vid_i (rq_vid),
.rq_has_vid_i (rq_has_vid),
.rq_prio_i (rq_prio),
.rq_has_prio_i (rq_has_prio),
.rsp_valid_o (rsp_valid),
.rsp_dst_port_mask_o (rsp_dst_port_mask),
.rsp_drop_o (rsp_drop),
.rsp_prio_o (rsp_prio),
.rsp_ack_i (rsp_ack),
.port_almost_full_o (port_almost_full),
.port_full_o (port_full),
.wb_addr_i (rtu_wb.master.adr),
.wb_data_i (rtu_wb.master.dat_o),
.wb_data_o (rtu_wb.master.dat_i),
.wb_sel_i (rtu_wb.master.sel),
.wb_cyc_i (rtu_wb.master.cyc),
.wb_stb_i (rtu_wb.master.stb),
.wb_ack_o (rtu_wb.master.ack),
// .wb_irq_o (),
.wb_we_i (rtu_wb.master.we)
);
genvar i, k;
generate
for(i=0;i<g_num_ports;i=i+1)
begin
`array_assign(rq_smac,(i+1)*g_mac_addr_width-1, i*g_mac_addr_width,port[i].rq_smac,0);
`array_assign(rq_dmac,(i+1)*g_mac_addr_width-1, i*g_mac_addr_width,port[i].rq_dmac,0);
`array_assign(rq_vid, (i+1)*g_vid_num_width -1, i*g_vid_num_width, port[i].rq_vid, 0);
`array_assign(rq_prio,(i+1)*g_prio_num_width-1, i*g_prio_num_width,port[i].rq_prio,0);
assign port[i].rtu_idle = rtu_idle[i];
assign rq_strobe_p[i] = port[i].rq_strobe_p;
assign rq_has_vid[i] = port[i].rq_has_vid;
assign rq_has_prio[i] = port[i].rq_has_prio;
assign port[i].rsp_valid = rsp_valid[i];
assign port[i].rsp_drop = rsp_drop[i];
assign rsp_ack[i] = port[i].rsp_ack;
assign port[i].port_almost_full = port_almost_full[i];
assign port[i].port_full = port_full[i];
`array_assign(port[i].rsp_dst_port_mask,g_port_mask_bits-1,0,rsp_dst_port_mask,i*g_port_mask_bits);
`array_assign(port[i].rsp_prio, g_prio_num_width-1,0,rsp_prio, i*g_prio_num_width);
end //for(i=0;i<g_num_ports;i=i+1)
endgenerate
endmodule
-------------------------------------------------------------------------------
-- Title : Testbench wrapper for extended (interface-wise) Routing Table Unit (RTU)
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : xwrsw_rtu_wrapper.vhd
-- Authors : Maciej Lipinski
-- Company : CERN BE-Co-HT
-- Created : 2012-05-23
-- Last update: 2012-05-23
-- Platform : FPGA-generic
-- Standard : VHDL
-------------------------------------------------------------------------------
-- Description: wrapping xwrsw_rtu.vhd for testbench in systemVerilog
--
-------------------------------------------------------------------------------
--
-- Copyright (c) 2012 Maciej Lipinski / CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source 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 Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2012-05-23 1.0 mlipinsk Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.wishbone_pkg.all;
use work.wrsw_shared_types_pkg.all;
use work.wrsw_rtu_private_pkg.all;
entity xwrsw_rtu_wrapper is
generic (
g_interface_mode : t_wishbone_interface_mode := PIPELINED;
g_address_granularity : t_wishbone_address_granularity := WORD;
g_handle_only_single_req_per_port : boolean := TRUE;
g_prio_num : integer;
g_prio_num_width : integer;
g_vid_num_width : integer;
g_mac_addr_width : integer;
g_num_ports : integer;
g_port_mask_bits : integer);
port(
clk_i : in std_logic;
rst_n_i : in std_logic;
-------------------------------------------------------------------------------
-- N-port RTU input interface (from the endpoint)
-------------------------------------------------------------------------------
rtu_idle_o : out std_logic_vector(g_num_ports-1 downto 0);
rq_strobe_p_i : in std_logic_vector(g_num_ports-1 downto 0);
rq_smac_i : in std_logic_vector(g_num_ports * g_mac_addr_width - 1 downto 0);
rq_dmac_i : in std_logic_vector(g_num_ports * g_mac_addr_width -1 downto 0);
rq_vid_i : in std_logic_vector(g_num_ports * g_vid_num_width - 1 downto 0);
rq_has_vid_i : in std_logic_vector(g_num_ports -1 downto 0);
rq_prio_i : in std_logic_vector(g_num_ports * g_prio_num_width -1 downto 0);
rq_has_prio_i : in std_logic_vector(g_num_ports -1 downto 0);
-------------------------------------------------------------------------------
-- N-port RTU output interface (to the packet buffer
-------------------------------------------------------------------------------
rsp_valid_o : out std_logic_vector(g_num_ports-1 downto 0);
rsp_dst_port_mask_o : out std_logic_vector(g_num_ports * g_port_mask_bits - 1 downto 0);
rsp_drop_o : out std_logic_vector(g_num_ports -1 downto 0);
rsp_prio_o : out std_logic_vector(g_num_ports * g_prio_num_width - 1 downto 0);
rsp_ack_i : in std_logic_vector(g_num_ports -1 downto 0);
port_almost_full_o : out std_logic_vector(g_num_ports -1 downto 0);
port_full_o : out std_logic_vector(g_num_ports -1 downto 0);
-------------------------------------------------------------------------------
-- Wishbone (synchronous to refclk2_i). See the wbgen2 file for register details
-------------------------------------------------------------------------------
wb_addr_i : in std_logic_vector(31 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_sel_i : in std_logic_vector(3 downto 0);
wb_cyc_i : in std_logic;
wb_stb_i : in std_logic;
wb_ack_o : out std_logic;
wb_irq_o : out std_logic;
wb_we_i : in std_logic
);
end xwrsw_rtu_wrapper;
architecture behavioral of xwrsw_rtu_wrapper is
component xwrsw_rtu
generic (
g_interface_mode : t_wishbone_interface_mode := PIPELINED;
g_address_granularity : t_wishbone_address_granularity := BYTE;
g_handle_only_single_req_per_port : boolean := FALSE;
g_prio_num : integer;
g_num_ports : integer;
g_port_mask_bits : integer);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
req_i : in t_rtu_request_array(g_num_ports-1 downto 0);
req_full_o : out std_logic_vector(g_num_ports-1 downto 0);
rsp_o : out t_rtu_response_array(g_num_ports-1 downto 0);
rsp_ack_i : in std_logic_vector(g_num_ports-1 downto 0);
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out
);
end component;
signal req : t_rtu_request_array(g_num_ports-1 downto 0);
signal req_full : std_logic_vector(g_num_ports-1 downto 0);
signal rsp : t_rtu_response_array(g_num_ports-1 downto 0);
signal rsp_ack : std_logic_vector(g_num_ports-1 downto 0);
signal wb_in : t_wishbone_slave_in;
signal wb_out : t_wishbone_slave_out;
begin
U_xwrsw_rtu: xwrsw_rtu
generic map (
g_interface_mode => g_interface_mode,
g_address_granularity => g_address_granularity,
g_handle_only_single_req_per_port => g_handle_only_single_req_per_port,
g_prio_num => g_prio_num,
g_num_ports => g_num_ports,
g_port_mask_bits => g_port_mask_bits )
port map(
clk_sys_i => clk_i,
rst_n_i => rst_n_i,
req_i => req,
req_full_o => req_full,
rsp_o => rsp,
rsp_ack_i => rsp_ack,
wb_i => wb_in,
wb_o => wb_out
);
rtu_idle_o <=(others => '0');
wb_in.adr(13 downto 0) <= wb_addr_i(13 downto 0);
wb_in.dat <= wb_data_i;
wb_in.sel <= wb_sel_i;
wb_in.cyc <= wb_cyc_i;
wb_in.stb <= wb_stb_i;
wb_in.we <= wb_we_i;
wb_data_o <= wb_out.dat;
wb_ack_o <= wb_out.ack;
wb_irq_o <= wb_out.int;
gen_merge_signals : for i in 0 to g_num_ports-1 generate
req(i).valid <= rq_strobe_p_i(i);
req(i).smac <= rq_smac_i(g_mac_addr_width * (i+1) - 1 downto g_mac_addr_width * i);
req(i).dmac <= rq_dmac_i(g_mac_addr_width * (i+1) - 1 downto g_mac_addr_width * i);
req(i).vid <= rq_vid_i(g_vid_num_width * (i+1) - 1 downto g_vid_num_width * i);
req(i).prio <= rq_prio_i(g_prio_num_width * (i+1) - 1 downto g_prio_num_width * i);
req(i).has_prio <= rq_has_prio_i(i);
req(i).has_vid <= rq_has_vid_i(i);
rsp_valid_o(i) <= rsp(i).valid;
rsp_dst_port_mask_o(g_port_mask_bits * (i+1) -1 downto g_port_mask_bits * i)<= rsp(i).port_mask(g_port_mask_bits-1 downto 0) ;
rsp_drop_o(i) <= rsp(i).drop;
rsp_ack(i) <= rsp_ack_i(i);
rsp_prio_o( g_prio_num_width * (i+1) -1 downto g_prio_num_width*i) <= rsp(i).prio;
port_full_o(i) <= req_full(i);
end generate gen_merge_signals;
end architecture; -- end of wrsw_rtu
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment