// -------------------------------------------------------------------- // -------------------------------------------------------------------- // // Major Functions: Audio Filter modules // 2nd order IIR module // 4th order IIR module // 6th order IIR module // Matlab pgm at end of code to convert Matlab filter to Verilog // -------------------------------------------------------------------- // // Revision History : // -------------------------------------------------------------------- // Bruce R Land, Cornell University, Nov 2007 // -------------------------------------------------------------------- module DE2_Default ( //////////////////// Clock Input //////////////////// CLOCK_27, // 27 MHz CLOCK_50, // 50 MHz EXT_CLOCK, // External Clock //////////////////// Push Button //////////////////// KEY, // Pushbutton[3:0] //////////////////// DPDT Switch //////////////////// SW, // Toggle Switch[17:0] //////////////////// 7-SEG Dispaly //////////////////// HEX0, // Seven Segment Digit 0 HEX1, // Seven Segment Digit 1 HEX2, // Seven Segment Digit 2 HEX3, // Seven Segment Digit 3 HEX4, // Seven Segment Digit 4 HEX5, // Seven Segment Digit 5 HEX6, // Seven Segment Digit 6 HEX7, // Seven Segment Digit 7 //////////////////////// LED //////////////////////// LEDG, // LED Green[8:0] LEDR, // LED Red[17:0] //////////////////////// UART //////////////////////// UART_TXD, // UART Transmitter UART_RXD, // UART Receiver //////////////////////// IRDA //////////////////////// IRDA_TXD, // IRDA Transmitter IRDA_RXD, // IRDA Receiver ///////////////////// SDRAM Interface //////////////// DRAM_DQ, // SDRAM Data bus 16 Bits DRAM_ADDR, // SDRAM Address bus 12 Bits DRAM_LDQM, // SDRAM Low-byte Data Mask DRAM_UDQM, // SDRAM High-byte Data Mask DRAM_WE_N, // SDRAM Write Enable DRAM_CAS_N, // SDRAM Column Address Strobe DRAM_RAS_N, // SDRAM Row Address Strobe DRAM_CS_N, // SDRAM Chip Select DRAM_BA_0, // SDRAM Bank Address 0 DRAM_BA_1, // SDRAM Bank Address 0 DRAM_CLK, // SDRAM Clock DRAM_CKE, // SDRAM Clock Enable //////////////////// Flash Interface //////////////// FL_DQ, // FLASH Data bus 8 Bits FL_ADDR, // FLASH Address bus 22 Bits FL_WE_N, // FLASH Write Enable FL_RST_N, // FLASH Reset FL_OE_N, // FLASH Output Enable FL_CE_N, // FLASH Chip Enable //////////////////// SRAM Interface //////////////// SRAM_DQ, // SRAM Data bus 16 Bits SRAM_ADDR, // SRAM Address bus 18 Bits SRAM_UB_N, // SRAM High-byte Data Mask SRAM_LB_N, // SRAM Low-byte Data Mask SRAM_WE_N, // SRAM Write Enable SRAM_CE_N, // SRAM Chip Enable SRAM_OE_N, // SRAM Output Enable //////////////////// ISP1362 Interface //////////////// OTG_DATA, // ISP1362 Data bus 16 Bits OTG_ADDR, // ISP1362 Address 2 Bits OTG_CS_N, // ISP1362 Chip Select OTG_RD_N, // ISP1362 Write OTG_WR_N, // ISP1362 Read OTG_RST_N, // ISP1362 Reset OTG_FSPEED, // USB Full Speed, 0 = Enable, Z = Disable OTG_LSPEED, // USB Low Speed, 0 = Enable, Z = Disable OTG_INT0, // ISP1362 Interrupt 0 OTG_INT1, // ISP1362 Interrupt 1 OTG_DREQ0, // ISP1362 DMA Request 0 OTG_DREQ1, // ISP1362 DMA Request 1 OTG_DACK0_N, // ISP1362 DMA Acknowledge 0 OTG_DACK1_N, // ISP1362 DMA Acknowledge 1 //////////////////// LCD Module 16X2 //////////////// LCD_ON, // LCD Power ON/OFF LCD_BLON, // LCD Back Light ON/OFF LCD_RW, // LCD Read/Write Select, 0 = Write, 1 = Read LCD_EN, // LCD Enable LCD_RS, // LCD Command/Data Select, 0 = Command, 1 = Data LCD_DATA, // LCD Data bus 8 bits //////////////////// SD_Card Interface //////////////// SD_DAT, // SD Card Data SD_DAT3, // SD Card Data 3 SD_CMD, // SD Card Command Signal SD_CLK, // SD Card Clock //////////////////// USB JTAG link //////////////////// TDI, // CPLD -> FPGA (data in) TCK, // CPLD -> FPGA (clk) TCS, // CPLD -> FPGA (CS) TDO, // FPGA -> CPLD (data out) //////////////////// I2C //////////////////////////// I2C_SDAT, // I2C Data I2C_SCLK, // I2C Clock //////////////////// PS2 //////////////////////////// PS2_DAT, // PS2 Data PS2_CLK, // PS2 Clock //////////////////// VGA //////////////////////////// VGA_CLK, // VGA Clock VGA_HS, // VGA H_SYNC VGA_VS, // VGA V_SYNC VGA_BLANK, // VGA BLANK VGA_SYNC, // VGA SYNC VGA_R, // VGA Red[9:0] VGA_G, // VGA Green[9:0] VGA_B, // VGA Blue[9:0] //////////// Ethernet Interface //////////////////////// ENET_DATA, // DM9000A DATA bus 16Bits ENET_CMD, // DM9000A Command/Data Select, 0 = Command, 1 = Data ENET_CS_N, // DM9000A Chip Select ENET_WR_N, // DM9000A Write ENET_RD_N, // DM9000A Read ENET_RST_N, // DM9000A Reset ENET_INT, // DM9000A Interrupt ENET_CLK, // DM9000A Clock 25 MHz //////////////// Audio CODEC //////////////////////// AUD_ADCLRCK, // Audio CODEC ADC LR Clock AUD_ADCDAT, // Audio CODEC ADC Data AUD_DACLRCK, // Audio CODEC DAC LR Clock AUD_DACDAT, // Audio CODEC DAC Data AUD_BCLK, // Audio CODEC Bit-Stream Clock AUD_XCK, // Audio CODEC Chip Clock //////////////// TV Decoder //////////////////////// TD_DATA, // TV Decoder Data bus 8 bits TD_HS, // TV Decoder H_SYNC TD_VS, // TV Decoder V_SYNC TD_RESET, // TV Decoder Reset //////////////////// GPIO //////////////////////////// GPIO_0, // GPIO Connection 0 GPIO_1 // GPIO Connection 1 ); //////////////////////// Clock Input //////////////////////// input CLOCK_27; // 27 MHz input CLOCK_50; // 50 MHz input EXT_CLOCK; // External Clock //////////////////////// Push Button //////////////////////// input [3:0] KEY; // Pushbutton[3:0] //////////////////////// DPDT Switch //////////////////////// input [17:0] SW; // Toggle Switch[17:0] //////////////////////// 7-SEG Dispaly //////////////////////// output [6:0] HEX0; // Seven Segment Digit 0 output [6:0] HEX1; // Seven Segment Digit 1 output [6:0] HEX2; // Seven Segment Digit 2 output [6:0] HEX3; // Seven Segment Digit 3 output [6:0] HEX4; // Seven Segment Digit 4 output [6:0] HEX5; // Seven Segment Digit 5 output [6:0] HEX6; // Seven Segment Digit 6 output [6:0] HEX7; // Seven Segment Digit 7 //////////////////////////// LED //////////////////////////// output [8:0] LEDG; // LED Green[8:0] output [17:0] LEDR; // LED Red[17:0] //////////////////////////// UART //////////////////////////// output UART_TXD; // UART Transmitter input UART_RXD; // UART Receiver //////////////////////////// IRDA //////////////////////////// output IRDA_TXD; // IRDA Transmitter input IRDA_RXD; // IRDA Receiver /////////////////////// SDRAM Interface //////////////////////// inout [15:0] DRAM_DQ; // SDRAM Data bus 16 Bits output [11:0] DRAM_ADDR; // SDRAM Address bus 12 Bits output DRAM_LDQM; // SDRAM Low-byte Data Mask output DRAM_UDQM; // SDRAM High-byte Data Mask output DRAM_WE_N; // SDRAM Write Enable output DRAM_CAS_N; // SDRAM Column Address Strobe output DRAM_RAS_N; // SDRAM Row Address Strobe output DRAM_CS_N; // SDRAM Chip Select output DRAM_BA_0; // SDRAM Bank Address 0 output DRAM_BA_1; // SDRAM Bank Address 0 output DRAM_CLK; // SDRAM Clock output DRAM_CKE; // SDRAM Clock Enable //////////////////////// Flash Interface //////////////////////// inout [7:0] FL_DQ; // FLASH Data bus 8 Bits output [21:0] FL_ADDR; // FLASH Address bus 22 Bits output FL_WE_N; // FLASH Write Enable output FL_RST_N; // FLASH Reset output FL_OE_N; // FLASH Output Enable output FL_CE_N; // FLASH Chip Enable //////////////////////// SRAM Interface //////////////////////// inout [15:0] SRAM_DQ; // SRAM Data bus 16 Bits output [17:0] SRAM_ADDR; // SRAM Address bus 18 Bits output SRAM_UB_N; // SRAM High-byte Data Mask output SRAM_LB_N; // SRAM Low-byte Data Mask output SRAM_WE_N; // SRAM Write Enable output SRAM_CE_N; // SRAM Chip Enable output SRAM_OE_N; // SRAM Output Enable //////////////////// ISP1362 Interface //////////////////////// inout [15:0] OTG_DATA; // ISP1362 Data bus 16 Bits output [1:0] OTG_ADDR; // ISP1362 Address 2 Bits output OTG_CS_N; // ISP1362 Chip Select output OTG_RD_N; // ISP1362 Write output OTG_WR_N; // ISP1362 Read output OTG_RST_N; // ISP1362 Reset output OTG_FSPEED; // USB Full Speed, 0 = Enable, Z = Disable output OTG_LSPEED; // USB Low Speed, 0 = Enable, Z = Disable input OTG_INT0; // ISP1362 Interrupt 0 input OTG_INT1; // ISP1362 Interrupt 1 input OTG_DREQ0; // ISP1362 DMA Request 0 input OTG_DREQ1; // ISP1362 DMA Request 1 output OTG_DACK0_N; // ISP1362 DMA Acknowledge 0 output OTG_DACK1_N; // ISP1362 DMA Acknowledge 1 //////////////////// LCD Module 16X2 //////////////////////////// inout [7:0] LCD_DATA; // LCD Data bus 8 bits output LCD_ON; // LCD Power ON/OFF output LCD_BLON; // LCD Back Light ON/OFF output LCD_RW; // LCD Read/Write Select, 0 = Write, 1 = Read output LCD_EN; // LCD Enable output LCD_RS; // LCD Command/Data Select, 0 = Command, 1 = Data //////////////////// SD Card Interface //////////////////////// inout SD_DAT; // SD Card Data inout SD_DAT3; // SD Card Data 3 inout SD_CMD; // SD Card Command Signal output SD_CLK; // SD Card Clock //////////////////////// I2C //////////////////////////////// inout I2C_SDAT; // I2C Data output I2C_SCLK; // I2C Clock //////////////////////// PS2 //////////////////////////////// input PS2_DAT; // PS2 Data input PS2_CLK; // PS2 Clock //////////////////// USB JTAG link //////////////////////////// input TDI; // CPLD -> FPGA (data in) input TCK; // CPLD -> FPGA (clk) input TCS; // CPLD -> FPGA (CS) output TDO; // FPGA -> CPLD (data out) //////////////////////// VGA //////////////////////////// output VGA_CLK; // VGA Clock output VGA_HS; // VGA H_SYNC output VGA_VS; // VGA V_SYNC output VGA_BLANK; // VGA BLANK output VGA_SYNC; // VGA SYNC output [9:0] VGA_R; // VGA Red[9:0] output [9:0] VGA_G; // VGA Green[9:0] output [9:0] VGA_B; // VGA Blue[9:0] //////////////// Ethernet Interface //////////////////////////// inout [15:0] ENET_DATA; // DM9000A DATA bus 16Bits output ENET_CMD; // DM9000A Command/Data Select, 0 = Command, 1 = Data output ENET_CS_N; // DM9000A Chip Select output ENET_WR_N; // DM9000A Write output ENET_RD_N; // DM9000A Read output ENET_RST_N; // DM9000A Reset input ENET_INT; // DM9000A Interrupt output ENET_CLK; // DM9000A Clock 25 MHz //////////////////// Audio CODEC //////////////////////////// output AUD_ADCLRCK; // Audio CODEC ADC LR Clock input AUD_ADCDAT; // Audio CODEC ADC Data output AUD_DACLRCK; // Audio CODEC DAC LR Clock output AUD_DACDAT; // Audio CODEC DAC Data output AUD_BCLK; // Audio CODEC Bit-Stream Clock output AUD_XCK; // Audio CODEC Chip Clock //////////////////// TV Devoder //////////////////////////// input [7:0] TD_DATA; // TV Decoder Data bus 8 bits input TD_HS; // TV Decoder H_SYNC input TD_VS; // TV Decoder V_SYNC output TD_RESET; // TV Decoder Reset //////////////////////// GPIO //////////////////////////////// inout [35:0] GPIO_0; // GPIO Connection 0 inout [35:0] GPIO_1; // GPIO Connection 1 // LCD ON assign LCD_ON = 1'b0; assign LCD_BLON = 1'b0; // All inout port turn to tri-state assign DRAM_DQ = 16'hzzzz; assign FL_DQ = 8'hzz; assign SRAM_DQ = 16'hzzzz; assign OTG_DATA = 16'hzzzz; assign SD_DAT = 1'bz; assign ENET_DATA = 16'hzzzz; assign GPIO_0 = 36'hzzzzzzzzz; assign GPIO_1 = 36'hzzzzzzzzz; wire VGA_CTRL_CLK; wire AUD_CTRL_CLK; wire DLY_RST; 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[0]), // 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[17]), .iCLK_18_4(AUD_CTRL_CLK), .iRST_N(DLY_RST) ); /* AudioCodecControllerPE 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[17]), .iCLK(AUD_CTRL_CLK), .iRST_N(DLY_RST) ); */ /// reset /////////////////////////////////////////////////////// //state machine start up wire reset; // reset control assign reset = ~KEY[0]; /// audio stuff ///////////////////////////////////////////////// // output to audio DAC wire signed [15:0] audio_outL, audio_outR ; // input from audio ADC wire signed [15:0] audio_inL, audio_inR ; // filter outputs wire signed [15:0] filter2_out, filter4_out, filter6_out ; //reg signed [15:0] filter_out_buffer2 ; // make some output // original signal in R channel // filtered signal in L channel assign audio_outR = audio_inR ; assign audio_outL = filter6_out ; //Filter: cutoff=0.100000 //Filter: cutoff=0.200000 IIR2sos filter2( .audio_out (filter2_out), .audio_in (audio_inR), .b11 (18'h10300), .b12 (18'h0), .b13 (18'h30300), .a12 (18'h1038E), .a13 (18'h30173), .gain(18'hFD18), .state_clk(AUD_CTRL_CLK), .lr_clk(AUD_DACLRCK), .reset(reset) ) ; //end filter //Filter: cutoff=0.100000 //Filter: cutoff=0.200000 IIR4sos filter4( .audio_out (filter4_out), .audio_in (audio_inR), .b11 (18'h10300), .b12 (18'h10500), .b13 (18'h10300), .a12 (18'h1037A), .a13 (18'h30185), .b21 (18'h10300), .b22 (18'h30500), .b23 (18'h10300), .a22 (18'h103BC), .a23 (18'h301B0), .gain(18'hF749), .state_clk(AUD_CTRL_CLK), .lr_clk(AUD_DACLRCK), .reset(reset) ) ; //end filter //Filter: cutoff=0.100000 //Filter: cutoff=0.200000 IIR6sos filter6( .audio_out (filter6_out), .audio_in (audio_inR), .b11 (18'h10300), .b12 (18'h2E112), .b13 (18'h301FF), .a12 (18'h1038E), .a13 (18'h30173), .b21 (18'h10300), .b22 (18'h10500), .b23 (18'h10300), .a22 (18'h1037F), .a23 (18'h301A3), .b31 (18'h10300), .b32 (18'h303FF), .b33 (18'h101FF), .a32 (18'h103CB), .a33 (18'h301C9), .gain(18'hF17B), .state_clk(AUD_CTRL_CLK), .lr_clk(AUD_DACLRCK), .reset(reset) ) ; //end filter endmodule /////////////////////////////////////////////////////////////////// /// Second order IIR filter /////////////////////////////////////// /////////////////////////////////////////////////////////////////// module IIR2sos (audio_out, audio_in, b11, b12, b13, a12, a13, gain, state_clk, lr_clk, reset) ; // The filter is a "Direct Form II Transposed" // but is factored into two second order filters and a gain // // a(1)*y(n) = b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb) // - a(2)*y(n-1) - ... - a(na+1)*y(n-na) // // If a(1) is not equal to 1, FILTER normalizes the filter // coefficients by a(1). // // one audio sample, 16 bit, 2's complement output wire signed [15:0] audio_out ; // one audio sample, 16 bit, 2's complement input wire signed [15:0] audio_in ; // filter coefficients input wire [17:0] b11, b12, b13, a12, a13, gain ; input wire state_clk, lr_clk, reset ; /// filter vars ////////////////////////////////////////////////// wire [17:0] f_mac_new, f_coeff_x_value ; reg [17:0] f_coeff, f_mac_old, f_value ; // input to filters reg [17:0] x1_n ; // input history x(n-1), x(n-2) reg [17:0] x1_n1, x1_n2 ; // output history: y_n is the new filter output, BUT it is // immediately stored in f1_y_n1 for the next loop through // the filter state machine reg [17:0] f1_y_n1, f1_y_n2 ; // i/o conversion // int output of FP calc wire [9:0] audio_out_int ; reg [17:0] audio_out_FP ; wire [17:0] audio_in_FP ; int2fp f_input(audio_in_FP, audio_in[15:6], 0) ; fp2int f_output(audio_out_int, audio_out_FP, 0) ; assign audio_out = {audio_out_int, 6'h0} ; // MAC operation fpmult f_c_x_v (f_coeff_x_value, f_coeff, f_value); fpadd f_mac_add (f_mac_new, f_mac_old, f_coeff_x_value) ; // state variable reg [3:0] state ; //oneshot gen to sync to audio clock reg last_clk ; /////////////////////////////////////////////////////////////////// //Run the filter state machine FAST so that it completes in one //audio cycle always @ (posedge state_clk) begin if (reset) begin state <= 4'd15 ; //turn off the state machine end else begin case (state) 1: begin // set up b11*x(n) f_mac_old <= 18'd0 ; f_coeff <= b11 ; f_value <= audio_in_FP ; //register input x1_n <= audio_in_FP ; // next state state <= 4'd2; end 2: begin // set up b12*x(n-1) f_mac_old <= f_mac_new ; f_coeff <= b12 ; f_value <= x1_n1 ; // next state state <= 4'd3; end 3: begin // set up b13*x(n-2) f_mac_old <= f_mac_new ; f_coeff <= b13 ; f_value <= x1_n2 ; // next state state <= 4'd4; end 4: begin // set up a12*y(n-1) f_mac_old <= f_mac_new ; f_coeff <= a12 ; f_value <= f1_y_n1 ; // next state state <= 4'd5; end 5: begin // set up a13*y(n-2) f_mac_old <= f_mac_new ; f_coeff <= a13 ; f_value <= f1_y_n2 ; // next state state <= 4'd6; end 6: begin // get the output of the first SOS // and put it in the LAST output var // for the next pass thru the state machine f1_y_n1 <= f_mac_new ; // apply the final gain mult f_value <= f_mac_new ; f_coeff <= gain ; // update output history f1_y_n2 <= f1_y_n1 ; // update input history x1_n1 <= x1_n ; x1_n2 <= x1_n1 ; //next state state <= 4'd8; end 8: begin audio_out_FP <= f_coeff_x_value ; //next state state <= 4'd15; end 15: begin // wait for the audio clock and one-shot it if (lr_clk && last_clk==1) begin state <= 4'd1 ; last_clk <= 1'h0 ; end // reset the one-shot memory else if (~lr_clk && last_clk==0) begin last_clk <= 1'h1 ; end end default: begin // default state is end state state <= 4'd15 ; end endcase end end endmodule /////////////////////////////////////////////////////////////////// /// Fourth order IIR filter -- written as two SOS ///////////////// /////////////////////////////////////////////////////////////////// module IIR4sos (audio_out, audio_in, b11, b12, b13, a12, a13, b21, b22, b23, a22, a23, gain, state_clk, lr_clk, reset) ; // The filter is a "Direct Form II Transposed" // but is factored into two second order filters and a gain // // a(1)*y(n) = b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb) // - a(2)*y(n-1) - ... - a(na+1)*y(n-na) // // If a(1) is not equal to 1, FILTER normalizes the filter // coefficients by a(1). // // one audio sample, 16 bit, 2's complement output wire signed [15:0] audio_out ; // one audio sample, 16 bit, 2's complement input wire signed [15:0] audio_in ; // filter coefficients input wire [17:0] b11, b12, b13, a12, a13, b21, b22, b23, a22, a23, gain ; input wire state_clk, lr_clk, reset ; /// filter vars ////////////////////////////////////////////////// wire [17:0] f_mac_new, f_coeff_x_value ; reg [17:0] f_coeff, f_mac_old, f_value ; // input to filters reg [17:0] x1_n, x2_n ; // input history x(n-1), x(n-2) reg [17:0] x1_n1, x1_n2, x2_n1, x2_n2 ; // output history: y_n is the new filter output, BUT it is // immediately stored in f1_y_n1 for the next loop through // the filter state machine reg [17:0] f1_y_n1, f1_y_n2, f2_y_n1, f2_y_n2 ; // i/o conversion // int output of FP calc wire [9:0] audio_out_int ; reg [17:0] audio_out_FP ; wire [17:0] audio_in_FP ; int2fp f_input(audio_in_FP, audio_in[15:6], 0) ; fp2int f_output(audio_out_int, audio_out_FP, 0) ; assign audio_out = {audio_out_int, 6'h0} ; // MAC operation fpmult f_c_x_v (f_coeff_x_value, f_coeff, f_value); fpadd f_mac_add (f_mac_new, f_mac_old, f_coeff_x_value) ; // state variable reg [3:0] state ; //oneshot gen to sync to audio clock reg last_clk ; /////////////////////////////////////////////////////////////////// //Run the filter state machine FAST so that it completes in one //audio cycle always @ (posedge state_clk) begin if (reset) begin state <= 4'd15 ; //turn off the state machine end else begin case (state) 1: begin // set up b11*x(n) f_mac_old <= 18'd0 ; f_coeff <= b11 ; f_value <= audio_in_FP ; //register input x1_n <= audio_in_FP ; // next state state <= 4'd2; end 2: begin // set up b12*x(n-1) f_mac_old <= f_mac_new ; f_coeff <= b12 ; f_value <= x1_n1 ; // next state state <= 4'd3; end 3: begin // set up b13*x(n-2) f_mac_old <= f_mac_new ; f_coeff <= b13 ; f_value <= x1_n2 ; // next state state <= 4'd4; end 4: begin // set up a12*y(n-1) f_mac_old <= f_mac_new ; f_coeff <= a12 ; f_value <= f1_y_n1 ; // next state state <= 4'd5; end 5: begin // set up a13*y(n-2) f_mac_old <= f_mac_new ; f_coeff <= a13 ; f_value <= f1_y_n2 ; // next state state <= 4'd6; end 6: begin // get the output of the first SOS // and put it in the LAST output var // for the next pass thru the state machine f1_y_n1 <= f_mac_new ; // link first SOS to second SOS x2_n <= f_mac_new ; // update output history f1_y_n2 <= f1_y_n1 ; // update input history x1_n1 <= x1_n ; x1_n2 <= x1_n1 ; //next state state <= 4'd8; end 8: begin // set up b21*x(n) f_mac_old <= 18'd0 ; f_coeff <= b21 ; f_value <= x2_n ; // next state state <= 4'd9; end 9: begin // set up b22*x(n-1) f_mac_old <= f_mac_new ; f_coeff <= b22 ; f_value <= x2_n1 ; // next state state <= 4'd10; end 10: begin // set up b23*x(n-2) f_mac_old <= f_mac_new ; f_coeff <= b23 ; f_value <= x2_n2 ; // next state state <= 4'd11; end 11: begin // set up a22*y(n-1) f_mac_old <= f_mac_new ; f_coeff <= a22 ; f_value <= f2_y_n1 ; // next state state <= 4'd12; end 12: begin // set up a23*y(n-2) f_mac_old <= f_mac_new ; f_coeff <= a23 ; f_value <= f2_y_n2 ; // next state state <= 4'd13; end 13: begin // get the output // and put it in the LAST output var // for the next pass thru the state machine f2_y_n1 <= f_mac_new ; // apply the final gain mult f_value <= f_mac_new ; f_coeff <= gain ; // update output history f2_y_n2 <= f2_y_n1 ; // update input history x2_n1 <= x2_n ; x2_n2 <= x2_n1 ; //next state state <= 4'd14; end 14: begin audio_out_FP <= f_coeff_x_value ; //next state state <= 4'd15; end 15: begin // wait for the audio clock and one-shot it if (lr_clk && last_clk==1) begin state <= 4'd1 ; last_clk <= 1'h0 ; end // reset the one-shot memory else if (~lr_clk && last_clk==0) begin last_clk <= 1'h1 ; end end default: begin // default state is end state state <= 4'd15 ; end endcase end end endmodule /////////////////////////////////////////////////////////////////// /// Sixth order IIR filter -- written as 3 SOS //////////////////// /////////////////////////////////////////////////////////////////// module IIR6sos (audio_out, audio_in, b11, b12, b13, a12, a13, b21, b22, b23, a22, a23, b31, b32, b33, a32, a33, gain, state_clk, lr_clk, reset) ; // The filter is a "Direct Form II Transposed" // but is factored into two second order filters and a gain // // a(1)*y(n) = b(1)*x(n) + b(2)*x(n-1) + ... + b(nb+1)*x(n-nb) // - a(2)*y(n-1) - ... - a(na+1)*y(n-na) // // If a(1) is not equal to 1, FILTER normalizes the filter // coefficients by a(1). // // one audio sample, 16 bit, 2's complement output wire signed [15:0] audio_out ; // one audio sample, 16 bit, 2's complement input wire signed [15:0] audio_in ; // filter coefficients input wire [17:0] b11, b12, b13, a12, a13, b21, b22, b23, a22, a23, b31, b32, b33, a32, a33, gain ; input wire state_clk, lr_clk, reset ; /// filter vars ////////////////////////////////////////////////// wire [17:0] f_mac_new, f_coeff_x_value ; reg [17:0] f_coeff, f_mac_old, f_value ; // input to filters reg [17:0] x1_n, x2_n, x3_n ; // input history x(n-1), x(n-2) reg [17:0] x1_n1, x1_n2, x2_n1, x2_n2, x3_n1, x3_n2 ; // output history: y_n is the new filter output, BUT it is // immediately stored in f1_y_n1 for the next loop through // the filter state machine reg [17:0] f1_y_n1, f1_y_n2, f2_y_n1, f2_y_n2, f3_y_n1, f3_y_n2 ; // i/o conversion // int output of FP calc wire [9:0] audio_out_int ; reg [17:0] audio_out_FP ; wire [17:0] audio_in_FP ; int2fp f_input(audio_in_FP, audio_in[15:6], 0) ; fp2int f_output(audio_out_int, audio_out_FP, 0) ; assign audio_out = {audio_out_int, 6'h0} ; // MAC operation fpmult f_c_x_v (f_coeff_x_value, f_coeff, f_value); fpadd f_mac_add (f_mac_new, f_mac_old, f_coeff_x_value) ; // state variable reg [4:0] state ; //oneshot gen to sync to audio clock reg last_clk ; /////////////////////////////////////////////////////////////////// //Run the filter state machine FAST so that it completes in one //audio cycle always @ (posedge state_clk) begin if (reset) begin state <= 5'd31 ; //turn off the state machine end else begin case (state) 1: begin // set up b11*x(n) f_mac_old <= 18'd0 ; f_coeff <= b11 ; f_value <= audio_in_FP ; //register input x1_n <= audio_in_FP ; // next state state <= 4'd2; end 2: begin // set up b12*x(n-1) f_mac_old <= f_mac_new ; f_coeff <= b12 ; f_value <= x1_n1 ; // next state state <= 4'd3; end 3: begin // set up b13*x(n-2) f_mac_old <= f_mac_new ; f_coeff <= b13 ; f_value <= x1_n2 ; // next state state <= 4'd4; end 4: begin // set up a12*y(n-1) f_mac_old <= f_mac_new ; f_coeff <= a12 ; f_value <= f1_y_n1 ; // next state state <= 4'd5; end 5: begin // set up a13*y(n-2) f_mac_old <= f_mac_new ; f_coeff <= a13 ; f_value <= f1_y_n2 ; // next state state <= 4'd6; end 6: begin // get the output of the first SOS // and put it in the LAST output var // for the next pass thru the state machine f1_y_n1 <= f_mac_new ; // link first SOS to second SOS x2_n <= f_mac_new ; // update output history f1_y_n2 <= f1_y_n1 ; // update input history x1_n1 <= x1_n ; x1_n2 <= x1_n1 ; //next state state <= 4'd8; end 8: begin // set up b21*x(n) f_mac_old <= 18'd0 ; f_coeff <= b21 ; f_value <= x2_n ; // next state state <= 4'd9; end 9: begin // set up b22*x(n-1) f_mac_old <= f_mac_new ; f_coeff <= b22 ; f_value <= x2_n1 ; // next state state <= 4'd10; end 10: begin // set up b23*x(n-2) f_mac_old <= f_mac_new ; f_coeff <= b23 ; f_value <= x2_n2 ; // next state state <= 4'd11; end 11: begin // set up a22*y(n-1) f_mac_old <= f_mac_new ; f_coeff <= a22 ; f_value <= f2_y_n1 ; // next state state <= 4'd12; end 12: begin // set up a23*y(n-2) f_mac_old <= f_mac_new ; f_coeff <= a23 ; f_value <= f2_y_n2 ; // next state state <= 4'd13; end 13: begin // get the output // and put it in the LAST output var // for the next pass thru the state machine f2_y_n1 <= f_mac_new ; // link to next section x3_n <= f_mac_new ; // update output history f2_y_n2 <= f2_y_n1 ; // update input history x2_n1 <= x2_n ; x2_n2 <= x2_n1 ; //next state state <= 4'd14; end 14: begin // set up b31*x(n) f_mac_old <= 18'd0 ; f_coeff <= b31 ; f_value <= x3_n ; // next state state <= 5'd15; end 15: begin // set up b32*x(n-1) f_mac_old <= f_mac_new ; f_coeff <= b32 ; f_value <= x3_n1 ; // next state state <= 5'd16; end 16: begin // set up b33*x(n-2) f_mac_old <= f_mac_new ; f_coeff <= b33 ; f_value <= x3_n2 ; // next state state <= 5'd17; end 17: begin // set up a32*y(n-1) f_mac_old <= f_mac_new ; f_coeff <= a32 ; f_value <= f3_y_n1 ; // next state state <= 5'd18; end 18: begin // set up a33*y(n-2) f_mac_old <= f_mac_new ; f_coeff <= a33 ; f_value <= f3_y_n2 ; // next state state <= 5'd19; end 19: begin // get the output // and put it in the LAST output var // for the next pass thru the state machine f3_y_n1 <= f_mac_new ; // apply the final gain mult f_value <= f_mac_new ; f_coeff <= gain ; // update output history f3_y_n2 <= f3_y_n1 ; // update input history x3_n1 <= x3_n ; x3_n2 <= x3_n1 ; //next state state <= 5'd20; end 20: begin audio_out_FP <= f_coeff_x_value ; //next state state <= 5'd31; end 31: begin // wait for the audio clock and one-shot it if (lr_clk && last_clk==1) begin state <= 5'd1 ; last_clk <= 1'h0 ; end // reset the one-shot memory else if (~lr_clk && last_clk==0) begin last_clk <= 1'h1 ; end end default: begin // default state is end state state <= 5'd31 ; end endcase end end endmodule ////////////////////////////////////////////////////////// // floating point multiply // -- sign bit -- 8-bit exponent -- 9-bit mantissa // Similar to fp_mult from altera // NO denorms, no flags, no NAN, no infinity, no rounding! ////////////////////////////////////////////////////////// // f1 = {s1, e1, m1), f2 = {s2, e2, m2) // If either is zero (zero MSB of mantissa) then output is zero // If e1+e2<129 the result is zero (underflow) /////////////////////////////////////////////////////////// module fpmult (fout, f1, f2); input [17:0] f1, f2 ; output [17:0] fout ; wire [17:0] fout ; reg sout ; reg [8:0] mout ; reg [8:0] eout ; // 9-bits for overflow wire s1, s2; wire [8:0] m1, m2 ; wire [8:0] e1, e2, sum_e1_e2 ; // extend to 9 bits to avoid overflow wire [17:0] mult_out ; // raw multiplier output // parse f1 assign s1 = f1[17]; // sign assign e1 = {1'b0, f1[16:9]}; // exponent assign m1 = f1[8:0] ; // mantissa // parse f2 assign s2 = f2[17]; assign e2 = {1'b0, f2[16:9]}; assign m2 = f2[8:0] ; // first step in mult is to add extended exponents assign sum_e1_e2 = e1 + e2 ; // build output // raw integer multiply unsigned_mult mm(mult_out, m1, m2); // assemble output bits assign fout = {sout, eout[7:0], mout} ; always @(*) begin // if either is denormed or exponents are too small if ((m1[8]==1'd0) || (m2[8]==1'd0) || (sum_e1_e2 < 9'h82)) begin mout = 0; eout = 0; sout = 0; // output sign end else // both inputs are nonzero and no exponent underflow begin sout = s1 ^ s2 ; // output sign if (mult_out[17]==1) begin // MSB of product==1 implies normalized -- result >=0.5 eout = sum_e1_e2 - 9'h80; mout = mult_out[17:9] ; end else // MSB of product==0 implies result <0.5, so shift ome left begin eout = sum_e1_e2 - 9'h81; mout = mult_out[16:8] ; end end // nonzero mult logic end // always @(*) endmodule /////////////////////////////////////// // low level integer multiply // From Altera HDL style manual /////////////////////////////////////// module unsigned_mult (out, a, b); output [17:0] out; input [8:0] a; input [8:0] b; assign out = a * b; endmodule ///////////////////////////////////////////////////////////////////////////// // floating point Add // -- sign bit -- 8-bit exponent -- 9-bit mantissa // NO denorms, no flags, no NAN, no infinity, no rounding! ///////////////////////////////////////////////////////////////////////////// // f1 = {s1, e1, m1), f2 = {s2, e2, m2) // If either input is zero (zero MSB of mantissa) then output is the remaining input. // If either input is <(other input)/2**9 then output is the remaining input. // Sign of the output is the sign of the greater magnitude input // Add the two inputs if their signs are the same. // Subtract the two inputs (bigger-smaller) if their signs are different ////////////////////////////////////////////////////////////////////////////// module fpadd (fout, f1, f2); input [17:0] f1, f2 ; output [17:0] fout ; wire [17:0] fout ; wire sout ; reg [8:0] mout ; reg [7:0] eout ; reg [9:0] shift_small, denorm_mout ; //9th bit is overflow bit wire s1, s2 ; // input signs reg sb, ss ; // signs of bigger and smaller wire [8:0] m1, m2 ; // input mantissas reg [8:0] mb, ms ; // mantissas of bigger and smaller wire [7:0] e1, e2 ; // input exp wire [7:0] ediff ; // exponent difference reg [7:0] eb, es ; // exp of bigger and smaller reg [7:0] num_zeros ; // high order zeros in the difference calc // parse f1 assign s1 = f1[17]; // sign assign e1 = f1[16:9]; // exponent assign m1 = f1[8:0] ; // mantissa // parse f2 assign s2 = f2[17]; assign e2 = f2[16:9]; assign m2 = f2[8:0] ; // find biggest magnitude always @(*) begin if (e1>e2) // f1 is bigger begin sb = s1 ; // the bigger number (absolute value) eb = e1 ; mb = m1 ; ss = s2 ; // the smaller number es = e2 ; ms = m2 ; end else if (e2>e1) //f2 is bigger begin sb = s2 ; // the bigger number (absolute value) eb = e2 ; mb = m2 ; ss = s1 ; // the smaller number es = e1 ; ms = m1 ; end else // e1==e2, so need to look at mantissa to determine bigger/smaller begin if (m1>m2) // f1 is bigger begin sb = s1 ; // the bigger number (absolute value) eb = e1 ; mb = m1 ; ss = s2 ; // the smaller number es = e2 ; ms = m2 ; end else // f2 is bigger or same size begin sb = s2 ; // the bigger number (absolute value) eb = e2 ; mb = m2 ; ss = s1 ; // the smaller number es = e1 ; ms = m1 ; end end end //found the bigger number // sign of output is the sign of the bigger (magnitude) input assign sout = sb ; // form the output assign fout = {sout, eout, mout} ; // do the actual add: // -- equalize exponents // -- add/sub // -- normalize assign ediff = eb - es ; // the actual difference in exponents always @(*) begin if ((ms[8]==0) && (mb[8]==0)) // both inputs are zero begin mout = 9'b0 ; eout = 8'b0 ; end else if ((ms[8]==0) || ediff>8) // smaller is too small to matter begin mout = mb ; eout = eb ; end else // shift/add/normalize begin // now shift but save the low order bits by extending the registers // need a high order bit for 1.0> ediff ; // same signs means add -- different means subtract if (sb==ss) //do the add begin denorm_mout = {1'b0, mb} + shift_small ; // normalize -- // when adding result has to be 0.58'h80)? (m_in >> (8'h89 - e_in)) : 10'd0 ; //assign int_out = (m_in[8])? {sign, (sign? (~abs_int)+9'd1 : abs_int)} : 10'd0 ; assign int_out = (sign? (~abs_int)+10'd1 : abs_int) ; //assign int_out = {sign, sign? (~abs_int)+9'd1 : abs_int} ; endmodule ///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////// //// Time weighted average amplitude (2'comp) /////////////////////////////////////////////////////// // dk_const e-folding time of average // 3 ~8 samples // 4 15 // 5 32 // 6 64 // 7 128 -- 2.7 mSec at 48kHz // 8 256 -- 5.3 mSec (useful for music/voice) // 9 512 -- 10.5 mSec (useful for music/voice) // 10 1024 -- 21 mSec (useful for music/voice) // 11 2048 -- 42 mSec ///////////////////////////////////////////////////////// module average (out, in, dk_const, clk); output reg signed [15:0] out ; input wire signed [15:0] in ; input wire [3:0] dk_const ; input wire clk; wire signed [17:0] new_out ; //first order lowpass of absolute value of input assign new_out = out - (out>>>dk_const) + ((in[15]?-in:in)>>>dk_const) ; always @(posedge clk) begin out <= new_out ; end endmodule ////////////////////////////////////////////////// ////////////////////////////////////////////// // Decode one hex digit for LED 7-seg display module HexDigit(segs, num); input [3:0] num ; //the hex digit to be displayed output [6:0] segs ; //actual LED segments reg [6:0] segs ; always @ (num) begin case (num) 4'h0: segs = 7'b1000000; 4'h1: segs = 7'b1111001; 4'h2: segs = 7'b0100100; 4'h3: segs = 7'b0110000; 4'h4: segs = 7'b0011001; 4'h5: segs = 7'b0010010; 4'h6: segs = 7'b0000010; 4'h7: segs = 7'b1111000; 4'h8: segs = 7'b0000000; 4'h9: segs = 7'b0010000; 4'ha: segs = 7'b0001000; 4'hb: segs = 7'b0000011; 4'hc: segs = 7'b1000110; 4'hd: segs = 7'b0100001; 4'he: segs = 7'b0000110; 4'hf: segs = 7'b0001110; default segs = 7'b1111111; endcase end endmodule /////////////////////////////////////////////// /* */