📄 iquant_vhd.vhd
字号:
--*********************************************************************
-- *********************************************************************
-- ** -----------------------------------------------------------------------------**
-- ** 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
-- *********************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
ENTITY iquant IS
PORT (
CLK : IN std_logic;
RST : IN std_logic;
quant_dct_in : IN std_logic_vector(11 DOWNTO 0); -- 12 bit output from DCT block
rdy_in : IN std_logic; -- ready signal , starts quantization process
-- ready signal , starts quantization process
-- after DCT is done for the block
macroblock_type : IN std_logic;
quant_scale_type : IN std_logic; -- used to choose b/n intra(0) & non-intra(1)
-- used to choose b/n intra(0) & non-intra(1)
-- blocks
quant_scale_code : IN std_logic_vector(4 DOWNTO 0);
q_value : IN std_logic_vector(7 DOWNTO 0);
-- intraq, non_intraq ;/* user defined input Q matrix values */
-- q_scale_code and q_scale_type are used
-- q_scale_code and q_scale_type are used
-- together to choose the quantiser_scale value
-- as given in MPEG2 standard
load_intra_qmatrix : IN std_logic;
load_non_intra_qmatrix : IN std_logic;
q_out : OUT std_logic_vector(11 DOWNTO 0); -- quantised output value
iquant_rdy_out : OUT std_logic);
END iquant;
ARCHITECTURE translated OF iquant IS
TYPE ram_mem1 IS ARRAY (64 DOWNTO 1) OF std_logic_vector(7 DOWNTO 0);
TYPE ram_mem2 IS ARRAY (64 DOWNTO 1) OF std_logic_vector(7 DOWNTO 0);
-- signals
SIGNAL quant_scale_code_reg1 : std_logic_vector(4 DOWNTO 0);
SIGNAL quant_scale_code_reg2 : std_logic_vector(4 DOWNTO 0);
SIGNAL quant_scale_type_reg1 : std_logic;
SIGNAL quant_scale_type_reg2 : std_logic;
SIGNAL load_intra_qmatrix_reg1 : std_logic;
SIGNAL load_non_intra_qmatrix_reg1 : std_logic;
SIGNAL load_intra_qmatrix_reg2 : std_logic;
SIGNAL load_non_intra_qmatrix_reg2 : std_logic;
SIGNAL load_intra_qmatrix_reg3 : std_logic;
SIGNAL load_non_intra_qmatrix_reg3 : std_logic;
SIGNAL load_intra_qmatrix_reg4 : std_logic;
SIGNAL load_non_intra_qmatrix_reg4 : std_logic;
SIGNAL macroblock_type_reg1 : std_logic;
SIGNAL macroblock_type_reg2 : std_logic;
SIGNAL macroblock_type_reg3 : std_logic;
SIGNAL cnt64 : std_logic_vector(6 DOWNTO 0);
SIGNAL cnt64c : std_logic_vector(6 DOWNTO 0);
SIGNAL cnt64b : std_logic_vector(6 DOWNTO 0);
SIGNAL cnt_start : std_logic;
SIGNAL cnt12 : std_logic_vector(3 DOWNTO 0);
--reg[11:0] qdct_in_reg;
SIGNAL qdct_out : std_logic_vector(11 DOWNTO 0);
SIGNAL qdct_out_reg : std_logic_vector(11 DOWNTO 0);
SIGNAL qdct_out_mag2 : std_logic;
SIGNAL qdct_out_mag3 : std_logic;
SIGNAL qdct_out_mag4 : std_logic;
SIGNAL qdct_out_mag5 : std_logic;
SIGNAL qdct_out_mag6 : std_logic;
SIGNAL qdct_out_mag7 : std_logic;
SIGNAL quant_shift : std_logic_vector(12 DOWNTO 0);
SIGNAL quant_shift_reg1 : std_logic_vector(12 DOWNTO 0);
SIGNAL quant_shift_reg2 : std_logic_vector(12 DOWNTO 0);
SIGNAL qscale_reg : std_logic_vector(9 DOWNTO 0);
-- synthesis syn_romstyle = "select_rom"
SIGNAL q_scale_mem : std_logic_vector(9 DOWNTO 0);
--reg[7:0] q_value_new_intra, q_value_new_non_intra,q_value_new_out;
SIGNAL qscale_mem_sel : std_logic_vector(6 DOWNTO 0);
SIGNAL q_value_new_out : std_logic_vector(7 DOWNTO 0);
SIGNAL q_value_new_intra : ram_mem1;
SIGNAL q_value_new_non_intra : ram_mem2;
SIGNAL qdct_in_reg : std_logic_vector(11 DOWNTO 0);
SIGNAL prod1 : std_logic_vector(14 DOWNTO 0);
SIGNAL prod1_reg : std_logic_vector(14 DOWNTO 0);
SIGNAL prod2_rnd : std_logic_vector(21 DOWNTO 0);
SIGNAL prod2 : std_logic_vector(26 DOWNTO 0);
SIGNAL prod2_sign : std_logic_vector(21 DOWNTO 0);
SIGNAL prod2_sign_reg : std_logic_vector(21 DOWNTO 0);
SIGNAL prod_sat : std_logic_vector(11 DOWNTO 0);
SIGNAL prod_sat_reg : std_logic_vector(11 DOWNTO 0);
SIGNAL prod_mismatch : std_logic_vector(11 DOWNTO 0);
-- synthesis syn_romstyle = "select_rom"
SIGNAL def_q_mem : std_logic_vector(7 DOWNTO 0);
SIGNAL def_q_mem_reg : std_logic_vector(7 DOWNTO 0);
SIGNAL def_q_mem_reg1 : std_logic_vector(7 DOWNTO 0);
SIGNAL def_qmem_sel : std_logic_vector(8 DOWNTO 0);
SIGNAL quant_sum : std_logic_vector(1 DOWNTO 0);
SIGNAL qdct_out_comp : std_logic;
SIGNAL Q_cnt64 : integer;
SIGNAL case_wire : std_logic_vector(2 DOWNTO 0);
SIGNAL prod2_rnd_pos : std_logic;
SIGNAL prod2_rnd_neg : std_logic;
SIGNAL temp4 : std_logic_vector(10 DOWNTO 0);
SIGNAL temp5 : std_logic_vector(26 DOWNTO 5);
SIGNAL temp6 : std_logic_vector(21 DOWNTO 0);
SIGNAL temp7 : std_logic; -- was25&15
SIGNAL temp8 : std_logic;
SIGNAL temp9 : std_logic_vector(11 DOWNTO 0);
SIGNAL temp10 : std_logic_vector(11 DOWNTO 0);
SIGNAL temp12 : std_logic_vector(11 DOWNTO 0);
BEGIN
--***************************************************************************
-- counter to count up to 64. This counter is used to read in the 64
-- 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
PROCESS (CLK, RST)
BEGIN
IF (RST = '1') THEN
cnt64 <= "1000000";
ELSIF (CLK'EVENT AND CLK = '1') THEN
IF (rdy_in = '1' AND cnt64 < "1000000") THEN
cnt64 <= cnt64 + "0000001";
ELSE
IF (rdy_in = '1') THEN
cnt64 <= "0000001";
END IF;
END IF;
END IF;
END PROCESS;
-- first active quant sum output occurs when cnt64 = 10. So quant sum
-- first active quant sum output occurs when cnt64 = 10. So quant sum
-- should be added for 64 clks after every cnt64 = 10
PROCESS (CLK, RST)
BEGIN
IF (RST = '1') THEN
cnt64b <= "0111111";
ELSIF (CLK'EVENT AND CLK = '1') THEN
IF (rdy_in = '1') THEN
IF (cnt64b < "1000000") THEN
cnt64b <= cnt64b + "0000001";
ELSE
cnt64b <= "0000001";
END IF;
END IF;
END IF;
END PROCESS;
PROCESS (CLK, RST)
BEGIN
IF (RST = '1') THEN
cnt64c <= "0111111";
ELSIF (CLK'EVENT AND CLK = '1') THEN
IF (rdy_in = '1') THEN
IF (cnt64c < "1000000") THEN
cnt64c <= cnt64c + "0000001";
ELSE
cnt64c <= "0000001";
END IF;
END IF;
END IF;
END PROCESS;
--***************************************************************************
PROCESS (CLK, RST)
BEGIN
IF (RST = '1') THEN
cnt_start <= '0';
ELSIF (CLK'EVENT AND CLK = '1') THEN
IF (rdy_in = '1' AND cnt64 = "1000000") THEN
cnt_start <= '1';
ELSE
cnt_start <= cnt_start;
END IF;
END IF;
END PROCESS;
PROCESS (CLK, RST)
BEGIN
IF (RST = '1') THEN
macroblock_type_reg1 <= '0';
quant_scale_code_reg1 <= "00000";
quant_scale_type_reg1 <= '0';
load_intra_qmatrix_reg1 <= '0';
load_non_intra_qmatrix_reg1 <= '0';
ELSIF (CLK'EVENT AND CLK = '1') THEN
IF (rdy_in = '1' AND cnt64 = "1000000") THEN
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;
ELSE
END IF;
END IF;
END PROCESS;
PROCESS (CLK, RST)
BEGIN
IF (RST = '1') THEN
quant_scale_code_reg2 <= "00000";
quant_scale_type_reg2 <= '0';
load_intra_qmatrix_reg2 <= '0';
load_non_intra_qmatrix_reg2 <= '0';
load_intra_qmatrix_reg3 <= '0';
load_non_intra_qmatrix_reg3 <= '0';
load_intra_qmatrix_reg4 <= '0';
load_non_intra_qmatrix_reg4 <= '0';
ELSIF (CLK'EVENT AND CLK = '1') THEN
IF (rdy_in = '1') THEN
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;
ELSE
END IF;
END IF;
END PROCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -