Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

create circular buffer form RAM ????

i read about circulr buffer in wiki and i want to use RAM to create a circular buffer, so what should i do i will choose what kind of ram( dual ram or single ram ) ????

Read / Write Countsedit]Another solution is to keep counts of the number of items written to and read from the circular buffer. Both counts are stored in signed integer variables with numerical limits larger than the number of items that can be stored and are allowed to wrap freely.
The unsigned difference (write_count - read_count) always yields the number of items placed in the buffer and not yet retrieved. This can indicate that the buffer is empty, partially full, completely full (without waste of a storage location) or in a state of overrun.
The advantage is:
The source and sink of data can implement independent policies for dealing with a full buffer and overrun while adhering to the rule that only the source of data modifies the write count and only the sink of data modifies the read count. This can result in elegant and robust circular buffer implementations even in multi-threaded environments.
The disadvantage is:
You need two additional variables.
Absolute indicesedit]It is possible to optimize the previous solution by using indices instead of pointers: indices can store read/write counts instead of the offset from start of the buffer, the separate variables in the above solution are removed and relative indices are obtained on the fly by division modulo the buffer's length.
The advantage is:
No extra variables are needed.
The disadvantages are:
Every access needs an additional modulo operation.
If counter wrap is possible, complex logic can be needed if the buffer's length is not a divisor of the counter's capacity.
On binary computers, both of these disadvantages disappear if the buffer's length is a power of two—at the cost of a constraint on possible buffers lengths.
here is the way i want to do

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Why do you want a circular buffer? what is the application? what have you done so far?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Why do you want a circular buffer? what is the application? what have you done so far?

    --- Quote End ---

    i want to bult a FIR filter, and on the internet they suggest use circular buffer, and because the circular buffer need to be buffering the signal from the audio codec (data stream ). before i try to use flip-flip d for my filter but i doesnt work so i change the way to think about buffer
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Are you sure the circular buffer isnt intended for a software approach? On an FPGA the data stream is constant, and the FIR is just a pipe delay, so there is no need for any buffering, unless you are trying to do some sort of time delay filtering...

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Are you sure the circular buffer isnt intended for a software approach? On an FPGA the data stream is constant, and the FIR is just a pipe delay, so there is no need for any buffering, unless you are trying to do some sort of time delay filtering...

    --- Quote End ---

    // --------------------------------------------------------------------
    assign	TD_RESET	=	1'b1;	//	Allow 27 MHz
    assign	AUD_ADCLRCK	=	AUD_DACLRCK;
    assign	AUD_XCK		=	AUD_CTRL_CLK;
    Reset_Delay			r0	(	.iCLK(CLOCK_50),.oRESET(DLY_RST)	);
    VGA_Audio_PLL 		p1	(	.areset(~DLY_RST),.inclk0(CLOCK_27),.c0(VGA_CTRL_CLK),.c1(AUD_CTRL_CLK),.c2(VGA_CLK)	);
    I2C_AV_Config 		u3	(	//	Host Side
    							.iCLK(CLOCK_50),
    							.iRST_N(KEY),
    							//	I2C Side
    							.I2C_SCLK(I2C_SCLK),
    							.I2C_SDAT(I2C_SDAT)	);
    AUDIO_DAC_ADC 			u4	(	//	Audio Side
    							.oAUD_BCK(AUD_BCLK),
    							.oAUD_DATA(AUD_DACDAT),
    							.oAUD_LRCK(AUD_DACLRCK),
    							.oAUD_inL(audio_inL), // audio data from ADC 
    							.oAUD_inR(audio_inR), // audio data from ADC 
    							.iAUD_ADCDAT(AUD_ADCDAT),
    							.iAUD_extL(audio_outL), // audio data to DAC
    							.iAUD_extR(audio_outR), // audio data to DAC
    							//	Control Signals
    							//.iSrc_Select(SW),
    				            .iCLK_18_4(AUD_CTRL_CLK),
    							.iRST_N(DLY_RST)
    							);
    /// reset //////////////////////////////////////						
    //state machine start up	
    wire reset; 
    // reset control
    assign reset = ~KEY;
    ///////////////////////////////////////////////
    // state variable 
    reg  state ;
    //oneshot gen to sync to audio clock
    reg last_clk ; 
    // output to audio DAC
    reg signed  audio_outL, audio_outR ;
    // input from audio ADC
    wire signed  audio_inL, audio_inR;
    		
    /// memory for phase shifter /////////////////////////////////////////
    //memory control
    reg we; //write enable--active high
    wire  read_data; 
    reg   write_data;
    reg  addr_reg;
    //pointers into the shift register
    //200 samples at 48kHz for 1/4 cycle 60 Hz noise
    reg  ptr_in, ptr_out; 
    //make the phase shift register
    ram_infer PhaseShifter(read_data, addr_reg, write_data, we, CLOCK_50);	
    //////////////////////////////////////////////////////////////////////
    /// LMS /////////////////////////////////////////////////////////////
    // LMS registers
    // 2 weights
    reg signed  w1, w2;
    // 2 inputs
    reg signed  ref60, shifted_ref60 ;
    // error output (main output)
    wire signed  error_out ;
    // two product terms
    wire signed  w1_x_ref, w2_x_shifted_ref;
    // mult for weight times ref and weight times phase-shifted ref
    signed_mult w1xRef(w1_x_ref, w1, ref60);
    signed_mult w2xRefShifted(w2_x_shifted_ref, w2, shifted_ref60) ;
    //assume noisy signal is on right channel, ref on left channel
    assign error_out = {audio_inR, 2'h0} - (w1_x_ref + w2_x_shifted_ref);
    //////////////////////////////////////////////////////////////////////
    /*
    // loopback test
    always @ (posedge AUD_DACLRCK)
    begin
    	audio_outL <= audio_inL;
    	audio_outR <= audio_inR;
    end
    */
    //debug readouts
    assign LEDG = state;
    assign LEDR = ptr_out;
    //Run the state machine FAST so that it completes in one 
    //audio cycle
    always @ (posedge CLOCK_27)
    begin
    	if (reset)
    	begin
    		ptr_out <= 8'h1 ; // beginning of shift register
    		ptr_in <= 8'h0 ;
    		we <= 1'h0 ; 
    		state <= 4'd8 ; //turn off the state machine	
    		//last_clk <= 1'h1;
    	end
    	
    	else begin
    		case (state)
    	
    			1: 
    			begin
    				// set up read ptr_out data
    				addr_reg <= ptr_out;
    				we <= 1'h0;
    				
    				// next state
    				state <= 4'd2;
    			end
    	
    			2: 
    			begin
    				//get ptr_out data
    				shifted_ref60 <= {read_data, 2'h0} ;
    					
    				// set up write ptr_in data
    				addr_reg <= ptr_in;
    				we <= 1'h1;
    				write_data <= audio_inL ;
    				
    				// store current ref channel
    				ref60 <= {audio_inL, 2'h0} ;
    				
    				// make some output
    				// original signal in R channel
    				// denoised signal in L channel
    				// audio seems to negate signal, so invert it
    				audio_outR <= -audio_inR ;
    				audio_outL <= -error_out;
    				
    				// next state
    				state <= 4'd3;
    			end
    			
    			3:
    			begin
    				// turn off memroy write
    				we <= 1'h0;
    				// update weights
    				w1 <= w1 + (((ref60)? -error_out : error_out)>>>10) ;
    				w2 <= w2 + (((shifted_ref60)? -error_out : error_out)>>>10) ;
    				// next state
    				state <= 4'd5;
    			end
    			
    			
    			5: 
    			begin
    				// phase shifter pointer control
    				// update write pointer
    				if (ptr_in == 8'd200) //200
    					ptr_in <= 8'h0;
    				else
    					ptr_in <= ptr_in + 8'h1 ;
    					
    				// update read pointer
    				if (ptr_out == 8'd200)
    					ptr_out <= 8'h0;
    				else
    					ptr_out <= ptr_out + 8'h1 ;
    				
    				//next state is end state
    				state <= 4'd8;
    			end
    			
    			8:
    			begin
    				// wait for the audio clock and one-shot it
    				if (AUD_DACLRCK && last_clk==1)
    				begin
    					state <= 4'd1 ;
    					last_clk <= 1'h0 ;
    				end
    				// reset the one-shot memory
    				else if (~AUD_DACLRCK && last_clk==0)
    				begin
    					last_clk <= 1'h1 ;
    				end	
    			end
    			
    			default:
    			begin
    				// default state is end state
    				state <= 4'd8 ;
    			end
    		endcase
    	end
    end	
    endmodule
    //////////////////////////////////////////////////
    //// M4k ram for circular buffer /////////////////
    //////////////////////////////////////////////////
    // Synchronous RAM 
    // modified for 16 bit access
    // of 200 words to tune for 1/4 cycle at 60 Hz
    module ram_infer (q, a, d, we, clk);
    output reg   q;
    input  d;
    input  a;
    input we, clk;
     
    reg  mem ;
    	always @ (posedge clk) 
    	begin
    		if (we) mem <= d;
    		q <= mem ;
    	end
    endmodule 
    //////////////////////////////////////////////////
    //////////////////////////////////////////////////
    //// signed mult of 2.16 format 2'comp////////////
    //////////////////////////////////////////////////
    module signed_mult (out, a, b);
    	output 			out;
    	input 	signed	 	a;
    	input 	signed	 	b;
    	
    	wire	signed		out;
    	wire 	signed		mult_out;
    	assign mult_out = a * b;
    	//assign out = mult_out;
    	assign out = {mult_out, mult_out};
    endmodule
    //////////////////////////////////////////////////

    here is the verilog code search from the internet, they use circular buffer, now i want to do it with VHDL code