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