FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6343 Discussions

AVALON-MM Master Template on DE2

Altera_Forum
Honored Contributor II
1,561 Views

I'm attempting to use the Avalon-MM Master Templates located at: (altera.com/support/examples/nios2/exm-avalon-mm.html) in order to control some external SDRAM on the Terasic DE2 Development board and have run into some trouble and was wondering if anyone who has experience using this can help. 

 

In order to accomplish this task I created a Qsys system with an SDR SDRAM controller and the Master Template configured in read mode. Hooked up as shown in the qsys_system.jpg attachment. I then instantiated the system in a verilog file and wrote some very simple HDL to test If I could get a successful read. 

 

The HDL simply toggles the go pin on the master conduit for one clock cycle and then waits for user_data_available signal from the master template to go high. At this point it would dump the data to the LEDs on the board, toggle the read acknowledge back to the master and start over. I have it set to trigger on the overflow of a counter so there is lots of space between reads just incase. 

 

The problem I have though is I toggle the 'go' pin (I can see that control_done goes low when I look using SignalTap) and then it just sits waiting forever because the master never posts a read or asserts control_done. 

 

Does anyone have any idea what might be going wrong or how I can best trouble shoot it? I've been spending many hours goofing around in SignalTap trying to see what the heck is going wrong. As far as I can tell the Master isn't talking to the SDRAM controller properly, the master settings are wrong, or the SDRAM controller settings are wrong. I used the same settings for the SDRAM controller as listed in the NIOS tutorial for this board, including instantiating a seperate -3ns clock to send to the SDRAM chip seperate. 

 

Below is a snippet from my Verilog HDL that shows my process (with plenty of comments). Feel free to comment on anything I may be doing wrong here too, I'm pretty new to HDL and have to teach myself. 

 

always @(posedge CLOCK_50) begin if (!KEY) //Only incremement when I have button held down. (Possible it started before memory initialized before?) read_count <= read_count + 1'b1; end always @(posedge CLOCK_50) begin if (state == 3'b000) //Idle state begin go <= 1'b0; //DRAM controller 'go' bit inactive at idle FIFO_read <= 1'b0; //DRAM controller FIFO read ack LEDG <= state; //green LED state diagnostic if (user_data_available_from_the_master_template_0) //If there is data available for some reason state <= 3'b010; //skip ahead to state 2 else if (read_count == 100000) //When a counter gets to this number a read will begin begin state <= 3'b001; //Increment to next state go <= 1'b1; //set go signal high for one clock cycle. LEDG <= state; end end else if(state == 3'b001) //First state of read process begin go <= 1'b0; //go bit goes low after one clock state <= 3'b010; //increment to next state LEDG <= state; end else if (state == 3'b010) //Second state of read process begin if (user_data_available_from_the_master_template_0) //Stay in this state till there is some data to read begin state <= 3'b011; //Increment state after data is found LEDR <= user_buffer_output_data_from_the_master_template_0; //Output the data to LEDs FIFO_read <= 1'b1; //Send signal that acknowledges I read the FIFO end LEDG <= state; end else if (state == 3'b011) //Third state of read process begin state <= 3'b100; //Increment state FIFO_read <= 1'b0; //set the ack signal low LEDG <= state; end else if (state == 3'b100) //Fourth state of read process begin if (user_data_available_from_the_master_template_0) //If there is more data for some reason state <= 3'b010; //Go back to state 2 else state <= 3'b000; //Otherwise move back to idle state LEDG <= state; end else // Catch all states not defined begin state <= 3'b000; //Send to idle state go <= 1'b0; //Set signals to low FIFO_read <= 1'b0; LEDG <= state; end end
0 Kudos
11 Replies
Altera_Forum
Honored Contributor II
494 Views

You should be using the "control_done" signal to determine when it's safe to send a new command and not the "user_data_available" signal. User_data_available is just a signal that tells you that at least one word of data is buffered in the internal FIFO. Control_done tells you when all the reads have completed. 

 

In your 000 state you have multiple drivers of the 'go' register. I'm kinda surprised that compiled to be honest. If 'read_count' was coded in such a way that it would never hit the value of 100000 then I can see why it was allowed to compile since the 'go' assertion would get optimized away. 

 

Are you reading multiple words of data from memory or just one at a time? If it is just one then I recommend building an Avalon read master instead since the master template is meant for reading buffers from memory.
0 Kudos
Altera_Forum
Honored Contributor II
494 Views

 

