Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Valued Contributor III
1,156 Views

BFM Read from On Chip RAM

I followed D. W. Hawkins (dwh@ovro.caltech.edu) tutorial on JTAG-to-Avalon-MM. There is a task in the tutorial that reads a slave address using the BFM master. The slave is onchip_ram. The problem is that there is a latency of 1 clock cycle for the data to be available on the bus after the read address is available. This task reads the current value on bus (at the moment when the address is up), not the next cycle of the data (which is what I need). How can I fix it (such as introduce a latency in the response)? 

 

// -------------------------------------------- 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
0 Kudos
7 Replies
Highlighted
Valued Contributor III
7 Views

 

--- Quote Start ---  

There is a task in the tutorial that reads a slave address using the BFM master. The slave is onchip_ram. The problem is that there is a latency of 1 clock cycle for the data to be available on the bus after the read address is available. This task reads the current value on bus (at the moment when the address is up), not the next cycle of the data (which is what I need). How can I fix it (such as introduce a latency in the response)? 

 

--- Quote End ---  

 

The BFM task knows *nothing* about the Avalon-MM bus timing. The whole idea of BFMs is to create an abstraction where you do not have to care about signals at the bus-level, as that is taken care of by the BFM. 

 

The task pushes a read transaction into the BFM transaction queue, and then waits for the BFM response queue to have data. This wait may take multiple clock cycles (hence the while loop). 

 

Once the queue has a response, the response is popped off the BFM queue, and its data returned to the user. 

 

