1 |
6 |
galland |
----------------------------------------------------------------------------------
|
2 |
|
|
-- Company: VISENGI S.L. (www.visengi.com)
|
3 |
|
|
-- Engineer: Victor Lopez Lorenzo (victor.lopez (at) visengi (dot) com)
|
4 |
|
|
--
|
5 |
|
|
-- Create Date: 19:34:36 04/November/2008
|
6 |
|
|
-- 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_unsigned.all;
|
33 |
|
|
USE ieee.std_logic_arith.all;
|
34 |
|
|
use ieee.numeric_std.all;
|
35 |
|
|
|
36 |
|
|
ENTITY tb_IMA_ADPCM_top_vhd IS
|
37 |
|
|
END tb_IMA_ADPCM_top_vhd;
|
38 |
|
|
|
39 |
|
|
ARCHITECTURE behavior OF tb_IMA_ADPCM_top_vhd IS
|
40 |
|
|
|
41 |
|
|
-- Component Declaration for the Unit Under Test (UUT)
|
42 |
|
|
COMPONENT IMA_ADPCM_top
|
43 |
|
|
PORT(
|
44 |
|
|
wb_clk_i : IN std_logic;
|
45 |
|
|
wb_rst_i : IN std_logic;
|
46 |
|
|
wb_cyc_i : IN std_logic;
|
47 |
|
|
wb_stb_i : IN std_logic;
|
48 |
|
|
wb_we_i : IN std_logic;
|
49 |
|
|
wb_adr_i : IN std_logic_vector(1 downto 0);
|
50 |
|
|
wb_dat_i : IN std_logic_vector(15 downto 0);
|
51 |
|
|
wb_dat_o : OUT std_logic_vector(15 downto 0);
|
52 |
|
|
wb_ack_o : OUT std_logic
|
53 |
|
|
);
|
54 |
|
|
END COMPONENT;
|
55 |
|
|
|
56 |
|
|
--Inputs
|
57 |
|
|
SIGNAL wb_clk_i : std_logic := '0';
|
58 |
|
|
SIGNAL wb_rst_i : std_logic := '0';
|
59 |
|
|
SIGNAL wb_cyc_i : std_logic := '0';
|
60 |
|
|
SIGNAL wb_stb_i : std_logic := '0';
|
61 |
|
|
SIGNAL wb_we_i : std_logic := '0';
|
62 |
|
|
SIGNAL wb_adr_i : std_logic_vector(1 downto 0) := (others=>'0');
|
63 |
|
|
SIGNAL wb_dat_i : std_logic_vector(15 downto 0) := (others=>'0');
|
64 |
|
|
|
65 |
|
|
--Outputs
|
66 |
|
|
SIGNAL wb_dat_o : std_logic_vector(15 downto 0);
|
67 |
|
|
SIGNAL wb_ack_o : std_logic;
|
68 |
|
|
|
69 |
|
|
|
70 |
|
|
type ByteFileType is file of character;
|
71 |
|
|
file infile : ByteFileType open read_mode is "input.wav";
|
72 |
|
|
file outfile : ByteFileType open write_mode is "output.wav";
|
73 |
|
|
|
74 |
|
|
signal bytes, bytesout : std_logic_vector(23 downto 0);
|
75 |
|
|
|
76 |
|
|
signal SamplesPerSec : std_logic_vector(15 downto 0);
|
77 |
|
|
signal SecondsToCompress : std_logic_vector(31 downto 0);
|
78 |
|
|
BEGIN
|
79 |
|
|
|
80 |
|
|
-- Instantiate the Unit Under Test (UUT)
|
81 |
|
|
uut: IMA_ADPCM_top PORT MAP(
|
82 |
|
|
wb_clk_i => wb_clk_i,
|
83 |
|
|
wb_rst_i => wb_rst_i,
|
84 |
|
|
wb_cyc_i => wb_cyc_i,
|
85 |
|
|
wb_stb_i => wb_stb_i,
|
86 |
|
|
wb_we_i => wb_we_i,
|
87 |
|
|
wb_adr_i => wb_adr_i,
|
88 |
|
|
wb_dat_i => wb_dat_i,
|
89 |
|
|
wb_dat_o => wb_dat_o,
|
90 |
|
|
wb_ack_o => wb_ack_o
|
91 |
|
|
);
|
92 |
|
|
|
93 |
|
|
wb_rst_i <= '1', '0' after 40 ns; --active high reset
|
94 |
|
|
|
95 |
|
|
Clocking : process --50 MHz -> T = 20 ns
|
96 |
|
|
begin
|
97 |
|
|
wb_clk_i <= '1'; wait for 20 ns;
|
98 |
|
|
wb_clk_i <= '0'; wait for 20 ns;
|
99 |
|
|
end process;
|
100 |
|
|
|
101 |
|
|
|
102 |
|
|
|
103 |
|
|
|
104 |
|
|
Control_Compressor : process (wb_clk_i, wb_rst_i)
|
105 |
|
|
variable byte : character;
|
106 |
|
|
variable WaitACK, EndSignaled : std_logic;
|
107 |
|
|
variable State : integer;
|
108 |
|
|
variable data : std_logic_vector(15 downto 0);
|
109 |
|
|
variable DataBytes : std_logic_vector(31 downto 0);
|
110 |
|
|
begin
|
111 |
|
|
if (wb_rst_i = '1') then
|
112 |
|
|
bytes <= (others => '0');
|
113 |
|
|
bytesout <= (others => '0');
|
114 |
|
|
State := 0;
|
115 |
|
|
WaitACK := '0';
|
116 |
|
|
EndSignaled := '0';
|
117 |
|
|
wb_cyc_i <= '0';
|
118 |
|
|
wb_stb_i <= '0';
|
119 |
|
|
wb_we_i <= '0';
|
120 |
|
|
wb_adr_i <= (others => '0');
|
121 |
|
|
wb_dat_i <= (others => '0');
|
122 |
|
|
data := (others => '0');
|
123 |
|
|
elsif (wb_clk_i = '1' and wb_clk_i'event) then
|
124 |
|
|
if (WaitACK = '1') then
|
125 |
|
|
if (wb_ack_o = '1') then
|
126 |
|
|
wb_cyc_i <= '0'; wb_stb_i <= '0'; wb_we_i <= '0';
|
127 |
|
|
data := wb_dat_o; WaitACK := '0';
|
128 |
|
|
end if;
|
129 |
|
|
end if;
|
130 |
|
|
|
131 |
|
|
if (WaitACK = '0') then
|
132 |
|
|
case State is
|
133 |
|
|
when 0 =>
|
134 |
|
|
--read the WAV header in search of SamplesPerSecond (bytes 19h and 18h in little endian)
|
135 |
|
|
--and DataBytes (bytes 39h,38h,37h,36h in little endian) to get SecondsToCompress as DataBytes/2/SamplesPerSecond
|
136 |
|
|
for i in 0 to 57 loop --PCM header has 58 bytes
|
137 |
|
|
read(infile, byte);
|
138 |
|
|
case i is
|
139 |
|
|
when 25 => --x"19" => --MSB of SamplesPerSecond
|
140 |
|
|
SamplesPerSec(15 downto 8) <= conv_std_logic_vector(character'pos(byte),8);
|
141 |
|
|
when 24 => --x"18" => --LSB of SamplesPerSecond
|
142 |
|
|
SamplesPerSec(7 downto 0) <= conv_std_logic_vector(character'pos(byte),8);
|
143 |
|
|
|
144 |
|
|
when 7 => --x"39" => --1stMSB of DataBytes
|
145 |
|
|
DataBytes(31 downto 24) := conv_std_logic_vector(character'pos(byte),8);
|
146 |
|
|
when 6 => --x"38" => --2ndMSB of DataBytes
|
147 |
|
|
DataBytes(23 downto 16) := conv_std_logic_vector(character'pos(byte),8);
|
148 |
|
|
when 5 => --x"37" => --3rdMSB of DataBytes
|
149 |
|
|
DataBytes(15 downto 8) := conv_std_logic_vector(character'pos(byte),8);
|
150 |
|
|
when 4 => --x"36" => --4thMSB of DataBytes
|
151 |
|
|
DataBytes(7 downto 0) := conv_std_logic_vector(character'pos(byte),8);
|
152 |
|
|
when others =>
|
153 |
|
|
null;
|
154 |
|
|
end case;
|
155 |
|
|
end loop;
|
156 |
|
|
EndSignaled := '0';
|
157 |
|
|
bytes <= (others => '0');
|
158 |
|
|
bytesout <= (others => '0');
|
159 |
|
|
DataBytes := DataBytes - x"32"; --with fmt18 and fact4 chunks
|
160 |
|
|
State := State + 1;
|
161 |
|
|
when 1 =>
|
162 |
|
|
SecondsToCompress <= conv_std_logic_vector((conv_integer(DataBytes)/conv_integer(SamplesPerSec))/2,32);
|
163 |
|
|
wb_adr_i <= "01"; wb_dat_i <= SamplesPerSec; wb_we_i <= '1'; WaitACK := '1';
|
164 |
|
|
State := State + 1;
|
165 |
|
|
when 2 =>
|
166 |
|
|
wb_adr_i <= "10"; wb_dat_i <= SecondsToCompress(15 downto 0); wb_we_i <= '1'; WaitACK := '1';
|
167 |
|
|
State := State + 1;
|
168 |
|
|
when 3 =>
|
169 |
|
|
wb_adr_i <= "00"; wb_dat_i <= x"8000"; wb_we_i <= '1'; WaitACK := '1';
|
170 |
|
|
State := State + 1;
|
171 |
|
|
when 4 =>
|
172 |
|
|
wb_adr_i <= "00"; wb_we_i <= '0'; WaitACK := '1'; State := State + 1;
|
173 |
|
|
when 5 =>
|
174 |
|
|
if (data(15) = '0') then --compression end
|
175 |
|
|
File_Close(infile); --finished
|
176 |
|
|
report "Input bytes = " & integer'image(conv_integer(bytes)) & " at time " & time'image(now);
|
177 |
|
|
report "Output bytes = " & integer'image(conv_integer(bytesout)) & " at time " & time'image(now);
|
178 |
|
|
File_Close(outfile); --finished
|
179 |
|
|
report "-----------> Compression Finished OK!" severity FAILURE; --everything went fine, it's just to stop the simulation
|
180 |
|
|
else
|
181 |
|
|
if (data(0) = '1') then --output word ready
|
182 |
|
|
wb_adr_i <= "11"; wb_we_i <= '0'; WaitACK := '1';
|
183 |
|
|
State := 15; --write word
|
184 |
|
|
elsif (data(1) = '1' and EndSignaled = '0') then --ready for new input sample AND haven't reached the input file's EOF?
|
185 |
|
|
if (bytes < DataBytes(23 downto 0) and not endfile(infile)) then
|
186 |
|
|
--send two bytes to the WAV compressor
|
187 |
|
|
read(infile,byte); --1st byte ----> goes in LSBs!!! (little endian)
|
188 |
|
|
wb_dat_i(7 downto 0) <= conv_std_logic_vector(character'pos(byte),8);
|
189 |
|
|
read(infile,byte); --2nd byte
|
190 |
|
|
wb_dat_i(15 downto 8) <= conv_std_logic_vector(character'pos(byte),8);
|
191 |
|
|
bytes <= bytes + x"2";
|
192 |
|
|
wb_adr_i <= "11"; wb_we_i <= '1'; WaitACK := '1'; State := State - 1;
|
193 |
|
|
else --already sent the number of bytes indicated in PCM WAV header
|
194 |
|
|
wb_adr_i <= "00"; wb_dat_i <= x"0000"; wb_we_i <= '1'; WaitACK := '1'; --signal finish compression
|
195 |
|
|
EndSignaled := '1'; State := State - 1; --there will be still bytes to write but don't get in here again (EndSignaled='1')
|
196 |
|
|
end if;
|
197 |
|
|
else
|
198 |
|
|
wb_adr_i <= "00"; wb_we_i <= '0'; WaitACK := '1'; --read again and stay in this state
|
199 |
|
|
end if;
|
200 |
|
|
end if;
|
201 |
|
|
|
202 |
|
|
|
203 |
|
|
when 15 => --write word
|
204 |
|
|
write(outfile, character'val(conv_integer(data(15 downto 8))));
|
205 |
|
|
write(outfile, character'val(conv_integer(data(7 downto 0))));
|
206 |
|
|
bytesout <= bytesout + x"2";
|
207 |
|
|
wb_adr_i <= "00"; wb_we_i <= '0'; WaitACK := '1'; State := 5; --go back and continue
|
208 |
|
|
|
209 |
|
|
when others =>
|
210 |
|
|
State := 0;
|
211 |
|
|
end case;
|
212 |
|
|
end if;
|
213 |
|
|
if (WaitACK = '1') then wb_cyc_i <= '1'; wb_stb_i <= '1'; end if;
|
214 |
|
|
end if;
|
215 |
|
|
end process Control_Compressor;
|
216 |
|
|
|
217 |
|
|
END;
|