--- Quote Start ---  

You should be using the "control_done" signal to determine when it's safe to send a new command and not the "user_data_available" signal. User_data_available is just a signal that tells you that at least one word of data is buffered in the internal FIFO. Control_done tells you when all the reads have completed. 

--- Quote End ---  

 

I am checking the "user_data_available" signal only to see if there is anything in the FIFO and if so, skipping to the state where I read whatever is in there by toggling the user_read_buffer signal (FIFO_read in my case). It is probably a good idea to check that control_done is asserted before issuing a read command by toggling the "go" signal though so I've changed one line to -> " else if (read_count == 100000 & control_done_from_the_master_template_0) " 

 

I've also tried just removing the counter thing and having it as " else if (control_done_from_the_master_template_0) " but that doesn't seem to change anything. 

 

 

--- Quote Start ---  

In your 000 state you have multiple drivers of the 'go' register. I'm kinda surprised that compiled to be honest. If 'read_count' was coded in such a way that it would never hit the value of 100000 then I can see why it was allowed to compile since the 'go' assertion would get optimized away. 

--- Quote End ---  

 

Thanks for pointing this out. I've removed the " go <=1'b0 " and just left the one that sets it in the if else. No change to the observed results. 

 

 

--- Quote Start ---  

Are you reading multiple words of data from memory or just one at a time? If it is just one then I recommend building an Avalon read master instead since the master template is meant for reading buffers from memory. 

--- Quote End ---  

 

Forgot to mention what the configuration signals were set to. I am using the following: 

 

wire control_fixed_location_to_the_master_template_0 = 1'b1; 

wire [22:0] control_read_length_to_the_master_template_0 = 2; 

wire [22:0] control_read_base_to_the_master_template_0 = 0; 

 

At the moment I am just trying to read one 16bit word but in the future I plan to use it more thoroughly so that is why I am trying to use this instead of writing my own master. 

 

For all that I know, the master template could be working as intended but the slave is not communicating with the SDRAM module for some reason... Just not really sure how to troubleshoot that case. 

 

What I do know is control_done is high, I assert the go signal for one clock cycle, then I am stuck waiting for eternity in state 010 checking to see if user_data_available ever goes high.
0 Kudos
Altera_Forum
Honored Contributor II
494 Views

Since you are attempting to transfer only 2 bytes have you setup the read master to be 8 or 16 bits wide? I seem to recall it only being able to handle transfer lengths that are a multiple of it's data width. So if you set the read master to be 32-bit I could see it treating 2 bytes as 0 bytes and completing without issuing any reads. 

 

The location being read from also needs to be aligned in memory as well. So if you use say a 16-bit master then your memory location needs to be on a 2 byte boundary.
0 Kudos
Altera_Forum
Honored Contributor II
494 Views

The read master has 16 bit data width and I set the address to 0 just to make sure it's not in the middle of a word. 

 

The problem I see is that it never completes a read. I issue the command and it never replies with "data in the fifo" or "control done".
0 Kudos
Altera_Forum
Honored Contributor II
494 Views

I'm looking at the RTL and this is the behavior you should be seeing: 

 

Cycle 0 --> You assert 'go' for one clock cycle and send in all the control signals 

Cycle 1-x --> Control_done should be low, 'x' is the number of cycles before read data returns to the read master 

Cycle x+1 --> Control_done should be high 

Cycle x + 2 --> Data should be available in the read master FIFO 

 

The reason why control_done asserts first is because it's based on all the reads being issued and read data returned. There is a little bit of latency in the FIFO which causes control_done to potentially assert before data is available. Even if data is not available it is safe to send in another read command. 

 

Have you checked the read master to see if the read signal is asserted? It could be the read master is trying to read but the SDRAM is asserting waitrequest for a long time. I also see a typo on line 179 of the "latency_aware_read_master.v" file, the sensitivity list should be "posedge clk or posedge reset" (I highly doubt this is the culprit though).
0 Kudos
Altera_Forum
Honored Contributor II
494 Views

Well I'm not sure why but I got it to work by increasing the size of the FIFO depth in the master template settings from 4 to 32. It was constantly stuck in a state of "too_many_pending_reads" for some reason. 

 

Thanks for the help and the tips BadOmen. 

 

Edit: The problem stems from this line in the latency_aware_read_master file: 

 

