Line 1... |
Line 1... |
// $Id: fw_link_tb.v,v 1.1 2002-03-10 17:17:36 johnsonw10 Exp $
|
// $Id: fw_link_tb.v,v 1.2 2003-04-27 04:30:51 johnsonw10 Exp $
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// FIREWIRE IP Core ////
|
//// FIREWIRE IP Core ////
|
//// ////
|
//// ////
|
//// This file is part of the firewire project ////
|
//// This file is part of the firewire project ////
|
Line 44... |
Line 44... |
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//
|
//
|
// CVS Revision History
|
// CVS Revision History
|
//
|
//
|
// $Log: not supported by cvs2svn $
|
// $Log: not supported by cvs2svn $
|
|
// Revision 1.1 2002/03/10 17:17:36 johnsonw10
|
|
// Initail revision. Top level test bench.
|
|
//
|
//
|
//
|
//
|
//
|
|
|
/**********************************************************************
|
/**********************************************************************
|
Design Notes:
|
Design Notes:
|
Line 63... |
Line 66... |
|
|
// synopsys translate_off
|
// synopsys translate_off
|
`include "timescale.v"
|
`include "timescale.v"
|
// synopsys translate_on
|
// synopsys translate_on
|
|
|
|
`include "fw_link_defines.vh"
|
|
|
module fw_link_tb;
|
module fw_link_tb;
|
|
|
|
parameter BUF_SIZE = 64;
|
reg reset_n;
|
reg reset_n;
|
reg sclk;
|
reg sclk;
|
|
|
wire [0:7] d;
|
wire [0:7] d;
|
wire [0:1] ctl;
|
wire [0:1] ctl;
|
Line 76... |
Line 82... |
wire [0:3] phy_reg_addr;
|
wire [0:3] phy_reg_addr;
|
wire [0:7] phy_reg_data;
|
wire [0:7] phy_reg_data;
|
|
|
wire [0:31] grxf_data, atxf_data, itxf_data;
|
wire [0:31] grxf_data, atxf_data, itxf_data;
|
|
|
|
integer pkt_type;
|
|
|
reg [0:31] selfid_data;
|
reg [0:31] selfid_data;
|
|
reg [0:3] ack_code;
|
|
|
// host interface
|
// host interface
|
reg [0:7] host_addr;
|
reg [0:7] host_addr;
|
wire [0:31] host_data;
|
wire [0:31] host_data;
|
reg [0:31] host_data_out; // driven by the host
|
reg [0:31] host_data_out; // driven by the host
|
|
|
reg host_cs_n, host_wr_n;
|
reg host_cs_n, host_wr_n;
|
reg [0:31] rcv_buf[0:63];
|
reg [0:31] send_buf[0:BUF_SIZE-1];
|
reg [0:31] send_buf[0:63];
|
reg [0:31] exp_buf[0:BUF_SIZE-1];
|
|
|
reg [0:7] phy_d;
|
wire [0:7] phy_d;
|
reg [0:1] phy_ctl;
|
wire [0:1] phy_ctl;
|
reg phy_oe;
|
|
|
|
reg [0:15] status_data;
|
reg [0:15] status, exp_status, rcvd_status;
|
|
|
integer grxf_data_num;
|
integer rcvd_ql_num, exp_ql_num;
|
|
|
reg [0:31] atxf_din;
|
reg [0:31] atxf_din;
|
reg atxf_wr;
|
reg atxf_wr;
|
|
|
reg [0:31] itxf_din;
|
reg [0:31] itxf_din;
|
reg itxf_wr;
|
reg itxf_wr;
|
|
|
reg set_arb_won;
|
// 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
|
initial begin
|
|
// set time format
|
|
$timeformat(-9, 1, " ns", 5);
|
|
err_count = 0;
|
reset_n = 1;
|
reset_n = 1;
|
host_cs_n = 1;
|
host_cs_n = 1;
|
host_wr_n = 1;
|
host_wr_n = 1;
|
|
|
phy_oe = 0;
|
rcvd_ql_num = 0;
|
phy_ctl = 2'b00;
|
|
phy_d = 8'h00;
|
|
grxf_data_num = 0;
|
|
atxf_wr = 0;
|
atxf_wr = 0;
|
|
|
#25 reset_n = 0;
|
#25 reset_n = 0;
|
#100 reset_n = 1;
|
#100 reset_n = 1;
|
|
|
Line 124... |
Line 142... |
host_write_reg (16'h08, 32'h0780_0000);
|
host_write_reg (16'h08, 32'h0780_0000);
|
|
|
#100;
|
#100;
|
|
|
// phy receive selfid packet #0
|
// phy receive selfid packet #0
|
|
spd = 2'b00;
|
|
pkt_type = `SELF_ID_PKT;
|
selfid_data[0:1] = 2'b01; //selfid packet identifier
|
selfid_data[0:1] = 2'b01; //selfid packet identifier
|
selfid_data[2:7] = 6'b00_0011; //sender's phy_ID
|
selfid_data[2:7] = 6'b00_0011; //sender's phy_ID
|
selfid_data[8] = 1'b0; //always 0
|
selfid_data[8] = 1'b0; //always 0
|
selfid_data[9] = 1'b1; //link_active = 1
|
selfid_data[9] = 1'b1; //link_active = 1
|
selfid_data[10:15] = 6'b01_0000; //gap_count = 10h
|
selfid_data[10:15] = 6'b01_0000; //gap_count = 10h
|
Line 139... |
Line 159... |
selfid_data[26:27] = 2'b11; //p1
|
selfid_data[26:27] = 2'b11; //p1
|
selfid_data[28:29] = 2'b11; //p2
|
selfid_data[28:29] = 2'b11; //p2
|
selfid_data[30] = 1'b0; //initiated_reset = 0
|
selfid_data[30] = 1'b0; //initiated_reset = 0
|
selfid_data[31] = 1'b0; //more_packets = 0
|
selfid_data[31] = 1'b0; //more_packets = 0
|
|
|
rcv_buf[0] = selfid_data;
|
phy_ctrl.rcv_buf[0] = selfid_data;
|
rcv_buf[1] = ~selfid_data;
|
phy_ctrl.rcv_buf[1] = ~selfid_data;
|
|
|
|
set_exp_buf (2);
|
|
|
$display ("PHY is in receive mode...");
|
phy_ctrl.phy_rcv_pkt (spd, pkt_type); //receive 2 32-bit word at 100Mbit/s
|
$display (" data 0 = %h", rcv_buf[0]);
|
|
$display (" data 1 = %h", rcv_buf[1]);
|
|
phy_rcv_pkt (2'b00, 2); //receive 2 32-bit word at 100Mbit/s
|
|
|
|
#100;
|
#100;
|
|
|
//phy status receviing self-id packet
|
//phy status
|
status_data[0] = 1'b1; // reset_gap = 1
|
status[0] = 1'b1; // reset_gap = 1
|
status_data[1] = 1'b1; // sub_gap = 1
|
status[1] = 1'b0; // sub_gap = 0
|
status_data[2] = 1'b0; // bus_reset = 0;
|
status[2] = 1'b0; // bus_reset = 0;
|
status_data[3] = 1'b0; // bus_time_out = 0;
|
status[3] = 1'b0; // bus_time_out = 0;
|
status_data[4:7] = 4'h0; // physical_id addr
|
status[4:7] = 4'h0; // physical_id addr
|
status_data[8:15] = 8'b0010_1000; // id = a, r = 0, ps = 0
|
status[8:15] = 8'b0010_1000; // id = a, r = 0, ps = 0
|
|
|
$display ("PHY is in status mode...");
|
exp_status = status;
|
$display (" status = %h", status_data);
|
phy_ctrl.phy_status (status);
|
phy_status (status_data);
|
|
|
// read request for data quadlet at 400Mbit/s
|
// read request for data quadlet at 100Mbit/s
|
phy_ctrl.arb_won = 1; //tells phy to grant the bus control
|
// phy wins arbiration case
|
spd = 2'b10;
|
set_arb_won = 1'b1;
|
tl = 6'b010101;
|
|
rt = 2'b01;
|
send_buf[0] = {16'h0000, 6'b010101, 2'b01, 4'h4, 4'h0};
|
tc = 4'h4;
|
send_buf[1] = {16'haaaa, 16'h5555};
|
pri = 4'h0;
|
send_buf[2] = 32'h1234_5678;
|
dest_id = 16'haaaa;
|
$display ("LINK is sending read request for data for quadlet");
|
dest_offset = 48'h1234_5678_9abc;
|
$display (" data 0 = %h", send_buf[0]);
|
|
$display (" data 1 = %h", send_buf[1]);
|
|
$display (" data 2 = %h", send_buf[2]);
|
|
|
|
|
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);
|
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
|
end
|
|
|
initial sclk = 0;
|
initial sclk = 0;
|
always #10 sclk = ~sclk; // 50MHz sclk
|
always #10 sclk = ~sclk; // 50MHz sclk
|
|
|
Line 208... |
Line 237... |
.din (itxf_din[0:31]),
|
.din (itxf_din[0:31]),
|
.rd (itxf_rd));
|
.rd (itxf_rd));
|
|
|
wire [0:15] src_id;
|
wire [0:15] src_id;
|
wire hard_rst = ~reset_n;
|
wire hard_rst = ~reset_n;
|
assign d = (phy_oe) ? phy_d : 8'hzz;
|
|
assign ctl = (phy_oe) ? phy_ctl : 2'bzz;
|
// 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;
|
assign host_data = host_data_out;
|
|
|
fw_link_host_if link_host_if (/*AUTOINST*/
|
fw_link_host_if link_host_if (/*AUTOINST*/
|
// Outputs
|
// Outputs
|
Line 262... |
Line 302... |
.atxf_data (atxf_data[0:31]),
|
.atxf_data (atxf_data[0:31]),
|
.itxf_ef (itxf_ef),
|
.itxf_ef (itxf_ef),
|
.itxf_data (itxf_data[0:31]),
|
.itxf_data (itxf_data[0:31]),
|
.grxf_ff (grxf_ff));
|
.grxf_ff (grxf_ff));
|
|
|
|
|
// simple phy arbitor model
|
|
// ctl pin encodings
|
|
parameter CTL_IDLE = 2'b00;
|
|
// encodings when PHY has control
|
|
parameter CTL_PHY_STATUS = 2'b01;
|
|
parameter CTL_PHY_RECEIVE = 2'b10;
|
|
parameter CTL_PHY_TRANSMIT = 2'b11;
|
|
// encodings when link has control
|
|
parameter CTL_LINK_HOLD = 2'b01;
|
|
parameter CTL_LINK_TRANSMIT = 2'b10;
|
|
parameter CTL_LINK_UNUSED = 2'b11;
|
|
|
|
wire lreq_sent;
|
wire lreq_sent;
|
|
|
assign lreq_sent = link_ctrl.link_req.req_sent;
|
assign phy_ctrl.lreq_rcvd = link_ctrl.link_req.req_sent;
|
|
|
always begin
|
|
wait (lreq_sent);
|
|
repeat (10) @ (posedge sclk); // wait for 10 clock cycles
|
|
|
|
if (set_arb_won) begin
|
|
// send arb won sequence on ctl pin
|
|
@ (posedge sclk);
|
|
phy_oe = 1'b1;
|
|
phy_ctl = CTL_PHY_TRANSMIT;
|
|
@ (posedge sclk);
|
|
phy_ctl = CTL_IDLE;
|
|
// release control of ctl and d
|
|
@ (posedge sclk);
|
|
phy_oe = 1'b0;
|
|
end
|
|
else begin
|
|
// send arb lose sequence on ctl pin
|
|
@ (posedge sclk);
|
|
phy_oe = 1'b1;
|
|
phy_ctl = CTL_PHY_RECEIVE;
|
|
@ (posedge sclk);
|
|
phy_ctl = CTL_IDLE;
|
|
end
|
|
end
|
|
|
|
|
|
|
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
|
// grxf monitor
|
always @ (posedge sclk) begin : grxf_monitor
|
always @ (posedge sclk) begin : grxf_monitor
|
if (grxf_we) begin
|
if (grxf_we) begin
|
$display ("===>Writing GRXF data[%d] = %h", grxf_data_num, grxf_data);
|
$display ("STATUS @%t: %m: received quadlet %0d = %x",
|
grxf_data_num <= grxf_data_num + 1;
|
$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
|
end
|
end
|
|
|
// status monitor
|
// status monitor
|
always @ (posedge sclk) begin : status_monitor
|
always @ (posedge sclk) begin : status_monitor
|
if (status_rcvd) begin
|
if (status_rcvd) begin
|
$display ("===>Received status = %h", {arb_reset_gap, sub_gap,
|
rcvd_status = {arb_reset_gap, sub_gap, bus_reset, state_time_out,
|
bus_reset, state_time_out,
|
phy_reg_addr, phy_reg_data};
|
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 (" arb_reset_gap = %h", arb_reset_gap);
|
$display (" sub_gap = %h", sub_gap);
|
$display (" sub_gap = %h", sub_gap);
|
$display (" bus_reset = %h", bus_reset);
|
$display (" bus_reset = %h", bus_reset);
|
$display (" state_time_out = %h", state_time_out);
|
$display (" state_time_out = %h", state_time_out);
|
$display (" phy_reg_addr = %h", phy_reg_addr);
|
$display (" phy_reg_addr = %h", phy_reg_addr);
|
$display (" phy_reg_data = %h", phy_reg_data);
|
$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
|
end
|
end
|
|
|
`include "fw_phy_tasks.v"
|
|
`include "fw_host_tasks.v"
|
`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
|
endmodule // fw_link_tb
|
|
|
// Local Variables:
|
// Local Variables:
|
// verilog-library-directories:("." "../../rtl/verilog")
|
// verilog-library-directories:("." "../../rtl/verilog")
|
// End:
|
// End:
|
No newline at end of file
|
No newline at end of file
|