URL
https://opencores.org/ocsvn/ima_adpcm_encoder/ima_adpcm_encoder/trunk
Subversion Repositories ima_adpcm_encoder
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/trunk/tb_IMA_ADPCM_top.vhd
0,0 → 1,217
---------------------------------------------------------------------------------- |
-- Company: VISENGI S.L. (www.visengi.com) |
-- Engineer: Victor Lopez Lorenzo (victor.lopez (at) visengi (dot) com) |
-- |
-- Create Date: 19:34:36 04/November/2008 |
-- Project Name: IMA ADPCM Encoder |
-- Tool versions: Xilinx ISE 9.2i |
-- Description: |
-- |
-- Description: This project features a full-hardware sound compressor using the well known algorithm IMA ADPCM. |
-- The core acts as a slave WISHBONE device. The output is perfectly compatible with any sound player |
-- with the IMA ADPCM codec (included by default in every Windows). Includes a testbench that takes |
-- an uncompressed PCM 16 bits Mono WAV file and outputs an IMA ADPCM compressed WAV file. |
-- Compression ratio is fixed for IMA-ADPCM, being 4:1. |
-- |
-- |
-- LICENSE TERMS: GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 |
-- That is you may use it in ANY project (commercial or not) without paying a cent. |
-- You are only required to include in the copyrights/about section of accompanying |
-- software and manuals of use that your system contains a "IMA ADPCM Encoder |
-- (C) VISENGI S.L. under LGPL license" |
-- This holds also in the case where you modify the core, as the resulting core |
-- would be a derived work. |
-- Also, we would like to know if you use this core in a project of yours, just an email will do. |
-- |
-- Please take good note of the disclaimer section of the LPGL license, as we don't |
-- take any responsability for anything that this core does. |
---------------------------------------------------------------------------------- |
|
LIBRARY ieee; |
USE ieee.std_logic_1164.ALL; |
USE ieee.std_logic_unsigned.all; |
USE ieee.std_logic_arith.all; |
use ieee.numeric_std.all; |
|
ENTITY tb_IMA_ADPCM_top_vhd IS |
END tb_IMA_ADPCM_top_vhd; |
|
ARCHITECTURE behavior OF tb_IMA_ADPCM_top_vhd IS |
|
-- Component Declaration for the Unit Under Test (UUT) |
COMPONENT IMA_ADPCM_top |
PORT( |
wb_clk_i : IN std_logic; |
wb_rst_i : IN std_logic; |
wb_cyc_i : IN std_logic; |
wb_stb_i : IN std_logic; |
wb_we_i : IN std_logic; |
wb_adr_i : IN std_logic_vector(1 downto 0); |
wb_dat_i : IN std_logic_vector(15 downto 0); |
wb_dat_o : OUT std_logic_vector(15 downto 0); |
wb_ack_o : OUT std_logic |
); |
END COMPONENT; |
|
--Inputs |
SIGNAL wb_clk_i : std_logic := '0'; |
SIGNAL wb_rst_i : std_logic := '0'; |
SIGNAL wb_cyc_i : std_logic := '0'; |
SIGNAL wb_stb_i : std_logic := '0'; |
SIGNAL wb_we_i : std_logic := '0'; |
SIGNAL wb_adr_i : std_logic_vector(1 downto 0) := (others=>'0'); |
SIGNAL wb_dat_i : std_logic_vector(15 downto 0) := (others=>'0'); |
|
--Outputs |
SIGNAL wb_dat_o : std_logic_vector(15 downto 0); |
SIGNAL wb_ack_o : std_logic; |
|
|
type ByteFileType is file of character; |
file infile : ByteFileType open read_mode is "input.wav"; |
file outfile : ByteFileType open write_mode is "output.wav"; |
|
signal bytes, bytesout : std_logic_vector(23 downto 0); |
|
signal SamplesPerSec : std_logic_vector(15 downto 0); |
signal SecondsToCompress : std_logic_vector(31 downto 0); |
BEGIN |
|
-- Instantiate the Unit Under Test (UUT) |
uut: IMA_ADPCM_top PORT MAP( |
wb_clk_i => wb_clk_i, |
wb_rst_i => wb_rst_i, |
wb_cyc_i => wb_cyc_i, |
wb_stb_i => wb_stb_i, |
wb_we_i => wb_we_i, |
wb_adr_i => wb_adr_i, |
wb_dat_i => wb_dat_i, |
wb_dat_o => wb_dat_o, |
wb_ack_o => wb_ack_o |
); |
|
wb_rst_i <= '1', '0' after 40 ns; --active high reset |
|
Clocking : process --50 MHz -> T = 20 ns |
begin |
wb_clk_i <= '1'; wait for 20 ns; |
wb_clk_i <= '0'; wait for 20 ns; |
end process; |
|
|
|
|
Control_Compressor : process (wb_clk_i, wb_rst_i) |
variable byte : character; |
variable WaitACK, EndSignaled : std_logic; |
variable State : integer; |
variable data : std_logic_vector(15 downto 0); |
variable DataBytes : std_logic_vector(31 downto 0); |
begin |
if (wb_rst_i = '1') then |
bytes <= (others => '0'); |
bytesout <= (others => '0'); |
State := 0; |
WaitACK := '0'; |
EndSignaled := '0'; |
wb_cyc_i <= '0'; |
wb_stb_i <= '0'; |
wb_we_i <= '0'; |
wb_adr_i <= (others => '0'); |
wb_dat_i <= (others => '0'); |
data := (others => '0'); |
elsif (wb_clk_i = '1' and wb_clk_i'event) then |
if (WaitACK = '1') then |
if (wb_ack_o = '1') then |
wb_cyc_i <= '0'; wb_stb_i <= '0'; wb_we_i <= '0'; |
data := wb_dat_o; WaitACK := '0'; |
end if; |
end if; |
|
if (WaitACK = '0') then |
case State is |
when 0 => |
--read the WAV header in search of SamplesPerSecond (bytes 19h and 18h in little endian) |
--and DataBytes (bytes 39h,38h,37h,36h in little endian) to get SecondsToCompress as DataBytes/2/SamplesPerSecond |
for i in 0 to 57 loop --PCM header has 58 bytes |
read(infile, byte); |
case i is |
when 25 => --x"19" => --MSB of SamplesPerSecond |
SamplesPerSec(15 downto 8) <= conv_std_logic_vector(character'pos(byte),8); |
when 24 => --x"18" => --LSB of SamplesPerSecond |
SamplesPerSec(7 downto 0) <= conv_std_logic_vector(character'pos(byte),8); |
|
when 7 => --x"39" => --1stMSB of DataBytes |
DataBytes(31 downto 24) := conv_std_logic_vector(character'pos(byte),8); |
when 6 => --x"38" => --2ndMSB of DataBytes |
DataBytes(23 downto 16) := conv_std_logic_vector(character'pos(byte),8); |
when 5 => --x"37" => --3rdMSB of DataBytes |
DataBytes(15 downto 8) := conv_std_logic_vector(character'pos(byte),8); |
when 4 => --x"36" => --4thMSB of DataBytes |
DataBytes(7 downto 0) := conv_std_logic_vector(character'pos(byte),8); |
when others => |
null; |
end case; |
end loop; |
EndSignaled := '0'; |
bytes <= (others => '0'); |
bytesout <= (others => '0'); |
DataBytes := DataBytes - x"32"; --with fmt18 and fact4 chunks |
State := State + 1; |
when 1 => |
SecondsToCompress <= conv_std_logic_vector((conv_integer(DataBytes)/conv_integer(SamplesPerSec))/2,32); |
wb_adr_i <= "01"; wb_dat_i <= SamplesPerSec; wb_we_i <= '1'; WaitACK := '1'; |
State := State + 1; |
when 2 => |
wb_adr_i <= "10"; wb_dat_i <= SecondsToCompress(15 downto 0); wb_we_i <= '1'; WaitACK := '1'; |
State := State + 1; |
when 3 => |
wb_adr_i <= "00"; wb_dat_i <= x"8000"; wb_we_i <= '1'; WaitACK := '1'; |
State := State + 1; |
when 4 => |
wb_adr_i <= "00"; wb_we_i <= '0'; WaitACK := '1'; State := State + 1; |
when 5 => |
if (data(15) = '0') then --compression end |
File_Close(infile); --finished |
report "Input bytes = " & integer'image(conv_integer(bytes)) & " at time " & time'image(now); |
report "Output bytes = " & integer'image(conv_integer(bytesout)) & " at time " & time'image(now); |
File_Close(outfile); --finished |
report "-----------> Compression Finished OK!" severity FAILURE; --everything went fine, it's just to stop the simulation |
else |
if (data(0) = '1') then --output word ready |
wb_adr_i <= "11"; wb_we_i <= '0'; WaitACK := '1'; |
State := 15; --write word |
elsif (data(1) = '1' and EndSignaled = '0') then --ready for new input sample AND haven't reached the input file's EOF? |
if (bytes < DataBytes(23 downto 0) and not endfile(infile)) then |
--send two bytes to the WAV compressor |
read(infile,byte); --1st byte ----> goes in LSBs!!! (little endian) |
wb_dat_i(7 downto 0) <= conv_std_logic_vector(character'pos(byte),8); |
read(infile,byte); --2nd byte |
wb_dat_i(15 downto 8) <= conv_std_logic_vector(character'pos(byte),8); |
bytes <= bytes + x"2"; |
wb_adr_i <= "11"; wb_we_i <= '1'; WaitACK := '1'; State := State - 1; |
else --already sent the number of bytes indicated in PCM WAV header |
wb_adr_i <= "00"; wb_dat_i <= x"0000"; wb_we_i <= '1'; WaitACK := '1'; --signal finish compression |
EndSignaled := '1'; State := State - 1; --there will be still bytes to write but don't get in here again (EndSignaled='1') |
end if; |
else |
wb_adr_i <= "00"; wb_we_i <= '0'; WaitACK := '1'; --read again and stay in this state |
end if; |
end if; |
|
|
when 15 => --write word |
write(outfile, character'val(conv_integer(data(15 downto 8)))); |
write(outfile, character'val(conv_integer(data(7 downto 0)))); |
bytesout <= bytesout + x"2"; |
wb_adr_i <= "00"; wb_we_i <= '0'; WaitACK := '1'; State := 5; --go back and continue |
|
when others => |
State := 0; |
end case; |
end if; |
if (WaitACK = '1') then wb_cyc_i <= '1'; wb_stb_i <= '1'; end if; |
end if; |
end process Control_Compressor; |
|
END; |
/trunk/WAV_header_rom.vhd
0,0 → 1,149
---------------------------------------------------------------------------------- |
-- Company: VISENGI S.L. (www.visengi.com) |
-- Engineer: Victor Lopez Lorenzo (victor.lopez (at) visengi (dot) com) |
-- |
-- Create Date: 18:46:15 03/November/2008 |
-- Project Name: IMA ADPCM Encoder |
-- Tool versions: Xilinx ISE 9.2i |
-- Description: |
-- |
-- Description: This project features a full-hardware sound compressor using the well known algorithm IMA ADPCM. |
-- The core acts as a slave WISHBONE device. The output is perfectly compatible with any sound player |
-- with the IMA ADPCM codec (included by default in every Windows). Includes a testbench that takes |
-- an uncompressed PCM 16 bits Mono WAV file and outputs an IMA ADPCM compressed WAV file. |
-- Compression ratio is fixed for IMA-ADPCM, being 4:1. |
-- |
-- |
-- LICENSE TERMS: GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 |
-- That is you may use it in ANY project (commercial or not) without paying a cent. |
-- You are only required to include in the copyrights/about section of accompanying |
-- software and manuals of use that your system contains a "IMA ADPCM Encoder |
-- (C) VISENGI S.L. under LGPL license" |
-- This holds also in the case where you modify the core, as the resulting core |
-- would be a derived work. |
-- Also, we would like to know if you use this core in a project of yours, just an email will do. |
-- |
-- Please take good note of the disclaimer section of the LPGL license, as we don't |
-- take any responsability for anything that this core does. |
---------------------------------------------------------------------------------- |
|
-------------------------------------------------------------------------------- |
-- WAV HEADER ROM |
-------------------------------------------------------------------------------- |
|
library IEEE; |
use IEEE.STD_LOGIC_1164.all; |
use ieee.numeric_std.all; |
|
entity WAV_header_rom is |
generic (ROMADDR_W : integer := 6; |
ROMDATA_W : integer := 8); |
port( |
addr0 : in STD_LOGIC_VECTOR(ROMADDR_W-1 downto 0); |
clk : in STD_LOGIC; |
datao0 : out STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0)); |
end WAV_header_rom; |
|
architecture RTL of WAV_header_rom is |
|
type ROM_TYPE is array (0 to 2**ROMADDR_W-1) |
of STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0); |
constant rom : ROM_TYPE := |
( |
-- Everything little endian: |
-- 52 49 46 46 00 00 00 00 57 41 56 45 66 6D 74 20 14 00 00 00 |
-- R I F F x x x x W A V E f m t x x x x <-- these last are ok |
--x ^ ^ ^ ^ = change these for (file_size-8 or, simply, bytes that follow) |
-- 11 00 <-- wFormatTag = IMA ADPCM |
-- 01 00 <-- nChannels = 1 (Mono) |
--x40 1F 00 00 <-- nSamplesPerSec = 8000 |
--xD7 0F 00 00 <-- nAvgBytesPerSec = 4055 |
-- (505 samples/block -> 8000 samples/sec -> 504/2 + 4 header bytes w. 1 sample = 256 bytes/block -> (8000/505)*256 = 4055 bytes/sec) |
-- can be an approximate number and still be reproducible (i.e. nAvgBytesPerSec=nSamplesPerSec/512*256=nSamplesPerSec/2) |
-- 00 01 <-- nBlockAlign = 100h = 256 bytes block size |
-- 04 00 <-- wBitsPerSample = 4 bits |
-- 02 00 <-- cbSize = size of extension = 2 bytes |
-- F9 01 <-- wSamplesPerBlock = 505 samples/block |
-- |
-- 66 61 63 74 04 00 00 00 00 00 00 00 64 61 74 61 00 00 00 00 |
--x f a c t x x x x x x x x d a t a x x x x <-- change these for (file_size-60 or, simply, bytes that follow) |
--x ^ ^ ^ ^ = # samples per channel in file |
"01010010", |
"01001001", |
"01000110", |
"01000110", |
"11111111", |
"11111111", |
"11111111", |
"01111111", |
"01010111", |
"01000001", |
"01010110", |
"01000101", |
"01100110", |
"01101101", |
"01110100", |
"00100000", |
"00010100", |
"00000000", |
"00000000", |
"00000000", |
"00010001", |
"00000000", |
"00000001", |
"00000000", |
"01000000", |
"00011111", |
"00000000", |
"00000000", |
"11010111", |
"00001111", |
"00000000", |
"00000000", |
"00000000", |
"00000001", |
"00000100", |
"00000000", |
"00000010", |
"00000000", |
"11111001", |
"00000001", |
"01100110", |
"01100001", |
"01100011", |
"01110100", |
"00000100", |
"00000000", |
"00000000", |
"00000000", |
"11111111", |
"11111111", |
"11111111", |
"01111111", |
"01100100", |
"01100001", |
"01110100", |
"01100001", |
"11111111", |
"11111111", |
"11111111", |
"01111111", |
--0 stuffing |
"00000000", |
"00000000", |
"00000000", |
"00000000"); |
signal addr_reg0 : STD_LOGIC_VECTOR(ROMADDR_W-1 downto 0); |
|
begin |
|
datao0 <= rom( TO_INTEGER(UNSIGNED(addr_reg0)) ); |
|
process(clk) |
begin |
if clk = '1' and clk'event then |
addr_reg0 <= addr0; |
end if; |
end process; |
|
end RTL; |
/trunk/IMA_ADPCM_Encode.vhd
0,0 → 1,200
---------------------------------------------------------------------------------- |
-- Company: VISENGI S.L. (www.visengi.com) |
-- Engineer: Victor Lopez Lorenzo (victor.lopez (at) visengi (dot) com) |
-- |
-- Create Date: 01:34:59 31/October/2008 |
-- Project Name: IMA ADPCM Encoder |
-- Tool versions: Xilinx ISE 9.2i |
-- Description: |
-- |
-- Description: This project features a full-hardware sound compressor using the well known algorithm IMA ADPCM. |
-- The core acts as a slave WISHBONE device. The output is perfectly compatible with any sound player |
-- with the IMA ADPCM codec (included by default in every Windows). Includes a testbench that takes |
-- an uncompressed PCM 16 bits Mono WAV file and outputs an IMA ADPCM compressed WAV file. |
-- Compression ratio is fixed for IMA-ADPCM, being 4:1. |
-- |
-- |
-- LICENSE TERMS: GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 |
-- That is you may use it in ANY project (commercial or not) without paying a cent. |
-- You are only required to include in the copyrights/about section of accompanying |
-- software and manuals of use that your system contains a "IMA ADPCM Encoder |
-- (C) VISENGI S.L. under LGPL license" |
-- This holds also in the case where you modify the core, as the resulting core |
-- would be a derived work. |
-- Also, we would like to know if you use this core in a project of yours, just an email will do. |
-- |
-- Please take good note of the disclaimer section of the LPGL license, as we don't |
-- take any responsability for anything that this core does. |
---------------------------------------------------------------------------------- |
|
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_ARITH.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
entity IMA_ADPCM_Encode is |
Port ( clk : in STD_LOGIC; |
reset : in STD_LOGIC; |
|
PredictedValue_o : out std_logic_vector(15 downto 0); |
StepIndex_o : out std_logic_vector(6 downto 0); |
StateRDY : out std_logic; |
|
sample : in std_logic_vector(15 downto 0); --don't change it while sample_rdy='1' |
sample_rdy : in std_logic; --lower it only when ADPCM_sample_rdy = '1' |
ADPCM_sample : out std_logic_vector(3 downto 0); |
ADPCM_sample_rdy : out std_logic |
); |
end IMA_ADPCM_Encode; |
|
architecture Behavioral of IMA_ADPCM_Encode is |
signal PredictedValue : std_logic_vector(15 downto 0); |
signal StepIndex : std_logic_vector(6 downto 0); |
|
component IMA_adpcm_steptable_rom port( |
addr0 : in STD_LOGIC_VECTOR(6 downto 0); |
clk : in STD_LOGIC; |
datao0: out STD_LOGIC_VECTOR(14 downto 0)); |
end component; |
|
signal Step : std_logic_vector(14 downto 0); |
|
signal comp16b_AbtB : std_logic; --A bigger than B |
signal delta, diff : std_logic_vector(15 downto 0); |
signal State : integer range 0 to 31; |
begin |
StepTable_ROM : IMA_adpcm_steptable_rom port map ( |
addr0 => StepIndex, |
clk => clk, |
datao0=> Step); |
|
|
|
process (reset, clk) |
variable AdderSub16 : std_logic_vector(15 downto 0); |
variable ADPCM_sample2 : std_logic_vector(3 downto 0); |
begin |
if (reset = '1') then |
State <= 0; |
AdderSub16 := (others => '0'); |
ADPCM_sample <= x"0"; |
ADPCM_sample2 := x"0"; |
ADPCM_sample_rdy <= '0'; |
|
PredictedValue <= (others => '0'); |
StepIndex <= (others => '0'); |
PredictedValue_o <= (others => '0'); |
StepIndex_o <= (others => '0'); |
StateRDY <= '0'; |
delta <= (others => '0'); |
diff <= (others => '0'); |
comp16b_AbtB <= '0'; |
elsif (clk='1' and clk'event) then |
ADPCM_sample_rdy <= '0'; |
|
case State is |
when 0 => |
PredictedValue_o <= PredictedValue; StepIndex_o <= StepIndex; StateRDY <= '1'; |
if (sample_rdy = '1') then State <= 10; StateRDY <= '0'; end if; |
when 10 => --Signed comparison between A:sample and B:PredictedValue |
if (sample(15) = '1' and PredictedValue(15) = '0') then |
comp16b_AbtB <= '0'; --sample<0, Pred>=0 |
elsif (sample(15) = '0' and PredictedValue(15) = '1') then |
comp16b_AbtB <= '1'; --sample>=0, Pred<0 |
else --both positives or both negatives --> normal comparison |
if (sample > PredictedValue) then comp16b_AbtB <= '1'; else comp16b_AbtB <= '0'; end if; |
end if; |
State <= State + 1; |
when 11 => |
if (comp16b_AbtB = '1') then --it really should be beq but a negative zero is as good as a positive one |
delta <= sample - PredictedValue; |
ADPCM_sample2(3) := '0'; |
else |
delta <= PredictedValue - sample; |
ADPCM_sample2(3) := '1'; --set the sign (negative) |
end if; |
State <= State + 1; |
|
when 12 => --we've got the rigth Step now |
diff <= "0000" & Step(14 downto 3); |
if (delta > '0' & Step) then comp16b_AbtB <= '1'; else comp16b_AbtB <= '0'; end if; |
State <= State + 1; |
when 13 => |
if (comp16b_AbtB = '1') then --delta > step |
delta <= delta - ('0' & Step); |
diff <= diff + ('0' & Step); |
ADPCM_sample2(2) := '1'; |
else |
ADPCM_sample2(2) := '0'; |
end if; |
State <= State + 1; |
|
when 14 => |
if (delta > "00" & Step(14 downto 1)) then comp16b_AbtB <= '1'; else comp16b_AbtB <= '0'; end if; |
State <= State + 1; |
when 15 => |
if (comp16b_AbtB = '1') then --delta > step |
delta <= delta - ("00" & Step(14 downto 1)); |
diff <= diff + ("00" & Step(14 downto 1)); |
ADPCM_sample2(1) := '1'; |
else |
ADPCM_sample2(1) := '0'; |
end if; |
State <= State + 1; |
|
when 16 => |
if (delta > "000" & Step(14 downto 2)) then comp16b_AbtB <= '1'; else comp16b_AbtB <= '0'; end if; |
State <= State + 1; |
when 17 => |
if (comp16b_AbtB = '1') then --delta > step |
diff <= diff + ("000" & Step(14 downto 2)); |
ADPCM_sample2(0) := '1'; |
else |
ADPCM_sample2(0) := '0'; |
end if; |
ADPCM_sample_rdy <= '1'; |
State <= State + 1; |
|
when 18 => |
if (ADPCM_sample2(3) = '1') then --negative |
AdderSub16 := PredictedValue - diff; |
else |
AdderSub16 := PredictedValue + diff; |
end if; |
|
--IMA_ADPCMIndexTable[8] = -1, -1, -1, -1, 2, 4, 6, 8, |
case ADPCM_sample2(2 downto 0) is |
when "111" => StepIndex <= StepIndex + "0001000"; |
when "110" => StepIndex <= StepIndex + "0000110"; |
when "101" => StepIndex <= StepIndex + "0000100"; |
when "100" => StepIndex <= StepIndex + "0000010"; |
when others => StepIndex <= StepIndex - "0000001"; |
end case; |
State <= State + 1; |
when 19 => |
if (StepIndex = "1111111") then |
StepIndex <= (others => '0'); |
elsif (StepIndex > "1011000") then |
StepIndex <= "1011000"; |
end if; |
|
--diff is always positive, it becomes negative if we substract Pred - diff == Pred + (-diff) |
--so the sign of diff is marked by ADPCM_sample2(3) |
if (PredictedValue(15) = '0' and ADPCM_sample2(3) = '0' and AdderSub16(15) = '1') then --both positives result in negative? |
PredictedValue <= '0' & (14 downto 0 => '1'); --positive overflow -> set biggest positive |
elsif (PredictedValue(15) = '1' and ADPCM_sample2(3) = '1' and AdderSub16(15) = '0') then --both negatives result positive? |
PredictedValue <= '1' & (14 downto 0 => '0'); --negative overflow -> set biggest negative |
else --one positive, the other negative (overflow not possible) |
PredictedValue <= AdderSub16(15 downto 0); |
end if; |
State <= 0; --go wait for new sample ready |
|
when others => |
State <= 0; |
end case; |
ADPCM_sample <= ADPCM_sample2; |
end if; |
end process; |
|
end Behavioral; |
|
/trunk/IMA_adpcm_steptable_rom.vhd
0,0 → 1,211
---------------------------------------------------------------------------------- |
-- Company: VISENGI S.L. (www.visengi.com) |
-- Engineer: Victor Lopez Lorenzo (victor.lopez (at) visengi (dot) com) |
-- |
-- Create Date: 01:34:59 31/October/2008 |
-- Project Name: IMA ADPCM Encoder |
-- Tool versions: Xilinx ISE 9.2i |
-- Description: |
-- |
-- Description: This project features a full-hardware sound compressor using the well known algorithm IMA ADPCM. |
-- The core acts as a slave WISHBONE device. The output is perfectly compatible with any sound player |
-- with the IMA ADPCM codec (included by default in every Windows). Includes a testbench that takes |
-- an uncompressed PCM 16 bits Mono WAV file and outputs an IMA ADPCM compressed WAV file. |
-- Compression ratio is fixed for IMA-ADPCM, being 4:1. |
-- |
-- |
-- LICENSE TERMS: GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 |
-- That is you may use it in ANY project (commercial or not) without paying a cent. |
-- You are only required to include in the copyrights/about section of accompanying |
-- software and manuals of use that your system contains a "IMA ADPCM Encoder |
-- (C) VISENGI S.L. under LGPL license" |
-- This holds also in the case where you modify the core, as the resulting core |
-- would be a derived work. |
-- Also, we would like to know if you use this core in a project of yours, just an email will do. |
-- |
-- Please take good note of the disclaimer section of the LPGL license, as we don't |
-- take any responsability for anything that this core does. |
---------------------------------------------------------------------------------- |
|
-------------------------------------------------------------------------------- |
-- |
-- static const uint16_t IMA_ADPCMStepTable[89] = |
-- { |
-- 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 |
-- }; |
-- |
-------------------------------------------------------------------------------- |
|
library IEEE; |
use IEEE.STD_LOGIC_1164.all; |
use ieee.numeric_std.all; |
|
entity IMA_adpcm_steptable_rom is |
generic (ROMADDR_W : integer := 7; |
ROMDATA_W : integer := 15); |
port( |
addr0 : in STD_LOGIC_VECTOR(ROMADDR_W-1 downto 0); |
clk : in STD_LOGIC; |
datao0 : out STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0)); |
end IMA_adpcm_steptable_rom; |
|
architecture RTL of IMA_adpcm_steptable_rom is |
|
type ROM_TYPE is array (0 to 2**ROMADDR_W-1) |
of STD_LOGIC_VECTOR(ROMDATA_W-1 downto 0); |
constant rom : ROM_TYPE := |
( |
"000000000000111", |
"000000000001000", |
"000000000001001", |
"000000000001010", |
"000000000001011", |
"000000000001100", |
"000000000001101", |
"000000000001110", |
"000000000010000", |
"000000000010001", |
"000000000010011", |
"000000000010101", |
"000000000010111", |
"000000000011001", |
"000000000011100", |
"000000000011111", |
"000000000100010", |
"000000000100101", |
"000000000101001", |
"000000000101101", |
"000000000110010", |
"000000000110111", |
"000000000111100", |
"000000001000010", |
"000000001001001", |
"000000001010000", |
"000000001011000", |
"000000001100001", |
"000000001101011", |
"000000001110110", |
"000000010000010", |
"000000010001111", |
"000000010011101", |
"000000010101101", |
"000000010111110", |
"000000011010001", |
"000000011100110", |
"000000011111101", |
"000000100010111", |
"000000100110011", |
"000000101010001", |
"000000101110011", |
"000000110011000", |
"000000111000001", |
"000000111101110", |
"000001000100000", |
"000001001010110", |
"000001010010010", |
"000001011010100", |
"000001100011100", |
"000001101101100", |
"000001111000011", |
"000010000100100", |
"000010010001110", |
"000010100000010", |
"000010110000011", |
"000011000010000", |
"000011010101011", |
"000011101010110", |
"000100000010010", |
"000100011100000", |
"000100111000011", |
"000101010111101", |
"000101111010000", |
"000110011111111", |
"000111001001100", |
"000111110111010", |
"001000101001100", |
"001001100000111", |
"001010011101110", |
"001011100000110", |
"001100101010100", |
"001101111011100", |
"001111010100101", |
"010000110110110", |
"010010100010101", |
"010100011001010", |
"010110011011111", |
"011000101011011", |
"011011001001011", |
"011101110111001", |
"100000110110010", |
"100100001000100", |
"100111101111110", |
"101011101110001", |
"110000000101111", |
"110100111001110", |
"111010001100010", |
"111111111111111", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000", |
"000000000000000" |
); |
signal addr_reg0 : STD_LOGIC_VECTOR(ROMADDR_W-1 downto 0); |
|
begin |
|
datao0 <= rom( TO_INTEGER(UNSIGNED(addr_reg0)) ); |
|
process(clk) |
begin |
if clk = '1' and clk'event then |
addr_reg0 <= addr0; |
end if; |
end process; |
|
end RTL; |
/trunk/IMA_ADPCM_top.vhd
0,0 → 1,427
---------------------------------------------------------------------------------- |
-- Company: VISENGI S.L. (www.visengi.com) |
-- Engineer: Victor Lopez Lorenzo (victor.lopez (at) visengi (dot) com) |
-- |
-- Create Date: 18:46:15 03/November/2008 |
-- Project Name: IMA ADPCM Encoder |
-- Tool versions: Xilinx ISE 9.2i |
-- Description: |
-- |
-- Description: This project features a full-hardware sound compressor using the well known algorithm IMA ADPCM. |
-- The core acts as a slave WISHBONE device. The output is perfectly compatible with any sound player |
-- with the IMA ADPCM codec (included by default in every Windows). Includes a testbench that takes |
-- an uncompressed PCM 16 bits Mono WAV file and outputs an IMA ADPCM compressed WAV file. |
-- Compression ratio is fixed for IMA-ADPCM, being 4:1. |
-- |
-- |
-- LICENSE TERMS: GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 |
-- That is you may use it in ANY project (commercial or not) without paying a cent. |
-- You are only required to include in the copyrights/about section of accompanying |
-- software and manuals of use that your system contains a "IMA ADPCM Encoder |
-- (C) VISENGI S.L. under LGPL license" |
-- This holds also in the case where you modify the core, as the resulting core |
-- would be a derived work. |
-- Also, we would like to know if you use this core in a project of yours, just an email will do. |
-- |
-- Please take good note of the disclaimer section of the LPGL license, as we don't |
-- take any responsability for anything that this core does. |
---------------------------------------------------------------------------------- |
|
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_ARITH.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
entity IMA_ADPCM_top is |
Port ( wb_clk_i : in std_logic; |
wb_rst_i : in std_logic; |
wb_cyc_i : in std_logic; |
wb_stb_i : in std_logic; |
wb_we_i : in std_logic; |
wb_adr_i : in std_logic_vector(1 downto 0); |
wb_dat_i : in std_logic_vector(15 downto 0); |
wb_dat_o : out std_logic_vector(15 downto 0); |
wb_ack_o : out std_logic); |
end IMA_ADPCM_top; |
|
architecture Behavioral of IMA_ADPCM_top is |
component IMA_ADPCM_Encode port ( |
clk : in STD_LOGIC; |
reset : in STD_LOGIC; |
PredictedValue_o : out std_logic_vector(15 downto 0); |
StepIndex_o : out std_logic_vector(6 downto 0); |
StateRDY : out std_logic; |
sample : in std_logic_vector(15 downto 0); --don't change it while sample_rdy='1' |
sample_rdy : in std_logic; --lower it only when ADPCM_sample_rdy = '1' |
ADPCM_sample : out std_logic_vector(3 downto 0); |
ADPCM_sample_rdy : out std_logic); |
end component; |
|
component WAV_header_rom port( |
addr0 : in STD_LOGIC_VECTOR(5 downto 0); |
clk : in STD_LOGIC; |
datao0: out STD_LOGIC_VECTOR(7 downto 0)); |
end component; |
|
signal WAV_addr : std_logic_vector(5 downto 0); |
signal WAV_data : std_logic_vector(7 downto 0); |
|
signal sample : std_logic_vector(15 downto 0); |
signal ADPCM_sample : std_logic_vector(3 downto 0); |
signal sample_rdy, ADPCM_sample_rdy : std_logic; |
|
signal soft_reset, isoft_reset : std_logic; |
signal iwb_ack_o : std_logic; |
|
|
-- IMPORTANT: Remember that flow control MUST be done externally (that is, if SamplesPerSec is set to 8000, then 8000 samples must be fed every second) |
-- The first 60 bytes of data correspond to the WAV header |
-- |
--WISHBONE REGS' DESCRIPTION: |
--reg 0: Control(W: WRITES)/Status(R: READS) |
-- bit 15: (R) 0=finished, 1=compressing (W) 0=end file (if compressing), 1=start file compression |
-- clearing this bit while compressing doesn't immediately end it, because the current block must be finished (block size=256 bytes) |
-- the only thing that happens is that the next samples up to the end of the block (samples_per_block=505) will be zeros (silence). |
-- bit 1: (R) 1=ready for new input sample to be written on reg 3 (auto-cleared on write to reg 3), 0=processing last input sample |
-- bit 0: (R) 1=16 bits of output file are ready to be read on reg 3 (auto-cleared on read to reg 3), 0=processing next output word |
--reg 1: SamplesPerSec (i.e.: 8000, 22050, 32000, 44100, ...) |
--reg 2: SecondsToCompress (0 for undefined (max values will be used in file headers) -> the sound will be complete and reproducible but an "early EOF" or "damaged file" error may appear in player at the end of the sound) |
--reg 3: On writes: a 16 bit sample is expected - On reads: data lines will contain 16 bits of the compressed output file (only if reg(0)(0)='1'!!!) |
--output words of 16 bits should be read from MSB to LSB |
|
signal SamplesPerSec1, SecondsToCompress2, CompressedWord : std_logic_vector(15 downto 0); |
signal InputRDY, OutputRDY, OutputRDY_sync2, RDYOutput, FinishBlock : std_logic; |
signal StartCompressing, Compressing, EndCompression : std_logic; |
signal CompressedNibbles : integer range 0 to 4; |
|
signal WriteHeader, WriteHeader_sync2 : std_logic; |
signal WriteState, WriteState_sync2 : std_logic; |
signal BlockBytes : integer range 0 to 255; |
signal SecondsCompressed : std_logic_vector(15 downto 0); |
signal SamplesCompressed : std_logic_vector(15 downto 0); |
signal MSB, LoadROM : std_logic; |
signal SamplesInFile : std_logic_vector(31 downto 0); |
|
signal PredictedValue : std_logic_vector(15 downto 0); |
signal StepIndex : std_logic_vector(6 downto 0); |
signal StateRDY : std_logic; |
signal WriteStateLSWord : std_logic; |
begin |
isoft_reset <= soft_reset or wb_rst_i; |
|
WAV_ROM: WAV_header_rom port map ( |
addr0 => WAV_addr, |
clk => wb_clk_i, |
datao0 => WAV_data); |
|
IMA_ADPCM_Encoder : IMA_ADPCM_Encode port map ( |
clk => wb_clk_i, |
reset => isoft_reset, |
PredictedValue_o => PredictedValue, |
StepIndex_o => StepIndex, |
StateRDY => StateRDY, |
sample => sample, |
sample_rdy => sample_rdy, |
ADPCM_sample => ADPCM_sample, |
ADPCM_sample_rdy => ADPCM_sample_rdy); |
|
Input_process : process (wb_clk_i, wb_rst_i) |
variable WaitW : std_logic; |
begin |
if (wb_rst_i = '1') then |
iwb_ack_o <= '0'; |
wb_dat_o <= (others => '0'); |
InputRDY <= '0'; |
OutputRDY <= '0'; |
OutputRDY_sync2 <= '0'; |
SamplesPerSec1 <= (others => '0'); |
SecondsToCompress2 <= (others => '0'); |
Compressing <= '0'; |
StartCompressing <= '0'; |
WaitW := '0'; |
soft_reset <= '0'; |
|
sample <= (others => '0'); |
sample_rdy <= '0'; |
elsif (wb_clk_i = '1' and wb_clk_i'event) then |
OutputRDY_sync2 <= OutputRDY; |
soft_reset <= '0'; |
iwb_ack_o <= wb_cyc_i and wb_stb_i and not iwb_ack_o; |
|
if (RDYOutput = '1') then OutputRDY <= '1'; end if; |
if (ADPCM_sample_rdy = '1') then |
sample_rdy <= '0'; |
if (CompressedNibbles < 3 and WriteState = '0') then InputRDY <= '1'; end if; |
end if; |
|
if (OutputRDY_sync2 = '1' and OutputRDY = '0' and WriteState = '0' and WriteHeader = '0') then InputRDY <= '1'; end if; |
if (((OutputRDY_sync2 = '1' and OutputRDY = '0') or (WriteHeader_sync2 = '1' and WriteHeader = '0')) and WriteState = '1' and BlockBytes = 0 and WaitW = '0') then InputRDY <= '1'; WaitW := '1'; end if; --to write the block header one input sample is required |
if (WriteState_sync2 = '1' and WriteState = '0') then InputRDY <= '1'; WaitW := '0'; end if; --after writing the block header, ask for input sample |
|
|
if (EndCompression = '1') then Compressing <= '0'; end if; |
|
if (FinishBlock = '1') then |
sample <= x"0000"; |
sample_rdy <= '1'; |
InputRDY <= '0'; |
end if; |
|
if (wb_cyc_i = '1' and wb_stb_i = '1') then |
case wb_adr_i is |
when "00" => --control/status |
if (wb_we_i = '0') then --read = status |
wb_dat_o <= (others => '0'); |
wb_dat_o(15) <= Compressing; |
wb_dat_o(1) <= InputRDY; |
wb_dat_o(0) <= OutputRDY; |
else --write = control |
StartCompressing <= wb_dat_i(15); |
if (wb_dat_i(15) = '1' and Compressing = '0') then --start new operation? |
soft_reset <= '1'; |
OutputRDY <= '0'; |
InputRDY <= '0'; --wait for WriteHeader |
Compressing <= '1'; |
end if; |
end if; |
when "11" => --data in/out |
if (wb_we_i = '0') then --read = get compressed data |
if (OutputRDY = '1') then |
wb_dat_o <= CompressedWord; |
OutputRDY <= '0'; |
end if; |
else --write = put input sample |
if (InputRDY = '1') then |
if (FinishBlock = '0') then sample <= wb_dat_i; else sample <= x"0000"; end if; |
sample_rdy <= '1'; |
InputRDY <= '0'; |
end if; |
end if; |
when "01" => --SamplesPerSec |
if (wb_we_i = '0') then --read |
wb_dat_o <= SamplesPerSec1; |
else --write |
SamplesPerSec1 <= wb_dat_i; |
end if; |
when "10" => --SecondsToCompress |
if (wb_we_i = '0') then --read |
wb_dat_o <= SecondsToCompress2; |
else --write |
SecondsToCompress2 <= wb_dat_i; |
end if; |
when others => |
report "-----------> Wrong WB Address!" severity WARNING; |
end case; |
end if; |
end if; |
end process; |
|
wb_ack_o <= iwb_ack_o; |
|
|
Output_process : process (wb_clk_i, wb_rst_i) |
variable WaitADPCM : std_logic; |
variable WAV_data_to_write : std_logic_vector(7 downto 0); |
begin |
if (wb_rst_i = '1') then |
CompressedWord <= (others => '0'); |
RDYOutput <= '0'; |
WriteHeader <= '1'; |
WriteHeader_sync2 <= '1'; |
FinishBlock <= '0'; |
BlockBytes <= 0; |
CompressedNibbles <= 0; |
EndCompression <= '0'; |
MSB <= '1'; |
LoadROM <= '1'; |
WAV_addr <= (others => '0'); |
WAV_data_to_write := (others => '0'); |
|
SecondsCompressed <= (others => '0'); |
SamplesCompressed <= (others => '0'); |
|
WriteState <= '0'; |
WriteState_sync2 <= '0'; |
WriteStateLSWord <= '0'; |
WaitADPCM := '0'; |
elsif (wb_clk_i = '1' and wb_clk_i'event) then |
WriteHeader_sync2 <= WriteHeader; |
WriteState_sync2 <= WriteState; |
|
if (WriteState_sync2 = '0' and WriteState = '1') then WaitADPCM := '1'; end if; |
|
EndCompression <= '0'; |
RDYOutput <= '0'; |
if (StartCompressing = '0' and Compressing = '1') then FinishBlock <= '1'; end if; --finish compression on end of current block! |
|
if (ADPCM_sample_rdy = '1' and WriteState = '0') then --because WriteState uses one ADPCM_sample_rdy to write its own header sample |
case CompressedNibbles is --little endian on each byte (byte 0:n1n0, byte 1:n3n2, ...) |
when 0 => |
CompressedWord(11 downto 8) <= ADPCM_sample; |
CompressedNibbles <= CompressedNibbles + 1; |
when 1 => |
CompressedWord(15 downto 12) <= ADPCM_sample; |
CompressedNibbles <= CompressedNibbles + 1; |
when 2 => |
CompressedWord(3 downto 0) <= ADPCM_sample; |
CompressedNibbles <= CompressedNibbles + 1; |
when 3 => |
CompressedWord(7 downto 4) <= ADPCM_sample; |
CompressedNibbles <= CompressedNibbles + 1; |
if (BlockBytes /= 254) then |
BlockBytes <= BlockBytes + 2; |
else |
BlockBytes <= 0; |
WriteState <= '1'; |
end if; |
when others => --4 pending wb read of reg 3 |
CompressedNibbles <= CompressedNibbles; |
end case; |
|
|
if (SamplesCompressed = SamplesPerSec1) then |
if (SecondsCompressed = SecondsToCompress2) then |
FinishBlock <= '1'; --finish compression on end of current block! |
else |
SamplesCompressed <= (others => '0'); |
SecondsCompressed <= SecondsCompressed + 1; |
end if; |
else |
SamplesCompressed <= SamplesCompressed + 1; |
end if; |
end if; |
|
if (Compressing = '1' and EndCompression = '0') then |
if (CompressedNibbles = 4) then |
if (OutputRDY_sync2 = '1' and OutputRDY = '0') then |
CompressedNibbles <= 0; |
if (WriteStateLSWord = '0' and BlockBytes = 4) then WriteState <= '0'; end if; --lower it (but not in the cycle it is risen!) |
else |
if (OutputRDY = '0' and RDYOutput = '0') then RDYOutput <= '1'; end if; |
end if; |
else |
if (RDYOutput = '0' and OutputRDY = '0') then --get next nibble/s if last CompressedWord is read |
if (FinishBlock = '1') then --finish compression on end of current block! |
if (BlockBytes = 0) then |
EndCompression <= '1'; --signal input process the end of the compression |
end if; |
else --normal operation |
if (WriteHeader = '1') then --output WAV header |
if (LoadROM = '0') then |
LoadROM <= '1'; --give the ROM time to read a byte |
if (WAV_addr = "111100") then --last header byte + 1 |
WAV_addr <= (others => '0'); |
WriteHeader <= '0'; |
WriteState <= '1'; |
end if; |
else |
WAV_addr <= WAV_addr + 1; |
WAV_data_to_write := WAV_data; --by default times are for undefined in WAV header |
case WAV_addr is --all data is little-endian! |
when "000100" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(7 downto 0); end if; --LSB of file_size-8 (FF for undefined) |
when "000101" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(15 downto 8); end if; --LSB2 of file_size-8 (FF for undefined) |
when "000110" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(23 downto 16); end if; --MSB2 of file_size-8 (FF for undefined) |
when "000111" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(31 downto 24); end if; --MSB of file_size-8 (7F for undefined) |
|
when "011000" => WAV_data_to_write := SamplesPerSec1(7 downto 0); --LSB of SamplesPerSec |
when "011001" => WAV_data_to_write := SamplesPerSec1(15 downto 8); --MSB of SamplesPerSec |
when "011100" => WAV_data_to_write := SamplesPerSec1(8 downto 1); --LSB of AvgBytesPerSec : approx. SamplesPerSec/2 |
when "011101" => WAV_data_to_write := '0' & SamplesPerSec1(15 downto 9); --MSB of AvgBytesPerSec : approx. SamplesPerSec/2 |
|
when "110000" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(7 downto 0); end if; --LSB of SamplesPerChannelInFile (FF for undefined) |
when "110001" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(15 downto 8); end if; --LSB2 of SamplesPerChannelInFile (FF for undefined) |
when "110010" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(23 downto 16); end if; --MSB2 of SamplesPerChannelInFile (FF for undefined) |
when "110011" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(31 downto 24); end if; --MSB of SamplesPerChannelInFile (7F for undefined) |
|
when "111000" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(7 downto 0); end if; --LSB of file_size-60 (FF for undefined) |
when "111001" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(15 downto 8); end if; --LSB2 of file_size-60 (FF for undefined) |
when "111010" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(23 downto 16); end if; --MSB2 of file_size-60 (FF for undefined) |
when "111011" => if (SecondsToCompress2 /= x"0000") then WAV_data_to_write := SamplesInFile(31 downto 24); end if; --MSB of file_size-60 (7F for undefined) |
when others => null; |
end case; |
if (MSB = '1') then |
CompressedWord(15 downto 8) <= WAV_data_to_write; |
else |
CompressedWord(7 downto 0) <= WAV_data_to_write; |
CompressedNibbles <= 4; --signal word ready |
end if; |
MSB <= not MSB; |
LoadROM <= '0'; |
end if; |
else --output ADPCM data |
if (WriteState = '1' and FinishBlock = '0') then --block header with state at the beginning and every 256 bytes |
if (WaitADPCM = '1') then |
if (ADPCM_sample_rdy = '1') then WaitADPCM := '0'; end if; |
else |
if (StateRDY = '1') then |
if (WriteStateLSWord = '0') then --write first two bytes of state: PredictedValue |
CompressedWord <= PredictedValue(7 downto 0) & PredictedValue(15 downto 8); --little endian! |
BlockBytes <= 2; |
SamplesCompressed <= SamplesCompressed + 1; |
else --write second two bytes of state: StepIndex & x"00" |
CompressedWord <= '0' & StepIndex & x"00"; |
--WriteState <= '0'; lower it only after Output written |
BlockBytes <= BlockBytes + 2; |
end if; |
WriteStateLSWord <= not WriteStateLSWord; |
CompressedNibbles <= 4; --signal word ready |
end if; |
end if; |
else --data nibbles |
null; --taken care of above |
end if; |
end if; |
end if; |
end if; |
end if; |
else |
CompressedWord <= (others => '0'); |
RDYOutput <= '0'; |
WriteHeader <= '1'; |
FinishBlock <= '0'; |
BlockBytes <= 0; |
CompressedNibbles <= 0; |
EndCompression <= '0'; |
MSB <= '1'; |
LoadROM <= '1'; |
WAV_addr <= (others => '0'); |
SecondsCompressed <= (others => '0'); |
SamplesCompressed <= (others => '0'); |
WriteState <= '0'; |
WriteStateLSWord <= '0'; |
WaitADPCM := '0'; |
end if; |
end if; |
end process; |
|
process (wb_clk_i, wb_rst_i) |
begin |
if (wb_rst_i = '1') then |
SamplesInFile <= (others => '0'); |
elsif (wb_clk_i = '1' and wb_clk_i'event) then |
--comment next lines to save up a lot of resources (multiplier), |
--but then use undefined number of seconds for compression!! |
--(to stop it just write 0 to the MSb of WB reg 0) |
--just be aware that final WAV file will play but at the end, |
--some players will display an error saying something like "Early EOF" or "Corrupted file". |
|
--if (Compressing = '1' and EndCompression = '0') then |
--SamplesInFile <= SamplesPerSec1 * SecondsToCompress2; |
--else |
if (LoadROM = '1') then |
if (WAV_addr = "000000") then --file_size-8=SamplesInFile/2+52 |
--file size calculation is approximate, unless you want to mess up with floats |
--or you have a fixed sampling rate (and want to modify the source code of this process) |
SamplesInFile <= (('0' & SamplesPerSec1(15 downto 1)) * SecondsToCompress2) + x"34"; |
--SamplesInFile <= '0' & (SamplesInFile(31 downto 1) + x"34"); |
elsif (WAV_addr = "011101") then --get raw SamplesInFile |
SamplesInFile <= SamplesPerSec1 * SecondsToCompress2; |
elsif (WAV_addr = "110100") then --file_size-60=SamplesInFile/2 |
SamplesInFile <= '0' & SamplesInFile(31 downto 1); |
end if; |
end if; |
--end if; |
end if; |
end process; |
end Behavioral; |
|
/trunk/lgpl.txt
0,0 → 1,504
GNU LESSER GENERAL PUBLIC LICENSE |
Version 2.1, February 1999 |
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc. |
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Everyone is permitted to copy and distribute verbatim copies |
of this license document, but changing it is not allowed. |
|
[This is the first released version of the Lesser GPL. It also counts |
as the successor of the GNU Library Public License, version 2, hence |
the version number 2.1.] |
|
Preamble |
|
The licenses for most software are designed to take away your |
freedom to share and change it. By contrast, the GNU General Public |
Licenses are intended to guarantee your freedom to share and change |
free software--to make sure the software is free for all its users. |
|
This license, the Lesser General Public License, applies to some |
specially designated software packages--typically libraries--of the |
Free Software Foundation and other authors who decide to use it. You |
can use it too, but we suggest you first think carefully about whether |
this license or the ordinary General Public License is the better |
strategy to use in any particular case, based on the explanations below. |
|
When we speak of free software, we are referring to freedom of use, |
not price. Our General Public Licenses are designed to make sure that |
you have the freedom to distribute copies of free software (and charge |
for this service if you wish); that you receive source code or can get |
it if you want it; that you can change the software and use pieces of |
it in new free programs; and that you are informed that you can do |
these things. |
|
To protect your rights, we need to make restrictions that forbid |
distributors to deny you these rights or to ask you to surrender these |
rights. These restrictions translate to certain responsibilities for |
you if you distribute copies of the library or if you modify it. |
|
For example, if you distribute copies of the library, whether gratis |
or for a fee, you must give the recipients all the rights that we gave |
you. You must make sure that they, too, receive or can get the source |
code. If you link other code with the library, you must provide |
complete object files to the recipients, so that they can relink them |
with the library after making changes to the library and recompiling |
it. And you must show them these terms so they know their rights. |
|
We protect your rights with a two-step method: (1) we copyright the |
library, and (2) we offer you this license, which gives you legal |
permission to copy, distribute and/or modify the library. |
|
To protect each distributor, we want to make it very clear that |
there is no warranty for the free library. Also, if the library is |
modified by someone else and passed on, the recipients should know |
that what they have is not the original version, so that the original |
author's reputation will not be affected by problems that might be |
introduced by others. |
|
Finally, software patents pose a constant threat to the existence of |
any free program. We wish to make sure that a company cannot |
effectively restrict the users of a free program by obtaining a |
restrictive license from a patent holder. Therefore, we insist that |
any patent license obtained for a version of the library must be |
consistent with the full freedom of use specified in this license. |
|
Most GNU software, including some libraries, is covered by the |
ordinary GNU General Public License. This license, the GNU Lesser |
General Public License, applies to certain designated libraries, and |
is quite different from the ordinary General Public License. We use |
this license for certain libraries in order to permit linking those |
libraries into non-free programs. |
|
When a program is linked with a library, whether statically or using |
a shared library, the combination of the two is legally speaking a |
combined work, a derivative of the original library. The ordinary |
General Public License therefore permits such linking only if the |
entire combination fits its criteria of freedom. The Lesser General |
Public License permits more lax criteria for linking other code with |
the library. |
|
We call this license the "Lesser" General Public License because it |
does Less to protect the user's freedom than the ordinary General |
Public License. It also provides other free software developers Less |
of an advantage over competing non-free programs. These disadvantages |
are the reason we use the ordinary General Public License for many |
libraries. However, the Lesser license provides advantages in certain |
special circumstances. |
|
For example, on rare occasions, there may be a special need to |
encourage the widest possible use of a certain library, so that it becomes |
a de-facto standard. To achieve this, non-free programs must be |
allowed to use the library. A more frequent case is that a free |
library does the same job as widely used non-free libraries. In this |
case, there is little to gain by limiting the free library to free |
software only, so we use the Lesser General Public License. |
|
In other cases, permission to use a particular library in non-free |
programs enables a greater number of people to use a large body of |
free software. For example, permission to use the GNU C Library in |
non-free programs enables many more people to use the whole GNU |
operating system, as well as its variant, the GNU/Linux operating |
system. |
|
Although the Lesser General Public License is Less protective of the |
users' freedom, it does ensure that the user of a program that is |
linked with the Library has the freedom and the wherewithal to run |
that program using a modified version of the Library. |
|
The precise terms and conditions for copying, distribution and |
modification follow. Pay close attention to the difference between a |
"work based on the library" and a "work that uses the library". The |
former contains code derived from the library, whereas the latter must |
be combined with the library in order to run. |
|
GNU LESSER GENERAL PUBLIC LICENSE |
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
|
0. This License Agreement applies to any software library or other |
program which contains a notice placed by the copyright holder or |
other authorized party saying it may be distributed under the terms of |
this Lesser General Public License (also called "this License"). |
Each licensee is addressed as "you". |
|
A "library" means a collection of software functions and/or data |
prepared so as to be conveniently linked with application programs |
(which use some of those functions and data) to form executables. |
|
The "Library", below, refers to any such software library or work |
which has been distributed under these terms. A "work based on the |
Library" means either the Library or any derivative work under |
copyright law: that is to say, a work containing the Library or a |
portion of it, either verbatim or with modifications and/or translated |
straightforwardly into another language. (Hereinafter, translation is |
included without limitation in the term "modification".) |
|
"Source code" for a work means the preferred form of the work for |
making modifications to it. For a library, complete source code means |
all the source code for all modules it contains, plus any associated |
interface definition files, plus the scripts used to control compilation |
and installation of the library. |
|
Activities other than copying, distribution and modification are not |
covered by this License; they are outside its scope. The act of |
running a program using the Library is not restricted, and output from |
such a program is covered only if its contents constitute a work based |
on the Library (independent of the use of the Library in a tool for |
writing it). Whether that is true depends on what the Library does |
and what the program that uses the Library does. |
|
1. You may copy and distribute verbatim copies of the Library's |
complete source code as you receive it, in any medium, provided that |
you conspicuously and appropriately publish on each copy an |
appropriate copyright notice and disclaimer of warranty; keep intact |
all the notices that refer to this License and to the absence of any |
warranty; and distribute a copy of this License along with the |
Library. |
|
You may charge a fee for the physical act of transferring a copy, |
and you may at your option offer warranty protection in exchange for a |
fee. |
|
2. You may modify your copy or copies of the Library or any portion |
of it, thus forming a work based on the Library, and copy and |
distribute such modifications or work under the terms of Section 1 |
above, provided that you also meet all of these conditions: |
|
a) The modified work must itself be a software library. |
|
b) You must cause the files modified to carry prominent notices |
stating that you changed the files and the date of any change. |
|
c) You must cause the whole of the work to be licensed at no |
charge to all third parties under the terms of this License. |
|
d) If a facility in the modified Library refers to a function or a |
table of data to be supplied by an application program that uses |
the facility, other than as an argument passed when the facility |
is invoked, then you must make a good faith effort to ensure that, |
in the event an application does not supply such function or |
table, the facility still operates, and performs whatever part of |
its purpose remains meaningful. |
|
(For example, a function in a library to compute square roots has |
a purpose that is entirely well-defined independent of the |
application. Therefore, Subsection 2d requires that any |
application-supplied function or table used by this function must |
be optional: if the application does not supply it, the square |
root function must still compute square roots.) |
|
These requirements apply to the modified work as a whole. If |
identifiable sections of that work are not derived from the Library, |
and can be reasonably considered independent and separate works in |
themselves, then this License, and its terms, do not apply to those |
sections when you distribute them as separate works. But when you |
distribute the same sections as part of a whole which is a work based |
on the Library, the distribution of the whole must be on the terms of |
this License, whose permissions for other licensees extend to the |
entire whole, and thus to each and every part regardless of who wrote |
it. |
|
Thus, it is not the intent of this section to claim rights or contest |
your rights to work written entirely by you; rather, the intent is to |
exercise the right to control the distribution of derivative or |
collective works based on the Library. |
|
In addition, mere aggregation of another work not based on the Library |
with the Library (or with a work based on the Library) on a volume of |
a storage or distribution medium does not bring the other work under |
the scope of this License. |
|
3. You may opt to apply the terms of the ordinary GNU General Public |
License instead of this License to a given copy of the Library. To do |
this, you must alter all the notices that refer to this License, so |
that they refer to the ordinary GNU General Public License, version 2, |
instead of to this License. (If a newer version than version 2 of the |
ordinary GNU General Public License has appeared, then you can specify |
that version instead if you wish.) Do not make any other change in |
these notices. |
|
Once this change is made in a given copy, it is irreversible for |
that copy, so the ordinary GNU General Public License applies to all |
subsequent copies and derivative works made from that copy. |
|
This option is useful when you wish to copy part of the code of |
the Library into a program that is not a library. |
|
4. You may copy and distribute the Library (or a portion or |
derivative of it, under Section 2) in object code or executable form |
under the terms of Sections 1 and 2 above provided that you accompany |
it with the complete corresponding machine-readable source code, which |
must be distributed under the terms of Sections 1 and 2 above on a |
medium customarily used for software interchange. |
|
If distribution of object code is made by offering access to copy |
from a designated place, then offering equivalent access to copy the |
source code from the same place satisfies the requirement to |
distribute the source code, even though third parties are not |
compelled to copy the source along with the object code. |
|
5. A program that contains no derivative of any portion of the |
Library, but is designed to work with the Library by being compiled or |
linked with it, is called a "work that uses the Library". Such a |
work, in isolation, is not a derivative work of the Library, and |
therefore falls outside the scope of this License. |
|
However, linking a "work that uses the Library" with the Library |
creates an executable that is a derivative of the Library (because it |
contains portions of the Library), rather than a "work that uses the |
library". The executable is therefore covered by this License. |
Section 6 states terms for distribution of such executables. |
|
When a "work that uses the Library" uses material from a header file |
that is part of the Library, the object code for the work may be a |
derivative work of the Library even though the source code is not. |
Whether this is true is especially significant if the work can be |
linked without the Library, or if the work is itself a library. The |
threshold for this to be true is not precisely defined by law. |
|
If such an object file uses only numerical parameters, data |
structure layouts and accessors, and small macros and small inline |
functions (ten lines or less in length), then the use of the object |
file is unrestricted, regardless of whether it is legally a derivative |
work. (Executables containing this object code plus portions of the |
Library will still fall under Section 6.) |
|
Otherwise, if the work is a derivative of the Library, you may |
distribute the object code for the work under the terms of Section 6. |
Any executables containing that work also fall under Section 6, |
whether or not they are linked directly with the Library itself. |
|
6. As an exception to the Sections above, you may also combine or |
link a "work that uses the Library" with the Library to produce a |
work containing portions of the Library, and distribute that work |
under terms of your choice, provided that the terms permit |
modification of the work for the customer's own use and reverse |
engineering for debugging such modifications. |
|
You must give prominent notice with each copy of the work that the |
Library is used in it and that the Library and its use are covered by |
this License. You must supply a copy of this License. If the work |
during execution displays copyright notices, you must include the |
copyright notice for the Library among them, as well as a reference |
directing the user to the copy of this License. Also, you must do one |
of these things: |
|
a) Accompany the work with the complete corresponding |
machine-readable source code for the Library including whatever |
changes were used in the work (which must be distributed under |
Sections 1 and 2 above); and, if the work is an executable linked |
with the Library, with the complete machine-readable "work that |
uses the Library", as object code and/or source code, so that the |
user can modify the Library and then relink to produce a modified |
executable containing the modified Library. (It is understood |
that the user who changes the contents of definitions files in the |
Library will not necessarily be able to recompile the application |
to use the modified definitions.) |
|
b) Use a suitable shared library mechanism for linking with the |
Library. A suitable mechanism is one that (1) uses at run time a |
copy of the library already present on the user's computer system, |
rather than copying library functions into the executable, and (2) |
will operate properly with a modified version of the library, if |
the user installs one, as long as the modified version is |
interface-compatible with the version that the work was made with. |
|
c) Accompany the work with a written offer, valid for at |
least three years, to give the same user the materials |
specified in Subsection 6a, above, for a charge no more |
than the cost of performing this distribution. |
|
d) If distribution of the work is made by offering access to copy |
from a designated place, offer equivalent access to copy the above |
specified materials from the same place. |
|
e) Verify that the user has already received a copy of these |
materials or that you have already sent this user a copy. |
|
For an executable, the required form of the "work that uses the |
Library" must include any data and utility programs needed for |
reproducing the executable from it. However, as a special exception, |
the materials to be distributed need not include anything that is |
normally distributed (in either source or binary form) with the major |
components (compiler, kernel, and so on) of the operating system on |
which the executable runs, unless that component itself accompanies |
the executable. |
|
It may happen that this requirement contradicts the license |
restrictions of other proprietary libraries that do not normally |
accompany the operating system. Such a contradiction means you cannot |
use both them and the Library together in an executable that you |
distribute. |
|
7. You may place library facilities that are a work based on the |
Library side-by-side in a single library together with other library |
facilities not covered by this License, and distribute such a combined |
library, provided that the separate distribution of the work based on |
the Library and of the other library facilities is otherwise |
permitted, and provided that you do these two things: |
|
a) Accompany the combined library with a copy of the same work |
based on the Library, uncombined with any other library |
facilities. This must be distributed under the terms of the |
Sections above. |
|
b) Give prominent notice with the combined library of the fact |
that part of it is a work based on the Library, and explaining |
where to find the accompanying uncombined form of the same work. |
|
8. You may not copy, modify, sublicense, link with, or distribute |
the Library except as expressly provided under this License. Any |
attempt otherwise to copy, modify, sublicense, link with, or |
distribute the Library is void, and will automatically terminate your |
rights under this License. However, parties who have received copies, |
or rights, from you under this License will not have their licenses |
terminated so long as such parties remain in full compliance. |
|
9. You are not required to accept this License, since you have not |
signed it. However, nothing else grants you permission to modify or |
distribute the Library or its derivative works. These actions are |
prohibited by law if you do not accept this License. Therefore, by |
modifying or distributing the Library (or any work based on the |
Library), you indicate your acceptance of this License to do so, and |
all its terms and conditions for copying, distributing or modifying |
the Library or works based on it. |
|
10. Each time you redistribute the Library (or any work based on the |
Library), the recipient automatically receives a license from the |
original licensor to copy, distribute, link with or modify the Library |
subject to these terms and conditions. You may not impose any further |
restrictions on the recipients' exercise of the rights granted herein. |
You are not responsible for enforcing compliance by third parties with |
this License. |
|
11. If, as a consequence of a court judgment or allegation of patent |
infringement or for any other reason (not limited to patent issues), |
conditions are imposed on you (whether by court order, agreement or |
otherwise) that contradict the conditions of this License, they do not |
excuse you from the conditions of this License. If you cannot |
distribute so as to satisfy simultaneously your obligations under this |
License and any other pertinent obligations, then as a consequence you |
may not distribute the Library at all. For example, if a patent |
license would not permit royalty-free redistribution of the Library by |
all those who receive copies directly or indirectly through you, then |
the only way you could satisfy both it and this License would be to |
refrain entirely from distribution of the Library. |
|
If any portion of this section is held invalid or unenforceable under any |
particular circumstance, the balance of the section is intended to apply, |
and the section as a whole is intended to apply in other circumstances. |
|
It is not the purpose of this section to induce you to infringe any |
patents or other property right claims or to contest validity of any |
such claims; this section has the sole purpose of protecting the |
integrity of the free software distribution system which is |
implemented by public license practices. Many people have made |
generous contributions to the wide range of software distributed |
through that system in reliance on consistent application of that |
system; it is up to the author/donor to decide if he or she is willing |
to distribute software through any other system and a licensee cannot |
impose that choice. |
|
This section is intended to make thoroughly clear what is believed to |
be a consequence of the rest of this License. |
|
12. If the distribution and/or use of the Library is restricted in |
certain countries either by patents or by copyrighted interfaces, the |
original copyright holder who places the Library under this License may add |
an explicit geographical distribution limitation excluding those countries, |
so that distribution is permitted only in or among countries not thus |
excluded. In such case, this License incorporates the limitation as if |
written in the body of this License. |
|
13. The Free Software Foundation may publish revised and/or new |
versions of the Lesser General Public License from time to time. |
Such new versions will be similar in spirit to the present version, |
but may differ in detail to address new problems or concerns. |
|
Each version is given a distinguishing version number. If the Library |
specifies a version number of this License which applies to it and |
"any later version", you have the option of following the terms and |
conditions either of that version or of any later version published by |
the Free Software Foundation. If the Library does not specify a |
license version number, you may choose any version ever published by |
the Free Software Foundation. |
|
14. If you wish to incorporate parts of the Library into other free |
programs whose distribution conditions are incompatible with these, |
write to the author to ask for permission. For software which is |
copyrighted by the Free Software Foundation, write to the Free |
Software Foundation; we sometimes make exceptions for this. Our |
decision will be guided by the two goals of preserving the free status |
of all derivatives of our free software and of promoting the sharing |
and reuse of software generally. |
|
NO WARRANTY |
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO |
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. |
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR |
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY |
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE |
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME |
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN |
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY |
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU |
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR |
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE |
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING |
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A |
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF |
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
DAMAGES. |
|
END OF TERMS AND CONDITIONS |
|
How to Apply These Terms to Your New Libraries |
|
If you develop a new library, and you want it to be of the greatest |
possible use to the public, we recommend making it free software that |
everyone can redistribute and change. You can do so by permitting |
redistribution under these terms (or, alternatively, under the terms of the |
ordinary General Public License). |
|
To apply these terms, attach the following notices to the library. It is |
safest to attach them to the start of each source file to most effectively |
convey the exclusion of warranty; and each file should have at least the |
"copyright" line and a pointer to where the full notice is found. |
|
<one line to give the library's name and a brief idea of what it does.> |
Copyright (C) <year> <name of author> |
|
This library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Lesser General Public |
License as published by the Free Software Foundation; either |
version 2.1 of the License, or (at your option) any later version. |
|
This library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
Lesser General Public License for more details. |
|
You should have received a copy of the GNU Lesser General Public |
License along with this library; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
Also add information on how to contact you by electronic and paper mail. |
|
You should also get your employer (if you work as a programmer) or your |
school, if any, to sign a "copyright disclaimer" for the library, if |
necessary. Here is a sample; alter the names: |
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the |
library `Frob' (a library for tweaking knobs) written by James Random Hacker. |
|
<signature of Ty Coon>, 1 April 1990 |
Ty Coon, President of Vice |
|
That's all there is to it! |
|
|