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

📄 compressor.vhd

📁 JPEG标准下图象压缩的vhdl实现工程
💻 VHD
📖 第 1 页 / 共 5 页
字号:
                        DatoHeader := 0;
                     else
                        DatoHeader := DatoHeader + 1;
                     end if;   
               end case;
               CompressingInt <= '1';
               if ColumnToCompress = "0000000000" then --we've changed line, careful
                  --because we have to process the last block of the previous line
                  Linea := (not LineToCompress(3)) & "000";
                  Columna := ImgColumns(9 downto 3) & "000";
               else
                  Linea := LineToCompress(3) & "000";
                  Columna := (ColumnToCompress(9 downto 3) - 1) & "000";
               end if;
               Bloque := ColumnToCompress(1 downto 0);
               StepV <= 0;
               weY2 <= '0';
               weCb2 <= '0';
               weCr2 <= '0';
               Coeficiente := 0;
               Save <= '0';
               IniDC := '1';           
               GetPrevDC := '1';
               WriteAdditionalBits <= '0';
            else
            
            we <= '0';
            LumaBlock := Bloque(1) nor Bloque(0); --it is 1 if we are dealing with luminance component
            --It is necessary that Base be here so that it changes when Bloque changes in the "if" of Done in the last image's block
            if Bloque = "00" then --Q Coefficients of Table 0 (luminance)
               BaseH := (others => '0'); --address 0 of Huffman Luminance Table
               case Compression is
                  when "00" => --Low Quality
                     Base := "100000000";
                  when "01" => --Medium Quality
                     Base := "010000000";
                  when others => --10 High Quality
                     Base := "000000000";
               end case;
            else --Q Coefficients of Table 1 (chroma)
               BaseH := "010110000"; --address 0 of Huffman Chrominance Table
               case Compression is
                  when "00" => --Low Quality
                     Base := "101000000";
                  when "01" => --Medium Quality
                     Base := "011000000";
                  when others => --10 High Quality
                     Base := "001000000";
               end case;               
            end if;   
            
            case StepV is
               when 0 => --with the first data to let addrXX2 load and have the data in memory
                  weY2 <= '0';
                  weCb2 <= '0';
                  weCr2 <= '0';
                  if CompressingInt = '1' and Done = '0' then --Done=0 cause in case it is a Y block (but not the fourth (the last)) coming from StepV=3
                     StepV <= 1;
                  else
                     StepV <= 0;
                  end if;   
                  NDe <= '0';
                  RFDInt <= '0';
               when 1 => --Feeding of DCT1 with 64 pixels
                  if RFD = '1' then --DCT1 ready for data (RFD)
                     NDe <= '1';
                     ND <= NDe; --this way we delay ND one cycle to synchronize data
                     if RFDInt = '0' then
                        case Bloque is
                           when "00" => --block Y
                              DIND <= doutY(7 downto 0); 
                           when "01" => --block Cb
                              DIND <= doutCb(7 downto 0); 
                           when others => --can only be block Cr
                              DIND <= doutCr(7 downto 0); 
                        end case;
                     else
                        DIND <= RFDIntData; --to recover the "lost" cycle because RFD was 0 (if the DCT was such that RFD were 0 for more than a cycle it would be necessary to change this part)
                        RFDInt <= '0';
                     end if;   
                     if Columna(2 downto 0) = "111" then
                        Columna := Columna(9 downto 3) & "000";
                        Linea := Linea + 1;
                        if Linea(2 downto 0) = "000" then --we've finished this StepV, now we'll wait for the results
                           StepV <= 2; --we shall go to StepV 2 with the first column of the block
                           Linea(3) := not Linea(3); --makes it rest in current block
                           Primera := '1'; --to not let StepV 2 change Linea or Column in its 1st cycle because they already have adequate values
                        end if;   
                     else
                        Columna := Columna + 1;
                     end if;   
                  else
                     --to not lose the just read pixel (rememer that reads are ahead of their time!!)
                     RFDInt <= '1';
                     case Bloque is
                        when "00" => --block Y
                           RFDIntData <= doutY(7 downto 0); 
                        when "01" => --block Cb
                           RFDIntData <= doutCb(7 downto 0); 
                        when others => --can only be block Cr
                           RFDIntData <= doutCr(7 downto 0); 
                     end case;
                     --ND <= '0';
                  end if;
                  weY2 <= '0';
                  weCb2 <= '0';
                  weCr2 <= '0';
                  addrQ <= Base; --DC Coefficient's Q (Base + Linea*8 + Columna)
                  QDC := (others => '0');
               when 2 => --we receive the data, quantize it, truncate it and save them back to the buffer
                  --watch out because DCT1 outputs data column-wise (feeding was row-wise)
                  NDe <= '0'; --it stayed high while sending data byte
                  ND <= NDe;
                  case Bloque is  --needed to send the last data of the block (it is alright!!!)
                     when "00" => --block Y
                        DIND <= doutY(7 downto 0); 
                     when "01" => --block Cb
                        DIND <= doutCb(7 downto 0); 
                     when others => --can only be block Cr
                        DIND <= doutCr(7 downto 0); 
                  end case;                  
                  
                  if RDY = '1' then --output data ready!!
                     if QDC /= 0 then
                        DCTQ := MultiplierQ(DOUTD(14 downto 3), QDC);
                        QDC := (others => '0');
                     else        
                        DCTQ := MultiplierQ(DOUTD(14 downto 3), DOUTQ); --multiply the DCT coefficient times Qyx fraction's numerator
                     end if;
                     --if DCTQ(24) = '0' then --it is positive, let's round
                        DCTQ(24 downto 14) := DCTQ(24 downto 14) + DCTQ(13); --round to nearest integer
                     --end if;   
                     --if DCTQ(24 downto 13) = "111111111111" then --it is less or equal than -0.5, roung to 0
                     --   DCTQ(24 downto 13) := "000000000000"; --or else it will be read as -1
                     --end if;
                     case Bloque is --the "+ DCTQ(13)" is the nearest integer round!
                        when "00" => --block Y
                           dinY2 <= DCTQ(24) & DCTQ(24 downto 14);-- + DCTQ(13); --we divide (shifting right) by the general Q coefficient denominator (16384) and save the quantized coefficient
                           --sign-extension
                           weY2 <= '1';
                        when "01" => --block Cb
                           dinCb2 <= DCTQ(24) & DCTQ(24 downto 14);-- + DCTQ(13); --we divide (shifting right) by the general Q coefficient denominator (16384) and save the quantized coefficient
                           weCb2 <= '1';
                        when others => --can only be block Cr
                           dinCr2 <= DCTQ(24) & DCTQ(24 downto 14);-- + DCTQ(13); --we divide (shifting right) by the general Q coefficient denominator (16384) and save the quantized coefficient
                           weCr2 <= '1';
                     end case;                     
                     
                     --write column-wise
                     if Linea(2 downto 0) = "111" and Primera = '0' then --have we reached this line's end?
                        --Primera is used for the first cycle of StepV2 in which Columna and Linea arrive with the right value
                        --so they need not be changed in order to get the correct address
                        Linea := Linea(3) & "000";
                        Columna := Columna + 1;
                     else
                        if Primera = '1' then
                           Primera := '0';
                        else   
                           Linea := Linea + 1;
                           if Linea(2 downto 0) = "111" and Columna(2 downto 0) = "111" then --we have finished this StepV, now we must Huffman encode 
                              StepV <= 3;
                           end if;   
                        end if;   
                     end if;
                     
                     --the following code is because we must load one cycle early the addrQ so that in the
                     --current cycle we can have the right Q coefficient for current Linea and Columna values
                     if Linea(2 downto 0) = "110" then --have we reached the end?
                        --next coeff. is Linea 0 of the Coeff. Table and Columna is current plus one
                        addrQ <= Base + Columna(2 downto 0) + 2; --Base + Linea*8 + Columna --> remember coefficient table is 8x8
                     else
                        --next coeff is next Linea of the Coeff. Table and current Columna
                        addrQ <= Base + ((Linea(2 downto 0) + 2) & "000") + Columna(2 downto 0); --Base + Linea*8 + Columna
                     end if;
                     
                  else
                     --during Latency cycles we will be here waiting until RDY is 1
                     --and also every X cycles when RDY becomes 0 for one cycle
                     if QDC = 0 and addrQ = Base then --only happens when we enter this StepV from the previous one
                        QDC := DOUTQ; --save the DC value because Q reading must be ahead by two cycles now
                        addrQ <= Base + "1000"; --Base + Linea*8 + Columna (Linea=1, Columna=0)
                     end if;   
                     weY2 <= '0';
                     weCr2 <= '0';
                     weCb2 <= '0';
                  end if;   
               when 3 =>
                  weY2 <= '0';
                  weCr2 <= '0';
                  weCb2 <= '0';
                  --Make the "pointers" Linea and Columna point to the beginning of the next block
                  --must do it here because in the last cycle of StepV2, when StepV becomes 3, Linea and Columna
                  --must maintain their value
                  Linea := Linea(3) & "000";
                  Columna := Columna + 1;
                  if LumaBlock = '1' then --if we are processing the luminance block we can only save it when we have processed the 4 ones
                     --that compose the 2x2 block of subsampling, there is no problem with the order of the chroma ones because these ones too
                     --are saved when we have averaged four and that is controlled by the process RGB2YCbCr
                     if Linea(3) = '1' and Columna(3) = '0' then --checked, it is alright (remember it points to the next block)
                        StepV <= 4;
                        Elemento := "00"; --process the first square (8x8 block) of the 2x2 luminance block (16x16 pixels, 2x2 squares)
                        --Ready Linea and Columna to read element 00 that Huffman will receive
                        Linea := (others => '0');
                        Columna := (Columna(9 downto 4) - 1) & "0000";
                     else --the three first squares of the 2x2 luminance block are not sent to Huffman yet (subsampling requirements)
                        StepV <= 0;
                        Done <= '1';
                     end if;
                  else
                     Columna := Columna - 1;
                     Columna := Columna(9 downto 3) & "000"; --it is alright, because Columna arrives already adjusted to Cb and Cr.
                     StepV <= 4;
                  end if;
                  WriteAdditionalBits <= '0';
               when 4 => --with this dummy cycle we give time to the memory to give us address 0
                  --for the DC coefficient
                  weY2 <= '0';
                  weCr2 <= '0';
                  weCb2 <= '0';
                  Save <= '0'; --just in case we left it high in last step
                  we <= '0';
                  StepV <= 5;  
               when 5 => --Linea and Columna point to the beginning of the block

                  --If we change Linea and/or Columna in cycle 0 of this section, then the new address will
                  --be sent to memory in cycle 1 and in cycle 2 doutX will have the asked data, so careful!!
                  case Bloque is
                     when "00" => --block Y
                        Coef := doutY; 
                     when "01" => --block Cb
                        Coef := doutCb; 
                     when others => --can only be block Cr
                        Coef := doutCr; 
                  end case;

                  
                  we <= '0';   
                  if Done = '0' then --this way it does not go to look for the DC when we change Block (upsetting FirstDC)
                  if Save = '0' then
                     if WriteAdditionalBits = '0' then
                        if Coeficiente = 0 then 
                           --The previous component is read from the buffer varying Linea and Columna
                           if IniDC = '1' then --we've not yet obtained the previous DC to calculate the difference
                              if Linea = "0000" and Columna = "000000000" and FirstDC = '1' and GetPrevDC = '1' then --must do it this way
                                 --or else the luminance, which has 4 blocks in its first Huffmanear takes DC=0 for all
                                 --GetPrevDC = 1 is so that execution doesnt get here if in the previous cycle GetPrevDC became zero in the bottom "if"
                                 --and put Linea and Columna to zero
                                 --we are in the first block of the image, PrevDC is zero
                                 if Bloque = "10" then --if we are in the last, we zero it
                                    FirstDC := '0'; --because it has already been used by the three components (Y,Cb,Cr)
                                 end if;
                                 PrevDC := (others => '0');
                                 IniDC := '0';
                              else
                                 if GetPrevDC = '1' then
                                    ColBk := Columna; --save the values of Linea and Columna
                                    LinBk := Linea;
                                    
                                    --Must obtain the quantized DC coefficient of the last processed block
                                    --as stated by specification, but actually the last block is indicated by MCU
                                    if Columna(9 downto 3) = "0000000" then --first block of the row?
                                       if LumaBlock = '1' then
                                          if Elemento = "00" then
                          

⌨️ 快捷键说明

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