//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// can_testbench.v ////
|
//// can_testbench.v ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//// This file is part of the CAN Protocol Controller ////
|
//// This file is part of the CAN Protocol Controller ////
|
//// http://www.opencores.org/projects/can/ ////
|
//// http://www.opencores.org/projects/can/ ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// Igor Mohor ////
|
//// Igor Mohor ////
|
//// igorm@opencores.org ////
|
//// igorm@opencores.org ////
|
//// ////
|
//// ////
|
//// ////
|
//// ////
|
//// All additional information is available in the README.txt ////
|
//// All additional information is available in the README.txt ////
|
//// file. ////
|
//// file. ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2002, 2003 Authors ////
|
//// Copyright (C) 2002, 2003 Authors ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
|
//// The CAN protocol is developed by Robert Bosch GmbH and ////
|
|
//// protected by patents. Anybody who wants to implement this ////
|
|
//// CAN IP core on silicon has to obtain a CAN protocol license ////
|
|
//// from Bosch. ////
|
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//
|
//
|
// CVS Revision History
|
// CVS Revision History
|
//
|
//
|
// $Log: not supported by cvs2svn $
|
// $Log: not supported by cvs2svn $
|
|
// Revision 1.19 2003/02/04 17:24:33 mohor
|
|
// Backup.
|
|
//
|
// Revision 1.18 2003/02/04 14:34:45 mohor
|
// Revision 1.18 2003/02/04 14:34:45 mohor
|
// *** empty log message ***
|
// *** empty log message ***
|
//
|
//
|
// Revision 1.17 2003/01/31 01:13:31 mohor
|
// Revision 1.17 2003/01/31 01:13:31 mohor
|
// backup.
|
// backup.
|
//
|
//
|
// Revision 1.16 2003/01/16 13:36:14 mohor
|
// Revision 1.16 2003/01/16 13:36:14 mohor
|
// Form error supported. When receiving messages, last bit of the end-of-frame
|
// Form error supported. When receiving messages, last bit of the end-of-frame
|
// does not generate form error. Receiver goes to the idle mode one bit sooner.
|
// does not generate form error. Receiver goes to the idle mode one bit sooner.
|
// (CAN specification ver 2.0, part B, page 57).
|
// (CAN specification ver 2.0, part B, page 57).
|
//
|
//
|
// Revision 1.15 2003/01/15 21:05:06 mohor
|
// Revision 1.15 2003/01/15 21:05:06 mohor
|
// CRC checking fixed (when bitstuff occurs at the end of a CRC sequence).
|
// CRC checking fixed (when bitstuff occurs at the end of a CRC sequence).
|
//
|
//
|
// Revision 1.14 2003/01/15 14:40:16 mohor
|
// Revision 1.14 2003/01/15 14:40:16 mohor
|
// RX state machine fixed to receive "remote request" frames correctly. No data bytes are written to fifo when such frames are received.
|
// RX state machine fixed to receive "remote request" frames correctly. No data bytes are written to fifo when such frames are received.
|
//
|
//
|
// Revision 1.13 2003/01/15 13:16:42 mohor
|
// Revision 1.13 2003/01/15 13:16:42 mohor
|
// When a frame with "remote request" is received, no data is stored to fifo, just the frame information (identifier, ...). Data length that is stored is the received data length and not the actual data length that is stored to fifo.
|
// When a frame with "remote request" is received, no data is stored to fifo, just the frame information (identifier, ...). Data length that is stored is the received data length and not the actual data length that is stored to fifo.
|
//
|
//
|
// Revision 1.12 2003/01/14 17:25:03 mohor
|
// Revision 1.12 2003/01/14 17:25:03 mohor
|
// Addresses corrected to decimal values (previously hex).
|
// Addresses corrected to decimal values (previously hex).
|
//
|
//
|
// Revision 1.11 2003/01/14 12:19:29 mohor
|
// Revision 1.11 2003/01/14 12:19:29 mohor
|
// rx_fifo is now working.
|
// rx_fifo is now working.
|
//
|
//
|
// Revision 1.10 2003/01/10 17:51:28 mohor
|
// Revision 1.10 2003/01/10 17:51:28 mohor
|
// Temporary version (backup).
|
// Temporary version (backup).
|
//
|
//
|
// Revision 1.9 2003/01/09 21:54:39 mohor
|
// Revision 1.9 2003/01/09 21:54:39 mohor
|
// rx fifo added. Not 100 % verified, yet.
|
// rx fifo added. Not 100 % verified, yet.
|
//
|
//
|
// Revision 1.8 2003/01/08 02:09:43 mohor
|
// Revision 1.8 2003/01/08 02:09:43 mohor
|
// Acceptance filter added.
|
// Acceptance filter added.
|
//
|
//
|
// Revision 1.7 2002/12/28 04:13:53 mohor
|
// Revision 1.7 2002/12/28 04:13:53 mohor
|
// Backup version.
|
// Backup version.
|
//
|
//
|
// Revision 1.6 2002/12/27 00:12:48 mohor
|
// Revision 1.6 2002/12/27 00:12:48 mohor
|
// Header changed, testbench improved to send a frame (crc still missing).
|
// Header changed, testbench improved to send a frame (crc still missing).
|
//
|
//
|
// Revision 1.5 2002/12/26 16:00:29 mohor
|
// Revision 1.5 2002/12/26 16:00:29 mohor
|
// Testbench define file added. Clock divider register added.
|
// Testbench define file added. Clock divider register added.
|
//
|
//
|
// Revision 1.4 2002/12/26 01:33:01 mohor
|
// Revision 1.4 2002/12/26 01:33:01 mohor
|
// Tripple sampling supported.
|
// Tripple sampling supported.
|
//
|
//
|
// Revision 1.3 2002/12/25 23:44:12 mohor
|
// Revision 1.3 2002/12/25 23:44:12 mohor
|
// Commented lines removed.
|
// Commented lines removed.
|
//
|
//
|
// Revision 1.2 2002/12/25 14:16:54 mohor
|
// Revision 1.2 2002/12/25 14:16:54 mohor
|
// Synchronization working.
|
// Synchronization working.
|
//
|
//
|
// Revision 1.1.1.1 2002/12/20 16:39:21 mohor
|
// Revision 1.1.1.1 2002/12/20 16:39:21 mohor
|
// Initial
|
// Initial
|
//
|
//
|
//
|
//
|
//
|
//
|
|
|
// synopsys translate_off
|
// synopsys translate_off
|
`include "timescale.v"
|
`include "timescale.v"
|
// synopsys translate_on
|
// synopsys translate_on
|
`include "can_defines.v"
|
`include "can_defines.v"
|
`include "can_testbench_defines.v"
|
`include "can_testbench_defines.v"
|
|
|
module can_testbench();
|
module can_testbench();
|
|
|
|
|
|
|
parameter Tp = 1;
|
parameter Tp = 1;
|
parameter BRP = 2*(`CAN_TIMING0_BRP + 1);
|
parameter BRP = 2*(`CAN_TIMING0_BRP + 1);
|
|
|
|
|
|
|
reg clk;
|
reg clk;
|
reg rst;
|
reg rst;
|
reg [7:0] data_in;
|
reg [7:0] data_in;
|
wire [7:0] data_out;
|
wire [7:0] data_out;
|
reg cs, rw;
|
reg cs, rw;
|
reg [7:0] addr;
|
reg [7:0] addr;
|
reg rx;
|
reg rx;
|
wire tx;
|
wire tx;
|
|
wire tx_oen;
|
|
wire tx_3st;
|
wire rx_and_tx;
|
wire rx_and_tx;
|
|
|
integer start_tb;
|
integer start_tb;
|
reg [7:0] tmp_data;
|
reg [7:0] tmp_data;
|
reg delayed_tx;
|
reg delayed_tx;
|
|
reg tx_bypassed;
|
|
|
|
|
// Instantiate can_top module
|
// Instantiate can_top module
|
can_top i_can_top
|
can_top i_can_top
|
(
|
(
|
.clk(clk),
|
.clk(clk),
|
.rst(rst),
|
.rst(rst),
|
.data_in(data_in),
|
.data_in(data_in),
|
.data_out(data_out),
|
.data_out(data_out),
|
.cs(cs),
|
.cs(cs),
|
.rw(rw),
|
.rw(rw),
|
.addr(addr),
|
.addr(addr),
|
.rx(rx_and_tx),
|
.rx(rx_and_tx),
|
.tx(tx)
|
.tx(tx),
|
|
.tx_oen(tx_oen)
|
);
|
);
|
|
|
|
assign tx_3st = tx_oen? 1'bz : tx;
|
|
|
|
|
// Generate clock signal 24 MHz
|
// Generate clock signal 24 MHz
|
initial
|
initial
|
begin
|
begin
|
clk=0;
|
clk=0;
|
forever #20 clk = ~clk;
|
forever #20 clk = ~clk;
|
end
|
end
|
|
|
initial
|
initial
|
begin
|
begin
|
start_tb = 0;
|
start_tb = 0;
|
data_in = 'hz;
|
data_in = 'hz;
|
cs = 0;
|
cs = 0;
|
rw = 'hz;
|
rw = 'hz;
|
addr = 'hz;
|
addr = 'hz;
|
rx = 1;
|
rx = 1;
|
rst = 1;
|
rst = 1;
|
#200 rst = 0;
|
#200 rst = 0;
|
#200 initialize_fifo;
|
#200 initialize_fifo;
|
#200 start_tb = 1;
|
#200 start_tb = 1;
|
|
tx_bypassed = 0;
|
end
|
end
|
|
|
|
|
|
|
|
|
// Generating delayed tx signal (CAN transciever delay)
|
// Generating delayed tx signal (CAN transciever delay)
|
always
|
always
|
begin
|
begin
|
wait (tx);
|
wait (tx_3st);
|
repeat (4*BRP) @ (posedge clk); // 4 time quants delay
|
repeat (4*BRP) @ (posedge clk); // 4 time quants delay
|
#1 delayed_tx = tx;
|
#1 delayed_tx = tx_3st;
|
wait (~tx);
|
wait (~tx_3st);
|
repeat (4*BRP) @ (posedge clk); // 4 time quants delay
|
repeat (4*BRP) @ (posedge clk); // 4 time quants delay
|
#1 delayed_tx = tx;
|
#1 delayed_tx = tx_3st;
|
end
|
end
|
|
|
assign rx_and_tx = rx & delayed_tx;
|
//assign rx_and_tx = rx & delayed_tx; FIX ME !!!
|
|
assign rx_and_tx = rx & (delayed_tx | tx_bypassed);
|
|
|
|
|
// Main testbench
|
// Main testbench
|
initial
|
initial
|
begin
|
begin
|
wait(start_tb);
|
wait(start_tb);
|
|
|
// Set bus timing register 0
|
// Set bus timing register 0
|
write_register(8'd6, {`CAN_TIMING0_SJW, `CAN_TIMING0_BRP});
|
write_register(8'd6, {`CAN_TIMING0_SJW, `CAN_TIMING0_BRP});
|
|
|
// Set bus timing register 1
|
// Set bus timing register 1
|
write_register(8'd7, {`CAN_TIMING1_SAM, `CAN_TIMING1_TSEG2, `CAN_TIMING1_TSEG1});
|
write_register(8'd7, {`CAN_TIMING1_SAM, `CAN_TIMING1_TSEG2, `CAN_TIMING1_TSEG1});
|
|
|
|
|
|
|
// Set Clock Divider register
|
// Set Clock Divider register
|
write_register(8'd31, {`CAN_CLOCK_DIVIDER_MODE, 7'h0}); // Setting the normal mode (not extended)
|
write_register(8'd31, {`CAN_CLOCK_DIVIDER_MODE, 7'h0}); // Setting the normal mode (not extended)
|
|
|
// Set Acceptance Code and Acceptance Mask registers (their address differs for basic and extended mode
|
// Set Acceptance Code and Acceptance Mask registers (their address differs for basic and extended mode
|
if(`CAN_CLOCK_DIVIDER_MODE) // Extended mode
|
if(`CAN_CLOCK_DIVIDER_MODE) // Extended mode
|
begin
|
begin
|
// Set Acceptance Code and Acceptance Mask registers
|
// Set Acceptance Code and Acceptance Mask registers
|
write_register(8'd16, 8'ha6); // acceptance code 0
|
write_register(8'd16, 8'ha6); // acceptance code 0
|
write_register(8'd17, 8'hb0); // acceptance code 1
|
write_register(8'd17, 8'hb0); // acceptance code 1
|
write_register(8'd18, 8'h12); // acceptance code 2
|
write_register(8'd18, 8'h12); // acceptance code 2
|
write_register(8'd19, 8'h30); // acceptance code 3
|
write_register(8'd19, 8'h30); // acceptance code 3
|
write_register(8'd20, 8'h0); // acceptance mask 0
|
write_register(8'd20, 8'h0); // acceptance mask 0
|
write_register(8'd21, 8'h0); // acceptance mask 1
|
write_register(8'd21, 8'h0); // acceptance mask 1
|
write_register(8'd22, 8'h00); // acceptance mask 2
|
write_register(8'd22, 8'h00); // acceptance mask 2
|
write_register(8'd23, 8'h00); // acceptance mask 3
|
write_register(8'd23, 8'h00); // acceptance mask 3
|
end
|
end
|
else
|
else
|
begin
|
begin
|
// Set Acceptance Code and Acceptance Mask registers
|
// Set Acceptance Code and Acceptance Mask registers
|
// write_register(8'd4, 8'ha6); // acceptance code
|
// write_register(8'd4, 8'ha6); // acceptance code
|
write_register(8'd4, 8'he8); // acceptance code
|
write_register(8'd4, 8'he8); // acceptance code
|
write_register(8'd5, 8'h0f); // acceptance mask
|
write_register(8'd5, 8'h0f); // acceptance mask
|
end
|
end
|
|
|
#10;
|
#10;
|
repeat (1000) @ (posedge clk);
|
repeat (1000) @ (posedge clk);
|
|
|
// Switch-off reset mode
|
// Switch-off reset mode
|
write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});
|
write_register(8'd0, {7'h0, ~(`CAN_MODE_RESET)});
|
|
|
repeat (BRP) @ (posedge clk); // At least BRP clocks needed before bus goes to dominant level. Otherwise 1 quant difference is possible
|
repeat (BRP) @ (posedge clk); // At least BRP clocks needed before bus goes to dominant level. Otherwise 1 quant difference is possible
|
// This difference is resynchronized later.
|
// This difference is resynchronized later.
|
|
|
// After exiting the reset mode
|
// After exiting the reset mode
|
repeat (7) send_bit(1); // Sending EOF
|
repeat (7) send_bit(1); // Sending EOF
|
repeat (3) send_bit(1); // Sending Interframe
|
repeat (3) send_bit(1); // Sending Interframe
|
|
|
// test_synchronization;
|
// test_synchronization;
|
|
|
|
|
|
|
if(`CAN_CLOCK_DIVIDER_MODE) // Extended mode
|
if(`CAN_CLOCK_DIVIDER_MODE) // Extended mode
|
begin
|
begin
|
// test_empty_fifo_ext; // test currently switched off
|
// test_empty_fifo_ext; // test currently switched off
|
test_full_fifo_ext; // test currently switched on
|
test_full_fifo_ext; // test currently switched on
|
// send_frame_ext; // test currently switched off
|
// send_frame_ext; // test currently switched off
|
end
|
end
|
else
|
else
|
begin
|
begin
|
// test_empty_fifo; // test currently switched off
|
// test_empty_fifo; // test currently switched off
|
// test_full_fifo; // test currently switched off
|
// test_full_fifo; // test currently switched off
|
send_frame; // test currently switched on
|
// send_frame; // test currently switched off
|
|
manual_frame; // test currently switched on
|
end
|
end
|
|
|
|
|
$display("CAN Testbench finished !");
|
$display("CAN Testbench finished !");
|
$stop;
|
$stop;
|
end
|
end
|
|
|
|
|
|
task manual_frame; // Testbench sends a frame
|
|
begin
|
|
|
|
begin
|
|
/*
|
|
$display("\n\nTestbench sends a frame bit by bit");
|
|
send_bit(0); // SOF
|
|
send_bit(1); // ID
|
|
send_bit(1); // ID
|
|
send_bit(1); // ID
|
|
send_bit(0); // ID
|
|
send_bit(1); // ID
|
|
send_bit(0); // ID
|
|
send_bit(0); // ID
|
|
send_bit(0); // ID
|
|
send_bit(1); // ID
|
|
send_bit(0); // ID
|
|
send_bit(1); // ID
|
|
send_bit(1); // RTR
|
|
send_bit(0); // IDE
|
|
send_bit(0); // r0
|
|
send_bit(0); // DLC
|
|
send_bit(1); // DLC
|
|
send_bit(0); // DLC
|
|
send_bit(0); // DLC
|
|
send_bit(1); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(0); // CRC // error
|
|
send_bit(1); // CRC DELIM
|
|
send_bit(0); // ACK
|
|
send_bit(1); // ACK DELIM
|
|
send_bit(0); // EOF // error comes here
|
|
send_bit(0); // EOF // error comes here
|
|
|
|
//tx_bypassed=1;
|
|
send_bit(0); // EOF // error comes here
|
|
//tx_bypassed=0;
|
|
|
|
send_bit(0); // EOF // error comes here
|
|
send_bit(0); // EOF // error comes here
|
|
send_bit(0); // EOF // error comes here
|
|
send_bit(1); // EOF // delimiter
|
|
send_bit(1); // INTER // delimiter
|
|
send_bit(1); // INTER // delimiter
|
|
send_bit(1); // INTER // delimiter
|
|
send_bit(1); // IDLE // delimiter
|
|
send_bit(1); // IDLE // delimiter
|
|
send_bit(1); // IDLE // delimiter
|
|
send_bit(0); // IDLE // delimiter
|
|
send_bit(1); // IDLE // delimiter
|
|
send_bit(1); // IDLE // delimiter
|
|
send_bit(1); // IDLE // delimiter
|
|
send_bit(1); // IDLE // delimiter
|
|
send_bit(1); // IDLE // delimiter
|
|
send_bit(1); // IDLE // delimiter
|
|
send_bit(1); // IDLE
|
|
send_bit(1); // IDLE
|
|
send_bit(1); // IDLE
|
|
*/
|
|
|
|
write_register(8'd10, 8'he8); // Writing ID[10:3] = 0xe8
|
|
write_register(8'd11, 8'hb7); // Writing ID[2:0] = 0x5, rtr = 1, length = 7
|
|
write_register(8'd12, 8'h00); // data byte 1
|
|
write_register(8'd13, 8'h00); // data byte 2
|
|
write_register(8'd14, 8'h00); // data byte 3
|
|
write_register(8'd15, 8'h00); // data byte 4
|
|
write_register(8'd16, 8'h00); // data byte 5
|
|
write_register(8'd17, 8'h00); // data byte 6
|
|
write_register(8'd18, 8'h00); // data byte 7
|
|
write_register(8'd19, 8'h00); // data byte 8
|
|
end
|
|
|
|
// tx_bypassed=1;
|
|
|
|
|
|
fork
|
|
begin
|
|
tx_request;
|
|
end
|
|
|
|
begin
|
|
#520;
|
|
send_bit(0); // SOF
|
|
send_bit(1); // ID
|
|
send_bit(1); // ID
|
|
send_bit(1); // ID
|
|
send_bit(0); // ID
|
|
send_bit(1); // ID
|
|
send_bit(0); // ID
|
|
send_bit(0); // ID
|
|
send_bit(0); // ID
|
|
send_bit(1); // ID
|
|
send_bit(0); // ID
|
|
send_bit(1); // ID
|
|
send_bit(1); // RTR
|
|
send_bit(0); // IDE
|
|
send_bit(0); // r0
|
|
send_bit(0); // DLC
|
|
send_bit(1); // DLC
|
|
send_bit(1); // DLC
|
|
send_bit(1); // DLC
|
|
send_bit(1); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(0); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(1); // CRC
|
|
send_bit(1); // CRC DELIM
|
|
send_bit(0); // ACK
|
|
send_bit(1); // ACK DELIM
|
|
send_bit(1); // EOF
|
|
send_bit(1); // EOF
|
|
send_bit(1); // EOF
|
|
send_bit(1); // EOF
|
|
send_bit(1); // EOF
|
|
send_bit(1); // EOF
|
|
send_bit(1); // EOF
|
|
// tx_bypassed=1;
|
|
send_bit(1); // INTER
|
|
send_bit(1); // INTER
|
|
send_bit(1); // INTER
|
|
send_bit(1); // IDLE
|
|
send_bit(1); // IDLE
|
|
send_bit(1); // IDLE
|
|
send_bit(1); // IDLE
|
|
|
|
end
|
|
|
|
|
|
join
|
|
|
|
read_receive_buffer;
|
|
release_rx_buffer;
|
|
|
|
|
|
|
|
|
|
|
|
read_receive_buffer;
|
|
release_rx_buffer;
|
|
read_receive_buffer;
|
|
|
|
#200000;
|
|
|
|
end
|
|
endtask
|
|
|
|
|
|
|
task send_frame; // CAN IP core sends frames
|
task send_frame; // CAN IP core sends frames
|
begin
|
begin
|
|
|
if(`CAN_CLOCK_DIVIDER_MODE) // Extended mode
|
if(`CAN_CLOCK_DIVIDER_MODE) // Extended mode
|
begin
|
begin
|
|
|
// Writing TX frame information + identifier + data
|
// Writing TX frame information + identifier + data
|
write_register(8'd16, 8'h12);
|
write_register(8'd16, 8'h12);
|
write_register(8'd17, 8'h34);
|
write_register(8'd17, 8'h34);
|
write_register(8'd18, 8'h56);
|
write_register(8'd18, 8'h56);
|
write_register(8'd19, 8'h78);
|
write_register(8'd19, 8'h78);
|
write_register(8'd20, 8'h9a);
|
write_register(8'd20, 8'h9a);
|
write_register(8'd21, 8'hbc);
|
write_register(8'd21, 8'hbc);
|
write_register(8'd22, 8'hde);
|
write_register(8'd22, 8'hde);
|
write_register(8'd23, 8'hf0);
|
write_register(8'd23, 8'hf0);
|
write_register(8'd24, 8'h0f);
|
write_register(8'd24, 8'h0f);
|
write_register(8'd25, 8'hed);
|
write_register(8'd25, 8'hed);
|
write_register(8'd26, 8'hcb);
|
write_register(8'd26, 8'hcb);
|
write_register(8'd27, 8'ha9);
|
write_register(8'd27, 8'ha9);
|
write_register(8'd28, 8'h87);
|
write_register(8'd28, 8'h87);
|
end
|
end
|
else
|
else
|
begin
|
begin
|
write_register(8'd10, 8'hea); // Writing ID[10:3] = 0xea
|
write_register(8'd10, 8'hea); // Writing ID[10:3] = 0xea
|
write_register(8'd11, 8'h28); // Writing ID[3:0] = 0x1, rtr = 0, length = 8
|
write_register(8'd11, 8'h28); // Writing ID[2:0] = 0x1, rtr = 0, length = 8
|
write_register(8'd12, 8'h56); // data byte 1
|
write_register(8'd12, 8'h56); // data byte 1
|
write_register(8'd13, 8'h78); // data byte 2
|
write_register(8'd13, 8'h78); // data byte 2
|
write_register(8'd14, 8'h9a); // data byte 3
|
write_register(8'd14, 8'h9a); // data byte 3
|
write_register(8'd15, 8'hbc); // data byte 4
|
write_register(8'd15, 8'hbc); // data byte 4
|
write_register(8'd16, 8'hde); // data byte 5
|
write_register(8'd16, 8'hde); // data byte 5
|
write_register(8'd17, 8'hf0); // data byte 6
|
write_register(8'd17, 8'hf0); // data byte 6
|
write_register(8'd18, 8'h0f); // data byte 7
|
write_register(8'd18, 8'h0f); // data byte 7
|
write_register(8'd19, 8'hed); // data byte 8
|
write_register(8'd19, 8'hed); // data byte 8
|
end
|
end
|
|
|
|
|
fork
|
fork
|
begin
|
begin
|
$display("\n\nStart receiving data from CAN bus");
|
$display("\n\nStart receiving data from CAN bus");
|
receive_frame(0, 0, {26'h00000e8, 3'h1}, 4'h0, 15'h2372); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000e8, 3'h1}, 4'h0, 15'h2372); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000e8, 3'h1}, 4'h1, 15'h30bb); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000e8, 3'h1}, 4'h1, 15'h30bb); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000e8, 3'h1}, 4'h2, 15'h2da1); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000e8, 3'h1}, 4'h2, 15'h2da1); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000ee, 3'h1}, 4'h0, 15'h6cea); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000ee, 3'h1}, 4'h0, 15'h6cea); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000ee, 3'h1}, 4'h1, 15'h00c5); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000ee, 3'h1}, 4'h1, 15'h00c5); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000ee, 3'h1}, 4'h2, 15'h7b4a); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h00000ee, 3'h1}, 4'h2, 15'h7b4a); // mode, rtr, id, length, crc
|
|
|
end
|
end
|
|
|
begin
|
begin
|
tx_request;
|
tx_request;
|
end
|
end
|
|
|
begin
|
begin
|
// Transmitting acknowledge
|
// Transmitting acknowledge
|
wait (can_testbench.i_can_top.i_can_bsp.tx_state & can_testbench.i_can_top.i_can_bsp.rx_ack);
|
wait (can_testbench.i_can_top.i_can_bsp.tx_state & can_testbench.i_can_top.i_can_bsp.rx_ack);
|
rx = 0;
|
#1 rx = 0;
|
wait (can_testbench.i_can_top.i_can_bsp.rx_ack_lim);
|
wait (can_testbench.i_can_top.i_can_bsp.rx_ack_lim);
|
rx = 1;
|
#1 rx = 1;
|
end
|
end
|
|
|
join
|
join
|
|
|
read_receive_buffer;
|
read_receive_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
|
|
#200000;
|
#200000;
|
|
|
read_receive_buffer;
|
read_receive_buffer;
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
task test_empty_fifo;
|
task test_empty_fifo;
|
begin
|
begin
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h3, 15'h7bcb); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h3, 15'h7bcb); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h7, 15'h085c); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h7, 15'h085c); // mode, rtr, id, length, crc
|
|
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
|
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
task test_empty_fifo_ext;
|
task test_empty_fifo_ext;
|
begin
|
begin
|
receive_frame(1, 0, 29'h14d60246, 4'h3, 15'h5262); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h3, 15'h5262); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h7, 15'h1730); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h7, 15'h1730); // mode, rtr, id, length, crc
|
|
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
receive_frame(1, 0, 29'h14d60246, 4'h8, 15'h2f7a); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h8, 15'h2f7a); // mode, rtr, id, length, crc
|
|
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
task test_full_fifo;
|
task test_full_fifo;
|
begin
|
begin
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h0, 15'h4edd); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h0, 15'h4edd); // mode, rtr, id, length, crc
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h1, 15'h1ccf); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h1, 15'h1ccf); // mode, rtr, id, length, crc
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h2, 15'h73f4); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h2, 15'h73f4); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
read_receive_buffer;
|
read_receive_buffer;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h3, 15'h7bcb); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h3, 15'h7bcb); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h4, 15'h37da); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h4, 15'h37da); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h5, 15'h7e15); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h5, 15'h7e15); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h6, 15'h39cf); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h6, 15'h39cf); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h7, 15'h085c); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h7, 15'h085c); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
read_overrun_info(0, 15);
|
read_overrun_info(0, 15);
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
receive_frame(0, 0, {26'h0000008, 3'h1}, 4'h8, 15'h57a0); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
read_overrun_info(0, 15);
|
read_overrun_info(0, 15);
|
$display("\n\n");
|
$display("\n\n");
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
task test_full_fifo_ext;
|
task test_full_fifo_ext;
|
begin
|
begin
|
release_rx_buffer;
|
release_rx_buffer;
|
$display("\n\n");
|
$display("\n\n");
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
receive_frame(1, 0, 29'h14d60246, 4'h0, 15'h6f54); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h0, 15'h6f54); // mode, rtr, id, length, crc
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
receive_frame(1, 0, 29'h14d60246, 4'h1, 15'h6d38); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h1, 15'h6d38); // mode, rtr, id, length, crc
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
receive_frame(1, 0, 29'h14d60246, 4'h2, 15'h053e); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h2, 15'h053e); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
read_receive_buffer;
|
read_receive_buffer;
|
receive_frame(1, 0, 29'h14d60246, 4'h3, 15'h5262); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h3, 15'h5262); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(1, 0, 29'h14d60246, 4'h4, 15'h4bba); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h4, 15'h4bba); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(1, 0, 29'h14d60246, 4'h5, 15'h4d7d); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h5, 15'h4d7d); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(1, 0, 29'h14d60246, 4'h6, 15'h6f40); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h6, 15'h6f40); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
receive_frame(1, 0, 29'h14d60246, 4'h7, 15'h1730); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h7, 15'h1730); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
read_overrun_info(0, 10);
|
read_overrun_info(0, 10);
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
release_rx_buffer;
|
fifo_info;
|
fifo_info;
|
receive_frame(1, 0, 29'h14d60246, 4'h8, 15'h2f7a); // mode, rtr, id, length, crc
|
receive_frame(1, 0, 29'h14d60246, 4'h8, 15'h2f7a); // mode, rtr, id, length, crc
|
fifo_info;
|
fifo_info;
|
read_overrun_info(0, 15);
|
read_overrun_info(0, 15);
|
$display("\n\n");
|
$display("\n\n");
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
release_rx_buffer;
|
release_rx_buffer;
|
read_receive_buffer;
|
read_receive_buffer;
|
fifo_info;
|
fifo_info;
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
task initialize_fifo;
|
task initialize_fifo;
|
integer i;
|
integer i;
|
begin
|
begin
|
for (i=0; i<32; i=i+1)
|
for (i=0; i<32; i=i+1)
|
begin
|
begin
|
can_testbench.i_can_top.i_can_bsp.i_can_fifo.length_info[i] = 0;
|
can_testbench.i_can_top.i_can_bsp.i_can_fifo.length_info[i] = 0;
|
can_testbench.i_can_top.i_can_bsp.i_can_fifo.overrun_info[i] = 0;
|
can_testbench.i_can_top.i_can_bsp.i_can_fifo.overrun_info[i] = 0;
|
end
|
end
|
|
|
for (i=0; i<64; i=i+1)
|
for (i=0; i<64; i=i+1)
|
begin
|
begin
|
can_testbench.i_can_top.i_can_bsp.i_can_fifo.fifo[i] = 0;
|
can_testbench.i_can_top.i_can_bsp.i_can_fifo.fifo[i] = 0;
|
end
|
end
|
|
|
$display("(%0t) Fifo initialized", $time);
|
$display("(%0t) Fifo initialized", $time);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task read_overrun_info;
|
task read_overrun_info;
|
input [4:0] start_addr;
|
input [4:0] start_addr;
|
input [4:0] end_addr;
|
input [4:0] end_addr;
|
integer i;
|
integer i;
|
begin
|
begin
|
for (i=start_addr; i<=end_addr; i=i+1)
|
for (i=start_addr; i<=end_addr; i=i+1)
|
begin
|
begin
|
$display("len[0x%0x]=0x%0x", i, can_testbench.i_can_top.i_can_bsp.i_can_fifo.length_info[i]);
|
$display("len[0x%0x]=0x%0x", i, can_testbench.i_can_top.i_can_bsp.i_can_fifo.length_info[i]);
|
$display("overrun[0x%0x]=0x%0x\n", i, can_testbench.i_can_top.i_can_bsp.i_can_fifo.overrun_info[i]);
|
$display("overrun[0x%0x]=0x%0x\n", i, can_testbench.i_can_top.i_can_bsp.i_can_fifo.overrun_info[i]);
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task fifo_info; // Displaying how many packets and how many bytes are in fifo. Not working when wr_info_pointer is smaller than rd_info_pointer.
|
task fifo_info; // Displaying how many packets and how many bytes are in fifo. Not working when wr_info_pointer is smaller than rd_info_pointer.
|
begin
|
begin
|
$display("(%0t) Currently %0d bytes in fifo (%0d packets)", $time, can_testbench.i_can_top.i_can_bsp.i_can_fifo.fifo_cnt,
|
$display("(%0t) Currently %0d bytes in fifo (%0d packets)", $time, can_testbench.i_can_top.i_can_bsp.i_can_fifo.fifo_cnt,
|
(can_testbench.i_can_top.i_can_bsp.i_can_fifo.wr_info_pointer - can_testbench.i_can_top.i_can_bsp.i_can_fifo.rd_info_pointer));
|
(can_testbench.i_can_top.i_can_bsp.i_can_fifo.wr_info_pointer - can_testbench.i_can_top.i_can_bsp.i_can_fifo.rd_info_pointer));
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task read_register;
|
task read_register;
|
input [7:0] reg_addr;
|
input [7:0] reg_addr;
|
|
|
begin
|
begin
|
@ (posedge clk);
|
@ (posedge clk);
|
#1;
|
#1;
|
addr = reg_addr;
|
addr = reg_addr;
|
cs = 1;
|
cs = 1;
|
rw = 1;
|
rw = 1;
|
@ (posedge clk);
|
@ (posedge clk);
|
$display("(%0t) Reading register [%0d] = 0x%0x", $time, addr, data_out);
|
$display("(%0t) Reading register [%0d] = 0x%0x", $time, addr, data_out);
|
#1;
|
#1;
|
addr = 'hz;
|
addr = 'hz;
|
cs = 0;
|
cs = 0;
|
rw = 'hz;
|
rw = 'hz;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task write_register;
|
task write_register;
|
input [7:0] reg_addr;
|
input [7:0] reg_addr;
|
input [7:0] reg_data;
|
input [7:0] reg_data;
|
|
|
begin
|
begin
|
@ (posedge clk);
|
@ (posedge clk);
|
#1;
|
#1;
|
addr = reg_addr;
|
addr = reg_addr;
|
data_in = reg_data;
|
data_in = reg_data;
|
cs = 1;
|
cs = 1;
|
rw = 0;
|
rw = 0;
|
@ (posedge clk);
|
@ (posedge clk);
|
#1;
|
#1;
|
addr = 'hz;
|
addr = 'hz;
|
data_in = 'hz;
|
data_in = 'hz;
|
cs = 0;
|
cs = 0;
|
rw = 'hz;
|
rw = 'hz;
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task read_receive_buffer;
|
task read_receive_buffer;
|
integer i;
|
integer i;
|
begin
|
begin
|
if(`CAN_CLOCK_DIVIDER_MODE) // Extended mode
|
if(`CAN_CLOCK_DIVIDER_MODE) // Extended mode
|
begin
|
begin
|
for (i=8'd16; i<=8'd28; i=i+1)
|
for (i=8'd16; i<=8'd28; i=i+1)
|
read_register(i);
|
read_register(i);
|
if (can_testbench.i_can_top.i_can_bsp.i_can_fifo.overrun_info[can_testbench.i_can_top.i_can_bsp.i_can_fifo.rd_info_pointer])
|
if (can_testbench.i_can_top.i_can_bsp.i_can_fifo.overrun_info[can_testbench.i_can_top.i_can_bsp.i_can_fifo.rd_info_pointer])
|
$display("\nWARNING: This packet was received with overrun.");
|
$display("\nWARNING: This packet was received with overrun.");
|
end
|
end
|
else
|
else
|
begin
|
begin
|
for (i=8'd20; i<=8'd29; i=i+1)
|
for (i=8'd20; i<=8'd29; i=i+1)
|
read_register(i);
|
read_register(i);
|
if (can_testbench.i_can_top.i_can_bsp.i_can_fifo.overrun_info[can_testbench.i_can_top.i_can_bsp.i_can_fifo.rd_info_pointer])
|
if (can_testbench.i_can_top.i_can_bsp.i_can_fifo.overrun_info[can_testbench.i_can_top.i_can_bsp.i_can_fifo.rd_info_pointer])
|
$display("\nWARNING: This packet was received with overrun.");
|
$display("\nWARNING: This packet was received with overrun.");
|
end
|
end
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task release_rx_buffer;
|
task release_rx_buffer;
|
begin
|
begin
|
write_register(8'd1, 8'h4);
|
write_register(8'd1, 8'h4);
|
$display("(%0t) Rx buffer released.", $time);
|
$display("(%0t) Rx buffer released.", $time);
|
repeat (2) @ (posedge clk); // Time to decrement all the counters
|
repeat (2) @ (posedge clk); // Time to decrement all the counters
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task tx_request;
|
task tx_request;
|
begin
|
begin
|
write_register(8'd1, 8'h1);
|
write_register(8'd1, 8'h1);
|
$display("(%0t) Tx requested.", $time);
|
$display("(%0t) Tx requested.", $time);
|
repeat (2) @ (posedge clk); // Time to decrement all the counters, etc.
|
repeat (2) @ (posedge clk); // Time to decrement all the counters, etc.
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task test_synchronization;
|
task test_synchronization;
|
begin
|
begin
|
// Hard synchronization
|
// Hard synchronization
|
#1 rx=0;
|
#1 rx=0;
|
repeat (2*BRP) @ (posedge clk);
|
repeat (2*BRP) @ (posedge clk);
|
repeat (8*BRP) @ (posedge clk);
|
repeat (8*BRP) @ (posedge clk);
|
#1 rx=1;
|
#1 rx=1;
|
repeat (10*BRP) @ (posedge clk);
|
repeat (10*BRP) @ (posedge clk);
|
|
|
// Resynchronization on time
|
// Resynchronization on time
|
#1 rx=0;
|
#1 rx=0;
|
repeat (10*BRP) @ (posedge clk);
|
repeat (10*BRP) @ (posedge clk);
|
#1 rx=1;
|
#1 rx=1;
|
repeat (10*BRP) @ (posedge clk);
|
repeat (10*BRP) @ (posedge clk);
|
|
|
// Resynchronization late
|
// Resynchronization late
|
repeat (BRP) @ (posedge clk);
|
repeat (BRP) @ (posedge clk);
|
repeat (BRP) @ (posedge clk);
|
repeat (BRP) @ (posedge clk);
|
#1 rx=0;
|
#1 rx=0;
|
repeat (10*BRP) @ (posedge clk);
|
repeat (10*BRP) @ (posedge clk);
|
#1 rx=1;
|
#1 rx=1;
|
|
|
// Resynchronization early
|
// Resynchronization early
|
repeat (8*BRP) @ (posedge clk); // two frames too early
|
repeat (8*BRP) @ (posedge clk); // two frames too early
|
#1 rx=0;
|
#1 rx=0;
|
repeat (10*BRP) @ (posedge clk);
|
repeat (10*BRP) @ (posedge clk);
|
#1 rx=1;
|
#1 rx=1;
|
repeat (10*BRP) @ (posedge clk);
|
repeat (10*BRP) @ (posedge clk);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task send_bit;
|
task send_bit;
|
input bit;
|
input bit;
|
integer cnt;
|
integer cnt;
|
begin
|
begin
|
#1 rx=bit;
|
#1 rx=bit;
|
repeat ((`CAN_TIMING1_TSEG1 + `CAN_TIMING1_TSEG2 + 3)*BRP) @ (posedge clk);
|
repeat ((`CAN_TIMING1_TSEG1 + `CAN_TIMING1_TSEG2 + 3)*BRP) @ (posedge clk);
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
task receive_frame; // CAN IP core receives frames
|
task receive_frame; // CAN IP core receives frames
|
input mode;
|
input mode;
|
input remote_trans_req;
|
input remote_trans_req;
|
input [28:0] id;
|
input [28:0] id;
|
input [3:0] length;
|
input [3:0] length;
|
input [14:0] crc;
|
input [14:0] crc;
|
|
|
reg [117:0] data;
|
reg [117:0] data;
|
reg previous_bit;
|
reg previous_bit;
|
reg stuff;
|
reg stuff;
|
reg tmp;
|
reg tmp;
|
reg arbitration_lost;
|
reg arbitration_lost;
|
integer pointer;
|
integer pointer;
|
integer cnt;
|
integer cnt;
|
integer total_bits;
|
integer total_bits;
|
integer stuff_cnt;
|
integer stuff_cnt;
|
|
|
begin
|
begin
|
|
|
stuff_cnt = 1;
|
stuff_cnt = 1;
|
stuff = 0;
|
stuff = 0;
|
|
|
if(mode) // Extended format
|
if(mode) // Extended format
|
data = {id[28:18], 1'b1, 1'b1, id[17:0], remote_trans_req, 2'h0, length};
|
data = {id[28:18], 1'b1, 1'b1, id[17:0], remote_trans_req, 2'h0, length};
|
else // Standard format
|
else // Standard format
|
data = {id[10:0], remote_trans_req, 1'b0, 1'b0, length};
|
data = {id[10:0], remote_trans_req, 1'b0, 1'b0, length};
|
|
|
if (~remote_trans_req)
|
if (~remote_trans_req)
|
begin
|
begin
|
if(length) // Send data if length is > 0
|
if(length) // Send data if length is > 0
|
begin
|
begin
|
for (cnt=1; cnt<=(2*length); cnt=cnt+1) // data (we are sending nibbles)
|
for (cnt=1; cnt<=(2*length); cnt=cnt+1) // data (we are sending nibbles)
|
data = {data[113:0], cnt[3:0]};
|
data = {data[113:0], cnt[3:0]};
|
end
|
end
|
end
|
end
|
|
|
// Adding CRC
|
// Adding CRC
|
data = {data[104:0], crc[14:0]};
|
data = {data[104:0], crc[14:0]};
|
|
|
|
|
// Calculating pointer that points to the bit that will be send
|
// Calculating pointer that points to the bit that will be send
|
if (remote_trans_req)
|
if (remote_trans_req)
|
begin
|
begin
|
if(mode) // Extended format
|
if(mode) // Extended format
|
pointer = 52;
|
pointer = 52;
|
else // Standard format
|
else // Standard format
|
pointer = 32;
|
pointer = 32;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if(mode) // Extended format
|
if(mode) // Extended format
|
pointer = 52 + 8 * length;
|
pointer = 52 + 8 * length;
|
else // Standard format
|
else // Standard format
|
pointer = 32 + 8 * length;
|
pointer = 32 + 8 * length;
|
end
|
end
|
|
|
// This is how many bits we need to shift
|
// This is how many bits we need to shift
|
total_bits = pointer;
|
total_bits = pointer;
|
|
|
// Waiting until previous msg is finished before sending another one
|
// Waiting until previous msg is finished before sending another one
|
wait (~can_testbench.i_can_top.i_can_bsp.error_frame & ~can_testbench.i_can_top.i_can_bsp.rx_inter & ~can_testbench.i_can_top.i_can_bsp.tx_state);
|
wait (~can_testbench.i_can_top.i_can_bsp.error_frame & ~can_testbench.i_can_top.i_can_bsp.rx_inter & ~can_testbench.i_can_top.i_can_bsp.tx_state);
|
arbitration_lost = 0;
|
arbitration_lost = 0;
|
|
|
send_bit(0); // SOF
|
send_bit(0); // SOF
|
previous_bit = 0;
|
previous_bit = 0;
|
|
|
fork
|
fork
|
|
|
begin
|
begin
|
while (~arbitration_lost)
|
while (~arbitration_lost)
|
begin
|
begin
|
for (cnt=0; cnt<=total_bits; cnt=cnt+1)
|
for (cnt=0; cnt<=total_bits; cnt=cnt+1)
|
begin
|
begin
|
if (stuff_cnt == 5)
|
if (stuff_cnt == 5)
|
begin
|
begin
|
stuff_cnt = 1;
|
stuff_cnt = 1;
|
total_bits = total_bits + 1;
|
total_bits = total_bits + 1;
|
stuff = 1;
|
stuff = 1;
|
tmp = ~data[pointer+1];
|
tmp = ~data[pointer+1];
|
send_bit(~data[pointer+1]);
|
send_bit(~data[pointer+1]);
|
previous_bit = ~data[pointer+1];
|
previous_bit = ~data[pointer+1];
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (data[pointer] == previous_bit)
|
if (data[pointer] == previous_bit)
|
stuff_cnt <= stuff_cnt + 1;
|
stuff_cnt <= stuff_cnt + 1;
|
else
|
else
|
stuff_cnt <= 1;
|
stuff_cnt <= 1;
|
|
|
stuff = 0;
|
stuff = 0;
|
tmp = data[pointer];
|
tmp = data[pointer];
|
send_bit(data[pointer]);
|
send_bit(data[pointer]);
|
previous_bit = data[pointer];
|
previous_bit = data[pointer];
|
pointer = pointer - 1;
|
pointer = pointer - 1;
|
end
|
end
|
if (arbitration_lost)
|
if (arbitration_lost)
|
cnt=total_bits+1; // Exit the for loop
|
cnt=total_bits+1; // Exit the for loop
|
end
|
end
|
arbitration_lost = 1; // At the end we exit the while loop
|
arbitration_lost = 1; // At the end we exit the while loop
|
|
|
// Nothing send after the data (just recessive bit)
|
// Nothing send after the data (just recessive bit)
|
repeat (13) send_bit(1); // CRC delimiter + ack + ack delimiter + EOF + intermission= 1 + 1 + 1 + 7 + 3
|
repeat (13) send_bit(1); // CRC delimiter + ack + ack delimiter + EOF + intermission= 1 + 1 + 1 + 7 + 3
|
end
|
end
|
end
|
end
|
|
|
begin
|
begin
|
while (~arbitration_lost)
|
while (~arbitration_lost)
|
begin
|
begin
|
#1 wait (can_testbench.i_can_top.sample_point);
|
#1 wait (can_testbench.i_can_top.sample_point);
|
if (mode)
|
if (mode)
|
begin
|
begin
|
if (cnt<32 & tmp & (~rx_and_tx))
|
if (cnt<32 & tmp & (~rx_and_tx))
|
begin
|
begin
|
arbitration_lost = 1;
|
arbitration_lost = 1;
|
rx = 1; // Only recessive is send from now on.
|
rx = 1; // Only recessive is send from now on.
|
end
|
end
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if (cnt<12 & tmp & (~rx_and_tx))
|
if (cnt<12 & tmp & (~rx_and_tx))
|
begin
|
begin
|
arbitration_lost = 1;
|
arbitration_lost = 1;
|
rx = 1; // Only recessive is send from now on.
|
rx = 1; // Only recessive is send from now on.
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
join
|
join
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
|
|
// State machine monitor (btl)
|
// State machine monitor (btl)
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if(can_testbench.i_can_top.i_can_btl.go_sync & can_testbench.i_can_top.i_can_btl.go_seg1 | can_testbench.i_can_top.i_can_btl.go_sync & can_testbench.i_can_top.i_can_btl.go_seg2 |
|
if(can_testbench.i_can_top.i_can_btl.go_sync & can_testbench.i_can_top.i_can_btl.go_seg1 | can_testbench.i_can_top.i_can_btl.go_sync & can_testbench.i_can_top.i_can_btl.go_seg2 |
|
can_testbench.i_can_top.i_can_btl.go_seg1 & can_testbench.i_can_top.i_can_btl.go_seg2)
|
can_testbench.i_can_top.i_can_btl.go_seg1 & can_testbench.i_can_top.i_can_btl.go_seg2)
|
begin
|
begin
|
$display("(%0t) ERROR multiple go_sync, go_seg1 or go_seg2 occurance\n\n", $time);
|
$display("(%0t) ERROR multiple go_sync, go_seg1 or go_seg2 occurance\n\n", $time);
|
#1000;
|
#1000;
|
$stop;
|
$stop;
|
end
|
end
|
|
|
if(can_testbench.i_can_top.i_can_btl.sync & can_testbench.i_can_top.i_can_btl.seg1 | can_testbench.i_can_top.i_can_btl.sync & can_testbench.i_can_top.i_can_btl.seg2 |
|
if(can_testbench.i_can_top.i_can_btl.sync & can_testbench.i_can_top.i_can_btl.seg1 | can_testbench.i_can_top.i_can_btl.sync & can_testbench.i_can_top.i_can_btl.seg2 |
|
can_testbench.i_can_top.i_can_btl.seg1 & can_testbench.i_can_top.i_can_btl.seg2)
|
can_testbench.i_can_top.i_can_btl.seg1 & can_testbench.i_can_top.i_can_btl.seg2)
|
begin
|
begin
|
$display("(%0t) ERROR multiple sync, seg1 or seg2 occurance\n\n", $time);
|
$display("(%0t) ERROR multiple sync, seg1 or seg2 occurance\n\n", $time);
|
#1000;
|
#1000;
|
$stop;
|
$stop;
|
end
|
end
|
end
|
end
|
|
|
/* stuff_error monitor (bsp)
|
/* stuff_error monitor (bsp)
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if(can_testbench.i_can_top.i_can_bsp.stuff_error)
|
if(can_testbench.i_can_top.i_can_bsp.stuff_error)
|
begin
|
begin
|
$display("\n\n(%0t) Stuff error occured in can_bsp.v file\n\n", $time);
|
$display("\n\n(%0t) Stuff error occured in can_bsp.v file\n\n", $time);
|
$stop; After everything is finished add another condition (something like & (~idle)) and enable stop
|
$stop; After everything is finished add another condition (something like & (~idle)) and enable stop
|
end
|
end
|
end
|
end
|
*/
|
*/
|
|
|
//
|
//
|
// CRC monitor (used until proper CRC generation is used in testbench
|
// CRC monitor (used until proper CRC generation is used in testbench
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if (can_testbench.i_can_top.i_can_bsp.crc_error)
|
if (can_testbench.i_can_top.i_can_bsp.crc_err)
|
$display("Calculated crc = 0x%0x, crc_in = 0x%0x", can_testbench.i_can_top.i_can_bsp.calculated_crc, can_testbench.i_can_top.i_can_bsp.crc_in);
|
$display("Calculated crc = 0x%0x, crc_in = 0x%0x", can_testbench.i_can_top.i_can_bsp.calculated_crc, can_testbench.i_can_top.i_can_bsp.crc_in);
|
end
|
end
|
//
|
//
|
|
|
|
|
|
|
|
|
/*
|
/*
|
// overrun monitor
|
// overrun monitor
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if (can_testbench.i_can_top.i_can_bsp.i_can_fifo.wr & can_testbench.i_can_top.i_can_bsp.i_can_fifo.fifo_full)
|
if (can_testbench.i_can_top.i_can_bsp.i_can_fifo.wr & can_testbench.i_can_top.i_can_bsp.i_can_fifo.fifo_full)
|
$display("(%0t)overrun", $time);
|
$display("(%0t)overrun", $time);
|
end
|
end
|
*/
|
*/
|
|
|
|
|
// form error monitor
|
// form error monitor
|
always @ (posedge clk)
|
always @ (posedge clk)
|
begin
|
begin
|
if (can_testbench.i_can_top.i_can_bsp.form_error)
|
if (can_testbench.i_can_top.i_can_bsp.form_err)
|
$display("\n\n(%0t) ERROR: form_error\n\n", $time);
|
$display("\n\n(%0t) ERROR: form_error\n\n", $time);
|
end
|
end
|
//
|
//
|
|
|
|
|
endmodule
|
endmodule
|
|
|
|
|