• JPEG解码:反zig_zag变换



    反量化模块就是对输入的64个数据进行重新排列,64个数据为8*8的数据,即8行8列。在进行编码的时候,DCT变换实际上是将图像从色彩域转向频频域,进过DCT变换的数据要经过量化,量化是实际上是对DCT系数的一个优化过程,它是利用人眼对高频部分不敏感的特性来实现数据的大幅度简化,具体操作时把频率域上的每个成分除以一个对于该成分的常数,去四舍五入接近的整数(已经在huffman解码模块实现反量化),是一种有损压缩。量化后的数据有个很大的特点,就是数列上的相邻点在图像上也是相邻的,还有个特点是直流分量对于交流分量来说要大,而且交流分量中含有大量的0,对于量化后的数据如何进行简化,从而再更大的进行数据压缩,这是就出现了Zig_Zag排列(“Z”字编排),如下图:

    这样做的特点就是后面的数据会出现多个0,方便后面的游程长度编码(RLE)。由上图可以看出编码的时候对数据并不是顺序排列的,而是一种类似Z字型排列的,那么在解码的时候对接收到的数据是不可以直接用的,必须把数据还原过来,就是一个对数据重新排列的过程,这是就要用到反量化表,如下图:

    由上表可以很清楚的看到数据的排列,对来到的每个数据从表中找到与之对应的位置然后存下即可,再读出的时候一次读出就可以了。

    经过分析可以知道:

    1:每次来需要等到64个数据全部来齐才可以操作

    2:需要一个存储器来保存这64个数据。本设计中使用了2个存储器来是为了提高速度,一个存储器用来接收数据,另个存储器用来输出数据,两个存储器实现循环操纵,如果只用一个存储器操作,则在数据输入的时候,输出必须等待64个数据全部输入完毕,在数据输出的时候出入又必须等待64个数据全部输出结束才可以接受新的数据。

    mem
      1 `timescale 1ps/1ps
    2 module zig_zag_mem
    3 (
    4 clk,
    5 rst_n,
    6 wr_en,
    7 wr_addr,
    8 data,
    9
    10 rd_addr,
    11 q
    12 );
    13
    14 input clk;
    15 input rst_n;
    16
    17 input wr_en;
    18 input [5:0]wr_addr;
    19 input [15:0]data;
    20
    21 input [5:0]rd_addr;
    22 output [15:0]q;
    23 //--------------------------------------------
    24 reg [15:0]RegData [0:63];
    25 always @(posedge clk or negedge rst_n)
    26 begin
    27 if(!rst_n)
    28 begin
    29 RegData[0] <= 16'h0000;
    30 RegData[1] <= 16'h0000;
    31 RegData[2] <= 16'h0000;
    32 RegData[3] <= 16'h0000;
    33 RegData[4] <= 16'h0000;
    34 RegData[5] <= 16'h0000;
    35 RegData[6] <= 16'h0000;
    36 RegData[7] <= 16'h0000;
    37 RegData[8] <= 16'h0000;
    38 RegData[9] <= 16'h0000;
    39 RegData[10] <= 16'h0000;
    40 RegData[11] <= 16'h0000;
    41 RegData[12] <= 16'h0000;
    42 RegData[13] <= 16'h0000;
    43 RegData[14] <= 16'h0000;
    44 RegData[15] <= 16'h0000;
    45 RegData[16] <= 16'h0000;
    46 RegData[17] <= 16'h0000;
    47 RegData[18] <= 16'h0000;
    48 RegData[19] <= 16'h0000;
    49 RegData[20] <= 16'h0000;
    50 RegData[21] <= 16'h0000;
    51 RegData[22] <= 16'h0000;
    52 RegData[23] <= 16'h0000;
    53 RegData[24] <= 16'h0000;
    54 RegData[25] <= 16'h0000;
    55 RegData[26] <= 16'h0000;
    56 RegData[27] <= 16'h0000;
    57 RegData[28] <= 16'h0000;
    58 RegData[29] <= 16'h0000;
    59 RegData[30] <= 16'h0000;
    60 RegData[31] <= 16'h0000;
    61 RegData[32] <= 16'h0000;
    62 RegData[33] <= 16'h0000;
    63 RegData[34] <= 16'h0000;
    64 RegData[35] <= 16'h0000;
    65 RegData[36] <= 16'h0000;
    66 RegData[37] <= 16'h0000;
    67 RegData[38] <= 16'h0000;
    68 RegData[39] <= 16'h0000;
    69 RegData[40] <= 16'h0000;
    70 RegData[41] <= 16'h0000;
    71 RegData[42] <= 16'h0000;
    72 RegData[43] <= 16'h0000;
    73 RegData[44] <= 16'h0000;
    74 RegData[45] <= 16'h0000;
    75 RegData[46] <= 16'h0000;
    76 RegData[47] <= 16'h0000;
    77 RegData[48] <= 16'h0000;
    78 RegData[49] <= 16'h0000;
    79 RegData[50] <= 16'h0000;
    80 RegData[51] <= 16'h0000;
    81 RegData[52] <= 16'h0000;
    82 RegData[53] <= 16'h0000;
    83 RegData[54] <= 16'h0000;
    84 RegData[55] <= 16'h0000;
    85 RegData[56] <= 16'h0000;
    86 RegData[57] <= 16'h0000;
    87 RegData[58] <= 16'h0000;
    88 RegData[59] <= 16'h0000;
    89 RegData[60] <= 16'h0000;
    90 RegData[61] <= 16'h0000;
    91 RegData[62] <= 16'h0000;
    92 RegData[63] <= 16'h0000;
    93 end
    94 else
    95 begin
    96 if(wr_en == 1'b1)
    97 begin
    98 RegData[wr_addr] <= data;
    99 if(wr_addr == 6'h00)
    100 begin
    101 RegData[1] <= 16'h0000;
    102 RegData[2] <= 16'h0000;
    103 RegData[3] <= 16'h0000;
    104 RegData[4] <= 16'h0000;
    105 RegData[5] <= 16'h0000;
    106 RegData[6] <= 16'h0000;
    107 RegData[7] <= 16'h0000;
    108 RegData[8] <= 16'h0000;
    109 RegData[9] <= 16'h0000;
    110 RegData[10] <= 16'h0000;
    111 RegData[11] <= 16'h0000;
    112 RegData[12] <= 16'h0000;
    113 RegData[13] <= 16'h0000;
    114 RegData[14] <= 16'h0000;
    115 RegData[15] <= 16'h0000;
    116 RegData[16] <= 16'h0000;
    117 RegData[17] <= 16'h0000;
    118 RegData[18] <= 16'h0000;
    119 RegData[19] <= 16'h0000;
    120 RegData[20] <= 16'h0000;
    121 RegData[21] <= 16'h0000;
    122 RegData[22] <= 16'h0000;
    123 RegData[23] <= 16'h0000;
    124 RegData[24] <= 16'h0000;
    125 RegData[25] <= 16'h0000;
    126 RegData[26] <= 16'h0000;
    127 RegData[27] <= 16'h0000;
    128 RegData[28] <= 16'h0000;
    129 RegData[29] <= 16'h0000;
    130 RegData[30] <= 16'h0000;
    131 RegData[31] <= 16'h0000;
    132 RegData[32] <= 16'h0000;
    133 RegData[33] <= 16'h0000;
    134 RegData[34] <= 16'h0000;
    135 RegData[35] <= 16'h0000;
    136 RegData[36] <= 16'h0000;
    137 RegData[37] <= 16'h0000;
    138 RegData[38] <= 16'h0000;
    139 RegData[39] <= 16'h0000;
    140 RegData[40] <= 16'h0000;
    141 RegData[41] <= 16'h0000;
    142 RegData[42] <= 16'h0000;
    143 RegData[43] <= 16'h0000;
    144 RegData[44] <= 16'h0000;
    145 RegData[45] <= 16'h0000;
    146 RegData[46] <= 16'h0000;
    147 RegData[47] <= 16'h0000;
    148 RegData[48] <= 16'h0000;
    149 RegData[49] <= 16'h0000;
    150 RegData[50] <= 16'h0000;
    151 RegData[51] <= 16'h0000;
    152 RegData[52] <= 16'h0000;
    153 RegData[53] <= 16'h0000;
    154 RegData[54] <= 16'h0000;
    155 RegData[55] <= 16'h0000;
    156 RegData[56] <= 16'h0000;
    157 RegData[57] <= 16'h0000;
    158 RegData[58] <= 16'h0000;
    159 RegData[59] <= 16'h0000;
    160 RegData[60] <= 16'h0000;
    161 RegData[61] <= 16'h0000;
    162 RegData[62] <= 16'h0000;
    163 RegData[63] <= 16'h0000;
    164 end
    165 end
    166 end
    167 end
    168
    169
    170 assign q = RegData [rd_addr];
    171 endmodule


    这是一个位宽为16位,深度为64的存储器。

    Z
      1 `timescale 1ps / 1ps
    2 module zig_zag
    3 (
    4 clk,
    5 rst_n,
    6
    7 datain_en,
    8 datain_addr,
    9 zig_zagIDLE,
    10 datain,
    11
    12 unit_en,
    13
    14 //DataOutOver,
    15 dataout_en,
    16 zig_dataout
    17 );
    18
    19 input clk;
    20 input rst_n;
    21
    22 input datain_en;
    23 input [5:0] datain_addr;
    24 input [15:0] datain;
    25
    26 input unit_en;
    27 //input DataOutOver;
    28
    29 output zig_zagIDLE;
    30 output dataout_en;
    31 output [11:0] zig_dataout;
    32 //-----------------------------------------------------
    33 wire [5:0] wr_addr;
    34 reg [5:0] rd_addr;
    35
    36 //ram使能
    37 reg wr_ram; //0选择ram0,1选择ram1
    38 always @(posedge clk or negedge rst_n) begin
    39 if(!rst_n) begin
    40 wr_ram <= 1'b0;
    41 end else if (unit_en == 1'b1) begin
    42 wr_ram <= ~wr_ram;
    43 end
    44 end
    45
    46
    47 wire wr_ram0;
    48 wire wr_ram1;
    49 assign wr_ram0 = (datain_en == 1'b1 & wr_ram == 1'b0);
    50 assign wr_ram1 = (datain_en == 1'b1 & wr_ram == 1'b1);
    51
    52
    53
    54
    55 function [5:0] result;
    56 input [5:0] count;
    57 case(count)
    58 6'd0: result = 6'd0;
    59 6'd1: result = 6'd1;
    60 6'd2: result = 6'd8;
    61 6'd3: result = 6'd16;
    62 6'd4: result = 6'd9;
    63 6'd5: result = 6'd2;
    64 6'd6: result = 6'd3;
    65 6'd7: result = 6'd10;
    66 6'd8: result = 6'd17;
    67 6'd9: result = 6'd24;
    68 6'd10: result = 6'd32;
    69 6'd11: result = 6'd25;
    70 6'd12: result = 6'd18;
    71 6'd13: result = 6'd11;
    72 6'd14: result = 6'd04;
    73 6'd15: result = 6'd05;
    74 6'd16: result = 6'd12;
    75 6'd17: result = 6'd19;
    76 6'd18: result = 6'd26;
    77 6'd19: result = 6'd33;
    78 6'd20: result = 6'd40;
    79 6'd21: result = 6'd48;
    80 6'd22: result = 6'd41;
    81 6'd23: result = 6'd34;
    82 6'd24: result = 6'd27;
    83 6'd25: result = 6'd20;
    84 6'd26: result = 6'd13;
    85 6'd27: result = 6'd06;
    86 6'd28: result = 6'd07;
    87 6'd29: result = 6'd14;
    88 6'd30: result = 6'd21;
    89 6'd31: result = 6'd28;
    90 6'd32: result = 6'd35;
    91 6'd33: result = 6'd42;
    92 6'd34: result = 6'd49;
    93 6'd35: result = 6'd56;
    94 6'd36: result = 6'd57;
    95 6'd37: result = 6'd50;
    96 6'd38: result = 6'd43;
    97 6'd39: result = 6'd36;
    98 6'd40: result = 6'd29;
    99 6'd41: result = 6'd22;
    100 6'd42: result = 6'd15;
    101 6'd43: result = 6'd23;
    102 6'd44: result = 6'd30;
    103 6'd45: result = 6'd37;
    104 6'd46: result = 6'd44;
    105 6'd47: result = 6'd51;
    106 6'd48: result = 6'd58;
    107 6'd49: result = 6'd59;
    108 6'd50: result = 6'd52;
    109 6'd51: result = 6'd45;
    110 6'd52: result = 6'd38;
    111 6'd53: result = 6'd31;
    112 6'd54: result = 6'd39;
    113 6'd55: result = 6'd46;
    114 6'd56: result = 6'd53;
    115 6'd57: result = 6'd60;
    116 6'd58: result = 6'd61;
    117 6'd59: result = 6'd54;
    118 6'd60: result = 6'd47;
    119 6'd61: result = 6'd55;
    120 6'd62: result = 6'd62;
    121 6'd63: result = 6'd63;
    122 endcase
    123 endfunction
    124 //读ram选择
    125 reg rd_ram;
    126 always @(posedge clk or negedge rst_n) begin
    127 if(!rst_n) begin
    128 rd_ram <= 1'b0;
    129 end else if (rd_addr == 6'd63) begin
    130 rd_ram <= ~rd_ram;
    131 end
    132 end
    133
    134 assign wr_addr = result(datain_addr);
    135 wire ram0_release;
    136 wire ram1_release;
    137 assign ram0_release = (rd_addr == 6'd63 & rd_ram == 1'b0);
    138 assign ram1_release = (rd_addr == 6'd63 & rd_ram == 1'b1);
    139
    140 reg rd_ram0;
    141 reg rd_ram1;
    142
    143 always @(posedge clk or negedge rst_n) begin
    144 if(!rst_n)
    145 begin
    146 rd_ram0= 1'b0;
    147 rd_ram1= 1'b0;
    148 end
    149 else
    150 begin
    151 if(rd_ram0 == 1'b0 & wr_ram == 1'b0)
    152 begin
    153 if(unit_en == 1'b1 & zig_zagIDLE == 1'b1)
    154 rd_ram0 = 1'b1;
    155 end
    156 else
    157 if(ram0_release == 1'b1)
    158 rd_ram0 = 1'b0;
    159 if(rd_ram1 == 1'b0 & wr_ram== 1'b1)
    160 begin
    161 if(unit_en == 1'b1 & zig_zagIDLE == 1'b1)
    162 rd_ram1 = 1'b1;
    163 end
    164 else
    165 if(ram1_release== 1'b1)
    166 rd_ram1 = 1'b0;
    167 end
    168 end
    169
    170 //产生读地址
    171 always @(posedge clk or negedge rst_n)
    172 begin
    173 if(!rst_n)
    174 begin
    175 rd_addr <= 6'd0;
    176 end
    177 else
    178 begin
    179 if (dataout_en == 1'b1)
    180 begin
    181 if (rd_addr == 6'd63)
    182 begin
    183 rd_addr <= 6'd0;
    184 end
    185 rd_addr <= rd_addr + 6'd1;
    186 end
    187 end
    188 end
    189
    190
    191
    192
    193
    194
    195 wire [11:0]q0;
    196 wire [11:0]q1;
    197 zig_zag_mem m1(
    198 .clk ( clk ),
    199 .rst_n ( rst_n ),
    200 .wr_en ( wr_ram0 ),
    201 .wr_addr( wr_addr ),
    202 .data ( datain ),
    203 .rd_addr( rd_addr ),
    204 .q ( q0 )
    205 );
    206
    207 zig_zag_mem m2(
    208 .clk ( clk ),
    209 .rst_n ( rst_n ),
    210 .wr_en ( wr_ram1 ),
    211 .wr_addr ( wr_addr ),
    212 .data ( datain ),
    213 .rd_addr ( rd_addr ),
    214 .q (q1 )
    215 );
    216
    217
    218 assign zig_zagIDLE = rd_ram0 == 1'b0 | rd_ram1 == 1'b0;
    219 assign dataout_en = rd_ram0 == 1'b1 | rd_ram1 == 1'b1 ;
    220 assign zig_dataout = (rd_ram)?q1[11:0]:q0[11:0];
    221
    222 endmodule


    这是Z变换的顶层模块,

    36-50行是定义连个ram使能进行循环操作,unit_en信号是huffman解码输出信号,高表示解码到64的数据,然后存储器转换。

    55-123行定义一个functiom,他的作用是对于输入的每个数据按照反Zig表分别计算出需要存储器的地址。

    124-169行是进行读取不同的ram的设置。

    170-188行是产生读地址,0-63循环操作。

    195-216行是例化2个存储器。

    218行是当两个ram都为空闲状态时,向huffman解码模块发出读取数据请求。

    219行是产生输出使能。

    220行是对输出有效数据的选择。

    到这里反Z变换已经结束,接下来将讨论IDCT模块,IDCT变换模块比较灵活,方法很多种,可优化的地方也很多,由于本人水平有限,现在只先讨论一种比较简单直接的没有任何优化的IDCT变换模块。


     

  • 相关阅读:
    PHP去除所有的空格
    PHP学习之分页类
    PHP学习之验证码类
    PHP学习之迭代生成器
    PHP学习之PHP trait解析
    PHP学习之PHP代码的优化
    PHP学习之PHP的语法糖
    PHP学习之PHP编码习惯
    PHP介绍
    Centos7安装PHP、安装MySQL、安装apache
  • 原文地址:https://www.cnblogs.com/tony1224/p/2407277.html
Copyright © 2020-2023  润新知