assign too_many_pending_reads = (fifo_used + reads_pending) >= (FIFODEPTH - 4); 

 

If you choose FIFODEPTH as the lowest option (4) and if there are no reads pending and the fifo_used is zero (no words in the FIFO) you still get too_many_pending_reads as high and this prevents it from beginning any more reads at all... even though there never was one to begin with.
0 Kudos
Altera_Forum
Honored Contributor II
494 Views

Good catch, 4 used to be a valid FIFO depth but the amount of pipelining was increased and the .tcl file wasn't adjusted accordingly (oops....). For SDRAM I recommend a FIFO depth of at least 16 when you move on to doing buffer data movements. I typically choose FIFO depths based on the on-chip memory block size of the FPGA I'm using. For example on a Cyclone II (m4k memory blocks) for 16 bit wide data you could choose a FIFO depth of 512 and still use the same amount of memory as a more shallow FIFO.

0 Kudos
Altera_Forum
Honored Contributor II
494 Views

Hi, 

 

I've run into the same (similar) problem with trying to use QDRII SRAM interface (AValon-enabled) in Qsys with Aletra's MM master read/write templates. The sims run correctly, but when I go to hadware, write transactions complte OK, but reads never return (control_done signal goes low upon asserting 'go' and never goes high again). I take it that the waitrequest from the fabric is staying high. Any clues?  

 

The fifos are defined size 32 (someone had an issue with size '4'). In the sims the interface takes a while to complete calibration. Is it possible the same happens in real life, i.e. calibration never succeeds? 

 

I'm using straix iv 100g dev board. 

 

Thanks
0 Kudos
Altera_Forum
Honored Contributor II
494 Views

 

--- Quote Start ---  

Hi, 

 

I've run into the same (similar) problem with trying to use QDRII SRAM interface (AValon-enabled) in Qsys with Aletra's MM master read/write templates. The sims run correctly, but when I go to hadware, write transactions complte OK, but reads never return (control_done signal goes low upon asserting 'go' and never goes high again). I take it that the waitrequest from the fabric is staying high. Any clues?  

 

The fifos are defined size 32 (someone had an issue with size '4'). In the sims the interface takes a while to complete calibration. Is it possible the same happens in real life, i.e. calibration never succeeds? 

 

I'm using straix iv 100g dev board. 

 

Thanks 

--- Quote End ---  

 

 

Did you already solve the problem or find a workaround? If not this may help you. 

 

I recently also had problem when using the Latency-Aware-Read-Master template (LARM). I used it in a multi-master system in qsys, so arbitration has to be done.  

The symptom was, that some read requests completed correctly, but at one point the system got stuck. I thought I produced a deadlock but did not find anything in my code. So i went on to debug into the QSYS fabric. It seams that the read signal is asserted one cycle to long when the LARM stops requesting data due to a full internal fifo. Normally this is not a problem because the FIFO never gets full (due to the -4 mentioned in the thread). However with arbitration, this read can causes bus grant. which is only removed when read is asserted in conjunction with a deasserted waitrequest. 

In my system the nios cpu emtying the fifo, had an instruction cache miss thus also requesting bus access and becoming stalled and stopping consuming the user fifo -> deadlock, because the read signal will never be asserted any more. 

 

the long story short - the solution: 

* in the LARM ther is a signal and a register too_many_pending_reads and too_many_pending_reads_d1.  

* the register is causing the extra read.  

* remove the register and update all references to it by using the signal instead. 

 

i am not sure if this is the correct solution - (i am not an avalon expert) - but for me it seems to work and i think it is plausible. 

 

kr
0 Kudos
Altera_Forum
Honored Contributor II
494 Views

It would be much easier to use the read master from the modular SGDMA or the Qsys tutorial design than trying to fix the read master template. In the future the Qsys tutorial masters will most likely replace the existing Avalon-MM master templates.

0 Kudos
Altera_Forum
Honored Contributor II
494 Views

I have same issue at here, my setup is: avalon read master talk with a onchip memory2_0. The simulation shows below:  

parameter DATAWIDTH = 16, parameter BYTEENABLEWIDTH = 2, parameter FIFODEPTH = 32. It looks the signal fifo_used in a unknown state somehow and cause too_many_pending_reads as well (assign too_many_pending_reads = ((fifo_used + reads_pending) >= (FIFODEPTH - 4))). 

Thanks,
0 Kudos
Reply