JPEG解码中桶型寄存器研究

[复制链接]
2892|14
 楼主| lxAPP 发表于 2012-10-14 20:30 | 显示全部楼层 |阅读模式
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时,才开始读入新的数据。每次解码之后,计数器的值都要减去本次解码所消耗的位数,确保下次输入数据的有效性。
代码如下:

 楼主| lxAPP 发表于 2012-10-14 20:32 | 显示全部楼层
  1. 1 `timescale 1ps / 1ps
  2. 2 module regdata(
  3. 3 clk,
  4. 4 rst_n, 5
  5. 6 start,
  6. 7 data,
  7. 8 data_en,
  8. 9 data_read,
  9. 10
  10. 11 data_out,
  11. 12 dataout_en,
  12. 13 data_end,
  13. 14
  14. 15 FF00,
  15. 16
  16. 17 use_bit,
  17. 18 use_width,
  18. 19 use_byte,
  19. 20 use_word
  20. 21 );
  21. 22
  22. 23
  23. 24 input clk;//系统输入时钟信号
  24. 25 input rst_n;//复位信号,低电平有效
  25. 26
  26. 27 input start;//开始信号
  27. 28 input [31:0] data;//输入数据
  28. 29 input data_en;//输入数据使能信号
  29. 30 output data_read;//读取存储器信号
  30. 31
  31. 32 output [31:0] data_out;//输出数据
  32. 33 output dataout_en;//数据输出使能信号
  33. 34 output data_end;//数据传输结束信号
  34. 35
  35. 36 input FF00;//允许去除冗余
  36. 37
  37. 38 input use_bit;//使用位传输数据
  38. 39 input [6:0] use_width;//传输的位宽
  39. 40 input use_byte;//每次传输一个字节 8bit
  40. 41 input use_word;//每次传输一个字 16bit
  41. 42
  42. 43 reg [95:0] reg_data;//96位的移位寄存器,用于保存每次进来的数据
  43. 44 reg [7:0] reg_width;//移位寄存器的有效数据的位数
  44. 45
  45. 46 wire valid; //有效信号,
  46. 47 assign valid = reg_width > 64;
  47. 48 //----------------------------------------------
  48. 49 //寄存器中的数据少于64位产生读外部存储器请求信号,
  49. 50 //即移出的超过32位时候继续读入数据(读入为32位)
  50. 51 assign data_read = valid == 1'b0 & data_en == 1'b1;
  51. 52
  52. 53 always @(posedge clk or negedge rst_n)
  53. 54 begin
  54. 55 if(!rst_n)
  55. 56 begin
  56. 57 reg_data <= 96'd0;
  57. 58 reg_width <= 8'h00;
  58. 59 end
  59. 60 else
  60. 61 begin
  61. 62 if(start == 1'b1) //数据开始,清空各值
  62. 63 begin
  63. 64 reg_data <= 96'd0;
  64. 65 reg_width <= 8'h00;
  65. 66 end
  66. 67 else if(valid == 1'b0 & data_en == 1'b1) //此情况为读取新数据
  67. 68 begin
  68. 69 if(FF00 == 1'b1) //sos开始,即读表信息结束,开始解码..............允许去冗余!
  69. 70 begin
  70. 71 if(reg_data[39: 8] == 32'hFF00FF00)
  71. 72 begin
  72. 73 reg_width <= reg_width + 8'd16;
  73. 74 reg_data[95:64] <= {8'h00,reg_data[71:48]};
  74. 75 reg_data[63:32] <= {reg_data[47:40],16'hFFFF,reg_data[7:0]};
  75. 76 end
  76. 77 else if(reg_data[39:24] == 16'hFF00 & reg_data[15: 0] == 16'hFF00)
  77. 78 begin
  78. 79 reg_width <= reg_width + 8'd16;
  79. 80 reg_data[95:64] <= {8'h00,reg_data[71:48]};
  80. 81 reg_data[63:32] <= {reg_data[47:40],8'hFF,reg_data[23:16],8'hFF};
  81. 82 end
  82. 83 else if(reg_data[31: 0] == 32'hFF00FF00)
  83. 84 begin
  84. 85 reg_width <= reg_width + 8'd16;
  85. 86 reg_data[95:64] <= {16'h0000,reg_data[71:56]};
  86. 87 reg_data[63:32] <= {reg_data[55:40],16'hFFFF};
  87. 88 end
  88. 89 else if(reg_data[39:24] == 16'hFF00)
  89. 90 begin
  90. 91 reg_width <= reg_width + 8'd24;
  91. 92 reg_data[95:64] <= {reg_data[71:40]};
  92. 93 reg_data[63:32] <= {8'hFF,reg_data[23:0]};
  93. 94 end
  94. 95 else if(reg_data[31:16] == 16'hFF00)
  95. 96 begin
  96. 97 reg_width <= reg_width + 8'd24;
  97. 98 reg_data[95:64] <= {reg_data[71:40]};
  98. 99 reg_data[63:32] <= {reg_data[39:32],8'hFF,reg_data[15:0]};
  99. 100 end
  100. 101 else if(reg_data[23: 8] == 16'hFF00)
  101. 102 begin
  102. 103 reg_width <= reg_width + 8'd24;
  103. 104 reg_data[95:64] <= {reg_data[71:40]};
  104. 105 reg_data[63:32] <= {reg_data[39:32],reg_data[31:24],8'hFF,reg_data[7:0]};
  105. 106 end
  106. 107 else if(reg_data[15: 0] == 16'hFF00)
  107. 108 begin
  108. 109 reg_width <= reg_width + 8'd24;
  109. 110 reg_data[95:64] <= {reg_data[71:40]};
  110. 111 reg_data[63:32] <= {reg_data[39:32],reg_data[31:16],8'hFF};
  111. 112 end
  112. 113 else
  113. 114 begin
  114. 115 reg_width <= reg_width + 8'd32;
  115. 116 reg_data[95:64] <= reg_data[63:32];
  116. 117 reg_data[63:32] <= reg_data[31:0];
  117. 118 end
  118. 119 end
  119. 120
  120. 121 else
  121. 122 begin
  122. 123 reg_width <= reg_width + 8'd32;
  123. 124 reg_data[95:64] <= reg_data[63:32];
  124. 125 reg_data[63:32] <= reg_data[31:0];
  125. 126 end
  126. 127
  127. 128 //reg_data[31: 0] <= {dataIn[7:0],dataIn[15:8],dataIn[23:16],dataIn[31:24]};
  128. 129 reg_data[31: 0] <= {data[31:24],data[23:16],data[15:8],data[7:0]};
  129. 130 end
  130. 131 else if(use_bit == 1'b1)
  131. 132 begin
  132. 133 reg_width <= reg_width - use_width;
  133. 134 end
  134. 135 else if(use_byte == 1'b1)
  135. 136 begin
  136. 137 reg_width <= reg_width - 8'd8;
  137. 138 end
  138. 139 else if(use_word == 1'b1)
  139. 140 begin
  140. 141 reg_width <= reg_width - 8'd16;
  141. 142 end
  142. 143 end
  143. 144 end
  144. 145
  145. 146 //---------------------------------------------------
  146. 147 //产生数据结束信号,当读到数据为FFD9,表示结束
  147. 148 assign data_end = (
  148. 149 reg_data[31:16] == 16'hFFd9 |
  149. 150 reg_data[23: 8] == 16'hFFd9 |
  150. 151 reg_data[15: 0] == 16'hFFd9
  151. 152 );
  152. 153
  153. 154 function [31:0] result;
  154. 155 input [95:0] reg_data;
  155. 156 input [7:0] reg_width;
  156. 157
  157. 158 case(reg_width)
  158. 159 8'd65: result = reg_data[64:33];
  159. 160 8'd66: result = reg_data[65:34];
  160. 161 8'd67: result = reg_data[66:35];
  161. 162 8'd68: result = reg_data[67:36];
  162. 163 8'd69: result = reg_data[68:37];
  163. 164 8'd70: result = reg_data[69:38];
  164. 165 8'd71: result = reg_data[70:39];
  165. 166 8'd72: result = reg_data[71:40];
  166. 167 8'd73: result = reg_data[72:41];
  167. 168 8'd74: result = reg_data[73:42];
  168. 169 8'd75: result = reg_data[74:43];
  169. 170 8'd76: result = reg_data[75:44];
  170. 171 8'd77: result = reg_data[76:45];
  171. 172 8'd78: result = reg_data[77:46];
  172. 173 8'd79: result = reg_data[78:47];
  173. 174 8'd80: result = reg_data[79:48];
  174. 175 8'd81: result = reg_data[80:49];
  175. 176 8'd82: result = reg_data[81:50];
  176. 177 8'd83: result = reg_data[82:51];
  177. 178 8'd84: result = reg_data[83:52];
  178. 179 8'd85: result = reg_data[84:53];
  179. 180 8'd86: result = reg_data[85:54];
  180. 181 8'd87: result = reg_data[86:55];
  181. 182 8'd88: result = reg_data[87:56];
  182. 183 8'd89: result = reg_data[88:57];
  183. 184 8'd90: result = reg_data[89:58];
  184. 185 8'd91: result = reg_data[90:59];
  185. 186 8'd92: result = reg_data[91:60];
  186. 187 8'd93: result = reg_data[92:61];
  187. 188 8'd94: result = reg_data[93:62];
  188. 189 8'd95: result = reg_data[94:63];
  189. 190 8'd96: result = reg_data[95:64];
  190. 191 default: result = 32'h00000000;
  191. 192 endcase
  192. 193 endfunction
  193. 194
  194. 195 reg OutEnable;
  195. 196 reg PreEnable;
  196. 197
  197. 198 reg[31:0] data_out;
  198. 199 always @(posedge clk or negedge rst_n)
  199. 200 begin
  200. 201 if(!rst_n)
  201. 202 begin
  202. 203 OutEnable <= 1'b0;
  203. 204 PreEnable <= 1'b0;
  204. 205 data_out <= 32'h00000000;
  205. 206 end
  206. 207 else
  207. 208 begin
  208. 209 OutEnable <= reg_width >64;
  209. 210 PreEnable <= (use_bit == 1'b1 | use_byte == 1'b1 | use_word == 1'b1);//本次有反馈使用宽度,则不输出,下次输出。即等有反馈后才输出。
  210. 211 data_out <= result(reg_data,reg_width);
  211. 212 end
  212. 213 end
  213. 214
  214. 215 assign dataout_en = (PreEnable == 1'b0)?OutEnable:1'b0;
  215. 216
  216. 217 endmodule
  217. 216行:产生输出使能。
 楼主| lxAPP 发表于 2012-10-14 20:32 | 显示全部楼层
44行:声明一个96位数据寄存器,用于保存输入的数据。

45行:用于标记数据寄存器中有效数据的位数。

52行:当数据存储器中的数据少于64位时,并且输入数据允许时候,产生读信号。

70-119行:表示在SOS段允许去除冗余信息,对各种冗余信息出现不同的位置做相应的处理。

132-143行:数据寄存器的有效数据减去用到的数据宽度,确保数据的有效。

149-153行:当读到的数据位FFD9时表示数据结束信号,EOI段。

155-194行:用一个函数来控制有效的数据。

211行:当有用到数据宽度的时候,此时数据输出使能无效,此时的数据为无效数据,要等到数据去除用到的数据,此时的数据才为有效数据。
GoldSunMonkey 发表于 2012-10-14 20:44 | 显示全部楼层
我上学的时候专门学习这个。现在都有代码了。太好了。
batsong 发表于 2012-10-15 08:43 | 显示全部楼层
ADI实现JPEG编码的芯片要50元以上,能自己搞就好了
jakfens 发表于 2012-10-15 11:09 | 显示全部楼层
:victory:
GoldSunMonkey 发表于 2012-10-15 13:23 | 显示全部楼层
ADI实现JPEG编码的芯片要50元以上,能自己搞就好了
batsong 发表于 2012-10-15 08:43
海思有没有?估计能更便宜,如果有的话。
li37hao 发表于 2013-2-21 15:36 | 显示全部楼层
82.83 else if(reg_data[31: 0] == 32'hFF00FF00)

83.84 begin

84.85 reg_width <= reg_width + 8'd16;

85.86 reg_data[95:64] <= {16'h0000,reg_data[71:56]};

86.87 reg_data[63:32] <= {reg_data[55:40],16'hFFFF};
这样子不会把reg_data[39:32]移没了吗?还是我理解错了?
qwempty 发表于 2013-2-21 18:53 | 显示全部楼层
学习了!
wuhaidianzi 发表于 2013-2-21 19:04 | 显示全部楼层
收下了
ywert000 发表于 2013-2-21 19:30 | 显示全部楼层
我把题目看成了马桶型。。
strouledfox 发表于 2013-2-21 19:49 | 显示全部楼层
。。。。。。。。。
hawksabre 发表于 2013-2-21 20:31 | 显示全部楼层
这个不想涉足了   电子这个行业   需要学习的东西太多了  呵呵   顶一个
habc987 发表于 2013-5-19 19:30 | 显示全部楼层
JPG编码,本人实现,ALTERA的FPGA
GoldSunMonkey 发表于 2013-5-19 23:15 | 显示全部楼层
habc987 发表于 2013-5-19 19:30
JPG编码,本人实现,ALTERA的FPGA

厉害啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则

58

主题

483

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部