I wrote another example that uses a BFM slave as well as the master. You could run that and setup the slave to have a larger number of wait-states to see how the BFM master still works correctly regardless of the number of slave wait-states between transaction acceptance and read-data availability. See this thread (Post# 25); 

 

http://www.alteraforum.com/forum/showthread.php?t=32952&page=3 

 

If you are having a problem with your specific simulation, post details (or a zip) and I'll try to help you figure it out :) 

 

Cheers, 

Dave
0 Kudos
Highlighted
Valued Contributor III
7 Views

Thanks a lot Mr. Hawkins for the reply. I went through the other thread before posting here. In the example qsys_vip that you have posted, you have a BFM slave module in QSys. I have a RAM slave module. I see that you are setting slave response latency like this: 

`SLAVE.set_response_latency(2, 0); 

 

In my case, I know the latency of the RAM ahead of time (you can set it in QSys parameters, can be 1 or 2 clock cycles). I just need to tell the BFM master to wait for it. I went through the "Altera Verification IP Guide" and couldn't find which API sets the master wait time. I found this one: 

get_response_wait_time() Returns the wait latency for transaction in the response descriptor that has been removed from the response queue. Each cycle in a burst has its own wait latency entry. 

 

This RAM transaction is a read transactions with no readdatavalid signal: 

https://www.alteraforum.com/forum/attachment.php?attachmentid=10160  

 

I assume when you get the value of get_response_wait_time() from slave BFM, you have to send it to the master BFM. What is the API for the master BFM to know about this wait time?
0 Kudos
Highlighted
Valued Contributor III
7 Views

 

--- Quote Start ---  

 

In my case, I know the latency of the RAM ahead of time (you can set it in QSys parameters, can be 1 or 2 clock cycles). I just need to tell the BFM master to wait for it. 

 

--- Quote End ---  

 

No, you're misunderstanding something, let me explain. 

 

The Avalon-MM bus specification defines the bus transaction timing. In your case, you are interested in a read. A read is initiated by the bus master by asserting the read signal. The read transaction is accepted by the slave when it deasserts the waitrequest signal. The read data is then valid when the slave asserts readdatavalid. The Avalon-MM BFM knows these rules (that is what makes it a bus functional model), and so it issues the read, waits for waitrequest to deassert, and then waits for readdatavalid to assert, at which point it copies the read data into the BFM structure that you can access from your testbench. 

 

 

--- Quote Start ---  

 

I went through the "Altera Verification IP Guide" and couldn't find which API sets the master wait time. I found this one: 

get_response_wait_time() Returns the wait latency for transaction in the response descriptor that has been removed from the response queue. Each cycle in a burst has its own wait latency entry. 

 

--- Quote End ---  

 

If you call this API function on the read response packet you get when you access your RAM, then the value should be 1, i.e., the readdatavalid signal asserted 1 clock after the transaction was accepted. 

 

 

--- Quote Start ---  

 

This RAM transaction is a read transactions with no readdatavalid signal 

 

--- Quote End ---  

 

This is the part that is leading to your confusion :) 

 

If the Altera on-chip RAM you are testing does not include a readdatavalid signal, then the Avalon-MM fabric can infer one from the settings in the _hw.tcl file, so although there is a readdatavalid, you cannot easily probe it in Modelsim. 

 

I'd recommend testing a component that uses waitrequest and readdatavalid. 

 

If this recommendation is beyond where you feel comfortable, let me know, and I'll take one of my existing components and make it into a standalone example for you. 

 

Cheers, 

Dave
0 Kudos
Highlighted
Valued Contributor III
7 Views

Okay, I got it. This on-chip RAM does not have both waitrequest and readdatavalid. It works on a pre-determined read latency. But as you said, the interconnect takes care of it: 

 

onchip_ram ( .clk (clk_clk), // clk1.clk .address (mm_interconnect_0_onchip_ram_s1_address), // s1.address .clken (mm_interconnect_0_onchip_ram_s1_clken), // .clken .chipselect (mm_interconnect_0_onchip_ram_s1_chipselect), // .chipselect .write (mm_interconnect_0_onchip_ram_s1_write), // .write .readdata (mm_interconnect_0_onchip_ram_s1_readdata), // .readdata .writedata (mm_interconnect_0_onchip_ram_s1_writedata), // .writedata .byteenable (mm_interconnect_0_onchip_ram_s1_byteenable), // .byteenable .reset (rst_controller_reset_out_reset), // reset1.reset .reset_req (rst_controller_reset_out_reset_req), // .reset_req .address2 (mm_interconnect_0_onchip_ram_s2_address), // s2.address .chipselect2 (mm_interconnect_0_onchip_ram_s2_chipselect), // .chipselect .clken2 (mm_interconnect_0_onchip_ram_s2_clken), // .clken .write2 (mm_interconnect_0_onchip_ram_s2_write), // .write .readdata2 (mm_interconnect_0_onchip_ram_s2_readdata), // .readdata .writedata2 (mm_interconnect_0_onchip_ram_s2_writedata), // .writedata .byteenable2 (mm_interconnect_0_onchip_ram_s2_byteenable), // .byteenable .clk2 (clk_clk), // clk2.clk .reset2 (rst_controller_reset_out_reset), // reset2.reset .reset_req2 (rst_controller_reset_out_reset_req) // .reset_req ); 

 

altera_merlin_slave_translator# ( .AV_ADDRESS_W (7), .AV_DATA_W (64), .UAV_DATA_W (64), .AV_BURSTCOUNT_W (1), .AV_BYTEENABLE_W (8), .UAV_BYTEENABLE_W (8), .UAV_ADDRESS_W (32), .UAV_BURSTCOUNT_W (4), .AV_READLATENCY (1), <--- .USE_READDATAVALID (0), <--- .USE_WAITREQUEST (0), <--- .USE_UAV_CLKEN (0), .USE_READRESPONSE (0), .USE_WRITERESPONSE (0), .AV_SYMBOLS_PER_WORD (8), .AV_ADDRESS_SYMBOLS (0), .AV_BURSTCOUNT_SYMBOLS (0), .AV_CONSTANT_BURST_BEHAVIOR (0), .UAV_CONSTANT_BURST_BEHAVIOR (0), .AV_REQUIRE_UNALIGNED_ADDRESSES (0), .CHIPSELECT_THROUGH_READLATENCY (0), .AV_READ_WAIT_CYCLES (0), .AV_WRITE_WAIT_CYCLES (0), .AV_SETUP_WAIT_CYCLES (0), .AV_DATA_HOLD_CYCLES (0) ) onchip_ram_s1_translator ( 

 

I just ran the simulation on ModelSim and traced the waitrequest=0 and readdatavalid=1 signals generated by the Avalon translator connected to this on-chip RAM. The readdatavalid is produced properly the next clock cycle when data is ready to read but the BFM master still reads the previous clock cycle :confused:
0 Kudos
Highlighted
Valued Contributor III
7 Views

 

--- Quote Start ---  

 

I just ran the simulation on ModelSim and traced the waitrequest=0 and readdatavalid=1 signals generated by the Avalon translator connected to this on-chip RAM. The readdatavalid is produced properly the next clock cycle when data is ready to read but the BFM master still reads the previous clock cycle 

 

--- Quote End ---  

 

Try tracing at the BFM interface, i.e., your Qsys design will have BFM<->fabric<->Slave. Since the fabric to slave interface does not have a waitrequest and readdatavalid, try probing at the BFM side. 

 

This might be what you just did, but it was not clear in your description ... 

 

Cheers, 

Dave
0 Kudos
Highlighted
Valued Contributor III
7 Views

I am very, very sorry to take your time this way. I was reading my preloaded RAM's HEX in a very very bizarre fashion which led to my confusions. I have spend the whole day debugging it... but I learned a lot about QSys/interconnects/translators/BFMs by probing all of them and how they work, thanks to your insight. 

 

Best regards.
0 Kudos
Highlighted
Valued Contributor III
7 Views

 

--- Quote Start ---  

I am very, very sorry to take your time this way. 

 

--- Quote End ---  

 

No need to apologize. If I'm too busy to read the forum, I simply won't answer :) 

 

 

--- Quote Start ---  

 

I was reading my preloaded RAM's HEX in a very very bizarre fashion which led to my confusions. I have spend the whole day debugging it... but I learned a lot about QSys/interconnects/translators/BFMs by probing all of them and how they work, thanks to your insight. 

 

--- Quote End ---  

 

So I take this to mean that everything is now working correctly? Excellent. 

 

I tend to appreciate bugs as an opportunity to learn. If everything "just worked" you'd never gain the insight you obtain by debugging a problem. 

 

Of course this appreciation only ever occurs after the bug has been fixed :) 

 

Cheers, 

Dave
0 Kudos