OpenCores
URL https://opencores.org/ocsvn/firewire/firewire/trunk

Subversion Repositories firewire

[/] [firewire/] [trunk/] [bench/] [verilog/] [fw_link_tb.v] - Rev 22

Compare with Previous | Blame | View Log

// $Id: fw_link_tb.v,v 1.2 2003-04-27 04:30:51 johnsonw10 Exp $
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// FIREWIRE IP Core                                             ////
////                                                              ////
//// This file is part of the firewire project                    ////
//// http://www.opencores.org/cores/firewire/                     ////
////                                                              ////
//// Description                                                  ////
//// Implementation of firewire IP core according to              ////
//// firewire IP core specification document.                     ////
////                                                              ////
//// To Do:                                                       ////
//// -                                                            ////
////                                                              ////
//// Author(s):                                                   ////
//// - johnsonw10@opencores.org                                   ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2001 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// 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.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.1  2002/03/10 17:17:36  johnsonw10
// Initail revision. Top level test bench.
//
//
//
 
/**********************************************************************
  Design Notes:
  1. Startup sequence:
     * hard reset
     * set all enable signals
     * PHY receives self ID packet
     * PHY status receiving of self ID packet (PHYID write)
     * 
     * 
     * 
***********************************************************************/
 
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
 
`include "fw_link_defines.vh"
 
module fw_link_tb;
 
parameter BUF_SIZE = 64;
reg reset_n;
reg sclk;
 
wire [0:7] d;
wire [0:1] ctl;
 
wire [0:3] phy_reg_addr;
wire [0:7] phy_reg_data;
 
wire [0:31] grxf_data, atxf_data, itxf_data;
 
integer pkt_type;
 
reg [0:31] selfid_data;
reg [0:3] ack_code;
 
// host interface
reg [0:7]  host_addr;
wire [0:31] host_data;
reg  [0:31] host_data_out;  // driven by the host
 
reg        host_cs_n, host_wr_n;
reg [0:31] send_buf[0:BUF_SIZE-1];
reg [0:31] exp_buf[0:BUF_SIZE-1];
 
wire [0:7]  phy_d;
wire [0:1]  phy_ctl;
 
reg [0:15] status, exp_status, rcvd_status;
 
integer rcvd_ql_num, exp_ql_num;
 
reg [0:31] atxf_din;
reg        atxf_wr;
 
reg [0:31] itxf_din;
reg        itxf_wr;
 
// packet fields
reg [0:1] spd;
reg [0:5] tl;
reg [0:1] rt;
reg [0:3] tc;
reg [0:3] pri;
reg [0:15] dest_id;
reg [0:47] dest_offset;
 
reg err_count;
 
 
initial begin
    // set time format
    $timeformat(-9, 1, " ns", 5);
    err_count = 0;
    reset_n = 1;
    host_cs_n = 1;
    host_wr_n = 1;
 
    rcvd_ql_num = 0;
    atxf_wr = 0;
 
    #25 reset_n = 0;
    #100 reset_n = 1;
 
 
    // enable link_op (set bits 5, 6, 7, 8 @ 0x08)
    host_write_reg (16'h08, 32'h0780_0000);
 
    #100;
 
    // phy receive selfid packet #0
    spd = 2'b00;
    pkt_type = `SELF_ID_PKT;
    selfid_data[0:1]   = 2'b01;          //selfid packet identifier
    selfid_data[2:7]   = 6'b00_0011;     //sender's phy_ID
    selfid_data[8]     = 1'b0;           //always 0
    selfid_data[9]     = 1'b1;           //link_active = 1
    selfid_data[10:15] = 6'b01_0000;     //gap_count = 10h
    selfid_data[16:17] = 2'b00;          //phy_speed = 100Mbit/s
    selfid_data[18:19] = 2'b00;          //phy_delay <= 144ns
    selfid_data[20]    = 1'b0;           //contender = 0
    selfid_data[21:23] = 3'b000;         //power_class = 0;
    selfid_data[24:25] = 2'b11;          //p0;
    selfid_data[26:27] = 2'b11;          //p1
    selfid_data[28:29] = 2'b11;          //p2
    selfid_data[30]    = 1'b0;           //initiated_reset = 0
    selfid_data[31]    = 1'b0;           //more_packets = 0
 
    phy_ctrl.rcv_buf[0] = selfid_data;
    phy_ctrl.rcv_buf[1] = ~selfid_data;
 
    set_exp_buf (2);
 
    phy_ctrl.phy_rcv_pkt (spd, pkt_type);     //receive 2 32-bit word at 100Mbit/s
 
    #100;
 
    //phy status
    status[0]    = 1'b1;     // reset_gap = 1
    status[1]    = 1'b0;     // sub_gap = 0
    status[2]    = 1'b0;     // bus_reset = 0;
    status[3]    = 1'b0;     // bus_time_out = 0;
    status[4:7]  = 4'h0;     // physical_id addr
    status[8:15] = 8'b0010_1000;  // id = a, r = 0, ps = 0
 
    exp_status = status;
    phy_ctrl.phy_status (status);
 
    // read request for data quadlet at 400Mbit/s
    phy_ctrl.arb_won = 1;  //tells phy to grant the bus control
    spd = 2'b10;
    tl = 6'b010101;
    rt = 2'b01;
    tc = 4'h4;
    pri = 4'h0;
    dest_id = 16'haaaa;
    dest_offset = 48'h1234_5678_9abc;
 
    phy_ctrl.send_ack = 1; //tells phy to send back ack pakcet
    set_send_buf (3);
 
    $display ("STATUS @%t: %m: sending read request for data for quadlet", 
	      $time);
    host_write_atxf (3);
 
    // dest sends back ack packet
    wait (phy_ctrl.pkt_sent);
    spd = 2'b10;
    pkt_type = `ACK_PKT;
    ack_code = `ACK_COMPLETE;
    phy_ctrl.rcv_buf[0] = {ack_code, ~ack_code, 24'h00_0000};
    phy_ctrl.phy_rcv_pkt(spd, pkt_type);
 
end
 
initial sclk = 0;
always #10 sclk = ~sclk;   // 50MHz sclk
 
// atx FIFO
fifo_beh atxf (
	       // Outputs
	       .dout			(atxf_data[0:31]),
	       .empty			(atxf_ef),
	       .full			(atxf_ff),
	       // Inputs
	       .reset_n			(reset_n),
	       .clk			(sclk),
	       .wr			(atxf_wr),
	       .din			(atxf_din[0:31]),
	       .rd			(atxf_rd));
 
// itx FIFO
fifo_beh itxf (
	       // Outputs
	       .dout			(itxf_data[0:31]),
	       .empty			(itxf_ef),
	       .full			(itxf_ff),
	       // Inputs
	       .reset_n			(reset_n),
	       .clk			(sclk),
	       .wr			(itxf_wr),
	       .din			(itxf_din[0:31]),
	       .rd			(itxf_rd));
 
wire [0:15] src_id;
wire hard_rst = ~reset_n;
 
// bi-directional d and ctl buses
tran tran_d0 (d[0], phy_d[0]);
tran tran_d1 (d[1], phy_d[1]);
tran tran_d2 (d[2], phy_d[2]);
tran tran_d3 (d[3], phy_d[3]);
tran tran_d4 (d[4], phy_d[4]);
tran tran_d5 (d[5], phy_d[5]);
tran tran_d6 (d[6], phy_d[6]);
tran tran_d7 (d[7], phy_d[7]);
 
tran tran_ctl0(ctl[0], phy_ctl[0]);
tran tran_ctl1(ctl[1], phy_ctl[1]);
 
assign host_data = host_data_out;
 
fw_link_host_if link_host_if (/*AUTOINST*/
			      // Outputs
			      .src_id	(src_id[0:15]),
			      .tx_asy_en(tx_asy_en),
			      .rx_asy_en(rx_asy_en),
			      .tx_iso_en(tx_iso_en),
			      .rx_iso_en(rx_iso_en),
			      .soft_rst	(soft_rst),
			      // Inouts
			      .host_data(host_data[0:31]),
			      // Inputs
			      .hard_rst	(hard_rst),
			      .sclk	(sclk),
			      .host_cs_n(host_cs_n),
			      .host_wr_n(host_wr_n),
			      .host_addr(host_addr[0:7]));
 
fw_link_ctrl link_ctrl (/*AUTOINST*/
			// Outputs
			.lreq		(lreq),
			.status_rcvd	(status_rcvd),
			.arb_reset_gap	(arb_reset_gap),
			.sub_gap	(sub_gap),
			.bus_reset	(bus_reset),
			.state_time_out	(state_time_out),
			.phy_reg_addr	(phy_reg_addr[0:3]),
			.phy_reg_data	(phy_reg_data[0:7]),
			.atxf_rd	(atxf_rd),
			.itxf_rd	(itxf_rd),
			.grxf_we	(grxf_we),
			.grxf_data	(grxf_data[0:31]),
			// Inouts
			.d		(d[0:7]),
			.ctl		(ctl[0:1]),
			// Inputs
			.hard_rst	(hard_rst),
			.sclk		(sclk),
			.src_id		(src_id[0:15]),
			.soft_rst	(soft_rst),
			.tx_asy_en	(tx_asy_en),
			.rx_asy_en	(rx_asy_en),
			.tx_iso_en	(tx_iso_en),
			.rx_iso_en	(rx_iso_en),
			.atxf_ef	(atxf_ef),
			.atxf_data	(atxf_data[0:31]),
			.itxf_ef	(itxf_ef),
			.itxf_data	(itxf_data[0:31]),
			.grxf_ff	(grxf_ff));
 
wire lreq_sent;
 
assign phy_ctrl.lreq_rcvd = link_ctrl.link_req.req_sent;
 
defparam phy_ctrl.BUF_SIZE = BUF_SIZE;
fw_phy_ctrl phy_ctrl (/*AUTOINST*/
		      // Inouts
		      .phy_ctl		(phy_ctl[0:1]),
		      .phy_d		(phy_d[0:7]),
		      // Inputs
		      .sclk		(sclk));
 
// grxf monitor
always @ (posedge sclk) begin : grxf_monitor
    if (grxf_we) begin
	$display ("STATUS @%t: %m: received quadlet %0d = %x", 
		  $time, rcvd_ql_num, grxf_data);
	if (grxf_data != exp_buf[rcvd_ql_num]) begin
	    $display ("ERROR @%t: %m: incorrect quadlet %0d received:", 
		      $time, rcvd_ql_num);
	    $display ("        expected: %x", exp_buf[rcvd_ql_num]);
	    $display ("        received: %x", grxf_data);
 
	    err_count = err_count + 1;
	end
 
	rcvd_ql_num = (rcvd_ql_num == exp_ql_num) ? 0 : (rcvd_ql_num + 1);
    end
end
 
// status monitor
always @ (posedge sclk) begin : status_monitor
    if (status_rcvd) begin
	rcvd_status = {arb_reset_gap, sub_gap, bus_reset, state_time_out, 
		       phy_reg_addr, phy_reg_data};
	$display ("STATUS @%t: %m: received phy status = %x", 
		  $time, rcvd_status);
	$display ("    arb_reset_gap = %h", arb_reset_gap);
	$display ("    sub_gap = %h", sub_gap);
	$display ("    bus_reset = %h", bus_reset);
	$display ("    state_time_out = %h", state_time_out);
	$display ("    phy_reg_addr = %h", phy_reg_addr);
	$display ("    phy_reg_data = %h", phy_reg_data);
 
	if (exp_status != rcvd_status) begin
	    $display ("ERROR @%t: %m: incorrect phy status received:", $time);
	    $display ("        expected: %x", exp_status);
	    $display ("        received: %x", rcvd_status);
 
	    err_count = err_count + 1;
	end
    end
end
 
`include "fw_host_tasks.v"
 
task set_send_buf;
input ql_num;
integer ql_num;
 
begin
    send_buf[0] = {14'h0000, spd, tl, rt, tc, pri};
    send_buf[1] = {dest_id, dest_offset[0:15]};
    send_buf[2] = dest_offset[16:47];
 
    // set exp_buf for the checker
    phy_ctrl.tx_spd     = spd;
    phy_ctrl.exp_ql_num = ql_num + 1;
    phy_ctrl.exp_buf[0] = {dest_id, tl, rt, tc, pri};
    phy_ctrl.exp_buf[1] = {src_id, dest_offset[0:15]};
    phy_ctrl.exp_buf[2] = dest_offset[16:47];
    phy_ctrl.exp_buf[3] = gen_crc(ql_num);
end
endtask // set_send_buf
 
task set_exp_buf;
input ql_num;
integer ql_num;
begin
    exp_ql_num = 2;
    exp_buf[0] = phy_ctrl.rcv_buf[0];
    exp_buf[1] = phy_ctrl.rcv_buf[1];
end
endtask // set_exp_buf
 
// CRC32 generation function
parameter MSB32       = 32'h8000_0000;
parameter CRC_COMPUTE = 32'h04c1_1db7;
parameter CRC_RESULTs = 32'hc704_dd7b;
 
function [0:31] gen_crc;
input ql_num;
integer ql_num;
 
reg [0:31] crc_sum;
reg [0:31] mask;
reg        new_bit, old_bit, sum_bit;
 
integer i;
integer in_ql;
begin
    crc_sum = 32'hffff_ffff;
    for (i = 0; i < ql_num; i = i + 1) begin
	in_ql = phy_ctrl.exp_buf[i];
	for (mask = MSB32; mask != 0; mask = mask >> 1) begin
	    new_bit = ((in_ql & mask) != 32'h0000_0000);
	    old_bit = ((crc_sum & MSB32) != 32'h0000_0000);
	    sum_bit = old_bit ^ new_bit;
 
	    // update crc_sum
	    crc_sum = (crc_sum << 1) ^ (sum_bit ? CRC_COMPUTE : 0);
	end // (mask = MSB32; mask != 0; mask = mask >> 1)
    end //for (i = 0; i < ql_num, i = i + 1)
 
    gen_crc = crc_sum;
end
endfunction
 
endmodule // fw_link_tb
 
// Local Variables:
// verilog-library-directories:("." "../../rtl/verilog")
// End:

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.