📄 quant.v
字号:
/**********************************************************************
** -----------------------------------------------------------------------------**
** 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 + -