⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ima_adpcm_top.vhd

📁 This project features a full-hardware sound compressor using the well known algorithm: IMA ADPCM.
💻 VHD
📖 第 1 页 / 共 2 页
字号:
         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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -