Forum Discussion
Altera_Forum
Honored Contributor
11 years ago --- 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