update
47
README.md
@ -10,7 +10,7 @@ Hard-PNG
|
|||||||
|
|
||||||
| ![diagram](./figures/diagram.png) |
|
| ![diagram](./figures/diagram.png) |
|
||||||
| :----: |
|
| :----: |
|
||||||
| 图1 : Hard-PNG 原理框图 |
|
| **图1** : Hard-PNG 原理框图 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -34,37 +34,39 @@ png 图像文件的扩展名为 .png 。以本库中的 SIM/test_image/img01.png
|
|||||||
|
|
||||||
# 使用 Hard-PNG
|
# 使用 Hard-PNG
|
||||||
|
|
||||||
RTL 目录中的 hard_png.sv 是一个能够输入 png 码流,输出解压后的像素的模块,它的接口如图2所示。
|
RTL 目录中的 hard_png.sv 是一个能够输入 png 码流,输出解压后的像素的模块,它的接口如**图2**所示。
|
||||||
|
|
||||||
| ![接口图](./figures/interface.png) |
|
| ![接口图](./figures/interface.png) |
|
||||||
| :----: |
|
| :----: |
|
||||||
| 图2 : hard_png 接口图 |
|
| **图2** : hard_png 接口图 |
|
||||||
|
|
||||||
hard_png 的使用方法很简单,在输入一张 png 图像的码流前,先要给模块复位(令 rstn=0 至少一个时钟周期),然后解除复位(令 rstn=1),然后输入 png 码流,并从图象基本信息输出接口和像素输出接口中得到解码结果。
|
## 输入码流
|
||||||
|
|
||||||
以 SIM/test_image/img01.png 为例,我们应该以图3的时序把 png 码流中的98个字节逐一输入到 hard_png 中。其中 ivalid 和 iready 构成了握手信号: ivalid=1 时说明外部想发送一个字节给 hard_png。iready=1 时说明 hard_png 已经准备好接收一个字节。只有 ivalid 和 iready 同时=1 时,ibyte 才被成功的输入 hard_png 中。
|
hard_png 的使用方法很简单,以 SIM/test_image/img01.png 这张图像为例,如**图3**,在输入一张图象的码流前,先要令 istart 上产生一个高电平脉冲(宽度至少为一个时钟周期),然后通过 ivalid 和 ibyte 信号来输入码流(这张图象的 png 码流有 98 字节,这 98 字节都要逐一输入给 hard_png),其中 ivalid 和 iready 构成了握手信号: ivalid=1 时说明外部想发送一个字节给 hard_png。iready=1 时说明 hard_png 已经准备好接收一个字节。只有 ivalid 和 iready 同时=1 时握手才成功,ibyte 才被成功的输入 hard_png 中。
|
||||||
|
|
||||||
| ![输入时序图](./figures/wave1.png) |
|
| ![输入时序图](./figures/wave1.png) |
|
||||||
| :----: |
|
| :----: |
|
||||||
| 图3 : hard_png 的输入波形图 |
|
| **图3** : hard_png 的输入波形图 |
|
||||||
|
|
||||||
在输入的同时,解压结果从模块中输出,如图4。在一帧图象输出前,newframe 信号会出现一个时钟周期的高电平脉冲,同时 colortype, width, height 有效。其中:
|
当一张 png 图象的码流输入结束后,可以立即或稍后输入下一张图像(也就是让 istart 上产生高电平脉冲,然后输入码流)。
|
||||||
|
|
||||||
- width, height 分别为图象的宽度和高度
|
## 输出图像信息和像素
|
||||||
- colortype 为 png 图像的颜色类型,含义如下表。
|
|
||||||
|
|
||||||
| colortype | 3'd0 | 3'd1 | 3'd2 | 3'd3 | 3‘d4 |
|
在输入码流的同时,这张图象的解压结果(也就是图像基本信息和原始像素)会从模块中输出,如**图4**,在图象的像素输出前,ovalid 信号会出现一个时钟周期的高电平脉冲,同时 colortype, width, height 会有效。其中:
|
||||||
|
|
||||||
|
- width, height 分别是图象的宽度和高度
|
||||||
|
- colortype 是 png 图像的颜色类型,含义如下表。
|
||||||
|
|
||||||
|
| colortype 值 | 3'd0 | 3'd1 | 3'd2 | 3'd3 | 3‘d4 |
|
||||||
| :-------: | :--: | :--: | :--: | :--: | :--: |
|
| :-------: | :--: | :--: | :--: | :--: | :--: |
|
||||||
| 颜色类型 | 灰度 | 灰度+A | RGB | RGB+A | 索引RGB |
|
| 颜色类型 | 灰度 | 灰度+A | RGB | RGB+A | 索引RGB |
|
||||||
| 备注 | R=G=B,A=0xFF | R=G=B≠A | R≠G≠B,A=0xFF | R≠G≠B≠A | R≠G≠B,A=0xFF |
|
| 备注 | R=G=B,A=0xFF | R=G=B≠A | R≠G≠B,A=0xFF | R≠G≠B≠A | R≠G≠B,A=0xFF |
|
||||||
|
|
||||||
然后,ovalid=1 代表该时钟周期有一个像素输出,该像素的 R,G,B,A 通道分别出现在 opixelr,opixelg,opixelb,opixela 信号上。
|
然后,ovalid=1 代表该时钟周期有一个像素输出,该像素的 R,G,B,A 通道会分别出现在 opixelr,opixelg,opixelb,opixela 信号上。
|
||||||
|
|
||||||
| ![输出时序图](./figures/wave2.png) |
|
| ![输出时序图](./figures/wave2.png) |
|
||||||
| :----: |
|
| :----: |
|
||||||
| 图4 : hard_png 的输出波形图 |
|
| **图4** : hard_png 的输出波形图 |
|
||||||
|
|
||||||
当一个 png 图象输入结束后,可以立即或稍后输入下一张图像(复位->解除复位->输入码流)。
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -79,7 +81,7 @@ hard_png 的使用方法很简单,在输入一张 png 图像的码流前,先
|
|||||||
|
|
||||||
使用 iverilog 进行仿真前,需要安装 iverilog ,见:[iverilog_usage](https://github.com/WangXuan95/WangXuan95/blob/main/iverilog_usage/iverilog_usage.md)
|
使用 iverilog 进行仿真前,需要安装 iverilog ,见:[iverilog_usage](https://github.com/WangXuan95/WangXuan95/blob/main/iverilog_usage/iverilog_usage.md)
|
||||||
|
|
||||||
然后双击 tb_hard_png_run_iverilog.bat 运行仿真,会运行大约半小时(可以中途强制关闭,但产生的仿真波形就是不全的)。
|
然后双击 tb_hard_png_run_iverilog.bat 即可运行仿真,会运行大约半小时(可以中途强制关闭,但产生的仿真波形就是不全的)。
|
||||||
|
|
||||||
仿真运行完后,可以打开生成的 dump.vcd 文件查看波形。
|
仿真运行完后,可以打开生成的 dump.vcd 文件查看波形。
|
||||||
|
|
||||||
@ -120,18 +122,19 @@ total 400 pixels validation successful!!
|
|||||||
| FPGA 型号 | LUT | LUT(%) | FF | FF(%) | Logic | Logic(%) | BRAM | BRAM(%) |
|
| FPGA 型号 | LUT | LUT(%) | FF | FF(%) | Logic | Logic(%) | BRAM | BRAM(%) |
|
||||||
| :----------------------------: | :--: | :----: | :--: | :---: | :---: | :------: | :-----: | :-----: |
|
| :----------------------------: | :--: | :----: | :--: | :---: | :---: | :------: | :-----: | :-----: |
|
||||||
| Xilinx Artix-7 XC7A35T | 2581 | 13% | 2253 | 5% | - | - | 792kbit | 44% |
|
| Xilinx Artix-7 XC7A35T | 2581 | 13% | 2253 | 5% | - | - | 792kbit | 44% |
|
||||||
| Altera Cyclone IV EP4CE40F23C6 | - | - | - | - | 4551 | 11% | 427kbit | 37% |
|
| Altera Cyclone IV EP4CE40F23C6 | - | - | - | - | 4682 | 11% | 427kbit | 37% |
|
||||||
|
|
||||||
## 性能
|
## 性能
|
||||||
|
|
||||||
在 Altera Cyclone IV EP4CE40F23C6 上部署 hard_png ,时钟频率= 50MHz (正好时序收敛)。根据仿真时每个图像消耗的时钟周期数,可以算出压缩图像时的性能,举例如下表。
|
在 Altera Cyclone IV EP4CE40F23C6 上部署 hard_png ,时钟频率= 50MHz (正好时序收敛)。根据仿真时每个图像消耗的时钟周期数,可以算出压缩图像时的性能,举例如下表。
|
||||||
|
|
||||||
| png文件名 | 颜色类型 | 图象长宽 | png 码流大小 (字节) | 消耗的时钟周期数 | 消耗时间 |
|
| 文件名 | 颜色类型 | 图象长宽 | 像素数 | png 码流大小 (字节) | 时钟周期数 | 消耗时间 |
|
||||||
| :-----------: | :----------: | :----------: | :--------------: | :---------------: | :---------------: |
|
| :-----------: | :----------: | :----------: | :--------------: | :---------------: | :---------------: | ------------- |
|
||||||
| img05.png | RGB | 300x256 | 96536 | 1105702 | 23ms |
|
| img05.png | RGB | 300x256 | 76800 | 96536 | 1105702 | 23ms |
|
||||||
| img06.png | 灰度 | 300x263 | 37283 | 395335 | 8ms |
|
| img06.png | 灰度 | 300x263 | 78900 | 37283 | 395335 | 8ms |
|
||||||
| img10.png | 索引RGB | 631x742 | 193489 | 2374224 | 48ms |
|
| img09.png | RGBA | 300x263 | 78900 | 125218 | 1382303 | 28ms |
|
||||||
| img14.png | 索引RGB | 1920x1080 | 818885 | 10177644 | 204ms |
|
| img10.png | 索引RGB | 631x742 | 468202 | 193489 | 2374224 | 48ms |
|
||||||
|
| img14.png | 索引RGB | 1920x1080 | 2073600 | 818885 | 10177644 | 204ms |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
237
RTL/hard_png.sv
@ -10,11 +10,12 @@ module hard_png (
|
|||||||
input wire rstn,
|
input wire rstn,
|
||||||
input wire clk,
|
input wire clk,
|
||||||
// png data input stream
|
// png data input stream
|
||||||
|
input wire istart,
|
||||||
input wire ivalid,
|
input wire ivalid,
|
||||||
output reg iready,
|
output reg iready,
|
||||||
input wire [ 7:0] ibyte,
|
input wire [ 7:0] ibyte,
|
||||||
// image frame configuration output
|
// image frame configuration output
|
||||||
output reg newframe,
|
output reg ostart,
|
||||||
output wire [ 2:0] colortype, // 0:gray 1:gray+A 2:RGB 3:RGBA 4:RGB-plte
|
output wire [ 2:0] colortype, // 0:gray 1:gray+A 2:RGB 3:RGBA 4:RGB-plte
|
||||||
output wire [13:0] width, // image width
|
output wire [13:0] width, // image width
|
||||||
output wire [31:0] height, // image height
|
output wire [31:0] height, // image height
|
||||||
@ -23,11 +24,9 @@ module hard_png (
|
|||||||
output wire [ 7:0] opixelr, opixelg, opixelb, opixela
|
output wire [ 7:0] opixelr, opixelg, opixelb, opixela
|
||||||
);
|
);
|
||||||
|
|
||||||
initial newframe = 1'b0;
|
initial ostart = 1'b0;
|
||||||
initial ovalid = 1'b0;
|
initial ovalid = 1'b0;
|
||||||
|
|
||||||
reg imagevalid = '0;
|
|
||||||
|
|
||||||
reg isplte = '0;
|
reg isplte = '0;
|
||||||
|
|
||||||
reg [ 1:0] bpp = '0; // bytes per pixel
|
reg [ 1:0] bpp = '0; // bytes per pixel
|
||||||
@ -88,7 +87,9 @@ generate genvar ii;
|
|||||||
if(~rstn)
|
if(~rstn)
|
||||||
latchbytes[ii] <= '0;
|
latchbytes[ii] <= '0;
|
||||||
else begin
|
else begin
|
||||||
if(ivalid)
|
if(istart)
|
||||||
|
latchbytes[ii] <= '0;
|
||||||
|
else if(ivalid)
|
||||||
latchbytes[ii] <= lastbytes[ii+1];
|
latchbytes[ii] <= lastbytes[ii+1];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -134,7 +135,7 @@ wire parametervalid = ( lastbytes[7]==8'h0 &&
|
|||||||
);
|
);
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
if(imagevalid && cnt>0 && curr_name==IDAT && gapcnt==2'd0) begin
|
if(cnt>0 && curr_name==IDAT && gapcnt==2'd0) begin
|
||||||
iready = pready;
|
iready = pready;
|
||||||
pvalid = ivalid;
|
pvalid = ivalid;
|
||||||
pbyte = ibyte;
|
pbyte = ibyte;
|
||||||
@ -152,7 +153,6 @@ always @ (posedge clk or negedge rstn)
|
|||||||
gapcnt <= '0;
|
gapcnt <= '0;
|
||||||
busy <= 1'b0;
|
busy <= 1'b0;
|
||||||
sizevalid <= 1'b0;
|
sizevalid <= 1'b0;
|
||||||
imagevalid <= 1'b0;
|
|
||||||
curr_name <= NONE;
|
curr_name <= NONE;
|
||||||
ispltetmp <= 1'b0;
|
ispltetmp <= 1'b0;
|
||||||
bpptmp <= '0;
|
bpptmp <= '0;
|
||||||
@ -164,18 +164,38 @@ always @ (posedge clk or negedge rstn)
|
|||||||
ppr <= '0;
|
ppr <= '0;
|
||||||
bpr <= '0;
|
bpr <= '0;
|
||||||
rpf <= '0;
|
rpf <= '0;
|
||||||
newframe <= 1'b0;
|
ostart <= 1'b0;
|
||||||
plte_wen <= 1'b0;
|
plte_wen <= 1'b0;
|
||||||
plte_waddr <= '0;
|
plte_waddr <= '0;
|
||||||
plte_wdata <= '0;
|
plte_wdata <= '0;
|
||||||
plte_bytecnt <= '0;
|
plte_bytecnt <= '0;
|
||||||
plte_pixcnt <= '0;
|
plte_pixcnt <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
newframe <= 1'b0;
|
ostart <= 1'b0;
|
||||||
plte_wen <= 1'b0;
|
plte_wen <= 1'b0;
|
||||||
plte_waddr <= '0;
|
plte_waddr <= '0;
|
||||||
plte_wdata <= '0;
|
plte_wdata <= '0;
|
||||||
if(ivalid) begin
|
if(istart) begin
|
||||||
|
bcnt <= '0;
|
||||||
|
cnt <= '0;
|
||||||
|
crccnt <= '0;
|
||||||
|
gapcnt <= '0;
|
||||||
|
busy <= 1'b0;
|
||||||
|
sizevalid <= 1'b0;
|
||||||
|
curr_name <= NONE;
|
||||||
|
ispltetmp <= 1'b0;
|
||||||
|
bpptmp <= '0;
|
||||||
|
pprtmp <= '0;
|
||||||
|
bprtmp <= '0;
|
||||||
|
rpftmp <= '0;
|
||||||
|
isplte <= 1'b0;
|
||||||
|
bpp <= '0;
|
||||||
|
ppr <= '0;
|
||||||
|
bpr <= '0;
|
||||||
|
rpf <= '0;
|
||||||
|
plte_bytecnt <= '0;
|
||||||
|
plte_pixcnt <= '0;
|
||||||
|
end else if(ivalid) begin
|
||||||
plte_bytecnt <= '0;
|
plte_bytecnt <= '0;
|
||||||
plte_pixcnt <= '0;
|
plte_pixcnt <= '0;
|
||||||
if(~busy) begin
|
if(~busy) begin
|
||||||
@ -190,7 +210,6 @@ always @ (posedge clk or negedge rstn)
|
|||||||
cnt <= cnt - 1;
|
cnt <= cnt - 1;
|
||||||
gapcnt <= 2'd2;
|
gapcnt <= 2'd2;
|
||||||
if(cnt==6) begin
|
if(cnt==6) begin
|
||||||
imagevalid <= 1'b0;
|
|
||||||
rpftmp <= l32bit;
|
rpftmp <= l32bit;
|
||||||
if(h32bit[31:14]=='0) begin
|
if(h32bit[31:14]=='0) begin
|
||||||
sizevalid <= 1'b1;
|
sizevalid <= 1'b1;
|
||||||
@ -211,15 +230,13 @@ always @ (posedge clk or negedge rstn)
|
|||||||
endcase
|
endcase
|
||||||
end else if(cnt==1) begin
|
end else if(cnt==1) begin
|
||||||
if(sizevalid && parametervalid && (bprtmp[15:14]==2'd0)) begin
|
if(sizevalid && parametervalid && (bprtmp[15:14]==2'd0)) begin
|
||||||
newframe <= 1'b1;
|
ostart <= 1'b1;
|
||||||
imagevalid <= 1'b1;
|
|
||||||
isplte <= ispltetmp;
|
isplte <= ispltetmp;
|
||||||
bpp <= bpptmp;
|
bpp <= bpptmp;
|
||||||
ppr <= pprtmp;
|
ppr <= pprtmp;
|
||||||
bpr <= bprtmp[13:0];
|
bpr <= bprtmp[13:0];
|
||||||
rpf <= rpftmp;
|
rpf <= rpftmp;
|
||||||
end else begin
|
end else begin
|
||||||
imagevalid <= 1'b0;
|
|
||||||
isplte <= 1'b0;
|
isplte <= 1'b0;
|
||||||
bpp <= '0;
|
bpp <= '0;
|
||||||
ppr <= '0;
|
ppr <= '0;
|
||||||
@ -230,7 +247,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
end else if(curr_name==IDAT) begin
|
end else if(curr_name==IDAT) begin
|
||||||
if(gapcnt>2'd0)
|
if(gapcnt>2'd0)
|
||||||
gapcnt <= gapcnt - 2'd1;
|
gapcnt <= gapcnt - 2'd1;
|
||||||
if(imagevalid && gapcnt==2'd0) begin
|
if(gapcnt==2'd0) begin
|
||||||
if(pready)
|
if(pready)
|
||||||
cnt <= cnt - 1;
|
cnt <= cnt - 1;
|
||||||
end else begin
|
end else begin
|
||||||
@ -291,36 +308,26 @@ always @ (posedge clk or negedge rstn)
|
|||||||
// uz_inflate
|
// uz_inflate
|
||||||
//-----------------------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
reg end_stream = '0;
|
reg end_stream = '0;
|
||||||
|
|
||||||
wire huffman_ovalid;
|
wire huffman_ovalid;
|
||||||
wire [7:0] huffman_obyte;
|
wire [7:0] huffman_obyte;
|
||||||
reg raw_ovalid;
|
|
||||||
reg [7:0] raw_obyte;
|
|
||||||
|
|
||||||
reg raw_mode = 1'b0;
|
|
||||||
reg raw_format = '0;
|
|
||||||
|
|
||||||
reg [ 2:0] status = '0;
|
|
||||||
reg [15:0] rcnt = '0;
|
|
||||||
reg [ 2:0] uz_cnt = '0;
|
reg [ 2:0] uz_cnt = '0;
|
||||||
reg [ 7:0] rbyte = '0;
|
reg [ 7:0] rbyte = '0;
|
||||||
|
|
||||||
reg tvalid;
|
reg tvalid;
|
||||||
wire tready;
|
wire tready;
|
||||||
reg tbit;
|
reg tbit;
|
||||||
|
|
||||||
always @ (posedge clk or negedge rstn)
|
always @ (posedge clk or negedge rstn)
|
||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
mvalid <= 1'b0;
|
mvalid <= 1'b0;
|
||||||
mbyte <= '0;
|
mbyte <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
mvalid <= 1'b0;
|
mvalid <= 1'b0;
|
||||||
mbyte <= '0;
|
mbyte <= '0;
|
||||||
end else if(raw_mode) begin
|
|
||||||
mvalid <= raw_ovalid;
|
|
||||||
mbyte <= raw_obyte;
|
|
||||||
end else begin
|
end else begin
|
||||||
mvalid <= huffman_ovalid;
|
mvalid <= huffman_ovalid;
|
||||||
mbyte <= huffman_obyte;
|
mbyte <= huffman_obyte;
|
||||||
@ -328,98 +335,33 @@ always @ (posedge clk or negedge rstn)
|
|||||||
end
|
end
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
if(~imagevalid) begin
|
if(uz_cnt==3'h0) begin
|
||||||
raw_ovalid = 1'b0;
|
pready = tready;
|
||||||
raw_obyte = '0;
|
tvalid = pvalid;
|
||||||
pready = 1'b0;
|
tbit = pbyte[0];
|
||||||
tvalid = 1'b0;
|
|
||||||
tbit = 1'b0;
|
|
||||||
end else begin
|
end else begin
|
||||||
raw_ovalid = 1'b0;
|
pready = 1'b0;
|
||||||
raw_obyte = '0;
|
tvalid = 1'b1;
|
||||||
if(raw_mode) begin
|
tbit = rbyte[uz_cnt];
|
||||||
pready = 1'b1;
|
|
||||||
tvalid = 1'b0;
|
|
||||||
tbit = 1'b0;
|
|
||||||
if(status>=3) begin
|
|
||||||
raw_ovalid = pvalid;
|
|
||||||
raw_obyte = pbyte;
|
|
||||||
end
|
|
||||||
end if(raw_format) begin
|
|
||||||
pready = 1'b1;
|
|
||||||
tvalid = 1'b0;
|
|
||||||
tbit = 1'b0;
|
|
||||||
end else if(uz_cnt==3'h0) begin
|
|
||||||
pready = tready;
|
|
||||||
tvalid = pvalid;
|
|
||||||
tbit = pbyte[0];
|
|
||||||
end else begin
|
|
||||||
pready = 1'b0;
|
|
||||||
tvalid = 1'b1;
|
|
||||||
tbit = rbyte[uz_cnt];
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (posedge clk or negedge rstn)
|
always @ (posedge clk or negedge rstn)
|
||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
raw_mode <= 1'b0;
|
|
||||||
uz_cnt <= '0;
|
uz_cnt <= '0;
|
||||||
rbyte <= '0;
|
rbyte <= '0;
|
||||||
rcnt <= '0;
|
|
||||||
status <= '0;
|
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
raw_mode <= 1'b0;
|
|
||||||
uz_cnt <= '0;
|
uz_cnt <= '0;
|
||||||
rbyte <= '0;
|
rbyte <= '0;
|
||||||
rcnt <= '0;
|
|
||||||
status <= '0;
|
|
||||||
end else if(raw_mode) begin
|
|
||||||
uz_cnt <= '0;
|
|
||||||
rbyte <= '0;
|
|
||||||
if(pvalid) begin
|
|
||||||
if (status==0) begin
|
|
||||||
rcnt[15:8] <= pbyte;
|
|
||||||
status <= status + 3'h1;
|
|
||||||
end else if(status==1) begin
|
|
||||||
status <= status + 3'h1;
|
|
||||||
end else if(status==2) begin
|
|
||||||
if(rcnt>0) begin
|
|
||||||
rcnt <= rcnt - 16'd1;
|
|
||||||
status <= status + 3'h1;
|
|
||||||
end else begin
|
|
||||||
raw_mode <= 1'b0;
|
|
||||||
status <= '0;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
if(rcnt>0) begin
|
|
||||||
rcnt <= rcnt - 16'd1;
|
|
||||||
end else begin
|
|
||||||
raw_mode <= 1'b0;
|
|
||||||
status <= '0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end else begin
|
end else begin
|
||||||
rcnt <= '0;
|
if(uz_cnt==3'h0) begin
|
||||||
status <= '0;
|
if(pvalid & tready) begin
|
||||||
if(raw_format) begin
|
uz_cnt <= uz_cnt + 3'h1;
|
||||||
if(pvalid) begin
|
rbyte <= pbyte;
|
||||||
raw_mode <= 1'b1;
|
|
||||||
rcnt[ 7:0] <= pbyte;
|
|
||||||
end
|
end
|
||||||
uz_cnt <= '0;
|
|
||||||
rbyte <= '0;
|
|
||||||
end else begin
|
end else begin
|
||||||
if(uz_cnt==3'h0) begin
|
if(tready)
|
||||||
if(pvalid & tready) begin
|
uz_cnt <= uz_cnt + 3'h1;
|
||||||
uz_cnt <= uz_cnt + 3'h1;
|
|
||||||
rbyte <= pbyte;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
if(tready)
|
|
||||||
uz_cnt <= uz_cnt + 3'h1;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -440,8 +382,6 @@ reg srepeat = 1'b0;
|
|||||||
reg symbol_valid = 1'b0;
|
reg symbol_valid = 1'b0;
|
||||||
reg [7:0] symbol = '0;
|
reg [7:0] symbol = '0;
|
||||||
|
|
||||||
reg decoder_new = 1'b1;
|
|
||||||
|
|
||||||
reg [ 1:0] iword = '0;
|
reg [ 1:0] iword = '0;
|
||||||
reg [ 1:0] ibcnt = '0;
|
reg [ 1:0] ibcnt = '0;
|
||||||
reg [ 4:0] precode_wpt = '0;
|
reg [ 4:0] precode_wpt = '0;
|
||||||
@ -484,14 +424,14 @@ reg [ 3:0] dscnt=4'h0, dsmax=4'h0;
|
|||||||
|
|
||||||
enum {T, D, R, S} huffman_status = T;
|
enum {T, D, R, S} huffman_status = T;
|
||||||
|
|
||||||
wire lentree_ien = ~end_stream & ~raw_format & tvalid & lentree_done & ~lentree_codeen & (repeat_mode==REPEAT_NONE && repeat_len==8'd0) & (tree_wpt<hmax);
|
wire lentree_ien = ~end_stream & tvalid & lentree_done & ~lentree_codeen & (repeat_mode==REPEAT_NONE && repeat_len==8'd0) & (tree_wpt<hmax);
|
||||||
wire codetree_ien = ~end_stream & ~raw_format & tvalid & tree_done & ~codetree_codeen & (tcnt==3'd0) & (dscnt==4'd0) & (huffman_status==T);
|
wire codetree_ien = ~end_stream & tvalid & tree_done & ~codetree_codeen & (tcnt==3'd0) & (dscnt==4'd0) & (huffman_status==T);
|
||||||
wire distree_ien = ~end_stream & ~raw_format & tvalid & tree_done & ~distree_codeen & (tcnt==3'd0) & (dscnt==4'd0) & (huffman_status==D);
|
wire distree_ien = ~end_stream & tvalid & tree_done & ~distree_codeen & (tcnt==3'd0) & (dscnt==4'd0) & (huffman_status==D);
|
||||||
|
|
||||||
assign tready = end_stream | (~raw_format & (
|
assign tready = end_stream | & (
|
||||||
( precode_wpt<5'd17 || lentree_wpt<hclen ) |
|
( precode_wpt<5'd17 || lentree_wpt<hclen ) |
|
||||||
( lentree_done & ~lentree_codeen & ((repeat_mode==REPEAT_NONE && repeat_len==8'd0) | repeat_code_pt>3'd0) & (tree_wpt<hmax) ) |
|
( lentree_done & ~lentree_codeen & ((repeat_mode==REPEAT_NONE && repeat_len==8'd0) | repeat_code_pt>3'd0) & (tree_wpt<hmax) ) |
|
||||||
( tree_done & ~codetree_codeen & ~distree_codeen & (huffman_status==T || huffman_status==D || (huffman_status==R && dscnt>4'd0)) ) ) );
|
( tree_done & ~codetree_codeen & ~distree_codeen & (huffman_status==T || huffman_status==D || (huffman_status==R && dscnt>4'd0)) ) );
|
||||||
|
|
||||||
reg [ 8:0] lengthb= '0;
|
reg [ 8:0] lengthb= '0;
|
||||||
reg [ 5:0] lengthe= '0;
|
reg [ 5:0] lengthe= '0;
|
||||||
@ -575,20 +515,17 @@ endtask
|
|||||||
|
|
||||||
always @ (posedge clk or negedge rstn)
|
always @ (posedge clk or negedge rstn)
|
||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
{raw_format, end_stream} <= '0;
|
end_stream <= '0;
|
||||||
decoder_new <= 1'b1;
|
|
||||||
reset_all_regs;
|
reset_all_regs;
|
||||||
end else begin
|
end else begin
|
||||||
if(raw_mode) begin
|
if(istart) begin
|
||||||
{raw_format, end_stream} <= '0;
|
end_stream <= '0;
|
||||||
decoder_new <= 1'b1;
|
|
||||||
reset_all_regs;
|
reset_all_regs;
|
||||||
end else begin
|
end else begin
|
||||||
symbol_valid <= 1'b0;
|
symbol_valid <= 1'b0;
|
||||||
symbol <= '0;
|
symbol <= '0;
|
||||||
irepeat <= 1'b0;
|
irepeat <= 1'b0;
|
||||||
srepeat <= 1'b0;
|
srepeat <= 1'b0;
|
||||||
decoder_new <= 1'b0;
|
|
||||||
lentree_write();
|
lentree_write();
|
||||||
codetree_write();
|
codetree_write();
|
||||||
distree_write();
|
distree_write();
|
||||||
@ -602,16 +539,12 @@ always @ (posedge clk or negedge rstn)
|
|||||||
end else if(precode_wpt==1) begin
|
end else if(precode_wpt==1) begin
|
||||||
bfix <= tbit;
|
bfix <= tbit;
|
||||||
end else begin
|
end else begin
|
||||||
case({tbit,bfix})
|
if( {tbit,bfix} == 2'b01 ) begin
|
||||||
2'b00 :
|
|
||||||
raw_format <= 1'b1;
|
|
||||||
2'b01 : begin
|
|
||||||
precode_wpt <= '1;
|
precode_wpt <= '1;
|
||||||
lentree_wpt <= '1;
|
lentree_wpt <= '1;
|
||||||
tree_wpt <= '1;
|
tree_wpt <= '1;
|
||||||
fixed_tree <= 1'b1;
|
fixed_tree <= 1'b1;
|
||||||
end
|
end
|
||||||
endcase
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end else if(precode_wpt<17) begin
|
end else if(precode_wpt<17) begin
|
||||||
@ -777,6 +710,7 @@ huffman_builder #(
|
|||||||
) lentree_builder (
|
) lentree_builder (
|
||||||
.rstn ( rstn ),
|
.rstn ( rstn ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.istart ( istart ),
|
||||||
.wren ( lentree_wen ),
|
.wren ( lentree_wen ),
|
||||||
.wraddr ( lentree_waddr ),
|
.wraddr ( lentree_waddr ),
|
||||||
.wrdata ( lentree_wdata ),
|
.wrdata ( lentree_wdata ),
|
||||||
@ -796,7 +730,7 @@ huffman_decoder #(
|
|||||||
) lentree_decoder (
|
) lentree_decoder (
|
||||||
.rstn ( rstn ),
|
.rstn ( rstn ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.inew ( decoder_new ),
|
.istart ( istart ),
|
||||||
.ien ( lentree_ien ),
|
.ien ( lentree_ien ),
|
||||||
.ibit ( tbit ),
|
.ibit ( tbit ),
|
||||||
.oen ( lentree_codeen ),
|
.oen ( lentree_codeen ),
|
||||||
@ -817,6 +751,7 @@ huffman_builder #(
|
|||||||
) codetree_builder (
|
) codetree_builder (
|
||||||
.rstn ( rstn ),
|
.rstn ( rstn ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.istart ( istart ),
|
||||||
.wren ( codetree_wen ),
|
.wren ( codetree_wen ),
|
||||||
.wraddr ( codetree_waddr ),
|
.wraddr ( codetree_waddr ),
|
||||||
.wrdata ( (5)'(codetree_wdata) ),
|
.wrdata ( (5)'(codetree_wdata) ),
|
||||||
@ -844,7 +779,7 @@ huffman_decoder #(
|
|||||||
) codetree_decoder (
|
) codetree_decoder (
|
||||||
.rstn ( rstn ),
|
.rstn ( rstn ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.inew ( decoder_new ),
|
.istart ( istart ),
|
||||||
.ien ( codetree_ien ),
|
.ien ( codetree_ien ),
|
||||||
.ibit ( tbit ),
|
.ibit ( tbit ),
|
||||||
.oen ( codetree_codeen),
|
.oen ( codetree_codeen),
|
||||||
@ -865,9 +800,10 @@ huffman_builder #(
|
|||||||
) distree_builder (
|
) distree_builder (
|
||||||
.rstn ( rstn ),
|
.rstn ( rstn ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
|
.istart ( istart ),
|
||||||
.wren ( distree_wen ),
|
.wren ( distree_wen ),
|
||||||
.wraddr ( distree_waddr ),
|
.wraddr ( distree_waddr ),
|
||||||
.wrdata ( (5)'(distree_wdata) ),
|
.wrdata ( (5)'(distree_wdata) ),
|
||||||
.run ( tree_run ),
|
.run ( tree_run ),
|
||||||
.done ( distree_done ),
|
.done ( distree_done ),
|
||||||
.rdaddr ( distree_raddr ),
|
.rdaddr ( distree_raddr ),
|
||||||
@ -892,7 +828,7 @@ huffman_decoder #(
|
|||||||
) distree_decoder (
|
) distree_decoder (
|
||||||
.rstn ( rstn ),
|
.rstn ( rstn ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
.inew ( decoder_new ),
|
.istart ( istart ),
|
||||||
.ien ( distree_ien ),
|
.ien ( distree_ien ),
|
||||||
.ibit ( tbit ),
|
.ibit ( tbit ),
|
||||||
.oen ( distree_codeen ),
|
.oen ( distree_codeen ),
|
||||||
@ -923,7 +859,10 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn)
|
if(~rstn)
|
||||||
wptr <= '0;
|
wptr <= '0;
|
||||||
else begin
|
else begin
|
||||||
if(huffman_ovalid) wptr <= (wptr<(REPEAT_BUFFER_MAXLEN-16'd1)) ? wptr+16'd1 : '0;
|
if(istart)
|
||||||
|
wptr <= '0;
|
||||||
|
else if(huffman_ovalid)
|
||||||
|
wptr <= (wptr<(REPEAT_BUFFER_MAXLEN-16'd1)) ? wptr+16'd1 : '0;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (posedge clk or negedge rstn)
|
always @ (posedge clk or negedge rstn)
|
||||||
@ -932,7 +871,11 @@ always @ (posedge clk or negedge rstn)
|
|||||||
sptr <= '0;
|
sptr <= '0;
|
||||||
eptr <= '0;
|
eptr <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(srepeat) begin
|
if(istart) begin
|
||||||
|
rptr <= '0;
|
||||||
|
sptr <= '0;
|
||||||
|
eptr <= '0;
|
||||||
|
end else if(srepeat) begin
|
||||||
rptr <= sptrw;
|
rptr <= sptrw;
|
||||||
sptr <= sptrw;
|
sptr <= sptrw;
|
||||||
eptr <= eptrw;
|
eptr <= eptrw;
|
||||||
@ -948,7 +891,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn)
|
if(~rstn)
|
||||||
repeat_valid <= '0;
|
repeat_valid <= '0;
|
||||||
else
|
else
|
||||||
repeat_valid <= irepeat;
|
repeat_valid <= istart ? '0 : irepeat;
|
||||||
|
|
||||||
reg [7:0] mem_repeat_buffer [REPEAT_BUFFER_MAXLEN];
|
reg [7:0] mem_repeat_buffer [REPEAT_BUFFER_MAXLEN];
|
||||||
|
|
||||||
@ -996,7 +939,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
nfirstrow <= 1'b0;
|
nfirstrow <= 1'b0;
|
||||||
col <= '0;
|
col <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
nfirstrow <= 1'b0;
|
nfirstrow <= 1'b0;
|
||||||
col <= '0;
|
col <= '0;
|
||||||
end else if(mvalid) begin
|
end else if(mvalid) begin
|
||||||
@ -1013,9 +956,9 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
mode <= '0;
|
mode <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart)
|
||||||
mode <= '0;
|
mode <= '0;
|
||||||
end else if(mvalid && col==14'h0)
|
else if(mvalid && col==14'h0)
|
||||||
mode <= mbyte[2:0];
|
mode <= mbyte[2:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1027,7 +970,7 @@ always_comb
|
|||||||
3'd3 : fdata = mbyte + SSdata[8:1];
|
3'd3 : fdata = mbyte + SSdata[8:1];
|
||||||
default: fdata = mbyte + paeth( (nfirstcol ? LLdata : 8'h0),
|
default: fdata = mbyte + paeth( (nfirstcol ? LLdata : 8'h0),
|
||||||
(nfirstrow ? UUdata : 8'h0),
|
(nfirstrow ? UUdata : 8'h0),
|
||||||
(nfirstrow&nfirstcol ? ULdata : 8'h0) );
|
(nfirstrow & nfirstcol ? ULdata : 8'h0) );
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
always @ (posedge clk or negedge rstn)
|
always @ (posedge clk or negedge rstn)
|
||||||
@ -1035,7 +978,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
bvalid <= 1'b0;
|
bvalid <= 1'b0;
|
||||||
bbyte <= '0;
|
bbyte <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
bvalid <= 1'b0;
|
bvalid <= 1'b0;
|
||||||
bbyte <= '0;
|
bbyte <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
@ -1052,7 +995,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
mem_sr_currline[0] <= '0;
|
mem_sr_currline[0] <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
mem_sr_currline[0] <= '0;
|
mem_sr_currline[0] <= '0;
|
||||||
end else if(mvalid)
|
end else if(mvalid)
|
||||||
mem_sr_currline[0] <= fdata;
|
mem_sr_currline[0] <= fdata;
|
||||||
@ -1063,7 +1006,7 @@ generate genvar isrcl;
|
|||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
mem_sr_currline[isrcl+1] <= '0;
|
mem_sr_currline[isrcl+1] <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
mem_sr_currline[isrcl+1] <= '0;
|
mem_sr_currline[isrcl+1] <= '0;
|
||||||
end else if(mvalid)
|
end else if(mvalid)
|
||||||
mem_sr_currline[isrcl+1] <= mem_sr_currline[isrcl];
|
mem_sr_currline[isrcl+1] <= mem_sr_currline[isrcl];
|
||||||
@ -1080,7 +1023,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
mem_sr_prevline[0] <= '0;
|
mem_sr_prevline[0] <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
mem_sr_prevline[0] <= '0;
|
mem_sr_prevline[0] <= '0;
|
||||||
end else if(mvalid)
|
end else if(mvalid)
|
||||||
mem_sr_prevline[0] <= UUdata;
|
mem_sr_prevline[0] <= UUdata;
|
||||||
@ -1091,7 +1034,7 @@ generate genvar isrpl;
|
|||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
mem_sr_prevline[isrpl+1] <= '0;
|
mem_sr_prevline[isrpl+1] <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
mem_sr_prevline[isrpl+1] <= '0;
|
mem_sr_prevline[isrpl+1] <= '0;
|
||||||
end else if(mvalid)
|
end else if(mvalid)
|
||||||
mem_sr_prevline[isrpl+1] <= mem_sr_prevline[isrpl];
|
mem_sr_prevline[isrpl+1] <= mem_sr_prevline[isrpl];
|
||||||
@ -1111,7 +1054,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
sb_lidata <= '0;
|
sb_lidata <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
sb_lidata <= '0;
|
sb_lidata <= '0;
|
||||||
end else if(mvalid)
|
end else if(mvalid)
|
||||||
sb_lidata <= fdata;
|
sb_lidata <= fdata;
|
||||||
@ -1121,7 +1064,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
sb_ptr <= '0;
|
sb_ptr <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
sb_ptr <= '0;
|
sb_ptr <= '0;
|
||||||
end else if(mvalid) begin
|
end else if(mvalid) begin
|
||||||
if(sb_ptr < (bpr-14'd1))
|
if(sb_ptr < (bpr-14'd1))
|
||||||
@ -1136,7 +1079,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
sb_ldata <= '0;
|
sb_ldata <= '0;
|
||||||
sb_rvalid <= 1'b0;
|
sb_rvalid <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~imagevalid) begin
|
if(istart) begin
|
||||||
sb_ldata <= '0;
|
sb_ldata <= '0;
|
||||||
sb_rvalid <= 1'b0;
|
sb_rvalid <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
@ -1177,7 +1120,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
{pr, pg, pb, pa} <= 0;
|
{pr, pg, pb, pa} <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
ovalid <= 1'b0;
|
ovalid <= 1'b0;
|
||||||
if(newframe) begin
|
if(istart | ostart) begin
|
||||||
pixcnt <= '0;
|
pixcnt <= '0;
|
||||||
{pr, pg, pb, pa} <= 0;
|
{pr, pg, pb, pa} <= 0;
|
||||||
end else if(bvalid) begin
|
end else if(bvalid) begin
|
||||||
|
@ -12,6 +12,7 @@ module huffman_builder #(
|
|||||||
parameter OUTWIDTH = 10
|
parameter OUTWIDTH = 10
|
||||||
) (
|
) (
|
||||||
rstn, clk,
|
rstn, clk,
|
||||||
|
istart,
|
||||||
wren, wraddr, wrdata,
|
wren, wraddr, wrdata,
|
||||||
run , done,
|
run , done,
|
||||||
rdaddr, rddata
|
rdaddr, rddata
|
||||||
@ -25,6 +26,7 @@ endfunction
|
|||||||
|
|
||||||
input rstn;
|
input rstn;
|
||||||
input clk;
|
input clk;
|
||||||
|
input istart;
|
||||||
input wren;
|
input wren;
|
||||||
input [ clogb2(NUMCODES-1)-1:0] wraddr;
|
input [ clogb2(NUMCODES-1)-1:0] wraddr;
|
||||||
input [ CODEBITS -1:0] wrdata;
|
input [ CODEBITS -1:0] wrdata;
|
||||||
@ -33,18 +35,19 @@ output done;
|
|||||||
input [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
input [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
||||||
output [ OUTWIDTH-1:0] rddata;
|
output [ OUTWIDTH-1:0] rddata;
|
||||||
|
|
||||||
wire rstn;
|
wire rstn;
|
||||||
wire clk;
|
wire clk;
|
||||||
wire wren;
|
wire istart;
|
||||||
wire [ clogb2(NUMCODES-1)-1:0] wraddr;
|
wire wren;
|
||||||
wire [ CODEBITS -1:0] wrdata;
|
wire [ clogb2(NUMCODES-1)-1:0] wraddr;
|
||||||
wire run;
|
wire [ CODEBITS -1:0] wrdata;
|
||||||
wire done;
|
wire run;
|
||||||
wire [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
wire done;
|
||||||
reg [ OUTWIDTH-1:0] rddata;
|
wire [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
||||||
|
reg [ OUTWIDTH-1:0] rddata;
|
||||||
|
|
||||||
reg [clogb2(NUMCODES)-1:0] blcount [BITLENGTH];
|
reg [clogb2(NUMCODES)-1:0] blcount [BITLENGTH];
|
||||||
reg [ (1<<CODEBITS)-1:0] nextcode [BITLENGTH+1];
|
reg [ (1<<CODEBITS)-1:0] nextcode [BITLENGTH+1];
|
||||||
|
|
||||||
initial for(int i=0; i< BITLENGTH; i++) blcount[i] = '0;
|
initial for(int i=0; i< BITLENGTH; i++) blcount[i] = '0;
|
||||||
initial for(int i=0; i<=BITLENGTH; i++) nextcode[i] = '0;
|
initial for(int i=0; i<=BITLENGTH; i++) nextcode[i] = '0;
|
||||||
@ -77,18 +80,29 @@ always @ (posedge clk or negedge rstn)
|
|||||||
lii <= '0;
|
lii <= '0;
|
||||||
lnn <= '0;
|
lnn <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
valid <= build_tree2d & nn<NUMCODES & blen>0;
|
if(istart) begin
|
||||||
treepos <= ntreepos;
|
valid <= '0;
|
||||||
tpos <= ntpos;
|
treepos <= '0;
|
||||||
lii <= ii;
|
tpos <= '0;
|
||||||
lnn <= nn;
|
lii <= '0;
|
||||||
|
lnn <= '0;
|
||||||
|
end else begin
|
||||||
|
valid <= build_tree2d & nn<NUMCODES & blen>0;
|
||||||
|
treepos <= ntreepos;
|
||||||
|
tpos <= ntpos;
|
||||||
|
lii <= ii;
|
||||||
|
lnn <= nn;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (posedge clk or negedge rstn)
|
always @ (posedge clk or negedge rstn)
|
||||||
if(~rstn)
|
if(~rstn)
|
||||||
blen <= '0;
|
blen <= '0;
|
||||||
else begin
|
else begin
|
||||||
if(islast) blen <= blenn;
|
if(istart)
|
||||||
|
blen <= '0;
|
||||||
|
else if(islast)
|
||||||
|
blen <= blenn;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (posedge clk or negedge rstn)
|
always @ (posedge clk or negedge rstn)
|
||||||
@ -96,7 +110,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
for(int i=0; i<BITLENGTH; i++)
|
for(int i=0; i<BITLENGTH; i++)
|
||||||
blcount[i] <= '0;
|
blcount[i] <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(done) begin
|
if(istart | done) begin
|
||||||
for(int i=0; i<BITLENGTH; i++)
|
for(int i=0; i<BITLENGTH; i++)
|
||||||
blcount[i] <= '0;
|
blcount[i] <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
@ -115,7 +129,7 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn)
|
if(~rstn)
|
||||||
nn <= '0;
|
nn <= '0;
|
||||||
else
|
else
|
||||||
nn <= nnn;
|
nn <= istart ? '0 : nnn;
|
||||||
|
|
||||||
always @ (posedge clk or negedge rstn)
|
always @ (posedge clk or negedge rstn)
|
||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
@ -129,7 +143,14 @@ always @ (posedge clk or negedge rstn)
|
|||||||
end else begin
|
end else begin
|
||||||
nextcode[0] <= '0;
|
nextcode[0] <= '0;
|
||||||
alldone <= 1'b0;
|
alldone <= 1'b0;
|
||||||
if(run) begin
|
if(istart | ~run) begin
|
||||||
|
if(istart) for(int i=0; i<=BITLENGTH; i++) nextcode[i] <= '0;
|
||||||
|
ii <= '0;
|
||||||
|
idx <= '0;
|
||||||
|
build_tree2d <= 1'b0;
|
||||||
|
clearidx <= '0;
|
||||||
|
clear_tree2d <= 1'b0;
|
||||||
|
end else if(run) begin
|
||||||
if(~clear_tree2d) begin
|
if(~clear_tree2d) begin
|
||||||
if( clearidx >= (clogb2(2*NUMCODES-1))'(2*NUMCODES-1) )
|
if( clearidx >= (clogb2(2*NUMCODES-1))'(2*NUMCODES-1) )
|
||||||
clear_tree2d <= 1'b1;
|
clear_tree2d <= 1'b1;
|
||||||
@ -153,12 +174,6 @@ always @ (posedge clk or negedge rstn)
|
|||||||
build_tree2d <= 1'b1;
|
build_tree2d <= 1'b1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end else begin
|
|
||||||
ii <= '0;
|
|
||||||
idx <= '0;
|
|
||||||
build_tree2d <= 1'b0;
|
|
||||||
clearidx <= '0;
|
|
||||||
clear_tree2d <= 1'b0;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -177,7 +192,9 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn) begin
|
if(~rstn) begin
|
||||||
nodefilled <= '0;
|
nodefilled <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
if(~run)
|
if(istart)
|
||||||
|
nodefilled <= '0;
|
||||||
|
else if(~run)
|
||||||
nodefilled <= (clogb2(2*NUMCODES-1))'(1);
|
nodefilled <= (clogb2(2*NUMCODES-1))'(1);
|
||||||
else if(valid & rdfilled & lii>0)
|
else if(valid & rdfilled & lii>0)
|
||||||
nodefilled <= nodefilled + (clogb2(2*NUMCODES-1))'(1);
|
nodefilled <= nodefilled + (clogb2(2*NUMCODES-1))'(1);
|
||||||
|
@ -10,7 +10,8 @@ module huffman_decoder #(
|
|||||||
parameter OUTWIDTH = 10
|
parameter OUTWIDTH = 10
|
||||||
)(
|
)(
|
||||||
rstn, clk,
|
rstn, clk,
|
||||||
inew, ien, ibit,
|
istart,
|
||||||
|
ien, ibit,
|
||||||
oen, ocode,
|
oen, ocode,
|
||||||
rdaddr, rddata
|
rdaddr, rddata
|
||||||
);
|
);
|
||||||
@ -22,22 +23,22 @@ function automatic integer clogb2(input integer val);
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
input rstn, clk;
|
input rstn, clk;
|
||||||
input inew, ien, ibit;
|
input istart, ien, ibit;
|
||||||
output oen;
|
output oen;
|
||||||
output [ OUTWIDTH-1:0] ocode;
|
output [ OUTWIDTH-1:0] ocode;
|
||||||
output [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
output [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
||||||
input [ OUTWIDTH-1:0] rddata;
|
input [ OUTWIDTH-1:0] rddata;
|
||||||
|
|
||||||
wire rstn, clk;
|
wire rstn, clk;
|
||||||
wire inew, ien, ibit;
|
wire istart, ien, ibit;
|
||||||
reg oen = 1'b0;
|
reg oen = 1'b0;
|
||||||
reg [ OUTWIDTH-1:0] ocode = '0;
|
reg [ OUTWIDTH-1:0] ocode = '0;
|
||||||
wire [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
wire [clogb2(2*NUMCODES-1)-1:0] rdaddr;
|
||||||
wire [ OUTWIDTH-1:0] rddata;
|
wire [ OUTWIDTH-1:0] rddata;
|
||||||
|
|
||||||
reg [clogb2(2*NUMCODES-1)-2:0] tpos = '0;
|
reg [clogb2(2*NUMCODES-1)-2:0] tpos = '0;
|
||||||
wire [clogb2(2*NUMCODES-1)-2:0] ntpos;
|
wire [clogb2(2*NUMCODES-1)-2:0] ntpos;
|
||||||
reg ienl = 1'b0;
|
reg ienl = 1'b0;
|
||||||
|
|
||||||
assign rdaddr = {ntpos, ibit};
|
assign rdaddr = {ntpos, ibit};
|
||||||
|
|
||||||
@ -47,13 +48,13 @@ always @ (posedge clk or negedge rstn)
|
|||||||
if(~rstn)
|
if(~rstn)
|
||||||
ienl <= '0;
|
ienl <= '0;
|
||||||
else
|
else
|
||||||
ienl <= inew ? '0 : ien;
|
ienl <= istart ? '0 : ien;
|
||||||
|
|
||||||
always @ (posedge clk or negedge rstn)
|
always @ (posedge clk or negedge rstn)
|
||||||
if(~rstn)
|
if(~rstn)
|
||||||
tpos <= '0;
|
tpos <= '0;
|
||||||
else
|
else
|
||||||
tpos <= inew ? '0 : ntpos;
|
tpos <= istart ? '0 : ntpos;
|
||||||
|
|
||||||
always_comb
|
always_comb
|
||||||
if(ienl && rddata<NUMCODES) begin
|
if(ienl && rddata<NUMCODES) begin
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
`timescale 1ps/1ps
|
`timescale 1ps/1ps
|
||||||
|
|
||||||
|
|
||||||
`define START_NO 1 // first png file number to decode
|
`define START_NO 1 // first png file number to decode
|
||||||
`define FINAL_NO 14 // last png file number to decode
|
`define FINAL_NO 14 // last png file number to decode
|
||||||
|
|
||||||
`define IN_PNG_FILE_FOMRAT "test_image/img%02d.png"
|
`define IN_PNG_FILE_FOMRAT "test_image/img%02d.png"
|
||||||
`define OUT_TXT_FILE_FORMAT "out%02d.txt"
|
`define OUT_TXT_FILE_FORMAT "out%02d.txt"
|
||||||
@ -18,19 +18,22 @@
|
|||||||
|
|
||||||
module tb_hard_png ();
|
module tb_hard_png ();
|
||||||
|
|
||||||
initial $dumpvars(1, tb_hard_png);
|
initial $dumpvars(0, tb_hard_png);
|
||||||
|
|
||||||
|
|
||||||
reg rstn = 1'b0;
|
reg rstn = 1'b0;
|
||||||
reg clk = 1'b1;
|
reg clk = 1'b1;
|
||||||
always #10000 clk = ~clk; // 50MHz
|
always #10000 clk = ~clk; // 50MHz
|
||||||
|
initial begin repeat(4) @(posedge clk); rstn<=1'b1; end
|
||||||
|
|
||||||
|
|
||||||
reg [ 7:0] ibyte = '0;
|
|
||||||
|
reg istart = '0;
|
||||||
reg ivalid = 1'b0;
|
reg ivalid = 1'b0;
|
||||||
wire iready;
|
wire iready;
|
||||||
|
reg [ 7:0] ibyte = '0;
|
||||||
|
|
||||||
wire newframe;
|
wire ostart;
|
||||||
wire [ 2:0] colortype;
|
wire [ 2:0] colortype;
|
||||||
wire [13:0] width;
|
wire [13:0] width;
|
||||||
wire [31:0] height;
|
wire [31:0] height;
|
||||||
@ -44,11 +47,12 @@ hard_png hard_png_i (
|
|||||||
.rstn ( rstn ),
|
.rstn ( rstn ),
|
||||||
.clk ( clk ),
|
.clk ( clk ),
|
||||||
// data input
|
// data input
|
||||||
|
.istart ( istart ),
|
||||||
.ivalid ( ivalid ),
|
.ivalid ( ivalid ),
|
||||||
.iready ( iready ),
|
.iready ( iready ),
|
||||||
.ibyte ( ibyte ),
|
.ibyte ( ibyte ),
|
||||||
// image size output
|
// image size output
|
||||||
.newframe ( newframe ),
|
.ostart ( ostart ),
|
||||||
.colortype ( colortype ),
|
.colortype ( colortype ),
|
||||||
.width ( width ),
|
.width ( width ),
|
||||||
.height ( height ),
|
.height ( height ),
|
||||||
@ -69,14 +73,17 @@ int png_no = 0;
|
|||||||
int txt_no = 0;
|
int txt_no = 0;
|
||||||
|
|
||||||
int cyccnt = 0;
|
int cyccnt = 0;
|
||||||
int bytecnt = 1;
|
int bytecnt = 0;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
while(~rstn) @(posedge clk);
|
||||||
|
|
||||||
fork
|
fork
|
||||||
// thread: input png file
|
// thread: input png file
|
||||||
for(png_no=`START_NO; png_no<=`FINAL_NO; png_no=png_no+1) begin
|
for(png_no=`START_NO; png_no<=`FINAL_NO; png_no=png_no+1) begin
|
||||||
|
istart <= 1'b1;
|
||||||
@ (posedge clk);
|
@ (posedge clk);
|
||||||
rstn <= 1'b1;
|
istart <= 1'b0;
|
||||||
|
|
||||||
$sformat(fname_png, `IN_PNG_FILE_FOMRAT , png_no);
|
$sformat(fname_png, `IN_PNG_FILE_FOMRAT , png_no);
|
||||||
|
|
||||||
@ -86,15 +93,15 @@ initial begin
|
|||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
cyccnt = 0;
|
cyccnt = 0;
|
||||||
bytecnt = 1;
|
bytecnt = 0;
|
||||||
|
|
||||||
$display("start to decode %30s", fname_png );
|
$display("\nstart to decode %30s", fname_png );
|
||||||
|
|
||||||
ibyte <= $fgetc(fppng);
|
ibyte <= $fgetc(fppng);
|
||||||
while( !$feof(fppng) ) @(posedge clk) begin
|
while( !$feof(fppng) ) @(posedge clk) begin
|
||||||
if(~ivalid | iready ) begin
|
if(~ivalid | iready ) begin
|
||||||
ivalid <= 1'b1; // use this to always try to input a byte to hard_png (no bubble, will get maximum throughput)
|
ivalid <= 1'b1; // A. use this to always try to input a byte to hard_png (no bubble, will get maximum throughput)
|
||||||
//ivalid <= ($random % 3) == 0; // use this to add random bubbles to the input stream of hard_png. (Although the maximum throughput cannot be achieved, it allows input with mismatched rate, which is more common in the actual engineering scenarios)
|
//ivalid <= ($random % 3) == 0; // B. use this to add random bubbles to the input stream of hard_png. (Although the maximum throughput cannot be achieved, it allows input with mismatched rate, which is more common in the actual engineering scenarios)
|
||||||
end
|
end
|
||||||
if( ivalid & iready ) begin
|
if( ivalid & iready ) begin
|
||||||
ibyte <= $fgetc(fppng);
|
ibyte <= $fgetc(fppng);
|
||||||
@ -103,7 +110,6 @@ initial begin
|
|||||||
cyccnt++;
|
cyccnt++;
|
||||||
end
|
end
|
||||||
ivalid <= 1'b0;
|
ivalid <= 1'b0;
|
||||||
rstn <= 1'b0;
|
|
||||||
|
|
||||||
$fclose(fppng);
|
$fclose(fppng);
|
||||||
$display("image %30s decode done, input %d bytes in %d cycles, throughput=%f byte/cycle", fname_png, bytecnt, cyccnt, (1.0*bytecnt)/cyccnt );
|
$display("image %30s decode done, input %d bytes in %d cycles, throughput=%f byte/cycle", fname_png, bytecnt, cyccnt, (1.0*bytecnt)/cyccnt );
|
||||||
@ -114,7 +120,7 @@ initial begin
|
|||||||
for(txt_no=`START_NO; txt_no<=`FINAL_NO; txt_no=txt_no+1) begin
|
for(txt_no=`START_NO; txt_no<=`FINAL_NO; txt_no=txt_no+1) begin
|
||||||
$sformat(fname_txt, `OUT_TXT_FILE_FORMAT , txt_no);
|
$sformat(fname_txt, `OUT_TXT_FILE_FORMAT , txt_no);
|
||||||
|
|
||||||
while(~newframe) @ (posedge clk);
|
while(~ostart) @ (posedge clk);
|
||||||
$display("decode result: colortype:%1d width:%1d height:%1d", colortype, width, height);
|
$display("decode result: colortype:%1d width:%1d height:%1d", colortype, width, height);
|
||||||
|
|
||||||
fptxt = $fopen(fname_txt, "w");
|
fptxt = $fopen(fname_txt, "w");
|
||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |