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

📄 iquant_v.v

📁 IDCT - xlinix design in vhdl
💻 V
📖 第 1 页 / 共 3 页
字号:

/**********************************************************************
** -----------------------------------------------------------------------------**
** iquant.v
**
** Quantization
**
**
**
**                  Author: Latha Pillai
**                  Senior Applications Engineer
**
**                  Video Applications
**                  Advanced Products Group
**                  Xilinx, Inc.
**
**                  Copyright (c) 2001 Xilinx, Inc.
**                  All rights reserved
**
**                  Date:   April. 10, 2002
**
**                  RESTRICTED RIGHTS LEGEND
**
**      This software has not been published by the author, and 
**      has been disclosed to others for the purpose of enhancing 
**      and promoting design productivity in Xilinx products.
**
**      Therefore use, duplication or disclosure, now and in the 
**      future should give consideration to the productivity 
**      enhancements afforded the user of this code by the author's 
**      efforts.  Thank you for using our products !
**
** Disclaimer:  THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY 
**              WHATSOEVER AND XILINX SPECIFICALLY DISCLAIMS ANY 
**              IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
**              A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
** Module: quant : 

** The 2D_DCT output is taken through the quantizer where each of the DCT 
** coefficient is quantized by dividing by the corresponding element in the 
** quantizer matrix. Quantization is done to zero out those DCT coefficients 
** that correspond to the higher frequency components.

 The default Q-matrices are as follows:
                     

       Intra quantizer matrix          Non-intra quantizer matrix

The Q_matrix is stored in a RAM. The "rdy_in" input signal goes active when the first Quant output is available. The inverse quantization starts when rdy_in goes high and as long as it is high. An internal 64-count clock is used to loop through the 64 elements in the Q_matrix. The two default Q matrices (one for luma and one for chroma) are stored in memory. Additional two memories are provided to store user specified Q matrices in case that is used. 

The quant_scale_code is 5 bits wide and is used to select the quantiser scale. quant_scale_code value can range from 1 to 31 . The inverse of the quant_scale_code is calculated and stored in q_scale_mem. The value is assigned 16 bits to minimize round off error. The 1 bit q_scale type is used to choose between two sets of q_scale_mems. q_scale_type is used to choose between the 2 quantizer_scale values. q_scale_type = 0 is used for MPEG1 and q_scale_type = 1 is used for MPEG2. Quantiser scale value for each quantiser scale code is found in the MPEG ISO/IEC document. 

The Q matrix has 64, 8-bit values. The 256 possible Q matrix entries are stored in q_value_mem. The default q_values  are stored in a FIFO (q_value_def). Upon receving a new user defined Q matrix, the new 64 values are read in , one value per clock and stored in memory, q_value_new. These values are then used to access the q_value_mem, which in turn outputs new values into the q_value_fifo. The fifo retains one set of values as long as the load_new_q_value is inactive. This signal, load_new_q_value is active for 64 clocks after it sees a high on load_intra_qmatrix or load_non_intra_qmatrix. The macroblock-type input signal is used to choose either the intro or non-intra Q_matrix depending on the type of frame.

Quantization in MPEG2 is given by the following equation




**********************************************************************/
//scale factor --- how many bits ?
`timescale 1ns/1ps

module iquant ( CLK, RST, quant_dct_in, rdy_in, macroblock_type, quant_scale_type, quant_scale_code,
          q_value, load_intra_qmatrix, load_non_intra_qmatrix,q_out,iquant_rdy_out);

		 // output[27:0] prod2;
output [11:0] q_out;            /* quantised output value */
output iquant_rdy_out;
input CLK, RST;
input[11:0] quant_dct_in;                /* 12 bit output from DCT block */
input rdy_in;                   /* ready signal , starts quantization process                      
                                   after DCT is done for the block */ 
input macroblock_type;          /* used to choose b/n intra(0) & non-intra(1) 
                                   blocks */
input[4:0] quant_scale_code; 
input quant_scale_type;         /* q_scale_code and q_scale_type are used 
                                   together to choose the quantiser_scale value 
                                   as given in MPEG2 standard */
input load_intra_qmatrix, load_non_intra_qmatrix;
input[7:0] q_value; //intraq, non_intraq ;/* user defined input Q matrix values */

/* signals */
reg[4:0]    quant_scale_code_reg1 ,quant_scale_code_reg2;
reg    quant_scale_type_reg1, quant_scale_type_reg2;     
reg    load_intra_qmatrix_reg1,load_non_intra_qmatrix_reg1;
reg    load_intra_qmatrix_reg2,load_non_intra_qmatrix_reg2;
reg    load_intra_qmatrix_reg3,load_non_intra_qmatrix_reg3;
reg    load_intra_qmatrix_reg4,load_non_intra_qmatrix_reg4;

reg macroblock_type_reg1,macroblock_type_reg2,macroblock_type_reg3;
reg[6:0] cnt64, cnt64c, cnt64b;
reg cnt_start;
reg[3:0] cnt12;
//reg[11:0] qdct_in_reg;
reg[11:0] qdct_out;
reg[11:0] qdct_out_reg;
reg qdct_out_mag2, qdct_out_mag3, qdct_out_mag4, qdct_out_mag5,
    qdct_out_mag6, qdct_out_mag7;
reg[12:0] quant_shift,quant_shift_reg1,quant_shift_reg2;
reg[9:0]  qscale_reg;
reg[9:0] q_scale_mem /* synthesis syn_romstyle = "select_rom" */;
//reg[7:0] q_value_new_intra, q_value_new_non_intra,q_value_new_out;
wire[6:0] qscale_mem_sel;
reg[7:0] q_value_new_out;
reg[7:0] q_value_new_intra[64:0],q_value_new_non_intra[64:0]; 
reg[11:0] qdct_in_reg;
reg[14:0] prod1,prod1_reg;
reg[21:0] prod2_rnd; 
reg[26:0] prod2;
reg[21:0] prod2_sign,prod2_sign_reg;
reg[11:0] prod_sat, prod_sat_reg, prod_mismatch;
reg[7:0] def_q_mem /* synthesis syn_romstyle = "select_rom" */;
reg[7:0] def_q_mem_reg, def_q_mem_reg1;
wire[8:0] def_qmem_sel;
reg quant_sum;
reg qdct_out_comp;
reg[11:0] q_out;
integer Q_cnt64;
wire[2:0] case_wire;
reg prod2_rnd_pos, prod2_rnd_neg;
reg iquant_rdy_out;

/*****************************************************************************/

/* counter to count up to 64. This counter is used to read in the 64
dct input values and the 64 values for the user defined Q matrix*/

always @ (posedge CLK or posedge RST)
   begin
   if (RST)
       begin
       cnt64 <= 7'b1000000;
       end
   else if (rdy_in == 1'b1 && cnt64 < 7'b1000000)
       begin
       cnt64 <= cnt64 + 1;
       end
   else if (rdy_in == 1'b1)
       begin
       cnt64 <= 7'b0000001;
       end
   end

/* first active quant sum output occurs when cnt64 = 10. So quant sum
should be added for 64 clks after every cnt64 = 10*/

 always @ (posedge CLK or posedge RST)
   begin
   if (RST)
       begin
       cnt64b <= 7'b0111111; 
       end
   else if (rdy_in == 1'b1)
      begin
        if (cnt64b < 7'b1000000)
            begin
            cnt64b <= cnt64b + 1;
            end
        else 
            begin
            cnt64b <= 7'b0000001;
            end

      end
   end 

always @ (posedge CLK or posedge RST)
   begin
   if (RST)
       begin
       cnt64c <= 7'b0111111; 
       end
   else if (rdy_in == 1'b1)
      begin
        if (cnt64c < 7'b1000000)
            begin
            cnt64c <= cnt64c + 1;
            end
        else 
            begin
            cnt64c <= 7'b0000001;
            end

      end
   end 


/*****************************************************************************/

always @ (posedge CLK or posedge RST)
   begin
   if (RST)
       begin
       cnt_start <= 1'b0; 
       end
   else if (rdy_in == 1'b1 && cnt64 == 7'd64)
       begin
       cnt_start <= 1'b1;
       end       
   else 
       begin   
       cnt_start <= cnt_start;
       end
   end


always @ (posedge CLK or posedge RST)
   begin
   if (RST)
       begin
       macroblock_type_reg1 <= 1'b0;
       quant_scale_code_reg1 <= 5'b00000; 
       quant_scale_type_reg1 <= 1'b0;     
       load_intra_qmatrix_reg1 <= 1'b0; 
       load_non_intra_qmatrix_reg1 <= 1'b0;
       end
   else if (rdy_in == 1'b1 && cnt64 == 7'b1000000)
       fork
       macroblock_type_reg1 <= macroblock_type;
       quant_scale_code_reg1 <= quant_scale_code; 
       quant_scale_type_reg1 <= quant_scale_type;     
       load_intra_qmatrix_reg1 <= load_intra_qmatrix; 
       load_non_intra_qmatrix_reg1 <= load_non_intra_qmatrix;
       join
   else 
       begin
       end
   end

always @ (posedge CLK or posedge RST)
   begin
   if (RST)
       begin
       quant_scale_code_reg2 <= 5'b00000; 
       quant_scale_type_reg2 <= 1'b0;    
       load_intra_qmatrix_reg2 <= 1'b0; 
       load_non_intra_qmatrix_reg2 <= 1'b0;
       load_intra_qmatrix_reg3 <= 1'b0; 
       load_non_intra_qmatrix_reg3 <= 1'b0;
       load_intra_qmatrix_reg4 <= 1'b0; 
       load_non_intra_qmatrix_reg4 <= 1'b0;
       end
   else if (rdy_in == 1'b1)
       fork
       quant_scale_code_reg2 <= quant_scale_code_reg1; 
       quant_scale_type_reg2 <= quant_scale_type_reg1;  
       load_intra_qmatrix_reg2 <= load_intra_qmatrix_reg1; 
       load_non_intra_qmatrix_reg2 <= load_non_intra_qmatrix_reg1;
       load_intra_qmatrix_reg3 <= load_intra_qmatrix_reg2; 
       load_non_intra_qmatrix_reg3 <= load_non_intra_qmatrix_reg2;
       load_intra_qmatrix_reg4 <= load_intra_qmatrix_reg3; 
       load_non_intra_qmatrix_reg4 <= load_non_intra_qmatrix_reg3;
       join
   else 
       begin
       end
   end


/*always @ (posedge CLK or posedge RST)
   begin
   if (RST)
       begin
       load_intra_qmatrix_reg2 <= 1'b0; 
       load_non_intra_qmatrix_reg2 <= 1'b0;
       load_intra_qmatrix_reg3 <= 1'b0; 
       load_non_intra_qmatrix_reg3 <= 1'b0;
       end
   else if (rdy_in == 1'b1)
       begin
       load_intra_qmatrix_reg2 <= load_intra_qmatrix_reg1; 
       load_non_intra_qmatrix_reg2 <= load_non_intra_qmatrix_reg1;
       load_intra_qmatrix_reg3 <= load_intra_qmatrix_reg2; 
       load_non_intra_qmatrix_reg3 <= load_non_intra_qmatrix_reg2;
       end
   end*/


/* store quant_scale_code/32 in q_scale_mem1 and q_scale_mem2. Q_scale_type is used to 
choose between the 2 memories. For scale type 0, the min. value is 2/32 and max
value = 62/32. For scale type 1, the min value = 1/32 and max value = 112/32. : pipe1 */

assign qscale_mem_sel = {cnt_start,quant_scale_type_reg2,quant_scale_code_reg2};
always @ (posedge CLK)
   //begin
   //if (RST)
   //    begin
   //    q_scale_mem <= 10'd0; 
   //    end
   //else if (cnt_start == 1'b1 && quant_scale_type_reg1 == 1'b0) 
       begin
	   case (qscale_mem_sel)
        7'b1000001 : begin q_scale_mem <= 10'b0000010000; end     
        7'b1000010 : begin q_scale_mem <= 10'b0000100000; end 
        7'b1000011 : begin q_scale_mem <= 10'b0000110000; end     
        7'b1000100 : begin q_scale_mem <= 10'b0001000000; end 
        7'b1000101 : begin q_scale_mem <= 10'b0001010000; end     
        7'b1000110 : begin q_scale_mem <= 10'b0001100000; end 
        7'b1000111 : begin q_scale_mem <= 10'b0001110000; end    
        7'b1001000 : begin q_scale_mem <= 10'b0010000000; end 
        7'b1001001 : begin q_scale_mem <= 10'b0010010000; end    
        7'b1001010 : begin q_scale_mem <= 10'b0010100000; end 
        7'b1001011 : begin q_scale_mem <= 10'b0010110000; end    

⌨️ 快捷键说明

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