JPEG解码:桶型寄存器
JPEG解码总共分为:桶型寄存器模块,状态控制模块,huffman解码模块,反量化模块,反zig_zag模块,反idct模块,色彩空间变换模块。桶型寄存器的作用是控制数据流和去除冗余。对于数据的控制是要求桶型存储器能读取数据的任何宽度,输出的数据给状态控制模块和huffman解码模块,状态控制模块要求输入的数据有两种,一种是8位,另一种是16位,huffman解码模块要求输入的数据为不定位数,huffman编码是不定位数的编码,所以在解码的时候事先不知道被解码数据的位数。冗余信息的产生是由于在编码非标志位的数据FF 时,必须在其后加上00,而产生了冗余信息00。所以再遇到FF00的时候必须去除00。
因为在一次解码的过程中,所需要的数据位数至少为27 位,所以使用两个32 位变量的组合来提供解码所需数据。为了便于冗余处理,一次处理数据的位数必须是16 的倍数,因此至少需要64位的数据寄存器用于解码。但实际上设计了一个96 位的寄存器给寄存器增加了32 位,在此32 位中可以去除冗余信息,以确保至少有64 位去冗余后的数据用于解码。
在加载新数据的过程中,用一个8位的计数器reg_width记录桶型寄存器的的有效数据的宽度,为了保证至少有32位数据输出,只有当计数器大于64时,才可以输出32位数据用于解码,为了防止桶型移位寄存器中未解码的数据被新的数据覆盖,只有当计数器值小于64时,才开始读入新的数据。每次解码之后,计数器的值都要减去本次解码所消耗的位数,确保下次输入数据的有效性。
代码如下:
1 `timescale 1ps / 1ps
2 module regdata(
3 clk,
4 rst_n,
5
6 start,
7 data,
8 data_en,
9 data_read,
10
11 data_out,
12 dataout_en,
13 data_end,
14
15 FF00,
16
17 use_bit,
18 use_width,
19 use_byte,
20 use_word
21 );
22
23
24 input clk;//系统输入时钟信号
25 input rst_n;//复位信号,低电平有效
26
27 input start;//开始信号
28 input [31:0] data;//输入数据
29 input data_en;//输入数据使能信号
30 output data_read;//读取存储器信号
31
32 output [31:0] data_out;//输出数据
33 output dataout_en;//数据输出使能信号
34 output data_end;//数据传输结束信号
35
36 input FF00;//允许去除冗余
37
38 input use_bit;//使用位传输数据
39 input [6:0] use_width;//传输的位宽
40 input use_byte;//每次传输一个字节 8bit
41 input use_word;//每次传输一个字 16bit
42
43 reg [95:0] reg_data;//96位的移位寄存器,用于保存每次进来的数据
44 reg [7:0] reg_width;//移位寄存器的有效数据的位数
45
46 wire valid; //有效信号,
47 assign valid = reg_width > 64;
48 //----------------------------------------------
49 //寄存器中的数据少于64位产生读外部存储器请求信号,
50 //即移出的超过32位时候继续读入数据(读入为32位)
51 assign data_read = valid == 1'b0 & data_en == 1'b1;
52
53 always @(posedge clk or negedge rst_n)
54 begin
55 if(!rst_n)
56 begin
57 reg_data <= 96'd0;
58 reg_width <= 8'h00;
59 end
60 else
61 begin
62 if(start == 1'b1) //数据开始,清空各值
63 begin
64 reg_data <= 96'd0;
65 reg_width <= 8'h00;
66 end
67 else if(valid == 1'b0 & data_en == 1'b1) //此情况为读取新数据
68 begin
69 if(FF00 == 1'b1) //sos开始,即读表信息结束,开始解码..............允许去冗余!
70 begin
71 if(reg_data[39: 8] == 32'hFF00FF00)
72 begin
73 reg_width <= reg_width + 8'd16;
74 reg_data[95:64] <= {8'h00,reg_data[71:48]};
75 reg_data[63:32] <= {reg_data[47:40],16'hFFFF,reg_data[7:0]};
76 end
77 else if(reg_data[39:24] == 16'hFF00 & reg_data[15: 0] == 16'hFF00)
78 begin
79 reg_width <= reg_width + 8'd16;
80 reg_data[95:64] <= {8'h00,reg_data[71:48]};
81 reg_data[63:32] <= {reg_data[47:40],8'hFF,reg_data[23:16],8'hFF};
82 end
83 else if(reg_data[31: 0] == 32'hFF00FF00)
84 begin
85 reg_width <= reg_width + 8'd16;
86 reg_data[95:64] <= {16'h0000,reg_data[71:56]};
87 reg_data[63:32] <= {reg_data[55:40],16'hFFFF};
88 end
89 else if(reg_data[39:24] == 16'hFF00)
90 begin
91 reg_width <= reg_width + 8'd24;
92 reg_data[95:64] <= {reg_data[71:40]};
93 reg_data[63:32] <= {8'hFF,reg_data[23:0]};
94 end
95 else if(reg_data[31:16] == 16'hFF00)
96 begin
97 reg_width <= reg_width + 8'd24;
98 reg_data[95:64] <= {reg_data[71:40]};
99 reg_data[63:32] <= {reg_data[39:32],8'hFF,reg_data[15:0]};
100 end
101 else if(reg_data[23: 8] == 16'hFF00)
102 begin
103 reg_width <= reg_width + 8'd24;
104 reg_data[95:64] <= {reg_data[71:40]};
105 reg_data[63:32] <= {reg_data[39:32],reg_data[31:24],8'hFF,reg_data[7:0]};
106 end
107 else if(reg_data[15: 0] == 16'hFF00)
108 begin
109 reg_width <= reg_width + 8'd24;
110 reg_data[95:64] <= {reg_data[71:40]};
111 reg_data[63:32] <= {reg_data[39:32],reg_data[31:16],8'hFF};
112 end
113 else
114 begin
115 reg_width <= reg_width + 8'd32;
116 reg_data[95:64] <= reg_data[63:32];
117 reg_data[63:32] <= reg_data[31:0];
118 end
119 end
120
121 else
122 begin
123 reg_width <= reg_width + 8'd32;
124 reg_data[95:64] <= reg_data[63:32];
125 reg_data[63:32] <= reg_data[31:0];
126 end
127
128 //reg_data[31: 0] <= {dataIn[7:0],dataIn[15:8],dataIn[23:16],dataIn[31:24]};
129 reg_data[31: 0] <= {data[31:24],data[23:16],data[15:8],data[7:0]};
130 end
131 else if(use_bit == 1'b1)
132 begin
133 reg_width <= reg_width - use_width;
134 end
135 else if(use_byte == 1'b1)
136 begin
137 reg_width <= reg_width - 8'd8;
138 end
139 else if(use_word == 1'b1)
140 begin
141 reg_width <= reg_width - 8'd16;
142 end
143 end
144 end
145
146 //---------------------------------------------------
147 //产生数据结束信号,当读到数据为FFD9,表示结束
148 assign data_end = (
149 reg_data[31:16] == 16'hFFd9 |
150 reg_data[23: 8] == 16'hFFd9 |
151 reg_data[15: 0] == 16'hFFd9
152 );
153
154 function [31:0] result;
155 input [95:0] reg_data;
156 input [7:0] reg_width;
157
158 case(reg_width)
159 8'd65: result = reg_data[64:33];
160 8'd66: result = reg_data[65:34];
161 8'd67: result = reg_data[66:35];
162 8'd68: result = reg_data[67:36];
163 8'd69: result = reg_data[68:37];
164 8'd70: result = reg_data[69:38];
165 8'd71: result = reg_data[70:39];
166 8'd72: result = reg_data[71:40];
167 8'd73: result = reg_data[72:41];
168 8'd74: result = reg_data[73:42];
169 8'd75: result = reg_data[74:43];
170 8'd76: result = reg_data[75:44];
171 8'd77: result = reg_data[76:45];
172 8'd78: result = reg_data[77:46];
173 8'd79: result = reg_data[78:47];
174 8'd80: result = reg_data[79:48];
175 8'd81: result = reg_data[80:49];
176 8'd82: result = reg_data[81:50];
177 8'd83: result = reg_data[82:51];
178 8'd84: result = reg_data[83:52];
179 8'd85: result = reg_data[84:53];
180 8'd86: result = reg_data[85:54];
181 8'd87: result = reg_data[86:55];
182 8'd88: result = reg_data[87:56];
183 8'd89: result = reg_data[88:57];
184 8'd90: result = reg_data[89:58];
185 8'd91: result = reg_data[90:59];
186 8'd92: result = reg_data[91:60];
187 8'd93: result = reg_data[92:61];
188 8'd94: result = reg_data[93:62];
189 8'd95: result = reg_data[94:63];
190 8'd96: result = reg_data[95:64];
191 default: result = 32'h00000000;
192 endcase
193 endfunction
194
195 reg OutEnable;
196 reg PreEnable;
197
198 reg[31:0] data_out;
199 always @(posedge clk or negedge rst_n)
200 begin
201 if(!rst_n)
202 begin
203 OutEnable <= 1'b0;
204 PreEnable <= 1'b0;
205 data_out <= 32'h00000000;
206 end
207 else
208 begin
209 OutEnable <= reg_width >64;
210 PreEnable <= (use_bit == 1'b1 | use_byte == 1'b1 | use_word == 1'b1);//本次有反馈使用宽度,则不输出,下次输出。即等有反馈后才输出。
211 data_out <= result(reg_data,reg_width);
212 end
213 end
214
215 assign dataout_en = (PreEnable == 1'b0)?OutEnable:1'b0;
216
217 endmodule
218
219
44行:声明一个96位数据寄存器,用于保存输入的数据。
45行:用于标记数据寄存器中有效数据的位数。
52行:当数据存储器中的数据少于64位时,并且输入数据允许时候,产生读信号。
70-119行:表示在SOS段允许去除冗余信息,对各种冗余信息出现不同的位置做相应的处理。
132-143行:数据寄存器的有效数据减去用到的数据宽度,确保数据的有效。
149-153行:当读到的数据位FFD9时表示数据结束信号,EOI段。
155-194行:用一个函数来控制有效的数据。
211行:当有用到数据宽度的时候,此时数据输出使能无效,此时的数据为无效数据,要等到数据去除用到的数据,此时的数据才为有效数据。
216行:产生输出使能。