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

📄 quant.v

📁 用于FPGA的量化算法的HDL编码
💻 V
📖 第 1 页 / 共 4 页
字号:

/**********************************************************************
** -----------------------------------------------------------------------------**
** quant.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 DCT output is 
available. The 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 inverse of the 256 possible Q matrix entries are stored in 
q_value_mem. The default q_values (in zig-zag order) are stored in a FIFO (q_value_fifo). Upon receving 
a new user defined Q matrix, the new 64 values are read in , one value per clock. 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 quant ( CLK, RST, dct_in, rdy_in, macroblock_type, quant_scale_type, quant_scale_code, 
q_value, load_intra_qmatrix, load_non_intra_qmatrix, quant_rdy_out, quant_dct_out);

output [11:0] quant_dct_out;     /* quantised output value */
output quant_rdy_out;
input CLK, RST;
input[11:0] dct_in;               /* 11 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[7:0] q_value;              /* user defined Q matrix value */
input load_intra_qmatrix, load_non_intra_qmatrix;

/* signals */

reg    macroblock_type_reg1 ,quant_scale_type_reg1, 
       quant_scale_type_reg2;
reg    load_intra_qmatrix_reg1,load_non_intra_qmatrix_reg1,
       load_intra_qmatrix_reg2,load_non_intra_qmatrix_reg2,
       load_intra_qmatrix_reg3,load_non_intra_qmatrix_reg3,
       load_intra_qmatrix_reg4,load_non_intra_qmatrix_reg4;
reg[4:0] quant_scale_code_reg1, quant_scale_code_reg2 ;
wire[6:0] qscale_mem_sel;
reg[11:0] quant_dct_out;
reg quant_rdy_out;
reg[6:0] cnt64, cnt64b, cnt64c;
wire[8:0] def_qmem_sel;
reg[3:0] cnt6;
reg[10:0] memoryQ ;
//reg[11:0] dct_in1;
//reg[11:0] dct_in_reg[63:0];
//reg[10:0] dct_out,dct_in_reg1,dct_in_reg2,dct_in_reg_mag;
reg[11:0] dct_in_pipe1;
reg[10:0] dct_in_pipe2,dct_in_pipe3,dct_in_pipe4,
          dct_in_pipe5,dct_in_pipe6,dct_in_pipe7;
reg dct_in_pipe2_sign,dct_in_pipe3_sign,dct_in_pipe4_sign,
    dct_in_pipe5_sign,dct_in_pipe6_sign,dct_in_pipe7_sign,
    dct_in_pipe8_sign,dct_in_pipe9_sign;
reg macroblock_type_pipe1,macroblock_type_pipe2,macroblock_type_pipe3,
    macroblock_type_pipe4,macroblock_type_pipe5,macroblock_type_pipe6,
    macroblock_type_pipe7,macroblock_type_pipe8 ;
//reg[16:0] dct_out_reg3;
//reg dct_in_reg_sign1, dct_in_reg_sign;
//reg[31:0] prod1;
//reg[16:0] dct_out_reg4; 
//reg[1:0] dct_in_mag;
reg[12:0] q_scale_mem, qscale_reg1, qscale_reg2;
reg[7:0] def_q_mem, def_q_mem_reg1, def_q_mem_reg2, def_q_mem_reg3;
//reg[7:0] q_value_mem;
reg[7:0] q_value_new_out, q_value_new_out_reg1;
reg[7:0] q_value_new_intra[64:0], q_value_new_non_intra[64:0];
reg[23:0] prod1;
reg[23:0] prod1_reg;
reg[34:0] prod2;
wire[16:0] prod2_round; 
reg[18:0] prod2_k;
//reg[12:0] prod2_sign;
reg [8:0] q_value_select;
reg cnt_start;

/*****************************************************************************/
/* COUNTER CODE */
/*****************************************************************************/

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


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 cnt6 <= 4'b0; end
   else if (rdy_in == 1'b1)
       begin
       if (cnt6 < 4'b1000)
           begin cnt6 <= cnt6 + 1; end
       else 
           begin cnt6 <= 4'b1000; 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

/*****************************************************************************/
/*PIPELINING INPUT SIGNALS */
/*****************************************************************************/

/* register inputs for 64 clks. This is done to make sure that all the 64 
   DCT coefficients see the same qscaletype, qscale_code,macroblock type,
   load intra matrix, load non intra matrix: pipe stages = 1 */

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
       macroblock_type_pipe1 <= 1'b0;macroblock_type_pipe2 <= 1'b0;
       macroblock_type_pipe3 <= 1'b0;macroblock_type_pipe4 <= 1'b0;
       macroblock_type_pipe5 <= 1'b0;

⌨️ 快捷键说明

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