Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16593 Discussions

How to use Avalon-MM Master BFM?

Altera_Forum
Honored Contributor II
7,005 Views

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, 

feng
0 Kudos
51 Replies
Altera_Forum
Honored Contributor II
3,402 Views

Hi feng, 

 

Your code enqueues a transaction, but it does not wait for it to complete, so Modelsim exits too soon. Here's a couple of tasks I use: 

 

// ============================================================ // 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  

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

 

--- Quote Start ---  

Hi feng, 

 

Your code enqueues a transaction, but it does not wait for it to complete, so Modelsim exits too soon. Here's a couple of tasks I use: 

 

// ============================================================ // 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  

 

Cheers, 

Dave 

--- Quote End ---  

 

I solved the problem using your tasks. Thanks, Dave. 

 

And I have another question. This custom component has an Avalon conduit interface connecting a LSI. I read the Conduit BFM section, and didn't find the right function. 

 

Can you tell me how to set the values of signals from the LSI? 

 

Best regards, 

feng
0 Kudos
Altera_Forum
Honored Contributor II
3,401 Views

 

--- Quote Start ---  

I solved the problem using your tasks. Thanks, Dave. 

 

--- Quote End ---  

 

 

Great! 

 

 

--- Quote Start ---  

And I have another question. This custom component has an Avalon conduit interface connecting a LSI. I read the Conduit BFM section, and didn't find the right function. 

 

Can you tell me how to set the values of signals from the LSI? 

 

--- Quote End ---  

 

 

Don't use their test_bench() module, use your own. Lets say your design is called sopc_system, then sopc_system.v contains a module called test_bench() at the end of it. Copy the contents of that testbench into your top-level testbench, and adjust the path to the BFM accordingly. Then drive or read the conduit interfaces on the sopc_system module directly. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
3,401 Views

Thanks for your reply, Dave. 

 

I'm using Quartus II 11.0 Web Edition, and I can't find the test_bench() module in my design file. Is the test_bench() module produced automatically by Qsys?  

 

Regards, 

feng
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

 

--- Quote Start ---  

 

I'm using Quartus II 11.0 Web Edition, and I can't find the test_bench() module in my design file. Is the test_bench() module produced automatically by Qsys?  

 

--- Quote End ---  

 

 

Yes. Look at your own code ... 

 

`define CLK_BFM top.tb.clock_source 

 

The 'tb' entry in that hierarchy is the test_bench() component you want to copy and eliminate from the design. You'll copy the clock generator, the reset generator, and the Qsys system instance, and then you will have access to the ports on the Qsys system instance, so you can manipulate the exported ports. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

Thanks, Dave. 

 

I'll try that. 

 

Regards, 

feng
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

 

--- Quote Start ---  

 

I'll try that. 

 

--- Quote End ---  

 

 

Use the Modelsim GUI to navigate to the component in the hierarchy. It'll tell you what file its in (you might be able to double-click to bring the file into the Modelsim editor). 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

Really thanks for your reply, Dave. 

 

Because I'm not familiar with ModelSim, so I don't know how to navigate to component. But I can find the files in my design folder.  

 

Regards, 

feng
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

Thanks guys. This thread helped my issue.

0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

Hello, 

 

this problem looks to be solved. My problem is very similar, so I don't want to start a new topic for my question.  

 

I would like to use 2 Avalon MM BFMs in my Simulation. First BFM should write data, the second one - read data. It is not difficult to get the simulation running with one BFM is doing both tasks, but what should I do differently to get 2 BFMS running?  

 

Let's say, that my BFMs are defined as:  

`define FIRST_BFM tb.simulation_inst.mm_master_bfm_0 

`define SEC_BFM tb.simulation_inst.mm_master_bfm_1 

 

 

 

When I change the write task to use SEC_BFM instead of FIRST_BFM I got this error and simulation fails:# 416198192: FAILURE: top.tb.simulation_inst.mm_master_bfm_1.request_timeout.timeout_thread: Command phase timeout
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

 

--- 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
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

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 :)
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

 

--- 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
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

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 ---  

 

 

// ============================================================ // 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  

 

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  

`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();  

but nothing changed, readdata signal is unknown. What am I doing wrong?
0 Kudos
Altera_Forum
Honored Contributor II
3,402 Views

 

--- 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
0 Kudos
Altera_Forum
Honored Contributor II
2,978 Views

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
0 Kudos
Reply