Forum Discussion
Altera_Forum
Honored Contributor
16 years agoFft In Sopc
Guyz please help , if u have an idea.
Uptil now i made a 64 point FFT using megacore and added it to the sopc as a new component but there are a lot of signals and so it gives me an error when i generate it. I believe i need a wrapper code for my FFT. CAN SUM1 HELP ME OUT WITH IT. THANKS webster_dev at the rate yahoo.com39 Replies
- Altera_Forum
Honored Contributor
i am doing same thing will this be enough for implementing fft to sopc and then to nios processor. will i need a wrapper code for interface conversion plz provide me code in vhdl if necessary. thanks for the tutorial.
- Altera_Forum
Honored Contributor
Hi every body:
after alot of work i successed to add FFT core to my Project and I attached some picture about how to add FFT 1-First you should add FFT core from Megafunction (as attached file1).. 2-add your Wrapper FFT to the Project path (file: fft_avalon_wraper.v). and you should change it to match your project. 3-add your FFT core as (new component) to SOPC builder (as attached file2-3-4). 4-connect your FFT to SGDMA (as attached file5-6-7). 5-be cerful to the Arbitration number (as attached file5). 6-add your code in C project (as attached file8). i hope that will successed, good lock all. - Altera_Forum
Honored Contributor
Hi
I want to speak about connect SGDMA and start transmit data. SGDMA has 4 Signal 1 - read/write Descriptor Signal: this Signal Should be connected to the memory where you write your Descriptor, for example: - in Sopc builder i will connect read/write Descriptor Signal to The (On_Chip_Memory) it name : "INPUT_RAM". -so in Nios II Program I should add Descriptor as following: alt_sgdma_descriptor *desc = (alt_sgdma_descriptor*)input_ram_base ; **************** 2 - read or In Signal: connected to the memory where I write my input Data in Nios II Program: alt_u32 *tx_ptr = (alt_u32 *) (INPUT_RAM_BASE+ ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE); where tx_ptr is a pointer of memory where data will be read from. ***************** 3 - CSR Signal: should connected to the CPU, it is needed to asked SGDMA about its status. ***************** 4 - write or out Signal: connected to the memory where i want to write output data: alt_u32 * rx_ptr = (alt_u32 *) (OUTPUT_RAM_BASE+ ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE); where tx_ptr is a pointer of memory where data is written - Altera_Forum
Honored Contributor
Can you post the project in C?
Thanks, Sean - Altera_Forum
Honored Contributor
here is my code :
# include <stdio.h># include <unistd.h># include <stdlib.h># include <string.h># include <ctype.h> # include "includes.h"# include "priv/alt_file.h"# include "sys/alt_cache.h"# include "sys/alt_alarm.h"# include "system.h"# include "io.h"# include "alt_types.h" /*SGDMA Library*/# include <altera_avalon_sgdma.h># include <altera_avalon_sgdma_descriptor.h># include <altera_avalon_sgdma_regs.h> /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// alt_sgdma_dev * transmit_DMA; alt_sgdma_dev * receive_DMA; alt_u32 *tx_ptr; alt_u32 *rx_ptr; alt_sgdma_descriptor *desc = (alt_sgdma_descriptor*)INPUT_RAM_BASE ; alt_sgdma_descriptor *desc1 = (alt_sgdma_descriptor*)OUTPUT_RAM_BASE ; /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// void init_FFT_sgdma() { /* Open a SG-DMA for MM-->ST and ST-->MM (two SG-DMAs are present) */ transmit_DMA = alt_avalon_sgdma_open("/dev/sgdma_mm_to_st_fft"); receive_DMA = alt_avalon_sgdma_open("/dev/sgdma_st_to_mm_fft"); // Making sure the SG-DMAs were opened correctly if(transmit_DMA == NULL || receive_DMA == NULL) printf("Could not open the SG-DMA of FFT\n"); add pointer to the input and output memory. //tx_ptr pointer on memory where i will write input data tx_ptr = (alt_u32 *) (INPUT_RAM_BASE+ ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE); //rx_ptr pointer on memory where i can read output data rx_ptr = (alt_u32 *) (OUTPUT_RAM_BASE+ ALTERA_AVALON_SGDMA_DESCRIPTOR_SIZE); } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// void Hardware_fourier_trans (N) { int i; alt_8 *s0= (alt_8*)tx_ptr; for(i = 0; i < N; i++) { tx_ptr = (alt_u32) (sig); //sig[1024] is array of input Signal //////////////////////////////////////////////// ///////* maybe you will face problem whith arrange bytes whish transmit by SGDMA so you should rearrange bytes when you read from memory */ //////////////////////////////////////////////// } // Construct descriptors in the same input and output memory. // here i use just one descriptorfor, if you want more than one replace "NULL" with name of next descriptor. alt_avalon_sgdma_construct_mem_to_stream_desc(desc,NULL,tx_ptr, (alt_u16)4096,0,1,1,0); alt_avalon_sgdma_construct_stream_to_mem_desc(desc1,NULL,rx_ptr,0,0); //start transfer data alt_avalon_sgdma_do_async_transfer(transmit_DMA, desc); //wait to finish while (IORD(SGDMA_MM_TO_ST_FFT_BASE,0)!=12) {}; //start receive data alt_avalon_sgdma_do_async_transfer(receive_DMA, desc1); while (IORD(SGDMA_ST_TO_MM_FFT_BASE,0)!=14) {}; //wait to finish short *s1= (alt_8*)rx_ptr; //calculate amplitude for (i=0;i<1024;i++) {sig[i]=-1*sqrt(pow(s1[2*i],2)+pow(s1[2*i+1],2));} } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// int main(void) { init_FFT_sgdma(); return 0; } Good Luck - Altera_Forum
Honored Contributor
What does your include.h file look like? Is that were you define pow() and sqrt()?
- Altera_Forum
Honored Contributor
This is my include.h:
------------------- # ifndef __INCLUDES_H__# define __INCLUDES_H__ /* ********************************************************************************************************* * uC/OS-II * The Real-Time Kernel * * (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL * All Rights Reserved * * MASTER INCLUDE FILE ********************************************************************************************************* */ # ifdef __cplusplus extern "C" {# endif /* __cplusplus */ # include "os_cpu.h"# include "os_cfg.h"# include "ucos_ii.h" # ifdef ONT_GLOBALS# define ONT_EXT# else# define ONT_EXT extern# endif /* ********************************************************************************************************* * DATA TYPES ********************************************************************************************************* */ typedef struct { char TaskName[30]; INT16U TaskCtr; INT16U TaskExecTime; INT32U TaskTotExecTime; } TASK_USER_DATA; /* ********************************************************************************************************* * VARIABLES ********************************************************************************************************* */ ONT_EXT TASK_USER_DATA TaskUserData[10]; /* ********************************************************************************************************* * FUNCTION PROTOTYPES ********************************************************************************************************* */ void DispTaskStat(INT8U id); # ifdef __cplusplus }# endif /* __cplusplus */ # endif /* __INCLUDES_H__ */ - Altera_Forum
Honored Contributor
Thanks Majd,
I have an update for anyone else that may have experienced the same issue: 1. Following Majd's example code, I built my SOPC just as he recommended. 2. Everything seemed to be ok, except my SGDMA_st_mm component never sent any data out. (see C code below) // Exert from file8.c //start transfer data alt_avalon_sgdma_do_async_transfer(transmit_DMA, desc); //wait to finish while (IORD(SGDMA_MM_TO_ST_FFT_BASE,0)!=12) {}; //start receive data alt_avalon_sgdma_do_async_transfer(receive_DMA, desc1); while (IORD(SGDMA_ST_TO_MM_FFT_BASE,0)!=14) {}; //wait to finish.... //(THIS NEVER HAPPENED!! THE CODE WAS STUCK AND AFTER DEBUGGING I // REALIZED THAT IT MUST HAVE BEEN THE FFT COMPONENT THAT WAS // NOT WORKING PROPERLY...WHAT ELSE COULD IT HAVE BEEN RIGHT?? 3. I then went back to the avalon wrapper that Majd provided in the same zip file. This file is written in verilog. Herein lies the issue: - My entire design (with the exception of some megacore-generated files), was written in VHDL. Using the verilig wrapper should not have posed an issue, since the SOPC builder analyzes the input file an generates yet another file that encapsulates the wrapper. The mere fact that the file was described in verilog was not the issue. - However, I looked over the verilog file and discovered a few things that concerned me (BTW, im not a verilog coder, but I learned enough to parse through the file): 1. There was no fft_pts input for the wrapped FFT component (Possibly not an issue, if your design assigns that signal properly, perhaps outside of the SOPC). Since my FFT component needed the input, and there was no other external port to feed the FFT component, I added a register for this input, WITHOUT PROPERLY REGISTERING THE SIGNAL, i.e. always@ (posedge clk). I just wrote "reg fft_pts and connected the register to the intantiated FFT's fftpts_in port. (MISTAKE# 1) 2. My fft component needed both real and imaginary component. The wrapper however, assigns 0 to the imaginary component. This is not an issue if your input contains only real data; my input had real and imaginary data. I then split the avalon_mm_to_st into 2 16-bit parts- The first 16-bits were assigned directly to the real input of the FFT, the lower 16-bits were assigned to the imaginary input to the FFT (Your fft may have a different precision, but the punchline is since the avalon interface only has 1 data port, you have to encapsalate inside of that 1 port). 3. Applying the same logic above, I added a register for the inverse signal to the FFT. Once again, if you have external signals that connect to the inverse, you may be able to approach it differently. Next I regenerated my SOPC, along with the new avalon_wrapper component. However, my code was still getting stuck at the same spot (see code above). I then figured that the FFT component was not working at all, but why? SOLUTION: I registered the inverse and fftpts_in registers PROPERLY. Simply declaring "reg [10 :0] fftpts_in" and "reg inverse" was not enough to truly register the signal, a prerequisite for the FFT component to work properly. What Majd provided in the zip file above really works! If you have any questions or need help getting your FFT component working with the SGDMA, Majd or myself can provide you with some additional help. Just post to the thread and fire away. EDIT: My code no longer stalls at the spot. Once the fft works properly, the avalon_st_mm interface will infact continue properly. Thanks Majd! - Altera_Forum
Honored Contributor
Hi Marlon Winder
thank you very much for you notice. when i posted my example here i posted it as it works in my application. you can see i did not use imag input or invers Signal...because doesnt need it. anyway when somebody want to use this example, he should read about SGDMA and FFT core then understand the example. thank Marlon for you notice, and i hope to have success in your Project. - Altera_Forum
Honored Contributor
So, now im having another issue. It appears that when I read data from the output_Ram component, the bytes are swapped. For the 32-bits of data read, bytes 4 and 1 are swapped and bytes 3 and 2 are swapped.
To get around this issue, I just made a byte pointer (alt_8 or alt_u8) and casted the rx_ptr to to a byte pointer : (alt_8) *byte_ptr = (alt_8*) rx_ptr; And then printed the bytes in the correct order using printf. However, I am now concerned that the input bytes maybe having the same issue. Majd, I noticed the note about the ordering of the bytes for the input. Do you think that changing the I/O Ordering parameter for the FFT component could also remedy the byte arrangements? Has anyone tried this approach?