OpenCores
URL https://opencores.org/ocsvn/mpeg2fpga/mpeg2fpga/trunk

Subversion Repositories mpeg2fpga

[/] [mpeg2fpga/] [trunk/] [rtl/] [mpeg2/] [iquant.v] - Rev 2

Compare with Previous | Blame | View Log

/* 
 * iquant.v
 * 
 * Copyright (c) 2007 Koen De Vleeschauwer. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE.
 */
 
`include "timescale.v"
 
`undef DEBUG
//`define DEBUG 1
 
module intra_quant_matrix(clk, rst, rd_addr, rd_clk_en, dta_out, wr_addr, dta_in, wr_clk_en, wr_en, rst_values, alternate_scan);
  input           clk;
  input           rst;
  input      [5:0]rd_addr;
  input           rd_clk_en;
  output reg [7:0]dta_out;
  input      [5:0]wr_addr;
  input      [7:0]dta_in;
  input           wr_en; 
  input           wr_clk_en;
  input           rst_values;
  input           alternate_scan;
 
  reg default_values;
  wire    [7:0]do;
  reg     [7:0]default_do;
  reg     [5:0]iquant_wr_addr;
  reg          iquant_wr_en;
  reg     [7:0]iquant_wr_dta;
 
  parameter [2:0]
    STATE_INIT  = 3'b001,
    STATE_CLEAR = 3'b010,
    STATE_RUN   = 3'b100;
 
  reg [2:0]next;
  reg [2:0]state;
 
  /*
   * state machine to initialize intra_quantiser_matrix at reset
   */
 
  always @*
    case (state)
      STATE_INIT:  next = STATE_CLEAR;
      STATE_CLEAR: if (iquant_wr_addr == 6'h3f) next = STATE_RUN;
                   else next = STATE_CLEAR;
      STATE_RUN:   next = STATE_RUN;
      default:     next = STATE_INIT;
    endcase 
 
  always @(posedge clk)
    if (~rst) state <= STATE_INIT;
    else state <= next;
 
  always @(posedge clk)
    if (~rst) iquant_wr_en <= 1'b0;
    else
      case (state)
        STATE_INIT:  iquant_wr_en <= 1'b0;
	STATE_CLEAR: iquant_wr_en <= 1'b1;
	STATE_RUN:   iquant_wr_en <= wr_clk_en && wr_en;
	default      iquant_wr_en <= 1'b0;
      endcase
 
  always @(posedge clk)
    if (~rst) iquant_wr_addr <= 6'b0;
    else
      case (state)
        STATE_INIT:  iquant_wr_addr <= 6'b0;
	STATE_CLEAR: iquant_wr_addr <= iquant_wr_addr + 6'b1;
	STATE_RUN:   iquant_wr_addr <= scan_reverse(alternate_scan, wr_addr);
	default      iquant_wr_addr <= 6'b0;
      endcase
 
  always @(posedge clk)
    if (~rst) iquant_wr_dta <= 8'b0;
    else
      case (state)
        STATE_INIT:  iquant_wr_dta <= 8'b0;
	STATE_CLEAR: iquant_wr_dta <= 8'b0;
	STATE_RUN:   iquant_wr_dta <= dta_in;
	default      iquant_wr_dta <= 8'b0;
      endcase
 
  /* reading */
 
  always @(posedge clk) 
    if (~rst) default_do <= 8'b0;
    else if (rd_clk_en) default_do <= default_intra_quant(rd_addr);
    else default_do <= default_do;
 
  always @(posedge clk) 
    if (~rst) dta_out <= 8'b0;
    else if (rd_clk_en && default_values) dta_out <= default_do;
    else if (rd_clk_en) dta_out <= do;
    else dta_out <= dta_out;
 
  always @(posedge clk)
    if (~rst) default_values <= 1;
    else if (wr_clk_en && rst_values) default_values <= 1;
    else if (wr_clk_en && wr_en && (wr_addr == 6'h3f)) default_values <= 0; // set after last of intra_quant values has been uploaded
    else default_values <= default_values;
 
`include "zigzag_table.v"  
 
 /* 
    intra block quantisation matrix. 
    par. 6.3.11: when sequence_header_code is decoded all matrices shall be reset to their default values.
    par. 7.3.1: inverse scan for quantization matrix download: 
    the quantisation matrix is sent in zigzag (scan 0) order, so here we un-zigzag it using scan0_reverse.
  */
 
  dpram_sc
    #(.addr_width(6),                                         // number of bits in address bus
    .dta_width(8))                                            // number of bits in data bus
    intra_quantiser_matrix (
    .rst(rst),                                                // reset, active low
    .clk(clk),                                                // clock, rising edge trigger
    .wr_en(iquant_wr_en),                                     // write enable, active high
    .wr_addr(iquant_wr_addr),                                 // write address
    .din(iquant_wr_dta),                                      // data input
    .rd_en(1'b1),                                             // read enable, active high
    .rd_addr(rd_addr),                                        // read address
    .dout(do)                                                 // data output
    );
 
  /*
    Default intra block quantisation matrix values. par. 6.3.11. 
  */
 
  function [7:0]default_intra_quant;
    input [5:0]u_v;
    begin
      casex(u_v)
        6'd00: default_intra_quant = 8;
        6'd01: default_intra_quant = 16;
        6'd02: default_intra_quant = 19;
        6'd03: default_intra_quant = 22;
        6'd04: default_intra_quant = 26;
        6'd05: default_intra_quant = 27;
        6'd06: default_intra_quant = 29;
        6'd07: default_intra_quant = 34;
        6'd08: default_intra_quant = 16;
        6'd09: default_intra_quant = 16;
        6'd10: default_intra_quant = 22;
        6'd11: default_intra_quant = 24;
        6'd12: default_intra_quant = 27;
        6'd13: default_intra_quant = 29;
        6'd14: default_intra_quant = 34;
        6'd15: default_intra_quant = 37;
        6'd16: default_intra_quant = 19;
        6'd17: default_intra_quant = 22;
        6'd18: default_intra_quant = 26;
        6'd19: default_intra_quant = 27;
        6'd20: default_intra_quant = 29;
        6'd21: default_intra_quant = 34;
        6'd22: default_intra_quant = 34;
        6'd23: default_intra_quant = 38;
        6'd24: default_intra_quant = 22;
        6'd25: default_intra_quant = 22;
        6'd26: default_intra_quant = 26;
        6'd27: default_intra_quant = 27;
        6'd28: default_intra_quant = 29;
        6'd29: default_intra_quant = 34;
        6'd30: default_intra_quant = 37;
        6'd31: default_intra_quant = 40;
        6'd32: default_intra_quant = 22;
        6'd33: default_intra_quant = 26;
        6'd34: default_intra_quant = 27;
        6'd35: default_intra_quant = 29;
        6'd36: default_intra_quant = 32;
        6'd37: default_intra_quant = 35;
        6'd38: default_intra_quant = 40;
        6'd39: default_intra_quant = 48;
        6'd40: default_intra_quant = 26;
        6'd41: default_intra_quant = 27;
        6'd42: default_intra_quant = 29;
        6'd43: default_intra_quant = 32;
        6'd44: default_intra_quant = 35;
        6'd45: default_intra_quant = 40;
        6'd46: default_intra_quant = 48;
        6'd47: default_intra_quant = 58;
        6'd48: default_intra_quant = 26;
        6'd49: default_intra_quant = 27;
        6'd50: default_intra_quant = 29;
        6'd51: default_intra_quant = 34;
        6'd52: default_intra_quant = 38;
        6'd53: default_intra_quant = 46;
        6'd54: default_intra_quant = 56;
        6'd55: default_intra_quant = 69;
        6'd56: default_intra_quant = 27;
        6'd57: default_intra_quant = 29;
        6'd58: default_intra_quant = 35;
        6'd59: default_intra_quant = 38;
        6'd60: default_intra_quant = 46;
        6'd61: default_intra_quant = 56;
        6'd62: default_intra_quant = 69;
        6'd63: default_intra_quant = 83;
      endcase
    end
  endfunction
 
`ifdef DEBUG
  always @(posedge clk) 
    if (rd_clk_en && default_values) #0 $display("%m\tread %h from %h (default value)", default_intra_quant(rd_addr), rd_addr);
    else if (rd_clk_en) #0 $display("%m\tread %h from %h", do, rd_addr);
 
  always @(posedge clk)
    if (~rst) $display("%m\tset to default values");
    else if (wr_clk_en && rst_values) $display("%m\tset to default values");
    else if (wr_clk_en && wr_en) $display("%m\tset to uploaded table");
 
  always @(posedge clk)
    if (wr_clk_en && wr_en) #0 $display("%m\twrite %h to %h (was %h)", dta_in, scan_reverse(alternate_scan, wr_addr), wr_addr);
 
`endif 
 
endmodule
 
module non_intra_quant_matrix(clk, rst, rd_addr, rd_clk_en, dta_out, wr_addr, dta_in, wr_clk_en, wr_en, rst_values, alternate_scan);
  input           clk;
  input           rst;
  input      [5:0]rd_addr;
  input           rd_clk_en;
  output reg [7:0]dta_out;
  input      [5:0]wr_addr;
  input      [7:0]dta_in;
  input           wr_clk_en; 
  input           wr_en; 
  input           rst_values;
  input           alternate_scan;
 
  reg default_values;
  wire [7:0]do;
  reg     [5:0]non_iquant_wr_addr;
  reg          non_iquant_wr_en;
  reg     [7:0]non_iquant_wr_dta;
 
  parameter [2:0]
    STATE_INIT  = 3'b001,
    STATE_CLEAR = 3'b010,
    STATE_RUN   = 3'b100;
 
  reg [2:0]next;
  reg [2:0]state;
 
  /*
   * state machine to initialize intra_quantiser_matrix at reset
   */
 
  always @*
    case (state)
      STATE_INIT:  next = STATE_CLEAR;
      STATE_CLEAR: if (non_iquant_wr_addr == 6'h3f) next = STATE_RUN;
                   else next = STATE_CLEAR;
      STATE_RUN:   next = STATE_RUN;
      default:     next = STATE_INIT;
    endcase 
 
  always @(posedge clk)
    if (~rst) state <= STATE_INIT;
    else state <= next;
 
  always @(posedge clk)
    if (~rst) non_iquant_wr_en <= 1'b0;
    else
      case (state)
        STATE_INIT:  non_iquant_wr_en <= 1'b0;
	STATE_CLEAR: non_iquant_wr_en <= 1'b1;
	STATE_RUN:   non_iquant_wr_en <= wr_clk_en && wr_en;
	default      non_iquant_wr_en <= 1'b0;
      endcase
 
  always @(posedge clk)
    if (~rst) non_iquant_wr_addr <= 6'b0;
    else
      case (state)
        STATE_INIT:  non_iquant_wr_addr <= 6'b0;
	STATE_CLEAR: non_iquant_wr_addr <= non_iquant_wr_addr + 6'b1;
	STATE_RUN:   non_iquant_wr_addr <= scan_reverse(alternate_scan, wr_addr);
	default      non_iquant_wr_addr <= 6'b0;
      endcase
 
  always @(posedge clk)
    if (~rst) non_iquant_wr_dta <= 8'b0;
    else
      case (state)
        STATE_INIT:  non_iquant_wr_dta <= 8'b0;
	STATE_CLEAR: non_iquant_wr_dta <= 8'b0;
	STATE_RUN:   non_iquant_wr_dta <= dta_in;
	default      non_iquant_wr_dta <= 8'b0;
      endcase
 
  /* reading */
 
  always @(posedge clk) 
    if (rd_clk_en && default_values) dta_out <= 8'd16 ; // Default non intra block quantisation matrix value is 8'd16. par. 6.3.11.
    else if (rd_clk_en) dta_out <= do;
    else dta_out <= dta_out;
 
  always @(posedge clk)
    if (~rst) default_values <= 1;
    else if (wr_clk_en && rst_values) default_values <= 1;
    else if (wr_clk_en && wr_en && (wr_addr == 6'h3f)) default_values <= 0; // set after last of non_intra_quant values has been uploaded
    else default_values <= default_values;
 
`include "zigzag_table.v"  
  /* 
    non intra block quantisation matrix. 
    par. 6.3.11: when sequence_header_code is decoded all matrices shall be reset to their default values.
    par. 7.3.1: inverse scan for quantization matrix download: 
    the quantisation matrix is sent in zigzag (scan 0) order, so here we un-zigzag it using scan0_reverse.
  */
 
  dpram_sc
    #(.addr_width(6),                                         // number of bits in address bus
    .dta_width(8))                                            // number of bits in data bus
    non_intra_quantiser_matrix (
    .rst(rst),                                                // reset, active low
    .clk(clk),                                                // clock, rising edge trigger
    .wr_en(non_iquant_wr_en),                                 // write enable, active high
    .wr_addr(non_iquant_wr_addr),                             // write address
    .din(non_iquant_wr_dta),                                  // data input
    .rd_en(1'b1),                                             // read enable, active high
    .rd_addr(rd_addr),                                        // read address
    .dout(do)                                                 // data output
    );
 
`ifdef DEBUG
  always @(posedge clk) 
    if (rd_clk_en && default_values) #0 $display("%m\tread %h from %h (default value)", 8'd16, rd_addr);
    else if (rd_clk_en) #0 $display("%m\tread %h from %h", do, rd_addr);
 
  always @(posedge clk)
    if (~rst) $display("%m\tset to default values");
    else if (wr_clk_en && rst_values) $display("%m\tset to default values");
    else if (wr_clk_en && wr_en && (wr_addr == 6'h3f)) $display("%m\tset to uploaded table");
 
  always @(posedge clk)
    if (wr_clk_en && wr_en) #0 $display("%m\twrite %h to %h (was %h)", dta_in, scan_reverse(alternate_scan, wr_addr), wr_addr);
 
`endif 
 
endmodule
/* not truncated */
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2019 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.