Forum Discussion
How to use Avalon-MM Master BFM?
Hello, all.
I want to use Avalon Verification IP Suite to check a Qsys custom componet, which have an Avalon salve interface and a Avalon conduit interface connecting a LSI. I wrote this program to test if the custom component can give right response to the Avalon Master BFM.
//Console messaging level
`define VERBOSITY VERBOSITY_INFO
//BFM hierachy
`define CLK_BFM top.tb.clock_source
`define RST_BFM top.tb.reset_source
`define MM_MASTER top.tb.avalon_mm_master
`define CONDUIT_BFM top.tb.conduit_bfm
module test_program();
import verbosity_pkg::*;
import avalon_mm_pkg::*;
event start_test;
event end_test;
//----------------------------------------------------------------------------------
// Set verbosity before the test starts
// Qsys-generated testbench activates clock and reset BMFs
//----------------------------------------------------------------------------------
initial begin
set_verbosity(`VERBOSITY);
// initialize BFMS
`MM_MASTER.init();
end
//----------------------------------------------------------------------------------
// Main test block
//----------------------------------------------------------------------------------
initial begin
// wait for reset inactive
wait(`RST_BFM.reset == 1);
-> start_test;
end
initial begin
@ start_test;
// start write access
`MM_MASTER.set_command_request(REQ_WRITE);
`MM_MASTER.set_command_address(16'h0);
`MM_MASTER.set_command_idle(2,0);
`MM_MASTER.set_command_init_latency(0);
`MM_MASTER.set_command_data(32'h0,0);
`MM_MASTER.push_command();
end
endmodule
Although this program can be compiled by ModelSim with no error, but it seems the write access was not started. Can you give me some hints or some examples about how to test custom components wit Avalon IP verification suite? Regards, feng51 Replies
- Altera_Forum
Honored Contributor
I'm not sure what your code looks like.
I've written a tutorial here that has read/write procedures for a single BFM: http://www.alterawiki.com/wiki/using_the_usb-blaster_as_an_sopc/qsys_avalon-mm_master_tutorial Start with that, and then add the second BFM. So long as the read/write procedures use their own variables, I don't see why you can't have multiple masters. Cheers, Dave - Altera_Forum
Honored Contributor
Thank you, your tutorial is great, I have seen it already and learned a lot. There are few tutorials for single BFM, but nothing for two or more. Even in Avalon Verification IP Suite User Guide is described simulation with only one BFM.
Here is my task. Without commented push commands it works fine. Now it produces already mentioned error. task master_set_and_push_command; input Request_t request; input [`AV_ADDRESS_W-1:0] addr; input [`AV_DATA_W-1:0] data; input [`AV_NUMSYMBOLS-1:0] byte_enable; input [`AV_DATA_W-1:0] idle; input [31:0] init_latency; begin if (request == REQ_WRITE) begin tb.simulation_inst.mm_master_bfm_0.set_command_request(request); tb.simulation_inst.mm_master_bfm_0.set_command_idle(idle, `INDEX_ZERO); tb.simulation_inst.mm_master_bfm_0.set_command_init_latency(init_latency); tb.simulation_inst.mm_master_bfm_0.set_command_address(addr); tb.simulation_inst.mm_master_bfm_0.set_command_byte_enable(byte_enable,`INDEX_ZERO); tb.simulation_inst.mm_master_bfm_0.set_command_burst_size(1); tb.simulation_inst.mm_master_bfm_0.set_command_burst_count(1); tb.simulation_inst.mm_master_bfm_0.set_command_burst_size(8); tb.simulation_inst.mm_master_bfm_0.set_command_burst_count(8); tb.simulation_inst.mm_master_bfm_0.set_command_byte_enable(byte_enable, 1); tb.simulation_inst.mm_master_bfm_0.set_command_byte_enable(byte_enable, 2); tb.simulation_inst.mm_master_bfm_0.set_command_byte_enable(byte_enable, 3); tb.simulation_inst.mm_master_bfm_0.set_command_byte_enable(byte_enable, 4); tb.simulation_inst.mm_master_bfm_0.set_command_byte_enable(byte_enable, 5); tb.simulation_inst.mm_master_bfm_0.set_command_byte_enable(byte_enable, 6); tb.simulation_inst.mm_master_bfm_0.set_command_byte_enable(byte_enable, 7); tb.simulation_inst.mm_master_bfm_0.set_command_data(data, `INDEX_ZERO); tb.simulation_inst.mm_master_bfm_0.set_command_data($random(), 1); tb.simulation_inst.mm_master_bfm_0.set_command_data($random(), 2); tb.simulation_inst.mm_master_bfm_0.set_command_data($random(), 3); tb.simulation_inst.mm_master_bfm_0.set_command_data($random(), 4); tb.simulation_inst.mm_master_bfm_0.set_command_data($random(), 5); tb.simulation_inst.mm_master_bfm_0.set_command_data($random(), 6); tb.simulation_inst.mm_master_bfm_0.set_command_data($random(), 7); tb.simulation_inst.mm_master_bfm_0.push_command(); tb.simulation_inst.mm_master_bfm_1.set_command_request(request); tb.simulation_inst.mm_master_bfm_1.set_command_idle(idle, `INDEX_ZERO); tb.simulation_inst.mm_master_bfm_1.set_command_init_latency(init_latency); tb.simulation_inst.mm_master_bfm_1.set_command_address(addr); tb.simulation_inst.mm_master_bfm_1.set_command_byte_enable(byte_enable,`INDEX_ZERO); tb.simulation_inst.mm_master_bfm_1.set_command_burst_size(1); tb.simulation_inst.mm_master_bfm_1.set_command_burst_count(1); tb.simulation_inst.mm_master_bfm_1.set_command_burst_size(8); tb.simulation_inst.mm_master_bfm_1.set_command_burst_count(8); tb.simulation_inst.mm_master_bfm_1.set_command_byte_enable(byte_enable, 1); tb.simulation_inst.mm_master_bfm_1.set_command_byte_enable(byte_enable, 2); tb.simulation_inst.mm_master_bfm_1.set_command_byte_enable(byte_enable, 3); tb.simulation_inst.mm_master_bfm_1.set_command_byte_enable(byte_enable, 4); tb.simulation_inst.mm_master_bfm_1.set_command_byte_enable(byte_enable, 5); tb.simulation_inst.mm_master_bfm_1.set_command_byte_enable(byte_enable, 6); tb.simulation_inst.mm_master_bfm_1.set_command_byte_enable(byte_enable, 7); tb.simulation_inst.mm_master_bfm_1.set_command_data(data, `INDEX_ZERO); tb.simulation_inst.mm_master_bfm_1.set_command_data(1000*($random()), 1); tb.simulation_inst.mm_master_bfm_1.set_command_data($random(), 2); tb.simulation_inst.mm_master_bfm_1.set_command_data($random(), 3); tb.simulation_inst.mm_master_bfm_1.set_command_data($random(), 4); tb.simulation_inst.mm_master_bfm_1.set_command_data($random(), 5); tb.simulation_inst.mm_master_bfm_1.set_command_data($random(), 6); tb.simulation_inst.mm_master_bfm_1.set_command_data($random(), 7); //tb.simulation_inst.mm_master_bfm_1.push_command(); end else begin tb.simulation_inst.mm_master_bfm_0.set_command_request(request); tb.simulation_inst.mm_master_bfm_0.set_command_idle(idle, `INDEX_ZERO); tb.simulation_inst.mm_master_bfm_0.set_command_init_latency(init_latency); tb.simulation_inst.mm_master_bfm_0.set_command_address(addr); tb.simulation_inst.mm_master_bfm_0.set_command_byte_enable(byte_enable,`INDEX_ZERO); tb.simulation_inst.mm_master_bfm_0.set_command_burst_size(1); tb.simulation_inst.mm_master_bfm_0.set_command_burst_count(1); tb.simulation_inst.mm_master_bfm_0.set_command_data(0, 0); //tb.simulation_inst.mm_master_bfm_0.push_command(); tb.simulation_inst.mm_master_bfm_1.set_command_request(request); tb.simulation_inst.mm_master_bfm_1.set_command_idle(idle, `INDEX_ZERO); tb.simulation_inst.mm_master_bfm_1.set_command_init_latency(init_latency); tb.simulation_inst.mm_master_bfm_1.set_command_address(addr); tb.simulation_inst.mm_master_bfm_1.set_command_byte_enable(byte_enable,`INDEX_ZERO); tb.simulation_inst.mm_master_bfm_1.set_command_burst_size(1); tb.simulation_inst.mm_master_bfm_1.set_command_burst_count(1); tb.simulation_inst.mm_master_bfm_1.set_command_data(0, 0); tb.simulation_inst.mm_master_bfm_1.push_command(); end end endtask - Altera_Forum
Honored Contributor
I've very little experience with Verilog/SystemVerilog, so cannot provide much help in this area.
What happens if you write this as two separate tasks, i.e., task master1_set_and_push_command and task master2_set_and_push_command? This would result in the two BFMs being accessed from different tasks ... it would also result in unique objects/variables being passed to the BFMs, rather than common variables as you are using now ... though push_command() should copy everything allowing you to reuse those same variables in a subsequent call. Cheers, Dave - Altera_Forum
Honored Contributor
I tried to make 2 separate tasks with their own variables, but nothing positive happened. When I turn off time outs with tb.simulation_inst.mm_master_bfm_0.set_command_timeout(0); simulation does not crash anymore, but read task still does not work. Still searching for a solution.
- Altera_Forum
Honored Contributor
--- Quote Start --- Still searching for a solution. --- Quote End --- Create a service request with Altera directly, and upload your code (a simplified case). Cheers, Dave - Altera_Forum
Honored Contributor
Thank you, Dave, I solved this problem. I cleaned my simulation project, generated everything once again and added to my read task these two lines:
wait(tb.simulation_inst.mm_master_bfm_0.signal_response_complete); tb.simulation_inst.mm_master_bfm_0.pop_response(); Now everything runs as expected :) - Altera_Forum
Honored Contributor
--- Quote Start --- I solved this problem. I cleaned my simulation project, generated everything once again and added to my read task these two lines: wait(tb.simulation_inst.mm_master_bfm_0.signal_response_complete); tb.simulation_inst.mm_master_bfm_0.pop_response(); Now everything runs as expected :) --- Quote End --- Great! The error sounded like it was due to an object being reused before the underlying library was finished with it, so this wait makes sense. Thanks for posting your solution. Cheers, Dave - Altera_Forum
Honored Contributor
Hello, I used this code in my test program (in test program i used standart altera_avalon_mm_master_bfm and altera_avalon_mm_slave_bfm submodels), but i have a trouble with using read task.
--- Quote Start ---
Cheers, Dave --- Quote End --- When i use write task address and data proceed from Master to Slave and it can be seen in diagrams in ModelSim. But when i use read task Slave component didn't form readdata in response to adress from Master. I added in read task this code// ============================================================ // Tasks // ============================================================ // // Avalon-MM single-transaction read and write procedures. // // ------------------------------------------------------------ task avalon_write ( // ------------------------------------------------------------ input addr, input data ); begin // Construct the BFM request `BFM.set_command_request(REQ_WRITE); `BFM.set_command_idle(0, 0); `BFM.set_command_init_latency(0); `BFM.set_command_address(addr); `BFM.set_command_byte_enable('1,0); `BFM.set_command_data(data, 0); // Queue the command `BFM.push_command(); // Wait until the transaction has completed while (`BFM.get_response_queue_size() != 1) @(posedge clk); // Dequeue the response and discard `BFM.pop_response(); end endtask // ------------------------------------------------------------ task avalon_read ( // ------------------------------------------------------------ input addr, output data ); begin // Construct the BFM request `BFM.set_command_request(REQ_READ); `BFM.set_command_idle(0, 0); `BFM.set_command_init_latency(0); `BFM.set_command_address(addr); `BFM.set_command_byte_enable('1,0); `BFM.set_command_data(0, 0); // Queue the command `BFM.push_command(); // Wait until the transaction has completed while (`BFM.get_response_queue_size() != 1) @(posedge clk); // Dequeue the response and return the data `BFM.pop_response(); data = `BFM.get_response_data(0); end endtask
but nothing changed, readdata signal is unknown. What am I doing wrong?`SL.set_response_request(REQ_READ); `SL.set_response_latency(0,0); `SL.set_response_data('h1234567,0); `SL.set_interface_wait_time(0,0); `SL.push_response(); - Altera_Forum
Honored Contributor
--- Quote Start --- What am I doing wrong? --- Quote End --- I'm not sure. I have not used the Slave BFMs, so I do not have an example that I can compare your code to. I'd recommend starting with working code from an Altera example, and then modifying it to suit your needs until you track the error down. My guess is that you have not initialized the model correctly. The above Master BFM tests only work correctly because earlier in the main body of the code the Master BFM was initialized. Cheers, Dave - Altera_Forum
Honored Contributor
Hi Dave,
I'm having problems setting up my Modelsim to simulate a Qsys project. My issue is basically my testbench doesn't appear to be controlling the BFM master. I used the avalon_write and avalon_read tasks, but i can't see any bus activity from the Avalon bus. Anyway, I found this thread and tried following your tutorial to try to understand how the testbench controls the BFM master, but i'm also running into issues. From your tutorial, section 4.5.2 Avalon-MM Master BFM, i can run upto the "com" command with no issues. But when i run this: vlog -sv $TUTORIAL/hdl/qsys_system/test/qsys_system_bfm_master_tb.sv -L qsys_system_bfm_master I get these errors: # ** Error: (vlog-19) Failed to access library 'qsys_system_bfm_master' at "qsys_system_bfm_master".# ** Error: h:/temp/altera_jtag_to_avalon_mm_tutorial/hdl/qsys_system/test/qsys_system_bfm_master_tb.sv(48): Could not find the package (verbosity_pkg). Design read will continue, but expect a cascade of errors after this failure. Furthermore if you experience a vopt-7 error immediately before this error then please check the package names or the library search paths on the command line.# ** Error: h:/temp/altera_jtag_to_avalon_mm_tutorial/hdl/qsys_system/test/qsys_system_bfm_master_tb.sv(49): Could not find the package (avalon_mm_pkg). Design read will continue, but expect a cascade of errors after this failure. Furthermore if you experience a vopt-7 error immediately before this error then please check the package names or the library search paths on the command line.# C:/altera/13.1/modelsim_ae/win32aloem/vlog failed. Any suggestion? I'm using Quartus 64 bit version 13.1.0 and Modelsim AE 10.1d. Thanks, Joel