OpenCores
URL https://opencores.org/ocsvn/ima_adpcm_enc_dec/ima_adpcm_enc_dec/trunk

Subversion Repositories ima_adpcm_enc_dec

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /ima_adpcm_enc_dec/trunk
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/doc/IMA ADPCM EncDec Core Specifications.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
doc/IMA ADPCM EncDec Core Specifications.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc =================================================================== --- doc (nonexistent) +++ doc (revision 2)
doc Property changes : Added: bugtraq:number ## -0,0 +1 ## +true \ No newline at end of property Index: verilog/bench/tb_ima_adpcm.v =================================================================== --- verilog/bench/tb_ima_adpcm.v (nonexistent) +++ verilog/bench/tb_ima_adpcm.v (revision 2) @@ -0,0 +1,283 @@ +//--------------------------------------------------------------------------------------- +// Project: ADPCM Encoder / Decoder +// +// Filename: tb_ima_adpcm.v (April 26, 2010 ) +// +// Author(s): Moti Litochevski +// +// Description: +// This file implements the ADPCM encoder & decoder test bench. The input samples +// to be encoded are read from a binary input file. The encoder stream output and +// decoded samples are also compared with binary files generated by the Scilab +// simulation. +// +//--------------------------------------------------------------------------------------- +// +// To Do: +// - +// +//--------------------------------------------------------------------------------------- +// +// Copyright (C) 2010 Moti Litochevski +// +// This source file may be used and distributed without restriction provided that this +// copyright statement is not removed from the file and that any derivative work +// contains the original copyright notice and the associated disclaimer. +// +// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +// FITNESS FOR A PARTICULAR PURPOSE. +// +//--------------------------------------------------------------------------------------- + +`timescale 1ns / 1ns + +module test; +//--------------------------------------------------------------------------------------- +// internal signal +reg clock; // global clock +reg reset; // global reset +reg [15:0] inSamp; // encoder input sample +reg inValid; // encoder input valid flag +wire inReady; // encoder input ready indication +wire [3:0] encPcm; // encoder encoded output value +wire encValid; // encoder output valid flag +wire [15:0] decSamp; // decoder output sample value +wire decValid; // decoder output valid flag +integer sampCount, encCount, decCount; +integer infid, encfid, decfid; +integer intmp, enctmp, dectmp; +reg [3:0] encExpVal; +reg [15:0] decExpVal; +reg [31:0] dispCount; + +// global definitions +`define EOF -1 + +// file names +`define IN_FILE "../../../scilab/test_in.bin" +`define ENC_FILE "../../../scilab/test_enc.bin" +`define DEC_FILE "../../../scilab/test_dec.bin" + +//--------------------------------------------------------------------------------------- +// test bench implementation +// global signals generation +initial +begin + clock = 0; + reset = 1; + #40 reset = 0; +end + +// clock generator - 50MHz clock +always +begin + #10 clock = 0; + #10 clock = 1; +end + +// test bench dump variables +initial +begin + $display(""); + $display("IMA ADPCM encoder & decoder simulation"); + $display("--------------------------------------"); + $dumpfile("test.vcd"); + $dumpvars(0, test); +end + +//------------------------------------------------------------------ +// encoder input samples read process +initial +begin + // clear encoder input signal + inSamp = 16'b0; + inValid = 1'b0; + // clear samples counter + sampCount = 0; + + // binary input file + infid = $fopen(`IN_FILE, "rb"); + + // wait for reset release + while (reset) @(posedge clock); + repeat (50) @(posedge clock); + + // read input samples file + intmp = $fgetc(infid); + while (intmp != `EOF) + begin + // read the next character to form the new input sample + // Note that first byte is used as the low byte of the sample + inSamp[7:0] <= intmp; + inSamp[15:8] <= $fgetc(infid); + // sign input sample is valid + inValid <= 1'b1; + @(posedge clock); + + // update the sample counter + sampCount = sampCount + 1; + + // wait for encoder input ready assertion to confirm the new sample was read + // by the encoder. + while (!inReady) + @(posedge clock); + + // read next character from the input file + intmp = $fgetc(infid); + end + // sign input is not valid + inValid <= 1'b0; + @(posedge clock); + + // close input file + $fclose(infid); +end + +// encoder output checker - the encoder output is compared to the value read from +// the ADPCM coded samples file. +initial +begin + // clear encoded sample value + encCount = 0; + // open input file + encfid = $fopen(`ENC_FILE, "rb"); + + // wait for reset release + while (reset) @(posedge clock); + + // encoder output compare loop + enctmp = $fgetc(encfid); + while (enctmp != `EOF) + begin + // assign the expected value to a register with the same width + encExpVal = enctmp; + + // wait for encoder output valid + while (!encValid) + @(posedge clock); + + // compare the encoded value with the value read from the input file + if (encPcm != encExpVal) + begin + // announce error detection and exit simulation + $display(" Error!"); + $display("Error found in encoder output index %0d.", encCount+1); + $display(" (expected value 'h%x, got value 'h%x)", encExpVal, encPcm); + // wait for a few clock cycles before ending simulation + repeat (20) @(posedge clock); + $finish; + end + + // update the encoded sample counter + encCount = encCount + 1; + // delay for a clock cycle after comparison + @(posedge clock); + + // read next char from input file + enctmp = $fgetc(encfid); + end + + // close input file + $fclose(encfid); +end + +// decoder output checker - the decoder output is compared to the value read from +// the ADPCM decoded samples file. +initial +begin + // clear decoded sample value + decCount = 0; + dispCount = 0; + // open input file + decfid = $fopen(`DEC_FILE, "rb"); + + // wait for reset release + while (reset) @(posedge clock); + + // display simulation progress bar title + $write("Simulation progress: "); + + // decoder output compare loop + dectmp = $fgetc(decfid); + while (dectmp != `EOF) + begin + // read the next char to form the expected 16 bit sample value + decExpVal[7:0] = dectmp; + decExpVal[15:8] = $fgetc(decfid); + + // wait for decoder output valid + while (!decValid) + @(posedge clock); + + // compare the decoded value with the value read from the input file + if (decSamp != decExpVal) + begin + // announce error detection and exit simulation + $display(" Error!"); + $display("Error found in decoder output index %0d.", decCount+1); + $display(" (expected value 'h%x, got value 'h%x)", decExpVal, decSamp); + // wait for a few clock cycles before ending simulation + repeat (20) @(posedge clock); + $finish; + end + // delay for a clock cycle after comparison + @(posedge clock); + + // update the decoded sample counter + decCount = decCount + 1; + + // check if simulation progress should be displayed + if (dispCount[31:13] != (decCount >> 13)) + $write("."); + // update the display counter + dispCount = decCount; + + // read next char from input file + dectmp = $fgetc(decfid); + end + + // close input file + $fclose(decfid); + + // when decoder output is done announce simulation was successful + $display(" Done"); + $display("Simulation ended successfully after %0d samples", decCount); + $finish; +end + +//------------------------------------------------------------------ +// device under test +// Encoder instance +ima_adpcm_enc enc +( + .clock(clock), + .reset(reset), + .inSamp(inSamp), + .inValid(inValid), + .inReady(inReady), + .outPCM(encPcm), + .outValid(encValid), + .outPredictSamp(/* not used */), + .outStepIndex(/* not used */) +); + +// Decoder instance +ima_adpcm_dec dec +( + .clock(clock), + .reset(reset), + .inPCM(encPcm), + .inValid(encValid), + .inReady(decReady), + .inPredictSamp(16'b0), + .inStepIndex(7'b0), + .inStateLoad(1'b0), + .outSamp(decSamp), + .outValid(decValid) +); + +endmodule +//--------------------------------------------------------------------------------------- +// Th.. Th.. Th.. Thats all folks !!! +//--------------------------------------------------------------------------------------- Index: verilog/bench =================================================================== --- verilog/bench (nonexistent) +++ verilog/bench (revision 2)
verilog/bench Property changes : Added: bugtraq:number ## -0,0 +1 ## +true \ No newline at end of property Index: verilog/rtl/ima_adpcm_enc.v =================================================================== --- verilog/rtl/ima_adpcm_enc.v (nonexistent) +++ verilog/rtl/ima_adpcm_enc.v (revision 2) @@ -0,0 +1,387 @@ +//--------------------------------------------------------------------------------------- +// Project: ADPCM Encoder +// +// Filename: ima_adpcm_enc.v (February 18, 2010) +// +// Author(s): Moti Litochevski +// +// Description: +// This module implements the IMA ADPCM audio encoding algorithm. The input samples +// interface is 16 bits wide. ADPCM encoded data output is 4 bits wide and is sent +// for every new input sample. +// +//--------------------------------------------------------------------------------------- +// +// To Do: +// - +// +//--------------------------------------------------------------------------------------- +// +// Copyright (C) 2010 Moti Litochevski +// +// This source file may be used and distributed without restriction provided that this +// copyright statement is not removed from the file and that any derivative work +// contains the original copyright notice and the associated disclaimer. +// +// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +// FITNESS FOR A PARTICULAR PURPOSE. +// +//--------------------------------------------------------------------------------------- + +module ima_adpcm_enc +( + clock, reset, + inSamp, inValid, + inReady, + outPCM, outValid, + outPredictSamp, outStepIndex +); +//--------------------------------------------------------------------------------------- +// global inputs +input reset; +input clock; + +// input interface +input [15:0] inSamp; // input sample +input inValid; // input valid flag +output inReady; // input ready indication + +// output interface +output [3:0] outPCM; // ADPCM encoded value +output outValid; // output valid flag +output [15:0] outPredictSamp; // predictor sample value output +output [6:0] outStepIndex; // step index value output + +//--------------------------------------------------------------------------------------- +// registers output +reg [3:0] outPCM; +reg outValid, inReady; + +// internals +reg [2:0] pcmSq; +reg [19:0] sampDiff, prePredSamp; +reg [18:0] predictorSamp, dequantSamp; +reg [3:0] prePCM; +reg [14:0] stepSize; // unsigned +reg [6:0] stepIndex; // unsigned +reg [4:0] stepDelta; +wire [7:0] preStepIndex; + +// constant declarations +// main state machine +`define PCM_IDLE 3'd0 +`define PCM_SIGN 3'd1 +`define PCM_BIT2 3'd2 +`define PCM_BIT1 3'd3 +`define PCM_BIT0 3'd4 +`define PCM_DONE 3'd5 + +//--------------------------------------------------------------------------------------- +// module implementation +// encoder main control process +always @ (posedge clock or posedge reset) +begin + if (reset) + begin + pcmSq <= 3'b0; + sampDiff <= 20'b0; + predictorSamp <= 19'b0; + dequantSamp <= 19'b0; + prePCM <= 4'b0; + inReady <= 1'b0; + end + else + begin + case (pcmSq) + // waiting for a new input sample + `PCM_IDLE: + // on a new input sample calculate the difference between the input + // sample and predictor output + if (inValid) + begin + // compute the difference between the current predictor output and the input + // sample with extended width to prevent any wrapping. + sampDiff <= {inSamp[15], inSamp, 3'b0} - {predictorSamp[18], predictorSamp}; + + // sign that input is not ready + inReady <= 1'b0; + + // switch to next state + pcmSq <= `PCM_SIGN; + end + else + // sign that input is ready + inReady <= 1'b1; + + // check the difference sign and set PCM sign bit accordingly + `PCM_SIGN: + begin + // check the difference sign + if (sampDiff[19]) + begin + // set PCM sign bit and negate the calculated sample difference + prePCM[3] <= 1'b1; + sampDiff <= (~sampDiff) + 1; + end + else + // clear the PCM sign bit + prePCM[3] <= 1'b0; + + // prepare the de-quantizer sample + dequantSamp <= {4'b0, stepSize}; + + // switch to next state + pcmSq <= `PCM_BIT2; + end + + // determine quantizer bit 2 value + `PCM_BIT2: + begin + // check if the difference is larger than step size + if (sampDiff[19:3] >= {2'b0, stepSize}) + begin + // bit 2 of PCM nibble is set + prePCM[2] <= 1'b1; + // update the difference value and the de-quantizer value + sampDiff[19:3] <= sampDiff[19:3] - {2'b0, stepSize}; + dequantSamp <= dequantSamp + {1'b0, stepSize, 3'b0}; + end + else + // bit 2 of PCM nibble is zero + prePCM[2] <= 1'b0; + + // switch to next state + pcmSq <= `PCM_BIT1; + end + + // determine quantizer bit 1 value + `PCM_BIT1: + begin + // check if the difference is larger than step size + if (sampDiff[19:2] >= {3'b0, stepSize}) + begin + // bit 1 of PCM nibble is set + prePCM[1] <= 1'b1; + // update the difference value and the de-quantizer value + sampDiff[19:2] <= sampDiff[19:2] - {3'b0, stepSize}; + dequantSamp <= dequantSamp + {2'b0, stepSize, 2'b0}; + end + else + // bit 1 of PCM nibble is zero + prePCM[1] <= 1'b0; + + // switch to next state + pcmSq <= `PCM_BIT0; + end + + // determine quantizer bit 0 value + `PCM_BIT0: + begin + // check if the difference is larger than step size + if (sampDiff[19:1] >= {4'b0, stepSize}) + begin + // bit 0 of PCM nibble is set + prePCM[0] <= 1'b1; + // update the de-quantizer value + dequantSamp <= dequantSamp + {3'b0, stepSize, 1'b0}; + end + else + // bit 0 of PCM nibble is zero + prePCM[0] <= 1'b0; + + // switch to next state + pcmSq <= `PCM_DONE; + end + + // check saturation condition on new predictor sample and update it + `PCM_DONE: + begin + // check the new predictor output saturation conditions + if (prePredSamp[19] && !prePredSamp[18]) + // negative saturation + predictorSamp <= {1'b1, 18'b0}; + else if (!prePredSamp[19] && prePredSamp[18]) + // positive saturation + predictorSamp <= {1'b0, {18{1'b1}}}; + else + // no saturation + predictorSamp <= prePredSamp[18:0]; + + // sign that input is ready + inReady <= 1'b1; + + // return to idle state + pcmSq <= `PCM_IDLE; + end + + // unused states + default: pcmSq <= `PCM_IDLE; + endcase + end +end +// internal state output assignment +assign outPredictSamp = predictorSamp[18:3] + predictorSamp[2]; +assign outStepIndex = stepIndex; + +// calculate the update predictor sample before it is updated by the state machine +always @ (prePCM or predictorSamp or dequantSamp) +begin + if (prePCM[3]) + prePredSamp <= {predictorSamp[18], predictorSamp} - {1'b0, dequantSamp}; + else + prePredSamp <= {predictorSamp[18], predictorSamp} + {1'b0, dequantSamp}; +end + +// output interface +always @ (posedge clock or posedge reset) +begin + if (reset) + begin + outPCM <= 4'b0; + outValid <= 1'b0; + end + else if (pcmSq == `PCM_DONE) + begin + outPCM <= prePCM; + outValid <= 1'b1; + end + else + outValid <= 1'b0; +end + +// quantizer index adaptation lookup table +always @ (prePCM) +begin + case (prePCM[2:0]) + 3'd0: stepDelta <= 5'd31; // = -1 + 3'd1: stepDelta <= 5'd31; // = -1 + 3'd2: stepDelta <= 5'd31; // = -1 + 3'd3: stepDelta <= 5'd31; // = -1 + 3'd4: stepDelta <= 5'd2; + 3'd5: stepDelta <= 5'd4; + 3'd6: stepDelta <= 5'd6; + 3'd7: stepDelta <= 5'd8; + endcase +end +// calculate the new index value before saturation +assign preStepIndex = {1'b0, stepIndex} + {{3{stepDelta[4]}}, stepDelta}; + +// update the step index with saturation checking +always @ (posedge clock or posedge reset) +begin + if (reset) + stepIndex <= 7'b0; + else if (pcmSq == `PCM_DONE) + begin + // check is the updated step value should be saturated + if (preStepIndex[7]) + stepIndex <= 7'd0; + else if (preStepIndex[6:0] > 7'd88) + stepIndex <= 7'd88; + else + stepIndex <= preStepIndex[6:0]; + end +end + +// quantizer step size lookup table +always @ (posedge clock) +begin + case (stepIndex) + 7'd0: stepSize <= 15'd7; + 7'd1: stepSize <= 15'd8; + 7'd2: stepSize <= 15'd9; + 7'd3: stepSize <= 15'd10; + 7'd4: stepSize <= 15'd11; + 7'd5: stepSize <= 15'd12; + 7'd6: stepSize <= 15'd13; + 7'd7: stepSize <= 15'd14; + 7'd8: stepSize <= 15'd16; + 7'd9: stepSize <= 15'd17; + 7'd10: stepSize <= 15'd19; + 7'd11: stepSize <= 15'd21; + 7'd12: stepSize <= 15'd23; + 7'd13: stepSize <= 15'd25; + 7'd14: stepSize <= 15'd28; + 7'd15: stepSize <= 15'd31; + 7'd16: stepSize <= 15'd34; + 7'd17: stepSize <= 15'd37; + 7'd18: stepSize <= 15'd41; + 7'd19: stepSize <= 15'd45; + 7'd20: stepSize <= 15'd50; + 7'd21: stepSize <= 15'd55; + 7'd22: stepSize <= 15'd60; + 7'd23: stepSize <= 15'd66; + 7'd24: stepSize <= 15'd73; + 7'd25: stepSize <= 15'd80; + 7'd26: stepSize <= 15'd88; + 7'd27: stepSize <= 15'd97; + 7'd28: stepSize <= 15'd107; + 7'd29: stepSize <= 15'd118; + 7'd30: stepSize <= 15'd130; + 7'd31: stepSize <= 15'd143; + 7'd32: stepSize <= 15'd157; + 7'd33: stepSize <= 15'd173; + 7'd34: stepSize <= 15'd190; + 7'd35: stepSize <= 15'd209; + 7'd36: stepSize <= 15'd230; + 7'd37: stepSize <= 15'd253; + 7'd38: stepSize <= 15'd279; + 7'd39: stepSize <= 15'd307; + 7'd40: stepSize <= 15'd337; + 7'd41: stepSize <= 15'd371; + 7'd42: stepSize <= 15'd408; + 7'd43: stepSize <= 15'd449; + 7'd44: stepSize <= 15'd494; + 7'd45: stepSize <= 15'd544; + 7'd46: stepSize <= 15'd598; + 7'd47: stepSize <= 15'd658; + 7'd48: stepSize <= 15'd724; + 7'd49: stepSize <= 15'd796; + 7'd50: stepSize <= 15'd876; + 7'd51: stepSize <= 15'd963; + 7'd52: stepSize <= 15'd1060; + 7'd53: stepSize <= 15'd1166; + 7'd54: stepSize <= 15'd1282; + 7'd55: stepSize <= 15'd1411; + 7'd56: stepSize <= 15'd1552; + 7'd57: stepSize <= 15'd1707; + 7'd58: stepSize <= 15'd1878; + 7'd59: stepSize <= 15'd2066; + 7'd60: stepSize <= 15'd2272; + 7'd61: stepSize <= 15'd2499; + 7'd62: stepSize <= 15'd2749; + 7'd63: stepSize <= 15'd3024; + 7'd64: stepSize <= 15'd3327; + 7'd65: stepSize <= 15'd3660; + 7'd66: stepSize <= 15'd4026; + 7'd67: stepSize <= 15'd4428; + 7'd68: stepSize <= 15'd4871; + 7'd69: stepSize <= 15'd5358; + 7'd70: stepSize <= 15'd5894; + 7'd71: stepSize <= 15'd6484; + 7'd72: stepSize <= 15'd7132; + 7'd73: stepSize <= 15'd7845; + 7'd74: stepSize <= 15'd8630; + 7'd75: stepSize <= 15'd9493; + 7'd76: stepSize <= 15'd10442; + 7'd77: stepSize <= 15'd11487; + 7'd78: stepSize <= 15'd12635; + 7'd79: stepSize <= 15'd13899; + 7'd80: stepSize <= 15'd15289; + 7'd81: stepSize <= 15'd16818; + 7'd82: stepSize <= 15'd18500; + 7'd83: stepSize <= 15'd20350; + 7'd84: stepSize <= 15'd22385; + 7'd85: stepSize <= 15'd24623; + 7'd86: stepSize <= 15'd27086; + 7'd87: stepSize <= 15'd29794; + 7'd88: stepSize <= 15'd32767; + default: stepSize <= 15'd32767; + endcase +end + +endmodule +//--------------------------------------------------------------------------------------- +// Th.. Th.. Th.. That's all folks !!! +//--------------------------------------------------------------------------------------- Index: verilog/rtl/ima_adpcm_dec.v =================================================================== --- verilog/rtl/ima_adpcm_dec.v (nonexistent) +++ verilog/rtl/ima_adpcm_dec.v (revision 2) @@ -0,0 +1,292 @@ +//--------------------------------------------------------------------------------------- +// Project: ADPCM Decoder +// +// Filename: ima_adpcm_enc.v (February 19, 2010) +// +// Author(s): Moti Litochevski +// +// Description: +// This module implements the IMA ADPCM audio decoding algorithm. The input ADPCM +// encoded data is 4 bits wide and is converted to linearly quantized 16 bits +// samples for every new input. +// The decoder module implemented here is not compatible to any particular protocol +// or file format. The module include optional interface to load the decoder +// internal state which includes the internal predictor sample and step index +// provided by the encoder. +// +//--------------------------------------------------------------------------------------- +// +// To Do: +// - +// +//--------------------------------------------------------------------------------------- +// +// Copyright (C) 2010 Moti Litochevski +// +// This source file may be used and distributed without restriction provided that this +// copyright statement is not removed from the file and that any derivative work +// contains the original copyright notice and the associated disclaimer. +// +// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND +// FITNESS FOR A PARTICULAR PURPOSE. +// +//--------------------------------------------------------------------------------------- + +module ima_adpcm_dec +( + clock, reset, + inPCM, inValid, + inReady, inPredictSamp, + inStepIndex, inStateLoad, + outSamp, outValid +); +//--------------------------------------------------------------------------------------- +// global inputs +input reset; +input clock; + +// input interface +input [3:0] inPCM; // input PCM nibble +input inValid; // input valid flag +output inReady; // input ready indication +// optional decoder state load +input [15:0] inPredictSamp; // predictor sample load input +input [6:0] inStepIndex; // step index load input +input inStateLoad; // internal state load input control + +// output interface +output [15:0] outSamp; // output sample value +output outValid; // output valid flag + +//--------------------------------------------------------------------------------------- +// registers output +reg [15:0] outSamp; +reg outValid; + +// internals +reg [18:0] predictorSamp; +wire [18:0] dequantSamp; +reg predValid; +wire [19:0] prePredSamp; +reg [14:0] stepSize; // unsigned +reg [6:0] stepIndex; // unsigned +reg [4:0] stepDelta; +wire [7:0] preStepIndex; +wire [16:0] preOutSamp; + +//--------------------------------------------------------------------------------------- +// module implementation +// main decoder process +always @ (posedge clock or posedge reset) +begin + if (reset) + begin + predictorSamp <= 19'b0; + predValid <= 1'b0; + end + else if (inStateLoad) + begin + // load predictor sample value + predictorSamp <= {inPredictSamp, 3'b0}; + // clear the internal delayed flag + predValid <= 1'b0; + end + else if (inValid) + begin + // check updated predictor sample saturation conditions + if (prePredSamp[19] && !prePredSamp[18]) + // negative saturation + predictorSamp <= {1'b1, 18'b0}; + else if (!prePredSamp[19] && prePredSamp[18]) + // positive saturation + predictorSamp <= {1'b0, {18{1'b1}}}; + else + // no saturation + predictorSamp <= prePredSamp[18:0]; + + // sign that predictor value is valid + predValid <= 1'b1; + end + else + predValid <= 1'b0; +end +// calculate the de-quantized difference value +assign dequantSamp = (inPCM[2] ? {1'b0, stepSize, 3'b0} : 19'b0) + + (inPCM[1] ? {2'b0, stepSize, 2'b0} : 19'b0) + + (inPCM[0] ? {3'b0, stepSize, 1'b0} : 19'b0) + + {4'b0, stepSize}; +// updated predictor output sample +assign prePredSamp = inPCM[3] ? ({predictorSamp[18], predictorSamp} - {1'b0, dequantSamp}) : + ({predictorSamp[18], predictorSamp} + {1'b0, dequantSamp}); + +// input interface is busy while updating the step size +assign inReady = ~predValid; + +// calculate the output sample before saturation +assign preOutSamp = {predictorSamp[18], predictorSamp[18:3]} + predictorSamp[2]; + +// output interface +always @ (posedge clock or posedge reset) +begin + if (reset) + begin + outSamp <= 16'b0; + outValid <= 1'b0; + end + else if (predValid) + begin + // output is taken from the predictor output with saturation check + if (!preOutSamp[16] && preOutSamp[15]) + // positive saturation condition + outSamp <= {1'b0, {15{1'b1}}}; + else if (preOutSamp[16] && !preOutSamp[15]) + // negative saturation condition + outSamp <= {1'b1, 15'b0}; + else + outSamp <= preOutSamp[15:0]; + + // sign output is valid + outValid <= 1'b1; + end + else + outValid <= 1'b0; +end + +// quantizer index adaptation lookup table +always @ (inPCM) +begin + case (inPCM[2:0]) + 3'd0: stepDelta <= 5'd31; // = -1 + 3'd1: stepDelta <= 5'd31; // = -1 + 3'd2: stepDelta <= 5'd31; // = -1 + 3'd3: stepDelta <= 5'd31; // = -1 + 3'd4: stepDelta <= 5'd2; // = +2 + 3'd5: stepDelta <= 5'd4; // = +4 + 3'd6: stepDelta <= 5'd6; // = +6 + 3'd7: stepDelta <= 5'd8; // = +8 + endcase +end +// calculate the new index value before saturation +assign preStepIndex = {1'b0, stepIndex} + {{3{stepDelta[4]}}, stepDelta}; + +// update the step index with saturation checking +always @ (posedge clock or posedge reset) +begin + if (reset) + stepIndex <= 7'b0; + else if (inStateLoad) + stepIndex <= inStepIndex; + else if (inValid) + begin + // check is the updated step value should be saturated + if (preStepIndex[7]) + stepIndex <= 7'd0; + else if (preStepIndex[6:0] > 7'd88) + stepIndex <= 7'd88; + else + stepIndex <= preStepIndex[6:0]; + end +end + +// quantizer step size lookup table +always @ (posedge clock) +begin + case (stepIndex) + 7'd0: stepSize <= 15'd7; + 7'd1: stepSize <= 15'd8; + 7'd2: stepSize <= 15'd9; + 7'd3: stepSize <= 15'd10; + 7'd4: stepSize <= 15'd11; + 7'd5: stepSize <= 15'd12; + 7'd6: stepSize <= 15'd13; + 7'd7: stepSize <= 15'd14; + 7'd8: stepSize <= 15'd16; + 7'd9: stepSize <= 15'd17; + 7'd10: stepSize <= 15'd19; + 7'd11: stepSize <= 15'd21; + 7'd12: stepSize <= 15'd23; + 7'd13: stepSize <= 15'd25; + 7'd14: stepSize <= 15'd28; + 7'd15: stepSize <= 15'd31; + 7'd16: stepSize <= 15'd34; + 7'd17: stepSize <= 15'd37; + 7'd18: stepSize <= 15'd41; + 7'd19: stepSize <= 15'd45; + 7'd20: stepSize <= 15'd50; + 7'd21: stepSize <= 15'd55; + 7'd22: stepSize <= 15'd60; + 7'd23: stepSize <= 15'd66; + 7'd24: stepSize <= 15'd73; + 7'd25: stepSize <= 15'd80; + 7'd26: stepSize <= 15'd88; + 7'd27: stepSize <= 15'd97; + 7'd28: stepSize <= 15'd107; + 7'd29: stepSize <= 15'd118; + 7'd30: stepSize <= 15'd130; + 7'd31: stepSize <= 15'd143; + 7'd32: stepSize <= 15'd157; + 7'd33: stepSize <= 15'd173; + 7'd34: stepSize <= 15'd190; + 7'd35: stepSize <= 15'd209; + 7'd36: stepSize <= 15'd230; + 7'd37: stepSize <= 15'd253; + 7'd38: stepSize <= 15'd279; + 7'd39: stepSize <= 15'd307; + 7'd40: stepSize <= 15'd337; + 7'd41: stepSize <= 15'd371; + 7'd42: stepSize <= 15'd408; + 7'd43: stepSize <= 15'd449; + 7'd44: stepSize <= 15'd494; + 7'd45: stepSize <= 15'd544; + 7'd46: stepSize <= 15'd598; + 7'd47: stepSize <= 15'd658; + 7'd48: stepSize <= 15'd724; + 7'd49: stepSize <= 15'd796; + 7'd50: stepSize <= 15'd876; + 7'd51: stepSize <= 15'd963; + 7'd52: stepSize <= 15'd1060; + 7'd53: stepSize <= 15'd1166; + 7'd54: stepSize <= 15'd1282; + 7'd55: stepSize <= 15'd1411; + 7'd56: stepSize <= 15'd1552; + 7'd57: stepSize <= 15'd1707; + 7'd58: stepSize <= 15'd1878; + 7'd59: stepSize <= 15'd2066; + 7'd60: stepSize <= 15'd2272; + 7'd61: stepSize <= 15'd2499; + 7'd62: stepSize <= 15'd2749; + 7'd63: stepSize <= 15'd3024; + 7'd64: stepSize <= 15'd3327; + 7'd65: stepSize <= 15'd3660; + 7'd66: stepSize <= 15'd4026; + 7'd67: stepSize <= 15'd4428; + 7'd68: stepSize <= 15'd4871; + 7'd69: stepSize <= 15'd5358; + 7'd70: stepSize <= 15'd5894; + 7'd71: stepSize <= 15'd6484; + 7'd72: stepSize <= 15'd7132; + 7'd73: stepSize <= 15'd7845; + 7'd74: stepSize <= 15'd8630; + 7'd75: stepSize <= 15'd9493; + 7'd76: stepSize <= 15'd10442; + 7'd77: stepSize <= 15'd11487; + 7'd78: stepSize <= 15'd12635; + 7'd79: stepSize <= 15'd13899; + 7'd80: stepSize <= 15'd15289; + 7'd81: stepSize <= 15'd16818; + 7'd82: stepSize <= 15'd18500; + 7'd83: stepSize <= 15'd20350; + 7'd84: stepSize <= 15'd22385; + 7'd85: stepSize <= 15'd24623; + 7'd86: stepSize <= 15'd27086; + 7'd87: stepSize <= 15'd29794; + 7'd88: stepSize <= 15'd32767; + default: stepSize <= 15'd32767; + endcase +end + +endmodule +//--------------------------------------------------------------------------------------- +// Th.. Th.. Th.. That's all folks !!! +//--------------------------------------------------------------------------------------- Index: verilog/rtl =================================================================== --- verilog/rtl (nonexistent) +++ verilog/rtl (revision 2)
verilog/rtl Property changes : Added: bugtraq:number ## -0,0 +1 ## +true \ No newline at end of property Index: verilog/sim/icarus/test.log =================================================================== --- verilog/sim/icarus/test.log (nonexistent) +++ verilog/sim/icarus/test.log (revision 2) @@ -0,0 +1,6 @@ + +IMA ADPCM encoder & decoder simulation +-------------------------------------- +VCD info: dumpfile test.vcd opened for output. +Simulation progress: ..................... Done +Simulation ended successfully after 174080 samples Index: verilog/sim/icarus/test.sav =================================================================== --- verilog/sim/icarus/test.sav (nonexistent) +++ verilog/sim/icarus/test.sav (revision 2) @@ -0,0 +1,82 @@ +[timestart] 245407 +[size] 1440 848 +[pos] 7 21 +*-6.233498 245600 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[treeopen] test. +@28 +test.clock +test.reset +@24 +test.sampCount[31:0] +@420 +test.inSamp[15:0] +@28 +test.inValid +test.inReady +@24 +test.encCount[31:0] +test.encExpVal[3:0] +test.encPcm[3:0] +@28 +test.encValid +@24 +test.decCount[31:0] +@420 +test.decExpVal[15:0] +@28 +test.decReady +@420 +test.decSamp[15:0] +@28 +test.decValid +@200 +-adpcm_enc +@420 +test.enc.inSamp[15:0] +@28 +test.enc.inValid +@421 +test.enc.sampDiff[19:0] +@24 +test.enc.stepIndex[6:0] +test.enc.stepSize[14:0] +@420 +test.enc.prePredSamp[19:0] +test.enc.predictorSamp[18:0] +@24 +test.enc.preStepIndex[7:0] +@420 +test.enc.stepDelta[4:0] +@24 +test.enc.stepIndex[6:0] +test.enc.stepSize[14:0] +@200 +-adpcm_dec +@28 +test.dec.clock +@420 +test.dec.dequantSamp[18:0] +@22 +test.dec.inPCM[3:0] +@28 +test.dec.inReady +test.dec.inValid +@420 +test.dec.outSamp[15:0] +@28 +test.dec.outValid +@420 +test.dec.prePredSamp[19:0] +@24 +test.dec.preStepIndex[7:0] +@28 +test.dec.predValid +@420 +test.dec.predictorSamp[18:0] +@28 +test.dec.reset +@420 +test.dec.stepDelta[4:0] +@24 +test.dec.stepIndex[6:0] +test.dec.stepSize[14:0] Index: verilog/sim/icarus/block.cfg =================================================================== --- verilog/sim/icarus/block.cfg (nonexistent) +++ verilog/sim/icarus/block.cfg (revision 2) @@ -0,0 +1,4 @@ ++incdir+../../bench +../../bench/tb_ima_adpcm.v +../../rtl/ima_adpcm_enc.v +../../rtl/ima_adpcm_dec.v Index: verilog/sim/icarus/run.bat =================================================================== --- verilog/sim/icarus/run.bat (nonexistent) +++ verilog/sim/icarus/run.bat (revision 2) @@ -0,0 +1 @@ +vvp -l test.log test.vvp Index: verilog/sim/icarus/gtk.bat =================================================================== --- verilog/sim/icarus/gtk.bat (nonexistent) +++ verilog/sim/icarus/gtk.bat (revision 2) @@ -0,0 +1 @@ +gtkwave test.vcd -a test.sav Index: verilog/sim/icarus/compile.bat =================================================================== --- verilog/sim/icarus/compile.bat (nonexistent) +++ verilog/sim/icarus/compile.bat (revision 2) @@ -0,0 +1 @@ +iverilog -o test.vvp -cblock.cfg Index: verilog/sim/icarus =================================================================== --- verilog/sim/icarus (nonexistent) +++ verilog/sim/icarus (revision 2)
verilog/sim/icarus Property changes : Added: bugtraq:number ## -0,0 +1 ## +true \ No newline at end of property Index: verilog/sim =================================================================== --- verilog/sim (nonexistent) +++ verilog/sim (revision 2)
verilog/sim Property changes : Added: bugtraq:number ## -0,0 +1 ## +true \ No newline at end of property Index: verilog =================================================================== --- verilog (nonexistent) +++ verilog (revision 2)
verilog Property changes : Added: bugtraq:number ## -0,0 +1 ## +true \ No newline at end of property Index: scilab/test_dec.bin =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: scilab/test_dec.bin =================================================================== --- scilab/test_dec.bin (nonexistent) +++ scilab/test_dec.bin (revision 2)
scilab/test_dec.bin Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: scilab/test_ima_adpcm.sce =================================================================== --- scilab/test_ima_adpcm.sce (nonexistent) +++ scilab/test_ima_adpcm.sce (revision 2) @@ -0,0 +1,77 @@ +// this script tests the ADC encoder & decoder +mode(-1) + +// set script parameters +// set to non zero to enable user selected WAV file +select_file_gui = 1; +// set default file name when GUI is disabled or canceled +default_filename = "1234.wav"; +// maximum length of audio samples to limit the runtime & verilog vector files +// set to 0 to disable any size limiting +maximum_samp_len = 0; +// set to non zero value to enable verilog simulation input & output vectors creation +verilog_vec_enable = 0; + +// get the functions +getd(); + +// set name of input WAV file +if (select_file_gui), + // get file from the user + fname=uigetfile("*.wav", "", "Select WAV File"); + // check if default file should be used + if ~length(fname), + fname = default_filename; + end +else + // use default filename + fname = default_filename; +end + +// load the WAV linear samples file +[samp, wav_Fs, wav_bits] = wavread(fname); +// only use a single channel +samp = samp(1, :); +// number of bits must be 16 +if (wav_bits ~= 16), + error("ERROR: WAV file must be 16 bits."); +end + +// limit the length of the input samples vector +if (maximum_samp_len), + samp = samp(1:min(maximum_samp_len, length(samp))); +end + +// call the encoder +enc_samp = ima_adpcm_enc(samp); + +// call the decoder +dec_samp = ima_adpcm_dec(enc_samp); + +// sound the result +sound(dec_samp/max(abs(dec_samp)), wav_Fs); + +// enable the following code to write Verilog simulation binary files +if (verilog_vec_enable), + // save the input samples to a binary file used by the verilog simulation + samp = round(samp * (2^15-1)); + fid = mopen("test_in.bin", "wb"); + mput(samp, "s"); + mclose(fid); + + // save the ADPCM encoded values + fid = mopen("test_enc.bin", "wb"); + mput(enc_samp, "uc"); + mclose(fid); + + // before saving the decoder samples they should be rounded using the hardware + // rounding implementation which only creates differences for negative .5 + // values. +// round_dec_samp = round(dec_samp); +// cor_idx = find((round_dec_samp - dec_samp) == -0.5); +// round_dec_samp(cor_idx) = round_dec_samp(cor_idx) + 1; + // save the decoded samples + fid = mopen("test_dec.bin", "wb"); + mput(dec_samp, "s"); + mclose(fid); +end Index: scilab/ima_adpcm_dec.sci =================================================================== --- scilab/ima_adpcm_dec.sci (nonexistent) +++ scilab/ima_adpcm_dec.sci (revision 2) @@ -0,0 +1,74 @@ +function out_samp = ima_adpcm_dec(in_pcm) +// This function decodes an IMA ADPCM compressed audio. The output is reconstructed +// to 16 bits per sample. +// +// Author: Moti Litochevski +// Date: February 17, 2010 +// + +// step quantizer adaptation lookup table +STEP_LUT = [ ... + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, ... + 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, ... + 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, ... + 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, ... + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, ... + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, ... + 20350, 22385, 24623, 27086, 29794, 32767]; +// index quantizer adaptation lookup table +INDEX_LUT = [-1, -1, -1, -1, 2, 4, 6, 8]; + +// prepare loop variables +predictor_samp = zeros(1, length(in_pcm)+1); +qstep_index = ones(1, length(in_pcm)+1); +// convert the input coded signal to binary form & calculate the PCM value (without sign) +pcm_bin = de2bi(in_pcm, 4); +pcm_val = pcm_bin(:,[2:4]) * [4, 2, 1]'; + +// decoding loop +for idx = [1:length(in_pcm)], + // extract the current quantizer step size + qstep_size = STEP_LUT(qstep_index(idx)); + + // de-quantizer implementation starts from the middle of the current + // quantization step (qstep_size/8) + dequant_samp = qstep_size; + // de-quantize bit by bit + dequant_samp = dequant_samp + pcm_bin(idx, 2) * qstep_size * 8; + dequant_samp = dequant_samp + pcm_bin(idx, 3) * qstep_size * 4; + dequant_samp = dequant_samp + pcm_bin(idx, 4) * qstep_size * 2; + + // update the predictor output sample according to the sign bit + if (pcm_bin(idx, 1)), + predictor_samp(idx+1) = predictor_samp(idx) - dequant_samp; + else + predictor_samp(idx+1) = predictor_samp(idx) + dequant_samp; + end + // check for predictor sample saturation condition + if (predictor_samp(idx+1) > (2^18-1)), + predictor_samp(idx+1) = 2^18-1; + elseif (predictor_samp(idx+1) < -2^18), + predictor_samp(idx+1) = -2^18; + end + + // update the step size index + qstep_index(idx+1) = qstep_index(idx) + INDEX_LUT(pcm_val(idx)+1); + // check index saturation conditions + if (qstep_index(idx+1) < 1) + qstep_index(idx+1) = 1; + elseif (qstep_index(idx+1) > 89) + qstep_index(idx+1) = 89; + end +end + +// output sample is just the saturated & scaled predictor output +out_samp = predictor_samp(2:$)/8; +// implement rounding +out_samp = round(out_samp); +cor_idx = find((out_samp - predictor_samp(2:$)/8) == -0.5); +out_samp(cor_idx) = out_samp(cor_idx) + 1; +// check for saturation +out_samp(find(predictor_samp(2:$)/8 > 32767)) = 32767; +out_samp(find(predictor_samp(2:$)/8 < -32768)) = -32768; + +endfunction Index: scilab/1234.wav =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: scilab/1234.wav =================================================================== --- scilab/1234.wav (nonexistent) +++ scilab/1234.wav (revision 2)
scilab/1234.wav Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: scilab/test_enc.bin =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: scilab/test_enc.bin =================================================================== --- scilab/test_enc.bin (nonexistent) +++ scilab/test_enc.bin (revision 2)
scilab/test_enc.bin Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: scilab/test_in.bin =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: scilab/test_in.bin =================================================================== --- scilab/test_in.bin (nonexistent) +++ scilab/test_in.bin (revision 2)
scilab/test_in.bin Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: scilab/ima_adpcm_enc.sci =================================================================== --- scilab/ima_adpcm_enc.sci (nonexistent) +++ scilab/ima_adpcm_enc.sci (revision 2) @@ -0,0 +1,92 @@ +function out_pcm = ima_adpcm_enc(in_samp) +// This function encodes the input samples audio vector using IMA ADPCM algorithm. The +// input is assumed to be sampled using 16 bits per sample. The output vector is a +// compressed version of the input audio signal which requires only 4 bits per input +// sample. +// The function will scale the input vector to 16 bits per sample automatically if all +// values in the vector are in the range [-1:1]. +// +// Author: Moti Litochevski +// Date: February 17, 2010 +// + +// check the input vector samples range +if (abs(in_samp) <= 1), + in_samp = round(in_samp * (2^15-1)); +end + +// step quantizer adaptation lookup table +STEP_LUT = [ ... + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, ... + 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, ... + 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, ... + 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, ... + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, ... + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, ... + 20350, 22385, 24623, 27086, 29794, 32767]; +// quantizer index adaptation lookup table +INDEX_LUT = [-1, -1, -1, -1, 2, 4, 6, 8]; + +// prepare output vector +out_pcm = zeros(length(in_samp), 4); // in binary format + +// prepare loop variables +predictor_samp = zeros(1, length(in_samp)+1); +qstep_index = ones(1, length(in_samp)+1); + +// compression loop +for idx = [1:length(in_samp)], + // subtract the previous sample form the current input sample + samp_diff = in_samp(idx)*8 - predictor_samp(idx); + + // extract the current quantizer step size + qstep_size = STEP_LUT(qstep_index(idx)); + + // start difference quantization from the sign bit + out_pcm(idx, 1) = 1 * (samp_diff < 0); + samp_diff = abs(samp_diff); + + // quantize the absolute value bit by bit + // the same process is used to calculate the de-quantizer output sample. note that the + // de-quantizer sample is started from the middle of the current step size (qstep_size/8). + dequant_samp = qstep_size; + // bit 2 + out_pcm(idx, 2) = 1 * (samp_diff >= (qstep_size * 8)); + samp_diff = samp_diff - out_pcm(idx, 2) * qstep_size * 8; + dequant_samp = dequant_samp + out_pcm(idx, 2) * qstep_size * 8; + // bit 1 + out_pcm(idx, 3) = 1 * (samp_diff >= (qstep_size * 4)); + samp_diff = samp_diff - out_pcm(idx, 3) * qstep_size * 4; + dequant_samp = dequant_samp + out_pcm(idx, 3) * qstep_size * 4; + // bit 0 + out_pcm(idx, 4) = 1 * (samp_diff >= (qstep_size * 2)); + dequant_samp = dequant_samp + out_pcm(idx, 4) * qstep_size * 2; + + // update the predictor sample for the next iteration according to the sign bit + if (out_pcm(idx, 1)), + predictor_samp(idx+1) = predictor_samp(idx) - dequant_samp; + else + predictor_samp(idx+1) = predictor_samp(idx) + dequant_samp; + end + // check for predictor sample saturation condition + if (predictor_samp(idx+1) > (2^18-1)), + predictor_samp(idx+1) = 2^18 - 1; + elseif (predictor_samp(idx+1) < -2^18), + predictor_samp(idx + 1) = -2^18; + end + + // update the step size index + pcm_val = out_pcm(idx, [2:4]) * [4, 2, 1]'; + qstep_index(idx+1) = qstep_index(idx) + INDEX_LUT(pcm_val+1); + // check index saturation conditions + if (qstep_index(idx+1) < 1) + qstep_index(idx+1) = 1; + elseif (qstep_index(idx+1) > 89) + qstep_index(idx+1) = 89; + end +end + +// convert the resulting compressed binary values to decimal +out_pcm = bi2de(out_pcm); + +endfunction Index: scilab =================================================================== --- scilab (nonexistent) +++ scilab (revision 2)
scilab Property changes : Added: bugtraq:number ## -0,0 +1 ## +true \ No newline at end of property

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.