1 |
6 |
galland |
----------------------------------------------------------------------------------
|
2 |
|
|
-- Company: VISENGI S.L. (www.visengi.com)
|
3 |
|
|
-- Engineer: Victor Lopez Lorenzo (victor.lopez (at) visengi (dot) com)
|
4 |
|
|
--
|
5 |
7 |
galland |
-- Create Date: 19:34:36 04/November/2008
|
6 |
6 |
galland |
-- Project Name: IMA ADPCM Encoder
|
7 |
|
|
-- Tool versions: Xilinx ISE 9.2i
|
8 |
|
|
-- Description:
|
9 |
|
|
--
|
10 |
|
|
-- Description: This project features a full-hardware sound compressor using the well known algorithm IMA ADPCM.
|
11 |
|
|
-- The core acts as a slave WISHBONE device. The output is perfectly compatible with any sound player
|
12 |
|
|
-- with the IMA ADPCM codec (included by default in every Windows). Includes a testbench that takes
|
13 |
|
|
-- an uncompressed PCM 16 bits Mono WAV file and outputs an IMA ADPCM compressed WAV file.
|
14 |
|
|
-- Compression ratio is fixed for IMA-ADPCM, being 4:1.
|
15 |
|
|
--
|
16 |
|
|
--
|
17 |
7 |
galland |
-- LICENSE TERMS: GNU GENERAL PUBLIC LICENSE Version 3
|
18 |
|
|
--
|
19 |
|
|
-- That is you may use it only in NON-COMMERCIAL projects.
|
20 |
|
|
-- You are only required to include in the copyrights/about section
|
21 |
|
|
-- that your system contains a "IMA ADPCM Encoder (C) VISENGI S.L. under GPL license"
|
22 |
6 |
galland |
-- This holds also in the case where you modify the core, as the resulting core
|
23 |
|
|
-- would be a derived work.
|
24 |
|
|
-- Also, we would like to know if you use this core in a project of yours, just an email will do.
|
25 |
|
|
--
|
26 |
7 |
galland |
-- Please take good note of the disclaimer section of the GPL license, as we don't
|
27 |
6 |
galland |
-- take any responsability for anything that this core does.
|
28 |
|
|
----------------------------------------------------------------------------------
|
29 |
|
|
|
30 |
|
|
library IEEE;
|
31 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
32 |
|
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
33 |
|
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
34 |
|
|
|
35 |
|
|
entity IMA_ADPCM_Encode is
|
36 |
|
|
Port ( clk : in STD_LOGIC;
|
37 |
|
|
reset : in STD_LOGIC;
|
38 |
|
|
|
39 |
|
|
PredictedValue_o : out std_logic_vector(15 downto 0);
|
40 |
|
|
StepIndex_o : out std_logic_vector(6 downto 0);
|
41 |
|
|
StateRDY : out std_logic;
|
42 |
|
|
|
43 |
|
|
sample : in std_logic_vector(15 downto 0); --don't change it while sample_rdy='1'
|
44 |
|
|
sample_rdy : in std_logic; --lower it only when ADPCM_sample_rdy = '1'
|
45 |
|
|
ADPCM_sample : out std_logic_vector(3 downto 0);
|
46 |
|
|
ADPCM_sample_rdy : out std_logic
|
47 |
|
|
);
|
48 |
|
|
end IMA_ADPCM_Encode;
|
49 |
|
|
|
50 |
|
|
architecture Behavioral of IMA_ADPCM_Encode is
|
51 |
|
|
signal PredictedValue : std_logic_vector(15 downto 0);
|
52 |
|
|
signal StepIndex : std_logic_vector(6 downto 0);
|
53 |
|
|
|
54 |
|
|
component IMA_adpcm_steptable_rom port(
|
55 |
|
|
addr0 : in STD_LOGIC_VECTOR(6 downto 0);
|
56 |
|
|
clk : in STD_LOGIC;
|
57 |
|
|
datao0: out STD_LOGIC_VECTOR(14 downto 0));
|
58 |
|
|
end component;
|
59 |
|
|
|
60 |
|
|
signal Step : std_logic_vector(14 downto 0);
|
61 |
|
|
|
62 |
|
|
signal comp16b_AbtB : std_logic; --A bigger than B
|
63 |
|
|
signal delta, diff : std_logic_vector(15 downto 0);
|
64 |
|
|
signal State : integer range 0 to 31;
|
65 |
|
|
begin
|
66 |
|
|
StepTable_ROM : IMA_adpcm_steptable_rom port map (
|
67 |
|
|
addr0 => StepIndex,
|
68 |
|
|
clk => clk,
|
69 |
|
|
datao0=> Step);
|
70 |
|
|
|
71 |
|
|
|
72 |
|
|
|
73 |
|
|
process (reset, clk)
|
74 |
|
|
variable AdderSub16 : std_logic_vector(15 downto 0);
|
75 |
|
|
variable ADPCM_sample2 : std_logic_vector(3 downto 0);
|
76 |
|
|
begin
|
77 |
|
|
if (reset = '1') then
|
78 |
|
|
State <= 0;
|
79 |
|
|
AdderSub16 := (others => '0');
|
80 |
|
|
ADPCM_sample <= x"0";
|
81 |
|
|
ADPCM_sample2 := x"0";
|
82 |
|
|
ADPCM_sample_rdy <= '0';
|
83 |
|
|
|
84 |
|
|
PredictedValue <= (others => '0');
|
85 |
|
|
StepIndex <= (others => '0');
|
86 |
|
|
PredictedValue_o <= (others => '0');
|
87 |
|
|
StepIndex_o <= (others => '0');
|
88 |
|
|
StateRDY <= '0';
|
89 |
|
|
delta <= (others => '0');
|
90 |
|
|
diff <= (others => '0');
|
91 |
|
|
comp16b_AbtB <= '0';
|
92 |
|
|
elsif (clk='1' and clk'event) then
|
93 |
|
|
ADPCM_sample_rdy <= '0';
|
94 |
|
|
|
95 |
|
|
case State is
|
96 |
|
|
when 0 =>
|
97 |
|
|
PredictedValue_o <= PredictedValue; StepIndex_o <= StepIndex; StateRDY <= '1';
|
98 |
|
|
if (sample_rdy = '1') then State <= 10; StateRDY <= '0'; end if;
|
99 |
|
|
when 10 => --Signed comparison between A:sample and B:PredictedValue
|
100 |
|
|
if (sample(15) = '1' and PredictedValue(15) = '0') then
|
101 |
|
|
comp16b_AbtB <= '0'; --sample<0, Pred>=0
|
102 |
|
|
elsif (sample(15) = '0' and PredictedValue(15) = '1') then
|
103 |
|
|
comp16b_AbtB <= '1'; --sample>=0, Pred<0
|
104 |
|
|
else --both positives or both negatives --> normal comparison
|
105 |
|
|
if (sample > PredictedValue) then comp16b_AbtB <= '1'; else comp16b_AbtB <= '0'; end if;
|
106 |
|
|
end if;
|
107 |
|
|
State <= State + 1;
|
108 |
|
|
when 11 =>
|
109 |
|
|
if (comp16b_AbtB = '1') then --it really should be beq but a negative zero is as good as a positive one
|
110 |
|
|
delta <= sample - PredictedValue;
|
111 |
|
|
ADPCM_sample2(3) := '0';
|
112 |
|
|
else
|
113 |
|
|
delta <= PredictedValue - sample;
|
114 |
|
|
ADPCM_sample2(3) := '1'; --set the sign (negative)
|
115 |
|
|
end if;
|
116 |
|
|
State <= State + 1;
|
117 |
|
|
|
118 |
|
|
when 12 => --we've got the rigth Step now
|
119 |
|
|
diff <= "0000" & Step(14 downto 3);
|
120 |
|
|
if (delta > '0' & Step) then comp16b_AbtB <= '1'; else comp16b_AbtB <= '0'; end if;
|
121 |
|
|
State <= State + 1;
|
122 |
|
|
when 13 =>
|
123 |
|
|
if (comp16b_AbtB = '1') then --delta > step
|
124 |
|
|
delta <= delta - ('0' & Step);
|
125 |
|
|
diff <= diff + ('0' & Step);
|
126 |
|
|
ADPCM_sample2(2) := '1';
|
127 |
|
|
else
|
128 |
|
|
ADPCM_sample2(2) := '0';
|
129 |
|
|
end if;
|
130 |
|
|
State <= State + 1;
|
131 |
|
|
|
132 |
|
|
when 14 =>
|
133 |
|
|
if (delta > "00" & Step(14 downto 1)) then comp16b_AbtB <= '1'; else comp16b_AbtB <= '0'; end if;
|
134 |
|
|
State <= State + 1;
|
135 |
|
|
when 15 =>
|
136 |
|
|
if (comp16b_AbtB = '1') then --delta > step
|
137 |
|
|
delta <= delta - ("00" & Step(14 downto 1));
|
138 |
|
|
diff <= diff + ("00" & Step(14 downto 1));
|
139 |
|
|
ADPCM_sample2(1) := '1';
|
140 |
|
|
else
|
141 |
|
|
ADPCM_sample2(1) := '0';
|
142 |
|
|
end if;
|
143 |
|
|
State <= State + 1;
|
144 |
|
|
|
145 |
|
|
when 16 =>
|
146 |
|
|
if (delta > "000" & Step(14 downto 2)) then comp16b_AbtB <= '1'; else comp16b_AbtB <= '0'; end if;
|
147 |
|
|
State <= State + 1;
|
148 |
|
|
when 17 =>
|
149 |
|
|
if (comp16b_AbtB = '1') then --delta > step
|
150 |
|
|
diff <= diff + ("000" & Step(14 downto 2));
|
151 |
|
|
ADPCM_sample2(0) := '1';
|
152 |
|
|
else
|
153 |
|
|
ADPCM_sample2(0) := '0';
|
154 |
|
|
end if;
|
155 |
|
|
ADPCM_sample_rdy <= '1';
|
156 |
|
|
State <= State + 1;
|
157 |
|
|
|
158 |
|
|
when 18 =>
|
159 |
|
|
if (ADPCM_sample2(3) = '1') then --negative
|
160 |
|
|
AdderSub16 := PredictedValue - diff;
|
161 |
|
|
else
|
162 |
|
|
AdderSub16 := PredictedValue + diff;
|
163 |
|
|
end if;
|
164 |
|
|
|
165 |
|
|
--IMA_ADPCMIndexTable[8] = -1, -1, -1, -1, 2, 4, 6, 8,
|
166 |
|
|
case ADPCM_sample2(2 downto 0) is
|
167 |
|
|
when "111" => StepIndex <= StepIndex + "0001000";
|
168 |
|
|
when "110" => StepIndex <= StepIndex + "0000110";
|
169 |
|
|
when "101" => StepIndex <= StepIndex + "0000100";
|
170 |
|
|
when "100" => StepIndex <= StepIndex + "0000010";
|
171 |
|
|
when others => StepIndex <= StepIndex - "0000001";
|
172 |
|
|
end case;
|
173 |
|
|
State <= State + 1;
|
174 |
|
|
when 19 =>
|
175 |
|
|
if (StepIndex = "1111111") then
|
176 |
|
|
StepIndex <= (others => '0');
|
177 |
|
|
elsif (StepIndex > "1011000") then
|
178 |
|
|
StepIndex <= "1011000";
|
179 |
|
|
end if;
|
180 |
|
|
|
181 |
|
|
--diff is always positive, it becomes negative if we substract Pred - diff == Pred + (-diff)
|
182 |
|
|
--so the sign of diff is marked by ADPCM_sample2(3)
|
183 |
|
|
if (PredictedValue(15) = '0' and ADPCM_sample2(3) = '0' and AdderSub16(15) = '1') then --both positives result in negative?
|
184 |
|
|
PredictedValue <= '0' & (14 downto 0 => '1'); --positive overflow -> set biggest positive
|
185 |
|
|
elsif (PredictedValue(15) = '1' and ADPCM_sample2(3) = '1' and AdderSub16(15) = '0') then --both negatives result positive?
|
186 |
|
|
PredictedValue <= '1' & (14 downto 0 => '0'); --negative overflow -> set biggest negative
|
187 |
|
|
else --one positive, the other negative (overflow not possible)
|
188 |
|
|
PredictedValue <= AdderSub16(15 downto 0);
|
189 |
|
|
end if;
|
190 |
|
|
State <= 0; --go wait for new sample ready
|
191 |
|
|
|
192 |
|
|
when others =>
|
193 |
|
|
State <= 0;
|
194 |
|
|
end case;
|
195 |
|
|
ADPCM_sample <= ADPCM_sample2;
|
196 |
|
|
end if;
|
197 |
|
|
end process;
|
198 |
|
|
|
199 |
|
|
end Behavioral;
|
200 |
|
|
|